media/omx-plugin/include/ics/utils/List.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial