1d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project
2d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
3d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public
4d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and
5d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// may be copied, distributed, and modified under those terms.
6d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
7d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// This program is distributed in the hope that it will be useful,
8d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of
9d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// GNU General Public License for more details.
11d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
12d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#ifndef ANDROID_BASE_CONTAINERS_POD_VECTOR_H
13d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#define ANDROID_BASE_CONTAINERS_POD_VECTOR_H
14d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
15d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include <android/base/Limits.h>
16d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include <android/base/Log.h>
17d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
18d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include <stddef.h>
19d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include <stdint.h>
20d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
21d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnernamespace android {
22d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnernamespace base {
23d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
24d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// A PodVector is a templated vector-like type that is used to store
25d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// POD-struct compatible items only. This allows the implementation to
26d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// use ::memmove() to move items, and also malloc_usable_size() to
27d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// determine the best capacity.
28d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
29d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// std::vector<> is capable of doing this in theory, using horrible
30d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// templating tricks that make error messages very difficult to
31d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// understand.
32d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
33d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// Note that a PodVector can be used to store items that contain pointers,
34d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// as long as these do not point to items in the same container.
35d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
36d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// The PodVector provides methods that also follow the std::vector<>
37d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// conventions, i.e. push_back() is an alias for append().
38d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
39d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
40d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// PodVectorBase is a base, non-templated, implementation class that all
41d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// PodVector instances derive from. This is used to reduce template
42d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// specialization. Do not use directly, i..e it's an implementation detail.
43d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnerclass PodVectorBase {
44d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnerprotected:
45d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    PodVectorBase() : mBegin(NULL), mEnd(NULL), mLimit(NULL) {}
46d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    explicit PodVectorBase(const PodVectorBase& other);
47d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    PodVectorBase& operator=(const PodVectorBase& other);
48d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    ~PodVectorBase();
49d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
50d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    bool empty() const { return mEnd == mBegin; }
51d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
52d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    size_t byteSize() const { return mEnd - mBegin; }
53d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
54d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    size_t byteCapacity() const { return mLimit - mBegin; }
55d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
56d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void* begin() { return mBegin; }
57d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const void* begin() const { return mBegin; }
58d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void* end() { return mEnd; }
59d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const void* end() const { return mEnd; }
60d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
61d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void* itemAt(size_t pos, size_t itemSize) {
62d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        const size_t kMaxCapacity = SIZE_MAX / itemSize;
63d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        DCHECK(pos <= kMaxCapacity);
64d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return mBegin + pos * itemSize;
65d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
66d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
67d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const void* itemAt(size_t pos, size_t itemSize) const {
68d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        const size_t kMaxCapacity = SIZE_MAX / itemSize;
69d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        DCHECK(pos <= kMaxCapacity);
70d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return mBegin + pos * itemSize;
71d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
72d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
73d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void assignFrom(const PodVectorBase& other);
74d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
75d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    inline size_t itemCount(size_t itemSize) const {
76d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        DCHECK(itemSize > 0) << "Item size cannot be 0!";
77d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return byteSize() / itemSize;
78d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
79d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
80d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    inline size_t itemCapacity(size_t itemSize) const {
81d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        DCHECK(itemSize > 0) << "Item size cannot be 0!";
82d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return byteCapacity() / itemSize;
83d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
84d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
85d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    inline size_t maxItemCapacity(size_t itemSize) const {
86d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        DCHECK(itemSize > 0) << "Item size cannot be 0!";
87d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return SIZE_MAX / itemSize;
88d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
89d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
90d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void resize(size_t newSize, size_t itemSize);
91d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void reserve(size_t newSize, size_t itemSize);
92d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
93d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void removeAt(size_t index, size_t itemSize);
94d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void* insertAt(size_t index, size_t itemSize);
95d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void swapAll(PodVectorBase* other);
96d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
97d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    char* mBegin;
98d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    char* mEnd;
99d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    char* mLimit;
100d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
101d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnerprivate:
102d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void initFrom(const void* from, size_t fromLen);
103d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner};
104d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
105d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
106d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// A PodVector<T> holds a vector (dynamically resizable array) or items
107d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// that must be POD-struct compatible (i.e. they cannot have constructors,
108d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// destructors, or virtual members). This allows the implementation to be
109d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// small, fast and efficient, memory-wise.
110d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
111d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// If you want to implement a vector of C++ objects, consider using
112d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// std::vector<> instead, but keep in mind that this implies a non-trivial
113d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner// cost when appending, inserting, removing items in the collection.
114d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner//
115d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnertemplate <typename T>
116d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnerclass PodVector : public PodVectorBase {
117d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turnerpublic:
118d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Default constructor for an empty PodVector<T>
119d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    PodVector() : PodVectorBase() {}
120d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
121d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Copy constructor. This copies all items from |other| into
122d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // the new instance with ::memmove().
123d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    PodVector(const PodVector& other) : PodVectorBase(other) {}
124d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
125d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Assignment operator.
126d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    PodVector& operator=(const PodVector& other) {
127d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        this->assignFrom(other);
128d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return *this;
129d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
130d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
131d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Destructor, this simply releases the internal storage block that
132d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // holds all the items, but doesn't touch them otherwise.
133d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    ~PodVector() {}
134d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
135d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return true iff the PodVector<T> instance is empty, i.e. does not
136d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // have any items.
137d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    bool empty() const { return PodVectorBase::empty(); }
138d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
139d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return the number of items in the current PodVector<T> instance.
140d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    size_t size() const { return PodVectorBase::itemCount(sizeof(T)); }
141d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
142d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return the current capacity in the current PodVector<T> instance.
143d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Do not use directly, except if you know what you're doing. Try to
144d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // use resize() or reserve() instead.
145d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    size_t capacity() const {
146d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return PodVectorBase::itemCapacity(sizeof(T));
147d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
148d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
149d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return the maximum capacity of any PodVector<T> instance.
150d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    static inline size_t maxCapacity() { return SIZE_MAX / sizeof(T); }
151d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
152d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Resize the vector to ensure it can hold |newSize|
153d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // items. This may or may not call reserve() under the hood.
154d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // It's a fatal error to try to resize above maxCapacity().
155d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void resize(size_t newSize) {
156d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        PodVectorBase::resize(newSize, sizeof(T));
157d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
158d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
159d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Resize the vector's storage array to ensure that it can hold at
160d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // least |newSize| items. It's a fatal error to try to resize above
161d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // maxCapacity().
162d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void reserve(size_t newSize) {
163d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        PodVectorBase::reserve(newSize, sizeof(T));
164d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
165d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
166d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return a pointer to the first item in the vector. This is only
167d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // valid until the next call to any function that changes the size
168d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // or capacity of the vector. Can be NULL if the vector is empty.
169d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    T* begin() {
170d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return reinterpret_cast<T*>(PodVectorBase::begin());
171d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
172d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
173d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return a constant pointer to the first item in the vector. This is
174d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // only valid until the next call to any function that changes the
175d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // size of capacity of the vector.
176d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const T* begin() const {
177d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return reinterpret_cast<T*>(PodVectorBase::begin());
178d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
179d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
180d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return a pointer past the last item in the vector. I.e. if the
181d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // result is not NULL, then |result - 1| points to the last item.
182d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Can be NULL if the vector is empty.
183d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    T* end() {
184d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return reinterpret_cast<T*>(PodVectorBase::end());
185d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
186d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
187d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Return a constant pointer past the last item in the vector. I.e. if
188d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // the result is not NULL, then |result - 1| points to the last item.
189d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Can be NULL if the vector is empty.
190d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const T* end() const {
191d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return reinterpret_cast<T*>(PodVectorBase::end());
192d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
193d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
194d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Returns a reference to the item a position |index| in the vector.
195d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // It may be a fatal error to access an out-of-bounds position.
196d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    T& operator[](size_t index) {
197d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return *reinterpret_cast<T*>(
198d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner                PodVectorBase::itemAt(index, sizeof(T)));
199d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
200d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
201d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    const T& operator[](size_t index) const {
202d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return *reinterpret_cast<const T*>(
203d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner                PodVectorBase::itemAt(index, sizeof(T)));
204d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
205d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
206d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Increase the vector's size by 1, then move all items past a given
207d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // position to the right. Return the position of the insertion point
208d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // to let the caller copy the content it desires there. It's preferrable
209d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // to use insert() directly, which will do the item copy for you.
210d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    T* emplace(size_t index) {
211d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        return reinterpret_cast<T*>(
212d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner                PodVectorBase::insertAt(index, sizeof(T)));
213d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
214d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
215d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Insert an item at a given position. |index| is the insertion position
216d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // which must be between 0 and size() included, or a fatal error may
217d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // occur. |item| is a reference to an item to copy into the array,
218d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // byte-by-byte.
219d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void insert(size_t index, const T& item) {
220d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        *(this->emplace(index)) = item;
221d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
222d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
223d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Prepend an item at the start of a vector. This moves all vector items
224d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // to the right, and is thus costly. |item| is a reference to an item
225d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // to copy to the start of the vector.
226d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void prepend(const T& item) {
227d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        *(this->emplace(0U)) = item;
228d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
229d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
230d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Append an item at the end of a vector. Specialized version of insert()
231d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // which always uses size() as the insertion position.
232d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void append(const T& item) {
233d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        *(this->emplace(this->size())) = item;
234d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
235d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
236d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Remove the item at a given position. |index| is the position of the
237d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // item to delete. It must be between 0 and size(), included, or
238d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // a fatal error may occur. Deleting the item at position size()
239d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // doesn't do anything.
240d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void remove(size_t index) {
241d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        PodVectorBase::removeAt(index, sizeof(T));
242d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
243d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
244d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void swap(PodVector* other) {
245d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner        PodVectorBase::swapAll(other);
246d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    }
247d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
248d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    // Compatibility methods for std::vector<>
249d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void push_back(const T& item) { append(item); }
250d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    void pop() { remove(0U); }
251d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
252d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    typedef T* iterator;
253d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner    typedef const T* const_iterator;
254d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner};
255d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
256d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner}  // namespace base
257d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner}  // namespace android
258d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
259d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner
260d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#endif  // ANDROID_BASE_VECTOR_H
261