Home | History | Annotate | Download | only in include
      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 
     41 namespace 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 
     59 template<typename _T>
     60 class 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 
    246 template<typename _T>
    247 vector<_T>::vector()
    248         :mBegin(NULL), mCapacity(0), mLength(0) { }
    249 
    250 template<typename _T>
    251 vector<_T>::vector(const size_type num, const value_type& init_value)
    252 {
    253     repeat_initialize(num, init_value);
    254 }
    255 
    256 template<typename _T>
    257 void 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 
    274 template<typename _T>
    275 bool 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 
    318 template<typename _T>
    319 void 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 
    338 template<typename _T>
    339 void 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 
    351 template<typename _T>
    352 typename vector<_T>::iterator
    353 vector<_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 
    364 template<typename _T>
    365 typename vector<_T>::iterator
    366 vector<_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 
    382 template<typename _T>
    383 void 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 
    401 template<typename _T>
    402 void 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 
    425 template<typename _T>
    426 void 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 
    433 template<typename _T>
    434 template<typename _InputIterator>
    435 void 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 
    446 template<typename _T>
    447 template<typename _Iterator>
    448 void 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().
    468 template<typename _T>
    469 typename 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.
    489 template<typename _T>
    490 void 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.
    503 template<typename _T> _T vector<_T>::sDummy;
    504 
    505 }  // namespace std
    506 
    507 #endif  // ANDROID_ASTL_VECTOR__
    508