KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > js > rhino > ScriptRuntime


1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * The contents of this file are subject to the Netscape Public
4  * License Version 1.1 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of
6  * the License at http://www.mozilla.org/NPL/
7  *
8  * Software distributed under the License is distributed on an "AS
9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10  * implied. See the License for the specific language governing
11  * rights and limitations under the License.
12  *
13  * The Original Code is Rhino code, released
14  * May 6, 1999.
15  *
16  * The Initial Developer of the Original Code is Netscape
17  * Communications Corporation. Portions created by Netscape are
18  * Copyright (C) 1997-2000 Netscape Communications Corporation. All
19  * Rights Reserved.
20  *
21  * Contributor(s):
22  * Patrick Beard
23  * Norris Boyd
24  * Igor Bukanov
25  * Roger Lawrence
26  * Frank Mitchell
27  * Andrew Wason
28  *
29  * Alternatively, the contents of this file may be used under the
30  * terms of the GNU Public License (the "GPL"), in which case the
31  * provisions of the GPL are applicable instead of those above.
32  * If you wish to allow use of your version of this file only
33  * under the terms of the GPL and not to allow others to use your
34  * version of this file under the NPL, indicate your decision by
35  * deleting the provisions above and replace them with the notice
36  * and other provisions required by the GPL. If you do not delete
37  * the provisions above, a recipient may use your version of this
38  * file under either the NPL or the GPL.
39  */

40 // Modified by Google
41

42 package com.google.gwt.dev.js.rhino;
43
44 /**
45  * This is the class that implements the runtime.
46  *
47  * @author Norris Boyd
48  */

49
50 public class ScriptRuntime {
51
52     public static double NaN = 0.0d / 0.0;
53
54     public static String JavaDoc numberToString(double d, int base) {
55         if (d != d)
56             return "NaN";
57         if (d == Double.POSITIVE_INFINITY)
58             return "Infinity";
59         if (d == Double.NEGATIVE_INFINITY)
60             return "-Infinity";
61         if (d == 0.0)
62             return "0";
63
64         if ((base < 2) || (base > 36)) {
65             throw new Error JavaDoc(Context.getMessage1("msg.bad.radix",
66                                                 Integer.toString(base)));
67         }
68
69         if (base != 10) {
70             return DToA.JS_dtobasestr(base, d);
71         } else {
72             StringBuffer JavaDoc result = new StringBuffer JavaDoc();
73             DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
74             return result.toString();
75         }
76
77     }
78
79     /*
80      * Helper function for toNumber, parseInt, and TokenStream.getToken.
81      */

82     static double stringToNumber(String JavaDoc s, int start, int radix) {
83         char digitMax = '9';
84         char lowerCaseBound = 'a';
85         char upperCaseBound = 'A';
86         int len = s.length();
87         if (radix < 10) {
88             digitMax = (char) ('0' + radix - 1);
89         }
90         if (radix > 10) {
91             lowerCaseBound = (char) ('a' + radix - 10);
92             upperCaseBound = (char) ('A' + radix - 10);
93         }
94         int end;
95         double sum = 0.0;
96         for (end=start; end < len; end++) {
97             char c = s.charAt(end);
98             int newDigit;
99             if ('0' <= c && c <= digitMax)
100                 newDigit = c - '0';
101             else if ('a' <= c && c < lowerCaseBound)
102                 newDigit = c - 'a' + 10;
103             else if ('A' <= c && c < upperCaseBound)
104                 newDigit = c - 'A' + 10;
105             else
106                 break;
107             sum = sum*radix + newDigit;
108         }
109         if (start == end) {
110             return NaN;
111         }
112         if (sum >= 9007199254740992.0) {
113             if (radix == 10) {
114                 /* If we're accumulating a decimal number and the number
115                  * is >= 2^53, then the result from the repeated multiply-add
116                  * above may be inaccurate. Call Java to get the correct
117                  * answer.
118                  */

119                 try {
120                     return Double.valueOf(s.substring(start, end)).doubleValue();
121                 } catch (NumberFormatException JavaDoc nfe) {
122                     return NaN;
123                 }
124             } else if (radix == 2 || radix == 4 || radix == 8 ||
125                        radix == 16 || radix == 32)
126             {
127                 /* The number may also be inaccurate for one of these bases.
128                  * This happens if the addition in value*radix + digit causes
129                  * a round-down to an even least significant mantissa bit
130                  * when the first dropped bit is a one. If any of the
131                  * following digits in the number (which haven't been added
132                  * in yet) are nonzero then the correct action would have
133                  * been to round up instead of down. An example of this
134                  * occurs when reading the number 0x1000000000000081, which
135                  * rounds to 0x1000000000000000 instead of 0x1000000000000100.
136                  */

137                 BinaryDigitReader bdr = new BinaryDigitReader(radix, s, start, end);
138                 int bit;
139                 sum = 0.0;
140
141                 /* Skip leading zeros. */
142                 do {
143                     bit = bdr.getNextBinaryDigit();
144                 } while (bit == 0);
145
146                 if (bit == 1) {
147                     /* Gather the 53 significant bits (including the leading 1) */
148                     sum = 1.0;
149                     for (int j = 52; j != 0; j--) {
150                         bit = bdr.getNextBinaryDigit();
151                         if (bit < 0)
152                             return sum;
153                         sum = sum*2 + bit;
154                     }
155                     /* bit54 is the 54th bit (the first dropped from the mantissa) */
156                     int bit54 = bdr.getNextBinaryDigit();
157                     if (bit54 >= 0) {
158                         double factor = 2.0;
159                         int sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
160                         int bit3;
161
162                         while ((bit3 = bdr.getNextBinaryDigit()) >= 0) {
163                             sticky |= bit3;
164                             factor *= 2;
165                         }
166                         sum += bit54 & (bit | sticky);
167                         sum *= factor;
168                     }
169                 }
170             }
171             /* We don't worry about inaccurate numbers for any other base. */
172         }
173         return sum;
174     }
175
176     /**
177      * For escaping strings printed by object and array literals; not quite
178      * the same as 'escape.'
179      */

180     public static String JavaDoc escapeString(String JavaDoc s) {
181
182         StringBuffer JavaDoc sb = null;
183
184         for(int i = 0, L = s.length(); i != L; ++i) {
185             int c = s.charAt(i);
186
187             if (' ' <= c && c <= '~' && c != '"' && c != '\\') {
188                 // an ordinary print character (like C isprint()) and not "
189
// or \ . Note single quote ' is not escaped
190
if (sb != null) {
191                     sb.append((char)c);
192                 }
193                 continue;
194             }
195             if (sb == null) {
196                 sb = new StringBuffer JavaDoc(L + 3);
197                 sb.append(s);
198                 sb.setLength(i);
199             }
200
201             int escape = -1;
202             switch (c) {
203                 case '\b': escape = 'b'; break;
204                 case '\f': escape = 'f'; break;
205                 case '\n': escape = 'n'; break;
206                 case '\r': escape = 'r'; break;
207                 case '\t': escape = 't'; break;
208                 case 0xb: escape = 'v'; break; // Java lacks \v.
209
case '"': escape = '"'; break;
210                 case ' ': escape = ' '; break;
211                 case '\\': escape = '\\'; break;
212             }
213             if (escape >= 0) {
214                 // an \escaped sort of character
215
sb.append('\\');
216                 sb.append((char)escape);
217             } else {
218                 int hexSize;
219                 if (c < 256) {
220                     // 2-digit hex
221
sb.append("\\x");
222                     hexSize = 2;
223                 } else {
224                     // Unicode.
225
sb.append("\\u");
226                     hexSize = 4;
227                 }
228                 // append hexadecimal form of c left-padded with 0
229
for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
230                     int digit = 0xf & (c >> shift);
231                     int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit;
232                     sb.append((char)hc);
233                 }
234             }
235         }
236
237         return (sb == null) ? s : sb.toString();
238     }
239
240 }
241
Popular Tags