• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 //
18 // Templated list class.  Normally we'd use STL, but we don't have that.
19 // This class mimics STL's interfaces.
20 //
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.
24 //
25 // The only class you want to use from here is "List".
26 //
27 #ifndef _LIBS_UTILS_LIST_H
28 #define _LIBS_UTILS_LIST_H
29 
30 #include <stddef.h>
31 #include <stdint.h>
32 
33 namespace android {
34 
35 /*
36  * Doubly-linked list.  Instantiate with "List<MyClass> myList".
37  *
38  * Objects added to the list are copied using the assignment operator,
39  * so this must be defined.
40  */
41 template<typename T>
42 class List
43 {
44 protected:
45     /*
46      * One element in the list.
47      */
48     class _Node {
49     public:
_Node(const T & val)50         explicit _Node(const T& val) : mVal(val) {}
~_Node()51         ~_Node() {}
getRef()52         inline T& getRef() { return mVal; }
getRef()53         inline const T& getRef() const { return mVal; }
getPrev()54         inline _Node* getPrev() const { return mpPrev; }
getNext()55         inline _Node* getNext() const { return mpNext; }
setVal(const T & val)56         inline void setVal(const T& val) { mVal = val; }
setPrev(_Node * ptr)57         inline void setPrev(_Node* ptr) { mpPrev = ptr; }
setNext(_Node * ptr)58         inline void setNext(_Node* ptr) { mpNext = ptr; }
59     private:
60         friend class List;
61         friend class _ListIterator;
62         T           mVal;
63         _Node*      mpPrev;
64         _Node*      mpNext;
65     };
66 
67     /*
68      * Iterator for walking through the list.
69      */
70 
71     template <typename TYPE>
72     struct CONST_ITERATOR {
73         typedef _Node const * NodePtr;
74         typedef const TYPE Type;
75     };
76 
77     template <typename TYPE>
78     struct NON_CONST_ITERATOR {
79         typedef _Node* NodePtr;
80         typedef TYPE Type;
81     };
82 
83     template<
84         typename U,
85         template <class> class Constness
86     >
87     class _ListIterator {
88         typedef _ListIterator<U, Constness>     _Iter;
89         typedef typename Constness<U>::NodePtr  _NodePtr;
90         typedef typename Constness<U>::Type     _Type;
91 
_ListIterator(_NodePtr ptr)92         explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
93 
94     public:
_ListIterator()95         _ListIterator() {}
_ListIterator(const _Iter & rhs)96         _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
~_ListIterator()97         ~_ListIterator() {}
98 
99         // this will handle conversions from iterator to const_iterator
100         // (and also all convertible iterators)
101         // Here, in this implementation, the iterators can be converted
102         // if the nodes can be converted
103         template<typename V> explicit
_ListIterator(const V & rhs)104         _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
105 
106 
107         /*
108          * Dereference operator.  Used to get at the juicy insides.
109          */
110         _Type& operator*() const { return mpNode->getRef(); }
111         _Type* operator->() const { return &(mpNode->getRef()); }
112 
113         /*
114          * Iterator comparison.
115          */
116         inline bool operator==(const _Iter& right) const {
117             return mpNode == right.mpNode; }
118 
119         inline bool operator!=(const _Iter& right) const {
120             return mpNode != right.mpNode; }
121 
122         /*
123          * handle comparisons between iterator and const_iterator
124          */
125         template<typename OTHER>
126         inline bool operator==(const OTHER& right) const {
127             return mpNode == right.mpNode; }
128 
129         template<typename OTHER>
130         inline bool operator!=(const OTHER& right) const {
131             return mpNode != right.mpNode; }
132 
133         /*
134          * Incr/decr, used to move through the list.
135          */
136         inline _Iter& operator++() {     // pre-increment
137             mpNode = mpNode->getNext();
138             return *this;
139         }
140         const _Iter operator++(int) {    // post-increment
141             _Iter tmp(*this);
142             mpNode = mpNode->getNext();
143             return tmp;
144         }
145         inline _Iter& operator--() {     // pre-increment
146             mpNode = mpNode->getPrev();
147             return *this;
148         }
149         const _Iter operator--(int) {   // post-increment
150             _Iter tmp(*this);
151             mpNode = mpNode->getPrev();
152             return tmp;
153         }
154 
getNode()155         inline _NodePtr getNode() const { return mpNode; }
156 
157         _NodePtr mpNode;    /* should be private, but older gcc fails */
158     private:
159         friend class List;
160     };
161 
162 public:
List()163     List() {
164         prep();
165     }
List(const List<T> & src)166     List(const List<T>& src) {      // copy-constructor
167         prep();
168         insert(begin(), src.begin(), src.end());
169     }
~List()170     virtual ~List() {
171         clear();
172         delete[] (unsigned char*) mpMiddle;
173     }
174 
175     typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
176     typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
177 
178     List<T>& operator=(const List<T>& right);
179 
180     /* returns true if the list is empty */
empty()181     inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
182 
183     /* return #of elements in list */
size()184     size_t size() const {
185         return size_t(distance(begin(), end()));
186     }
187 
188     /*
189      * Return the first element or one past the last element.  The
190      * _Node* we're returning is converted to an "iterator" by a
191      * constructor in _ListIterator.
192      */
begin()193     inline iterator begin() {
194         return iterator(mpMiddle->getNext());
195     }
begin()196     inline const_iterator begin() const {
197         return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
198     }
end()199     inline iterator end() {
200         return iterator(mpMiddle);
201     }
end()202     inline const_iterator end() const {
203         return const_iterator(const_cast<_Node const*>(mpMiddle));
204     }
205 
206     /* add the object to the head or tail of the list */
push_front(const T & val)207     void push_front(const T& val) { insert(begin(), val); }
push_back(const T & val)208     void push_back(const T& val) { insert(end(), val); }
209 
210     /* insert before the current node; returns iterator at new node */
insert(iterator posn,const T & val)211     iterator insert(iterator posn, const T& val)
212     {
213         _Node* newNode = new _Node(val);        // alloc & copy-construct
214         newNode->setNext(posn.getNode());
215         newNode->setPrev(posn.getNode()->getPrev());
216         posn.getNode()->getPrev()->setNext(newNode);
217         posn.getNode()->setPrev(newNode);
218         return iterator(newNode);
219     }
220 
221     /* insert a range of elements before the current node */
insert(iterator posn,const_iterator first,const_iterator last)222     void insert(iterator posn, const_iterator first, const_iterator last) {
223         for ( ; first != last; ++first)
224             insert(posn, *first);
225     }
226 
227     /* remove one entry; returns iterator at next node */
erase(iterator posn)228     iterator erase(iterator posn) {
229         _Node* pNext = posn.getNode()->getNext();
230         _Node* pPrev = posn.getNode()->getPrev();
231         pPrev->setNext(pNext);
232         pNext->setPrev(pPrev);
233         delete posn.getNode();
234         return iterator(pNext);
235     }
236 
237     /* remove a range of elements */
erase(iterator first,iterator last)238     iterator erase(iterator first, iterator last) {
239         while (first != last)
240             erase(first++);     // don't erase than incr later!
241         return iterator(last);
242     }
243 
244     /* remove all contents of the list */
clear()245     void clear() {
246         _Node* pCurrent = mpMiddle->getNext();
247         _Node* pNext;
248 
249         while (pCurrent != mpMiddle) {
250             pNext = pCurrent->getNext();
251             delete pCurrent;
252             pCurrent = pNext;
253         }
254         mpMiddle->setPrev(mpMiddle);
255         mpMiddle->setNext(mpMiddle);
256     }
257 
258     /*
259      * Measure the distance between two iterators.  On exist, "first"
260      * will be equal to "last".  The iterators must refer to the same
261      * list.
262      *
263      * FIXME: This is actually a generic iterator function. It should be a
264      * template function at the top-level with specializations for things like
265      * vector<>, which can just do pointer math). Here we limit it to
266      * _ListIterator of the same type but different constness.
267      */
268     template<
269         typename U,
270         template <class> class CL,
271         template <class> class CR
272     >
distance(_ListIterator<U,CL> first,_ListIterator<U,CR> last)273     ptrdiff_t distance(
274             _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
275     {
276         ptrdiff_t count = 0;
277         while (first != last) {
278             ++first;
279             ++count;
280         }
281         return count;
282     }
283 
284 private:
285     /*
286      * I want a _Node but don't need it to hold valid data.  More
287      * to the point, I don't want T's constructor to fire, since it
288      * might have side-effects or require arguments.  So, we do this
289      * slightly uncouth storage alloc.
290      */
prep()291     void prep() {
292         mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
293         mpMiddle->setPrev(mpMiddle);
294         mpMiddle->setNext(mpMiddle);
295     }
296 
297     /*
298      * This node plays the role of "pointer to head" and "pointer to tail".
299      * It sits in the middle of a circular list of nodes.  The iterator
300      * runs around the circle until it encounters this one.
301      */
302     _Node*      mpMiddle;
303 };
304 
305 /*
306  * Assignment operator.
307  *
308  * The simplest way to do this would be to clear out the target list and
309  * fill it with the source.  However, we can speed things along by
310  * re-using existing elements.
311  */
312 template<class T>
313 List<T>& List<T>::operator=(const List<T>& right)
314 {
315     if (this == &right)
316         return *this;       // self-assignment
317     iterator firstDst = begin();
318     iterator lastDst = end();
319     const_iterator firstSrc = right.begin();
320     const_iterator lastSrc = right.end();
321     while (firstSrc != lastSrc && firstDst != lastDst)
322         *firstDst++ = *firstSrc++;
323     if (firstSrc == lastSrc)        // ran out of elements in source?
324         erase(firstDst, lastDst);   // yes, erase any extras
325     else
326         insert(lastDst, firstSrc, lastSrc);     // copy remaining over
327     return *this;
328 }
329 
330 }; // namespace android
331 
332 #endif // _LIBS_UTILS_LIST_H
333