📄 jsnum.c
字号:
}JSBooljs_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip){ jsdouble d; if (!js_ValueToNumber(cx, v, &d)) return JS_FALSE; return js_DoubleToECMAInt32(cx, d, ip);}JSBooljs_DoubleToECMAInt32(JSContext *cx, jsdouble d, int32 *ip){ jsdouble two32 = 4294967296.0; jsdouble two31 = 2147483648.0; if (!JSDOUBLE_IS_FINITE(d) || d == 0) { *ip = 0; return JS_TRUE; } d = fmod(d, two32); d = (d >= 0) ? floor(d) : ceil(d) + two32; if (d >= two31) *ip = (int32)(d - two32); else *ip = (int32)d; return JS_TRUE;}JSBooljs_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip){ jsdouble d; if (!js_ValueToNumber(cx, v, &d)) return JS_FALSE; return js_DoubleToECMAUint32(cx, d, ip);}JSBooljs_DoubleToECMAUint32(JSContext *cx, jsdouble d, uint32 *ip){ JSBool neg; jsdouble two32 = 4294967296.0; if (!JSDOUBLE_IS_FINITE(d) || d == 0) { *ip = 0; return JS_TRUE; } neg = (d < 0); d = floor(neg ? -d : d); d = neg ? -d : d; d = fmod(d, two32); d = (d >= 0) ? d : d + two32; *ip = (uint32)d; return JS_TRUE;}JSBooljs_ValueToInt32(JSContext *cx, jsval v, int32 *ip){ jsdouble d; JSString *str; if (JSVAL_IS_INT(v)) { *ip = JSVAL_TO_INT(v); return JS_TRUE; } if (!js_ValueToNumber(cx, v, &d)) return JS_FALSE; if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) { str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); if (str) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT, JS_GetStringBytes(str)); } return JS_FALSE; } *ip = (int32)floor(d + 0.5); /* Round to nearest */ return JS_TRUE;}JSBooljs_ValueToUint16(JSContext *cx, jsval v, uint16 *ip){ jsdouble d; jsuint i, m; JSBool neg; if (!js_ValueToNumber(cx, v, &d)) return JS_FALSE; if (d == 0 || !JSDOUBLE_IS_FINITE(d)) { *ip = 0; return JS_TRUE; } i = (jsuint)d; if ((jsdouble)i == d) { *ip = (uint16)i; return JS_TRUE; } neg = (d < 0); d = floor(neg ? -d : d); d = neg ? -d : d; m = JS_BIT(16); d = fmod(d, (double)m); if (d < 0) d += m; *ip = (uint16) d; return JS_TRUE;}jsdoublejs_DoubleToInteger(jsdouble d){ JSBool neg; if (d == 0) return d; if (!JSDOUBLE_IS_FINITE(d)) { if (JSDOUBLE_IS_NaN(d)) return 0; return d; } neg = (d < 0); d = floor(neg ? -d : d); return neg ? -d : d;}JSBooljs_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp){ char cbuf[32]; size_t i; char *cstr, *istr, *estr; JSBool negative; jsdouble d; const jschar *s1 = js_SkipWhiteSpace(s); size_t length = js_strlen(s1); /* Use cbuf to avoid malloc */ if (length >= sizeof cbuf) { cstr = (char *) JS_malloc(cx, length + 1); if (!cstr) return JS_FALSE; } else { cstr = cbuf; } for (i = 0; i <= length; i++) { if (s1[i] >> 8) { cstr[i] = 0; break; } cstr[i] = (char)s1[i]; } istr = cstr; if ((negative = (*istr == '-')) != 0 || *istr == '+') istr++; if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) { d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity); estr = istr + 8; } else { int err; d = JS_strtod(cstr, &estr, &err); if (err == JS_DTOA_ENOMEM) { JS_ReportOutOfMemory(cx); if (cstr != cbuf) JS_free(cx, cstr); return JS_FALSE; } if (err == JS_DTOA_ERANGE) { if (d == HUGE_VAL) d = *cx->runtime->jsPositiveInfinity; else if (d == -HUGE_VAL) d = *cx->runtime->jsNegativeInfinity; }#ifdef HPUX if (d == 0.0 && negative) { /* * "-0", "-1e-2000" come out as positive zero * here on HPUX. Force a negative zero instead. */ JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT; JSDOUBLE_LO32(d) = 0; }#endif } i = estr - cstr; if (cstr != cbuf) JS_free(cx, cstr); *ep = i ? s1 + i : s; *dp = d; return JS_TRUE;}struct BinaryDigitReader{ uintN base; /* Base of number; must be a power of 2 */ uintN digit; /* Current digit value in radix given by base */ uintN digitMask; /* Mask to extract the next bit from digit */ const jschar *digits; /* Pointer to the remaining digits */ const jschar *end; /* Pointer to first non-digit */};/* Return the next binary digit from the number or -1 if done */static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr){ intN bit; if (bdr->digitMask == 0) { uintN c; if (bdr->digits == bdr->end) return -1; c = *bdr->digits++; if ('0' <= c && c <= '9') bdr->digit = c - '0'; else if ('a' <= c && c <= 'z') bdr->digit = c - 'a' + 10; else bdr->digit = c - 'A' + 10; bdr->digitMask = bdr->base >> 1; } bit = (bdr->digit & bdr->digitMask) != 0; bdr->digitMask >>= 1; return bit;}JSBooljs_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, jsdouble *dp){ JSBool negative; jsdouble value; const jschar *start; const jschar *s1 = js_SkipWhiteSpace(s); if ((negative = (*s1 == '-')) != 0 || *s1 == '+') s1++; if (base == 0) { /* No base supplied, or some base that evaluated to 0. */ if (*s1 == '0') { /* It's either hex or octal; only increment char if str isn't '0' */ if (s1[1] == 'X' || s1[1] == 'x') { /* Hex */ s1 += 2; base = 16; } else { /* Octal */ base = 8; } } else { base = 10; /* Default to decimal. */ } } else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x')) { /* If base is 16, ignore hex prefix. */ s1 += 2; } /* * Done with the preliminaries; find some prefix of the string that's * a number in the given base. */ start = s1; /* Mark - if string is empty, we return NaN. */ value = 0.0; for (;;) { uintN digit; jschar c = *s1; if ('0' <= c && c <= '9') digit = c - '0'; else if ('a' <= c && c <= 'z') digit = c - 'a' + 10; else if ('A' <= c && c <= 'Z') digit = c - 'A' + 10; else break; if (digit >= (uintN)base) break; value = value * base + digit; s1++; } if (value >= 9007199254740992.0) { if (base == 10) { /* * If we're accumulating a decimal number and the number is >= * 2^53, then the result from the repeated multiply-add above may * be inaccurate. Call JS_strtod to get the correct answer. */ size_t i; size_t length = s1 - start; char *cstr = (char *) JS_malloc(cx, length + 1); char *estr; int err=0; if (!cstr) return JS_FALSE; for (i = 0; i != length; i++) cstr[i] = (char)start[i]; cstr[length] = 0; value = JS_strtod(cstr, &estr, &err); if (err == JS_DTOA_ENOMEM) { JS_ReportOutOfMemory(cx); JS_free(cx, cstr); return JS_FALSE; } if (err == JS_DTOA_ERANGE && value == HUGE_VAL) value = *cx->runtime->jsPositiveInfinity; JS_free(cx, cstr); } else if ((base & (base - 1)) == 0) { /* * The number may also be inaccurate for power-of-two bases. This * happens if the addition in value * base + digit causes a round- * down to an even least significant mantissa bit when the first * dropped bit is a one. If any of the following digits in the * number (which haven't been added in yet) are nonzero, then the * correct action would have been to round up instead of down. An * example occurs when reading the number 0x1000000000000081, which * rounds to 0x1000000000000000 instead of 0x1000000000000100. */ struct BinaryDigitReader bdr; intN bit, bit2; intN j; bdr.base = base; bdr.digitMask = 0; bdr.digits = start; bdr.end = s1; value = 0.0; /* Skip leading zeros. */ do { bit = GetNextBinaryDigit(&bdr); } while (bit == 0); if (bit == 1) { /* Gather the 53 significant bits (including the leading 1) */ value = 1.0; for (j = 52; j; j--) { bit = GetNextBinaryDigit(&bdr); if (bit < 0) goto done; value = value*2 + bit; } /* bit2 is the 54th bit (the first dropped from the mantissa) */ bit2 = GetNextBinaryDigit(&bdr); if (bit2 >= 0) { jsdouble factor = 2.0; intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */ intN bit3; while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) { sticky |= bit3; factor *= 2; } value += bit2 & (bit | sticky); value *= factor; } done:; } } } /* We don't worry about inaccurate numbers for any other base. */ if (s1 == start) { *dp = 0.0; *ep = s; } else { *dp = negative ? -value : value; *ep = s1; } return JS_TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -