• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* -*- c++ -*- */
2/*
3 * Copyright (C) 2009 The Android Open Source Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *  * Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *  * Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef ANDROID_ASTL_VECTOR__
31#define ANDROID_ASTL_VECTOR__
32
33#include <cstddef>
34#include <cstdlib>
35#include <cstring>
36#include <algorithm>
37#include <iterator>
38#include <memory>
39#include <type_traits.h>
40
41namespace std {
42
43#ifdef _T
44#error "_T is a macro."
45#endif
46
47// Simple vector implementation. Its purpose is to be able to compile code that
48// uses the STL and requires std::vector.
49//
50// IMPORTANT:
51// . This class it is not fully STL compliant. Some constructors/methods maybe
52// missing, they will be added on demand.
53// . A standard container which offers fixed time access to individual
54// elements in any order.
55//
56// TODO: Use the stack for the default constructor. When the capacity
57// grows beyond that move the data to the heap.
58
59template<typename _T>
60class vector
61{
62    typedef vector<_T> vector_type;
63
64  public:
65    typedef _T         value_type;
66    typedef _T*        pointer;
67    typedef const _T*  const_pointer;
68    typedef _T&        reference;
69    typedef const _T&  const_reference;
70
71    typedef __wrapper_iterator<pointer,vector_type>  iterator;
72    typedef __wrapper_iterator<const_pointer,vector_type> const_iterator;
73
74    typedef size_t    size_type;
75    typedef ptrdiff_t difference_type;
76
77    vector();
78
79    // Create a vector with bitwise copies of an exemplar element.
80    // @param num The number of elements to create.
81    // @param init_value The element to copy.
82    explicit vector(const size_type num, const value_type& init_value = value_type());
83
84    // Create a vector by copying the elements from [first, last).
85    //
86    // If the iterators are random-access, the constructor will be
87    // able to reserve the memory in a single call before copying the
88    // elements. If the elements are POD, the constructor uses memmove.
89    template<typename _Iterator>
90    vector(_Iterator first, _Iterator last) {
91        // Because of template matching, vector<int>(int n, int val)
92        // will now match this constructor (int != size_type) instead
93        // of the repeat one above. In this case, the _Iterator
94        // template parameter is an integral type and not an iterator,
95        // we use that to call the correct initialize impl.
96        typedef typename is_integral<_Iterator>::type integral;
97        initialize(first, last, integral());
98    }
99
100    ~vector() { clear(); }
101
102    // @return true if the vector is empty, false otherwise.
103    bool empty() const { return mLength == 0; }
104    size_type size() const { return mLength; }
105
106    // @return the maximum size for a vector.
107    size_type max_size() const { return (~size_type(0)) / sizeof(value_type); }
108
109    // Change the capacity to new_size. 0 means shrink to fit. The
110    // extra memory is not initialized when the capacity is grown.
111    // @param new_size number of element to be allocated.
112    // @return true if successful. The STL version returns nothing.
113    bool reserve(size_type new_size = 0);
114
115    // @return The total number of elements that the vector can hold
116    // before more memory gets allocated.
117    size_type capacity() const { return mCapacity; }
118
119    reference front() { return *mBegin; }
120    const_reference front() const { return *mBegin; }
121
122    reference back() { return mLength ? *(mBegin + mLength - 1) : front(); }
123    const_reference back() const { return mLength ? *(mBegin + mLength - 1) : front(); }
124
125    // Subscript access to the vector's elements. Don't do boundary
126    // check. Use at() for checked access.
127    // @param index Of the element (0-based).
128    // @return A const reference to the element.
129    const_reference operator[](size_type index) const { return *(mBegin + index); }
130
131    // @param index Of the element (0-based).
132    // @return A reference to the element.
133    reference operator[](size_type index) { return *(mBegin + index); }
134
135    // 'at' is similar to operator[] except that it does check bounds.
136    const_reference at(const size_type index) const
137    { return index < mLength ? *( mBegin + index) : sDummy; }
138
139    reference at(const size_type index)
140    { return index < mLength ? *( mBegin + index) : sDummy; }
141
142    iterator begin() { return iterator(mBegin); }
143    iterator end() { return iterator(mBegin + mLength); }
144
145    const_iterator begin() const { return const_iterator(mBegin); }
146    const_iterator end() const { return const_iterator(mBegin + mLength); }
147
148    // Add data at the end of the vector. Constant in time if the
149    // memory has been preallocated (e.g using reserve).
150    // @param elt To be added.
151    void push_back(const value_type& elt);
152
153    // Remove the last element. However, no memory is reclaimed from
154    // the internal buffer: you need to call reserve() to recover it.
155    void pop_back();
156
157    // Remove the element pointed by the iterator.
158    // Expensive since the remaining elts must be shifted around.
159    // @param pos Iterator pointing to the elt to be removed.
160    // @return An iterator pointing to the next elt or end().
161    iterator erase(iterator pos);
162
163    // Remove a range of elements [first, last)
164    // @param first Iterator pointing to the first element to be removed.
165    // @param last Iterator pointing to one past the last element to be removed.
166    // @return An iterator pointing to the elt next to 'last' or end().
167    iterator erase(iterator first, iterator last);
168
169    // Empty the vector on return. Release the internal buffer. Length
170    // and capacity are both 0 on return. If you want to keep the
171    // internal buffer around for reuse, call 'resize'/'erase' instead.
172    void clear();
173
174    // Resize the vector to contain 'size' element. If 'size' is
175    // smaller than the current size, the extra elements are dropped
176    // but the reserved memory is not changed (use 'swap' to recover
177    // memory.) If 'size' is greater, the vector is expanded by
178    // inserting at the end as many copy of 'init_value' (this may
179    // lead to some realloc) as necessary. See 'reserve'.
180    void resize(size_type size, value_type init_value = value_type());
181
182    void swap(vector& other);
183  private:
184    // See the 2 'initialize' methods first. They desambiguate between
185    // repeat and range initialize. For range initialize, there is
186    // another desambiguation based on the nature of the iterators.
187
188    // Repeat constructor implementation.
189    void repeat_initialize(const size_type num,
190                           const value_type& init_value);
191
192    // Initialize from a random access iterator.
193    template<typename _Iterator>
194    void range_initialize(_Iterator first, _Iterator last,
195                          random_access_iterator_tag);
196
197    // Initialize from an input iterator.
198    template<typename _InputIterator>
199    void range_initialize(_InputIterator first, _InputIterator last,
200                          input_iterator_tag);
201
202    // Repeat constructor that matched the templatized constructor for iterator.
203    // The last parameter true_type is used by the caller to target this method.
204    template<typename _Integral>
205    void initialize(_Integral num, _Integral init_value, true_type) {
206        repeat_initialize((size_type)num, init_value);
207    }
208
209    // Not a repeat constructor (last param type is false_type). first
210    // and last are really iterators. Dispatch the call depending on
211    // the iterators' category.
212    template<typename _InputIterator>
213    void initialize(_InputIterator first, _InputIterator last, false_type) {
214        range_initialize(first, last, android::iterator_category(first));
215    }
216
217    // @return New internal buffer size when it is adjusted automatically.
218    size_type grow() const;
219
220    // Calls the class' deallocator explicitely on each instance in
221    // the vector.
222    void deallocate();
223
224    pointer mBegin;
225    size_type mCapacity;
226    size_type mLength;
227    static value_type sDummy;  // at() doen't throw exception and returns mDummy.
228    static const size_type kExponentialFactor = 2;
229    static const size_type kExponentialLimit = 256;
230    static const size_type kLinearIncrement = 256;
231};
232
233
234// The implementation uses malloc instead of new because Posix states that:
235// The pointer returned if the allocation succeeds shall be suitably
236// aligned so that it may be assigned to a pointer to any type of
237// object and then used to access such an object in the space
238// allocated
239// So as long as we malloc() more than 4 bytes, the returned block
240// must be able to contain a pointer, and thus will be 32-bit
241// aligned. I believe the bionic implementation uses a minimum of 8 or 16.
242//
243// Invariant: mLength <= mCapacity <= max_size()
244
245
246template<typename _T>
247vector<_T>::vector()
248        :mBegin(NULL), mCapacity(0), mLength(0) { }
249
250template<typename _T>
251vector<_T>::vector(const size_type num, const value_type& init_value)
252{
253    repeat_initialize(num, init_value);
254}
255
256template<typename _T>
257void vector<_T>::repeat_initialize(const size_type num,
258                                   const value_type& init_value)
259{
260    if (num < max_size())
261    {
262        mBegin = static_cast<pointer>(malloc(num * sizeof(value_type)));
263        if (mBegin)
264        {
265            mLength = mCapacity =  num;
266            std::uninitialized_fill(mBegin, mBegin + mLength, init_value);
267            return;
268        }
269    }
270    mBegin = NULL;
271    mLength = mCapacity =  0;
272}
273
274template<typename _T>
275bool vector<_T>::reserve(size_type new_size)
276{
277    if (0 == new_size)
278    {
279        if (0 == mLength)  // Free whatever has been reserved.
280        {
281            clear();
282            return true;
283        }
284        new_size = mLength;  // Shrink to fit.
285    }
286    else if (new_size < mLength || new_size > max_size())
287    {
288        return false;
289    }
290
291    if (is_pod<value_type>::value)
292    {
293        pointer oldBegin = mBegin;
294        mBegin = static_cast<pointer>(
295            realloc(mBegin, new_size * sizeof(value_type)));
296        if (!mBegin)
297        {
298            mBegin = oldBegin;
299            return false;
300        }
301    }
302    else
303    {
304        pointer newBegin =  static_cast<pointer>(
305            malloc(new_size * sizeof(value_type)));
306        if (!newBegin) return false;
307
308        if (mBegin != NULL) {
309            std::uninitialized_copy(mBegin, mBegin + mLength, newBegin);
310            deallocate();
311        }
312        mBegin = newBegin;
313    }
314    mCapacity = new_size;
315    return true;
316}
317
318template<typename _T>
319void vector<_T>::push_back(const value_type& elt)
320{
321    if (max_size() == mLength) return;
322    if (mCapacity == mLength)
323    {
324        const size_type new_capacity = grow();
325        if (0 == new_capacity || !reserve(new_capacity)) return;
326    }
327    // mLength < mCapacity
328    if (is_pod<value_type>::value) {
329        *(mBegin + mLength) = elt;
330    } else {
331        // The memory where the new element is added is uninitialized,
332        // we cannot use assigment (lhs is not valid).
333        new((void *)(mBegin + mLength)) _T(elt);
334    }
335    ++mLength;
336}
337
338template<typename _T>
339void vector<_T>::pop_back()
340{
341    if (mLength > 0)
342    {
343        --mLength;
344        if (!is_pod<value_type>::value)
345        {
346            (mBegin + mLength)->~_T();
347        }
348    }
349}
350
351template<typename _T>
352typename vector<_T>::iterator
353vector<_T>::erase(iterator pos) {
354    if (mLength) {
355        std::copy(pos + 1, end(), pos);
356        --mLength;
357        if (!is_pod<value_type>::value) {
358            end()->~_T();
359        }
360    }
361    return pos;
362}
363
364template<typename _T>
365typename vector<_T>::iterator
366vector<_T>::erase(iterator first, iterator last) {
367    difference_type len = std::distance(first, last);
368    if (len > 0) {
369        last = std::copy(last, end(), first);
370
371        if (!is_pod<value_type>::value) {
372            while (last != end()) {
373                last->~_T();
374                ++last;
375            }
376        }
377        mLength -= len;
378    }
379    return first;
380}
381
382template<typename _T>
383void vector<_T>::clear()
384{
385    if(mBegin)
386    {
387        if (is_pod<value_type>::value)
388        {
389            free(mBegin);
390        }
391        else
392        {
393            deallocate();
394        }
395    }
396    mBegin = NULL;
397    mCapacity = 0;
398    mLength = 0;
399}
400
401template<typename _T>
402void vector<_T>::resize(size_type new_size, value_type init_value)
403{
404    if (mLength == new_size || new_size > max_size()) {
405        return;
406    } else if (new_size < mLength) {
407        if (!is_pod<value_type>::value) {
408            const pointer end = mBegin + mLength;
409            for (pointer begin = mBegin + new_size;
410                 begin < end; ++begin) {
411                begin->~_T();
412            }
413        }
414        mLength = new_size;
415        return;
416    }
417
418    if (new_size > mCapacity && !reserve(new_size)) {
419        return;
420    }
421    std::uninitialized_fill(mBegin + mLength, mBegin + new_size, init_value);
422    mLength = new_size;
423}
424
425template<typename _T>
426void vector<_T>::swap(vector& other)
427{
428    std::swap(mBegin, other.mBegin);
429    std::swap(mCapacity, other.mCapacity);
430    std::swap(mLength, other.mLength);
431}
432
433template<typename _T>
434template<typename _InputIterator>
435void vector<_T>::range_initialize(_InputIterator first, _InputIterator last,
436                                  input_iterator_tag) {
437    // There is no way to know how many elements we are going to
438    // insert, call push_back which will alloc/realloc as needed.
439    mBegin = NULL;
440    mLength = mCapacity =  0;
441    for (; first != last; ++first) {
442        push_back(*first);
443    }
444}
445
446template<typename _T>
447template<typename _Iterator>
448void vector<_T>::range_initialize(_Iterator first, _Iterator last,
449                                  random_access_iterator_tag) {
450    typedef typename iterator_traits<_Iterator>::difference_type difference_type;
451    const difference_type num = std::distance(first, last);
452
453    if (0 <= num && static_cast<size_type>(num) < max_size()) {
454        mBegin = static_cast<pointer>(malloc(num * sizeof(value_type)));
455        if (mBegin) {
456            mLength = mCapacity =  num;
457            std::uninitialized_copy(first, last, iterator(mBegin));
458            return;
459        }
460    }
461    mBegin = NULL;
462    mLength = mCapacity =  0;
463}
464
465
466// Grow the capacity. Use exponential until kExponentialLimit then
467// linear until it reaches max_size().
468template<typename _T>
469typename vector<_T>::size_type vector<_T>::grow() const
470{
471    size_type new_capacity;
472    if (mCapacity > kExponentialLimit)
473    {
474        new_capacity = mCapacity + kLinearIncrement;
475    }
476    else
477    {
478        new_capacity = mCapacity == 0 ? kExponentialFactor : mCapacity * kExponentialFactor;
479    }
480    if (mCapacity > new_capacity || new_capacity > max_size())
481    { // Overflow: cap at max_size() if not there already.
482        new_capacity = mCapacity == max_size() ? 0 : max_size();
483    }
484    return  new_capacity;
485}
486
487
488// mBegin should not be NULL.
489template<typename _T>
490void vector<_T>::deallocate()
491{
492    pointer begin = mBegin;
493    pointer end = mBegin + mLength;
494
495    for (; begin != end; ++begin)
496    {
497        begin->~_T();
498    }
499    free(mBegin);
500}
501
502// Dummy element returned when at() is out of bound.
503template<typename _T> _T vector<_T>::sDummy;
504
505}  // namespace std
506
507#endif  // ANDROID_ASTL_VECTOR__
508