intl/icu/source/common/cmemory.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2 ******************************************************************************
     3 *
     4 *   Copyright (C) 1997-2012, International Business Machines
     5 *   Corporation and others.  All Rights Reserved.
     6 *
     7 ******************************************************************************
     8 *
     9 * File CMEMORY.H
    10 *
    11 *  Contains stdlib.h/string.h memory functions
    12 *
    13 * @author       Bertrand A. Damiba
    14 *
    15 * Modification History:
    16 *
    17 *   Date        Name        Description
    18 *   6/20/98     Bertrand    Created.
    19 *  05/03/99     stephen     Changed from functions to macros.
    20 *
    21 ******************************************************************************
    22 */
    24 #ifndef CMEMORY_H
    25 #define CMEMORY_H
    27 #include "unicode/utypes.h"
    29 #include <stddef.h>
    30 #include <string.h>
    31 #include "unicode/localpointer.h"
    33 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
    34 #include <stdio.h>
    35 #endif
    37 #if U_DEBUG
    39 /*
    40  * The C++ standard requires that the source pointer for memcpy() & memmove()
    41  * is valid, not NULL, and not at the end of an allocated memory block.
    42  * In debug mode, we read one byte from the source point to verify that it's
    43  * a valid, readable pointer.
    44  */
    46 U_CAPI void uprv_checkValidMemory(const void *p, size_t n);
    48 #define uprv_memcpy(dst, src, size) ( \
    49     uprv_checkValidMemory(src, 1), \
    50     U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
    51 #define uprv_memmove(dst, src, size) ( \
    52     uprv_checkValidMemory(src, 1), \
    53     U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
    55 #else
    57 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
    58 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
    60 #endif  /* U_DEBUG */
    62 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
    63 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
    65 U_CAPI void * U_EXPORT2
    66 uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
    68 U_CAPI void * U_EXPORT2
    69 uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
    71 U_CAPI void U_EXPORT2
    72 uprv_free(void *mem);
    74 U_CAPI void * U_EXPORT2
    75 uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
    77 /**
    78  * This should align the memory properly on any machine.
    79  * This is very useful for the safeClone functions.
    80  */
    81 typedef union {
    82     long    t1;
    83     double  t2;
    84     void   *t3;
    85 } UAlignedMemory;
    87 /**
    88  * Get the least significant bits of a pointer (a memory address).
    89  * For example, with a mask of 3, the macro gets the 2 least significant bits,
    90  * which will be 0 if the pointer is 32-bit (4-byte) aligned.
    91  *
    92  * ptrdiff_t is the most appropriate integer type to cast to.
    93  * size_t should work too, since on most (or all?) platforms it has the same
    94  * width as ptrdiff_t.
    95  */
    96 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
    98 /**
    99  * Get the amount of bytes that a pointer is off by from
   100  * the previous UAlignedMemory-aligned pointer.
   101  */
   102 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
   104 /**
   105  * Get the amount of bytes to add to a pointer
   106  * in order to get the next UAlignedMemory-aligned address.
   107  */
   108 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
   110 /**
   111   *  Indicate whether the ICU allocation functions have been used.
   112   *  This is used to determine whether ICU is in an initial, unused state.
   113   */
   114 U_CFUNC UBool 
   115 cmemory_inUse(void);
   117 /**
   118   *  Heap clean up function, called from u_cleanup()
   119   *    Clears any user heap functions from u_setMemoryFunctions()
   120   *    Does NOT deallocate any remaining allocated memory.
   121   */
   122 U_CFUNC UBool 
   123 cmemory_cleanup(void);
   125 /**
   126  * A function called by <TT>uhash_remove</TT>,
   127  * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
   128  * an existing key or value.
   129  * @param obj A key or value stored in a hashtable
   130  * @see uprv_deleteUObject
   131  */
   132 typedef void U_CALLCONV UObjectDeleter(void* obj);
   134 /**
   135  * Deleter for UObject instances.
   136  * Works for all subclasses of UObject because it has a virtual destructor.
   137  */
   138 U_CAPI void U_EXPORT2
   139 uprv_deleteUObject(void *obj);
   141 #ifdef __cplusplus
   143 U_NAMESPACE_BEGIN
   145 /**
   146  * "Smart pointer" class, deletes memory via uprv_free().
   147  * For most methods see the LocalPointerBase base class.
   148  * Adds operator[] for array item access.
   149  *
   150  * @see LocalPointerBase
   151  */
   152 template<typename T>
   153 class LocalMemory : public LocalPointerBase<T> {
   154 public:
   155     /**
   156      * Constructor takes ownership.
   157      * @param p simple pointer to an array of T items that is adopted
   158      */
   159     explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
   160     /**
   161      * Destructor deletes the memory it owns.
   162      */
   163     ~LocalMemory() {
   164         uprv_free(LocalPointerBase<T>::ptr);
   165     }
   166     /**
   167      * Deletes the array it owns,
   168      * and adopts (takes ownership of) the one passed in.
   169      * @param p simple pointer to an array of T items that is adopted
   170      */
   171     void adoptInstead(T *p) {
   172         uprv_free(LocalPointerBase<T>::ptr);
   173         LocalPointerBase<T>::ptr=p;
   174     }
   175     /**
   176      * Deletes the array it owns, allocates a new one and reset its bytes to 0.
   177      * Returns the new array pointer.
   178      * If the allocation fails, then the current array is unchanged and
   179      * this method returns NULL.
   180      * @param newCapacity must be >0
   181      * @return the allocated array pointer, or NULL if the allocation failed
   182      */
   183     inline T *allocateInsteadAndReset(int32_t newCapacity=1);
   184     /**
   185      * Deletes the array it owns and allocates a new one, copying length T items.
   186      * Returns the new array pointer.
   187      * If the allocation fails, then the current array is unchanged and
   188      * this method returns NULL.
   189      * @param newCapacity must be >0
   190      * @param length number of T items to be copied from the old array to the new one;
   191      *               must be no more than the capacity of the old array,
   192      *               which the caller must track because the LocalMemory does not track it
   193      * @return the allocated array pointer, or NULL if the allocation failed
   194      */
   195     inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
   196     /**
   197      * Array item access (writable).
   198      * No index bounds check.
   199      * @param i array index
   200      * @return reference to the array item
   201      */
   202     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
   203 };
   205 template<typename T>
   206 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
   207     if(newCapacity>0) {
   208         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
   209         if(p!=NULL) {
   210             uprv_memset(p, 0, newCapacity*sizeof(T));
   211             uprv_free(LocalPointerBase<T>::ptr);
   212             LocalPointerBase<T>::ptr=p;
   213         }
   214         return p;
   215     } else {
   216         return NULL;
   217     }
   218 }
   221 template<typename T>
   222 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
   223     if(newCapacity>0) {
   224         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
   225         if(p!=NULL) {
   226             if(length>0) {
   227                 if(length>newCapacity) {
   228                     length=newCapacity;
   229                 }
   230                 uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
   231             }
   232             uprv_free(LocalPointerBase<T>::ptr);
   233             LocalPointerBase<T>::ptr=p;
   234         }
   235         return p;
   236     } else {
   237         return NULL;
   238     }
   239 }
   241 /**
   242  * Simple array/buffer management class using uprv_malloc() and uprv_free().
   243  * Provides an internal array with fixed capacity. Can alias another array
   244  * or allocate one.
   245  *
   246  * The array address is properly aligned for type T. It might not be properly
   247  * aligned for types larger than T (or larger than the largest subtype of T).
   248  *
   249  * Unlike LocalMemory and LocalArray, this class never adopts
   250  * (takes ownership of) another array.
   251  */
   252 template<typename T, int32_t stackCapacity>
   253 class MaybeStackArray {
   254 public:
   255     /**
   256      * Default constructor initializes with internal T[stackCapacity] buffer.
   257      */
   258     MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
   259     /**
   260      * Destructor deletes the array (if owned).
   261      */
   262     ~MaybeStackArray() { releaseArray(); }
   263     /**
   264      * Returns the array capacity (number of T items).
   265      * @return array capacity
   266      */
   267     int32_t getCapacity() const { return capacity; }
   268     /**
   269      * Access without ownership change.
   270      * @return the array pointer
   271      */
   272     T *getAlias() const { return ptr; }
   273     /**
   274      * Returns the array limit. Simple convenience method.
   275      * @return getAlias()+getCapacity()
   276      */
   277     T *getArrayLimit() const { return getAlias()+capacity; }
   278     // No "operator T *() const" because that can make
   279     // expressions like mbs[index] ambiguous for some compilers.
   280     /**
   281      * Array item access (const).
   282      * No index bounds check.
   283      * @param i array index
   284      * @return reference to the array item
   285      */
   286     const T &operator[](ptrdiff_t i) const { return ptr[i]; }
   287     /**
   288      * Array item access (writable).
   289      * No index bounds check.
   290      * @param i array index
   291      * @return reference to the array item
   292      */
   293     T &operator[](ptrdiff_t i) { return ptr[i]; }
   294     /**
   295      * Deletes the array (if owned) and aliases another one, no transfer of ownership.
   296      * If the arguments are illegal, then the current array is unchanged.
   297      * @param otherArray must not be NULL
   298      * @param otherCapacity must be >0
   299      */
   300     void aliasInstead(T *otherArray, int32_t otherCapacity) {
   301         if(otherArray!=NULL && otherCapacity>0) {
   302             releaseArray();
   303             ptr=otherArray;
   304             capacity=otherCapacity;
   305             needToRelease=FALSE;
   306         }
   307     }
   308     /**
   309      * Deletes the array (if owned) and allocates a new one, copying length T items.
   310      * Returns the new array pointer.
   311      * If the allocation fails, then the current array is unchanged and
   312      * this method returns NULL.
   313      * @param newCapacity can be less than or greater than the current capacity;
   314      *                    must be >0
   315      * @param length number of T items to be copied from the old array to the new one
   316      * @return the allocated array pointer, or NULL if the allocation failed
   317      */
   318     inline T *resize(int32_t newCapacity, int32_t length=0);
   319     /**
   320      * Gives up ownership of the array if owned, or else clones it,
   321      * copying length T items; resets itself to the internal stack array.
   322      * Returns NULL if the allocation failed.
   323      * @param length number of T items to copy when cloning,
   324      *        and capacity of the clone when cloning
   325      * @param resultCapacity will be set to the returned array's capacity (output-only)
   326      * @return the array pointer;
   327      *         caller becomes responsible for deleting the array
   328      */
   329     inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
   330 private:
   331     T *ptr;
   332     int32_t capacity;
   333     UBool needToRelease;
   334     T stackArray[stackCapacity];
   335     void releaseArray() {
   336         if(needToRelease) {
   337             uprv_free(ptr);
   338         }
   339     }
   340     /* No comparison operators with other MaybeStackArray's. */
   341     bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
   342     bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
   343     /* No ownership transfer: No copy constructor, no assignment operator. */
   344     MaybeStackArray(const MaybeStackArray & /*other*/) {}
   345     void operator=(const MaybeStackArray & /*other*/) {}
   347     // No heap allocation. Use only on the stack.
   348     //   (Declaring these functions private triggers a cascade of problems:
   349     //      MSVC insists on exporting an instantiation of MaybeStackArray, which
   350     //      requires that all functions be defined.
   351     //      An empty implementation of new() is rejected, it must return a value.
   352     //      Returning NULL is rejected by gcc for operator new.
   353     //      The expedient thing is just not to override operator new.
   354     //      While relatively pointless, heap allocated instances will function.
   355     // static void * U_EXPORT2 operator new(size_t size); 
   356     // static void * U_EXPORT2 operator new[](size_t size);
   357 #if U_HAVE_PLACEMENT_NEW
   358     // static void * U_EXPORT2 operator new(size_t, void *ptr);
   359 #endif
   360 };
   362 template<typename T, int32_t stackCapacity>
   363 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
   364     if(newCapacity>0) {
   365 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
   366       ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
   367 #endif
   368         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
   369         if(p!=NULL) {
   370             if(length>0) {
   371                 if(length>capacity) {
   372                     length=capacity;
   373                 }
   374                 if(length>newCapacity) {
   375                     length=newCapacity;
   376                 }
   377                 uprv_memcpy(p, ptr, length*sizeof(T));
   378             }
   379             releaseArray();
   380             ptr=p;
   381             capacity=newCapacity;
   382             needToRelease=TRUE;
   383         }
   384         return p;
   385     } else {
   386         return NULL;
   387     }
   388 }
   390 template<typename T, int32_t stackCapacity>
   391 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
   392     T *p;
   393     if(needToRelease) {
   394         p=ptr;
   395     } else if(length<=0) {
   396         return NULL;
   397     } else {
   398         if(length>capacity) {
   399             length=capacity;
   400         }
   401         p=(T *)uprv_malloc(length*sizeof(T));
   402 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
   403       ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
   404 #endif
   405         if(p==NULL) {
   406             return NULL;
   407         }
   408         uprv_memcpy(p, ptr, length*sizeof(T));
   409     }
   410     resultCapacity=length;
   411     ptr=stackArray;
   412     capacity=stackCapacity;
   413     needToRelease=FALSE;
   414     return p;
   415 }
   417 /**
   418  * Variant of MaybeStackArray that allocates a header struct and an array
   419  * in one contiguous memory block, using uprv_malloc() and uprv_free().
   420  * Provides internal memory with fixed array capacity. Can alias another memory
   421  * block or allocate one.
   422  * The stackCapacity is the number of T items in the internal memory,
   423  * not counting the H header.
   424  * Unlike LocalMemory and LocalArray, this class never adopts
   425  * (takes ownership of) another memory block.
   426  */
   427 template<typename H, typename T, int32_t stackCapacity>
   428 class MaybeStackHeaderAndArray {
   429 public:
   430     /**
   431      * Default constructor initializes with internal H+T[stackCapacity] buffer.
   432      */
   433     MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
   434     /**
   435      * Destructor deletes the memory (if owned).
   436      */
   437     ~MaybeStackHeaderAndArray() { releaseMemory(); }
   438     /**
   439      * Returns the array capacity (number of T items).
   440      * @return array capacity
   441      */
   442     int32_t getCapacity() const { return capacity; }
   443     /**
   444      * Access without ownership change.
   445      * @return the header pointer
   446      */
   447     H *getAlias() const { return ptr; }
   448     /**
   449      * Returns the array start.
   450      * @return array start, same address as getAlias()+1
   451      */
   452     T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
   453     /**
   454      * Returns the array limit.
   455      * @return array limit
   456      */
   457     T *getArrayLimit() const { return getArrayStart()+capacity; }
   458     /**
   459      * Access without ownership change. Same as getAlias().
   460      * A class instance can be used directly in expressions that take a T *.
   461      * @return the header pointer
   462      */
   463     operator H *() const { return ptr; }
   464     /**
   465      * Array item access (writable).
   466      * No index bounds check.
   467      * @param i array index
   468      * @return reference to the array item
   469      */
   470     T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
   471     /**
   472      * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
   473      * If the arguments are illegal, then the current memory is unchanged.
   474      * @param otherArray must not be NULL
   475      * @param otherCapacity must be >0
   476      */
   477     void aliasInstead(H *otherMemory, int32_t otherCapacity) {
   478         if(otherMemory!=NULL && otherCapacity>0) {
   479             releaseMemory();
   480             ptr=otherMemory;
   481             capacity=otherCapacity;
   482             needToRelease=FALSE;
   483         }
   484     }
   485     /**
   486      * Deletes the memory block (if owned) and allocates a new one,
   487      * copying the header and length T array items.
   488      * Returns the new header pointer.
   489      * If the allocation fails, then the current memory is unchanged and
   490      * this method returns NULL.
   491      * @param newCapacity can be less than or greater than the current capacity;
   492      *                    must be >0
   493      * @param length number of T items to be copied from the old array to the new one
   494      * @return the allocated pointer, or NULL if the allocation failed
   495      */
   496     inline H *resize(int32_t newCapacity, int32_t length=0);
   497     /**
   498      * Gives up ownership of the memory if owned, or else clones it,
   499      * copying the header and length T array items; resets itself to the internal memory.
   500      * Returns NULL if the allocation failed.
   501      * @param length number of T items to copy when cloning,
   502      *        and array capacity of the clone when cloning
   503      * @param resultCapacity will be set to the returned array's capacity (output-only)
   504      * @return the header pointer;
   505      *         caller becomes responsible for deleting the array
   506      */
   507     inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
   508 private:
   509     H *ptr;
   510     int32_t capacity;
   511     UBool needToRelease;
   512     // stackHeader must precede stackArray immediately.
   513     H stackHeader;
   514     T stackArray[stackCapacity];
   515     void releaseMemory() {
   516         if(needToRelease) {
   517             uprv_free(ptr);
   518         }
   519     }
   520     /* No comparison operators with other MaybeStackHeaderAndArray's. */
   521     bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
   522     bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
   523     /* No ownership transfer: No copy constructor, no assignment operator. */
   524     MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
   525     void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
   527     // No heap allocation. Use only on the stack.
   528     //   (Declaring these functions private triggers a cascade of problems;
   529     //    see the MaybeStackArray class for details.)
   530     // static void * U_EXPORT2 operator new(size_t size); 
   531     // static void * U_EXPORT2 operator new[](size_t size);
   532 #if U_HAVE_PLACEMENT_NEW
   533     // static void * U_EXPORT2 operator new(size_t, void *ptr);
   534 #endif
   535 };
   537 template<typename H, typename T, int32_t stackCapacity>
   538 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
   539                                                                 int32_t length) {
   540     if(newCapacity>=0) {
   541 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
   542       ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
   543 #endif
   544         H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
   545         if(p!=NULL) {
   546             if(length<0) {
   547                 length=0;
   548             } else if(length>0) {
   549                 if(length>capacity) {
   550                     length=capacity;
   551                 }
   552                 if(length>newCapacity) {
   553                     length=newCapacity;
   554                 }
   555             }
   556             uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
   557             releaseMemory();
   558             ptr=p;
   559             capacity=newCapacity;
   560             needToRelease=TRUE;
   561         }
   562         return p;
   563     } else {
   564         return NULL;
   565     }
   566 }
   568 template<typename H, typename T, int32_t stackCapacity>
   569 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
   570                                                                        int32_t &resultCapacity) {
   571     H *p;
   572     if(needToRelease) {
   573         p=ptr;
   574     } else {
   575         if(length<0) {
   576             length=0;
   577         } else if(length>capacity) {
   578             length=capacity;
   579         }
   580 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
   581       ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
   582 #endif
   583         p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
   584         if(p==NULL) {
   585             return NULL;
   586         }
   587         uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
   588     }
   589     resultCapacity=length;
   590     ptr=&stackHeader;
   591     capacity=stackCapacity;
   592     needToRelease=FALSE;
   593     return p;
   594 }
   596 U_NAMESPACE_END
   598 #endif  /* __cplusplus */
   599 #endif  /* CMEMORY_H */

mercurial