blob: a2fdc9b9beb2253c728bc8e1b0743bfe0fca70b6 [file] [log] [blame]
/* -*- 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__