ee67076a3019f39b4579a8d173c0b683cb3cf12a
[platform/framework/web/crosswalk.git] / src / third_party / android_crazy_linker / src / src / crazy_linker_util.h
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
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