Index: third_party/crazy_linker/crazy_linker/src/crazy_linker_util.h |
diff --git a/third_party/crazy_linker/crazy_linker/src/crazy_linker_util.h b/third_party/crazy_linker/crazy_linker/src/crazy_linker_util.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5950ade2abc34815fb3c5e6bacd584eab58bedfd |
--- /dev/null |
+++ b/third_party/crazy_linker/crazy_linker/src/crazy_linker_util.h |
@@ -0,0 +1,325 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef CRAZY_LINKER_UTIL_H |
+#define CRAZY_LINKER_UTIL_H |
+ |
+#include <fcntl.h> |
+#include <stdarg.h> |
+#include <stdio.h> |
+#include <unistd.h> |
+ |
+namespace crazy { |
+ |
+// Helper macro to loop around EINTR errors in syscalls. |
+#define HANDLE_EINTR(expr) TEMP_FAILURE_RETRY(expr) |
+ |
+// Helper macro to tag unused variables. Use in the declaration, between |
+// the type and name, as in: |
+// int CRAZY_UNUSED my_var = 0; |
+#define CRAZY_UNUSED __attribute__((unused)) |
+ |
+// Helper scoped pointer class. |
+template <class T> |
+class ScopedPtr { |
+ public: |
+ ScopedPtr() : ptr_(NULL) {} |
+ explicit ScopedPtr(T* ptr) : ptr_(ptr) {} |
+ ~ScopedPtr() { |
+ Reset(NULL); |
+ } |
+ |
+ T* Release() { |
+ T* ret = ptr_; |
+ ptr_ = NULL; |
+ return ret; |
+ } |
+ |
+ void Reset(T* ptr) { |
+ if (ptr_) |
+ delete ptr_; |
+ ptr_ = ptr; |
+ } |
+ |
+ T* Get() { return ptr_; } |
+ T& operator*() { return *ptr_; } |
+ T* operator->() { return ptr_; } |
+ private: |
+ T* ptr_; |
+}; |
+ |
+// Return the base name from a file path. Important: this is a pointer |
+// into the original string. |
+const char* GetBaseNamePtr(const char* path); |
+ |
+// Helper class used to implement a string. Similar to std::string |
+// without all the crazy iterator / iostream stuff. |
+// |
+// Required because crazy linker should only link against the system |
+// libstdc++ that only provides new/delete. |
+// |
+class String { |
+ public: |
+ String(); |
+ String(const char* str, size_t len); |
+ String(const String& other); |
+ explicit String(const char* str); |
+ explicit String(char ch); |
+ |
+ ~String(); |
+ |
+ const char* c_str() const { return ptr_; } |
+ char* ptr() { return ptr_; } |
+ size_t size() const { return size_; } |
+ size_t capacity() const { return capacity_; } |
+ |
+ bool IsEmpty() const { return size_ == 0; } |
+ |
+ char& operator[](size_t index) { |
+ return ptr_[index]; |
+ } |
+ |
+ String& operator =(const String& other) { |
+ Assign(other.ptr_, other.size_); |
+ return *this; |
+ } |
+ |
+ String& operator=(const char* str) { |
+ Assign(str, strlen(str)); |
+ return *this; |
+ } |
+ |
+ String& operator=(char ch) { |
+ Assign(&ch, 1); |
+ return *this; |
+ } |
+ |
+ String& operator +=(const String& other) { |
+ Append(other); |
+ return *this; |
+ } |
+ |
+ String& operator +=(const char* str) { |
+ Append(str, strlen(str)); |
+ return *this; |
+ } |
+ |
+ String& operator +=(char ch) { |
+ Append(&ch, 1); |
+ return *this; |
+ } |
+ |
+ void Resize(size_t new_size); |
+ |
+ void Reserve(size_t new_capacity); |
+ |
+ void Assign(const char* str, size_t len); |
+ |
+ void Assign(const String& other) { |
+ Assign(other.ptr_, other.size_); |
+ } |
+ |
+ void Assign(const char* str) { |
+ Assign(str, strlen(str)); |
+ } |
+ |
+ void Append(const char* str, size_t len); |
+ |
+ void Append(const String& other) { |
+ Append(other.ptr_, other.size_); |
+ } |
+ |
+ void Append(const char* str) { |
+ Append(str, strlen(str)); |
+ } |
+ |
+ private: |
+ void Init(void) { |
+ ptr_ = const_cast<char*>(kEmpty); |
+ size_ = 0; |
+ capacity_ = 0; |
+ } |
+ |
+ static const char kEmpty[]; |
+ |
+ char* ptr_; |
+ size_t size_; |
+ size_t capacity_; |
+}; |
+ |
+// Helper template used to implement a simple vector or POD-struct items. |
+// I.e. this uses memmove() to move items during insertion / removal. |
+// |
+// Required because crazy linker should only link against the system |
+// libstdc++ which only provides new/delete. |
+// |
+template <class T> |
+class Vector { |
+ public: |
+ Vector() : items_(0), count_(0), capacity_(0) {} |
+ ~Vector() { |
+ free(items_); |
+ } |
+ |
+ T& operator[](size_t index) { |
+ return items_[index]; |
+ } |
+ |
+ bool IsEmpty() const { |
+ return count_ == 0; |
+ } |
+ |
+ void PushBack(T item) { |
+ InsertAt(static_cast<int>(count_), item); |
+ } |
+ |
+ T PopFirst() { |
+ T result = items_[0]; |
+ RemoveAt(0); |
+ return result; |
+ } |
+ |
+ T PopLast() { |
+ T result = items_[count_ - 1]; |
+ Resize(count_ - 1); |
+ return result; |
+ } |
+ |
+ void Remove(T item) { |
+ int index = IndexOf(item); |
+ if (index >= 0) |
+ RemoveAt(index); |
+ } |
+ |
+ void InsertAt(int index, T item); |
+ |
+ void RemoveAt(int index); |
+ |
+ int IndexOf(T item) const; |
+ |
+ bool Has(T item) const { |
+ return IndexOf(item) >= 0; |
+ } |
+ |
+ size_t GetCount() const { return count_; } |
+ |
+ void Reserve(size_t new_capacity); |
+ |
+ void Resize(size_t new_count); |
+ |
+ private: |
+ T* items_; |
+ size_t count_; |
+ size_t capacity_; |
+}; |
+ |
+template <class T> |
+int Vector<T>::IndexOf(T item) const { |
+ for (size_t n = 0; n < count_; ++n) { |
+ if (items_[n] == item) |
+ return static_cast<int>(n); |
+ } |
+ return -1; |
+} |
+ |
+template <class T> |
+void Vector<T>::InsertAt(int index, T item) { |
+ if (count_ >= capacity_) |
+ Reserve(capacity_ + (capacity_ >> 1) + 4); |
+ |
+ if (index < 0) |
+ index = 0; |
+ size_t n = static_cast<size_t>(index); |
+ if (n > count_) |
+ n = count_; |
+ else |
+ memmove(items_ + n + 1, items_ + n, (count_ - n) * sizeof(T)); |
+ |
+ items_[n] = item; |
+ count_++; |
+} |
+ |
+template <class T> |
+void Vector<T>::RemoveAt(int index) { |
+ if (index < 0) |
+ return; |
+ |
+ size_t n = static_cast<size_t>(index); |
+ if (n >= count_) |
+ return; |
+ |
+ memmove(items_ + n, items_ + n + 1, (count_ - n - 1) * sizeof(T)); |
+ count_--; |
+} |
+ |
+template <class T> |
+void Vector<T>::Reserve(size_t new_capacity) { |
+ items_ = reinterpret_cast<T*>(realloc(items_, new_capacity * sizeof(T))); |
+ capacity_ = new_capacity; |
+ if (count_ > capacity_) |
+ count_ = capacity_; |
+} |
+ |
+template <class T> |
+void Vector<T>::Resize(size_t new_size) { |
+ if (new_size > capacity_) |
+ Reserve(new_size); |
+ |
+ if (new_size > count_) |
+ memset(items_ + count_, 0, (new_size - count_) * sizeof(T)); |
+ |
+ count_ = new_size; |
+} |
+ |
+// Helper template class to implement a set. |
+// Given that the crazy linker doesn't expect to deal with hundreds |
+// of libraries at the same time, implement it with a vector. |
+template <class T> |
+class Set { |
+ public: |
+ Set() : items_() {} |
+ ~Set() {} |
+ |
+ // Returns the number of items in the set. |
+ size_t GetCount() const { return items_.GetCount(); } |
+ |
+ bool IsEmpty() const { return items_.IsEmpty(); } |
+ |
+ // Returns true iff the set contains a given item. |
+ bool Has(T item) const { |
+ return items_.Has(item); |
+ } |
+ |
+ // Add an item to the set. Returns false iff the item was already in it. |
+ bool Add(T item); |
+ |
+ // Delete an item from the set. Returns false iff the item was not in it. |
+ bool Del(T item); |
+ |
+ private: |
+ Vector<T> items_; |
+}; |
+ |
+template <class T> |
+bool Set<T>::Add(T item) { |
+ int idx = items_.IndexOf(item); |
+ if (idx >= 0) |
+ return false; |
+ |
+ items_.PushBack(item); |
+ return true; |
+} |
+ |
+template <class T> |
+bool Set<T>::Del(T item) { |
+ int idx = items_.IndexOf(item); |
+ if (idx < 0) |
+ return false; |
+ items_.RemoveAt(idx); |
+ return true; |
+} |
+ |
+} // namespace crazy |
+ |
+#endif // CRAZY_LINKER_UTIL_H |