2 * Copyright (C) 2005 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 // Templated list class. Normally we'd use STL, but we don't have that.
19 // This class mimics STL's interfaces.
21 // Objects are copied into the list with the '=' operator or with copy-
22 // construction, so if the compiler's auto-generated versions won't work for
23 // you, define your own.
25 // The only class you want to use from here is "List".
37 * Doubly-linked list. Instantiate with "List<MyClass> myList".
39 * Objects added to the list are copied using the assignment operator,
40 * so this must be defined.
47 * One element in the list.
51 explicit _Node(const T& val) : mVal(val) {}
53 inline T& getRef() { return mVal; }
54 inline const T& getRef() const { return mVal; }
55 inline _Node* getPrev() const { return mpPrev; }
56 inline _Node* getNext() const { return mpNext; }
57 inline void setVal(const T& val) { mVal = val; }
58 inline void setPrev(_Node* ptr) { mpPrev = ptr; }
59 inline void setNext(_Node* ptr) { mpNext = ptr; }
62 friend class _ListIterator;
69 * Iterator for walking through the list.
72 template <typename TYPE>
73 struct CONST_ITERATOR {
74 typedef _Node const * NodePtr;
75 typedef const TYPE Type;
78 template <typename TYPE>
79 struct NON_CONST_ITERATOR {
80 typedef _Node* NodePtr;
86 template <class> class Constness
89 typedef _ListIterator<U, Constness> _Iter;
90 typedef typename Constness<U>::NodePtr _NodePtr;
91 typedef typename Constness<U>::Type _Type;
93 explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
97 _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
100 // this will handle conversions from iterator to const_iterator
101 // (and also all convertible iterators)
102 // Here, in this implementation, the iterators can be converted
103 // if the nodes can be converted
104 template<typename V> explicit
105 _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
109 * Dereference operator. Used to get at the juicy insides.
111 _Type& operator*() const { return mpNode->getRef(); }
112 _Type* operator->() const { return &(mpNode->getRef()); }
115 * Iterator comparison.
117 inline bool operator==(const _Iter& right) const {
118 return mpNode == right.mpNode; }
120 inline bool operator!=(const _Iter& right) const {
121 return mpNode != right.mpNode; }
124 * handle comparisons between iterator and const_iterator
126 template<typename OTHER>
127 inline bool operator==(const OTHER& right) const {
128 return mpNode == right.mpNode; }
130 template<typename OTHER>
131 inline bool operator!=(const OTHER& right) const {
132 return mpNode != right.mpNode; }
135 * Incr/decr, used to move through the list.
137 inline _Iter& operator++() { // pre-increment
138 mpNode = mpNode->getNext();
141 const _Iter operator++(int) { // post-increment
143 mpNode = mpNode->getNext();
146 inline _Iter& operator--() { // pre-increment
147 mpNode = mpNode->getPrev();
150 const _Iter operator--(int) { // post-increment
152 mpNode = mpNode->getPrev();
156 inline _NodePtr getNode() const { return mpNode; }
158 _NodePtr mpNode; /* should be private, but older gcc fails */
167 List(const List<T>& src) { // copy-constructor
169 insert(begin(), src.begin(), src.end());
173 delete[] (unsigned char*) mpMiddle;
176 typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
177 typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
179 List<T>& operator=(const List<T>& right);
181 /* returns true if the list is empty */
182 inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
184 /* return #of elements in list */
185 size_t size() const {
186 return size_t(distance(begin(), end()));
190 * Return the first element or one past the last element. The
191 * _Node* we're returning is converted to an "iterator" by a
192 * constructor in _ListIterator.
194 inline iterator begin() {
195 return iterator(mpMiddle->getNext());
197 inline const_iterator begin() const {
198 return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
200 inline iterator end() {
201 return iterator(mpMiddle);
203 inline const_iterator end() const {
204 return const_iterator(const_cast<_Node const*>(mpMiddle));
207 /* add the object to the head or tail of the list */
208 void push_front(const T& val) { insert(begin(), val); }
209 void push_back(const T& val) { insert(end(), val); }
211 /* insert before the current node; returns iterator at new node */
212 iterator insert(iterator posn, const T& val)
214 _Node* newNode = new _Node(val); // alloc & copy-construct
215 newNode->setNext(posn.getNode());
216 newNode->setPrev(posn.getNode()->getPrev());
217 posn.getNode()->getPrev()->setNext(newNode);
218 posn.getNode()->setPrev(newNode);
219 return iterator(newNode);
222 /* insert a range of elements before the current node */
223 void insert(iterator posn, const_iterator first, const_iterator last) {
224 for ( ; first != last; ++first)
225 insert(posn, *first);
228 /* remove one entry; returns iterator at next node */
229 iterator erase(iterator posn) {
230 _Node* pNext = posn.getNode()->getNext();
231 _Node* pPrev = posn.getNode()->getPrev();
232 pPrev->setNext(pNext);
233 pNext->setPrev(pPrev);
234 delete posn.getNode();
235 return iterator(pNext);
238 /* remove a range of elements */
239 iterator erase(iterator first, iterator last) {
240 while (first != last)
241 erase(first++); // don't erase than incr later!
242 return iterator(last);
245 /* remove all contents of the list */
247 _Node* pCurrent = mpMiddle->getNext();
250 while (pCurrent != mpMiddle) {
251 pNext = pCurrent->getNext();
255 mpMiddle->setPrev(mpMiddle);
256 mpMiddle->setNext(mpMiddle);
260 * Measure the distance between two iterators. On exist, "first"
261 * will be equal to "last". The iterators must refer to the same
264 * FIXME: This is actually a generic iterator function. It should be a
265 * template function at the top-level with specializations for things like
266 * vector<>, which can just do pointer math). Here we limit it to
267 * _ListIterator of the same type but different constness.
271 template <class> class CL,
272 template <class> class CR
275 _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
278 while (first != last) {
287 * I want a _Node but don't need it to hold valid data. More
288 * to the point, I don't want T's constructor to fire, since it
289 * might have side-effects or require arguments. So, we do this
290 * slightly uncouth storage alloc.
293 mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
294 mpMiddle->setPrev(mpMiddle);
295 mpMiddle->setNext(mpMiddle);
299 * This node plays the role of "pointer to head" and "pointer to tail".
300 * It sits in the middle of a circular list of nodes. The iterator
301 * runs around the circle until it encounters this one.
307 * Assignment operator.
309 * The simplest way to do this would be to clear out the target list and
310 * fill it with the source. However, we can speed things along by
311 * re-using existing elements.
314 List<T>& List<T>::operator=(const List<T>& right)
317 return *this; // self-assignment
318 iterator firstDst = begin();
319 iterator lastDst = end();
320 const_iterator firstSrc = right.begin();
321 const_iterator lastSrc = right.end();
322 while (firstSrc != lastSrc && firstDst != lastDst)
323 *firstDst++ = *firstSrc++;
324 if (firstSrc == lastSrc) // ran out of elements in source?
325 erase(firstDst, lastDst); // yes, erase any extras
327 insert(lastDst, firstSrc, lastSrc); // copy remaining over
332 }; // namespace android
334 #endif // _NETD_LIST_H