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 _SYSUTILS_LIST_H 28 #define _SYSUTILS_LIST_H 29 30 #include <stddef.h> 31 #include <stdint.h> 32 33 namespace android { 34 namespace sysutils { 35 36 /* 37 * Doubly-linked list. Instantiate with "List<MyClass> myList". 38 * 39 * Objects added to the list are copied using the assignment operator, 40 * so this must be defined. 41 */ 42 template<typename T> 43 class List 44 { 45 protected: 46 /* 47 * One element in the list. 48 */ 49 class _Node { 50 public: _Node(const T & val)51 explicit _Node(const T& val) : mVal(val) {} ~_Node()52 ~_Node() {} getRef()53 inline T& getRef() { return mVal; } getRef()54 inline const T& getRef() const { return mVal; } getPrev()55 inline _Node* getPrev() const { return mpPrev; } getNext()56 inline _Node* getNext() const { return mpNext; } setVal(const T & val)57 inline void setVal(const T& val) { mVal = val; } setPrev(_Node * ptr)58 inline void setPrev(_Node* ptr) { mpPrev = ptr; } setNext(_Node * ptr)59 inline void setNext(_Node* ptr) { mpNext = ptr; } 60 private: 61 friend class List; 62 friend class _ListIterator; 63 T mVal; 64 _Node* mpPrev; 65 _Node* mpNext; 66 }; 67 68 /* 69 * Iterator for walking through the list. 70 */ 71 72 template <typename TYPE> 73 struct CONST_ITERATOR { 74 typedef _Node const * NodePtr; 75 typedef const TYPE Type; 76 }; 77 78 template <typename TYPE> 79 struct NON_CONST_ITERATOR { 80 typedef _Node* NodePtr; 81 typedef TYPE Type; 82 }; 83 84 template< 85 typename U, 86 template <class> class Constness 87 > 88 class _ListIterator { 89 typedef _ListIterator<U, Constness> _Iter; 90 typedef typename Constness<U>::NodePtr _NodePtr; 91 typedef typename Constness<U>::Type _Type; 92 _ListIterator(_NodePtr ptr)93 explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {} 94 95 public: _ListIterator()96 _ListIterator() {} _ListIterator(const _Iter & rhs)97 _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {} ~_ListIterator()98 ~_ListIterator() {} 99 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 _ListIterator(const V & rhs)105 _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {} 106 107 108 /* 109 * Dereference operator. Used to get at the juicy insides. 110 */ 111 _Type& operator*() const { return mpNode->getRef(); } 112 _Type* operator->() const { return &(mpNode->getRef()); } 113 114 /* 115 * Iterator comparison. 116 */ 117 inline bool operator==(const _Iter& right) const { 118 return mpNode == right.mpNode; } 119 120 inline bool operator!=(const _Iter& right) const { 121 return mpNode != right.mpNode; } 122 123 /* 124 * handle comparisons between iterator and const_iterator 125 */ 126 template<typename OTHER> 127 inline bool operator==(const OTHER& right) const { 128 return mpNode == right.mpNode; } 129 130 template<typename OTHER> 131 inline bool operator!=(const OTHER& right) const { 132 return mpNode != right.mpNode; } 133 134 /* 135 * Incr/decr, used to move through the list. 136 */ 137 inline _Iter& operator++() { // pre-increment 138 mpNode = mpNode->getNext(); 139 return *this; 140 } 141 const _Iter operator++(int) { // post-increment 142 _Iter tmp(*this); 143 mpNode = mpNode->getNext(); 144 return tmp; 145 } 146 inline _Iter& operator--() { // pre-increment 147 mpNode = mpNode->getPrev(); 148 return *this; 149 } 150 const _Iter operator--(int) { // post-increment 151 _Iter tmp(*this); 152 mpNode = mpNode->getPrev(); 153 return tmp; 154 } 155 getNode()156 inline _NodePtr getNode() const { return mpNode; } 157 158 _NodePtr mpNode; /* should be private, but older gcc fails */ 159 private: 160 friend class List; 161 }; 162 163 public: List()164 List() { 165 prep(); 166 } List(const List<T> & src)167 List(const List<T>& src) { // copy-constructor 168 prep(); 169 insert(begin(), src.begin(), src.end()); 170 } ~List()171 virtual ~List() { 172 clear(); 173 delete[] (unsigned char*) mpMiddle; 174 } 175 176 typedef _ListIterator<T, NON_CONST_ITERATOR> iterator; 177 typedef _ListIterator<T, CONST_ITERATOR> const_iterator; 178 179 List<T>& operator=(const List<T>& right); 180 181 /* returns true if the list is empty */ empty()182 inline bool empty() const { return mpMiddle->getNext() == mpMiddle; } 183 184 /* return #of elements in list */ size()185 size_t size() const { 186 return size_t(distance(begin(), end())); 187 } 188 189 /* 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. 193 */ begin()194 inline iterator begin() { 195 return iterator(mpMiddle->getNext()); 196 } begin()197 inline const_iterator begin() const { 198 return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 199 } end()200 inline iterator end() { 201 return iterator(mpMiddle); 202 } end()203 inline const_iterator end() const { 204 return const_iterator(const_cast<_Node const*>(mpMiddle)); 205 } 206 207 /* add the object to the head or tail of the list */ push_front(const T & val)208 void push_front(const T& val) { insert(begin(), val); } push_back(const T & val)209 void push_back(const T& val) { insert(end(), val); } 210 211 /* insert before the current node; returns iterator at new node */ insert(iterator posn,const T & val)212 iterator insert(iterator posn, const T& val) 213 { 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); 220 } 221 222 /* insert a range of elements before the current node */ insert(iterator posn,const_iterator first,const_iterator last)223 void insert(iterator posn, const_iterator first, const_iterator last) { 224 for ( ; first != last; ++first) 225 insert(posn, *first); 226 } 227 228 /* remove one entry; returns iterator at next node */ erase(iterator posn)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); 236 } 237 238 /* remove a range of elements */ erase(iterator first,iterator last)239 iterator erase(iterator first, iterator last) { 240 while (first != last) 241 erase(first++); // don't erase than incr later! 242 return iterator(last); 243 } 244 245 /* remove all contents of the list */ clear()246 void clear() { 247 _Node* pCurrent = mpMiddle->getNext(); 248 _Node* pNext; 249 250 while (pCurrent != mpMiddle) { 251 pNext = pCurrent->getNext(); 252 delete pCurrent; 253 pCurrent = pNext; 254 } 255 mpMiddle->setPrev(mpMiddle); 256 mpMiddle->setNext(mpMiddle); 257 } 258 259 /* 260 * Measure the distance between two iterators. On exist, "first" 261 * will be equal to "last". The iterators must refer to the same 262 * list. 263 * 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. 268 */ 269 template< 270 typename U, 271 template <class> class CL, 272 template <class> class CR 273 > distance(_ListIterator<U,CL> first,_ListIterator<U,CR> last)274 ptrdiff_t distance( 275 _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 276 { 277 ptrdiff_t count = 0; 278 while (first != last) { 279 ++first; 280 ++count; 281 } 282 return count; 283 } 284 285 private: 286 /* 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. 291 */ prep()292 void prep() { 293 mpMiddle = (_Node*) new unsigned char[sizeof(_Node)]; 294 mpMiddle->setPrev(mpMiddle); 295 mpMiddle->setNext(mpMiddle); 296 } 297 298 /* 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. 302 */ 303 _Node* mpMiddle; 304 }; 305 306 /* 307 * Assignment operator. 308 * 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. 312 */ 313 template<class T> 314 List<T>& List<T>::operator=(const List<T>& right) 315 { 316 if (this == &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 326 else 327 insert(lastDst, firstSrc, lastSrc); // copy remaining over 328 return *this; 329 } 330 331 }; // namespace sysutils 332 }; // namespace android 333 334 #endif // _SYSUTILS_LIST_H 335