Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CRAZY_LINKER_UTIL_H
      6 #define CRAZY_LINKER_UTIL_H
      7 
      8 #include <fcntl.h>
      9 #include <stdarg.h>
     10 #include <stdio.h>
     11 #include <unistd.h>
     12 
     13 namespace crazy {
     14 
     15 // Helper macro to loop around EINTR errors in syscalls.
     16 #define HANDLE_EINTR(expr) TEMP_FAILURE_RETRY(expr)
     17 
     18 // Helper macro to tag unused variables. Use in the declaration, between
     19 // the type and name, as in:
     20 //     int CRAZY_UNUSED my_var = 0;
     21 #define CRAZY_UNUSED __attribute__((unused))
     22 
     23 // Helper scoped pointer class.
     24 template <class T>
     25 class ScopedPtr {
     26  public:
     27   ScopedPtr() : ptr_(NULL) {}
     28   explicit ScopedPtr(T* ptr) : ptr_(ptr) {}
     29   ~ScopedPtr() { Reset(NULL); }
     30 
     31   T* Release() {
     32     T* ret = ptr_;
     33     ptr_ = NULL;
     34     return ret;
     35   }
     36 
     37   void Reset(T* ptr) {
     38     if (ptr_)
     39       delete ptr_;
     40     ptr_ = ptr;
     41   }
     42 
     43   T* Get() { return ptr_; }
     44   T& operator*() { return *ptr_; }
     45   T* operator->() { return ptr_; }
     46 
     47  private:
     48   T* ptr_;
     49 };
     50 
     51 // Return the base name from a file path. Important: this is a pointer
     52 // into the original string.
     53 const char* GetBaseNamePtr(const char* path);
     54 
     55 // Helper class used to implement a string. Similar to std::string
     56 // without all the crazy iterator / iostream stuff.
     57 //
     58 // Required because crazy linker should only link against the system
     59 // libstdc++ that only provides new/delete.
     60 //
     61 class String {
     62  public:
     63   String();
     64   String(const char* str, size_t len);
     65   String(const String& other);
     66   explicit String(const char* str);
     67   explicit String(char ch);
     68 
     69   ~String();
     70 
     71   const char* c_str() const { return ptr_; }
     72   char* ptr() { return ptr_; }
     73   size_t size() const { return size_; }
     74   size_t capacity() const { return capacity_; }
     75 
     76   bool IsEmpty() const { return size_ == 0; }
     77 
     78   char& operator[](size_t index) { return ptr_[index]; }
     79 
     80   String& operator=(const String& other) {
     81     Assign(other.ptr_, other.size_);
     82     return *this;
     83   }
     84 
     85   String& operator=(const char* str) {
     86     Assign(str, strlen(str));
     87     return *this;
     88   }
     89 
     90   String& operator=(char ch) {
     91     Assign(&ch, 1);
     92     return *this;
     93   }
     94 
     95   String& operator+=(const String& other) {
     96     Append(other);
     97     return *this;
     98   }
     99 
    100   String& operator+=(const char* str) {
    101     Append(str, strlen(str));
    102     return *this;
    103   }
    104 
    105   String& operator+=(char ch) {
    106     Append(&ch, 1);
    107     return *this;
    108   }
    109 
    110   void Resize(size_t new_size);
    111 
    112   void Reserve(size_t new_capacity);
    113 
    114   void Assign(const char* str, size_t len);
    115 
    116   void Assign(const String& other) { Assign(other.ptr_, other.size_); }
    117 
    118   void Assign(const char* str) { Assign(str, strlen(str)); }
    119 
    120   void Append(const char* str, size_t len);
    121 
    122   void Append(const String& other) { Append(other.ptr_, other.size_); }
    123 
    124   void Append(const char* str) { Append(str, strlen(str)); }
    125 
    126  private:
    127   void Init(void) {
    128     ptr_ = const_cast<char*>(kEmpty);
    129     size_ = 0;
    130     capacity_ = 0;
    131   }
    132 
    133   static const char kEmpty[];
    134 
    135   char* ptr_;
    136   size_t size_;
    137   size_t capacity_;
    138 };
    139 
    140 // Helper template used to implement a simple vector or POD-struct items.
    141 // I.e. this uses memmove() to move items during insertion / removal.
    142 //
    143 // Required because crazy linker should only link against the system
    144 // libstdc++ which only provides new/delete.
    145 //
    146 template <class T>
    147 class Vector {
    148  public:
    149   Vector() : items_(0), count_(0), capacity_(0) {}
    150   ~Vector() { free(items_); }
    151 
    152   T& operator[](size_t index) { return items_[index]; }
    153 
    154   bool IsEmpty() const { return count_ == 0; }
    155 
    156   void PushBack(T item) { InsertAt(static_cast<int>(count_), item); }
    157 
    158   T PopFirst() {
    159     T result = items_[0];
    160     RemoveAt(0);
    161     return result;
    162   }
    163 
    164   T PopLast() {
    165     T result = items_[count_ - 1];
    166     Resize(count_ - 1);
    167     return result;
    168   }
    169 
    170   void Remove(T item) {
    171     int index = IndexOf(item);
    172     if (index >= 0)
    173       RemoveAt(index);
    174   }
    175 
    176   void InsertAt(int index, T item);
    177 
    178   void RemoveAt(int index);
    179 
    180   int IndexOf(T item) const;
    181 
    182   bool Has(T item) const { return IndexOf(item) >= 0; }
    183 
    184   size_t GetCount() const { return count_; }
    185 
    186   void Reserve(size_t new_capacity);
    187 
    188   void Resize(size_t new_count);
    189 
    190  private:
    191   T* items_;
    192   size_t count_;
    193   size_t capacity_;
    194 };
    195 
    196 template <class T>
    197 int Vector<T>::IndexOf(T item) const {
    198   for (size_t n = 0; n < count_; ++n) {
    199     if (items_[n] == item)
    200       return static_cast<int>(n);
    201   }
    202   return -1;
    203 }
    204 
    205 template <class T>
    206 void Vector<T>::InsertAt(int index, T item) {
    207   if (count_ >= capacity_)
    208     Reserve(capacity_ + (capacity_ >> 1) + 4);
    209 
    210   if (index < 0)
    211     index = 0;
    212   size_t n = static_cast<size_t>(index);
    213   if (n > count_)
    214     n = count_;
    215   else
    216     memmove(items_ + n + 1, items_ + n, (count_ - n) * sizeof(T));
    217 
    218   items_[n] = item;
    219   count_++;
    220 }
    221 
    222 template <class T>
    223 void Vector<T>::RemoveAt(int index) {
    224   if (index < 0)
    225     return;
    226 
    227   size_t n = static_cast<size_t>(index);
    228   if (n >= count_)
    229     return;
    230 
    231   memmove(items_ + n, items_ + n + 1, (count_ - n - 1) * sizeof(T));
    232   count_--;
    233 }
    234 
    235 template <class T>
    236 void Vector<T>::Reserve(size_t new_capacity) {
    237   items_ = reinterpret_cast<T*>(realloc(items_, new_capacity * sizeof(T)));
    238   capacity_ = new_capacity;
    239   if (count_ > capacity_)
    240     count_ = capacity_;
    241 }
    242 
    243 template <class T>
    244 void Vector<T>::Resize(size_t new_size) {
    245   if (new_size > capacity_)
    246     Reserve(new_size);
    247 
    248   if (new_size > count_)
    249     memset(items_ + count_, 0, (new_size - count_) * sizeof(T));
    250 
    251   count_ = new_size;
    252 }
    253 
    254 // Helper template class to implement a set.
    255 // Given that the crazy linker doesn't expect to deal with hundreds
    256 // of libraries at the same time, implement it with a vector.
    257 template <class T>
    258 class Set {
    259  public:
    260   Set() : items_() {}
    261   ~Set() {}
    262 
    263   // Returns the number of items in the set.
    264   size_t GetCount() const { return items_.GetCount(); }
    265 
    266   bool IsEmpty() const { return items_.IsEmpty(); }
    267 
    268   // Returns true iff the set contains a given item.
    269   bool Has(T item) const { return items_.Has(item); }
    270 
    271   // Add an item to the set. Returns false iff the item was already in it.
    272   bool Add(T item);
    273 
    274   // Delete an item from the set. Returns false iff the item was not in it.
    275   bool Del(T item);
    276 
    277  private:
    278   Vector<T> items_;
    279 };
    280 
    281 template <class T>
    282 bool Set<T>::Add(T item) {
    283   int idx = items_.IndexOf(item);
    284   if (idx >= 0)
    285     return false;
    286 
    287   items_.PushBack(item);
    288   return true;
    289 }
    290 
    291 template <class T>
    292 bool Set<T>::Del(T item) {
    293   int idx = items_.IndexOf(item);
    294   if (idx < 0)
    295     return false;
    296   items_.RemoveAt(idx);
    297   return true;
    298 }
    299 
    300 }  // namespace crazy
    301 
    302 #endif  // CRAZY_LINKER_UTIL_H
    303