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))
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) {
219 exec->setException(err);
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))
263 Value fractionDigits = args[0];
264 if (args.
size() > 0) {
266 if (f < 0 || f > 20) {
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) {
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) {
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));
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.