gfx/skia/trunk/include/core/SkTemplates.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.

     2 /*
     3  * Copyright 2006 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
    10 #ifndef SkTemplates_DEFINED
    11 #define SkTemplates_DEFINED
    13 #include "SkTypes.h"
    14 #include <limits>
    15 #include <limits.h>
    16 #include <new>
    18 /** \file SkTemplates.h
    20     This file contains light-weight template classes for type-safe and exception-safe
    21     resource management.
    22 */
    24 /**
    25  *  Marks a local variable as known to be unused (to avoid warnings).
    26  *  Note that this does *not* prevent the local variable from being optimized away.
    27  */
    28 template<typename T> inline void sk_ignore_unused_variable(const T&) { }
    30 /**
    31  *  SkTIsConst<T>::value is true if the type T is const.
    32  *  The type T is constrained not to be an array or reference type.
    33  */
    34 template <typename T> struct SkTIsConst {
    35     static T* t;
    36     static uint16_t test(const volatile void*);
    37     static uint32_t test(volatile void *);
    38     static const bool value = (sizeof(uint16_t) == sizeof(test(t)));
    39 };
    41 ///@{
    42 /** SkTConstType<T, CONST>::type will be 'const T' if CONST is true, 'T' otherwise. */
    43 template <typename T, bool CONST> struct SkTConstType {
    44     typedef T type;
    45 };
    46 template <typename T> struct SkTConstType<T, true> {
    47     typedef const T type;
    48 };
    49 ///@}
    51 /**
    52  *  Returns a pointer to a D which comes immediately after S[count].
    53  */
    54 template <typename D, typename S> static D* SkTAfter(S* ptr, size_t count = 1) {
    55     return reinterpret_cast<D*>(ptr + count);
    56 }
    58 /**
    59  *  Returns a pointer to a D which comes byteOffset bytes after S.
    60  */
    61 template <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffset) {
    62     // The intermediate char* has the same const-ness as D as this produces better error messages.
    63     // This relies on the fact that reinterpret_cast can add constness, but cannot remove it.
    64     return reinterpret_cast<D*>(
    65         reinterpret_cast<typename SkTConstType<char, SkTIsConst<D>::value>::type*>(ptr) + byteOffset
    66     );
    67 }
    69 /** SkTSetBit<N, T>::value is a T with the Nth bit set. */
    70 template<unsigned N, typename T = uintmax_t> struct SkTSetBit {
    71     static const T value = static_cast<T>(1) << N;
    72     SK_COMPILE_ASSERT(sizeof(T)*CHAR_BIT > N, SkTSetBit_N_too_large);
    73     SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, SkTSetBit_T_must_be_integer);
    74     SK_COMPILE_ASSERT(!std::numeric_limits<T>::is_signed, SkTSetBit_T_must_be_unsigned);
    75     SK_COMPILE_ASSERT(std::numeric_limits<T>::radix == 2, SkTSetBit_T_radix_must_be_2);
    76 };
    78 /** \class SkAutoTCallVProc
    80     Call a function when this goes out of scope. The template uses two
    81     parameters, the object, and a function that is to be called in the destructor.
    82     If detach() is called, the object reference is set to null. If the object
    83     reference is null when the destructor is called, we do not call the
    84     function.
    85 */
    86 template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
    87 public:
    88     SkAutoTCallVProc(T* obj): fObj(obj) {}
    89     ~SkAutoTCallVProc() { if (fObj) P(fObj); }
    90     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
    91 private:
    92     T* fObj;
    93 };
    95 /** \class SkAutoTCallIProc
    97 Call a function when this goes out of scope. The template uses two
    98 parameters, the object, and a function that is to be called in the destructor.
    99 If detach() is called, the object reference is set to null. If the object
   100 reference is null when the destructor is called, we do not call the
   101 function.
   102 */
   103 template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
   104 public:
   105     SkAutoTCallIProc(T* obj): fObj(obj) {}
   106     ~SkAutoTCallIProc() { if (fObj) P(fObj); }
   107     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
   108 private:
   109     T* fObj;
   110 };
   112 /** \class SkAutoTDelete
   113   An SkAutoTDelete<T> is like a T*, except that the destructor of SkAutoTDelete<T>
   114   automatically deletes the pointer it holds (if any).  That is, SkAutoTDelete<T>
   115   owns the T object that it points to.  Like a T*, an SkAutoTDelete<T> may hold
   116   either NULL or a pointer to a T object.  Also like T*, SkAutoTDelete<T> is
   117   thread-compatible, and once you dereference it, you get the threadsafety
   118   guarantees of T.
   120   The size of a SkAutoTDelete is small: sizeof(SkAutoTDelete<T>) == sizeof(T*)
   121 */
   122 template <typename T> class SkAutoTDelete : SkNoncopyable {
   123 public:
   124     SkAutoTDelete(T* obj = NULL) : fObj(obj) {}
   125     ~SkAutoTDelete() { SkDELETE(fObj); }
   127     T* get() const { return fObj; }
   128     T& operator*() const { SkASSERT(fObj); return *fObj; }
   129     T* operator->() const { SkASSERT(fObj); return fObj; }
   131     void reset(T* obj) {
   132         if (fObj != obj) {
   133             SkDELETE(fObj);
   134             fObj = obj;
   135         }
   136     }
   138     /**
   139      *  Delete the owned object, setting the internal pointer to NULL.
   140      */
   141     void free() {
   142         SkDELETE(fObj);
   143         fObj = NULL;
   144     }
   146     /**
   147      *  Transfer ownership of the object to the caller, setting the internal
   148      *  pointer to NULL. Note that this differs from get(), which also returns
   149      *  the pointer, but it does not transfer ownership.
   150      */
   151     T* detach() {
   152         T* obj = fObj;
   153         fObj = NULL;
   154         return obj;
   155     }
   157     void swap(SkAutoTDelete* that) {
   158         SkTSwap(fObj, that->fObj);
   159     }
   161 private:
   162     T*  fObj;
   163 };
   165 // Calls ~T() in the destructor.
   166 template <typename T> class SkAutoTDestroy : SkNoncopyable {
   167 public:
   168     SkAutoTDestroy(T* obj = NULL) : fObj(obj) {}
   169     ~SkAutoTDestroy() {
   170         if (NULL != fObj) {
   171             fObj->~T();
   172         }
   173     }
   175     T* get() const { return fObj; }
   176     T& operator*() const { SkASSERT(fObj); return *fObj; }
   177     T* operator->() const { SkASSERT(fObj); return fObj; }
   179 private:
   180     T*  fObj;
   181 };
   183 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
   184 public:
   185     SkAutoTDeleteArray(T array[]) : fArray(array) {}
   186     ~SkAutoTDeleteArray() { SkDELETE_ARRAY(fArray); }
   188     T*      get() const { return fArray; }
   189     void    free() { SkDELETE_ARRAY(fArray); fArray = NULL; }
   190     T*      detach() { T* array = fArray; fArray = NULL; return array; }
   192     void reset(T array[]) {
   193         if (fArray != array) {
   194             SkDELETE_ARRAY(fArray);
   195             fArray = array;
   196         }
   197     }
   199 private:
   200     T*  fArray;
   201 };
   203 /** Allocate an array of T elements, and free the array in the destructor
   204  */
   205 template <typename T> class SkAutoTArray : SkNoncopyable {
   206 public:
   207     SkAutoTArray() {
   208         fArray = NULL;
   209         SkDEBUGCODE(fCount = 0;)
   210     }
   211     /** Allocate count number of T elements
   212      */
   213     explicit SkAutoTArray(int count) {
   214         SkASSERT(count >= 0);
   215         fArray = NULL;
   216         if (count) {
   217             fArray = SkNEW_ARRAY(T, count);
   218         }
   219         SkDEBUGCODE(fCount = count;)
   220     }
   222     /** Reallocates given a new count. Reallocation occurs even if new count equals old count.
   223      */
   224     void reset(int count) {
   225         SkDELETE_ARRAY(fArray);
   226         SkASSERT(count >= 0);
   227         fArray = NULL;
   228         if (count) {
   229             fArray = SkNEW_ARRAY(T, count);
   230         }
   231         SkDEBUGCODE(fCount = count;)
   232     }
   234     ~SkAutoTArray() {
   235         SkDELETE_ARRAY(fArray);
   236     }
   238     /** Return the array of T elements. Will be NULL if count == 0
   239      */
   240     T* get() const { return fArray; }
   242     /** Return the nth element in the array
   243      */
   244     T&  operator[](int index) const {
   245         SkASSERT((unsigned)index < (unsigned)fCount);
   246         return fArray[index];
   247     }
   249 private:
   250     T*  fArray;
   251     SkDEBUGCODE(int fCount;)
   252 };
   254 /** Wraps SkAutoTArray, with room for up to N elements preallocated
   255  */
   256 template <int N, typename T> class SkAutoSTArray : SkNoncopyable {
   257 public:
   258     /** Initialize with no objects */
   259     SkAutoSTArray() {
   260         fArray = NULL;
   261         fCount = 0;
   262     }
   264     /** Allocate count number of T elements
   265      */
   266     SkAutoSTArray(int count) {
   267         fArray = NULL;
   268         fCount = 0;
   269         this->reset(count);
   270     }
   272     ~SkAutoSTArray() {
   273         this->reset(0);
   274     }
   276     /** Destroys previous objects in the array and default constructs count number of objects */
   277     void reset(int count) {
   278         T* start = fArray;
   279         T* iter = start + fCount;
   280         while (iter > start) {
   281             (--iter)->~T();
   282         }
   284         if (fCount != count) {
   285             if (fCount > N) {
   286                 // 'fArray' was allocated last time so free it now
   287                 SkASSERT((T*) fStorage != fArray);
   288                 sk_free(fArray);
   289             }
   291             if (count > N) {
   292                 fArray = (T*) sk_malloc_throw(count * sizeof(T));
   293             } else if (count > 0) {
   294                 fArray = (T*) fStorage;
   295             } else {
   296                 fArray = NULL;
   297             }
   299             fCount = count;
   300         }
   302         iter = fArray;
   303         T* stop = fArray + count;
   304         while (iter < stop) {
   305             SkNEW_PLACEMENT(iter++, T);
   306         }
   307     }
   309     /** Return the number of T elements in the array
   310      */
   311     int count() const { return fCount; }
   313     /** Return the array of T elements. Will be NULL if count == 0
   314      */
   315     T* get() const { return fArray; }
   317     /** Return the nth element in the array
   318      */
   319     T&  operator[](int index) const {
   320         SkASSERT(index < fCount);
   321         return fArray[index];
   322     }
   324 private:
   325     int     fCount;
   326     T*      fArray;
   327     // since we come right after fArray, fStorage should be properly aligned
   328     char    fStorage[N * sizeof(T)];
   329 };
   331 /** Manages an array of T elements, freeing the array in the destructor.
   332  *  Does NOT call any constructors/destructors on T (T must be POD).
   333  */
   334 template <typename T> class SkAutoTMalloc : SkNoncopyable {
   335 public:
   336     /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */
   337     explicit SkAutoTMalloc(T* ptr = NULL) {
   338         fPtr = ptr;
   339     }
   341     /** Allocates space for 'count' Ts. */
   342     explicit SkAutoTMalloc(size_t count) {
   343         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
   344     }
   346     ~SkAutoTMalloc() {
   347         sk_free(fPtr);
   348     }
   350     /** Resize the memory area pointed to by the current ptr preserving contents. */
   351     void realloc(size_t count) {
   352         fPtr = reinterpret_cast<T*>(sk_realloc_throw(fPtr, count * sizeof(T)));
   353     }
   355     /** Resize the memory area pointed to by the current ptr without preserving contents. */
   356     void reset(size_t count) {
   357         sk_free(fPtr);
   358         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
   359     }
   361     T* get() const { return fPtr; }
   363     operator T*() {
   364         return fPtr;
   365     }
   367     operator const T*() const {
   368         return fPtr;
   369     }
   371     T& operator[](int index) {
   372         return fPtr[index];
   373     }
   375     const T& operator[](int index) const {
   376         return fPtr[index];
   377     }
   379     /**
   380      *  Transfer ownership of the ptr to the caller, setting the internal
   381      *  pointer to NULL. Note that this differs from get(), which also returns
   382      *  the pointer, but it does not transfer ownership.
   383      */
   384     T* detach() {
   385         T* ptr = fPtr;
   386         fPtr = NULL;
   387         return ptr;
   388     }
   390 private:
   391     T* fPtr;
   392 };
   394 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
   395 public:
   396     SkAutoSTMalloc() {
   397         fPtr = NULL;
   398     }
   400     SkAutoSTMalloc(size_t count) {
   401         if (count > N) {
   402             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
   403         } else if (count) {
   404             fPtr = fTStorage;
   405         } else {
   406             fPtr = NULL;
   407         }
   408     }
   410     ~SkAutoSTMalloc() {
   411         if (fPtr != fTStorage) {
   412             sk_free(fPtr);
   413         }
   414     }
   416     // doesn't preserve contents
   417     T* reset(size_t count) {
   418         if (fPtr != fTStorage) {
   419             sk_free(fPtr);
   420         }
   421         if (count > N) {
   422             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
   423         } else if (count) {
   424             fPtr = fTStorage;
   425         } else {
   426             fPtr = NULL;
   427         }
   428         return fPtr;
   429     }
   431     T* get() const { return fPtr; }
   433     operator T*() {
   434         return fPtr;
   435     }
   437     operator const T*() const {
   438         return fPtr;
   439     }
   441     T& operator[](int index) {
   442         return fPtr[index];
   443     }
   445     const T& operator[](int index) const {
   446         return fPtr[index];
   447     }
   449 private:
   450     T*          fPtr;
   451     union {
   452         uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
   453         T           fTStorage[1];   // do NOT want to invoke T::T()
   454     };
   455 };
   457 /**
   458  * Reserves memory that is aligned on double and pointer boundaries.
   459  * Hopefully this is sufficient for all practical purposes.
   460  */
   461 template <size_t N> class SkAlignedSStorage : SkNoncopyable {
   462 public:
   463     void* get() { return fData; }
   464 private:
   465     union {
   466         void*   fPtr;
   467         double  fDouble;
   468         char    fData[N];
   469     };
   470 };
   472 /**
   473  * Reserves memory that is aligned on double and pointer boundaries.
   474  * Hopefully this is sufficient for all practical purposes. Otherwise,
   475  * we have to do some arcane trickery to determine alignment of non-POD
   476  * types. Lifetime of the memory is the lifetime of the object.
   477  */
   478 template <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {
   479 public:
   480     /**
   481      * Returns void* because this object does not initialize the
   482      * memory. Use placement new for types that require a cons.
   483      */
   484     void* get() { return fStorage.get(); }
   485 private:
   486     SkAlignedSStorage<sizeof(T)*N> fStorage;
   487 };
   489 #endif

mercurial