1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifndef __LINKED_LIST_H 30 #define __LINKED_LIST_H 31 32 #include "private/bionic_macros.h" 33 34 template<typename T> 35 struct LinkedListEntry { 36 LinkedListEntry<T>* next; 37 T* element; 38 }; 39 40 // ForwardInputIterator 41 template<typename T> 42 class LinkedListIterator { 43 public: LinkedListIterator()44 LinkedListIterator() : entry_(nullptr) {} LinkedListIterator(const LinkedListIterator<T> & that)45 LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {} LinkedListIterator(LinkedListEntry<T> * entry)46 explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {} 47 48 LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) { 49 entry_ = that.entry_; 50 return *this; 51 } 52 53 LinkedListIterator<T>& operator++() { 54 entry_ = entry_->next; 55 return *this; 56 } 57 58 T* const operator*() { 59 return entry_->element; 60 } 61 62 bool operator==(const LinkedListIterator<T>& that) const { 63 return entry_ == that.entry_; 64 } 65 66 bool operator!=(const LinkedListIterator<T>& that) const { 67 return entry_ != that.entry_; 68 } 69 70 private: 71 LinkedListEntry<T> *entry_; 72 }; 73 74 /* 75 * Represents linked list of objects of type T 76 */ 77 template<typename T, typename Allocator> 78 class LinkedList { 79 public: 80 typedef LinkedListIterator<T> iterator; 81 typedef T* value_type; 82 LinkedList()83 LinkedList() : head_(nullptr), tail_(nullptr) {} ~LinkedList()84 ~LinkedList() { 85 clear(); 86 } 87 LinkedList(LinkedList && that)88 LinkedList(LinkedList&& that) { 89 this->head_ = that.head_; 90 this->tail_ = that.tail_; 91 that.head_ = that.tail_ = nullptr; 92 } 93 push_front(T * const element)94 void push_front(T* const element) { 95 LinkedListEntry<T>* new_entry = Allocator::alloc(); 96 new_entry->next = head_; 97 new_entry->element = element; 98 head_ = new_entry; 99 if (tail_ == nullptr) { 100 tail_ = new_entry; 101 } 102 } 103 push_back(T * const element)104 void push_back(T* const element) { 105 LinkedListEntry<T>* new_entry = Allocator::alloc(); 106 new_entry->next = nullptr; 107 new_entry->element = element; 108 if (tail_ == nullptr) { 109 tail_ = head_ = new_entry; 110 } else { 111 tail_->next = new_entry; 112 tail_ = new_entry; 113 } 114 } 115 pop_front()116 T* pop_front() { 117 if (head_ == nullptr) { 118 return nullptr; 119 } 120 121 LinkedListEntry<T>* entry = head_; 122 T* element = entry->element; 123 head_ = entry->next; 124 Allocator::free(entry); 125 126 if (head_ == nullptr) { 127 tail_ = nullptr; 128 } 129 130 return element; 131 } 132 front()133 T* front() const { 134 if (head_ == nullptr) { 135 return nullptr; 136 } 137 138 return head_->element; 139 } 140 clear()141 void clear() { 142 while (head_ != nullptr) { 143 LinkedListEntry<T>* p = head_; 144 head_ = head_->next; 145 Allocator::free(p); 146 } 147 148 tail_ = nullptr; 149 } 150 empty()151 bool empty() { 152 return (head_ == nullptr); 153 } 154 155 template<typename F> for_each(F action)156 void for_each(F action) const { 157 visit([&] (T* si) { 158 action(si); 159 return true; 160 }); 161 } 162 163 template<typename F> visit(F action)164 bool visit(F action) const { 165 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 166 if (!action(e->element)) { 167 return false; 168 } 169 } 170 return true; 171 } 172 173 template<typename F> remove_if(F predicate)174 void remove_if(F predicate) { 175 for (LinkedListEntry<T>* e = head_, *p = nullptr; e != nullptr;) { 176 if (predicate(e->element)) { 177 LinkedListEntry<T>* next = e->next; 178 if (p == nullptr) { 179 head_ = next; 180 } else { 181 p->next = next; 182 } 183 184 if (tail_ == e) { 185 tail_ = p; 186 } 187 188 Allocator::free(e); 189 190 e = next; 191 } else { 192 p = e; 193 e = e->next; 194 } 195 } 196 } 197 remove(T * element)198 void remove(T* element) { 199 remove_if([&](T* e) { 200 return e == element; 201 }); 202 } 203 204 template<typename F> find_if(F predicate)205 T* find_if(F predicate) const { 206 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 207 if (predicate(e->element)) { 208 return e->element; 209 } 210 } 211 212 return nullptr; 213 } 214 begin()215 iterator begin() const { 216 return iterator(head_); 217 } 218 end()219 iterator end() const { 220 return iterator(nullptr); 221 } 222 find(T * value)223 iterator find(T* value) const { 224 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 225 if (e->element == value) { 226 return iterator(e); 227 } 228 } 229 230 return end(); 231 } 232 copy_to_array(T * array[],size_t array_length)233 size_t copy_to_array(T* array[], size_t array_length) const { 234 size_t sz = 0; 235 for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) { 236 array[sz++] = e->element; 237 } 238 239 return sz; 240 } 241 contains(const T * el)242 bool contains(const T* el) const { 243 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 244 if (e->element == el) { 245 return true; 246 } 247 } 248 return false; 249 } 250 make_list(T * const element)251 static LinkedList make_list(T* const element) { 252 LinkedList<T, Allocator> one_element_list; 253 one_element_list.push_back(element); 254 return one_element_list; 255 } 256 257 private: 258 LinkedListEntry<T>* head_; 259 LinkedListEntry<T>* tail_; 260 DISALLOW_COPY_AND_ASSIGN(LinkedList); 261 }; 262 263 #endif // __LINKED_LIST_H 264