aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Catania <niko@google.com>2010-02-07 09:33:29 -0800
committerNicolas Catania <niko@google.com>2010-02-10 16:21:03 -0800
commit0d0613671834f13e40436d6becddab8f426de289 (patch)
treea4f6d3ad2b89459b1c8f99f5a9cefa10934804bb
parent464136e01a1facf09ce3befccbfc04f2d1da8d5b (diff)
downloadastl-0d0613671834f13e40436d6becddab8f426de289.tar.gz
Added erase to list.
-rw-r--r--include/list57
-rw-r--r--tests/test_list.cpp68
2 files changed, 121 insertions, 4 deletions
diff --git a/include/list b/include/list
index d6583d2..a2fdc9b 100644
--- a/include/list
+++ b/include/list
@@ -171,10 +171,10 @@ class list {
void clear();
// Element access.
- reference front() { return *begin(); }
- const_reference front() const { return *begin(); }
- reference back() { return *(end()--); }
- const_reference back() const { return *(end()--); }
+ 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); }
@@ -187,6 +187,13 @@ class list {
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.
@@ -201,12 +208,28 @@ class list {
// @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;
@@ -238,6 +261,32 @@ typename list<_T>::iterator list<_T>::insert(iterator pos, const value_type& elt
}
}
+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__
diff --git a/tests/test_list.cpp b/tests/test_list.cpp
index 6cb9634..b017a29 100644
--- a/tests/test_list.cpp
+++ b/tests/test_list.cpp
@@ -115,6 +115,71 @@ bool testIterator()
return true;
}
+bool testErase() {
+ list<int> l;
+ for (int i = 0; i < 100; ++i) {
+ l.push_back(i);
+ }
+
+ // Deleting the first element.
+ list<int>::iterator val = l.erase(l.begin());
+ EXPECT_TRUE(l.size() == 99);
+ EXPECT_TRUE(*val == 1);
+
+ // Deleting the last should be a no op.
+ l.erase(l.end());
+ EXPECT_TRUE(l.size() == 99);
+
+ // Empty bay removing the last element;
+ while (l.size() > 0) {
+ val = l.erase(--l.end());
+ }
+
+ EXPECT_TRUE(l.size() == 0);
+ EXPECT_TRUE(val == l.end());
+
+ return true;
+}
+
+bool testEraseRange() {
+ list<int> l;
+ for (int i = 0; i < 100; ++i) {
+ l.push_back(i);
+ }
+ l.erase(l.begin(), l.end());
+ EXPECT_TRUE(l.size() == 0);
+ return true;
+}
+
+bool testPushPop() {
+ list<int> l;
+
+ l.push_front(10);
+ EXPECT_TRUE(l.front() == 10);
+ l.push_back(100);
+ EXPECT_TRUE(l.back() == 100);
+
+ l.push_front(1);
+ EXPECT_TRUE(l.front() == 1);
+ l.push_back(1000);
+ EXPECT_TRUE(l.back() == 1000);
+
+ l.pop_front();
+ EXPECT_TRUE(l.front() == 10);
+ l.pop_back();
+ EXPECT_TRUE(l.back() == 100);
+ l.pop_front();
+ EXPECT_TRUE(l.front() == 100);
+ EXPECT_TRUE(l.back() == 100);
+ l.pop_back();
+ EXPECT_TRUE(l.empty());
+ // all these are noops
+ l.pop_back();
+ l.pop_front();
+ l.pop_back();
+ return true;
+}
+
} // namespace android
int main(int argc, char **argv)
@@ -123,5 +188,8 @@ int main(int argc, char **argv)
FAIL_UNLESS(testSize);
FAIL_UNLESS(testClear);
FAIL_UNLESS(testIterator);
+ FAIL_UNLESS(testErase);
+ FAIL_UNLESS(testEraseRange);
+ FAIL_UNLESS(testPushPop);
return kPassed;
}