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