Home | History | Annotate | Download | only in linker
      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:
     44   LinkedListIterator() : entry_(nullptr) {}
     45   LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.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 
     83   LinkedList() : head_(nullptr), tail_(nullptr) {}
     84   ~LinkedList() {
     85     clear();
     86   }
     87 
     88   LinkedList(LinkedList&& that) {
     89     this->head_ = that.head_;
     90     this->tail_ = that.tail_;
     91     that.head_ = that.tail_ = nullptr;
     92   }
     93 
     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 
    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 
    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 
    133   T* front() const {
    134     if (head_ == nullptr) {
    135       return nullptr;
    136     }
    137 
    138     return head_->element;
    139   }
    140 
    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 
    151   bool empty() {
    152     return (head_ == nullptr);
    153   }
    154 
    155   template<typename F>
    156   void for_each(F action) const {
    157     visit([&] (T* si) {
    158       action(si);
    159       return true;
    160     });
    161   }
    162 
    163   template<typename F>
    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>
    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 
    198   void remove(T* element) {
    199     remove_if([&](T* e) {
    200       return e == element;
    201     });
    202   }
    203 
    204   template<typename F>
    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 
    215   iterator begin() const {
    216     return iterator(head_);
    217   }
    218 
    219   iterator end() const {
    220     return iterator(nullptr);
    221   }
    222 
    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 
    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 
    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 
    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