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