Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef jsnum_h
8 #define jsnum_h
10 #include "mozilla/FloatingPoint.h"
12 #include "NamespaceImports.h"
14 #include "vm/NumericConversions.h"
16 namespace js {
18 class StringBuffer;
20 extern bool
21 InitRuntimeNumberState(JSRuntime *rt);
23 #if !EXPOSE_INTL_API
24 extern void
25 FinishRuntimeNumberState(JSRuntime *rt);
26 #endif
28 } /* namespace js */
30 /* Initialize the Number class, returning its prototype object. */
31 extern JSObject *
32 js_InitNumberClass(JSContext *cx, js::HandleObject obj);
34 /*
35 * String constants for global function names, used in jsapi.c and jsnum.c.
36 */
37 extern const char js_isNaN_str[];
38 extern const char js_isFinite_str[];
39 extern const char js_parseFloat_str[];
40 extern const char js_parseInt_str[];
42 class JSAtom;
44 namespace js {
46 /*
47 * When base == 10, this function implements ToString() as specified by
48 * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
49 * performance. See also js::NumberToCString().
50 */
51 template <js::AllowGC allowGC>
52 extern JSString *
53 NumberToString(js::ThreadSafeContext *cx, double d);
55 extern JSAtom *
56 NumberToAtom(js::ExclusiveContext *cx, double d);
58 template <AllowGC allowGC>
59 extern JSFlatString *
60 Int32ToString(ThreadSafeContext *cx, int32_t i);
62 extern JSAtom *
63 Int32ToAtom(ExclusiveContext *cx, int32_t si);
65 /*
66 * Convert an integer or double (contained in the given value) to a string and
67 * append to the given buffer.
68 */
69 extern bool JS_FASTCALL
70 NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb);
72 /* Same as js_NumberToString, different signature. */
73 extern JSFlatString *
74 NumberToString(JSContext *cx, double d);
76 extern JSFlatString *
77 IndexToString(JSContext *cx, uint32_t index);
79 /*
80 * Usually a small amount of static storage is enough, but sometimes we need
81 * to dynamically allocate much more. This struct encapsulates that.
82 * Dynamically allocated memory will be freed when the object is destroyed.
83 */
84 struct ToCStringBuf
85 {
86 /*
87 * The longest possible result that would need to fit in sbuf is
88 * (-0x80000000).toString(2), which has length 33. Longer cases are
89 * possible, but they'll go in dbuf.
90 */
91 static const size_t sbufSize = 34;
92 char sbuf[sbufSize];
93 char *dbuf;
95 ToCStringBuf();
96 ~ToCStringBuf();
97 };
99 /*
100 * Convert a number to a C string. When base==10, this function implements
101 * ToString() as specified by ECMA-262-5 section 9.8.1. It handles integral
102 * values cheaply. Return nullptr if we ran out of memory. See also
103 * js_NumberToCString().
104 */
105 extern char *
106 NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10);
108 /*
109 * The largest positive integer such that all positive integers less than it
110 * may be precisely represented using the IEEE-754 double-precision format.
111 */
112 const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53;
114 /*
115 * Parse a decimal number encoded in |chars|. The decimal number must be
116 * sufficiently small that it will not overflow the integrally-precise range of
117 * the double type -- that is, the number will be smaller than
118 * DOUBLE_INTEGRAL_PRECISION_LIMIT
119 */
120 extern double
121 ParseDecimalNumber(const JS::TwoByteChars chars);
123 /*
124 * Compute the positive integer of the given base described immediately at the
125 * start of the range [start, end) -- no whitespace-skipping, no magical
126 * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just
127 * reading the digits of the integer. Return the index one past the end of the
128 * digits of the integer in *endp, and return the integer itself in *dp. If
129 * base is 10 or a power of two the returned integer is the closest possible
130 * double; otherwise extremely large integers may be slightly inaccurate.
131 *
132 * If [start, end) does not begin with a number with the specified base,
133 * *dp == 0 and *endp == start upon return.
134 */
135 extern bool
136 GetPrefixInteger(ThreadSafeContext *cx, const jschar *start, const jschar *end, int base,
137 const jschar **endp, double *dp);
139 /*
140 * This is like GetPrefixInteger, but only deals with base 10, and doesn't have
141 * and |endp| outparam. It should only be used when the jschars are known to
142 * only contain digits.
143 */
144 extern bool
145 GetDecimalInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, double *dp);
147 extern bool
148 StringToNumber(ThreadSafeContext *cx, JSString *str, double *result);
150 /* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
151 MOZ_ALWAYS_INLINE bool
152 ToNumber(JSContext *cx, JS::MutableHandleValue vp)
153 {
154 if (vp.isNumber())
155 return true;
156 double d;
157 extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp);
158 if (!ToNumberSlow(cx, vp, &d))
159 return false;
161 vp.setNumber(d);
162 return true;
163 }
165 bool
166 num_parseInt(JSContext *cx, unsigned argc, Value *vp);
168 } /* namespace js */
170 /*
171 * Similar to strtod except that it replaces overflows with infinities of the
172 * correct sign, and underflows with zeros of the correct sign. Guaranteed to
173 * return the closest double number to the given input in dp.
174 *
175 * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
176 * the appropriate sign. The case of the "Infinity" string must match exactly.
177 * If the string does not contain a number, set *ep to s and return 0.0 in dp.
178 * Return false if out of memory.
179 */
180 extern bool
181 js_strtod(js::ThreadSafeContext *cx, const jschar *s, const jschar *send,
182 const jschar **ep, double *dp);
184 extern bool
185 js_num_toString(JSContext *cx, unsigned argc, js::Value *vp);
187 extern bool
188 js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp);
190 namespace js {
192 static MOZ_ALWAYS_INLINE bool
193 ValueFitsInInt32(const Value &v, int32_t *pi)
194 {
195 if (v.isInt32()) {
196 *pi = v.toInt32();
197 return true;
198 }
199 return v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), pi);
200 }
202 /*
203 * Returns true if the given value is definitely an index: that is, the value
204 * is a number that's an unsigned 32-bit integer.
205 *
206 * This method prioritizes common-case speed over accuracy in every case. It
207 * can produce false negatives (but not false positives): some values which are
208 * indexes will be reported not to be indexes by this method. Users must
209 * consider this possibility when using this method.
210 */
211 static MOZ_ALWAYS_INLINE bool
212 IsDefinitelyIndex(const Value &v, uint32_t *indexp)
213 {
214 if (v.isInt32() && v.toInt32() >= 0) {
215 *indexp = v.toInt32();
216 return true;
217 }
219 int32_t i;
220 if (v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), &i) && i >= 0) {
221 *indexp = uint32_t(i);
222 return true;
223 }
225 return false;
226 }
228 /* ES5 9.4 ToInteger. */
229 static inline bool
230 ToInteger(JSContext *cx, HandleValue v, double *dp)
231 {
232 if (v.isInt32()) {
233 *dp = v.toInt32();
234 return true;
235 }
236 if (v.isDouble()) {
237 *dp = v.toDouble();
238 } else {
239 extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp);
240 if (!ToNumberSlow(cx, v, dp))
241 return false;
242 }
243 *dp = ToInteger(*dp);
244 return true;
245 }
247 inline bool
248 SafeAdd(int32_t one, int32_t two, int32_t *res)
249 {
250 // Use unsigned for the 32-bit operation since signed overflow gets
251 // undefined behavior.
252 *res = uint32_t(one) + uint32_t(two);
253 int64_t ores = (int64_t)one + (int64_t)two;
254 return ores == (int64_t)*res;
255 }
257 inline bool
258 SafeSub(int32_t one, int32_t two, int32_t *res)
259 {
260 *res = uint32_t(one) - uint32_t(two);
261 int64_t ores = (int64_t)one - (int64_t)two;
262 return ores == (int64_t)*res;
263 }
265 inline bool
266 SafeMul(int32_t one, int32_t two, int32_t *res)
267 {
268 *res = uint32_t(one) * uint32_t(two);
269 int64_t ores = (int64_t)one * (int64_t)two;
270 return ores == (int64_t)*res;
271 }
273 extern bool
274 ToNumberSlow(ExclusiveContext *cx, Value v, double *dp);
276 // Variant of ToNumber which takes an ExclusiveContext instead of a JSContext.
277 // ToNumber is part of the API and can't use ExclusiveContext directly.
278 MOZ_ALWAYS_INLINE bool
279 ToNumber(ExclusiveContext *cx, const Value &v, double *out)
280 {
281 if (v.isNumber()) {
282 *out = v.toNumber();
283 return true;
284 }
285 return ToNumberSlow(cx, v, out);
286 }
288 /*
289 * Thread safe variants of number conversion functions.
290 */
292 bool
293 NonObjectToNumberSlow(ThreadSafeContext *cx, Value v, double *out);
295 inline bool
296 NonObjectToNumber(ThreadSafeContext *cx, const Value &v, double *out)
297 {
298 if (v.isNumber()) {
299 *out = v.toNumber();
300 return true;
301 }
302 return NonObjectToNumberSlow(cx, v, out);
303 }
305 bool
306 NonObjectToInt32Slow(ThreadSafeContext *cx, const Value &v, int32_t *out);
308 inline bool
309 NonObjectToInt32(ThreadSafeContext *cx, const Value &v, int32_t *out)
310 {
311 if (v.isInt32()) {
312 *out = v.toInt32();
313 return true;
314 }
315 return NonObjectToInt32Slow(cx, v, out);
316 }
318 bool
319 NonObjectToUint32Slow(ThreadSafeContext *cx, const Value &v, uint32_t *out);
321 MOZ_ALWAYS_INLINE bool
322 NonObjectToUint32(ThreadSafeContext *cx, const Value &v, uint32_t *out)
323 {
324 if (v.isInt32()) {
325 *out = uint32_t(v.toInt32());
326 return true;
327 }
328 return NonObjectToUint32Slow(cx, v, out);
329 }
331 } /* namespace js */
333 #endif /* jsnum_h */