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