From 93f7aeea7ac79573748c5f2632059aa6b50d74e2 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Thu, 13 Jun 2002 18:16:26 +0000
Subject: natString.cc (init): Handle case where DONT_COPY is true and
 OFFSET!=0.

	* java/lang/natString.cc (init): Handle case where DONT_COPY is
	true and OFFSET!=0.
	* java/lang/String.java (String(char[],int,int,boolean): New
	constructor.
	* java/lang/Long.java: Imported new version from Classpath.
	* java/lang/Number.java: Likewise.
	* java/lang/Integer.java: Likewise.
	* java/lang/Long.java: Likewise.
	* java/lang/Float.java: Likewise.
	* java/lang/Boolean.java: Likewise.
	* java/lang/Double.java: Likewise.
	* java/lang/Void.java: Likewise.

From-SVN: r54595
---
 libjava/java/lang/Long.java | 799 +++++++++++++++++++++++---------------------
 1 file changed, 410 insertions(+), 389 deletions(-)

(limited to 'libjava/java/lang/Long.java')

diff --git a/libjava/java/lang/Long.java b/libjava/java/lang/Long.java
index 42f2761..1420e58 100644
--- a/libjava/java/lang/Long.java
+++ b/libjava/java/lang/Long.java
@@ -1,5 +1,5 @@
-/* java.lang.Long
-   Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+/* Long.java -- object wrapper for long
+   Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
- 
+
 GNU Classpath is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
@@ -39,8 +39,8 @@ exception statement from your version. */
 package java.lang;
 
 /**
- * Instances of class <code>Double</code> represent primitive
- * <code>double</code> values.
+ * Instances of class <code>Long</code> represent primitive
+ * <code>long</code> values.
  *
  * Additionally, this class provides various helper functions and variables
  * related to longs.
@@ -48,38 +48,45 @@ package java.lang;
  * @author Paul Fisher
  * @author John Keiser
  * @author Warren Levy
- * @since JDK 1.0
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.0
+ * @status updated to 1.4
  */
 public final class Long extends Number implements Comparable
 {
-  // compatible with JDK 1.0.2+
-  static final long serialVersionUID = 4290774380558885855L;
+  /**
+   * Compatible with JDK 1.0.2+.
+   */
+  private static final long serialVersionUID = 4290774380558885855L;
 
   /**
    * The minimum value a <code>long</code> can represent is
-   * -9223372036854775808.
+   * -9223372036854775808L (or -2<sup>63</sup>).
    */
   public static final long MIN_VALUE = 0x8000000000000000L;
 
   /**
    * The maximum value a <code>long</code> can represent is
-   * 9223372036854775807.
+   * 9223372036854775807 (or 2<sup>63</sup> - 1).
    */
   public static final long MAX_VALUE = 0x7fffffffffffffffL;
 
   /**
-   * The primitive type <code>long</code> is represented by this 
+   * The primitive type <code>long</code> is represented by this
    * <code>Class</code> object.
+   * @since 1.1
    */
   public static final Class TYPE = VMClassLoader.getPrimitiveClass ('J');
 
   /**
    * The immutable value of this Long.
+   *
+   * @serial the wrapped long
    */
   private final long value;
 
   /**
-   * Create a <code>Long</code> object representing the value of the 
+   * Create a <code>Long</code> object representing the value of the
    * <code>long</code> argument.
    *
    * @param value the value to use
@@ -90,504 +97,518 @@ public final class Long extends Number implements Comparable
   }
 
   /**
-   * Create a <code>Long</code> object representing the value of the 
+   * Create a <code>Long</code> object representing the value of the
    * argument after conversion to a <code>long</code>.
    *
-   * @param s the string to convert.
+   * @param s the string to convert
+   * @throws NumberFormatException if the String does not contain a long
+   * @see #valueOf(String)
    */
-  public Long(String s) throws NumberFormatException
+  public Long(String s)
   {
-    value = parseLong(s, 10);
+    value = parseLong(s, 10, false);
   }
 
   /**
-   * If the <code>Object</code> is not <code>null</code>, is an
-   * <code>instanceof</code> <code>Long</code>, and represents
-   * the same primitive <code>long</code> value return 
-   * <code>true</code>.  Otherwise <code>false</code> is returned.
+   * Converts the <code>long</code> to a <code>String</code> using
+   * the specified radix (base). If the radix exceeds
+   * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10
+   * is used instead. If the result is negative, the leading character is
+   * '-' ('\\u002D'). The remaining characters come from
+   * <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z').
+   *
+   * @param num the <code>long</code> to convert to <code>String</code>
+   * @param radix the radix (base) to use in the conversion
+   * @return the <code>String</code> representation of the argument
    */
-  public boolean equals(Object obj)
+  public static String toString(long num, int radix)
   {
-    return obj instanceof Long && ((Long)obj).value == value;
+    // Use the Integer toString for efficiency if possible.
+    if ((int) num == num)
+      return Integer.toString((int) num, radix);
+
+    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+      radix = 10;
+
+    // For negative numbers, print out the absolute value w/ a leading '-'.
+    // Use an array large enough for a binary number.
+    char[] buffer = new char[65];
+    int i = 65;
+    boolean isNeg = false;
+    if (num < 0)
+      {
+        isNeg = true;
+        num = -num;
+
+        // When the value is MIN_VALUE, it overflows when made positive
+        if (num < 0)
+	  {
+	    buffer[--i] = digits[(int) (-(num + radix) % radix)];
+	    num = -(num / radix);
+	  }
+      }
+
+    do
+      {
+        buffer[--i] = digits[(int) (num % radix)];
+        num /= radix;
+      }
+    while (num > 0);
+
+    if (isNeg)
+      buffer[--i] = '-';
+
+    // Package constructor avoids an array copy.
+    return new String(buffer, i, 65 - i, true);
   }
 
   /**
-   * Return a hashcode representing this Object.
+   * Converts the <code>long</code> to a <code>String</code> assuming it is
+   * unsigned in base 16.
    *
-   * <code>Long</code>'s hash code is calculated by simply returning its
-   * value.
+   * @param l the <code>long</code> to convert to <code>String</code>
+   * @return the <code>String</code> representation of the argument
+   */
+  public static String toHexString(long l)
+  {
+    return toUnsignedString(l, 4);
+  }
+
+  /**
+   * Converts the <code>long</code> to a <code>String</code> assuming it is
+   * unsigned in base 8.
    *
-   * @return this Object's hash code.
+   * @param l the <code>long</code> to convert to <code>String</code>
+   * @return the <code>String</code> representation of the argument
    */
-  public int hashCode()
+  public static String toOctalString(long l)
   {
-    return (int)(value^(value>>>32));
+    return toUnsignedString(l, 3);
   }
 
   /**
-   * Get the specified system property as a <code>Long</code>.
+   * Converts the <code>long</code> to a <code>String</code> assuming it is
+   * unsigned in base 2.
    *
-   * A method similar to <code>Integer</code>'s <code>decode()</code> will be
-   * used to interpret the value of the property.
-   * 
-   * @param nm the name of the system property
-   * @return the system property as an <code>Long</code>, or
-   *         <code>null</code> if the property is not found or cannot be
-   *         decoded as a <code>Long</code>.
-   * @see java.lang.System#getProperty(java.lang.String)
-   * @see java.lang.Integer#decode(int)
+   * @param l the <code>long</code> to convert to <code>String</code>
+   * @return the <code>String</code> representation of the argument
    */
-  public static Long getLong(String nm)
+  public static String toBinaryString(long l)
   {
-    return getLong(nm, null);
+    return toUnsignedString(l, 1);
   }
 
   /**
-   * Get the specified system property as an <code>Long</code>, or use a
-   * default <code>long</code> value if the property is not found or is not
-   * decodable.
-   * 
-   * A method similar to <code>Integer</code>'s <code>decode()</code> will be
-   * used to interpret the value of the property.
-   * 
-   * @param nm the name of the system property
-   * @param val the default value to use if the property is not found or not
-   *        a number.
-   * @return the system property as a <code>Long</code>, or the default
-   *         value if the property is not found or cannot be decoded as a
-   *         <code>Long</code>.
-   * @see java.lang.System#getProperty(java.lang.String)
-   * @see java.lang.Integer#decode(int)
-   * @see #getLong(java.lang.String,java.lang.Long)
+   * Converts the <code>long</code> to a <code>String</code> and assumes
+   * a radix of 10.
+   *
+   * @param num the <code>long</code> to convert to <code>String</code>
+   * @return the <code>String</code> representation of the argument
+   * @see #toString(long, int)
    */
-  public static Long getLong(String nm, long val)
+  public static String toString(long num)
   {
-    Long result = getLong(nm, null);
-    return (result == null) ? new Long(val) : result;
+    return toString(num, 10);
   }
 
   /**
-   * Get the specified system property as an <code>Long</code>, or use a
-   * default <code>Long</code> value if the property is not found or is
-   * not decodable.
-   * 
-   * The <code>decode()</code> method will be used to interpret the value of
-   * the property.
+   * Converts the specified <code>String</code> into an <code>int</code>
+   * using the specified radix (base). The string must not be <code>null</code>
+   * or empty. It may begin with an optional '-', which will negate the answer,
+   * provided that there are also valid digits. Each digit is parsed as if by
+   * <code>Character.digit(d, radix)</code>, and must be in the range
+   * <code>0</code> to <code>radix - 1</code>. Finally, the result must be
+   * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive.
+   * Unlike Double.parseDouble, you may not have a leading '+'; and 'l' or
+   * 'L' as the last character is only valid in radices 22 or greater, where
+   * it is a digit and not a type indicator.
    *
-   * @param nm the name of the system property
-   * @param val the default value to use if the property is not found or not
-   *        a number.
-   * @return the system property as an <code>Long</code>, or the default
-   *         value if the property is not found or cannot be decoded as an
-   *         <code>Long</code>.
-   * @see java.lang.System#getProperty(java.lang.String)
-   * @see java.lang.Integer#decode(int)
-   * @see #getLong(java.lang.String,long)
+   * @param s the <code>String</code> to convert
+   * @param radix the radix (base) to use in the conversion
+   * @return the <code>String</code> argument converted to </code>long</code>
+   * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+   *         <code>long</code>
    */
-  public static Long getLong(String nm, Long def)
+  public static long parseLong(String str, int radix)
   {
-    String val = System.getProperty(nm);
-    if (val == null)
-      return def;
-    try
-      {
-	return decode(nm);
-      }
-    catch (NumberFormatException e)
-      {
-	return def;
-      }
+    return parseLong(str, radix, false);
   }
 
-  private static String toUnsignedString(long num, int exp)
+  /**
+   * Converts the specified <code>String</code> into a <code>long</code>.
+   * This function assumes a radix of 10.
+   *
+   * @param s the <code>String</code> to convert
+   * @return the <code>int</code> value of <code>s</code>
+   * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+   *         <code>long</code>
+   * @see #parseLong(String, int)
+   */
+  public static long parseLong(String s)
   {
-    // Use an array large enough for a binary number.
-    int radix = 1 << exp;
-    int mask = radix - 1;
-    char[] buffer = new char[64];
-    int i = 64;
-    do
-      {
-        buffer[--i] = Character.forDigit((int) num & mask, radix);
-        num = num >>> exp;
-      }
-    while (num != 0);
+    return parseLong(s, 10, false);
+  }
 
-    return String.valueOf(buffer, i, 64-i);
+  /**
+   * Creates a new <code>Long</code> object using the <code>String</code>
+   * and specified radix (base).
+   *
+   * @param s the <code>String</code> to convert
+   * @param radix the radix (base) to convert with
+   * @return the new <code>Long</code>
+   * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+   *         <code>long</code>
+   * @see #parseLong(String, int)
+   */
+  public static Long valueOf(String s, int radix)
+  {
+    return new Long(parseLong(s, radix, false));
   }
 
   /**
-   * Converts the <code>long</code> to a <code>String</code> assuming it is
-   * unsigned in base 16.
-   * @param i the <code>long</code> to convert to <code>String</code>
-   * @return the <code>String</code> representation of the argument.
+   * Creates a new <code>Long</code> object using the <code>String</code>,
+   * assuming a radix of 10.
+   *
+   * @param s the <code>String</code> to convert
+   * @return the new <code>Long</code>
+   * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+   *         <code>long</code>
+   * @see #Long(String)
+   * @see #parseLong(String)
    */
-  public static String toHexString(long i)
+  public static Long valueOf(String s)
   {
-    return toUnsignedString(i, 4);
+    return new Long(parseLong(s, 10, false));
   }
 
   /**
-   * Converts the <code>long</code> to a <code>String</code> assuming it is
-   * unsigned in base 8.
-   * @param i the <code>long</code> to convert to <code>String</code>
-   * @return the <code>String</code> representation of the argument.
+   * Convert the specified <code>String</code> into a <code>Long</code>.
+   * The <code>String</code> may represent decimal, hexadecimal, or
+   * octal numbers.
+   *
+   * <p>The extended BNF grammar is as follows:<br>
+   * <pre>
+   * <em>DecodableString</em>:
+   *      ( [ <code>-</code> ] <em>DecimalNumber</em> )
+   *    | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code>
+   *              | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } )
+   *    | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } )
+   * <em>DecimalNumber</em>:
+   *        <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> }
+   * <em>DecimalDigit</em>:
+   *        <em>Character.digit(d, 10) has value 0 to 9</em>
+   * <em>OctalDigit</em>:
+   *        <em>Character.digit(d, 8) has value 0 to 7</em>
+   * <em>DecimalDigit</em>:
+   *        <em>Character.digit(d, 16) has value 0 to 15</em>
+   * </pre>
+   * Finally, the value must be in the range <code>MIN_VALUE</code> to
+   * <code>MAX_VALUE</code>, or an exception is thrown. Note that you cannot
+   * use a trailing 'l' or 'L', unlike in Java source code.
+   *
+   * @param s the <code>String</code> to interpret
+   * @return the value of the String as a <code>Long</code>
+   * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+   *         <code>long</code>
+   * @throws NullPointerException if <code>s</code> is null
+   * @since 1.2
    */
-  public static String toOctalString(long i)
+  public static Long decode(String str)
   {
-    return toUnsignedString(i, 3);
+    return new Long(parseLong(str, 10, true));
   }
 
   /**
-   * Converts the <code>long</code> to a <code>String</code> assuming it is
-   * unsigned in base 2.
-   * @param i the <code>long</code> to convert to <code>String</code>
-   * @return the <code>String</code> representation of the argument.
+   * Return the value of this <code>Long</code> as a <code>byte</code>.
+   *
+   * @return the byte value
    */
-  public static String toBinaryString(long i) {
-    return toUnsignedString(i, 1);
+  public byte byteValue()
+  {
+    return (byte) value;
   }
 
   /**
-   * Converts the <code>long</code> to a <code>String</code> and assumes
-   * a radix of 10.
-   * @param num the <code>long</code> to convert to <code>String</code>
-   * @return the <code>String</code> representation of the argument.
-   */    
-  public static String toString(long num)
+   * Return the value of this <code>Long</code> as a <code>short</code>.
+   *
+   * @return the short value
+   */
+  public short shortValue()
   {
-    // Use the Integer toString for efficiency if possible.
-    if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)
-      return Integer.toString((int) num);
+    return (short) value;
+  }
 
-    // Use an array large enough for "-9223372036854775808"; i.e. 20 chars.
-    char[] buffer = new char[20];
-    int i = 20;
-    boolean isNeg;
-    if (num < 0)
-      {
-        isNeg = true;
-        num = -(num);
-        if (num < 0)
-          {
-            // Must be MIN_VALUE, so handle this special case.
-            buffer[--i] = '8';
-            num = 922337203685477580L;
-          }
-      }
-    else
-      isNeg = false;
+  /**
+   * Return the value of this <code>Long</code> as an <code>int</code>.
+   *
+   * @return the int value
+   */
+  public int intValue()
+  {
+    return (int) value;
+  }
 
-    do
-      {
-        buffer[--i] = (char) ((int) '0' + (num % 10));
-        num /= 10;
-      }
-    while (num > 0);
+  /**
+   * Return the value of this <code>Long</code>.
+   *
+   * @return the long value
+   */
+  public long longValue()
+  {
+    return value;
+  }
 
-    if (isNeg)
-      buffer[--i] = '-';
+  /**
+   * Return the value of this <code>Long</code> as a <code>float</code>.
+   *
+   * @return the float value
+   */
+  public float floatValue()
+  {
+    return value;
+  }
 
-    return String.valueOf(buffer, i, 20-i);
+  /**
+   * Return the value of this <code>Long</code> as a <code>double</code>.
+   *
+   * @return the double value
+   */
+  public double doubleValue()
+  {
+    return value;
   }
 
   /**
    * Converts the <code>Long</code> value to a <code>String</code> and
    * assumes a radix of 10.
-   * @return the <code>String</code> representation of this <code>Long</code>.
-   */    
+   *
+   * @return the <code>String</code> representation
+   */
   public String toString()
   {
-    return toString(value);
+    return toString(value, 10);
   }
-  
+
   /**
-   * Converts the <code>long</code> to a <code>String</code> using
-   * the specified radix (base).
-   * @param num the <code>long</code> to convert to <code>String</code>.
-   * @param radix the radix (base) to use in the conversion.
-   * @return the <code>String</code> representation of the argument.
+   * Return a hashcode representing this Object. <code>Long</code>'s hash
+   * code is calculated by <code>(int) (value ^ (value &gt;&gt; 32))</code>.
+   *
+   * @return this Object's hash code
    */
-  public static String toString(long num, int radix)
+  public int hashCode()
   {
-    // Use optimized method for the typical case.
-    if (radix == 10 ||
-        radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
-      return toString(num);
-
-    // Use the Integer toString for efficiency if possible.
-    if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)
-      return Integer.toString((int) num, radix);
-
-    // For negative numbers, print out the absolute value w/ a leading '-'.
-    // Use an array large enough for a binary number.
-    char[] buffer = new char[65];
-    int i = 65;
-    boolean isNeg;
-    if (num < 0)
-      {
-        isNeg = true;
-        num = -(num);
-
-        // When the value is MIN_VALUE, it overflows when made positive
-        if (num < 0)
-          {
-            buffer[--i] = Character.forDigit((int) (-(num + radix) % radix),
-						radix);
-            num = -(num / radix);
-          }
-      }
-    else
-      isNeg = false;
+    return (int) (value ^ (value >>> 32));
+  }
 
-    do
-      {
-        buffer[--i] = Character.forDigit((int) (num % radix), radix);
-        num /= radix;
-      }
-    while (num > 0);
+  /**
+   * Returns <code>true</code> if <code>obj</code> is an instance of
+   * <code>Long</code> and represents the same long value.
+   *
+   * @param obj the object to compare
+   * @return whether these Objects are semantically equal
+   */
+  public boolean equals(Object obj)
+  {
+    return obj instanceof Long && value == ((Long) obj).value;
+  }
 
-    if (isNeg)
-      buffer[--i] = '-';
+  /**
+   * Get the specified system property as a <code>Long</code>. The
+   * <code>decode()</code> method will be used to interpret the value of
+   * the property.
+   *
+   * @param nm the name of the system property
+   * @return the system property as a <code>Long</code>, or null if the
+   *         property is not found or cannot be decoded
+   * @throws SecurityException if accessing the system property is forbidden
+   * @see System#getProperty(String)
+   * @see #decode(String)
+   */
+  public static Long getLong(String nm)
+  {
+    return getLong(nm, null);
+  }
 
-    return String.valueOf(buffer, i, 65-i);
+  /**
+   * Get the specified system property as a <code>Long</code>, or use a
+   * default <code>long</code> value if the property is not found or is not
+   * decodable. The <code>decode()</code> method will be used to interpret
+   * the value of the property.
+   *
+   * @param nm the name of the system property
+   * @param val the default value
+   * @return the value of the system property, or the default
+   * @throws SecurityException if accessing the system property is forbidden
+   * @see System#getProperty(String)
+   * @see #decode(String)
+   */
+  public static Long getLong(String nm, long val)
+  {
+    Long result = getLong(nm, null);
+    return result == null ? new Long(val) : result;
   }
-    
+
   /**
-   * Creates a new <code>Long</code> object using the <code>String</code>,
-   * assuming a radix of 10.
-   * @param s the <code>String</code> to convert.
-   * @return the new <code>Long</code>.
-   * @see #Long(java.lang.String)
-   * @see #parseLong(java.lang.String)
-   * @exception NumberFormatException thrown if the <code>String</code> 
-   * cannot be parsed as a <code>long</code>.
-   */
-  public static Long valueOf(String s) throws NumberFormatException
+   * Get the specified system property as a <code>Long</code>, or use a
+   * default <code>Long</code> value if the property is not found or is
+   * not decodable. The <code>decode()</code> method will be used to
+   * interpret the value of the property.
+   *
+   * @param nm the name of the system property
+   * @param val the default value
+   * @return the value of the system property, or the default
+   * @throws SecurityException if accessing the system property is forbidden
+   * @see System#getProperty(String)
+   * @see #decode(String)
+   */
+  public static Long getLong(String nm, Long def)
   {
-    return new Long(parseLong(s));
+    if (nm == null || "".equals(nm))
+      return def;
+    nm = System.getProperty(nm);
+    if (nm == null)
+      return def;
+    try
+      {
+        return decode(nm);
+      }
+    catch (NumberFormatException e)
+      {
+        return def;
+      }
   }
 
   /**
-   * Creates a new <code>Long</code> object using the <code>String</code>
-   * and specified radix (base).
-   * @param s the <code>String</code> to convert.
-   * @param radix the radix (base) to convert with.
-   * @return the new <code>Long</code>.
-   * @see #parseLong(java.lang.String,int)
-   * @exception NumberFormatException thrown if the <code>String</code> 
-   * cannot be parsed as a <code>long</code>.
-   */
-  public static Long valueOf(String s, int radix) throws NumberFormatException
+   * Compare two Longs numerically by comparing their <code>long</code>
+   * values. The result is positive if the first is greater, negative if the
+   * second is greater, and 0 if the two are equal.
+   *
+   * @param l the Long to compare
+   * @return the comparison
+   * @since 1.2
+   */
+  public int compareTo(Long l)
   {
-    return new Long(parseLong(s, radix));
+    if (value == l.value)
+      return 0;
+    // Returns just -1 or 1 on inequality; doing math might overflow the long.
+    return value > l.value ? 1 : -1;
   }
 
   /**
-   * Converts the specified <code>String</code> into a <code>long</code>.
-   * This function assumes a radix of 10.
+   * Behaves like <code>compareTo(Long)</code> unless the Object
+   * is not a <code>Long</code>.
    *
-   * @param s the <code>String</code> to convert
-   * @return the <code>long</code> value of the <code>String</code>
-   *         argument.
-   * @exception NumberFormatException thrown if the <code>String</code> 
-   * cannot be parsed as a <code>long</code>.
+   * @param o the object to compare
+   * @return the comparison
+   * @throws ClassCastException if the argument is not a <code>Long</code>
+   * @see #compareTo(Long)
+   * @see Comparable
+   * @since 1.2
    */
-  public static long parseLong(String s) throws NumberFormatException
+  public int compareTo(Object o)
   {
-    return parseLong(s, 10);
+    return compareTo((Long) o);
   }
 
   /**
-   * Converts the specified <code>String</code> into a <code>long</code>
-   * using the specified radix (base).
+   * Helper for converting unsigned numbers to String.
    *
-   * @param s the <code>String</code> to convert
-   * @param radix the radix (base) to use in the conversion
-   * @return the <code>String</code> argument converted to </code>long</code>.
-   * @exception NumberFormatException thrown if the <code>String</code> 
-   * cannot be parsed as a <code>long</code>.    
+   * @param num the number
+   * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex)
    */
-  public static long parseLong(String str, int radix)
-    throws NumberFormatException
+  private static String toUnsignedString(long num, int exp)
   {
-    final int len;
+    // Use the Integer toUnsignedString for efficiency if possible.
+    // If NUM<0 then this particular optimization doesn't work
+    // properly.
+    if (num >= 0 && (int) num == num)
+      return Integer.toUnsignedString((int) num, exp);
 
-    if ((len = str.length()) == 0 || radix < Character.MIN_RADIX 
-         || radix > Character.MAX_RADIX)
-      throw new NumberFormatException();
+    // Use an array large enough for a binary number.
+    int mask = (1 << exp) - 1;
+    char[] buffer = new char[64];
+    int i = 64;
+    do
+      {
+        buffer[--i] = digits[(int) num & mask];
+        num >>>= exp;
+      }
+    while (num != 0);
 
-    boolean isNeg = false;
-    int index = 0;
-    if (str.charAt(index) == '-')
-      if (len > 1)
-        {
-          isNeg = true;
-          index++;
-        }
-      else
-        throw new NumberFormatException();
-
-    return parseLong(str, index, len, isNeg, radix);
+    // Package constructor avoids an array copy.
+    return new String(buffer, i, 64 - i, true);
   }
 
-  public static Long decode(String str) throws NumberFormatException
+  /**
+   * Helper for parsing longs.
+   *
+   * @param str the string to parse
+   * @param radix the radix to use, must be 10 if decode is true
+   * @param decode if called from decode
+   * @return the parsed long value
+   * @throws NumberFormatException if there is an error
+   * @throws NullPointerException if decode is true and str is null
+   * @see #parseLong(String, int)
+   * @see #decode(String)
+   */
+  private static long parseLong(String str, int radix, boolean decode)
   {
-    boolean isNeg = false;
+    if (! decode && str == null)
+      throw new NumberFormatException();
     int index = 0;
-    int radix = 10;
-    final int len;
-
-    if ((len = str.length()) == 0)
+    int len = str.length();
+    boolean isNeg = false;
+    if (len == 0)
       throw new NumberFormatException();
-
-    // Negative numbers are always radix 10.
-    if (str.charAt(0) == '-')
+    int ch = str.charAt(index);
+    if (ch == '-')
       {
-        radix = 10;
-        index++;
+        if (len == 1)
+          throw new NumberFormatException();
         isNeg = true;
+        ch = str.charAt(++index);
       }
-    else if (str.charAt(index) == '#')
-      {
-        radix = 16;
-        index++;
-      }
-    else if (str.charAt(index) == '0')
+    if (decode)
       {
-        // Check if str is just "0"
-        if (len == 1)
-          return new Long(0L);
-
-        index++;
-        if (str.charAt(index) == 'x')
+        if (ch == '0')
+          {
+            if (++index == len)
+              return 0;
+            if ((str.charAt(index) & ~('x' ^ 'X')) == 'X')
+              {
+                radix = 16;
+                index++;
+              }
+            else
+              radix = 8;
+          }
+        else if (ch == '#')
           {
             radix = 16;
             index++;
           }
-        else
-          radix = 8;
       }
-
-    if (index >= len)
+    if (index == len)
       throw new NumberFormatException();
 
-    return new Long(parseLong(str, index, len, isNeg, radix));
-  }
-
-  private static long parseLong(String str, int index, int len, boolean isNeg,
-        			int radix) throws NumberFormatException
-  {
-    long val = 0;
-    int digval;
-
     long max = MAX_VALUE / radix;
     // We can't directly write `max = (MAX_VALUE + 1) / radix'.
     // So instead we fake it.
     if (isNeg && MAX_VALUE % radix == radix - 1)
       ++max;
 
-    for ( ; index < len; index++)
+    long val = 0;
+    while (index < len)
       {
 	if (val < 0 || val > max)
 	  throw new NumberFormatException();
 
-        if ((digval = Character.digit(str.charAt(index), radix)) < 0)
+        ch = Character.digit(str.charAt(index++), radix);
+        val = val * radix + ch;
+        if (ch < 0 || (val < 0 && (! isNeg || val != MIN_VALUE)))
           throw new NumberFormatException();
-
-        // Throw an exception for overflow if result is negative.
-	// However, we special-case the most negative value.
-	val = val * radix + digval;
-	if (val < 0 && (! isNeg || val != MIN_VALUE))
-	  throw new NumberFormatException();
       }
-
-    return isNeg ? -(val) : val;
-  }
-
-  /** Return the value of this <code>Long</code> as an <code>short</code>.
-   ** @return the value of this <code>Long</code> as an <code>short</code>.
-   **/
-  public byte byteValue()
-  {
-    return (byte) value;
-  }
-
-  /** Return the value of this <code>Long</code> as an <code>short</code>.
-   ** @return the value of this <code>Long</code> as an <code>short</code>.
-   **/
-  public short shortValue()
-  {
-    return (short) value;
-  }
-
-  /** Return the value of this <code>Long</code> as an <code>int</code>.
-   ** @return the value of this <code>Long</code> as an <code>int</code>.
-   **/
-  public int intValue()
-  {
-    return (int) value;
-  }
-
-  /** Return the value of this <code>Long</code> as a <code>long</code>.
-   ** @return the value of this <code>Long</code> as a <code>long</code>.
-   **/
-  public long longValue()
-  {
-    return value;
-  }
-
-  /** Return the value of this <code>Long</code> as a <code>float</code>.
-   ** @return the value of this <code>Long</code> as a <code>float</code>.
-   **/
-  public float floatValue()
-  {
-    return value;
-  }
-
-  /** Return the value of this <code>Long</code> as a <code>double</code>.
-   ** @return the value of this <code>Long</code> as a <code>double</code>.
-   **/
-  public double doubleValue()
-  {
-    return value;
-  }
-
-  /**
-   * Compare two Longs numerically by comparing their
-   * <code>long</code> values.
-   * @return a positive value if this <code>Long</code> is greater
-   * in value than the argument <code>Long</code>; a negative value
-   * if this <code>Long</code> is smaller in value than the argument
-   * <code>Long</code>; and <code>0</code>, zero, if this
-   * <code>Long</code> is equal in value to the argument
-   * <code>Long</code>.  
-   *
-   * @since 1.2
-   */
-  public int compareTo(Long l)
-  {
-    if (this.value == l.value)
-      return 0;
-
-    // Returns just -1 or 1 on inequality; doing math might overflow the long.
-    if (this.value > l.value)
-      return 1;
-
-    return -1;
-  }
-    
-  /**
-   * Behaves like <code>compareTo(java.lang.Long)</code> unless the Object
-   * is not a <code>Long</code>.  Then it throws a 
-   * <code>ClassCastException</code>.
-   * @exception ClassCastException if the argument is not a
-   * <code>Long</code>.
-   *
-   * @since 1.2
-   */
-  public int compareTo(Object o)
-  {
-    return compareTo((Long)o);
+    return isNeg ? -val : val;
   }
 }
-- 
cgit v1.1