| /* -*- c++ -*- */ |
| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #ifndef ANDROID_ASTL_LIST__ |
| #define ANDROID_ASTL_LIST__ |
| |
| #include <cstddef> |
| #include <iterator> |
| #include <limits> |
| #include <algorithm> |
| |
| // Double linked list. In the android NS we declare the nodes and |
| // iterators. The list declaration in the std NS follows that. |
| |
| namespace android { |
| |
| struct ListNodeBase { |
| ListNodeBase *mNext; |
| ListNodeBase *mPrev; |
| |
| // Swap 2 nodes. |
| static void swap(ListNodeBase& a, ListNodeBase& b); |
| |
| // Insert this node BEFORE pos. |
| void hook(ListNodeBase * const pos); |
| |
| // Remove this node and link prev and next together. |
| void unhook(); |
| }; |
| |
| template <typename _T> |
| struct ListNode: public ListNodeBase { |
| _T mData; |
| }; |
| |
| // iterators: ListIterator and ListConstIterator are bidirectional ones. |
| template<typename _T> |
| struct ListIterator |
| { |
| typedef ListIterator<_T> iterator_type; |
| typedef android::ListNode<_T> node_type; |
| public: |
| typedef ptrdiff_t difference_type; |
| typedef std::bidirectional_iterator_tag iterator_category; |
| typedef _T value_type; |
| typedef _T* pointer; |
| typedef _T& reference; |
| |
| ListIterator(): |
| mNode() { } |
| |
| explicit ListIterator(android::ListNodeBase* node): |
| mNode(node) { } |
| |
| reference operator*() const { return static_cast<node_type*>(mNode)->mData; } |
| pointer operator->() const { return &operator*(); } |
| |
| iterator_type& operator++() { mNode = mNode->mNext; return *this; } |
| iterator_type& operator++(int) { |
| iterator_type tmp = *this; |
| mNode = mNode->mNext; |
| return *tmp; |
| } |
| |
| iterator_type& operator--() { mNode = mNode->mPrev; return *this; } |
| iterator_type& operator--(int) { |
| iterator_type tmp = *this; |
| mNode = mNode->mPrev; |
| return *tmp; |
| } |
| |
| bool operator==(const iterator_type& o) const { return mNode == o.mNode; } |
| bool operator!=(const iterator_type& o) const { return mNode != o.mNode; } |
| |
| ListNodeBase *mNode; |
| }; |
| |
| template<typename _T> |
| struct ListConstIterator |
| { |
| typedef ListConstIterator<_T> iterator_type; |
| typedef android::ListNode<_T> node_type; |
| public: |
| typedef ptrdiff_t difference_type; |
| typedef std::bidirectional_iterator_tag iterator_category; |
| typedef _T value_type; |
| typedef _T* pointer; |
| typedef _T& reference; |
| |
| ListConstIterator(): |
| mNode() { } |
| |
| explicit ListConstIterator(ListNodeBase* node): |
| mNode(node) { } |
| |
| ListConstIterator(const ListIterator<_T>& it): mNode(it.mNode) { } |
| |
| reference operator*() const { return static_cast<node_type*>(mNode)->mData; } |
| pointer operator->() const { return &operator*(); } |
| |
| iterator_type& operator++() { mNode = mNode->mNext; return *this; } |
| iterator_type& operator++(int) { |
| iterator_type tmp = *this; |
| mNode = mNode->mNext; |
| return *tmp; |
| } |
| |
| iterator_type& operator--() { mNode = mNode->mPrev; return *this; } |
| iterator_type& operator--(int) { |
| iterator_type tmp = *this; |
| mNode = mNode->mPrev; |
| return *tmp; |
| } |
| |
| bool operator==(const iterator_type& o) const { return mNode == o.mNode; } |
| bool operator!=(const iterator_type& o) const { return mNode != o.mNode; } |
| |
| ListNodeBase *mNode; |
| }; |
| |
| } // namespace android |
| |
| namespace std { |
| |
| // std::list |
| |
| template<typename _T> |
| class list { |
| public: |
| typedef _T value_type; |
| typedef _T* pointer; |
| typedef const _T* const_pointer; |
| typedef _T& reference; |
| typedef const _T& const_reference; |
| typedef android::ListIterator<_T> iterator; |
| typedef android::ListConstIterator<_T> const_iterator; |
| typedef size_t size_type; |
| typedef ptrdiff_t difference_type; |
| |
| // Default constructor, no element. |
| list() { init(); } |
| ~list() { clear(); } |
| |
| // Empty the list. |
| void clear(); |
| |
| // Element access. |
| reference front() { return *iterator(mHead.mNext); } |
| const_reference front() const { return *iterator(mHead.mNext); } |
| reference back() { return *iterator(mHead.mPrev); } |
| const_reference back() const { return *iterator(mHead.mPrev); } |
| |
| // Iterators. |
| iterator begin() { return iterator(mHead.mNext); } |
| const_iterator begin() const { return const_iterator(mHead.mNext); } |
| iterator end() { return iterator(&mHead); } |
| const_iterator end() const { return const_iterator(&mHead); } |
| |
| // Add data at the begin of the list. |
| // @param elt To be added. |
| void push_front(const value_type& elt) { insert(begin(), elt); } |
| void push_back(const value_type& elt) { insert(end(), elt); } |
| |
| // Removes first element. Invalidated the iterators/references to begin. |
| void pop_front() { eraseAtPos(iterator(mHead.mNext)); } |
| |
| // Removes last element. Invalidated the iterators/references to |
| // the last element. |
| void pop_back() { eraseAtPos(iterator(mHead.mPrev)); } |
| |
| bool empty() const { return mLength == 0; } |
| |
| // @eturn the number of elements in the list. |
| size_type size() const { return mLength; } |
| |
| // @return the maximum size for a list |
| size_type max_size() const { return numeric_limits<size_type>::max(); } |
| |
| // Insert the element BEFORE the 'pos' iterator. |
| // @param pos Iterator in the list. |
| // @param elt Element to be inserted. |
| // @return an iterator that points to the inserted element. |
| iterator insert(iterator pos, const value_type& elt); |
| |
| // Remove the element pointed by the iterator. Constant in time, |
| // calls once to _T's destructor. |
| // @param pos Iterator pointing to the elt to be removed. |
| // @return An iterator pointing to the next elt or end(). |
| iterator erase(iterator position); |
| |
| // Remove a range of elements [first, last) |
| // @param first Iterator pointing to the first element to be removed. |
| // @param last Iterator pointing to one past the last element to be removed. |
| // @return An iterator pointing to the elt next to 'last' or end(). |
| iterator erase(iterator first, iterator last); |
| |
| private: |
| void init() { |
| mHead.mNext = &mHead; |
| mHead.mPrev = &mHead; |
| mLength = 0; |
| } |
| |
| // Erase, don't return anything. |
| void eraseAtPos(iterator pos); |
| |
| size_type mLength; |
| // mHead does not contain any data, it represents end(). |
| android::ListNodeBase mHead; |
| }; |
| |
| |
| template<typename _T> |
| void list<_T>::clear() { |
| while (mHead.mNext != &mHead) { |
| // Upcast so delete will reclaim all the memory. |
| android::ListNode<_T> *node = |
| static_cast<android::ListNode<_T> *>(mHead.mNext); |
| mHead.mNext = node->mNext; |
| delete node; |
| } |
| init(); |
| } |
| |
| template<typename _T> |
| typename list<_T>::iterator list<_T>::insert(iterator pos, const value_type& elt) { |
| if (mLength + 1 > mLength) { |
| android::ListNode<_T> *node = new android::ListNode<_T>(); |
| node->mData = elt; |
| node->hook(pos.mNode); |
| ++mLength; |
| return iterator(node); |
| } else { |
| return end(); |
| } |
| } |
| |
| template<typename _T> |
| typename list<_T>::iterator list<_T>::erase(iterator pos) { |
| iterator res = iterator(pos.mNode->mNext); |
| eraseAtPos(pos); |
| return res; |
| } |
| |
| template<typename _T> |
| typename list<_T>::iterator list<_T>::erase(iterator first, iterator last) { |
| while (first != last) { |
| first = erase(first); // erase returns an iterator to the next elt. |
| } |
| return last; |
| } |
| |
| template<typename _T> |
| void list<_T>::eraseAtPos(iterator pos) { |
| if (pos.mNode != &mHead) { |
| pos.mNode->unhook(); |
| android::ListNode<_T>* node = |
| static_cast<android::ListNode<_T>*>(pos.mNode); |
| delete node; |
| --mLength; |
| } |
| } |
| |
| } // namespace std |
| |
| #endif // ANDROID_ASTL_LIST__ |