michael@0: /* michael@0: * Copyright (C) 2005 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef ANDROID_VECTOR_H michael@0: #define ANDROID_VECTOR_H michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: namespace android { michael@0: michael@0: template michael@0: class SortedVector; michael@0: michael@0: /*! michael@0: * The main templated vector class ensuring type safety michael@0: * while making use of VectorImpl. michael@0: * This is the class users want to use. michael@0: */ michael@0: michael@0: template michael@0: class Vector : private VectorImpl michael@0: { michael@0: public: michael@0: typedef TYPE value_type; michael@0: michael@0: /*! michael@0: * Constructors and destructors michael@0: */ michael@0: michael@0: Vector(); michael@0: Vector(const Vector& rhs); michael@0: explicit Vector(const SortedVector& rhs); michael@0: virtual ~Vector(); michael@0: michael@0: /*! copy operator */ michael@0: const Vector& operator = (const Vector& rhs) const; michael@0: Vector& operator = (const Vector& rhs); michael@0: michael@0: const Vector& operator = (const SortedVector& rhs) const; michael@0: Vector& operator = (const SortedVector& rhs); michael@0: michael@0: /* michael@0: * empty the vector michael@0: */ michael@0: michael@0: inline void clear() { VectorImpl::clear(); } michael@0: michael@0: /*! michael@0: * vector stats michael@0: */ michael@0: michael@0: //! returns number of items in the vector michael@0: inline size_t size() const { return VectorImpl::size(); } michael@0: //! returns whether or not the vector is empty michael@0: inline bool isEmpty() const { return VectorImpl::isEmpty(); } michael@0: //! returns how many items can be stored without reallocating the backing store michael@0: inline size_t capacity() const { return VectorImpl::capacity(); } michael@0: //! sets the capacity. capacity can never be reduced less than size() michael@0: inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); } michael@0: michael@0: /*! michael@0: * set the size of the vector. items are appended with the default michael@0: * constructor, or removed from the end as needed. michael@0: */ michael@0: inline ssize_t resize(size_t size) { return VectorImpl::resize(size); } michael@0: michael@0: /*! michael@0: * C-style array access michael@0: */ michael@0: michael@0: //! read-only C-style access michael@0: inline const TYPE* array() const; michael@0: //! read-write C-style access michael@0: TYPE* editArray(); michael@0: michael@0: /*! michael@0: * accessors michael@0: */ michael@0: michael@0: //! read-only access to an item at a given index michael@0: inline const TYPE& operator [] (size_t index) const; michael@0: //! alternate name for operator [] michael@0: inline const TYPE& itemAt(size_t index) const; michael@0: //! stack-usage of the vector. returns the top of the stack (last element) michael@0: const TYPE& top() const; michael@0: michael@0: /*! michael@0: * modifying the array michael@0: */ michael@0: michael@0: //! copy-on write support, grants write access to an item michael@0: TYPE& editItemAt(size_t index); michael@0: //! grants right access to the top of the stack (last element) michael@0: TYPE& editTop(); michael@0: michael@0: /*! michael@0: * append/insert another vector michael@0: */ michael@0: michael@0: //! insert another vector at a given index michael@0: ssize_t insertVectorAt(const Vector& vector, size_t index); michael@0: michael@0: //! append another vector at the end of this one michael@0: ssize_t appendVector(const Vector& vector); michael@0: michael@0: michael@0: //! insert an array at a given index michael@0: ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length); michael@0: michael@0: //! append an array at the end of this vector michael@0: ssize_t appendArray(const TYPE* array, size_t length); michael@0: michael@0: /*! michael@0: * add/insert/replace items michael@0: */ michael@0: michael@0: //! insert one or several items initialized with their default constructor michael@0: inline ssize_t insertAt(size_t index, size_t numItems = 1); michael@0: //! insert one or several items initialized from a prototype item michael@0: ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1); michael@0: //! pop the top of the stack (removes the last element). No-op if the stack's empty michael@0: inline void pop(); michael@0: //! pushes an item initialized with its default constructor michael@0: inline void push(); michael@0: //! pushes an item on the top of the stack michael@0: void push(const TYPE& item); michael@0: //! same as push() but returns the index the item was added at (or an error) michael@0: inline ssize_t add(); michael@0: //! same as push() but returns the index the item was added at (or an error) michael@0: ssize_t add(const TYPE& item); michael@0: //! replace an item with a new one initialized with its default constructor michael@0: inline ssize_t replaceAt(size_t index); michael@0: //! replace an item with a new one michael@0: ssize_t replaceAt(const TYPE& item, size_t index); michael@0: michael@0: /*! michael@0: * remove items michael@0: */ michael@0: michael@0: //! remove several items michael@0: inline ssize_t removeItemsAt(size_t index, size_t count = 1); michael@0: //! remove one item michael@0: inline ssize_t removeAt(size_t index) { return removeItemsAt(index); } michael@0: michael@0: /*! michael@0: * sort (stable) the array michael@0: */ michael@0: michael@0: typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs); michael@0: typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state); michael@0: michael@0: inline status_t sort(compar_t cmp); michael@0: inline status_t sort(compar_r_t cmp, void* state); michael@0: michael@0: // for debugging only michael@0: inline size_t getItemSize() const { return itemSize(); } michael@0: michael@0: michael@0: /* michael@0: * these inlines add some level of compatibility with STL. eventually michael@0: * we should probably turn things around. michael@0: */ michael@0: typedef TYPE* iterator; michael@0: typedef TYPE const* const_iterator; michael@0: michael@0: inline iterator begin() { return editArray(); } michael@0: inline iterator end() { return editArray() + size(); } michael@0: inline const_iterator begin() const { return array(); } michael@0: inline const_iterator end() const { return array() + size(); } michael@0: inline void reserve(size_t n) { setCapacity(n); } michael@0: inline bool empty() const{ return isEmpty(); } michael@0: inline void push_back(const TYPE& item) { insertAt(item, size(), 1); } michael@0: inline void push_front(const TYPE& item) { insertAt(item, 0, 1); } michael@0: inline iterator erase(iterator pos) { michael@0: ssize_t index = removeItemsAt(pos-array()); michael@0: return begin() + index; michael@0: } michael@0: michael@0: protected: michael@0: virtual void do_construct(void* storage, size_t num) const; michael@0: virtual void do_destroy(void* storage, size_t num) const; michael@0: virtual void do_copy(void* dest, const void* from, size_t num) const; michael@0: virtual void do_splat(void* dest, const void* item, size_t num) const; michael@0: virtual void do_move_forward(void* dest, const void* from, size_t num) const; michael@0: virtual void do_move_backward(void* dest, const void* from, size_t num) const; michael@0: }; michael@0: michael@0: // Vector can be trivially moved using memcpy() because moving does not michael@0: // require any change to the underlying SharedBuffer contents or reference count. michael@0: template struct trait_trivial_move > { enum { value = true }; }; michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // No user serviceable parts from here... michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: template inline michael@0: Vector::Vector() michael@0: : VectorImpl(sizeof(TYPE), michael@0: ((traits::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0) michael@0: |(traits::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0) michael@0: |(traits::has_trivial_copy ? HAS_TRIVIAL_COPY : 0)) michael@0: ) michael@0: { michael@0: } michael@0: michael@0: template inline michael@0: Vector::Vector(const Vector& rhs) michael@0: : VectorImpl(rhs) { michael@0: } michael@0: michael@0: template inline michael@0: Vector::Vector(const SortedVector& rhs) michael@0: : VectorImpl(static_cast(rhs)) { michael@0: } michael@0: michael@0: template inline michael@0: Vector::~Vector() { michael@0: finish_vector(); michael@0: } michael@0: michael@0: template inline michael@0: Vector& Vector::operator = (const Vector& rhs) { michael@0: VectorImpl::operator = (rhs); michael@0: return *this; michael@0: } michael@0: michael@0: template inline michael@0: const Vector& Vector::operator = (const Vector& rhs) const { michael@0: VectorImpl::operator = (static_cast(rhs)); michael@0: return *this; michael@0: } michael@0: michael@0: template inline michael@0: Vector& Vector::operator = (const SortedVector& rhs) { michael@0: VectorImpl::operator = (static_cast(rhs)); michael@0: return *this; michael@0: } michael@0: michael@0: template inline michael@0: const Vector& Vector::operator = (const SortedVector& rhs) const { michael@0: VectorImpl::operator = (rhs); michael@0: return *this; michael@0: } michael@0: michael@0: template inline michael@0: const TYPE* Vector::array() const { michael@0: return static_cast(arrayImpl()); michael@0: } michael@0: michael@0: template inline michael@0: TYPE* Vector::editArray() { michael@0: return static_cast(editArrayImpl()); michael@0: } michael@0: michael@0: michael@0: template inline michael@0: const TYPE& Vector::operator[](size_t index) const { michael@0: LOG_FATAL_IF(index>=size(), michael@0: "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__, michael@0: int(index), int(size())); michael@0: return *(array() + index); michael@0: } michael@0: michael@0: template inline michael@0: const TYPE& Vector::itemAt(size_t index) const { michael@0: return operator[](index); michael@0: } michael@0: michael@0: template inline michael@0: const TYPE& Vector::top() const { michael@0: return *(array() + size() - 1); michael@0: } michael@0: michael@0: template inline michael@0: TYPE& Vector::editItemAt(size_t index) { michael@0: return *( static_cast(editItemLocation(index)) ); michael@0: } michael@0: michael@0: template inline michael@0: TYPE& Vector::editTop() { michael@0: return *( static_cast(editItemLocation(size()-1)) ); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::insertVectorAt(const Vector& vector, size_t index) { michael@0: return VectorImpl::insertVectorAt(reinterpret_cast(vector), index); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::appendVector(const Vector& vector) { michael@0: return VectorImpl::appendVector(reinterpret_cast(vector)); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::insertArrayAt(const TYPE* array, size_t index, size_t length) { michael@0: return VectorImpl::insertArrayAt(array, index, length); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::appendArray(const TYPE* array, size_t length) { michael@0: return VectorImpl::appendArray(array, length); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::insertAt(const TYPE& item, size_t index, size_t numItems) { michael@0: return VectorImpl::insertAt(&item, index, numItems); michael@0: } michael@0: michael@0: template inline michael@0: void Vector::push(const TYPE& item) { michael@0: return VectorImpl::push(&item); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::add(const TYPE& item) { michael@0: return VectorImpl::add(&item); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::replaceAt(const TYPE& item, size_t index) { michael@0: return VectorImpl::replaceAt(&item, index); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::insertAt(size_t index, size_t numItems) { michael@0: return VectorImpl::insertAt(index, numItems); michael@0: } michael@0: michael@0: template inline michael@0: void Vector::pop() { michael@0: VectorImpl::pop(); michael@0: } michael@0: michael@0: template inline michael@0: void Vector::push() { michael@0: VectorImpl::push(); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::add() { michael@0: return VectorImpl::add(); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::replaceAt(size_t index) { michael@0: return VectorImpl::replaceAt(index); michael@0: } michael@0: michael@0: template inline michael@0: ssize_t Vector::removeItemsAt(size_t index, size_t count) { michael@0: return VectorImpl::removeItemsAt(index, count); michael@0: } michael@0: michael@0: template inline michael@0: status_t Vector::sort(Vector::compar_t cmp) { michael@0: return VectorImpl::sort((VectorImpl::compar_t)cmp); michael@0: } michael@0: michael@0: template inline michael@0: status_t Vector::sort(Vector::compar_r_t cmp, void* state) { michael@0: return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state); michael@0: } michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: template michael@0: void Vector::do_construct(void* storage, size_t num) const { michael@0: construct_type( reinterpret_cast(storage), num ); michael@0: } michael@0: michael@0: template michael@0: void Vector::do_destroy(void* storage, size_t num) const { michael@0: destroy_type( reinterpret_cast(storage), num ); michael@0: } michael@0: michael@0: template michael@0: void Vector::do_copy(void* dest, const void* from, size_t num) const { michael@0: copy_type( reinterpret_cast(dest), reinterpret_cast(from), num ); michael@0: } michael@0: michael@0: template michael@0: void Vector::do_splat(void* dest, const void* item, size_t num) const { michael@0: splat_type( reinterpret_cast(dest), reinterpret_cast(item), num ); michael@0: } michael@0: michael@0: template michael@0: void Vector::do_move_forward(void* dest, const void* from, size_t num) const { michael@0: move_forward_type( reinterpret_cast(dest), reinterpret_cast(from), num ); michael@0: } michael@0: michael@0: template michael@0: void Vector::do_move_backward(void* dest, const void* from, size_t num) const { michael@0: move_backward_type( reinterpret_cast(dest), reinterpret_cast(from), num ); michael@0: } michael@0: michael@0: }; // namespace android michael@0: michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: #endif // ANDROID_VECTOR_H michael@0: