8950714095d2fb071ae9001ca82e5aa1e8a55849
[WebKit-https.git] / JavaScriptCore / kjs / number_object.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "value.h"
23 #include "object.h"
24 #include "types.h"
25 #include "interpreter.h"
26 #include "operations.h"
27 #include "number_object.h"
28 #include "error_object.h"
29
30 #include "number_object.lut.h"
31
32 using namespace KJS;
33
34
35 // ------------------------------ NumberInstanceImp ----------------------------
36
37 const ClassInfo NumberInstanceImp::info = {"Number", 0, 0, 0};
38
39 NumberInstanceImp::NumberInstanceImp(ObjectImp *proto)
40   : ObjectImp(proto)
41 {
42 }
43 // ------------------------------ NumberPrototypeImp ---------------------------
44
45 // ECMA 15.7.4
46
47 NumberPrototypeImp::NumberPrototypeImp(ExecState *exec,
48                                        ObjectPrototypeImp *objProto,
49                                        FunctionPrototypeImp *funcProto)
50   : NumberInstanceImp(objProto)
51 {
52   Value protect(this);
53   setInternalValue(NumberImp::zero());
54
55   // The constructor will be added later, after NumberObjectImp has been constructed
56
57   putDirect(toStringPropertyName,       new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToString,       1), DontEnum);
58   putDirect(toLocaleStringPropertyName, new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToLocaleString, 0), DontEnum);
59   putDirect(valueOfPropertyName,        new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ValueOf,        0), DontEnum);
60 }
61
62
63 // ------------------------------ NumberProtoFuncImp ---------------------------
64
65 NumberProtoFuncImp::NumberProtoFuncImp(ExecState *exec,
66                                        FunctionPrototypeImp *funcProto, int i, int len)
67   : InternalFunctionImp(funcProto), id(i)
68 {
69   Value protect(this);
70   putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
71 }
72
73
74 bool NumberProtoFuncImp::implementsCall() const
75 {
76   return true;
77 }
78
79 // ECMA 15.7.4.2 - 15.7.4.7
80 Value NumberProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
81 {
82   Value result;
83
84   // no generic function. "this" has to be a Number object
85   if (!thisObj.inherits(&NumberInstanceImp::info)) {
86     Object err = Error::create(exec,TypeError);
87     exec->setException(err);
88     return err;
89   }
90
91   // execute "toString()" or "valueOf()", respectively
92   Value v = thisObj.internalValue();
93   switch (id) {
94   case ToString: {
95     double dradix = 10;
96     if (!args.isEmpty() && args[0].type() != UndefinedType)
97       dradix = args[0].toInteger(exec);
98     if (dradix < 2 || dradix > 36 || dradix == 10)
99       result = String(v.toString(exec));
100     else {
101       int radix = static_cast<int>(radix);
102       unsigned i = v.toUInt32(exec);
103       char s[33];
104       char *p = s + sizeof(s);
105       *--p = '\0';
106       do {
107         *--p = "0123456789abcdefghijklmnopqrstuvwxyz"[i % radix];
108         i /= radix;
109       } while (i);
110       result = String(p);
111     }
112     break;
113   }
114   case ToLocaleString: /* TODO */
115     result = String(v.toString(exec));
116     break;
117   case ValueOf:
118     result = Number(v.toNumber(exec));
119     break;
120   }
121
122   return result;
123 }
124
125 // ------------------------------ NumberObjectImp ------------------------------
126
127 const ClassInfo NumberObjectImp::info = {"Number", &InternalFunctionImp::info, &numberTable, 0};
128 //const ClassInfo NumberObjectImp::info = {"Number", 0, &numberTable, 0};
129
130 /* Source for number_object.lut.h
131 @begin numberTable 5
132   NaN                   NumberObjectImp::NaNValue       DontEnum
133   NEGATIVE_INFINITY     NumberObjectImp::NegInfinity    DontEnum
134   POSITIVE_INFINITY     NumberObjectImp::PosInfinity    DontEnum
135   MAX_VALUE             NumberObjectImp::MaxValue       DontEnum
136   MIN_VALUE             NumberObjectImp::MinValue       DontEnum
137 @end
138 */
139 NumberObjectImp::NumberObjectImp(ExecState *exec,
140                                  FunctionPrototypeImp *funcProto,
141                                  NumberPrototypeImp *numberProto)
142   : InternalFunctionImp(funcProto)
143 {
144   Value protect(this);
145   // Number.Prototype
146   putDirect(prototypePropertyName, numberProto,DontEnum|DontDelete|ReadOnly);
147
148   // no. of arguments for constructor
149   putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
150 }
151
152 Value NumberObjectImp::get(ExecState *exec, const Identifier &propertyName) const
153 {
154   return lookupGetValue<NumberObjectImp, InternalFunctionImp>( exec, propertyName, &numberTable, this );
155 }
156
157 Value NumberObjectImp::getValueProperty(ExecState *, int token) const
158 {
159   // ECMA 15.7.3
160   switch(token) {
161   case NaNValue:
162     return Number(NaN);
163   case NegInfinity:
164     return Number(-Inf);
165   case PosInfinity:
166     return Number(Inf);
167   case MaxValue:
168     return Number(1.7976931348623157E+308);
169   case MinValue:
170     return Number(5E-324);
171   }
172   return Null();
173 }
174
175 bool NumberObjectImp::implementsConstruct() const
176 {
177   return true;
178 }
179
180
181 // ECMA 15.7.1
182 Object NumberObjectImp::construct(ExecState *exec, const List &args)
183 {
184   ObjectImp *proto = exec->lexicalInterpreter()->builtinNumberPrototype().imp();
185   Object obj(new NumberInstanceImp(proto));
186
187   Number n;
188   if (args.isEmpty())
189     n = Number(0);
190   else
191     n = args[0].toNumber(exec);
192
193   obj.setInternalValue(n);
194
195   return obj;
196 }
197
198 bool NumberObjectImp::implementsCall() const
199 {
200   return true;
201 }
202
203 // ECMA 15.7.2
204 Value NumberObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
205 {
206   if (args.isEmpty())
207     return Number(0);
208   else
209     return Number(args[0].toNumber(exec));
210 }