26 #include "interpreter.h" 27 #include "operations.h" 28 #include "number_object.h" 29 #include "error_object.h" 32 #include "number_object.lut.h" 41 const ClassInfo NumberInstanceImp::info = {
"Number", 0, 0, 0};
43 NumberInstanceImp::NumberInstanceImp(ObjectImp *proto)
51 NumberPrototypeImp::NumberPrototypeImp(
ExecState *exec,
52 ObjectPrototypeImp *objProto,
54 : NumberInstanceImp(objProto)
57 setInternalValue(NumberImp::zero());
61 putDirect(toStringPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToString,
62 1,toStringPropertyName),DontEnum);
63 putDirect(toLocaleStringPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToLocaleString,
64 0,toLocaleStringPropertyName),DontEnum);
65 putDirect(valueOfPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ValueOf,
66 0,valueOfPropertyName),DontEnum);
67 putDirect(
"toFixed",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToFixed,
68 1,
"toFixed"),DontEnum);
69 putDirect(
"toExponential",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToExponential,
70 1,
"toExponential"),DontEnum);
71 putDirect(
"toPrecision",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToPrecision,
72 1,
"toPrecision"),DontEnum);
83 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
88 bool NumberProtoFuncImp::implementsCall()
const 93 static UString integer_part_noexp(
double d)
97 char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &signDummy, NULL);
98 int length = strlen(result);
101 UString str = d < 0 ?
"-" :
"";
102 if (decimalPoint == 9999) {
104 }
else if (decimalPoint <= 0) {
109 if (length <= decimalPoint) {
110 buf = (
char*)malloc(decimalPoint+1);
112 memset(buf+length,
'0',decimalPoint-length);
114 buf = (
char*)malloc(decimalPoint+1);
115 strncpy(buf,result,decimalPoint);
118 buf[decimalPoint] =
'\0';
123 kjs_freedtoa(result);
128 static UString char_sequence(
char c,
int count)
130 char *buf = (
char*)malloc(count+1);
144 KJS_CHECK_THIS( NumberInstanceImp, thisObj );
151 if (!args.
isEmpty() && args[0].type() != UndefinedType)
152 radix = args[0].toInteger(exec);
153 if (radix < 2 || radix > 36 || radix == 10)
156 const char digits[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
162 if (isNaN(x) || isInf(x))
173 char *dot = s +
sizeof(s) / 2;
177 *--p = digits[int(fmod(d,
double(radix)))];
179 }
while ((d <= -1.0 || d >= 1.0) && p > s);
182 const double eps = 0.001;
183 if (d < -eps || d > eps) {
187 *dot++ = digits[int(d)];
189 }
while ((d < -eps || d > eps) && dot - s <
int(
sizeof(s)) - 1);
210 Value fractionDigits = args[0];
212 double fd = fractionDigits.
toNumber(exec);
215 }
else if (!isInf(fd)) {
218 if (f < 0 || f > 20) {
220 exec->setException(err);
237 double n = floor(x*pow(10.0,f));
238 if (fabs(n/pow(10.0,f)-x) > fabs((n+1)/pow(10.0,f)-x))
241 UString m = integer_part_noexp(n);
246 for (
int i = 0; i < f+1-k; i++)
250 assert(k == m.size());
257 case ToExponential: {
260 if (isNaN(x) || isInf(x))
264 Value fractionDigits = args[0];
265 if (args.
size() > 0) {
267 if (f < 0 || f > 20) {
269 exec->setException(err);
274 int decimalAdjust = 0;
275 if (!fractionDigits.
isA(UndefinedType)) {
276 double logx = floor(log10(fabs(x)));
278 double fx = floor(x*pow(10.0,f))/pow(10.0,f);
279 double cx = ceil(x*pow(10.0,f))/pow(10.0,f);
281 if (fabs(fx-x) < fabs(cx-x))
286 decimalAdjust = int(logx);
296 char *result = kjs_dtoa(x, 0, 0, &decimalPoint, &sign, NULL);
297 int length = strlen(result);
298 decimalPoint += decimalAdjust;
305 if (decimalPoint == 999) {
306 strcpy(buf + i, result);
308 buf[i++] = result[0];
310 if (fractionDigits.
isA(UndefinedType))
313 if (length > 1 && f > 0) {
315 int haveFDigits = length-1;
316 if (f < haveFDigits) {
317 strncpy(buf+i,result+1, f);
321 strcpy(buf+i,result+1);
323 for (
int j = 0; j < f-haveFDigits; j++)
329 buf[i++] = (decimalPoint >= 0) ?
'+' :
'-';
332 int exponential = decimalPoint - 1;
333 if (exponential < 0) {
334 exponential = exponential * -1;
336 if (exponential >= 100) {
337 buf[i++] =
'0' + exponential / 100;
339 if (exponential >= 10) {
340 buf[i++] =
'0' + (exponential % 100) / 10;
342 buf[i++] =
'0' + exponential % 10;
348 kjs_freedtoa(result);
357 int p = args[0].toInteger(exec);
359 if (args[0].isA(UndefinedType) || isNaN(x) || isInf(x))
368 if (p < 1 || p > 21) {
370 "toPrecision() argument must be between 1 and 21");
371 exec->setException(err);
378 double n = floor(x/pow(10.0,e-p+1));
379 if (n < pow(10.0,p-1)) {
382 n = floor(x/pow(10.0,e-p+1));
383 if (n >= pow(10.0,p)) {
386 e = int(log10(x/n)) + p - 1;
390 if (fabs((n+1)*pow(10.0,e-p+1)-x) < fabs(n*pow(10.0,e-p+1)-x))
392 assert(pow(10.0,p-1) <= n);
393 assert(n < pow(10.0,p));
395 m = integer_part_noexp(n);
396 if (e < -6 || e >= p) {
406 m = char_sequence(
'0',p);
420 return String(s+
"0."+char_sequence(
'0',-(e+1))+m);
430 const ClassInfo NumberObjectImp::info = {
"Function", &InternalFunctionImp::info, &numberTable, 0};
441 NumberObjectImp::NumberObjectImp(
ExecState * ,
443 NumberPrototypeImp *numberProto)
448 putDirect(prototypePropertyName, numberProto, DontEnum|DontDelete|ReadOnly);
451 putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
456 return lookupGetValue<NumberObjectImp, InternalFunctionImp>( exec, propertyName, &numberTable, this );
459 Value NumberObjectImp::getValueProperty(
ExecState *,
int token)
const 470 return Number(1.7976931348623157E+308);
477 bool NumberObjectImp::implementsConstruct()
const 487 Object obj(
new NumberInstanceImp(proto));
493 n = args[0].toNumber(exec);
495 obj.setInternalValue(n);
500 bool NumberObjectImp::implementsCall()
const 511 return Number(args[0].toNumber(exec));
Value objects are act as wrappers ("smart pointers") around ValueImp objects and their descendents...
UString toString(ExecState *exec) const
Performs the ToString type conversion operation on this value (ECMA 9.8)
double toNumber(ExecState *exec) const
Performs the ToNumber type conversion operation on this value (ECMA 9.3)
Base class for all function objects.
static UString from(int i)
Constructs a string from an int.
UString substr(int pos=0, int len=-1) const
Represents an primitive Number value.
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
Represents an primitive Null value.
static Object create(ExecState *exec, ErrorType errtype=GeneralError, const char *message=0, int lineno=-1, int sourceId=-1)
Factory method for error objects.
The initial value of Function.prototype (and thus all objects created with the Function constructor) ...
bool isA(Type t) const
Checks whether or not the value is of a particular tpye.
Object builtinNumberPrototype() const
Returns the builtin "Number.prototype" object.
int toInteger(ExecState *exec) const
Performs the ToInteger type conversion operation on this value (ECMA 9.4)
Represents an primitive String value.
Value internalValue() const
Returns the internal value of the object.
Represents the current state of script execution.
Represents an Identifier for a Javascript object.