⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsnum.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): *   IBM Corp. * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS number type and wrapper class. */#include "jsstddef.h"#if defined(XP_WIN) || defined(XP_OS2)#include <float.h>#endif#include <math.h>#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsutil.h" /* Added by JSIFY */#include "jsapi.h"#include "jsatom.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsdtoa.h"#include "jsgc.h"#include "jsinterp.h"#include "jsnum.h"#include "jsobj.h"#include "jsopcode.h"#include "jsprf.h"#include "jsstr.h"static JSBoolnum_isNaN(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsdouble x;    if (!js_ValueToNumber(cx, argv[0], &x))	return JS_FALSE;    *rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));    return JS_TRUE;}static JSBoolnum_isFinite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsdouble x;    if (!js_ValueToNumber(cx, argv[0], &x))	return JS_FALSE;    *rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));    return JS_TRUE;}static JSBoolnum_parseFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSString *str;    jsdouble d;    const jschar *bp, *ep;    str = js_ValueToString(cx, argv[0]);    if (!str)	return JS_FALSE;    /* XXXbe js_strtod shouldn't require NUL termination */    bp = js_UndependString(cx, str);    if (!bp)	return JS_FALSE;    if (!js_strtod(cx, bp, &ep, &d))	return JS_FALSE;    if (ep == bp) {	*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);	return JS_TRUE;    }    return js_NewNumberValue(cx, d, rval);}/* See ECMA 15.1.2.2. */static JSBoolnum_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSString *str;    jsint radix;    jsdouble d;    const jschar *bp, *ep;    str = js_ValueToString(cx, argv[0]);    if (!str)	return JS_FALSE;    if (argc > 1) {	if (!js_ValueToECMAInt32(cx, argv[1], &radix))	    return JS_FALSE;    } else	radix = 0;    if (radix != 0 && (radix < 2 || radix > 36)) {	*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);	return JS_TRUE;    }    /* XXXbe js_strtointeger shouldn't require NUL termination */    bp = js_UndependString(cx, str);    if (!bp)	return JS_FALSE;    if (!js_strtointeger(cx, bp, &ep, radix, &d))	return JS_FALSE;    if (ep == bp) {	*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);	return JS_TRUE;    }    return js_NewNumberValue(cx, d, rval);}const char js_Infinity_str[]   = "Infinity";const char js_NaN_str[]        = "NaN";const char js_isNaN_str[]      = "isNaN";const char js_isFinite_str[]   = "isFinite";const char js_parseFloat_str[] = "parseFloat";const char js_parseInt_str[]   = "parseInt";static JSFunctionSpec number_functions[] = {    {"isNaN",           num_isNaN,              1,0,0},    {"isFinite",        num_isFinite,           1,0,0},    {"parseFloat",      num_parseFloat,         1,0,0},    {"parseInt",        num_parseInt,           2,0,0},    {0,0,0,0,0}};static JSClass number_class = {    "Number",    JSCLASS_HAS_PRIVATE,    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,    JSCLASS_NO_OPTIONAL_MEMBERS};static JSBoolNumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsdouble d;    jsval v;    if (argc != 0) {	if (!js_ValueToNumber(cx, argv[0], &d))	    return JS_FALSE;    } else {	d = 0.0;    }    if (!js_NewNumberValue(cx, d, &v))	return JS_FALSE;    if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {	*rval = v;	return JS_TRUE;    }    OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v);    return JS_TRUE;}#if JS_HAS_TOSOURCEstatic JSBoolnum_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsval v;    jsdouble d;    char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;    char buf[64];    JSString *str;    if (!JS_InstanceOf(cx, obj, &number_class, 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);    numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);    if (!numStr) {	JS_ReportOutOfMemory(cx);	return JS_FALSE;    }    JS_snprintf(buf, sizeof buf, "(new %s(%s))", number_class.name, numStr);    str = JS_NewStringCopyZ(cx, buf);    if (!str)	return JS_FALSE;    *rval = STRING_TO_JSVAL(str);    return JS_TRUE;}#endif/* The buf must be big enough for MIN_INT to fit including '-' and '\0'. */static char *IntToString(jsint i, char *buf, size_t bufSize){    char *cp;    jsuint u;        u = (i < 0) ? -i : i;    cp = buf + bufSize; /* one past last buffer cell */    *--cp = '\0';       /* null terminate the string to be */        /*     * Build the string from behind. We use multiply and subtraction     * instead of modulus because that's much faster.     */    do {        jsuint newu = u / 10;        *--cp = (char)(u - newu * 10) + '0';        u = newu;    } while (u != 0);        if (i < 0)        *--cp = '-';    return cp;}static JSBoolnum_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){  JSString *string;  string = JS_InternString (cx, "[type Object]");  if (string == NULL)    return JS_FALSE;  *rval = STRING_TO_JSVAL (string);  return JS_TRUE;#if 0    jsval v;    jsdouble d;    jsint base;    JSString *str;    if (!JS_InstanceOf(cx, obj, &number_class, 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);    base = 10;    if (argc != 0) {	if (!js_ValueToECMAInt32(cx, argv[0], &base))	    return JS_FALSE;	if (base < 2 || base > 36) {	    char numBuf[12];	    char *numStr = IntToString(base, numBuf, sizeof numBuf);	    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,	    			 numStr);	    return JS_FALSE;	}    }    if (base == 10)	str = js_NumberToString(cx, d);    else {	char *dStr = JS_dtobasestr(base, d);	if (!dStr) {	    JS_ReportOutOfMemory(cx);	    return JS_FALSE;	}	str = JS_NewStringCopyZ(cx, dStr);	free(dStr);    }    if (!str)	return JS_FALSE;    *rval = STRING_TO_JSVAL(str);    return JS_TRUE;#endif}static JSBoolnum_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,                   jsval *argv, jsval *rval){/* *  For now, forcibly ignore the first (or any) argument and return toString(). *  ECMA allows this, although it doesn't 'encourage it'. *  [The first argument is being reserved by ECMA and we don't want it confused *  with a radix] */    return num_toString(cx, obj, 0, argv, rval);}static JSBoolnum_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    if (!JS_InstanceOf(cx, obj, &number_class, argv))	return JS_FALSE;    *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);    return JS_TRUE;}#if JS_HAS_NUMBER_FORMATS#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 (!JS_InstanceOf(cx, obj, &number_class, 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);}#endif /* JS_HAS_NUMBER_FORMATS */static JSFunctionSpec number_methods[] = {#if JS_HAS_TOSOURCE    {js_toSource_str,       num_toSource,       0,0,0},#endif    {js_toString_str,	    num_toString,       0,0,0},    {js_toLocaleString_str, num_toLocaleString, 0,0,0},    {js_valueOf_str,	    num_valueOf,        0,0,0},#if JS_HAS_NUMBER_FORMATS    {"toFixed",             num_toFixed,        1,0,0},    {"toExponential",       num_toExponential,  1,0,0},    {"toPrecision",         num_toPrecision,    1,0,0},#endif    {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 __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;    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);    if (!rt->jsNaN || !js_LockGCThing(cx, 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);    if (!rt->jsPositiveInfinity ||        !js_LockGCThing(cx, 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);    if (!rt->jsNegativeInfinity ||        !js_LockGCThing(cx, rt->jsNegativeInfinity)) {        return JS_FALSE;    }    u.s.hi = 0;    u.s.lo = 1;    number_constants[NC_MIN_VALUE].dval = u.d;    return JS_TRUE;}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;}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, &number_class, 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -