js/src/jsnum.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial