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