Line data Source code
1 : // Copyright 2010 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #ifndef DOUBLE_CONVERSION_UTILS_H_
29 : #define DOUBLE_CONVERSION_UTILS_H_
30 :
31 : #include <stdlib.h>
32 : #include <string.h>
33 :
34 : #include "mozilla/Assertions.h"
35 : #ifndef ASSERT
36 : #define ASSERT(condition) \
37 : MOZ_ASSERT(condition)
38 : #endif
39 : #ifndef UNIMPLEMENTED
40 : #define UNIMPLEMENTED() MOZ_CRASH()
41 : #endif
42 : #ifndef DOUBLE_CONVERSION_NO_RETURN
43 : #ifdef _MSC_VER
44 : #define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
45 : #else
46 : #define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
47 : #endif
48 : #endif
49 : #ifndef UNREACHABLE
50 : #ifdef _MSC_VER
51 : void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
52 : inline void abort_noreturn() { MOZ_CRASH(); }
53 : #define UNREACHABLE() (abort_noreturn())
54 : #else
55 : #define UNREACHABLE() MOZ_CRASH()
56 : #endif
57 : #endif
58 :
59 :
60 : // Double operations detection based on target architecture.
61 : // Linux uses a 80bit wide floating point stack on x86. This induces double
62 : // rounding, which in turn leads to wrong results.
63 : // An easy way to test if the floating-point operations are correct is to
64 : // evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
65 : // the result is equal to 89255e-22.
66 : // The best way to test this, is to create a division-function and to compare
67 : // the output of the division with the expected result. (Inlining must be
68 : // disabled.)
69 : // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
70 : #if defined(_M_X64) || defined(__x86_64__) || \
71 : defined(__ARMEL__) || defined(__avr32__) || \
72 : defined(__hppa__) || defined(__ia64__) || \
73 : defined(__mips__) || \
74 : defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
75 : defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
76 : defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
77 : defined(__SH4__) || defined(__alpha__) || \
78 : defined(_MIPS_ARCH_MIPS32R2) || \
79 : defined(__AARCH64EL__) || defined(__aarch64__) || \
80 : defined(__riscv)
81 : #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
82 : #elif defined(__mc68000__)
83 : #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
84 : #elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
85 : #if defined(_WIN32)
86 : // Windows uses a 64bit wide floating point stack.
87 : #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
88 : #else
89 : #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
90 : #endif // _WIN32
91 : #else
92 : #error Target architecture was not detected as supported by Double-Conversion.
93 : #endif
94 :
95 : #if defined(__GNUC__)
96 : #define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
97 : #else
98 : #define DOUBLE_CONVERSION_UNUSED
99 : #endif
100 :
101 : #include <stdint.h>
102 :
103 : typedef uint16_t uc16;
104 :
105 : // The following macro works on both 32 and 64-bit platforms.
106 : // Usage: instead of writing 0x1234567890123456
107 : // write UINT64_2PART_C(0x12345678,90123456);
108 : #define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
109 :
110 :
111 : // The expression ARRAY_SIZE(a) is a compile-time constant of type
112 : // size_t which represents the number of elements of the given
113 : // array. You should only use ARRAY_SIZE on statically allocated
114 : // arrays.
115 : #ifndef ARRAY_SIZE
116 : #define ARRAY_SIZE(a) \
117 : ((sizeof(a) / sizeof(*(a))) / \
118 : static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
119 : #endif
120 :
121 : // A macro to disallow the evil copy constructor and operator= functions
122 : // This should be used in the private: declarations for a class
123 : #ifndef DISALLOW_COPY_AND_ASSIGN
124 : #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
125 : TypeName(const TypeName&); \
126 : void operator=(const TypeName&)
127 : #endif
128 :
129 : // A macro to disallow all the implicit constructors, namely the
130 : // default constructor, copy constructor and operator= functions.
131 : //
132 : // This should be used in the private: declarations for a class
133 : // that wants to prevent anyone from instantiating it. This is
134 : // especially useful for classes containing only static methods.
135 : #ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
136 : #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
137 : TypeName(); \
138 : DISALLOW_COPY_AND_ASSIGN(TypeName)
139 : #endif
140 :
141 : namespace double_conversion {
142 :
143 : static const int kCharSize = sizeof(char);
144 :
145 : // Returns the maximum of the two parameters.
146 : template <typename T>
147 8 : static T Max(T a, T b) {
148 8 : return a < b ? b : a;
149 : }
150 :
151 :
152 : // Returns the minimum of the two parameters.
153 : template <typename T>
154 0 : static T Min(T a, T b) {
155 0 : return a < b ? a : b;
156 : }
157 :
158 :
159 0 : inline int StrLength(const char* string) {
160 0 : size_t length = strlen(string);
161 0 : ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
162 0 : return static_cast<int>(length);
163 : }
164 :
165 : // This is a simplified version of V8's Vector class.
166 : template <typename T>
167 : class Vector {
168 : public:
169 0 : Vector() : start_(NULL), length_(0) {}
170 16 : Vector(T* data, int len) : start_(data), length_(len) {
171 16 : ASSERT(len == 0 || (len > 0 && data != NULL));
172 16 : }
173 :
174 : // Returns a vector using the same backing storage as this one,
175 : // spanning from and including 'from', to but not including 'to'.
176 0 : Vector<T> SubVector(int from, int to) {
177 0 : ASSERT(to <= length_);
178 0 : ASSERT(from < to);
179 0 : ASSERT(0 <= from);
180 0 : return Vector<T>(start() + from, to - from);
181 : }
182 :
183 : // Returns the length of the vector.
184 30 : int length() const { return length_; }
185 :
186 : // Returns whether or not the vector is empty.
187 : bool is_empty() const { return length_ == 0; }
188 :
189 : // Returns the pointer to the start of the data in the vector.
190 16 : T* start() const { return start_; }
191 :
192 : // Access individual vector elements - checks bounds in debug mode.
193 149 : T& operator[](int index) const {
194 149 : ASSERT(0 <= index && index < length_);
195 149 : return start_[index];
196 : }
197 :
198 : T& first() { return start_[0]; }
199 :
200 : T& last() { return start_[length_ - 1]; }
201 :
202 : private:
203 : T* start_;
204 : int length_;
205 : };
206 :
207 :
208 : // Helper class for building result strings in a character buffer. The
209 : // purpose of the class is to use safe operations that checks the
210 : // buffer bounds on all operations in debug mode.
211 : class StringBuilder {
212 : public:
213 8 : StringBuilder(char* buffer, int buffer_size)
214 8 : : buffer_(buffer, buffer_size), position_(0) { }
215 :
216 8 : ~StringBuilder() { if (!is_finalized()) Finalize(); }
217 :
218 : int size() const { return buffer_.length(); }
219 :
220 : // Get the current position in the builder.
221 0 : int position() const {
222 0 : ASSERT(!is_finalized());
223 0 : return position_;
224 : }
225 :
226 : // Reset the position.
227 : void Reset() { position_ = 0; }
228 :
229 : // Add a single character to the builder. It is not allowed to add
230 : // 0-characters; use the Finalize() method to terminate the string
231 : // instead.
232 10 : void AddCharacter(char c) {
233 10 : ASSERT(c != '\0');
234 10 : ASSERT(!is_finalized() && position_ < buffer_.length());
235 10 : buffer_[position_++] = c;
236 10 : }
237 :
238 : // Add an entire string to the builder. Uses strlen() internally to
239 : // compute the length of the input string.
240 0 : void AddString(const char* s) {
241 0 : AddSubstring(s, StrLength(s));
242 0 : }
243 :
244 : // Add the first 'n' characters of the given string 's' to the
245 : // builder. The input string must have enough characters.
246 12 : void AddSubstring(const char* s, int n) {
247 12 : ASSERT(!is_finalized() && position_ + n < buffer_.length());
248 12 : ASSERT(static_cast<size_t>(n) <= strlen(s));
249 12 : memmove(&buffer_[position_], s, n * kCharSize);
250 12 : position_ += n;
251 12 : }
252 :
253 :
254 : // Add character padding to the builder. If count is non-positive,
255 : // nothing is added to the builder.
256 11 : void AddPadding(char c, int count) {
257 11 : for (int i = 0; i < count; i++) {
258 0 : AddCharacter(c);
259 : }
260 11 : }
261 :
262 : // Finalize the string by 0-terminating it and returning the buffer.
263 8 : char* Finalize() {
264 8 : ASSERT(!is_finalized() && position_ < buffer_.length());
265 8 : buffer_[position_] = '\0';
266 : // Make sure nobody managed to add a 0-character to the
267 : // buffer while building the string.
268 8 : ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
269 8 : position_ = -1;
270 8 : ASSERT(is_finalized());
271 8 : return buffer_.start();
272 : }
273 :
274 : private:
275 : Vector<char> buffer_;
276 : int position_;
277 :
278 46 : bool is_finalized() const { return position_ < 0; }
279 :
280 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
281 : };
282 :
283 : // The type-based aliasing rule allows the compiler to assume that pointers of
284 : // different types (for some definition of different) never alias each other.
285 : // Thus the following code does not work:
286 : //
287 : // float f = foo();
288 : // int fbits = *(int*)(&f);
289 : //
290 : // The compiler 'knows' that the int pointer can't refer to f since the types
291 : // don't match, so the compiler may cache f in a register, leaving random data
292 : // in fbits. Using C++ style casts makes no difference, however a pointer to
293 : // char data is assumed to alias any other pointer. This is the 'memcpy
294 : // exception'.
295 : //
296 : // Bit_cast uses the memcpy exception to move the bits from a variable of one
297 : // type of a variable of another type. Of course the end result is likely to
298 : // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
299 : // will completely optimize BitCast away.
300 : //
301 : // There is an additional use for BitCast.
302 : // Recent gccs will warn when they see casts that may result in breakage due to
303 : // the type-based aliasing rule. If you have checked that there is no breakage
304 : // you can use BitCast to cast one pointer type to another. This confuses gcc
305 : // enough that it can no longer see that you have cast one pointer type to
306 : // another thus avoiding the warning.
307 : template <class Dest, class Source>
308 64 : inline Dest BitCast(const Source& source) {
309 : // Compile time assertion: sizeof(Dest) == sizeof(Source)
310 : // A compile error here means your Dest and Source have different sizes.
311 : DOUBLE_CONVERSION_UNUSED
312 : typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
313 :
314 : Dest dest;
315 64 : memmove(&dest, &source, sizeof(dest));
316 64 : return dest;
317 : }
318 :
319 : template <class Dest, class Source>
320 : inline Dest BitCast(Source* source) {
321 : return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
322 : }
323 :
324 : } // namespace double_conversion
325 :
326 : #endif // DOUBLE_CONVERSION_UTILS_H_
|