25 #include "interpreter.h"
26 #include "operations.h"
27 #include "number_object.h"
28 #include "error_object.h"
31 #include "number_object.lut.h"
40 const ClassInfo NumberInstanceImp::info = {
"Number", 0, 0, 0};
42 NumberInstanceImp::NumberInstanceImp(ObjectImp *proto)
50 NumberPrototypeImp::NumberPrototypeImp(
ExecState *exec,
51 ObjectPrototypeImp *objProto,
53 : NumberInstanceImp(objProto)
56 setInternalValue(NumberImp::zero());
60 putDirect(toStringPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToString,
61 1,toStringPropertyName),DontEnum);
62 putDirect(toLocaleStringPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToLocaleString,
63 0,toLocaleStringPropertyName),DontEnum);
64 putDirect(valueOfPropertyName,
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ValueOf,
65 0,valueOfPropertyName),DontEnum);
66 putDirect(
"toFixed",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToFixed,
67 1,
"toFixed"),DontEnum);
68 putDirect(
"toExponential",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToExponential,
69 1,
"toExponential"),DontEnum);
70 putDirect(
"toPrecision",
new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToPrecision,
71 1,
"toPrecision"),DontEnum);
82 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
87 bool NumberProtoFuncImp::implementsCall()
const
92 static UString integer_part_noexp(
double d)
96 char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &signDummy, NULL);
97 int length = strlen(result);
100 UString str = d < 0 ?
"-" :
"";
101 if (decimalPoint == 9999) {
103 }
else if (decimalPoint <= 0) {
108 if (length <= decimalPoint) {
109 buf = (
char*)malloc(decimalPoint+1);
111 memset(buf+length,
'0',decimalPoint-length);
113 buf = (
char*)malloc(decimalPoint+1);
114 strncpy(buf,result,decimalPoint);
117 buf[decimalPoint] =
'\0';
122 kjs_freedtoa(result);
127 static UString char_sequence(
char c,
int count)
129 char *buf = (
char*)malloc(count+1);
143 KJS_CHECK_THIS( NumberInstanceImp, thisObj );
150 if (!args.
isEmpty() && args[0].type() != UndefinedType)
151 radix = args[0].toInteger(exec);
152 if (radix < 2 || radix > 36 || radix == 10)
155 const char digits[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
161 if (isNaN(x) || isInf(x))
162 return String(UString::from(x));
172 char *dot = s +
sizeof(s) / 2;
176 *--p = digits[int(fmod(d,
double(radix)))];
178 }
while ((d <= -1.0 || d >= 1.0) && p > s);
181 const double eps = 0.001;
182 if (d < -eps || d > eps) {
186 *dot++ = digits[int(d)];
188 }
while ((d < -eps || d > eps) && dot - s <
int(
sizeof(s)) - 1);
209 Value fractionDigits = args[0];
211 double fd = fractionDigits.
toNumber(exec);
214 }
else if (!isInf(fd)) {
217 if (f < 0 || f > 20) {
218 Object err = Error::create(exec,RangeError);
219 exec->setException(err);
234 return String(s+UString::from(x));
236 double n = floor(x*pow(10.0,f));
237 if (fabs(n/pow(10.0,f)-x) > fabs((n+1)/pow(10.0,f)-x))
240 UString m = integer_part_noexp(n);
245 for (
int i = 0; i < f+1-k; i++)
249 assert(k == m.size());
256 case ToExponential: {
259 if (isNaN(x) || isInf(x))
260 return String(UString::from(x));
263 Value fractionDigits = args[0];
264 if (args.
size() > 0) {
266 if (f < 0 || f > 20) {
267 Object err = Error::create(exec,RangeError);
268 exec->setException(err);
273 int decimalAdjust = 0;
274 if (!fractionDigits.
isA(UndefinedType)) {
275 double logx = floor(log10(fabs(x)));
277 double fx = floor(x*pow(10.0,f))/pow(10.0,f);
278 double cx = ceil(x*pow(10.0,f))/pow(10.0,f);
280 if (fabs(fx-x) < fabs(cx-x))
285 decimalAdjust = int(logx);
295 char *result = kjs_dtoa(x, 0, 0, &decimalPoint, &sign, NULL);
296 int length = strlen(result);
297 decimalPoint += decimalAdjust;
304 if (decimalPoint == 999) {
305 strcpy(buf + i, result);
307 buf[i++] = result[0];
309 if (fractionDigits.
isA(UndefinedType))
312 if (length > 1 && f > 0) {
314 int haveFDigits = length-1;
315 if (f < haveFDigits) {
316 strncpy(buf+i,result+1, f);
320 strcpy(buf+i,result+1);
322 for (
int j = 0; j < f-haveFDigits; j++)
328 buf[i++] = (decimalPoint >= 0) ?
'+' :
'-';
331 int exponential = decimalPoint - 1;
332 if (exponential < 0) {
333 exponential = exponential * -1;
335 if (exponential >= 100) {
336 buf[i++] =
'0' + exponential / 100;
338 if (exponential >= 10) {
339 buf[i++] =
'0' + (exponential % 100) / 10;
341 buf[i++] =
'0' + exponential % 10;
347 kjs_freedtoa(result);
356 int p = args[0].toInteger(exec);
358 if (args[0].isA(UndefinedType) || isNaN(x) || isInf(x))
367 if (p < 1 || p > 21) {
368 Object err = Error::create(exec, RangeError,
369 "toPrecision() argument must be between 1 and 21");
370 exec->setException(err);
377 double n = floor(x/pow(10.0,e-p+1));
378 if (n < pow(10.0,p-1)) {
381 n = floor(x/pow(10.0,e-p+1));
382 if (n >= pow(10.0,p)) {
385 e = int(log10(x/n)) + p - 1;
389 if (fabs((n+1)*pow(10.0,e-p+1)-x) < fabs(n*pow(10.0,e-p+1)-x))
391 assert(pow(10.0,p-1) <= n);
392 assert(n < pow(10.0,p));
394 m = integer_part_noexp(n);
395 if (e < -6 || e >= p) {
399 return String(s+m+
"e+"+UString::from(e));
401 return String(s+m+
"e-"+UString::from(-e));
405 m = char_sequence(
'0',p);
419 return String(s+
"0."+char_sequence(
'0',-(e+1))+m);
429 const ClassInfo NumberObjectImp::info = {
"Function", &InternalFunctionImp::info, &numberTable, 0};
440 NumberObjectImp::NumberObjectImp(
ExecState * ,
442 NumberPrototypeImp *numberProto)
447 putDirect(prototypePropertyName, numberProto, DontEnum|DontDelete|ReadOnly);
450 putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
455 return lookupGetValue<NumberObjectImp, InternalFunctionImp>( exec, propertyName, &numberTable,
this );
458 Value NumberObjectImp::getValueProperty(
ExecState *,
int token)
const
469 return Number(1.7976931348623157E+308);
476 bool NumberObjectImp::implementsConstruct()
const
486 Object obj(
new NumberInstanceImp(proto));
492 n = args[0].toNumber(exec);
494 obj.setInternalValue(n);
499 bool NumberObjectImp::implementsCall()
const
510 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)