• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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