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/. */
10 #include "mozilla/FloatingPoint.h"
11 #include "mozilla/Range.h"
13 #include "NamespaceImports.h"
15 #include "js/Conversions.h"
22 InitRuntimeNumberState(JSRuntime
* rt
);
26 FinishRuntimeNumberState(JSRuntime
* rt
);
31 /* Initialize the Number class, returning its prototype object. */
33 js_InitNumberClass(JSContext
* cx
, js::HandleObject obj
);
36 * String constants for global function names, used in jsapi.c and jsnum.c.
38 extern const char js_isNaN_str
[];
39 extern const char js_isFinite_str
[];
40 extern const char js_parseFloat_str
[];
41 extern const char js_parseInt_str
[];
48 * When base == 10, this function implements ToString() as specified by
49 * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
50 * performance. See also js::NumberToCString().
52 template <AllowGC allowGC
>
54 NumberToString(ExclusiveContext
* cx
, double d
);
57 NumberToAtom(ExclusiveContext
* cx
, double d
);
59 template <AllowGC allowGC
>
61 Int32ToString(ExclusiveContext
* cx
, int32_t i
);
64 Int32ToAtom(ExclusiveContext
* cx
, int32_t si
);
67 * Convert an integer or double (contained in the given value) to a string and
68 * append to the given buffer.
70 extern bool JS_FASTCALL
71 NumberValueToStringBuffer(JSContext
* cx
, const Value
& v
, StringBuffer
& sb
);
73 /* Same as js_NumberToString, different signature. */
75 NumberToString(JSContext
* cx
, double d
);
78 IndexToString(JSContext
* cx
, uint32_t index
);
81 * Usually a small amount of static storage is enough, but sometimes we need
82 * to dynamically allocate much more. This struct encapsulates that.
83 * Dynamically allocated memory will be freed when the object is destroyed.
88 * The longest possible result that would need to fit in sbuf is
89 * (-0x80000000).toString(2), which has length 33. Longer cases are
90 * possible, but they'll go in dbuf.
92 static const size_t sbufSize
= 34;
101 * Convert a number to a C string. When base==10, this function implements
102 * ToString() as specified by ECMA-262-5 section 9.8.1. It handles integral
103 * values cheaply. Return nullptr if we ran out of memory. See also
104 * js_NumberToCString().
107 NumberToCString(JSContext
* cx
, ToCStringBuf
* cbuf
, double d
, int base
= 10);
110 * The largest positive integer such that all positive integers less than it
111 * may be precisely represented using the IEEE-754 double-precision format.
113 const double DOUBLE_INTEGRAL_PRECISION_LIMIT
= uint64_t(1) << 53;
116 * Parse a decimal number encoded in |chars|. The decimal number must be
117 * sufficiently small that it will not overflow the integrally-precise range of
118 * the double type -- that is, the number will be smaller than
119 * DOUBLE_INTEGRAL_PRECISION_LIMIT
121 template <typename CharT
>
123 ParseDecimalNumber(const mozilla::Range
<const CharT
> chars
);
126 * Compute the positive integer of the given base described immediately at the
127 * start of the range [start, end) -- no whitespace-skipping, no magical
128 * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just
129 * reading the digits of the integer. Return the index one past the end of the
130 * digits of the integer in *endp, and return the integer itself in *dp. If
131 * base is 10 or a power of two the returned integer is the closest possible
132 * double; otherwise extremely large integers may be slightly inaccurate.
134 * If [start, end) does not begin with a number with the specified base,
135 * *dp == 0 and *endp == start upon return.
137 template <typename CharT
>
139 GetPrefixInteger(ExclusiveContext
* cx
, const CharT
* start
, const CharT
* end
, int base
,
140 const CharT
** endp
, double* dp
);
143 * This is like GetPrefixInteger, but only deals with base 10, and doesn't have
144 * and |endp| outparam. It should only be used when the characters are known to
145 * only contain digits.
148 GetDecimalInteger(ExclusiveContext
* cx
, const char16_t
* start
, const char16_t
* end
, double* dp
);
151 StringToNumber(ExclusiveContext
* cx
, JSString
* str
, double* result
);
153 /* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
154 MOZ_ALWAYS_INLINE
bool
155 ToNumber(JSContext
* cx
, JS::MutableHandleValue vp
)
160 extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext
* cx
, Value v
, double* dp
);
161 if (!ToNumberSlow(cx
, vp
, &d
))
169 num_parseInt(JSContext
* cx
, unsigned argc
, Value
* vp
);
174 * Similar to strtod except that it replaces overflows with infinities of the
175 * correct sign, and underflows with zeros of the correct sign. Guaranteed to
176 * return the closest double number to the given input in dp.
178 * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
179 * the appropriate sign. The case of the "Infinity" string must match exactly.
180 * If the string does not contain a number, set *dEnd to begin and return 0.0
183 * Return false if out of memory.
185 template <typename CharT
>
187 js_strtod(js::ExclusiveContext
* cx
, const CharT
* begin
, const CharT
* end
,
188 const CharT
** dEnd
, double* d
);
191 js_num_toString(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
194 js_num_valueOf(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
198 static MOZ_ALWAYS_INLINE
bool
199 ValueFitsInInt32(const Value
& v
, int32_t* pi
)
205 return v
.isDouble() && mozilla::NumberIsInt32(v
.toDouble(), pi
);
209 * Returns true if the given value is definitely an index: that is, the value
210 * is a number that's an unsigned 32-bit integer.
212 * This method prioritizes common-case speed over accuracy in every case. It
213 * can produce false negatives (but not false positives): some values which are
214 * indexes will be reported not to be indexes by this method. Users must
215 * consider this possibility when using this method.
217 static MOZ_ALWAYS_INLINE
bool
218 IsDefinitelyIndex(const Value
& v
, uint32_t* indexp
)
220 if (v
.isInt32() && v
.toInt32() >= 0) {
221 *indexp
= v
.toInt32();
226 if (v
.isDouble() && mozilla::NumberIsInt32(v
.toDouble(), &i
) && i
>= 0) {
227 *indexp
= uint32_t(i
);
234 /* ES5 9.4 ToInteger. */
236 ToInteger(JSContext
* cx
, HandleValue v
, double* dp
)
245 extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext
* cx
, Value v
, double* dp
);
246 if (!ToNumberSlow(cx
, v
, dp
))
249 *dp
= JS::ToInteger(*dp
);
253 /* ES6 7.1.15 ToLength, but clamped to the [0,2^32-2] range. If the
254 * return value is false then *overflow will be true iff the value was
255 * not clampable to uint32_t range.
257 * For JSContext and ExclusiveContext.
260 bool ToLengthClamped(T
* cx
, HandleValue v
, uint32_t* out
, bool* overflow
);
263 SafeAdd(int32_t one
, int32_t two
, int32_t* res
)
265 // Use unsigned for the 32-bit operation since signed overflow gets
266 // undefined behavior.
267 *res
= uint32_t(one
) + uint32_t(two
);
268 int64_t ores
= (int64_t)one
+ (int64_t)two
;
269 return ores
== (int64_t)*res
;
273 SafeSub(int32_t one
, int32_t two
, int32_t* res
)
275 *res
= uint32_t(one
) - uint32_t(two
);
276 int64_t ores
= (int64_t)one
- (int64_t)two
;
277 return ores
== (int64_t)*res
;
281 SafeMul(int32_t one
, int32_t two
, int32_t* res
)
283 *res
= uint32_t(one
) * uint32_t(two
);
284 int64_t ores
= (int64_t)one
* (int64_t)two
;
285 return ores
== (int64_t)*res
;
289 ToNumberSlow(ExclusiveContext
* cx
, Value v
, double* dp
);
291 // Variant of ToNumber which takes an ExclusiveContext instead of a JSContext.
292 // ToNumber is part of the API and can't use ExclusiveContext directly.
293 MOZ_ALWAYS_INLINE
bool
294 ToNumber(ExclusiveContext
* cx
, const Value
& v
, double* out
)
300 return ToNumberSlow(cx
, v
, out
);