SkTypes.h revision e61a86cfa00ea393ecc4a71fca94e1d476a37ecc
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/*
3bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Copyright 2006 The Android Open Source Project
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * found in the LICENSE file.
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef SkTypes_DEFINED
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SkTypes_DEFINED
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkPreConfig.h"
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkUserConfig.h"
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkPostConfig.h"
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdint.h>
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/** \file SkTypes.h
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/** See SkGraphics::GetVersion() to retrieve these at runtime
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SKIA_VERSION_MAJOR  1
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SKIA_VERSION_MINOR  0
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SKIA_VERSION_PATCH  0
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    memory wrappers to be implemented by the porting layer (platform)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/** Called internally if we run out of memory. The platform implementation must
321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    not return, but should either throw an exception or otherwise exit.
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)*/
3406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)SK_API extern void sk_out_of_memory(void);
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)/** Called internally if we hit an unrecoverable error.
36bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    The platform implementation must not return, but should either throw
37bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    an exception or otherwise exit.
38f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)*/
39bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)SK_API extern void sk_throw(void);
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)enum {
4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SK_MALLOC_TEMP  = 0x01, //!< hint to sk_malloc that the requested memory will be freed in the scope of the stack frame
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SK_MALLOC_THROW = 0x02  //!< instructs sk_malloc to call sk_throw if the memory cannot be allocated.
441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)};
459bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)/** Return a block of memory (at least 4-byte aligned) of at least the
46f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    specified size. If the requested memory cannot be returned, either
47f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    return null (if SK_MALLOC_TEMP bit is clear) or throw an exception
48bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free().
491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)*/
50f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)SK_API extern void* sk_malloc_flags(size_t size, unsigned flags);
511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)/** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag
521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)*/
531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)SK_API extern void* sk_malloc_throw(size_t size);
54bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)/** Same as standard realloc(), but this one never returns null on failure. It will throw
559bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    an exception if it fails.
561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)*/
571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)SK_API extern void* sk_realloc_throw(void* buffer, size_t size);
58bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)/** Free memory returned by sk_malloc(). It is safe to pass null.
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/
609bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)SK_API extern void sk_free(void*);
6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
629bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)/** Much like calloc: returns a pointer to at least size zero bytes, or NULL on failure.
631e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) */
64SK_API extern void* sk_calloc(size_t size);
65
66/** Same as sk_calloc, but throws an exception instead of returning NULL on failure.
67 */
68SK_API extern void* sk_calloc_throw(size_t size);
69
70// bzero is safer than memset, but we can't rely on it, so... sk_bzero()
71static inline void sk_bzero(void* buffer, size_t size) {
72    memset(buffer, 0, size);
73}
74
75///////////////////////////////////////////////////////////////////////////////
76
77#ifdef SK_OVERRIDE_GLOBAL_NEW
78#include <new>
79
80inline void* operator new(size_t size) {
81    return sk_malloc_throw(size);
82}
83
84inline void operator delete(void* p) {
85    sk_free(p);
86}
87#endif
88
89///////////////////////////////////////////////////////////////////////////////
90
91#define SK_INIT_TO_AVOID_WARNING    = 0
92
93#ifndef SkDebugf
94    void SkDebugf(const char format[], ...);
95#endif
96
97#ifdef SK_DEBUG
98    #define SkASSERT(cond)              SK_DEBUGBREAK(cond)
99    #define SkDEBUGFAIL(message)        SkASSERT(false && message)
100    #define SkDEBUGCODE(code)           code
101    #define SkDECLAREPARAM(type, var)   , type var
102    #define SkPARAM(var)                , var
103//  #define SkDEBUGF(args       )       SkDebugf##args
104    #define SkDEBUGF(args       )       SkDebugf args
105    #define SkAssertResult(cond)        SkASSERT(cond)
106#else
107    #define SkASSERT(cond)
108    #define SkDEBUGFAIL(message)
109    #define SkDEBUGCODE(code)
110    #define SkDEBUGF(args)
111    #define SkDECLAREPARAM(type, var)
112    #define SkPARAM(var)
113
114    // unlike SkASSERT, this guy executes its condition in the non-debug build
115    #define SkAssertResult(cond)        cond
116#endif
117
118#ifdef SK_DEVELOPER
119    #define SkDEVCODE(code)             code
120    // the 'toString' helper functions convert Sk* objects to human-readable
121    // form in developer mode
122    #define SK_DEVELOPER_TO_STRING()    virtual void toString(SkString* str) const SK_OVERRIDE;
123#else
124    #define SkDEVCODE(code)
125    #define SK_DEVELOPER_TO_STRING()
126#endif
127
128template <bool>
129struct SkCompileAssert {
130};
131
132#define SK_COMPILE_ASSERT(expr, msg) \
133    typedef SkCompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] SK_UNUSED
134
135/*
136 *  Usage:  SK_MACRO_CONCAT(a, b)   to construct the symbol ab
137 *
138 *  SK_MACRO_CONCAT_IMPL_PRIV just exists to make this work. Do not use directly
139 *
140 */
141#define SK_MACRO_CONCAT(X, Y)           SK_MACRO_CONCAT_IMPL_PRIV(X, Y)
142#define SK_MACRO_CONCAT_IMPL_PRIV(X, Y)  X ## Y
143
144/*
145 *  Usage: SK_MACRO_APPEND_LINE(foo)    to make foo123, where 123 is the current
146 *                                      line number. Easy way to construct
147 *                                      unique names for local functions or
148 *                                      variables.
149 */
150#define SK_MACRO_APPEND_LINE(name)  SK_MACRO_CONCAT(name, __LINE__)
151
152/**
153 * For some classes, it's almost always an error to instantiate one without a name, e.g.
154 *   {
155 *       SkAutoMutexAcquire(&mutex);
156 *       <some code>
157 *   }
158 * In this case, the writer meant to hold mutex while the rest of the code in the block runs,
159 * but instead the mutex is acquired and then immediately released.  The correct usage is
160 *   {
161 *       SkAutoMutexAcquire lock(&mutex);
162 *       <some code>
163 *   }
164 *
165 * To prevent callers from instantiating your class without a name, use SK_REQUIRE_LOCAL_VAR
166 * like this:
167 *   class classname {
168 *       <your class>
169 *   };
170 *   #define classname(...) SK_REQUIRE_LOCAL_VAR(classname)
171 *
172 * This won't work with templates, and you must inline the class' constructors and destructors.
173 * Take a look at SkAutoFree and SkAutoMalloc in this file for examples.
174 */
175#define SK_REQUIRE_LOCAL_VAR(classname) \
176    SK_COMPILE_ASSERT(false, missing_name_for_##classname)
177
178///////////////////////////////////////////////////////////////////////
179
180/**
181 *  Fast type for signed 8 bits. Use for parameter passing and local variables,
182 *  not for storage.
183 */
184typedef int S8CPU;
185
186/**
187 *  Fast type for unsigned 8 bits. Use for parameter passing and local
188 *  variables, not for storage
189 */
190typedef unsigned U8CPU;
191
192/**
193 *  Fast type for signed 16 bits. Use for parameter passing and local variables,
194 *  not for storage
195 */
196typedef int S16CPU;
197
198/**
199 *  Fast type for unsigned 16 bits. Use for parameter passing and local
200 *  variables, not for storage
201 */
202typedef unsigned U16CPU;
203
204/**
205 *  Meant to be faster than bool (doesn't promise to be 0 or 1,
206 *  just 0 or non-zero
207 */
208typedef int SkBool;
209
210/**
211 *  Meant to be a small version of bool, for storage purposes. Will be 0 or 1
212 */
213typedef uint8_t SkBool8;
214
215#ifdef SK_DEBUG
216    SK_API int8_t      SkToS8(intmax_t);
217    SK_API uint8_t     SkToU8(uintmax_t);
218    SK_API int16_t     SkToS16(intmax_t);
219    SK_API uint16_t    SkToU16(uintmax_t);
220    SK_API int32_t     SkToS32(intmax_t);
221    SK_API uint32_t    SkToU32(uintmax_t);
222#else
223    #define SkToS8(x)   ((int8_t)(x))
224    #define SkToU8(x)   ((uint8_t)(x))
225    #define SkToS16(x)  ((int16_t)(x))
226    #define SkToU16(x)  ((uint16_t)(x))
227    #define SkToS32(x)  ((int32_t)(x))
228    #define SkToU32(x)  ((uint32_t)(x))
229#endif
230
231/** Returns 0 or 1 based on the condition
232*/
233#define SkToBool(cond)  ((cond) != 0)
234
235#define SK_MaxS16   32767
236#define SK_MinS16   -32767
237#define SK_MaxU16   0xFFFF
238#define SK_MinU16   0
239#define SK_MaxS32   0x7FFFFFFF
240#define SK_MinS32   -SK_MaxS32
241#define SK_MaxU32   0xFFFFFFFF
242#define SK_MinU32   0
243#define SK_NaN32    (1 << 31)
244
245/** Returns true if the value can be represented with signed 16bits
246 */
247static inline bool SkIsS16(long x) {
248    return (int16_t)x == x;
249}
250
251/** Returns true if the value can be represented with unsigned 16bits
252 */
253static inline bool SkIsU16(long x) {
254    return (uint16_t)x == x;
255}
256
257//////////////////////////////////////////////////////////////////////////////
258#ifndef SK_OFFSETOF
259    #define SK_OFFSETOF(type, field)    (size_t)((char*)&(((type*)1)->field) - (char*)1)
260#endif
261
262/** Returns the number of entries in an array (not a pointer)
263*/
264#define SK_ARRAY_COUNT(array)       (sizeof(array) / sizeof(array[0]))
265
266#define SkAlign2(x)     (((x) + 1) >> 1 << 1)
267#define SkIsAlign2(x)   (0 == ((x) & 1))
268
269#define SkAlign4(x)     (((x) + 3) >> 2 << 2)
270#define SkIsAlign4(x)   (0 == ((x) & 3))
271
272#define SkAlign8(x)     (((x) + 7) >> 3 << 3)
273#define SkIsAlign8(x)   (0 == ((x) & 7))
274
275typedef uint32_t SkFourByteTag;
276#define SkSetFourByteTag(a, b, c, d)    (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
277
278/** 32 bit integer to hold a unicode value
279*/
280typedef int32_t SkUnichar;
281/** 32 bit value to hold a millisecond count
282*/
283typedef uint32_t SkMSec;
284/** 1 second measured in milliseconds
285*/
286#define SK_MSec1 1000
287/** maximum representable milliseconds
288*/
289#define SK_MSecMax 0x7FFFFFFF
290/** Returns a < b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
291*/
292#define SkMSec_LT(a, b)     ((int32_t)(a) - (int32_t)(b) < 0)
293/** Returns a <= b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
294*/
295#define SkMSec_LE(a, b)     ((int32_t)(a) - (int32_t)(b) <= 0)
296
297/****************************************************************************
298    The rest of these only build with C++
299*/
300#ifdef __cplusplus
301
302/** Faster than SkToBool for integral conditions. Returns 0 or 1
303*/
304static inline int Sk32ToBool(uint32_t n) {
305    return (n | (0-n)) >> 31;
306}
307
308/** Generic swap function. Classes with efficient swaps should specialize this function to take
309    their fast path. This function is used by SkTSort. */
310template <typename T> inline void SkTSwap(T& a, T& b) {
311    T c(a);
312    a = b;
313    b = c;
314}
315
316static inline int32_t SkAbs32(int32_t value) {
317    if (value < 0) {
318        value = -value;
319    }
320    return value;
321}
322
323template <typename T> inline T SkTAbs(T value) {
324    if (value < 0) {
325        value = -value;
326    }
327    return value;
328}
329
330static inline int32_t SkMax32(int32_t a, int32_t b) {
331    if (a < b)
332        a = b;
333    return a;
334}
335
336static inline int32_t SkMin32(int32_t a, int32_t b) {
337    if (a > b)
338        a = b;
339    return a;
340}
341
342template <typename T> const T& SkTMin(const T& a, const T& b) {
343    return (a < b) ? a : b;
344}
345
346template <typename T> const T& SkTMax(const T& a, const T& b) {
347    return (b < a) ? a : b;
348}
349
350static inline int32_t SkSign32(int32_t a) {
351    return (a >> 31) | ((unsigned) -a >> 31);
352}
353
354static inline int32_t SkFastMin32(int32_t value, int32_t max) {
355    if (value > max) {
356        value = max;
357    }
358    return value;
359}
360
361/** Returns signed 32 bit value pinned between min and max, inclusively
362*/
363static inline int32_t SkPin32(int32_t value, int32_t min, int32_t max) {
364    if (value < min) {
365        value = min;
366    }
367    if (value > max) {
368        value = max;
369    }
370    return value;
371}
372
373static inline uint32_t SkSetClearShift(uint32_t bits, bool cond,
374                                       unsigned shift) {
375    SkASSERT((int)cond == 0 || (int)cond == 1);
376    return (bits & ~(1 << shift)) | ((int)cond << shift);
377}
378
379static inline uint32_t SkSetClearMask(uint32_t bits, bool cond,
380                                      uint32_t mask) {
381    return cond ? bits | mask : bits & ~mask;
382}
383
384///////////////////////////////////////////////////////////////////////////////
385
386/** Use to combine multiple bits in a bitmask in a type safe way.
387 */
388template <typename T>
389T SkTBitOr(T a, T b) {
390    return (T)(a | b);
391}
392
393/**
394 *  Use to cast a pointer to a different type, and maintaining strict-aliasing
395 */
396template <typename Dst> Dst SkTCast(const void* ptr) {
397    union {
398        const void* src;
399        Dst dst;
400    } data;
401    data.src = ptr;
402    return data.dst;
403}
404
405//////////////////////////////////////////////////////////////////////////////
406
407/** \class SkNoncopyable
408
409SkNoncopyable is the base class for objects that may do not want to
410be copied. It hides its copy-constructor and its assignment-operator.
411*/
412class SK_API SkNoncopyable {
413public:
414    SkNoncopyable() {}
415
416private:
417    SkNoncopyable(const SkNoncopyable&);
418    SkNoncopyable& operator=(const SkNoncopyable&);
419};
420
421class SkAutoFree : SkNoncopyable {
422public:
423    SkAutoFree() : fPtr(NULL) {}
424    explicit SkAutoFree(void* ptr) : fPtr(ptr) {}
425    ~SkAutoFree() { sk_free(fPtr); }
426
427    /** Return the currently allocate buffer, or null
428    */
429    void* get() const { return fPtr; }
430
431    /** Assign a new ptr allocated with sk_malloc (or null), and return the
432        previous ptr. Note it is the caller's responsibility to sk_free the
433        returned ptr.
434    */
435    void* set(void* ptr) {
436        void* prev = fPtr;
437        fPtr = ptr;
438        return prev;
439    }
440
441    /** Transfer ownership of the current ptr to the caller, setting the
442        internal reference to null. Note the caller is reponsible for calling
443        sk_free on the returned address.
444    */
445    void* detach() { return this->set(NULL); }
446
447    /** Free the current buffer, and set the internal reference to NULL. Same
448        as calling sk_free(detach())
449    */
450    void free() {
451        sk_free(fPtr);
452        fPtr = NULL;
453    }
454
455private:
456    void* fPtr;
457    // illegal
458    SkAutoFree(const SkAutoFree&);
459    SkAutoFree& operator=(const SkAutoFree&);
460};
461#define SkAutoFree(...) SK_REQUIRE_LOCAL_VAR(SkAutoFree)
462
463/**
464 *  Manage an allocated block of heap memory. This object is the sole manager of
465 *  the lifetime of the block, so the caller must not call sk_free() or delete
466 *  on the block, unless detach() was called.
467 */
468class SkAutoMalloc : public SkNoncopyable {
469public:
470    explicit SkAutoMalloc(size_t size = 0) {
471        fPtr = size ? sk_malloc_throw(size) : NULL;
472        fSize = size;
473    }
474
475    ~SkAutoMalloc() {
476        sk_free(fPtr);
477    }
478
479    /**
480     *  Passed to reset to specify what happens if the requested size is smaller
481     *  than the current size (and the current block was dynamically allocated).
482     */
483    enum OnShrink {
484        /**
485         *  If the requested size is smaller than the current size, and the
486         *  current block is dynamically allocated, free the old block and
487         *  malloc a new block of the smaller size.
488         */
489        kAlloc_OnShrink,
490
491        /**
492         *  If the requested size is smaller than the current size, and the
493         *  current block is dynamically allocated, just return the old
494         *  block.
495         */
496        kReuse_OnShrink
497    };
498
499    /**
500     *  Reallocates the block to a new size. The ptr may or may not change.
501     */
502    void* reset(size_t size, OnShrink shrink = kAlloc_OnShrink,  bool* didChangeAlloc = NULL) {
503        if (size == fSize || (kReuse_OnShrink == shrink && size < fSize)) {
504            if (NULL != didChangeAlloc) {
505                *didChangeAlloc = false;
506            }
507            return fPtr;
508        }
509
510        sk_free(fPtr);
511        fPtr = size ? sk_malloc_throw(size) : NULL;
512        fSize = size;
513        if (NULL != didChangeAlloc) {
514            *didChangeAlloc = true;
515        }
516
517        return fPtr;
518    }
519
520    /**
521     *  Releases the block back to the heap
522     */
523    void free() {
524        this->reset(0);
525    }
526
527    /**
528     *  Return the allocated block.
529     */
530    void* get() { return fPtr; }
531    const void* get() const { return fPtr; }
532
533   /** Transfer ownership of the current ptr to the caller, setting the
534       internal reference to null. Note the caller is reponsible for calling
535       sk_free on the returned address.
536    */
537    void* detach() {
538        void* ptr = fPtr;
539        fPtr = NULL;
540        fSize = 0;
541        return ptr;
542    }
543
544private:
545    void*   fPtr;
546    size_t  fSize;  // can be larger than the requested size (see kReuse)
547};
548#define SkAutoMalloc(...) SK_REQUIRE_LOCAL_VAR(SkAutoMalloc)
549
550/**
551 *  Manage an allocated block of memory. If the requested size is <= kSize, then
552 *  the allocation will come from the stack rather than the heap. This object
553 *  is the sole manager of the lifetime of the block, so the caller must not
554 *  call sk_free() or delete on the block.
555 */
556template <size_t kSize> class SkAutoSMalloc : SkNoncopyable {
557public:
558    /**
559     *  Creates initially empty storage. get() returns a ptr, but it is to
560     *  a zero-byte allocation. Must call reset(size) to return an allocated
561     *  block.
562     */
563    SkAutoSMalloc() {
564        fPtr = fStorage;
565        fSize = kSize;
566    }
567
568    /**
569     *  Allocate a block of the specified size. If size <= kSize, then the
570     *  allocation will come from the stack, otherwise it will be dynamically
571     *  allocated.
572     */
573    explicit SkAutoSMalloc(size_t size) {
574        fPtr = fStorage;
575        fSize = kSize;
576        this->reset(size);
577    }
578
579    /**
580     *  Free the allocated block (if any). If the block was small enought to
581     *  have been allocated on the stack (size <= kSize) then this does nothing.
582     */
583    ~SkAutoSMalloc() {
584        if (fPtr != (void*)fStorage) {
585            sk_free(fPtr);
586        }
587    }
588
589    /**
590     *  Return the allocated block. May return non-null even if the block is
591     *  of zero size. Since this may be on the stack or dynamically allocated,
592     *  the caller must not call sk_free() on it, but must rely on SkAutoSMalloc
593     *  to manage it.
594     */
595    void* get() const { return fPtr; }
596
597    /**
598     *  Return a new block of the requested size, freeing (as necessary) any
599     *  previously allocated block. As with the constructor, if size <= kSize
600     *  then the return block may be allocated locally, rather than from the
601     *  heap.
602     */
603    void* reset(size_t size,
604                SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink,
605                bool* didChangeAlloc = NULL) {
606        size = (size < kSize) ? kSize : size;
607        bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink || size > fSize);
608        if (NULL != didChangeAlloc) {
609            *didChangeAlloc = alloc;
610        }
611        if (alloc) {
612            if (fPtr != (void*)fStorage) {
613                sk_free(fPtr);
614            }
615
616            if (size == kSize) {
617                SkASSERT(fPtr != fStorage); // otherwise we lied when setting didChangeAlloc.
618                fPtr = fStorage;
619            } else {
620                fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP);
621            }
622
623            fSize = size;
624        }
625        SkASSERT(fSize >= size && fSize >= kSize);
626        SkASSERT((fPtr == fStorage) || fSize > kSize);
627        return fPtr;
628    }
629
630private:
631    void*       fPtr;
632    size_t      fSize;  // can be larger than the requested size (see kReuse)
633    uint32_t    fStorage[(kSize + 3) >> 2];
634};
635// Can't guard the constructor because it's a template class.
636
637#endif /* C++ */
638
639#endif
640