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 #pragma once 30 31 #include <android-base/macros.h> 32 33 template<typename T> 34 struct LinkedListEntry { 35 LinkedListEntry<T>* next; 36 T* element; 37 }; 38 39 // ForwardInputIterator 40 template<typename T> 41 class LinkedListIterator { 42 public: LinkedListIterator()43 LinkedListIterator() : entry_(nullptr) {} LinkedListIterator(const LinkedListIterator<T> & that)44 LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {} LinkedListIterator(LinkedListEntry<T> * entry)45 explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {} 46 47 LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) { 48 entry_ = that.entry_; 49 return *this; 50 } 51 52 LinkedListIterator<T>& operator++() { 53 entry_ = entry_->next; 54 return *this; 55 } 56 57 T* const operator*() { 58 return entry_->element; 59 } 60 61 bool operator==(const LinkedListIterator<T>& that) const { 62 return entry_ == that.entry_; 63 } 64 65 bool operator!=(const LinkedListIterator<T>& that) const { 66 return entry_ != that.entry_; 67 } 68 69 private: 70 LinkedListEntry<T> *entry_; 71 }; 72 73 /* 74 * Represents linked list of objects of type T 75 */ 76 template<typename T, typename Allocator> 77 class LinkedList { 78 public: 79 typedef LinkedListIterator<T> iterator; 80 typedef T* value_type; 81 LinkedList()82 LinkedList() : head_(nullptr), tail_(nullptr) {} ~LinkedList()83 ~LinkedList() { 84 clear(); 85 } 86 LinkedList(LinkedList && that)87 LinkedList(LinkedList&& that) noexcept { 88 this->head_ = that.head_; 89 this->tail_ = that.tail_; 90 that.head_ = that.tail_ = nullptr; 91 } 92 push_front(T * const element)93 void push_front(T* const element) { 94 LinkedListEntry<T>* new_entry = Allocator::alloc(); 95 new_entry->next = head_; 96 new_entry->element = element; 97 head_ = new_entry; 98 if (tail_ == nullptr) { 99 tail_ = new_entry; 100 } 101 } 102 push_back(T * const element)103 void push_back(T* const element) { 104 LinkedListEntry<T>* new_entry = Allocator::alloc(); 105 new_entry->next = nullptr; 106 new_entry->element = element; 107 if (tail_ == nullptr) { 108 tail_ = head_ = new_entry; 109 } else { 110 tail_->next = new_entry; 111 tail_ = new_entry; 112 } 113 } 114 pop_front()115 T* pop_front() { 116 if (head_ == nullptr) { 117 return nullptr; 118 } 119 120 LinkedListEntry<T>* entry = head_; 121 T* element = entry->element; 122 head_ = entry->next; 123 Allocator::free(entry); 124 125 if (head_ == nullptr) { 126 tail_ = nullptr; 127 } 128 129 return element; 130 } 131 front()132 T* front() const { 133 if (head_ == nullptr) { 134 return nullptr; 135 } 136 137 return head_->element; 138 } 139 clear()140 void clear() { 141 while (head_ != nullptr) { 142 LinkedListEntry<T>* p = head_; 143 head_ = head_->next; 144 Allocator::free(p); 145 } 146 147 tail_ = nullptr; 148 } 149 empty()150 bool empty() { 151 return (head_ == nullptr); 152 } 153 154 template<typename F> for_each(F action)155 void for_each(F action) const { 156 visit([&] (T* si) { 157 action(si); 158 return true; 159 }); 160 } 161 162 template<typename F> visit(F action)163 bool visit(F action) const { 164 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 165 if (!action(e->element)) { 166 return false; 167 } 168 } 169 return true; 170 } 171 172 template<typename F> remove_if(F predicate)173 void remove_if(F predicate) { 174 for (LinkedListEntry<T>* e = head_, *p = nullptr; e != nullptr;) { 175 if (predicate(e->element)) { 176 LinkedListEntry<T>* next = e->next; 177 if (p == nullptr) { 178 head_ = next; 179 } else { 180 p->next = next; 181 } 182 183 if (tail_ == e) { 184 tail_ = p; 185 } 186 187 Allocator::free(e); 188 189 e = next; 190 } else { 191 p = e; 192 e = e->next; 193 } 194 } 195 } 196 remove(T * element)197 void remove(T* element) { 198 remove_if([&](T* e) { 199 return e == element; 200 }); 201 } 202 203 template<typename F> find_if(F predicate)204 T* find_if(F predicate) const { 205 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 206 if (predicate(e->element)) { 207 return e->element; 208 } 209 } 210 211 return nullptr; 212 } 213 begin()214 iterator begin() const { 215 return iterator(head_); 216 } 217 end()218 iterator end() const { 219 return iterator(nullptr); 220 } 221 find(T * value)222 iterator find(T* value) const { 223 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 224 if (e->element == value) { 225 return iterator(e); 226 } 227 } 228 229 return end(); 230 } 231 copy_to_array(T * array[],size_t array_length)232 size_t copy_to_array(T* array[], size_t array_length) const { 233 size_t sz = 0; 234 for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) { 235 array[sz++] = e->element; 236 } 237 238 return sz; 239 } 240 contains(const T * el)241 bool contains(const T* el) const { 242 for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) { 243 if (e->element == el) { 244 return true; 245 } 246 } 247 return false; 248 } 249 make_list(T * const element)250 static LinkedList make_list(T* const element) { 251 LinkedList<T, Allocator> one_element_list; 252 one_element_list.push_back(element); 253 return one_element_list; 254 } 255 256 private: 257 LinkedListEntry<T>* head_; 258 LinkedListEntry<T>* tail_; 259 DISALLOW_COPY_AND_ASSIGN(LinkedList); 260 }; 261