001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-1999
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Igor Bukanov
027: * Mike McCabe
028: *
029: * Alternatively, the contents of this file may be used under the terms of
030: * the GNU General Public License Version 2 or later (the "GPL"), in which
031: * case the provisions of the GPL are applicable instead of those above. If
032: * you wish to allow use of your version of this file only under the terms of
033: * the GPL and not to allow others to use your version of this file under the
034: * MPL, indicate your decision by deleting the provisions above and replacing
035: * them with the notice and other provisions required by the GPL. If you do
036: * not delete the provisions above, a recipient may use your version of this
037: * file under either the MPL or the GPL.
038: *
039: * ***** END LICENSE BLOCK ***** */
040:
041: package org.mozilla.javascript;
042:
043: /**
044: * This class implements the Number native object.
045: *
046: * See ECMA 15.7.
047: *
048: * @author Norris Boyd
049: */
050: final class NativeNumber extends IdScriptableObject {
051: static final long serialVersionUID = 3504516769741512101L;
052:
053: private static final Object NUMBER_TAG = new Object();
054:
055: private static final int MAX_PRECISION = 100;
056:
057: static void init(Scriptable scope, boolean sealed) {
058: NativeNumber obj = new NativeNumber(0.0);
059: obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
060: }
061:
062: private NativeNumber(double number) {
063: doubleValue = number;
064: }
065:
066: public String getClassName() {
067: return "Number";
068: }
069:
070: protected void fillConstructorProperties(IdFunctionObject ctor) {
071: final int attr = ScriptableObject.DONTENUM
072: | ScriptableObject.PERMANENT
073: | ScriptableObject.READONLY;
074:
075: ctor.defineProperty("NaN", ScriptRuntime.NaNobj, attr);
076: ctor.defineProperty("POSITIVE_INFINITY", ScriptRuntime
077: .wrapNumber(Double.POSITIVE_INFINITY), attr);
078: ctor.defineProperty("NEGATIVE_INFINITY", ScriptRuntime
079: .wrapNumber(Double.NEGATIVE_INFINITY), attr);
080: ctor.defineProperty("MAX_VALUE", ScriptRuntime
081: .wrapNumber(Double.MAX_VALUE), attr);
082: ctor.defineProperty("MIN_VALUE", ScriptRuntime
083: .wrapNumber(Double.MIN_VALUE), attr);
084:
085: super .fillConstructorProperties(ctor);
086: }
087:
088: protected void initPrototypeId(int id) {
089: String s;
090: int arity;
091: switch (id) {
092: case Id_constructor:
093: arity = 1;
094: s = "constructor";
095: break;
096: case Id_toString:
097: arity = 1;
098: s = "toString";
099: break;
100: case Id_toLocaleString:
101: arity = 1;
102: s = "toLocaleString";
103: break;
104: case Id_toSource:
105: arity = 0;
106: s = "toSource";
107: break;
108: case Id_valueOf:
109: arity = 0;
110: s = "valueOf";
111: break;
112: case Id_toFixed:
113: arity = 1;
114: s = "toFixed";
115: break;
116: case Id_toExponential:
117: arity = 1;
118: s = "toExponential";
119: break;
120: case Id_toPrecision:
121: arity = 1;
122: s = "toPrecision";
123: break;
124: default:
125: throw new IllegalArgumentException(String.valueOf(id));
126: }
127: initPrototypeMethod(NUMBER_TAG, id, s, arity);
128: }
129:
130: public Object execIdCall(IdFunctionObject f, Context cx,
131: Scriptable scope, Scriptable this Obj, Object[] args) {
132: if (!f.hasTag(NUMBER_TAG)) {
133: return super .execIdCall(f, cx, scope, this Obj, args);
134: }
135: int id = f.methodId();
136: if (id == Id_constructor) {
137: double val = (args.length >= 1) ? ScriptRuntime
138: .toNumber(args[0]) : 0.0;
139: if (this Obj == null) {
140: // new Number(val) creates a new Number object.
141: return new NativeNumber(val);
142: }
143: // Number(val) converts val to a number value.
144: return ScriptRuntime.wrapNumber(val);
145: }
146:
147: // The rest of Number.prototype methods require thisObj to be Number
148:
149: if (!(this Obj instanceof NativeNumber))
150: throw incompatibleCallError(f);
151: double value = ((NativeNumber) this Obj).doubleValue;
152:
153: switch (id) {
154:
155: case Id_toString:
156: case Id_toLocaleString: {
157: // toLocaleString is just an alias for toString for now
158: int base = (args.length == 0) ? 10 : ScriptRuntime
159: .toInt32(args[0]);
160: return ScriptRuntime.numberToString(value, base);
161: }
162:
163: case Id_toSource:
164: return "(new Number(" + ScriptRuntime.toString(value)
165: + "))";
166:
167: case Id_valueOf:
168: return ScriptRuntime.wrapNumber(value);
169:
170: case Id_toFixed:
171: return num_to(value, args, DToA.DTOSTR_FIXED,
172: DToA.DTOSTR_FIXED, -20, 0);
173:
174: case Id_toExponential:
175: return num_to(value, args,
176: DToA.DTOSTR_STANDARD_EXPONENTIAL,
177: DToA.DTOSTR_EXPONENTIAL, 0, 1);
178:
179: case Id_toPrecision:
180: return num_to(value, args, DToA.DTOSTR_STANDARD,
181: DToA.DTOSTR_PRECISION, 1, 0);
182:
183: default:
184: throw new IllegalArgumentException(String.valueOf(id));
185: }
186: }
187:
188: public String toString() {
189: return ScriptRuntime.numberToString(doubleValue, 10);
190: }
191:
192: private static String num_to(double val, Object[] args,
193: int zeroArgMode, int oneArgMode, int precisionMin,
194: int precisionOffset) {
195: int precision;
196: if (args.length == 0) {
197: precision = 0;
198: oneArgMode = zeroArgMode;
199: } else {
200: /* We allow a larger range of precision than
201: ECMA requires; this is permitted by ECMA. */
202: precision = ScriptRuntime.toInt32(args[0]);
203: if (precision < precisionMin || precision > MAX_PRECISION) {
204: String msg = ScriptRuntime.getMessage1(
205: "msg.bad.precision", ScriptRuntime
206: .toString(args[0]));
207: throw ScriptRuntime.constructError("RangeError", msg);
208: }
209: }
210: StringBuffer sb = new StringBuffer();
211: DToA
212: .JS_dtostr(sb, oneArgMode, precision + precisionOffset,
213: val);
214: return sb.toString();
215: }
216:
217: // #string_id_map#
218:
219: protected int findPrototypeId(String s) {
220: int id;
221: // #generated# Last update: 2007-05-09 08:15:50 EDT
222: L0: {
223: id = 0;
224: String X = null;
225: int c;
226: L: switch (s.length()) {
227: case 7:
228: c = s.charAt(0);
229: if (c == 't') {
230: X = "toFixed";
231: id = Id_toFixed;
232: } else if (c == 'v') {
233: X = "valueOf";
234: id = Id_valueOf;
235: }
236: break L;
237: case 8:
238: c = s.charAt(3);
239: if (c == 'o') {
240: X = "toSource";
241: id = Id_toSource;
242: } else if (c == 't') {
243: X = "toString";
244: id = Id_toString;
245: }
246: break L;
247: case 11:
248: c = s.charAt(0);
249: if (c == 'c') {
250: X = "constructor";
251: id = Id_constructor;
252: } else if (c == 't') {
253: X = "toPrecision";
254: id = Id_toPrecision;
255: }
256: break L;
257: case 13:
258: X = "toExponential";
259: id = Id_toExponential;
260: break L;
261: case 14:
262: X = "toLocaleString";
263: id = Id_toLocaleString;
264: break L;
265: }
266: if (X != null && X != s && !X.equals(s))
267: id = 0;
268: break L0;
269: }
270: // #/generated#
271: return id;
272: }
273:
274: private static final int Id_constructor = 1, Id_toString = 2,
275: Id_toLocaleString = 3, Id_toSource = 4, Id_valueOf = 5,
276: Id_toFixed = 6, Id_toExponential = 7, Id_toPrecision = 8,
277: MAX_PROTOTYPE_ID = 8;
278:
279: // #/string_id_map#
280:
281: private double doubleValue;
282: }
|