OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 // This should be used in the private: declarations for a class | 108 // This should be used in the private: declarations for a class |
109 // that wants to prevent anyone from instantiating it. This is | 109 // that wants to prevent anyone from instantiating it. This is |
110 // especially useful for classes containing only static methods. | 110 // especially useful for classes containing only static methods. |
111 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ | 111 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ |
112 TypeName(); \ | 112 TypeName(); \ |
113 DISALLOW_COPY_AND_ASSIGN(TypeName) | 113 DISALLOW_COPY_AND_ASSIGN(TypeName) |
114 | 114 |
115 namespace WTF { | 115 namespace WTF { |
116 | 116 |
117 namespace double_conversion { | 117 namespace double_conversion { |
118 | 118 |
119 static const int kCharSize = sizeof(char); | 119 static const int kCharSize = sizeof(char); |
120 | 120 |
121 // Returns the maximum of the two parameters. | 121 // Returns the maximum of the two parameters. |
122 template <typename T> | 122 template <typename T> |
123 static T Max(T a, T b) { | 123 static T Max(T a, T b) { |
124 return a < b ? b : a; | 124 return a < b ? b : a; |
125 } | 125 } |
126 | 126 |
127 | 127 |
128 // Returns the minimum of the two parameters. | 128 // Returns the minimum of the two parameters. |
129 template <typename T> | 129 template <typename T> |
130 static T Min(T a, T b) { | 130 static T Min(T a, T b) { |
131 return a < b ? a : b; | 131 return a < b ? a : b; |
132 } | 132 } |
133 | 133 |
134 | 134 |
135 inline int StrLength(const char* string) { | 135 inline int StrLength(const char* string) { |
136 size_t length = strlen(string); | 136 size_t length = strlen(string); |
137 ASSERT(length == static_cast<size_t>(static_cast<int>(length))); | 137 ASSERT(length == static_cast<size_t>(static_cast<int>(length))); |
138 return static_cast<int>(length); | 138 return static_cast<int>(length); |
139 } | 139 } |
140 | 140 |
141 // This is a simplified version of V8's Vector class. | 141 // This is a simplified version of V8's Vector class. |
142 template <typename T> | 142 template <typename T> |
143 class Vector { | 143 class Vector { |
144 public: | 144 public: |
145 Vector() : start_(NULL), length_(0) {} | 145 Vector() : start_(NULL), length_(0) {} |
146 Vector(T* data, int length) : start_(data), length_(length) { | 146 Vector(T* data, int length) : start_(data), length_(length) { |
147 ASSERT(length == 0 || (length > 0 && data != NULL)); | 147 ASSERT(length == 0 || (length > 0 && data != NULL)); |
148 } | 148 } |
149 | 149 |
150 // Returns a vector using the same backing storage as this one, | 150 // Returns a vector using the same backing storage as this one, |
151 // spanning from and including 'from', to but not including 'to'. | 151 // spanning from and including 'from', to but not including 'to'. |
152 Vector<T> SubVector(int from, int to) { | 152 Vector<T> SubVector(int from, int to) { |
153 ASSERT(to <= length_); | 153 ASSERT(to <= length_); |
154 ASSERT(from < to); | 154 ASSERT(from < to); |
155 ASSERT(0 <= from); | 155 ASSERT(0 <= from); |
156 return Vector<T>(start() + from, to - from); | 156 return Vector<T>(start() + from, to - from); |
157 } | 157 } |
158 | 158 |
159 // Returns the length of the vector. | 159 // Returns the length of the vector. |
160 int length() const { return length_; } | 160 int length() const { return length_; } |
161 | 161 |
162 // Returns whether or not the vector is empty. | 162 // Returns whether or not the vector is empty. |
163 bool is_empty() const { return length_ == 0; } | 163 bool is_empty() const { return length_ == 0; } |
164 | 164 |
165 // Returns the pointer to the start of the data in the vector. | 165 // Returns the pointer to the start of the data in the vector. |
166 T* start() const { return start_; } | 166 T* start() const { return start_; } |
167 | 167 |
168 // Access individual vector elements - checks bounds in debug mode. | 168 // Access individual vector elements - checks bounds in debug mode. |
169 T& operator[](int index) const { | 169 T& operator[](int index) const { |
170 ASSERT(0 <= index && index < length_); | 170 ASSERT(0 <= index && index < length_); |
171 return start_[index]; | 171 return start_[index]; |
172 } | 172 } |
173 | 173 |
174 T& first() { return start_[0]; } | 174 T& first() { return start_[0]; } |
175 | 175 |
176 T& last() { return start_[length_ - 1]; } | 176 T& last() { return start_[length_ - 1]; } |
177 | 177 |
178 private: | 178 private: |
179 T* start_; | 179 T* start_; |
180 int length_; | 180 int length_; |
181 }; | 181 }; |
182 | 182 |
183 | 183 |
184 // Helper class for building result strings in a character buffer. The | 184 // Helper class for building result strings in a character buffer. The |
185 // purpose of the class is to use safe operations that checks the | 185 // purpose of the class is to use safe operations that checks the |
186 // buffer bounds on all operations in debug mode. | 186 // buffer bounds on all operations in debug mode. |
187 class StringBuilder { | 187 class StringBuilder { |
188 public: | 188 public: |
189 StringBuilder(char* buffer, int size) | 189 StringBuilder(char* buffer, int size) |
190 : buffer_(buffer, size), position_(0) { } | 190 : buffer_(buffer, size), position_(0) { } |
191 | 191 |
192 ~StringBuilder() { if (!is_finalized()) Finalize(); } | 192 ~StringBuilder() { if (!is_finalized()) Finalize(); } |
193 | 193 |
194 int size() const { return buffer_.length(); } | 194 int size() const { return buffer_.length(); } |
195 | 195 |
196 // Get the current position in the builder. | 196 // Get the current position in the builder. |
197 int position() const { | 197 int position() const { |
198 ASSERT(!is_finalized()); | 198 ASSERT(!is_finalized()); |
199 return position_; | 199 return position_; |
200 } | 200 } |
201 | 201 |
202 // Set the current position in the builder. | 202 // Set the current position in the builder. |
203 void SetPosition(int position) | 203 void SetPosition(int position) |
204 { | 204 { |
205 ASSERT(!is_finalized()); | 205 ASSERT(!is_finalized()); |
206 ASSERT_WITH_SECURITY_IMPLICATION(position < size()); | 206 ASSERT_WITH_SECURITY_IMPLICATION(position < size()); |
207 position_ = position; | 207 position_ = position; |
208 } | 208 } |
209 | 209 |
210 // Reset the position. | 210 // Reset the position. |
211 void Reset() { position_ = 0; } | 211 void Reset() { position_ = 0; } |
212 | 212 |
213 // Add a single character to the builder. It is not allowed to add | 213 // Add a single character to the builder. It is not allowed to add |
214 // 0-characters; use the Finalize() method to terminate the string | 214 // 0-characters; use the Finalize() method to terminate the string |
215 // instead. | 215 // instead. |
216 void AddCharacter(char c) { | 216 void AddCharacter(char c) { |
217 ASSERT(c != '\0'); | 217 ASSERT(c != '\0'); |
218 ASSERT(!is_finalized() && position_ < buffer_.length()); | 218 ASSERT(!is_finalized() && position_ < buffer_.length()); |
219 buffer_[position_++] = c; | 219 buffer_[position_++] = c; |
220 } | 220 } |
221 | 221 |
222 // Add an entire string to the builder. Uses strlen() internally to | 222 // Add an entire string to the builder. Uses strlen() internally to |
223 // compute the length of the input string. | 223 // compute the length of the input string. |
224 void AddString(const char* s) { | 224 void AddString(const char* s) { |
225 AddSubstring(s, StrLength(s)); | 225 AddSubstring(s, StrLength(s)); |
226 } | 226 } |
227 | 227 |
228 // Add the first 'n' characters of the given string 's' to the | 228 // Add the first 'n' characters of the given string 's' to the |
229 // builder. The input string must have enough characters. | 229 // builder. The input string must have enough characters. |
230 void AddSubstring(const char* s, int n) { | 230 void AddSubstring(const char* s, int n) { |
231 ASSERT(!is_finalized() && position_ + n < buffer_.length()); | 231 ASSERT(!is_finalized() && position_ + n < buffer_.length()); |
232 ASSERT_WITH_SECURITY_IMPLICATION(static_cast<size_t>(n) <= strlen(s)
); | 232 ASSERT_WITH_SECURITY_IMPLICATION(static_cast<size_t>(n) <= strlen(s)
); |
233 memcpy(&buffer_[position_], s, n * kCharSize); | 233 memcpy(&buffer_[position_], s, n * kCharSize); |
234 position_ += n; | 234 position_ += n; |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 // Add character padding to the builder. If count is non-positive, | 238 // Add character padding to the builder. If count is non-positive, |
239 // nothing is added to the builder. | 239 // nothing is added to the builder. |
240 void AddPadding(char c, int count) { | 240 void AddPadding(char c, int count) { |
241 for (int i = 0; i < count; i++) { | 241 for (int i = 0; i < count; i++) { |
242 AddCharacter(c); | 242 AddCharacter(c); |
243 } | 243 } |
244 } | 244 } |
245 | 245 |
246 // Finalize the string by 0-terminating it and returning the buffer. | 246 // Finalize the string by 0-terminating it and returning the buffer. |
247 char* Finalize() { | 247 char* Finalize() { |
248 ASSERT(!is_finalized() && position_ < buffer_.length()); | 248 ASSERT(!is_finalized() && position_ < buffer_.length()); |
249 buffer_[position_] = '\0'; | 249 buffer_[position_] = '\0'; |
250 // Make sure nobody managed to add a 0-character to the | 250 // Make sure nobody managed to add a 0-character to the |
251 // buffer while building the string. | 251 // buffer while building the string. |
252 ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); | 252 ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); |
253 position_ = -1; | 253 position_ = -1; |
254 ASSERT(is_finalized()); | 254 ASSERT(is_finalized()); |
255 return buffer_.start(); | 255 return buffer_.start(); |
256 } | 256 } |
257 | 257 |
258 private: | 258 private: |
259 Vector<char> buffer_; | 259 Vector<char> buffer_; |
260 int position_; | 260 int position_; |
261 | 261 |
262 bool is_finalized() const { return position_ < 0; } | 262 bool is_finalized() const { return position_ < 0; } |
263 | 263 |
264 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); | 264 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); |
265 }; | 265 }; |
266 | 266 |
267 // The type-based aliasing rule allows the compiler to assume that pointers
of | 267 // The type-based aliasing rule allows the compiler to assume that pointers
of |
268 // different types (for some definition of different) never alias each other
. | 268 // different types (for some definition of different) never alias each other
. |
269 // Thus the following code does not work: | 269 // Thus the following code does not work: |
270 // | 270 // |
271 // float f = foo(); | 271 // float f = foo(); |
272 // int fbits = *(int*)(&f); | 272 // int fbits = *(int*)(&f); |
273 // | 273 // |
274 // The compiler 'knows' that the int pointer can't refer to f since the type
s | 274 // The compiler 'knows' that the int pointer can't refer to f since the type
s |
275 // don't match, so the compiler may cache f in a register, leaving random da
ta | 275 // don't match, so the compiler may cache f in a register, leaving random da
ta |
276 // in fbits. Using C++ style casts makes no difference, however a pointer t
o | 276 // in fbits. Using C++ style casts makes no difference, however a pointer t
o |
277 // char data is assumed to alias any other pointer. This is the 'memcpy | 277 // char data is assumed to alias any other pointer. This is the 'memcpy |
278 // exception'. | 278 // exception'. |
279 // | 279 // |
280 // Bit_cast uses the memcpy exception to move the bits from a variable of on
e | 280 // Bit_cast uses the memcpy exception to move the bits from a variable of on
e |
281 // type of a variable of another type. Of course the end result is likely t
o | 281 // type of a variable of another type. Of course the end result is likely t
o |
282 // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) | 282 // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) |
283 // will completely optimize BitCast away. | 283 // will completely optimize BitCast away. |
284 // | 284 // |
285 // There is an additional use for BitCast. | 285 // There is an additional use for BitCast. |
286 // Recent gccs will warn when they see casts that may result in breakage due
to | 286 // Recent gccs will warn when they see casts that may result in breakage due
to |
287 // the type-based aliasing rule. If you have checked that there is no break
age | 287 // the type-based aliasing rule. If you have checked that there is no break
age |
288 // you can use BitCast to cast one pointer type to another. This confuses g
cc | 288 // you can use BitCast to cast one pointer type to another. This confuses g
cc |
289 // enough that it can no longer see that you have cast one pointer type to | 289 // enough that it can no longer see that you have cast one pointer type to |
290 // another thus avoiding the warning. | 290 // another thus avoiding the warning. |
291 template <class Dest, class Source> | 291 template <class Dest, class Source> |
292 inline Dest BitCast(const Source& source) { | 292 inline Dest BitCast(const Source& source) { |
293 // Compile time assertion: sizeof(Dest) == sizeof(Source) | 293 // Compile time assertion: sizeof(Dest) == sizeof(Source) |
294 // A compile error here means your Dest and Source have different sizes. | 294 // A compile error here means your Dest and Source have different sizes. |
295 typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1
]; | 295 typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1
]; |
296 | 296 |
297 Dest dest; | 297 Dest dest; |
298 memcpy(&dest, &source, sizeof(dest)); | 298 memcpy(&dest, &source, sizeof(dest)); |
299 return dest; | 299 return dest; |
300 } | 300 } |
301 | 301 |
302 template <class Dest, class Source> | 302 template <class Dest, class Source> |
303 inline Dest BitCast(Source* source) { | 303 inline Dest BitCast(Source* source) { |
304 return BitCast<Dest>(reinterpret_cast<uintptr_t>(source)); | 304 return BitCast<Dest>(reinterpret_cast<uintptr_t>(source)); |
305 } | 305 } |
306 | 306 |
307 } // namespace double_conversion | 307 } // namespace double_conversion |
308 | 308 |
309 } // namespace WTF | 309 } // namespace WTF |
310 | 310 |
311 #endif // DOUBLE_CONVERSION_UTILS_H_ | 311 #endif // DOUBLE_CONVERSION_UTILS_H_ |
OLD | NEW |