1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsnum.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jsnum_h 1.11 +#define jsnum_h 1.12 + 1.13 +#include "mozilla/FloatingPoint.h" 1.14 + 1.15 +#include "NamespaceImports.h" 1.16 + 1.17 +#include "vm/NumericConversions.h" 1.18 + 1.19 +namespace js { 1.20 + 1.21 +class StringBuffer; 1.22 + 1.23 +extern bool 1.24 +InitRuntimeNumberState(JSRuntime *rt); 1.25 + 1.26 +#if !EXPOSE_INTL_API 1.27 +extern void 1.28 +FinishRuntimeNumberState(JSRuntime *rt); 1.29 +#endif 1.30 + 1.31 +} /* namespace js */ 1.32 + 1.33 +/* Initialize the Number class, returning its prototype object. */ 1.34 +extern JSObject * 1.35 +js_InitNumberClass(JSContext *cx, js::HandleObject obj); 1.36 + 1.37 +/* 1.38 + * String constants for global function names, used in jsapi.c and jsnum.c. 1.39 + */ 1.40 +extern const char js_isNaN_str[]; 1.41 +extern const char js_isFinite_str[]; 1.42 +extern const char js_parseFloat_str[]; 1.43 +extern const char js_parseInt_str[]; 1.44 + 1.45 +class JSAtom; 1.46 + 1.47 +namespace js { 1.48 + 1.49 +/* 1.50 + * When base == 10, this function implements ToString() as specified by 1.51 + * ECMA-262-5 section 9.8.1; but note that it handles integers specially for 1.52 + * performance. See also js::NumberToCString(). 1.53 + */ 1.54 +template <js::AllowGC allowGC> 1.55 +extern JSString * 1.56 +NumberToString(js::ThreadSafeContext *cx, double d); 1.57 + 1.58 +extern JSAtom * 1.59 +NumberToAtom(js::ExclusiveContext *cx, double d); 1.60 + 1.61 +template <AllowGC allowGC> 1.62 +extern JSFlatString * 1.63 +Int32ToString(ThreadSafeContext *cx, int32_t i); 1.64 + 1.65 +extern JSAtom * 1.66 +Int32ToAtom(ExclusiveContext *cx, int32_t si); 1.67 + 1.68 +/* 1.69 + * Convert an integer or double (contained in the given value) to a string and 1.70 + * append to the given buffer. 1.71 + */ 1.72 +extern bool JS_FASTCALL 1.73 +NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb); 1.74 + 1.75 +/* Same as js_NumberToString, different signature. */ 1.76 +extern JSFlatString * 1.77 +NumberToString(JSContext *cx, double d); 1.78 + 1.79 +extern JSFlatString * 1.80 +IndexToString(JSContext *cx, uint32_t index); 1.81 + 1.82 +/* 1.83 + * Usually a small amount of static storage is enough, but sometimes we need 1.84 + * to dynamically allocate much more. This struct encapsulates that. 1.85 + * Dynamically allocated memory will be freed when the object is destroyed. 1.86 + */ 1.87 +struct ToCStringBuf 1.88 +{ 1.89 + /* 1.90 + * The longest possible result that would need to fit in sbuf is 1.91 + * (-0x80000000).toString(2), which has length 33. Longer cases are 1.92 + * possible, but they'll go in dbuf. 1.93 + */ 1.94 + static const size_t sbufSize = 34; 1.95 + char sbuf[sbufSize]; 1.96 + char *dbuf; 1.97 + 1.98 + ToCStringBuf(); 1.99 + ~ToCStringBuf(); 1.100 +}; 1.101 + 1.102 +/* 1.103 + * Convert a number to a C string. When base==10, this function implements 1.104 + * ToString() as specified by ECMA-262-5 section 9.8.1. It handles integral 1.105 + * values cheaply. Return nullptr if we ran out of memory. See also 1.106 + * js_NumberToCString(). 1.107 + */ 1.108 +extern char * 1.109 +NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10); 1.110 + 1.111 +/* 1.112 + * The largest positive integer such that all positive integers less than it 1.113 + * may be precisely represented using the IEEE-754 double-precision format. 1.114 + */ 1.115 +const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53; 1.116 + 1.117 +/* 1.118 + * Parse a decimal number encoded in |chars|. The decimal number must be 1.119 + * sufficiently small that it will not overflow the integrally-precise range of 1.120 + * the double type -- that is, the number will be smaller than 1.121 + * DOUBLE_INTEGRAL_PRECISION_LIMIT 1.122 + */ 1.123 +extern double 1.124 +ParseDecimalNumber(const JS::TwoByteChars chars); 1.125 + 1.126 +/* 1.127 + * Compute the positive integer of the given base described immediately at the 1.128 + * start of the range [start, end) -- no whitespace-skipping, no magical 1.129 + * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just 1.130 + * reading the digits of the integer. Return the index one past the end of the 1.131 + * digits of the integer in *endp, and return the integer itself in *dp. If 1.132 + * base is 10 or a power of two the returned integer is the closest possible 1.133 + * double; otherwise extremely large integers may be slightly inaccurate. 1.134 + * 1.135 + * If [start, end) does not begin with a number with the specified base, 1.136 + * *dp == 0 and *endp == start upon return. 1.137 + */ 1.138 +extern bool 1.139 +GetPrefixInteger(ThreadSafeContext *cx, const jschar *start, const jschar *end, int base, 1.140 + const jschar **endp, double *dp); 1.141 + 1.142 +/* 1.143 + * This is like GetPrefixInteger, but only deals with base 10, and doesn't have 1.144 + * and |endp| outparam. It should only be used when the jschars are known to 1.145 + * only contain digits. 1.146 + */ 1.147 +extern bool 1.148 +GetDecimalInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, double *dp); 1.149 + 1.150 +extern bool 1.151 +StringToNumber(ThreadSafeContext *cx, JSString *str, double *result); 1.152 + 1.153 +/* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */ 1.154 +MOZ_ALWAYS_INLINE bool 1.155 +ToNumber(JSContext *cx, JS::MutableHandleValue vp) 1.156 +{ 1.157 + if (vp.isNumber()) 1.158 + return true; 1.159 + double d; 1.160 + extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp); 1.161 + if (!ToNumberSlow(cx, vp, &d)) 1.162 + return false; 1.163 + 1.164 + vp.setNumber(d); 1.165 + return true; 1.166 +} 1.167 + 1.168 +bool 1.169 +num_parseInt(JSContext *cx, unsigned argc, Value *vp); 1.170 + 1.171 +} /* namespace js */ 1.172 + 1.173 +/* 1.174 + * Similar to strtod except that it replaces overflows with infinities of the 1.175 + * correct sign, and underflows with zeros of the correct sign. Guaranteed to 1.176 + * return the closest double number to the given input in dp. 1.177 + * 1.178 + * Also allows inputs of the form [+|-]Infinity, which produce an infinity of 1.179 + * the appropriate sign. The case of the "Infinity" string must match exactly. 1.180 + * If the string does not contain a number, set *ep to s and return 0.0 in dp. 1.181 + * Return false if out of memory. 1.182 + */ 1.183 +extern bool 1.184 +js_strtod(js::ThreadSafeContext *cx, const jschar *s, const jschar *send, 1.185 + const jschar **ep, double *dp); 1.186 + 1.187 +extern bool 1.188 +js_num_toString(JSContext *cx, unsigned argc, js::Value *vp); 1.189 + 1.190 +extern bool 1.191 +js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp); 1.192 + 1.193 +namespace js { 1.194 + 1.195 +static MOZ_ALWAYS_INLINE bool 1.196 +ValueFitsInInt32(const Value &v, int32_t *pi) 1.197 +{ 1.198 + if (v.isInt32()) { 1.199 + *pi = v.toInt32(); 1.200 + return true; 1.201 + } 1.202 + return v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), pi); 1.203 +} 1.204 + 1.205 +/* 1.206 + * Returns true if the given value is definitely an index: that is, the value 1.207 + * is a number that's an unsigned 32-bit integer. 1.208 + * 1.209 + * This method prioritizes common-case speed over accuracy in every case. It 1.210 + * can produce false negatives (but not false positives): some values which are 1.211 + * indexes will be reported not to be indexes by this method. Users must 1.212 + * consider this possibility when using this method. 1.213 + */ 1.214 +static MOZ_ALWAYS_INLINE bool 1.215 +IsDefinitelyIndex(const Value &v, uint32_t *indexp) 1.216 +{ 1.217 + if (v.isInt32() && v.toInt32() >= 0) { 1.218 + *indexp = v.toInt32(); 1.219 + return true; 1.220 + } 1.221 + 1.222 + int32_t i; 1.223 + if (v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), &i) && i >= 0) { 1.224 + *indexp = uint32_t(i); 1.225 + return true; 1.226 + } 1.227 + 1.228 + return false; 1.229 +} 1.230 + 1.231 +/* ES5 9.4 ToInteger. */ 1.232 +static inline bool 1.233 +ToInteger(JSContext *cx, HandleValue v, double *dp) 1.234 +{ 1.235 + if (v.isInt32()) { 1.236 + *dp = v.toInt32(); 1.237 + return true; 1.238 + } 1.239 + if (v.isDouble()) { 1.240 + *dp = v.toDouble(); 1.241 + } else { 1.242 + extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp); 1.243 + if (!ToNumberSlow(cx, v, dp)) 1.244 + return false; 1.245 + } 1.246 + *dp = ToInteger(*dp); 1.247 + return true; 1.248 +} 1.249 + 1.250 +inline bool 1.251 +SafeAdd(int32_t one, int32_t two, int32_t *res) 1.252 +{ 1.253 + // Use unsigned for the 32-bit operation since signed overflow gets 1.254 + // undefined behavior. 1.255 + *res = uint32_t(one) + uint32_t(two); 1.256 + int64_t ores = (int64_t)one + (int64_t)two; 1.257 + return ores == (int64_t)*res; 1.258 +} 1.259 + 1.260 +inline bool 1.261 +SafeSub(int32_t one, int32_t two, int32_t *res) 1.262 +{ 1.263 + *res = uint32_t(one) - uint32_t(two); 1.264 + int64_t ores = (int64_t)one - (int64_t)two; 1.265 + return ores == (int64_t)*res; 1.266 +} 1.267 + 1.268 +inline bool 1.269 +SafeMul(int32_t one, int32_t two, int32_t *res) 1.270 +{ 1.271 + *res = uint32_t(one) * uint32_t(two); 1.272 + int64_t ores = (int64_t)one * (int64_t)two; 1.273 + return ores == (int64_t)*res; 1.274 +} 1.275 + 1.276 +extern bool 1.277 +ToNumberSlow(ExclusiveContext *cx, Value v, double *dp); 1.278 + 1.279 +// Variant of ToNumber which takes an ExclusiveContext instead of a JSContext. 1.280 +// ToNumber is part of the API and can't use ExclusiveContext directly. 1.281 +MOZ_ALWAYS_INLINE bool 1.282 +ToNumber(ExclusiveContext *cx, const Value &v, double *out) 1.283 +{ 1.284 + if (v.isNumber()) { 1.285 + *out = v.toNumber(); 1.286 + return true; 1.287 + } 1.288 + return ToNumberSlow(cx, v, out); 1.289 +} 1.290 + 1.291 +/* 1.292 + * Thread safe variants of number conversion functions. 1.293 + */ 1.294 + 1.295 +bool 1.296 +NonObjectToNumberSlow(ThreadSafeContext *cx, Value v, double *out); 1.297 + 1.298 +inline bool 1.299 +NonObjectToNumber(ThreadSafeContext *cx, const Value &v, double *out) 1.300 +{ 1.301 + if (v.isNumber()) { 1.302 + *out = v.toNumber(); 1.303 + return true; 1.304 + } 1.305 + return NonObjectToNumberSlow(cx, v, out); 1.306 +} 1.307 + 1.308 +bool 1.309 +NonObjectToInt32Slow(ThreadSafeContext *cx, const Value &v, int32_t *out); 1.310 + 1.311 +inline bool 1.312 +NonObjectToInt32(ThreadSafeContext *cx, const Value &v, int32_t *out) 1.313 +{ 1.314 + if (v.isInt32()) { 1.315 + *out = v.toInt32(); 1.316 + return true; 1.317 + } 1.318 + return NonObjectToInt32Slow(cx, v, out); 1.319 +} 1.320 + 1.321 +bool 1.322 +NonObjectToUint32Slow(ThreadSafeContext *cx, const Value &v, uint32_t *out); 1.323 + 1.324 +MOZ_ALWAYS_INLINE bool 1.325 +NonObjectToUint32(ThreadSafeContext *cx, const Value &v, uint32_t *out) 1.326 +{ 1.327 + if (v.isInt32()) { 1.328 + *out = uint32_t(v.toInt32()); 1.329 + return true; 1.330 + } 1.331 + return NonObjectToUint32Slow(cx, v, out); 1.332 +} 1.333 + 1.334 +} /* namespace js */ 1.335 + 1.336 +#endif /* jsnum_h */