/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation

   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;

  private static final long serialVersionUID = 4290774380558885855L;

  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
  /** @throws ClassCastException */
  public int compareTo(Object o)
  {
    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 ((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 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
      {
        String val = System.getProperty(prop);
	if (val != null)    
	  return decode(val);
      }
    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 ((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));
  }
}
