1// Copyright 2014 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 13namespace 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. 24template <class T> 25class 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. 53const 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// 61class 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// 146template <class T> 147class 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 196template <class T> 197int 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 205template <class T> 206void 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 222template <class T> 223void 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 235template <class T> 236void 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 243template <class T> 244void 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. 257template <class T> 258class 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 281template <class T> 282bool 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 291template <class T> 292bool 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