001 
002 /*
003  *  JScripter Emulation 1.0 - To Script Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.emu.java.lang;
021 
022 import js.ArrayLike;
023 import js.Js;
024 import js.Vars;
025 
026 /**
027  * <p><b>Internally</b> represents primitive int values, emulating a standard
028  * <tt>java.lang</tt> interface or class with the same simple name as this one.</p>
029  * <p>This interface or class is only used internally by JS re-compiler implementations.</p>
030  * <p>Please refer to <a href="http://java.sun.com/docs/">the Java API Standards</a> for detail description of the original class or interface.</p>
031  * 
032  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
033  * 
034  * @javascript Re-compilers must redirect the resolution of the emulated original Java class or interface to this one.
035  */
036 public final class Integer extends Number implements Comparable<Integer>
037 {
038     /**
039      * <p>Internally stores a constant holding the minimum value an int can have, -2<sup>31</sup>.</p>
040      * @since 1.0
041      * @javascript Re-compilers must report error on end-users directly using this field.
042      */
043     public static final int MIN_VALUE = 0x80000000;
044     /**
045      * <p>Internally stores a constant holding the maximum value an int can have, 2<sup>31</sup>-1.</p>
046      * @since 1.0
047      * @javascript Re-compilers must report error on end-users directly using this field.
048      */
049     public static final int MAX_VALUE = 0x7FFFFFFF;
050     /**
051      * <p>Internally stores the number of bits used to represent an int value in
052      * two's complement binary form.</p>
053      * @since 1.0
054      * @javascript Re-compilers must report error on end-users directly using this field.
055      */
056     public static final int SIZE = 32;
057 
058     /**
059      * <p>Returns the number of one-bits in the two's complement binary
060      * representation of the specified int value.</p>
061      * @param i An int value to count population.
062      * @return The number of one-bits in the two's complement binary representation of the specified value.
063      * @since 1.0
064      * @javascript Re-compilers must report error on end-users directly using this method.
065      */
066     public static final int bitCount(int i) {
067         int cnt = 0;
068         for (int q = MIN_VALUE; q > 0; q = q >> 1) {
069             if ((q & i) != 0) {
070                 cnt++;
071             }
072         }
073         return cnt;
074     }
075 
076     /**
077      * <p>Decodes a string into a {@link Integer}.</p>
078      * @param s A string to decode.
079      * @return A {@link Integer} represented by <tt>s</tt>.
080      * @throws java.lang.NumberFormatException if the string does not contain a parsable int.
081      * @since 1.0
082      * @javascript Re-compilers must report error on end-users directly using this method.
083      */
084     public static final java.lang.Integer decode(java.lang.String s)
085             throws java.lang.NumberFormatException {
086         try {
087             return Js.parseInt(s).intValue();
088         } catch (java.lang.Exception e) {
089             throw new java.lang.NumberFormatException(e.toString());
090         }
091     }
092 
093     /**
094      * <p>Returns an int value with at most a single one-bit, in the position of
095      * the highest-order ("leftmost") one-bit in the specified int value.</p>
096      * <p>This method returns 0 if the specified value has no one-bits in its two's
097      * complement binary representation, that is, if it is equal to 0.</p>
098      * @param i An int value.
099      * @return An int value with a single one-bit, in the position of the highest-order one-bit in 
100      * the specified value, or 0 if the specified value is itself equal to 0.
101      * @since 1.0
102      * @javascript Re-compilers must report error on end-users directly using this method.
103      */
104     public static final int highestOneBit(int i) {
105         if (i < 0) {
106             return MIN_VALUE;
107         } else if (i == 0) {
108             return 0;
109         } else {
110             int rtn;
111             for (rtn = MIN_VALUE >>> 1; (rtn & i) == 0; rtn = rtn >> 1);
112             return rtn;
113         }
114     }
115 
116     /**
117      * <p>Returns an int value with at most a single one-bit, in the position of
118      * the lowest-order ("rightmost") one-bit in the specified int value.</p>
119      * <p>This method returns 0 if the specified value has no one-bits in its two's
120      * complement binary representation, that is, if it is equal to 0.</p>
121      * @param i An int value.
122      * @return An int value with a single one-bit, in the position of the lowest-order one-bit in 
123      * the specified value, or 0 if the specified value is itself equal to 0.
124      * @since 1.0
125      * @javascript Re-compilers must report error on end-users directly using this method.
126      */
127     public static final int lowestOneBit(int i) {
128         if (i == 0) {
129             return 0;
130         } else if (i == MIN_VALUE) {
131             return MIN_VALUE;
132         } else {
133             int r = 1;
134             while ((r & i) == 0) {
135                 r = r * 2;
136             }
137             return r;
138         }
139     }
140 
141     /**
142      * <p>Returns the number of zero bits preceding the highest-order ("leftmost")
143      * one-bit in the two's complement binary representation of the specified int value.</p>
144      * <p>This method returns 32 if the specified value has no one-bits in its
145      * two's complement representation, i.e., if it is equal to 0.</p>
146      * @param i An int value.
147      * @return The number of zero bits preceding the highest-order ("leftmost") one-bit in the two's 
148      * complement binary representation of the specified int value, or 32 if the value is equal to 0.
149      * @since 1.0
150      * @javascript Re-compilers must report error on end-users directly using this method.
151      */
152     public static final int numberOfLeadingZeros(int i) {
153         if (i < 0) {
154             return 0;
155         } else if (i == 0) {
156             return SIZE;
157         } else {
158             return SIZE - 1 - (int) Math.floor(Math.log(i) / Math.log(2.0d));
159         }
160     }
161 
162     /**
163      * <p>Returns the number of zero bits following the lowest-order ("rightmost")
164      * one-bit in the two's complement binary representation of the specified int value.</p>
165      * <p>This method returns 32 if the specified value has no one-bits in its
166      * two's complement representation, i.e., if it is equal to 0.</p>
167      * @param i An int value.
168      * @return The number of zero bits following the lowest-order ("rightmost") one-bit in the two's 
169      * complement binary representation of the specified int value, or 32 if the value is equal to 0.
170      * @since 1.0
171      * @javascript Re-compilers must report error on end-users directly using this method.
172      */
173     public static final int numberOfTrailingZeros(int i) {
174         if (i == 0) {
175             return SIZE;
176         } else {
177             int rtn = 0;
178             for (int r = 1; (r & i) == 0; r = r * 2) {
179                 rtn++;
180             }
181             return rtn;
182         }
183     }
184 
185     /**
186      * <p>Parses the string argument as a signed decimal int.</p>
187      * <p>The characters in the string must all be decimal digits, except that the
188      * first character may be an ASCII minus sign '-' ('-') to indicate a negative value. 
189      * The resulting int value is returned, exactly as if the argument and the radix 10 were given 
190      * as arguments to the {@link #parseInt(String, int)} method.</p>
191      * @param s A string containing the int representation to be parsed.
192      * @return The {@link Integer} represented by the string argument in decimal.
193      * @throws java.lang.NumberFormatException if the string does not contain a parsable int.
194      * @since 1.0
195      * @javascript Re-compilers must report error on end-users directly using this method. 
196      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
197      */
198     public static final synchronized int parseInt(java.lang.String s)
199             throws java.lang.NumberFormatException {
200         return parseInt(s, 10);
201     }
202 
203     /**
204      * <p>Parses the string argument as a signed int in the radix specified by the second argument.</p>
205      * <p>The characters in the string must all be digits, of the specified radix
206      * (as determined by whether {@link Character#digit(char, int)} returns a nonnegative value) 
207      * except that the first character may be an ASCII minus sign '-' ('-') to indicate a 
208      * negative value. The resulting int value is returned.</p>
209      * @param s A string containing the short representation to be parsed.
210      * @param radix The radix to be used while parsing <tt>s</tt>.
211      * @return The {@link Integer} represented by the string argument in the specified radix.
212      * @throws java.lang.NumberFormatException if the string does not contain a parsable int.
213      * @since 1.0
214      * @javascript Re-compilers must report error on end-users directly using this method.
215      */
216     public static final int parseInt(java.lang.String s, int radix)
217             throws java.lang.NumberFormatException {
218         try {
219             java.lang.Number n = Js.parseInt(s);
220             if (Js.lt(n, MIN_VALUE) || Js.gt(n, MAX_VALUE)) {
221                 throw new java.lang.NumberFormatException("out of bounds");
222             }
223             return n.intValue();
224         } catch (java.lang.Exception e) {
225             throw new java.lang.NumberFormatException(e.toString());
226         }
227     }
228 
229     /**
230      * <p>Returns the value obtained by reversing the order of the bits in the
231      * two's complement binary representation of the specified int value.</p>
232      * @param i An int to be converted.
233      * @return The value obtained by reversing order of the bits in the specified int value.
234      * @since 1.0
235      * @javascript Re-compilers must report error on end-users directly using this method.
236      */
237     public static final int reverse(int i) {
238         int ui = i & MAX_VALUE; // avoid sign extension
239         int acc = 0;
240         int front = MIN_VALUE;
241         int back = 1;
242         int swing = 31;
243         while (swing > 0) {
244             acc = acc | ((ui & front) >> swing) | ((ui & back) << swing);
245             swing -= 2;
246             front = front >> 1;
247             back = back << 1;
248         }
249         if (i < 0) {
250             acc = acc | 0x1; // restore the real value of 0x80000000
251         }
252         return acc;
253     }
254 
255     /**
256      * <p>Returns the value obtained by reversing the order of the bytes in the
257      * two's complement representation of the specified int value.</p>
258      * @param i An int to be converted.
259      * @return The value obtained by reversing the bytes in the specified value.
260      * @since 1.0
261      * @javascript Re-compilers must report error on end-users directly using this method.
262      */
263     public static final int reverseBytes(int i) {
264         return Js.bor(
265                 Js.bor(Js.bor(Js.shl(Js.band(i, 0xff), 24),
266                         Js.shl(Js.band(i, 0xff00), 8)),
267                         Js.shr(Js.band(i, 0xff0000), 8)),
268                 Js.shr(Js.band(i, 0xff000000), 24));
269     }
270 
271     /**
272      * <p>Returns the value obtained by rotating the two's complement binary representation of 
273      * the specified int value left by the specified number of bits.</p>
274      * <p>Bits shifted out of the left hand, or high-order, side reenter on the right, or low-order.</p>
275      * <p>Note that left rotation with a negative distance is equivalent to right rotation:
276      * <pre>
277      * rotateLeft(i, -distance) == rotateRight(i, distance)
278      * </pre>
279      * Note also that rotation by any multiple of 32 is a no-op, so all but the last five bits of 
280      * the rotation distance can be ignored, even if the distance is negative:
281      * <pre>
282      * rotateLeft(i, distance) == rotateLeft(i, distance &amp; 0x1F)
283      * </pre></p>
284      * @param i An int to be shifted.
285      * @return The value obtained by rotating the two's complement binary representation of the 
286      * specified int value left by the specified number of bits.
287      * @since 1.0
288      * @javascript Re-compilers must report error on end-users directly using this method.
289      */
290     public static final int rotateLeft(int i, int distance) {
291         if (distance < 0) {
292             return rotateRight(i, -distance);
293         }
294         distance &= 0x1F;
295         while (distance-- > 0) {
296             i = i << 1 | ((i < 0) ? 1 : 0);
297         }
298         return i;
299     }
300 
301     /**
302      * <p>Returns the value obtained by rotating the two's complement binary representation of 
303      * the specified int value right by the specified number of bits.</p>
304      * <p>Bits shifted out of the right hand, or low-order, side reenter on the left, or high-order.</p>
305      * <p>Note that right rotation with a negative distance is equivalent to left rotation:
306      * <pre>
307      * rotateRight(i, -distance) == rotateLeft(i, distance)
308      * </pre>
309      * Note also that rotation by any multiple of 32 is a no-op, so all but the last five bits of 
310      * the rotation distance can be ignored, even if the distance is negative:
311      * <pre>
312      * rotateRight(i, distance) == rotateRight(i, distance &amp; 0x1F)
313      * </pre></p>
314      * @param i An int to be shifted.
315      * @return The value obtained by rotating the two's complement binary representation of the 
316      * specified int value right by the specified number of bits.
317      * @since 1.0
318      * @javascript Re-compilers must report error on end-users directly using this method.
319      */
320     public static final int rotateRight(int i, int distance) {
321         if (distance < 0) {
322             return rotateLeft(i, -distance);
323         }
324         distance &= 0x1F;
325         int ui = i & MAX_VALUE; // avoid sign extension
326         int carry = i < 0 ? MIN_VALUE >>> 1 : 0; // 0x40000000 = 0x80000000 >>>
327                                                     // 1
328         while (distance-- > 0) {
329             int nextcarry = ui & 1;
330             ui = carry | (ui >> 1);
331             carry = (nextcarry == 0) ? 0 : MIN_VALUE >>> 1;
332         }
333         if (carry != 0) {
334             ui = ui | MIN_VALUE;
335         }
336         return ui;
337     }
338 
339     /**
340      * <p>Returns the signum function of the specified int value</p>
341      * @param i An int value.
342      * @return -1 if the specified value is negative; 0 if the specified value is zero; and 1 if 
343      * the specified value is positive.
344      * @since 1.0
345      * @javascript Re-compilers must report error on end-users directly using this method.
346      */
347     public static final int signum(int i) {
348         return ((java.lang.Integer) Js.cond(Js.eq(i, 0), 0,
349                 Js.cond(Js.lt(i, 0), -1, 1))).intValue();
350     }
351 
352     final static ArrayLike<java.lang.String> digits16 = new Vars<java.lang.String>()
353             .add("0").add("1").add("2").add("3").add("4").add("5").add("6")
354             .add("7").add("8").add("9").add("a").add("b").add("c").add("d")
355             .add("e").add("f").var();
356 
357     private static final java.lang.String toBinary(int x, int bm1, int bits) {
358         if (x == 0) {
359             return "0";
360         }
361         java.lang.String s = "";
362         while (x != 0) {
363             int digit = x & bm1;
364             s = Js.add(digits16.get(digit), s);
365             x = x >>> bits;
366         }
367         return s;
368     }
369 
370     /**
371      * <p>Returns a string representation of the argument as an unsigned value in base 2.</p>
372      * @param x A value to be converted to a string.
373      * @return The string representation of the unsigned value represented by the argument in binary (base 2).
374      * @since 1.0
375      * @javascript Re-compilers must report error on end-users directly using this method. 
376      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
377      */
378     public static final synchronized java.lang.String toBinaryString(int x) {
379         return toBinary(x, 1, 1);
380     }
381 
382     /**
383      * <p>Returns a string representation of the argument as an unsigned value in base 8.</p>
384      * @param x A value to be converted to a string.
385      * @return The string representation of the unsigned value represented by the argument in octal (base 8).
386      * @javascript Re-compilers must report error on end-users directly using this method. 
387      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
388      */
389     public static final synchronized java.lang.String toOctalString(int x) {
390         return toBinary(x, 7, 3);
391     }
392 
393     /**
394      * <p>Returns a string representation of the argument as an unsigned value in base 16.</p>
395      * @param x A value to be converted to a string.
396      * @return The string representation of the unsigned value represented by the argument in 
397      * hexadecimal (base 16).
398      * @javascript Re-compilers must report error on end-users directly using this method. 
399      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
400      */
401     public static final synchronized java.lang.String toHexString(int x) {
402         return toBinary(x, 15, 4);
403     }
404 
405     /**
406      * <p>Returns a string representing the specified int. The radix is assumed to be 10.</p>
407      * @param i An int to be converted.
408      * @return The string representation of the specified int.
409      * @since 1.0
410      * @javascript Re-compilers must report error on end-users directly using this method. 
411      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
412      */
413     public static final synchronized java.lang.String toString(int i) {
414         return String.valueOf(i);
415     }
416 
417     /**
418      * <p>Returns an {@link Integer} representing the specified int value.</p>
419      * @param i An int value.
420      * @return An {@link Integer} representing <tt>i</tt>.
421      * @since 1.0
422      * @javascript Re-compilers must report error on end-users directly using this method. 
423      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
424      */
425     public static final synchronized Integer valueOf(int i) {
426         return new Integer(i);
427     }
428 
429     /**
430      * <p>Returns an {@link Integer} represented by the specified string value.</p>
431      * @param s A string value.
432      * @return An {@link Integer} represented by <tt>s</tt>.
433      * @throws java.lang.NumberFormatException if the string does not contain a parsable int.
434      * @since 1.0
435      * @javascript Re-compilers must report error on end-users directly using this method. 
436      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
437      */
438     public static final synchronized Integer valueOf(java.lang.String s)
439             throws java.lang.NumberFormatException {
440         return new Integer(parseInt(s));
441     }
442 
443     /**
444      * <p>Returns an {@link Integer} represented by the specified string value when
445      * parsed with the radix given by the second argument.</p>
446      * @param s A string value.
447      * @param radix The radix to be used in interpreting <tt>s</tt>.
448      * @return An {@link Integer} represented by <tt>s</tt> in the specified radix.
449      * @throws java.lang.NumberFormatException if the string does not contain a parsable int.
450      * @since 1.0
451      * @javascript Re-compilers must report error on end-users directly using this method. 
452      * As a "synchronized" static emulating method, its invocation should be re-compiled into in-lined code for efficiency.
453      */
454     public static final synchronized Integer valueOf(java.lang.String s,
455             int radix) throws java.lang.NumberFormatException {
456         return new Integer(parseInt(s, radix));
457     }
458 
459     /**
460      * <p>Allocates an {@link Integer} representing the int argument.</p>
461      * @param value An int value.
462      * @since 1.0
463      * @javascript Re-compilers must report error on end-users directly using this constructor. 
464      * A re-compiler simply replaces an invocation of this constructor with its argument.
465      */
466     public Integer(int value) {}
467 
468     /**
469      * <p>Allocates an {@link Integer} representing the value indicated by the string parameter.</p>
470      * <p>The string is converted to an int value in exactly the manner used by the
471      * {@link #parseInt(String)} method for radix 10.</p>
472      * @param s A string to be converted to an {@link Integer}.
473      * @throws NumberFormatException if the string does not contain a parsable int.
474      * @since 1.0
475      * @javascript Re-compilers must report error on end-users directly using this constructor. 
476      * A re-compiler simply replaces an invocation of this constructor with an invocation of {@link #valueOf(String)} passing the string argument.
477      */
478     public Integer(java.lang.String s) {}
479 
480     /**
481      * <p>Returns the value of this {@link Integer} as a byte primitive.</p>
482      * @return The primitive byte value.
483      * @since 1.0
484      * @javascript Re-compilers must report error on end-users directly using this method. 
485      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer} involving rounding or truncation necessarily.
486      */
487     @Override
488     public final native byte byteValue();
489 
490     /**
491      * <p>Returns the value of this {@link Integer} as a short primitive.</p>
492      * @return The primitive short value.
493      * @since 1.0
494      * @javascript Re-compilers must report error on end-users directly using this method. 
495      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer} involving rounding or truncation necessarily.
496      */
497     @Override
498     public final native short shortValue();
499 
500     /**
501      * <p>Returns the value of this {@link Integer} as an int primitive.</p>
502      * @return The primitive int value.
503      * @since 1.0
504      * @javascript Re-compilers must report error on end-users directly using this method. 
505      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer}.
506      */
507     @Override
508     public final native int intValue();
509 
510     /**
511      * <p>Returns the value of this {@link Integer} as a long primitive.</p>
512      * @return The primitive long value.
513      * @since 1.0
514      * @javascript Re-compilers must report error on end-users directly using this method. 
515      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer}.
516      */
517     @Override
518     public final native long longValue();
519 
520     /**
521      * <p>Returns the value of this {@link Integer} as a float primitive.</p>
522      * @return The primitive float value.
523      * @since 1.0
524      * @javascript Re-compilers must report error on end-users directly using this method. 
525      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer}.
526      */
527     @Override
528     public final native float floatValue();
529 
530     /**
531      * <p>Returns the value of this {@link Integer} as a long primitive.</p>
532      * @return The primitive double value.
533      * @since 1.0
534      * @javascript Re-compilers must report error on end-users directly using this method. 
535      * A re-compiler simply replaces an invocation of this native method with the current {@link Integer}.
536      */
537     @Override
538     public final native double doubleValue();
539 
540     /**
541      * <p>Compares two {@link Integer}s numerically.</p>
542      * @param i The {@link Integer} to be compared.
543      * @return 0 if this {@link Integer} is equal to the argument {@link Integer}; a value less 
544      * than 0 if this {@link Integer} is numerically less than the argument {@link Integer}; and 
545      * a value greater than 0 if this {@link Integer} is numerically greater than the argument 
546      * {@link Integer} (signed comparison).
547      * @since 1.0
548      * @javascript Re-compilers must report error on end-users directly using this method. 
549      * For efficiency, the invocation of this instance emulation method with single statement can be in-lined in re-compilation.
550      */
551     public final int compareTo(Integer i) {
552         return ((java.lang.Integer) Js.cond(Js.lt(this, i), -1,
553                 Js.cond(Js.gt(this, i), 1, 0))).intValue();
554     }
555 
556     /**
557      * <p>Compares this {@link Integer} to the specified object.</p>
558      * <p>Returns <tt>true</tt> if and only if the argument is not <tt>null</tt>
559      * and is an {@link Integer} that represents the same value as this {@link Integer}.</p>
560      * @param o The object to compare with.
561      * @return <tt>true</tt> if the {@link Integer}s represent the same value; <tt>false</tt> otherwise.
562      * @since 1.0
563      * @javascript Re-compilers must report error on end-users directly using this method. 
564      * For efficiency, the invocation of this instance emulation method with single statement can be in-lined in re-compilation.
565      */
566     @Override
567     public final boolean equals(java.lang.Object o) {
568         return Js.eq(this, o);
569     }
570 
571     /**
572      * <p>Returns a hash code for this {@link Integer}.</p>
573      * @return A hash code value for this {@link Integer}.
574      * @since 1.0
575      * @javascript Re-compilers must report error on end-users directly using this method. 
576      * For efficiency, the invocation of this instance emulation method with single statement can be in-lined in re-compilation.
577      */
578     @Override
579     public final int hashCode() {
580         return intValue();
581     }
582 
583     /**
584      * <p>Returns a string representing this {@link Integer}'s value.</p>
585      * <p>The value is converted to signed decimal representation and returned as a
586      * string, exactly as if the int value were given as an argument to the
587      * {@link #toString(int)} method.</p>
588      * @return A string representation of this {@link Integer} in base 10.
589      * @since 1.0
590      * @javascript Re-compilers must report error on end-users directly using this method.
591      */
592     @Override
593     public final java.lang.String toString() {
594         return toString(intValue());
595     }
596 }