/* Copyright (C) 1998, 1999  Cygnus Solutions

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */
 
package java.lang;

/**
 * @author Warren Levy <warrenl@cygnus.com>
 * @date September 18, 1998.  
 */
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
 * Status:  Believed complete and correct.
 */
 
public final class Long extends Number implements Comparable
{
  public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
  public static final long MIN_VALUE = 0x8000000000000000L;

  // This initialization is seemingly circular, but it is accepted
  // by javac, and is handled specially by gcc.
  public static final Class TYPE = long.class;

  /* The long value of the instance. */
  private long value;

  public Long(long val)
  {
    value = val;
  }

  public Long(String str) throws NumberFormatException
  {
    value = parseLong(str, 10);
  }

  public byte byteValue()
  {
    return (byte) value;
  }

  public double doubleValue()
  {
    return (double) value;
  }

  public float floatValue()
  {
    return (float) value;
  }

  public int intValue()
  {
    return (int) value;
  }

  public long longValue()
  {
    return value;
  }

  public short shortValue()
  {
    return (short) value;
  }

  // Added in JDK 1.2
  public int compareTo(Long anotherLong)
  {
    if (this.value == anotherLong.value)
      return 0;

    // Returns just -1 or 1 on inequality; doing math might overflow the long.
    if (this.value > anotherLong.value)
      return 1;

    return -1;
  }

  // Added in JDK 1.2
  public int compareTo(Object o) throws ClassCastException
  {
    if (!(o instanceof Long))
      throw new ClassCastException();

    return this.compareTo((Long) o);
  }

  // Added in JDK 1.2
  public static Long decode(String str) throws NumberFormatException
  {
    boolean isNeg = false;
    int index = 0;
    int radix = 10;
    final int len;

    if (str == null || (len = str.length()) == 0)
      throw new NumberFormatException();

    // Negative numbers are always radix 10.
    if (str.charAt(0) == '-')
      {
        radix = 10;
        index++;
        isNeg = true;
      }
    else if (str.charAt(index) == '#')
      {
        radix = 16;
        index++;
      }
    else if (str.charAt(index) == '0')
      {
        // Check if str is just "0"
        if (len == 1)
          return new Long(0L);

        index++;
        if (str.charAt(index) == 'x')
          {
            radix = 16;
            index++;
          }
        else
          radix = 8;
      }

    if (index >= len)
      throw new NumberFormatException();

    return new Long(parseLong(str, index, len, isNeg, radix));
  }

  public boolean equals(Object obj)
  {
    return (obj != null && (obj instanceof Long)
            && ((Long) obj).value == value);
  }

  public static Long getLong(String prop)
  {
    return getLong(prop, null);
  }

  public static Long getLong(String prop, long defval)
  {
    Long val = getLong(prop, null);
    return val == null ? new Long(defval) : val;
  }

  public static Long getLong(String prop, Long defobj)
  {
    try
    {
      return decode(System.getProperty(prop));
    }
    catch (NumberFormatException ex)
    {
      return defobj;
    }
  }

  public int hashCode()
  {
    return (int)(this.longValue()^(this.longValue()>>>32));
  }

  public static long parseLong(String str) throws NumberFormatException
  {
    return parseLong(str, 10);
  }

  public static long parseLong(String str, int radix)
			throws NumberFormatException
  {
    final int len;

    if (str == null || (len = str.length()) == 0 ||
        radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
      throw new NumberFormatException();

    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);
  }

  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++)
      {
	if (val < 0 || val > max)
	  throw new NumberFormatException();

        if ((digval = Character.digit(str.charAt(index), radix)) < 0)
          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;
  }

  public static String toBinaryString(long num)
  {
    return toUnsignedString(num, 1);
  }

  public static String toHexString(long num)
  {
    return toUnsignedString(num, 4);
  }

  public static String toOctalString(long num)
  {
    return toUnsignedString(num, 3);
  }

  private static String toUnsignedString(long num, int exp)
  {
    // Use an array large enough for a binary number.
    int radix = 1 << exp;
    long 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 String.valueOf(buffer, i, 64-i);
  }

  public String toString()
  {
    return toString(this.value);
  }

  public static String toString(long num)
  {
    // Use the Integer toString for efficiency if possible.
    if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)
      return Integer.toString((int) num);

    // Use an arrary large enough for "-9223372036854775808"; i.e. 11 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;

    do
      {
        buffer[--i] = (char) ((int) '0' + (num % 10));
        num /= 10;
      }
    while (num > 0);

    if (isNeg)
      buffer[--i] = '-';

    return String.valueOf(buffer, i, 20-i);
  }

  public static String toString(long num, int radix)
  {
    // 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;

    do
      {
        buffer[--i] = Character.forDigit((int) (num % radix), radix);
        num /= radix;
      }
    while (num > 0);

    if (isNeg)
      buffer[--i] = '-';

    return String.valueOf(buffer, i, 65-i);
  }

  public static Long valueOf(String str) throws NumberFormatException
  {
    return new Long(parseLong(str, 10));
  }

  public static Long valueOf(String str, int radix)
  				throws NumberFormatException
  {
    return new Long(parseLong(str, radix));
  }
}
