2003/05/12 05:10:30
[org.ibex.core.git] / src / org / mozilla / javascript / NativeNumber.java
1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
2  *\r
3  * The contents of this file are subject to the Netscape Public\r
4  * License Version 1.1 (the "License"); you may not use this file\r
5  * except in compliance with the License. You may obtain a copy of\r
6  * the License at http://www.mozilla.org/NPL/\r
7  *\r
8  * Software distributed under the License is distributed on an "AS\r
9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
10  * implied. See the License for the specific language governing\r
11  * rights and limitations under the License.\r
12  *\r
13  * The Original Code is Rhino code, released\r
14  * May 6, 1999.\r
15  *\r
16  * The Initial Developer of the Original Code is Netscape\r
17  * Communications Corporation.  Portions created by Netscape are\r
18  * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
19  * Rights Reserved.\r
20  *\r
21  * Contributor(s):\r
22  * Norris Boyd\r
23  * Igor Bukanov\r
24  * Mike McCabe\r
25  *\r
26  * Alternatively, the contents of this file may be used under the\r
27  * terms of the GNU Public License (the "GPL"), in which case the\r
28  * provisions of the GPL are applicable instead of those above.\r
29  * If you wish to allow use of your version of this file only\r
30  * under the terms of the GPL and not to allow others to use your\r
31  * version of this file under the NPL, indicate your decision by\r
32  * deleting the provisions above and replace them with the notice\r
33  * and other provisions required by the GPL.  If you do not delete\r
34  * the provisions above, a recipient may use your version of this\r
35  * file under either the NPL or the GPL.\r
36  */\r
37 \r
38 package org.mozilla.javascript;\r
39 \r
40 /**\r
41  * This class implements the Number native object.\r
42  *\r
43  * See ECMA 15.7.\r
44  *\r
45  * @author Norris Boyd\r
46  */\r
47 public class NativeNumber extends IdScriptable {\r
48 \r
49     private static final int MAX_PRECISION = 100;\r
50 \r
51     public static void init(Context cx, Scriptable scope, boolean sealed) {\r
52         NativeNumber obj = new NativeNumber();\r
53         obj.prototypeFlag = true;\r
54         obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
55     }\r
56 \r
57     /**\r
58      * Zero-parameter constructor: just used to create Number.prototype\r
59      */\r
60     public NativeNumber() {\r
61         doubleValue = defaultValue;\r
62     }\r
63 \r
64     public NativeNumber(double number) {\r
65         doubleValue = number;\r
66     }\r
67 \r
68     public String getClassName() {\r
69         return "Number";\r
70     }\r
71 \r
72     protected void fillConstructorProperties\r
73         (Context cx, IdFunction ctor, boolean sealed)\r
74     {\r
75         final int attr = ScriptableObject.DONTENUM |\r
76                          ScriptableObject.PERMANENT |\r
77                          ScriptableObject.READONLY;\r
78 \r
79         ctor.defineProperty("NaN", wrap_double(ScriptRuntime.NaN), attr);\r
80         ctor.defineProperty("POSITIVE_INFINITY",\r
81                             wrap_double(Double.POSITIVE_INFINITY), attr);\r
82         ctor.defineProperty("NEGATIVE_INFINITY",\r
83                             wrap_double(Double.NEGATIVE_INFINITY), attr);\r
84         ctor.defineProperty("MAX_VALUE", wrap_double(Double.MAX_VALUE), attr);\r
85         ctor.defineProperty("MIN_VALUE", wrap_double(Double.MIN_VALUE), attr);\r
86 \r
87         super.fillConstructorProperties(cx, ctor, sealed);\r
88     }\r
89     \r
90     public int methodArity(int methodId) {\r
91         if (prototypeFlag) {\r
92             switch (methodId) {\r
93                 case Id_constructor:     return 1; \r
94                 case Id_toString:        return 1; \r
95                 case Id_valueOf:         return 0; \r
96                 case Id_toLocaleString:  return 1; \r
97                 case Id_toFixed:         return 1;\r
98                 case Id_toExponential:   return 1;\r
99                 case Id_toPrecision:     return 1;\r
100             }\r
101         }\r
102         return super.methodArity(methodId);\r
103     }\r
104 \r
105     public Object execMethod\r
106         (int methodId, IdFunction f,\r
107          Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
108         throws JavaScriptException\r
109     {\r
110         if (prototypeFlag) {\r
111             switch (methodId) {\r
112                 case Id_constructor:\r
113                     return jsConstructor(args, thisObj == null);\r
114 \r
115                 case Id_toString: return realThis(thisObj, f).\r
116                     jsFunction_toString(toBase(args, 0));\r
117 \r
118                 case Id_valueOf: return wrap_double(realThis(thisObj, f).\r
119                     jsFunction_valueOf());\r
120 \r
121                 case Id_toLocaleString: return realThis(thisObj, f).\r
122                     jsFunction_toLocaleString(toBase(args, 0));\r
123 \r
124                 case Id_toFixed: return realThis(thisObj, f).\r
125                     jsFunction_toFixed(cx, args);\r
126 \r
127                 case Id_toExponential: return realThis(thisObj, f).\r
128                     jsFunction_toExponential(cx, args);\r
129 \r
130                 case Id_toPrecision:return realThis(thisObj, f).\r
131                     jsFunction_toPrecision(cx, args);\r
132             }\r
133         }\r
134         return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
135     }\r
136 \r
137     private NativeNumber realThis(Scriptable thisObj, IdFunction f) {\r
138         while (!(thisObj instanceof NativeNumber)) {\r
139             thisObj = nextInstanceCheck(thisObj, f, true);\r
140         }\r
141         return (NativeNumber)thisObj;\r
142     }\r
143 \r
144     private static int toBase(Object[] args, int index) {\r
145         return (index < args.length) ? ScriptRuntime.toInt32(args[index]) : 10;\r
146     }\r
147 \r
148     private Object jsConstructor(Object[] args, boolean inNewExpr) {\r
149         double d = args.length >= 1\r
150                    ? ScriptRuntime.toNumber(args[0])\r
151                    : defaultValue;\r
152         if (inNewExpr) {\r
153             // new Number(val) creates a new Number object.\r
154             return new NativeNumber(d);\r
155         }\r
156         // Number(val) converts val to a number value.\r
157         return wrap_double(d);\r
158     }\r
159 \r
160     public String toString() {\r
161         return jsFunction_toString(10);\r
162     }\r
163 \r
164     private String jsFunction_toString(int base) {\r
165         return ScriptRuntime.numberToString(doubleValue, base);\r
166     }\r
167 \r
168     private double jsFunction_valueOf() {\r
169         return doubleValue;\r
170     }\r
171 \r
172     private String jsFunction_toLocaleString(int base) {\r
173         return jsFunction_toString(base);\r
174     }\r
175 \r
176     private String jsFunction_toFixed(Context cx, Object[] args) {\r
177         /* We allow a larger range of precision than\r
178            ECMA requires; this is permitted by ECMA. */\r
179         return num_to(cx, args, DToA.DTOSTR_FIXED, DToA.DTOSTR_FIXED,\r
180                       -20, MAX_PRECISION, 0);\r
181     }\r
182 \r
183     private String jsFunction_toExponential(Context cx, Object[] args) {\r
184         /* We allow a larger range of precision than\r
185            ECMA requires; this is permitted by ECMA. */\r
186         return num_to(cx, args,\r
187                       DToA.DTOSTR_STANDARD_EXPONENTIAL,\r
188                       DToA.DTOSTR_EXPONENTIAL,\r
189                       0, MAX_PRECISION, 1);\r
190     }\r
191 \r
192     private String jsFunction_toPrecision(Context cx, Object[] args) {\r
193         /* We allow a larger range of precision than\r
194            ECMA requires; this is permitted by ECMA. */\r
195         return num_to(cx, args, DToA.DTOSTR_STANDARD, DToA.DTOSTR_PRECISION,\r
196                       1, MAX_PRECISION, 0);\r
197     }\r
198 \r
199     private String num_to(Context cx, Object[] args,\r
200                           int zeroArgMode, int oneArgMode,\r
201                           int precisionMin, int precisionMax,\r
202                           int precisionOffset)\r
203     {\r
204         int precision;\r
205 \r
206         if (args.length == 0) {\r
207             precision = 0;\r
208             oneArgMode = zeroArgMode;\r
209         } else {\r
210             precision = ScriptRuntime.toInt32(args[0]);\r
211             if (precision < precisionMin || precision > precisionMax) {\r
212                 String msg = ScriptRuntime.getMessage1(\r
213                     "msg.bad.precision", ScriptRuntime.toString(args[0]));\r
214                 throw NativeGlobal.constructError(cx, "RangeError", msg, this);\r
215             }\r
216         }\r
217         StringBuffer result = new StringBuffer();\r
218         DToA.JS_dtostr(result, oneArgMode, precision + precisionOffset,\r
219                        doubleValue);\r
220         return result.toString();\r
221     }\r
222 \r
223     protected String getIdName(int id) {\r
224         if (prototypeFlag) {\r
225             switch (id) {\r
226                 case Id_constructor:     return "constructor"; \r
227                 case Id_toString:        return "toString"; \r
228                 case Id_valueOf:         return "valueOf"; \r
229                 case Id_toLocaleString:  return "toLocaleString"; \r
230                 case Id_toFixed:         return "toFixed";\r
231                 case Id_toExponential:   return "toExponential";\r
232                 case Id_toPrecision:     return "toPrecision";\r
233             }\r
234         }\r
235         return null;        \r
236     }\r
237 \r
238 // #string_id_map#\r
239 \r
240     protected int mapNameToId(String s) {\r
241         if (!prototypeFlag) { return 0; }\r
242         int id;\r
243 // #generated# Last update: 2001-04-23 10:40:45 CEST\r
244         L0: { id = 0; String X = null; int c;\r
245             L: switch (s.length()) {\r
246             case 7: c=s.charAt(0);\r
247                 if (c=='t') { X="toFixed";id=Id_toFixed; }\r
248                 else if (c=='v') { X="valueOf";id=Id_valueOf; }\r
249                 break L;\r
250             case 8: X="toString";id=Id_toString; break L;\r
251             case 11: c=s.charAt(0);\r
252                 if (c=='c') { X="constructor";id=Id_constructor; }\r
253                 else if (c=='t') { X="toPrecision";id=Id_toPrecision; }\r
254                 break L;\r
255             case 13: X="toExponential";id=Id_toExponential; break L;\r
256             case 14: X="toLocaleString";id=Id_toLocaleString; break L;\r
257             }\r
258             if (X!=null && X!=s && !X.equals(s)) id = 0;\r
259         }\r
260 // #/generated#\r
261         return id;\r
262     }\r
263 \r
264     private static final int\r
265         Id_constructor           = 1,\r
266         Id_toString              = 2,\r
267         Id_valueOf               = 3,\r
268         Id_toLocaleString        = 4,\r
269         Id_toFixed               = 5,\r
270         Id_toExponential         = 6,\r
271         Id_toPrecision           = 7,\r
272         MAX_PROTOTYPE_ID         = 7;\r
273 \r
274 // #/string_id_map#\r
275 \r
276     private static final double defaultValue = +0.0;\r
277     private double doubleValue;\r
278 \r
279     private boolean prototypeFlag;\r
280 }\r