1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com#ifndef SkTArray_DEFINED
949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com#define SkTArray_DEFINED
10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
11918090c819109585f8fd2295039385a60eb0b572bungeman#include "../private/SkTLogic.h"
12f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "../private/SkTemplates.h"
1349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com#include "SkTypes.h"
14f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman
15f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include <new>
16221524de3be1fc343ad328c5e99562f32b5cad9cbungeman#include <utility>
17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
18a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com/** When MEM_COPY is true T will be bit copied when moved.
19a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com    When MEM_COPY is false, T will be copy constructed / destructed.
20d58a856418ba3b3ecdc5e94629c911ec0034dfb1bungeman@google.com    In all cases T will be default-initialized on allocation,
21a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com    and its destructor will be called from this object's destructor.
22a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com*/
2385dc359f749c349bbd8e0ba56825b9457f654237bungemantemplate <typename T, bool MEM_COPY = false> class SkTArray {
24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.compublic:
2549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
2649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Creates an empty array with no initial storage
2749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
2849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    SkTArray() {
29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCount = 0;
3049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        fReserveCount = gMIN_ALLOC_COUNT;
31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAllocCount = 0;
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fMemArray = NULL;
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fPreAllocMemArray = NULL;
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
37fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * Creates an empty array that will preallocate space for reserveCount
3849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * elements.
3949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
4049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    explicit SkTArray(int reserveCount) {
4192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(NULL, 0, NULL, reserveCount);
42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
4549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Copies one array to another. The new array will be heap allocated.
4649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
4749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    explicit SkTArray(const SkTArray& array) {
4892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(array.fItemArray, array.fCount, NULL, 0);
49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
5149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
52fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * Creates a SkTArray by copying contents of a standard C array. The new
5349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * array will be heap allocated. Be careful not to use this constructor
5449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * when you really want the (void*, int) version.
5549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
5649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    SkTArray(const T* array, int count) {
5792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(array, count, NULL, 0);
58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
6049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
6149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * assign copy of array to this
6249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
6349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    SkTArray& operator =(const SkTArray& array) {
641c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        for (int i = 0; i < fCount; ++i) {
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fItemArray[i].~T();
66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCount = 0;
68d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        this->checkRealloc((int)array.count());
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCount = array.count();
70918090c819109585f8fd2295039385a60eb0b572bungeman        this->copy(static_cast<const T*>(array.fMemArray));
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return *this;
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
74383ff1047f64192a8d7231a9e20d90126f85997dbsalomon    ~SkTArray() {
751c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        for (int i = 0; i < fCount; ++i) {
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fItemArray[i].~T();
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fMemArray != fPreAllocMemArray) {
7949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com            sk_free(fMemArray);
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
8449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Resets to count() == 0
8549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
86d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    void reset() { this->pop_back_n(fCount); }
87d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com
8849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
89b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org     * Resets to count() = n newly constructed T objects.
90b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org     */
91b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org    void reset(int n) {
92b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        SkASSERT(n >= 0);
93b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        for (int i = 0; i < fCount; ++i) {
94b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org            fItemArray[i].~T();
95b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        }
96b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        // set fCount to 0 before calling checkRealloc so that no copy cons. are called.
97b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        fCount = 0;
98b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        this->checkRealloc(n);
99b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        fCount = n;
100b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        for (int i = 0; i < fCount; ++i) {
101385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new (fItemArray + i) T;
102b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        }
103b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org    }
104b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org
105b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org    /**
106054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com     * Resets to a copy of a C array.
107054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com     */
108054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com    void reset(const T* array, int count) {
109054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        for (int i = 0; i < fCount; ++i) {
110054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com            fItemArray[i].~T();
111054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        }
112054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        int delta = count - fCount;
113054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        this->checkRealloc(delta);
114054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        fCount = count;
115918090c819109585f8fd2295039385a60eb0b572bungeman        this->copy(array);
11695ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com    }
11795ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com
11895ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com    void removeShuffle(int n) {
11995ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com        SkASSERT(n < fCount);
12095ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com        int newCount = fCount - 1;
12195ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com        fCount = newCount;
12295ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com        fItemArray[n].~T();
12395ebd17cf4f66952862289882ee5ac00da31cb8abungeman@google.com        if (n != newCount) {
124918090c819109585f8fd2295039385a60eb0b572bungeman            this->move(n, newCount);
125054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com        }
126054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com    }
127054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com
128054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com    /**
12949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Number of elements in the array.
13049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
1311c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    int count() const { return fCount; }
132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
13349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
13449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Is the array empty.
13549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    bool empty() const { return !fCount; }
137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
138a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com    /**
139d58a856418ba3b3ecdc5e94629c911ec0034dfb1bungeman@google.com     * Adds 1 new default-initialized T value and returns it by reference. Note
140a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com     * the reference only remains valid until the next call that adds or removes
141a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com     * elements.
142a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com     */
143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    T& push_back() {
144d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
145385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        new (newT) T;
146d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        return *newT;
147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
149a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com    /**
1504fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     * Version of above that uses a copy constructor to initialize the new item
1514fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     */
1524fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    T& push_back(const T& t) {
153d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
154385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        new (newT) T(t);
155d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        return *newT;
1564fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    }
1574fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com
1584fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    /**
159f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary     *  Construct a new T at the back of this array.
160f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary     */
161f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary    template<class... Args> T& emplace_back(Args&&... args) {
162f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary        T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
163221524de3be1fc343ad328c5e99562f32b5cad9cbungeman        return *new (newT) T(std::forward<Args>(args)...);
164f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary    }
165f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary
166f12a1673f024d30d30f06b9f88b5cc072b8a2d1ehalcanary    /**
167d58a856418ba3b3ecdc5e94629c911ec0034dfb1bungeman@google.com     * Allocates n more default-initialized T values, and returns the address of
168d58a856418ba3b3ecdc5e94629c911ec0034dfb1bungeman@google.com     * the start of that new range. Note: this address is only valid until the
169d58a856418ba3b3ecdc5e94629c911ec0034dfb1bungeman@google.com     * next API call made on the array that might add or remove elements.
170a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com     */
171a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com    T* push_back_n(int n) {
17249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(n >= 0);
173d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
1741c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        for (int i = 0; i < n; ++i) {
175385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new (newTs + i) T;
176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
177d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        return newTs;
178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
18049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
1814fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     * Version of above that uses a copy constructor to initialize all n items
1824fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     * to the same T.
1834fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     */
1844fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    T* push_back_n(int n, const T& t) {
1854fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        SkASSERT(n >= 0);
186d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
1874fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        for (int i = 0; i < n; ++i) {
188385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new (newTs[i]) T(t);
1894fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        }
190d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        return newTs;
1914fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    }
1924fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com
1934fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    /**
1944fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     * Version of above that uses a copy constructor to initialize the n items
1954fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     * to separate T values.
1964fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com     */
1974fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    T* push_back_n(int n, const T t[]) {
1984fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        SkASSERT(n >= 0);
199b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        this->checkRealloc(n);
2004fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        for (int i = 0; i < n; ++i) {
201385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new (fItemArray + fCount + i) T(t[i]);
2024fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        }
2034fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        fCount += n;
2044fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com        return fItemArray + fCount - n;
2054fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    }
2064fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com
2074fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com    /**
20849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Removes the last element. Not safe to call when count() == 0.
20949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
210ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    void pop_back() {
21149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(fCount > 0);
212ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        --fCount;
213ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fItemArray[fCount].~T();
214b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        this->checkRealloc(0);
215ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
216ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
21749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
21849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Removes the last n elements. Not safe to call when count() < n.
21949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
2201c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    void pop_back_n(int n) {
22149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(n >= 0);
22249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(fCount >= n);
223ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCount -= n;
2241c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        for (int i = 0; i < n; ++i) {
225d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com            fItemArray[fCount + i].~T();
226ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
227b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org        this->checkRealloc(0);
228ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
229ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
23049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
23149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Pushes or pops from the back to resize. Pushes will be default
23249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * initialized.
23349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
2341c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    void resize_back(int newCount) {
23549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(newCount >= 0);
2361c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
237ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (newCount > fCount) {
238b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org            this->push_back_n(newCount - fCount);
239ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        } else if (newCount < fCount) {
240b4a8d97b4c68896da363e7f365354ab8ddbb7fc1commit-bot@chromium.org            this->pop_back_n(fCount - newCount);
241ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
242ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
243ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
24423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    /** Swaps the contents of this array with that array. Does a pointer swap if possible,
24523e619cf462b2a8a500f3ca750e099f79601f508bsalomon        otherwise copies the T values. */
24623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    void swap(SkTArray* that) {
2473632f8473a7842b6f1351694d9b4071a66529224bsalomon        if (this == that) {
2483632f8473a7842b6f1351694d9b4071a66529224bsalomon            return;
2493632f8473a7842b6f1351694d9b4071a66529224bsalomon        }
25023e619cf462b2a8a500f3ca750e099f79601f508bsalomon        if (this->fPreAllocMemArray != this->fItemArray &&
25123e619cf462b2a8a500f3ca750e099f79601f508bsalomon            that->fPreAllocMemArray != that->fItemArray) {
25223e619cf462b2a8a500f3ca750e099f79601f508bsalomon            // If neither is using a preallocated array then just swap.
25323e619cf462b2a8a500f3ca750e099f79601f508bsalomon            SkTSwap(fItemArray, that->fItemArray);
25423e619cf462b2a8a500f3ca750e099f79601f508bsalomon            SkTSwap(fCount, that->fCount);
25523e619cf462b2a8a500f3ca750e099f79601f508bsalomon            SkTSwap(fAllocCount, that->fAllocCount);
25623e619cf462b2a8a500f3ca750e099f79601f508bsalomon        } else {
25723e619cf462b2a8a500f3ca750e099f79601f508bsalomon            // This could be more optimal...
25823e619cf462b2a8a500f3ca750e099f79601f508bsalomon            SkTArray copy(*that);
25923e619cf462b2a8a500f3ca750e099f79601f508bsalomon            *that = *this;
26023e619cf462b2a8a500f3ca750e099f79601f508bsalomon            *this = copy;
26123e619cf462b2a8a500f3ca750e099f79601f508bsalomon        }
26223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    }
26323e619cf462b2a8a500f3ca750e099f79601f508bsalomon
2649b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    T* begin() {
2659b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        return fItemArray;
2669b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    }
2679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    const T* begin() const {
2689b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        return fItemArray;
2699b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    }
2709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    T* end() {
2719b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        return fItemArray ? fItemArray + fCount : NULL;
2729b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    }
2739b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    const T* end() const {
274567ff2f6143ecb993dbedede402a43feb71c420atfarina        return fItemArray ? fItemArray + fCount : NULL;
2759b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    }
2769b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2779b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com   /**
27849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * Get the i^th element.
27949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
2801c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    T& operator[] (int i) {
28149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i < fCount);
28249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i >= 0);
283ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return fItemArray[i];
284ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
285ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2861c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    const T& operator[] (int i) const {
28749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i < fCount);
28849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i >= 0);
289ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return fItemArray[i];
290ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
291ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
29249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
29349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * equivalent to operator[](0)
29449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
29549313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
29749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
298ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
29949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
30049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * equivalent to operator[](count() - 1)
30149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
30249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
303ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
30449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
305ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
30649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    /**
30749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     * equivalent to operator[](count()-1-i)
30849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com     */
3091c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    T& fromBack(int i) {
31049313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i >= 0);
31149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i < fCount);
312ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return fItemArray[fCount - i - 1];
313ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
314ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3151c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    const T& fromBack(int i) const {
31649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i >= 0);
31749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(i < fCount);
318ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return fItemArray[fCount - i - 1];
319ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
320ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
321ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    bool operator==(const SkTArray<T, MEM_COPY>& right) const {
322ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        int leftCount = this->count();
323ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        if (leftCount != right.count()) {
324ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            return false;
325ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
326ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        for (int index = 0; index < leftCount; ++index) {
327ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            if (fItemArray[index] != right.fItemArray[index]) {
328ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org                return false;
329ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            }
330ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
331ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        return true;
332ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
333ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
334ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    bool operator!=(const SkTArray<T, MEM_COPY>& right) const {
335ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        return !(*this == right);
336ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
337ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
33892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.comprotected:
33992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    /**
34092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * Creates an empty array that will use the passed storage block until it
34192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * is insufficiently large to hold the entire array.
34292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     */
34392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    template <int N>
34492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkTArray(SkAlignedSTStorage<N,T>* storage) {
34592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(NULL, 0, storage->get(), N);
34692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
34792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
34892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    /**
34992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * Copy another array, using preallocated storage if preAllocCount >=
35092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * array.count(). Otherwise storage will only be used when array shrinks
35192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * to fit.
35292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     */
35392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    template <int N>
35492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {
35592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(array.fItemArray, array.fCount, storage->get(), N);
35692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
35792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
35892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    /**
35992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * Copy a C array, using preallocated storage if preAllocCount >=
36092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * count. Otherwise storage will only be used when array shrinks
36192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     * to fit.
36292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com     */
36392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    template <int N>
36492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {
36592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        this->init(array, count, storage->get(), N);
36692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
36792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
36892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    void init(const T* array, int count,
36923e619cf462b2a8a500f3ca750e099f79601f508bsalomon              void* preAllocStorage, int preAllocOrReserveCount) {
370d80a509eb773cdca6c7a9d3af4ac44a6dd24c567junov@chromium.org        SkASSERT(count >= 0);
371d80a509eb773cdca6c7a9d3af4ac44a6dd24c567junov@chromium.org        SkASSERT(preAllocOrReserveCount >= 0);
37292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        fCount              = count;
37392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        fReserveCount       = (preAllocOrReserveCount > 0) ?
37492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com                                    preAllocOrReserveCount :
37592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com                                    gMIN_ALLOC_COUNT;
37692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        fPreAllocMemArray   = preAllocStorage;
37792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        if (fReserveCount >= fCount &&
37849f085dddff10473b6ebf832a974288300224e60bsalomon            preAllocStorage) {
37992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com            fAllocCount = fReserveCount;
38092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com            fMemArray = preAllocStorage;
38192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        } else {
382d80a509eb773cdca6c7a9d3af4ac44a6dd24c567junov@chromium.org            fAllocCount = SkMax32(fCount, fReserveCount);
383d80a509eb773cdca6c7a9d3af4ac44a6dd24c567junov@chromium.org            fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
38492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        }
38592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
386918090c819109585f8fd2295039385a60eb0b572bungeman        this->copy(array);
38792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
38892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
389ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comprivate:
390918090c819109585f8fd2295039385a60eb0b572bungeman    /** In the following move and copy methods, 'dst' is assumed to be uninitialized raw storage.
391918090c819109585f8fd2295039385a60eb0b572bungeman     *  In the following move methods, 'src' is destroyed leaving behind uninitialized raw storage.
392918090c819109585f8fd2295039385a60eb0b572bungeman     */
393918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(E, void) copy(const T* src) {
394918090c819109585f8fd2295039385a60eb0b572bungeman        sk_careful_memcpy(fMemArray, src, fCount * sizeof(T));
395918090c819109585f8fd2295039385a60eb0b572bungeman    }
396918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(E, void) move(int dst, int src) {
397918090c819109585f8fd2295039385a60eb0b572bungeman        memcpy(&fItemArray[dst], &fItemArray[src], sizeof(T));
398918090c819109585f8fd2295039385a60eb0b572bungeman    }
399918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(E, void) move(char* dst) {
400918090c819109585f8fd2295039385a60eb0b572bungeman        sk_careful_memcpy(dst, fMemArray, fCount * sizeof(T));
401918090c819109585f8fd2295039385a60eb0b572bungeman    }
402918090c819109585f8fd2295039385a60eb0b572bungeman
403918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(!E, void) copy(const T* src) {
404918090c819109585f8fd2295039385a60eb0b572bungeman        for (int i = 0; i < fCount; ++i) {
405918090c819109585f8fd2295039385a60eb0b572bungeman            new (fItemArray + i) T(src[i]);
406918090c819109585f8fd2295039385a60eb0b572bungeman        }
407918090c819109585f8fd2295039385a60eb0b572bungeman    }
408918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(!E, void) move(int dst, int src) {
409918090c819109585f8fd2295039385a60eb0b572bungeman        new (&fItemArray[dst]) T(std::move(fItemArray[src]));
410918090c819109585f8fd2295039385a60eb0b572bungeman        fItemArray[src].~T();
411918090c819109585f8fd2295039385a60eb0b572bungeman    }
412918090c819109585f8fd2295039385a60eb0b572bungeman    template <bool E = MEM_COPY> SK_WHEN(!E, void) move(char* dst) {
413918090c819109585f8fd2295039385a60eb0b572bungeman        for (int i = 0; i < fCount; ++i) {
414918090c819109585f8fd2295039385a60eb0b572bungeman            new (dst + sizeof(T) * i) T(std::move(fItemArray[i]));
415918090c819109585f8fd2295039385a60eb0b572bungeman            fItemArray[i].~T();
416918090c819109585f8fd2295039385a60eb0b572bungeman        }
417918090c819109585f8fd2295039385a60eb0b572bungeman    }
418ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
41949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com    static const int gMIN_ALLOC_COUNT = 8;
4201c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
421d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    // Helper function that makes space for n objects, adjusts the count, but does not initialize
422d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    // the new objects.
423d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    void* push_back_raw(int n) {
424d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        this->checkRealloc(n);
425d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        void* ptr = fItemArray + fCount;
426d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        fCount += n;
427d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com        return ptr;
428d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com    }
429d51041469a9a45562d88e9ff137c6726562e8c40bsalomon@google.com
4301c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    inline void checkRealloc(int delta) {
43149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(fCount >= 0);
43249313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(fAllocCount >= 0);
4331c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
43449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com        SkASSERT(-delta <= fCount);
435ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
4361c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        int newCount = fCount + delta;
437a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com        int newAllocCount = fAllocCount;
438ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
439137209f9f4b6ee08ca59a135909185cb0caf6d91bsalomon@google.com        if (newCount > fAllocCount || newCount < (fAllocCount / 3)) {
440137209f9f4b6ee08ca59a135909185cb0caf6d91bsalomon@google.com            // whether we're growing or shrinking, we leave at least 50% extra space for future
441137209f9f4b6ee08ca59a135909185cb0caf6d91bsalomon@google.com            // growth (clamped to the reserve count).
442137209f9f4b6ee08ca59a135909185cb0caf6d91bsalomon@google.com            newAllocCount = SkMax32(newCount + ((newCount + 1) >> 1), fReserveCount);
443ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
444a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com        if (newAllocCount != fAllocCount) {
445ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
446a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com            fAllocCount = newAllocCount;
447a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com            char* newMemArray;
448ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
44949f085dddff10473b6ebf832a974288300224e60bsalomon            if (fAllocCount == fReserveCount && fPreAllocMemArray) {
450a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com                newMemArray = (char*) fPreAllocMemArray;
451ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            } else {
452a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com                newMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T));
453ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            }
454ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
455918090c819109585f8fd2295039385a60eb0b572bungeman            this->move(newMemArray);
456ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
457ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            if (fMemArray != fPreAllocMemArray) {
45849313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com                sk_free(fMemArray);
459ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            }
460a12cc7fda00236549961d7b8e2d708cfe3cfa4e6bungeman@google.com            fMemArray = newMemArray;
461ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
462ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
463ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
46423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    int     fReserveCount;
46523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    int     fCount;
46623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    int     fAllocCount;
46723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    void*   fPreAllocMemArray;
468ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    union {
469ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        T*       fItemArray;
470ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        void*    fMemArray;
471ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    };
472ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com};
473ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
47492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com/**
47592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com * Subclass of SkTArray that contains a preallocated memory block for the array.
47692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com */
477f47dd74da3c7454af46aa0abe052d3fc6f02b9b2bsalomon@google.comtemplate <int N, typename T, bool MEM_COPY = false>
478f47dd74da3c7454af46aa0abe052d3fc6f02b9b2bsalomon@google.comclass SkSTArray : public SkTArray<T, MEM_COPY> {
47992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.comprivate:
480f47dd74da3c7454af46aa0abe052d3fc6f02b9b2bsalomon@google.com    typedef SkTArray<T, MEM_COPY> INHERITED;
48192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
48292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.compublic:
48392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkSTArray() : INHERITED(&fStorage) {
48492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
48592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
48692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkSTArray(const SkSTArray& array)
48792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        : INHERITED(array, &fStorage) {
48892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
48992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
49092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    explicit SkSTArray(const INHERITED& array)
49192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        : INHERITED(array, &fStorage) {
49292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
49392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
4943390b9ac9ad69a6e772c2b957d75d19611239025commit-bot@chromium.org    explicit SkSTArray(int reserveCount)
4953390b9ac9ad69a6e772c2b957d75d19611239025commit-bot@chromium.org        : INHERITED(reserveCount) {
4963390b9ac9ad69a6e772c2b957d75d19611239025commit-bot@chromium.org    }
4973390b9ac9ad69a6e772c2b957d75d19611239025commit-bot@chromium.org
49892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkSTArray(const T* array, int count)
49992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        : INHERITED(array, count, &fStorage) {
50092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
50192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
50292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkSTArray& operator= (const SkSTArray& array) {
50392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        return *this = *(const INHERITED*)&array;
50492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
50592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
50692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkSTArray& operator= (const INHERITED& array) {
50792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        INHERITED::operator=(array);
50892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com        return *this;
50992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    }
51092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
51192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.comprivate:
51292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com    SkAlignedSTStorage<N,T> fStorage;
51392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com};
51492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com
515ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
516