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