📄 jsnum.c
字号:
str = JS_NewString(cx, buf, size); if (!str) { JS_free(cx, buf); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); return JS_TRUE;}static JSBoolnum_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (JSVAL_IS_NUMBER((jsval)obj)) { *rval = (jsval)obj; return JS_TRUE; } if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) return JS_FALSE; *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); return JS_TRUE;}#define MAX_PRECISION 100static JSBoolnum_to(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode, jsint precisionMin, jsint precisionMax, jsint precisionOffset){ jsval v; jsdouble d, precision; JSString *str; char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)], *numStr; /* Use MAX_PRECISION+1 because precisionOffset can be 1 */ if (JSVAL_IS_NUMBER((jsval)obj)) { v = (jsval)obj; } else { if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) return JS_FALSE; v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); JS_ASSERT(JSVAL_IS_NUMBER(v)); } d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v); if (JSVAL_IS_VOID(argv[0])) { precision = 0.0; oneArgMode = zeroArgMode; } else { if (!js_ValueToNumber(cx, argv[0], &precision)) return JS_FALSE; precision = js_DoubleToInteger(precision); if (precision < precisionMin || precision > precisionMax) { numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision); if (!numStr) JS_ReportOutOfMemory(cx); else JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr); return JS_FALSE; } } numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d); if (!numStr) { JS_ReportOutOfMemory(cx); return JS_FALSE; } str = JS_NewStringCopyZ(cx, numStr); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); return JS_TRUE;}static JSBoolnum_toFixed(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ return num_to(cx, obj, argc, argv, rval, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0);}static JSBoolnum_toExponential(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0, MAX_PRECISION, 1);}static JSBoolnum_toPrecision(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0);}static JSFunctionSpec number_methods[] = {#if JS_HAS_TOSOURCE {js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER,0},#endif {js_toString_str, num_toString, 0,JSFUN_THISP_NUMBER,0}, {js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER,0}, {js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER,0}, {"toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER,0}, {"toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER,0}, {"toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER,0}, {0,0,0,0,0}};/* NB: Keep this in synch with number_constants[]. */enum nc_slot { NC_NaN, NC_POSITIVE_INFINITY, NC_NEGATIVE_INFINITY, NC_MAX_VALUE, NC_MIN_VALUE, NC_LIMIT};/* * Some to most C compilers forbid spelling these at compile time, or barf * if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState * using union jsdpun. */static JSConstDoubleSpec number_constants[] = { {0, js_NaN_str, 0,{0,0,0}}, {0, "POSITIVE_INFINITY", 0,{0,0,0}}, {0, "NEGATIVE_INFINITY", 0,{0,0,0}}, {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}}, {0, "MIN_VALUE", 0,{0,0,0}}, {0,0,0,{0,0,0}}};static jsdouble NaN;#if (defined XP_WIN || defined XP_OS2) && \ !defined WINCE && \ !defined __MWERKS__ && \ (defined _M_IX86 || \ (defined __GNUC__ && !defined __MINGW32__))/* * Set the exception mask to mask all exceptions and set the FPU precision * to 53 bit mantissa. * On Alpha platform this is handled via Compiler option. */#define FIX_FPU() _control87(MCW_EM | PC_53, MCW_EM | MCW_PC)#else#define FIX_FPU() ((void)0)#endifJSBooljs_InitRuntimeNumberState(JSContext *cx){ JSRuntime *rt; jsdpun u; struct lconv *locale; rt = cx->runtime; JS_ASSERT(!rt->jsNaN); FIX_FPU(); u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK; u.s.lo = 0xffffffff; number_constants[NC_NaN].dval = NaN = u.d; rt->jsNaN = js_NewDouble(cx, NaN, GCF_LOCK); if (!rt->jsNaN) return JS_FALSE; u.s.hi = JSDOUBLE_HI32_EXPMASK; u.s.lo = 0x00000000; number_constants[NC_POSITIVE_INFINITY].dval = u.d; rt->jsPositiveInfinity = js_NewDouble(cx, u.d, GCF_LOCK); if (!rt->jsPositiveInfinity) return JS_FALSE; u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK; u.s.lo = 0x00000000; number_constants[NC_NEGATIVE_INFINITY].dval = u.d; rt->jsNegativeInfinity = js_NewDouble(cx, u.d, GCF_LOCK); if (!rt->jsNegativeInfinity) return JS_FALSE; u.s.hi = 0; u.s.lo = 1; number_constants[NC_MIN_VALUE].dval = u.d; locale = localeconv(); rt->thousandsSeparator = JS_strdup(cx, locale->thousands_sep ? locale->thousands_sep : "'"); rt->decimalSeparator = JS_strdup(cx, locale->decimal_point ? locale->decimal_point : "."); rt->numGrouping = JS_strdup(cx, locale->grouping ? locale->grouping : "\3\0"); return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping;}voidjs_FinishRuntimeNumberState(JSContext *cx){ JSRuntime *rt = cx->runtime; js_UnlockGCThingRT(rt, rt->jsNaN); js_UnlockGCThingRT(rt, rt->jsNegativeInfinity); js_UnlockGCThingRT(rt, rt->jsPositiveInfinity); rt->jsNaN = NULL; rt->jsNegativeInfinity = NULL; rt->jsPositiveInfinity = NULL; JS_free(cx, (void *)rt->thousandsSeparator); JS_free(cx, (void *)rt->decimalSeparator); JS_free(cx, (void *)rt->numGrouping); rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;}JSObject *js_InitNumberClass(JSContext *cx, JSObject *obj){ JSObject *proto, *ctor; JSRuntime *rt; /* XXX must do at least once per new thread, so do it per JSContext... */ FIX_FPU(); if (!JS_DefineFunctions(cx, obj, number_functions)) return NULL; proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1, NULL, number_methods, NULL, NULL); if (!proto || !(ctor = JS_GetConstructor(cx, proto))) return NULL; OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_ZERO); if (!JS_DefineConstDoubles(cx, ctor, number_constants)) return NULL; /* ECMA 15.1.1.1 */ rt = cx->runtime; if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN), NULL, NULL, JSPROP_PERMANENT)) { return NULL; } /* ECMA 15.1.1.2 */ if (!JS_DefineProperty(cx, obj, js_Infinity_str, DOUBLE_TO_JSVAL(rt->jsPositiveInfinity), NULL, NULL, JSPROP_PERMANENT)) { return NULL; } return proto;}jsdouble *js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag){ jsdouble *dp; dp = (jsdouble *) js_NewGCThing(cx, gcflag | GCX_DOUBLE, sizeof(jsdouble)); if (!dp) return NULL; *dp = d; return dp;}voidjs_FinalizeDouble(JSContext *cx, jsdouble *dp){ *dp = NaN;}JSBooljs_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval){ jsdouble *dp; dp = js_NewDouble(cx, d, 0); if (!dp) return JS_FALSE; *rval = DOUBLE_TO_JSVAL(dp); return JS_TRUE;}JSBooljs_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval){ jsint i; if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { *rval = INT_TO_JSVAL(i); } else { if (!js_NewDoubleValue(cx, d, rval)) return JS_FALSE; } return JS_TRUE;}JSObject *js_NumberToObject(JSContext *cx, jsdouble d){ JSObject *obj; jsval v; obj = js_NewObject(cx, &js_NumberClass, NULL, NULL); if (!obj) return NULL; if (!js_NewNumberValue(cx, d, &v)) { cx->weakRoots.newborn[GCX_OBJECT] = NULL; return NULL; } OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v); return obj;}JSString *js_NumberToString(JSContext *cx, jsdouble d){ jsint i; char buf[DTOSTR_STANDARD_BUFFER_SIZE]; char *numStr; if (JSDOUBLE_IS_INT(d, i)) { numStr = IntToString(i, buf, sizeof buf); } else { numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d); if (!numStr) { JS_ReportOutOfMemory(cx); return NULL; } } return JS_NewStringCopyZ(cx, numStr);}JSBooljs_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp){ JSObject *obj; JSString *str; const jschar *bp, *ep; if (JSVAL_IS_OBJECT(v)) { obj = JSVAL_TO_OBJECT(v); if (!obj) { *dp = 0; return JS_TRUE; } if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &v)) return JS_FALSE; } if (JSVAL_IS_INT(v)) { *dp = (jsdouble)JSVAL_TO_INT(v); } else if (JSVAL_IS_DOUBLE(v)) { *dp = *JSVAL_TO_DOUBLE(v); } else if (JSVAL_IS_STRING(v)) { str = JSVAL_TO_STRING(v); /* * Note that ECMA doesn't treat a string beginning with a '0' as an * octal number here. This works because all such numbers will be * interpreted as decimal by js_strtod and will never get passed to * js_strtointeger (which would interpret them as octal). */ /* XXXbe js_strtod shouldn't require NUL termination */ bp = js_UndependString(cx, str); if (!bp) return JS_FALSE; if ((!js_strtod(cx, bp, &ep, dp) || js_SkipWhiteSpace(ep) != bp + str->length) && (!js_strtointeger(cx, bp, &ep, 0, dp) || js_SkipWhiteSpace(ep) != bp + str->length)) { goto badstr; } } else if (JSVAL_IS_BOOLEAN(v)) { *dp = JSVAL_TO_BOOLEAN(v) ? 1 : 0; } else {badstr: *dp = *cx->runtime->jsNaN; } return JS_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -