1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2011 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkTArray_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkTArray_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../private/SkTLogic.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../private/SkTemplates.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <new>
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <utility>
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** When MEM_MOVE is true T will be bit copied when moved.
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    When MEM_MOVE is false, T will be copy constructed / destructed.
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    In all cases T will be default-initialized on allocation,
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    and its destructor will be called from this object's destructor.
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, bool MEM_MOVE = false> class SkTArray {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Creates an empty array with no initial storage
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray() { this->init(); }
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Creates an empty array that will preallocate space for reserveCount
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * elements.
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkTArray(int reserveCount) { this->init(0, reserveCount); }
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Copies one array to another. The new array will be heap allocated.
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkTArray(const SkTArray& that) {
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->init(that.fCount);
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(that.fItemArray);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkTArray(SkTArray&& that) {
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // TODO: If 'that' owns its memory why don't we just steal the pointer?
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->init(that.fCount);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        that.move(fMemArray);
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        that.fCount = 0;
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Creates a SkTArray by copying contents of a standard C array. The new
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * array will be heap allocated. Be careful not to use this constructor
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * when you really want the (void*, int) version.
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray(const T* array, int count) {
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->init(count);
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(array);
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray& operator=(const SkTArray& that) {
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (this == &that) {
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return *this;
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = 0;
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(that.count());
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = that.count();
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(that.fItemArray);
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray& operator=(SkTArray&& that) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (this == &that) {
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return *this;
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = 0;
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(that.count());
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = that.count();
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        that.move(fMemArray);
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        that.fCount = 0;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~SkTArray() {
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fOwnMemory) {
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_free(fMemArray);
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Resets to count() == 0 and resets any reserve count.
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset() {
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->pop_back_n(fCount);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fReserved = false;
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Resets to count() = n newly constructed T objects and resets any reserve count.
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset(int n) {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Set fCount to 0 before calling checkRealloc so that no elements are moved.
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = 0;
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(n);
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = n;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (fItemArray + i) T;
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fReserved = false;
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Resets to a copy of a C array and resets any reserve count.
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset(const T* array, int count) {
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = 0;
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(count);
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = count;
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(array);
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fReserved = false;
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Ensures there is enough reserved space for n additional elements. The is guaranteed at least
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * until the array size grows above n and subsequently shrinks below n, any version of reset()
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * is called, or reserve() is called again.
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reserve(int n) {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (n > 0) {
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->checkRealloc(n);
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fReserved = fOwnMemory;
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fReserved = false;
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void removeShuffle(int n) {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n < fCount);
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int newCount = fCount - 1;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = newCount;
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fItemArray[n].~T();
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (n != newCount) {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->move(n, newCount);
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Number of elements in the array.
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count() const { return fCount; }
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Is the array empty.
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool empty() const { return !fCount; }
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Adds 1 new default-initialized T value and returns it by reference. Note
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * the reference only remains valid until the next call that adds or removes
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * elements.
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& push_back() {
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newT = this->push_back_raw(1);
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *new (newT) T;
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Version of above that uses a copy constructor to initialize the new item
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& push_back(const T& t) {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newT = this->push_back_raw(1);
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *new (newT) T(t);
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Version of above that uses a move constructor to initialize the new item
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& push_back(T&& t) {
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newT = this->push_back_raw(1);
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *new (newT) T(std::move(t));
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Construct a new T at the back of this array.
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template<class... Args> T& emplace_back(Args&&... args) {
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newT = this->push_back_raw(1);
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *new (newT) T(std::forward<Args>(args)...);
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Allocates n more default-initialized T values, and returns the address of
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * the start of that new range. Note: this address is only valid until the
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * next API call made on the array that might add or remove elements.
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* push_back_n(int n) {
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newTs = this->push_back_raw(n);
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (static_cast<char*>(newTs) + i * sizeof(T)) T;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return static_cast<T*>(newTs);
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Version of above that uses a copy constructor to initialize all n items
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to the same T.
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* push_back_n(int n, const T& t) {
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newTs = this->push_back_raw(n);
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (static_cast<char*>(newTs) + i * sizeof(T)) T(t);
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return static_cast<T*>(newTs);
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Version of above that uses a copy constructor to initialize the n items
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to separate T values.
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* push_back_n(int n, const T t[]) {
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(n);
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (fItemArray + fCount + i) T(t[i]);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount += n;
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray + fCount - n;
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Version of above that uses the move constructor to set n items.
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* move_back_n(int n, T* t) {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(n);
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (fItemArray + fCount + i) T(std::move(t[i]));
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount += n;
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray + fCount - n;
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Removes the last element. Not safe to call when count() == 0.
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void pop_back() {
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fCount > 0);
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --fCount;
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fItemArray[fCount].~T();
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(0);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Removes the last n elements. Not safe to call when count() < n.
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void pop_back_n(int n) {
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(n >= 0);
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fCount >= n);
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount -= n;
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[fCount + i].~T();
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(0);
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Pushes or pops from the back to resize. Pushes will be default
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * initialized.
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void resize_back(int newCount) {
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(newCount >= 0);
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (newCount > fCount) {
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->push_back_n(newCount - fCount);
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else if (newCount < fCount) {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->pop_back_n(fCount - newCount);
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Swaps the contents of this array with that array. Does a pointer swap if possible,
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        otherwise copies the T values. */
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void swap(SkTArray* that) {
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (this == that) {
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fOwnMemory && that->fOwnMemory) {
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkTSwap(fItemArray, that->fItemArray);
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkTSwap(fCount, that->fCount);
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkTSwap(fAllocCount, that->fAllocCount);
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This could be more optimal...
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkTArray copy(std::move(*that));
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *that = std::move(*this);
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *this = std::move(copy);
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* begin() {
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray;
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T* begin() const {
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray;
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* end() {
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray ? fItemArray + fCount : nullptr;
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T* end() const {
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray ? fItemArray + fCount : nullptr;
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot   /**
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Get the i^th element.
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& operator[] (int i) {
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i < fCount);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i >= 0);
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray[i];
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T& operator[] (int i) const {
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i < fCount);
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i >= 0);
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray[i];
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * equivalent to operator[](0)
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * equivalent to operator[](count() - 1)
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * equivalent to operator[](count()-1-i)
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& fromBack(int i) {
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i >= 0);
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i < fCount);
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray[fCount - i - 1];
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const T& fromBack(int i) const {
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i >= 0);
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(i < fCount);
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fItemArray[fCount - i - 1];
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool operator==(const SkTArray<T, MEM_MOVE>& right) const {
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int leftCount = this->count();
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (leftCount != right.count()) {
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < leftCount; ++index) {
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fItemArray[index] != right.fItemArray[index]) {
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool operator!=(const SkTArray<T, MEM_MOVE>& right) const {
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return !(*this == right);
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    inline int allocCntForTest() const;
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Creates an empty array that will use the passed storage block until it
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * is insufficiently large to hold the entire array.
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <int N>
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray(SkAlignedSTStorage<N,T>* storage) {
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->initWithPreallocatedStorage(0, storage->get(), N);
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Copy another array, using preallocated storage if preAllocCount >=
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * array.count(). Otherwise storage will only be used when array shrinks
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to fit.
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <int N>
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->initWithPreallocatedStorage(array.fCount, storage->get(), N);
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(array.fItemArray);
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Move another array, using preallocated storage if preAllocCount >=
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * array.count(). Otherwise storage will only be used when array shrinks
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to fit.
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <int N>
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray(SkTArray&& array, SkAlignedSTStorage<N,T>* storage) {
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->initWithPreallocatedStorage(array.fCount, storage->get(), N);
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array.move(fMemArray);
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array.fCount = 0;
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Copy a C array, using preallocated storage if preAllocCount >=
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * count. Otherwise storage will only be used when array shrinks
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to fit.
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <int N>
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->initWithPreallocatedStorage(count, storage->get(), N);
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->copy(array);
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void init(int count = 0, int reserveCount = 0) {
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(count >= 0);
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(reserveCount >= 0);
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = count;
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!count && !reserveCount) {
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAllocCount = 0;
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fMemArray = nullptr;
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fOwnMemory = true;
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fReserved = false;
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAllocCount = SkTMax(count, SkTMax(kMinHeapAllocCount, reserveCount));
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fOwnMemory = true;
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fReserved = reserveCount > 0;
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void initWithPreallocatedStorage(int count, void* preallocStorage, int preallocCount) {
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(count >= 0);
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(preallocCount > 0);
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(preallocStorage);
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount = count;
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMemArray = nullptr;
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fReserved = false;
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (count > preallocCount) {
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAllocCount = SkTMax(count, kMinHeapAllocCount);
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fOwnMemory = true;
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAllocCount = preallocCount;
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fMemArray = preallocStorage;
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fOwnMemory = false;
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** In the following move and copy methods, 'dst' is assumed to be uninitialized raw storage.
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  In the following move methods, 'src' is destroyed leaving behind uninitialized raw storage.
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void copy(const T* src) {
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Some types may be trivially copyable, in which case we *could* use memcopy; but
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // MEM_MOVE == true implies that the type is trivially movable, and not necessarily
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // trivially copyable (think sk_sp<>).  So short of adding another template arg, we
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // must be conservative and use copy construction.
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (fItemArray + i) T(src[i]);
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <bool E = MEM_MOVE> SK_WHEN(E, void) move(int dst, int src) {
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        memcpy(&fItemArray[dst], &fItemArray[src], sizeof(T));
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <bool E = MEM_MOVE> SK_WHEN(E, void) move(void* dst) {
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_careful_memcpy(dst, fMemArray, fCount * sizeof(T));
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <bool E = MEM_MOVE> SK_WHEN(!E, void) move(int dst, int src) {
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        new (&fItemArray[dst]) T(std::move(fItemArray[src]));
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fItemArray[src].~T();
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <bool E = MEM_MOVE> SK_WHEN(!E, void) move(void* dst) {
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fCount; ++i) {
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (static_cast<char*>(dst) + sizeof(T) * i) T(std::move(fItemArray[i]));
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fItemArray[i].~T();
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMinHeapAllocCount = 8;
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Helper function that makes space for n objects, adjusts the count, but does not initialize
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the new objects.
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void* push_back_raw(int n) {
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->checkRealloc(n);
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* ptr = fItemArray + fCount;
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCount += n;
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return ptr;
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void checkRealloc(int delta) {
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fCount >= 0);
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fAllocCount >= 0);
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(-delta <= fCount);
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int newCount = fCount + delta;
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // We allow fAllocCount to be in the range [newCount, 3*newCount]. We also never shrink
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // when we're currently using preallocated memory, would allocate less than
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // kMinHeapAllocCount, or a reserve count was specified that has yet to be exceeded.
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool mustGrow = newCount > fAllocCount;
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool shouldShrink = fAllocCount > 3 * newCount && fOwnMemory && !fReserved;
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!mustGrow && !shouldShrink) {
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Whether we're growing or shrinking, we leave at least 50% extra space for future growth.
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int newAllocCount = newCount + ((newCount + 1) >> 1);
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Align the new allocation count to kMinHeapAllocCount.
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static_assert(SkIsPow2(kMinHeapAllocCount), "min alloc count not power of two.");
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        newAllocCount = (newAllocCount + (kMinHeapAllocCount - 1)) & ~(kMinHeapAllocCount - 1);
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // At small sizes the old and new alloc count can both be kMinHeapAllocCount.
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (newAllocCount == fAllocCount) {
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fAllocCount = newAllocCount;
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* newMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->move(newMemArray);
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fOwnMemory) {
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_free(fMemArray);
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMemArray = newMemArray;
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fOwnMemory = true;
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fReserved = false;
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    union {
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        T*       fItemArray;
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void*    fMemArray;
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fCount;
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fAllocCount;
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fOwnMemory : 1;
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fReserved : 1;
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename T, bool MEM_MOVE> constexpr int SkTArray<T, MEM_MOVE>::kMinHeapAllocCount;
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Subclass of SkTArray that contains a preallocated memory block for the array.
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <int N, typename T, bool MEM_MOVE= false>
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkSTArray : public SkTArray<T, MEM_MOVE> {
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef SkTArray<T, MEM_MOVE> INHERITED;
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray() : INHERITED(&fStorage) {
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray(const SkSTArray& array)
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(array, &fStorage) {
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray(SkSTArray&& array)
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(std::move(array), &fStorage) {
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkSTArray(const INHERITED& array)
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(array, &fStorage) {
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkSTArray(INHERITED&& array)
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(std::move(array), &fStorage) {
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit SkSTArray(int reserveCount)
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(reserveCount) {
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray(const T* array, int count)
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(array, count, &fStorage) {
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray& operator=(const SkSTArray& array) {
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        INHERITED::operator=(array);
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray& operator=(SkSTArray&& array) {
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        INHERITED::operator=(std::move(array));
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray& operator=(const INHERITED& array) {
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        INHERITED::operator=(array);
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray& operator=(INHERITED&& array) {
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        INHERITED::operator=(std::move(array));
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAlignedSTStorage<N,T> fStorage;
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
624