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 substr(int pos=0, int len=-1) const
Base class for all function objects.
static UString from(int i)
Constructs a string from an int.
Represents an primitive Number value.
Represents an primitive Null value.
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
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) ...
double toNumber(ExecState *exec) const
Performs the ToNumber type conversion operation on this value (ECMA 9.3)
bool isA(Type t) const
Checks whether or not the value is of a particular tpye.
Represents an primitive String value.
Value internalValue() const
Returns the internal value of the object.
UString toString(ExecState *exec) const
Performs the ToString type conversion operation on this value (ECMA 9.8)
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 the current state of script execution.
Represents an Identifier for a Javascript object.