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 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.