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))
163 return String(UString::from(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) {
219 Object err = Error::create(exec,RangeError);
220 exec->setException(err);
235 return String(s+UString::from(x));
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))
261 return String(UString::from(x));
264 Value fractionDigits = args[0];
265 if (args.
size() > 0) {
267 if (f < 0 || f > 20) {
268 Object err = Error::create(exec,RangeError);
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) {
369 Object err = Error::create(exec, RangeError,
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) {
400 return String(s+m+
"e+"+UString::from(e));
402 return String(s+m+
"e-"+UString::from(-e));
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));
Represents the current state of script execution.
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
The initial value of Function.prototype (and thus all objects created with the Function constructor)
Represents an Identifier for a Javascript object.
Base class for all function objects.
Object builtinNumberPrototype() const
Returns the builtin "Number.prototype" object.
Represents an primitive Null value.
Represents an primitive Number value.
Value internalValue() const
Returns the internal value of the object.
Represents an primitive String value.
UString substr(int pos=0, int len=-1) const
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)
bool isA(Type t) const
Checks whether or not the value is of a particular tpye.
int toInteger(ExecState *exec) const
Performs the ToInteger type conversion operation on this value (ECMA 9.4)
double toNumber(ExecState *exec) const
Performs the ToNumber type conversion operation on this value (ECMA 9.3)