1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkTemplates_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkTemplates_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h"
14562b2e67a29f24db4c258aa2fa59cd7b4ee15174bungeman@google.com#include <limits.h>
157103f182ce61280eacb35f1832df350b642a5381bungeman@google.com#include <new>
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \file SkTemplates.h
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    This file contains light-weight template classes for type-safe and exception-safe
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    resource management.
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com/**
247de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.com *  Marks a local variable as known to be unused (to avoid warnings).
257de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.com *  Note that this does *not* prevent the local variable from being optimized away.
267de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.com */
277de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.comtemplate<typename T> inline void sk_ignore_unused_variable(const T&) { }
287de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.com
297de18e5c7b4e4a8ad8910b1016688ded902f185bbungeman@google.com/**
3091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com *  SkTIsConst<T>::value is true if the type T is const.
3191208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com *  The type T is constrained not to be an array or reference type.
3291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com */
3391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> struct SkTIsConst {
3491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    static T* t;
3591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    static uint16_t test(const volatile void*);
3691208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    static uint32_t test(volatile void *);
3791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    static const bool value = (sizeof(uint16_t) == sizeof(test(t)));
3891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com};
3991208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com
4091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com///@{
4191208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com/** SkTConstType<T, CONST>::type will be 'const T' if CONST is true, 'T' otherwise. */
4291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T, bool CONST> struct SkTConstType {
4391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    typedef T type;
4491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com};
4591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> struct SkTConstType<T, true> {
4691208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    typedef const T type;
4791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com};
4891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com///@}
4991208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com
50b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org/**
51b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org *  Returns a pointer to a D which comes immediately after S[count].
52b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org */
53b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.orgtemplate <typename D, typename S> static D* SkTAfter(S* ptr, size_t count = 1) {
54b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    return reinterpret_cast<D*>(ptr + count);
55b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org}
56b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org
57b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org/**
58b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org *  Returns a pointer to a D which comes byteOffset bytes after S.
59b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org */
60b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.orgtemplate <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffset) {
61b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    // The intermediate char* has the same const-ness as D as this produces better error messages.
62b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    // This relies on the fact that reinterpret_cast can add constness, but cannot remove it.
63b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    return reinterpret_cast<D*>(
64b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        reinterpret_cast<typename SkTConstType<char, SkTIsConst<D>::value>::type*>(ptr) + byteOffset
65b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    );
66b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org}
67b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkAutoTCallVProc
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Call a function when this goes out of scope. The template uses two
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    parameters, the object, and a function that is to be called in the destructor.
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    If detach() is called, the object reference is set to null. If the object
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    reference is null when the destructor is called, we do not call the
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    function.
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTCallVProc(T* obj): fObj(obj) {}
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoTCallVProc() { if (fObj) P(fObj); }
80a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
81a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    operator T*() const { return fObj; }
82a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    T* operator->() const { SkASSERT(fObj); return fObj; }
83a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* detach() { T* obj = fObj; fObj = NULL; return obj; }
85a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    void reset(T* obj = NULL) {
86a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (fObj != obj) {
87a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (fObj) {
88a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                P(fObj);
89a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
90a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            fObj = obj;
91a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
92a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* fObj;
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkAutoTCallIProc
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comCall a function when this goes out of scope. The template uses two
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comparameters, the object, and a function that is to be called in the destructor.
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comIf detach() is called, the object reference is set to null. If the object
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comreference is null when the destructor is called, we do not call the
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comfunction.
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTCallIProc(T* obj): fObj(obj) {}
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoTCallIProc() { if (fObj) P(fObj); }
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* detach() { T* obj = fObj; fObj = NULL; return obj; }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* fObj;
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
114e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org/** \class SkAutoTDelete
115e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  An SkAutoTDelete<T> is like a T*, except that the destructor of SkAutoTDelete<T>
116e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  automatically deletes the pointer it holds (if any).  That is, SkAutoTDelete<T>
117e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  owns the T object that it points to.  Like a T*, an SkAutoTDelete<T> may hold
118e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  either NULL or a pointer to a T object.  Also like T*, SkAutoTDelete<T> is
119e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  thread-compatible, and once you dereference it, you get the threadsafety
120e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  guarantees of T.
121e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org
122e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org  The size of a SkAutoTDelete is small: sizeof(SkAutoTDelete<T>) == sizeof(T*)
123e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org*/
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T> class SkAutoTDelete : SkNoncopyable {
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1269d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com    SkAutoTDelete(T* obj = NULL) : fObj(obj) {}
1271198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com    ~SkAutoTDelete() { SkDELETE(fObj); }
12852657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com
12952657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    T* get() const { return fObj; }
1301790e25e1829ed4091fb149764425df7a3c9c0e0halcanary    operator T*() { return fObj; }
13152657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    T& operator*() const { SkASSERT(fObj); return *fObj; }
13252657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    T* operator->() const { SkASSERT(fObj); return fObj; }
13352657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com
1349d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com    void reset(T* obj) {
1359d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com        if (fObj != obj) {
1361198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com            SkDELETE(fObj);
1379d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com            fObj = obj;
1389d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com        }
1399d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com    }
1409d1cff124c14e550889a5755ffa5e6537af7c8c8reed@google.com
14152657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    /**
14252657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     *  Delete the owned object, setting the internal pointer to NULL.
14352657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     */
14452657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    void free() {
1451198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        SkDELETE(fObj);
14652657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com        fObj = NULL;
14757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14952657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    /**
15052657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     *  Transfer ownership of the object to the caller, setting the internal
15152657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     *  pointer to NULL. Note that this differs from get(), which also returns
15252657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     *  the pointer, but it does not transfer ownership.
15352657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com     */
15452657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    T* detach() {
15552657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com        T* obj = fObj;
15652657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com        fObj = NULL;
15752657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com        return obj;
15852657c75b5d4c0e72d64ecaec504b26d0d215a33reed@google.com    }
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16090313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org    void swap(SkAutoTDelete* that) {
16190313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org        SkTSwap(fObj, that->fObj);
16290313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org    }
16390313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*  fObj;
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com// Calls ~T() in the destructor.
169d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.comtemplate <typename T> class SkAutoTDestroy : SkNoncopyable {
170d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.compublic:
171d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    SkAutoTDestroy(T* obj = NULL) : fObj(obj) {}
172d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    ~SkAutoTDestroy() {
17349f085dddff10473b6ebf832a974288300224e60bsalomon        if (fObj) {
174d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com            fObj->~T();
175d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        }
176d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    }
177d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
178d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    T* get() const { return fObj; }
179d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    T& operator*() const { SkASSERT(fObj); return *fObj; }
180d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    T* operator->() const { SkASSERT(fObj); return fObj; }
181d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
182d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.comprivate:
183d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    T*  fObj;
184d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com};
185d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T> class SkAutoTDeleteArray : SkNoncopyable {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTDeleteArray(T array[]) : fArray(array) {}
18958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com    ~SkAutoTDeleteArray() { SkDELETE_ARRAY(fArray); }
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*      get() const { return fArray; }
19258b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com    void    free() { SkDELETE_ARRAY(fArray); fArray = NULL; }
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*      detach() { T* array = fArray; fArray = NULL; return array; }
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
195cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org    void reset(T array[]) {
196cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org        if (fArray != array) {
197cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org            SkDELETE_ARRAY(fArray);
198cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org            fArray = array;
199cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org        }
200cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org    }
201cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*  fArray;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Allocate an array of T elements, and free the array in the destructor
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T> class SkAutoTArray : SkNoncopyable {
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2106d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    SkAutoTArray() {
2116d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        fArray = NULL;
2126d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        SkDEBUGCODE(fCount = 0;)
2136d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    }
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Allocate count number of T elements
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
2166d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    explicit SkAutoTArray(int count) {
2176d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        SkASSERT(count >= 0);
2186d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        fArray = NULL;
2196d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        if (count) {
2201198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com            fArray = SkNEW_ARRAY(T, count);
2216d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        }
2226d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        SkDEBUGCODE(fCount = count;)
2236d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    }
2246d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com
2256d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    /** Reallocates given a new count. Reallocation occurs even if new count equals old count.
2266d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com     */
2276d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    void reset(int count) {
2281198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        SkDELETE_ARRAY(fArray);
2296d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        SkASSERT(count >= 0);
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fArray = NULL;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count) {
2321198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com            fArray = SkNEW_ARRAY(T, count);
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDEBUGCODE(fCount = count;)
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoTArray() {
2381198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        SkDELETE_ARRAY(fArray);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the array of T elements. Will be NULL if count == 0
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* get() const { return fArray; }
244fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the nth element in the array
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T&  operator[](int index) const {
2486d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com        SkASSERT((unsigned)index < (unsigned)fCount);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fArray[index];
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*  fArray;
2546d552ee5f56e76da6ba244df0f0df2234f2d8977bsalomon@google.com    SkDEBUGCODE(int fCount;)
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Wraps SkAutoTArray, with room for up to N elements preallocated
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
259adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.comtemplate <int N, typename T> class SkAutoSTArray : SkNoncopyable {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
261d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    /** Initialize with no objects */
262d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    SkAutoSTArray() {
263d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        fArray = NULL;
264d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        fCount = 0;
265d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    }
266d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Allocate count number of T elements
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
269adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    SkAutoSTArray(int count) {
270d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        fArray = NULL;
271d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        fCount = 0;
272d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        this->reset(count);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
274fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoSTArray() {
276d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        this->reset(0);
277d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    }
278d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
279d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    /** Destroys previous objects in the array and default constructs count number of objects */
280adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    void reset(int count) {
2811198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        T* start = fArray;
2821198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        T* iter = start + fCount;
2831198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        while (iter > start) {
2841198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com            (--iter)->~T();
2851198e740d58abba5edc749c14ed088688b3e76cascroggo@google.com        }
286d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
287d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        if (fCount != count) {
2884d3767373942c55be893d3bbbfe35e1975c2e1b4robertphillips@google.com            if (fCount > N) {
2894d3767373942c55be893d3bbbfe35e1975c2e1b4robertphillips@google.com                // 'fArray' was allocated last time so free it now
2904d3767373942c55be893d3bbbfe35e1975c2e1b4robertphillips@google.com                SkASSERT((T*) fStorage != fArray);
291d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com                sk_free(fArray);
292d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            }
293d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
294d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            if (count > N) {
295d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com                fArray = (T*) sk_malloc_throw(count * sizeof(T));
296d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            } else if (count > 0) {
297d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com                fArray = (T*) fStorage;
298d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            } else {
299d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com                fArray = NULL;
300d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            }
301d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
302d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            fCount = count;
303d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        }
304d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
305d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        iter = fArray;
306d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        T* stop = fArray + count;
307d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        while (iter < stop) {
308d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            SkNEW_PLACEMENT(iter++, T);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
311fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the number of T elements in the array
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
314adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    int count() const { return fCount; }
315fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the array of T elements. Will be NULL if count == 0
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* get() const { return fArray; }
319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the nth element in the array
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T&  operator[](int index) const {
323adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com        SkASSERT(index < fCount);
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fArray[index];
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
326fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
328adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    int     fCount;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*      fArray;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // since we come right after fArray, fStorage should be properly aligned
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    fStorage[N * sizeof(T)];
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
334b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org/** Manages an array of T elements, freeing the array in the destructor.
335b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org *  Does NOT call any constructors/destructors on T (T must be POD).
336b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org */
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtemplate <typename T> class SkAutoTMalloc : SkNoncopyable {
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
339b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */
340b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    explicit SkAutoTMalloc(T* ptr = NULL) {
341b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        fPtr = ptr;
342b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    }
343b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org
344b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    /** Allocates space for 'count' Ts. */
345b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    explicit SkAutoTMalloc(size_t count) {
34693fabf4847b4784ffabb8d81e722e14d88c92804Mike Klein        fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW);
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3483582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
3493582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    ~SkAutoTMalloc() {
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_free(fPtr);
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3523582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
353b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    /** Resize the memory area pointed to by the current ptr preserving contents. */
354b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    void realloc(size_t count) {
355b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        fPtr = reinterpret_cast<T*>(sk_realloc_throw(fPtr, count * sizeof(T)));
356b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    }
357b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org
358b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    /** Resize the memory area pointed to by the current ptr without preserving contents. */
359b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    void reset(size_t count) {
3603582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        sk_free(fPtr);
36193fabf4847b4784ffabb8d81e722e14d88c92804Mike Klein        fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW);
3623582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
3633582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* get() const { return fPtr; }
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3663582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    operator T*() {
3673582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr;
3683582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
3693582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
3703582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    operator const T*() const {
3713582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr;
3723582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
3733582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
3743582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    T& operator[](int index) {
3753582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr[index];
3763582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
3773582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
3783582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    const T& operator[](int index) const {
3793582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr[index];
3803582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
3813582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
382b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    /**
383b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org     *  Transfer ownership of the ptr to the caller, setting the internal
384b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org     *  pointer to NULL. Note that this differs from get(), which also returns
385b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org     *  the pointer, but it does not transfer ownership.
386b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org     */
387b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    T* detach() {
388b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        T* ptr = fPtr;
389b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        fPtr = NULL;
390b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org        return ptr;
391b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    }
392b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
394b5e34e22aa0e019e25f9f913f0e119a9a97e5562commit-bot@chromium.org    T* fPtr;
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
397ae326bb5ca55b7102e70a8a589adcb7cf78f37e7bungeman@google.comtemplate <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3997103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com    SkAutoSTMalloc() {
4007103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com        fPtr = NULL;
4017103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com    }
4027103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com
4033582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    SkAutoSTMalloc(size_t count) {
4047103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com        if (count > N) {
4057103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com            fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
4067103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com        } else if (count) {
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPtr = fTStorage;
4083582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        } else {
4097103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com            fPtr = NULL;
4103582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        }
4113582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
4123582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4133582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    ~SkAutoSTMalloc() {
4143582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        if (fPtr != fTStorage) {
4153582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            sk_free(fPtr);
4163582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        }
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4183582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4193582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    // doesn't preserve contents
4204e05fd25c88bea64a988ededfc810770095ed97creed@google.com    T* reset(size_t count) {
4213582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        if (fPtr != fTStorage) {
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_free(fPtr);
4233582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        }
4247103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com        if (count > N) {
4257103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com            fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
4267103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com        } else if (count) {
4273582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            fPtr = fTStorage;
4283582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        } else {
4297103344b64f3f0df88e76857c16edc8eedb58366bungeman@google.com            fPtr = NULL;
4303582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        }
4314e05fd25c88bea64a988ededfc810770095ed97creed@google.com        return fPtr;
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4333582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T* get() const { return fPtr; }
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4363582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    operator T*() {
4373582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr;
4383582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
4393582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4403582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    operator const T*() const {
4413582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr;
4423582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
4433582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4443582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    T& operator[](int index) {
4453582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr[index];
4463582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
4473582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4483582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    const T& operator[](int index) const {
4493582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com        return fPtr[index];
4503582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    }
4513582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    T*          fPtr;
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    union {
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        T           fTStorage[1];   // do NOT want to invoke T::T()
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com/**
46149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * Reserves memory that is aligned on double and pointer boundaries.
46249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * Hopefully this is sufficient for all practical purposes.
46349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com */
46449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtemplate <size_t N> class SkAlignedSStorage : SkNoncopyable {
46549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.compublic:
46649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    void* get() { return fData; }
46749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comprivate:
46849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    union {
46949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        void*   fPtr;
47049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        double  fDouble;
47149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        char    fData[N];
47249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    };
47349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com};
47449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com
47549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com/**
47649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * Reserves memory that is aligned on double and pointer boundaries.
47749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * Hopefully this is sufficient for all practical purposes. Otherwise,
47849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * we have to do some arcane trickery to determine alignment of non-POD
47949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * types. Lifetime of the memory is the lifetime of the object.
48049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com */
48149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtemplate <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {
48249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.compublic:
48349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
48449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Returns void* because this object does not initialize the
48549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * memory. Use placement new for types that require a cons.
48649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
48749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    void* get() { return fStorage.get(); }
48849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comprivate:
48949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    SkAlignedSStorage<sizeof(T)*N> fStorage;
49049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com};
49149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
493