/* 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;
import java.io.UnsupportedEncodingException;

/**
 * @author Per Bothner <bothner@cygnus.com>
 * @date September 4, 1998.  
 */
/* Written using "Java Class Libraries", 2nd edition, plus online
 * API docs for JDK 1.2 beta from http://www.javasoft.com.
 * Status:  Complete to 1.1, but see FIXMEs. Also see testsuite results.
 */

public final class String
{
  private Object data;
  private int boffset; // Note this is a byte offset - don't use in Java code!
  private int count;

  public String ()
  {
    init();
  }

  public String (String value)
  {
    data = value.data;
    boffset = value.boffset;
    count = value.count;
  }

  public String (StringBuffer buffer)
  {
    init (buffer.value, 0, buffer.count, true);
  }

  public String (char[] data)
  {
    init(data, 0, data.length, false);
  }

  public String (char[] data, int offset, int count)
  {
    init(data, offset, count, false);
  }

  public String (byte[] byteArray)
  {
    this (byteArray, 0, byteArray.length);
  }

  public String (byte[] byteArray, int offset, int count)
  {
    try
      {
	init (byteArray, offset, count,
	      System.getProperty("file.encoding", "8859_1"));
      }
    catch (UnsupportedEncodingException x1)
      {
	// Maybe the default encoding is bad.
	try
	  {
	    init (byteArray, offset, count, "8859_1");
	  }
	catch (UnsupportedEncodingException x2)
	  {
	    // We know this can't happen.
	  }
      }
  }

  public String (byte[] byteArray, String enc)
    throws UnsupportedEncodingException
  {
    this (byteArray, 0, byteArray.length, enc);
  }

  public String (byte[] byteArray, int offset, int count, String enc)
    throws UnsupportedEncodingException
  {
    init (byteArray, offset, count, enc);
  }

  public static String copyValueOf(char[] data)
  {
    return copyValueOf (data, 0, data.length);
  }

  public static String copyValueOf(char[] data, int offset, int count)
  {
    String r = new String ();
    r.init(data, offset, count, false);
    return r;
  }

  /** @deprecated */
  public String (byte[] ascii, int hibyte)
  {
    init(ascii, hibyte, 0, ascii.length);
  }

  /** @deprecated */
  public String (byte[] ascii, int hibyte, int offset, int count)
  {
    init(ascii, hibyte, offset, count);
  }

  public String toString ()
  {
    return this;
  }

  public native boolean equals (Object anObject);

  public native int hashCode ();

  public int length ()
  {
    return count;
  }

  public native char charAt (int index);

  public native void getChars (int srcBegin, int srcEnd,
			       char[] dst, int dstBegin);

  public byte[] getBytes ()
  {
    try
      {
	return getBytes (System.getProperty("file.encoding", "8859_1"));
      }
    catch (UnsupportedEncodingException x)
      {
	// This probably shouldn't happen, but could if file.encoding
	// is somehow changed to a value we don't understand.
	try
	  {
	    return getBytes ("8859_1");
	  }
	catch (UnsupportedEncodingException x2)
	  {
	    // This really shouldn't happen, because the 8859_1
	    // encoding should always be available.
	    throw new InternalError ("couldn't find 8859_1 encoder");
	  }
      }
  }

  public native byte[] getBytes (String enc)
    throws UnsupportedEncodingException;

  /** @deprecated */
  public native void getBytes (int srcBegin, int srcEnd,
				byte[] dst, int dstBegin);

  public native char[] toCharArray ();

  public native boolean equalsIgnoreCase (String anotherString);

  public native int compareTo (String anotherString);

  public native boolean regionMatches (int toffset,
				       String other, int ooffset, int len);

  public native boolean regionMatches (boolean ignoreCase, int toffset,
				       String other, int ooffset, int len);

  public boolean startsWith (String prefix)
  {
    return startsWith (prefix, 0);
  }

  public native boolean startsWith (String prefix, int toffset);

  public boolean endsWith (String suffix)
  {
    return regionMatches (this.count - suffix.count, suffix, 0, suffix.count);
  }

  // No such method specified in the doc, including JDK 1.2.
  // public boolean endsWith (String suffix, int toffset)
  // {
  //   return regionMatches (toffset, suffix, 0, suffix.count);
  // }

  // The Language Specification, and the JDK 1.2 API docs say that
  // index and lastIndex take an int, while the Class Libraries
  // say they take a char.  The former wins ...

  public int indexOf (int ch)
  {
    return indexOf (ch, 0);
  }

  public native int indexOf (int ch, int fromIndex);

  public int indexOf (String str)
  {
    return indexOf (str, 0);
  }

  public native int indexOf (String str, int fromIndex);

  public int lastIndexOf (int ch)
  {
    return lastIndexOf (ch, count - 1);
  }

  public native int lastIndexOf (int ch, int fromIndex);

  public int lastIndexOf (String str)
  {
    return lastIndexOf (str, count - str.count);
  }

  public int lastIndexOf (String str, int fromIndex)
  {
    if (fromIndex >= count)
      fromIndex = count - str.count;
    for (;; --fromIndex)
      {
	if (fromIndex < 0)
	  return -1;
	if (startsWith(str, fromIndex))
	  return fromIndex;
      }
  }

  public String substring (int beginIndex)
  {
    return substring (beginIndex, count);
  }

  public native String substring (int beginIndex, int endIndex);

  public native String concat (String str);

  public native String replace (char oldChar, char newChar);

  public native String toLowerCase ();

  public native String toUpperCase ();

  public native String trim ();

  public static String valueOf (Object obj)
  {
    return obj == null ? "null" : obj.toString();
  }

  public static String valueOf (char[] data)
  {
    return valueOf (data, 0, data.length);
  }

  public static native String valueOf (char[] data, int offset, int count);

  public static String valueOf (boolean b)
  {
    return b ? "true" : "false";
  }

  public static native String valueOf (char c);

  public static String valueOf (int i)
  {
    return Integer.toString(i);
  }

  public static String valueOf (long l)
  {
    return Long.toString(l);
  }

  public static String valueOf (float f)
  {
    return Float.toString(f);
  }

  public static String valueOf (double d)
  {
    return Double.toString(d);
  }

  public native String intern ();

  private native void init ();
  private native void init (char[] chars, int offset, int count,
			    boolean dont_copy);
  private native void init (byte[] chars, int hibyte, int offset, int count);
  private native void init (byte[] chars, int offset, int count, String enc)
    throws UnsupportedEncodingException;
  private native void unintern ();
  private static native void rehash ();
}
