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