| /* 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; |
| import java.io.UnsupportedEncodingException; |
| import java.io.Serializable; |
| import java.lang.Comparable; |
| import java.util.Comparator; |
| import java.util.Locale; |
| |
| /** |
| * @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.3. |
| */ |
| |
| public final class String implements Serializable, Comparable, CharSequence |
| { |
| private Object data; |
| private int boffset; // Note this is a byte offset - don't use in Java code! |
| private int count; |
| |
| // This is probably not necessary because this class is special cased already |
| // but it will avoid showing up as a discrepancy when comparing SUIDs. |
| private static final long serialVersionUID = -6849794470754667710L; |
| |
| /** |
| * An implementation for {@link CASE_INSENSITIVE_ORDER}. |
| * This must be {@link Serializable}. |
| */ |
| private static final class CaseInsensitiveComparator |
| implements Comparator, Serializable |
| { |
| /** |
| * The default private constructor generates unnecessary overhead |
| */ |
| CaseInsensitiveComparator() {} |
| |
| /** |
| * Compares two Strings, using |
| * <code>String.compareToIgnoreCase(String)</code>. |
| * |
| * @param o1 the first string |
| * @param o2 the second string |
| * @return < 0, 0, or > 0 depending on the case-insensitive |
| * comparison of the two strings. |
| * @throws NullPointerException if either argument is null |
| * @throws ClassCastException if either argument is not a String |
| * @see #compareToIgnoreCase(String) |
| */ |
| public int compare(Object o1, Object o2) |
| { |
| return ((String) o1).compareToIgnoreCase((String) o2); |
| } |
| } |
| |
| /** |
| * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>. |
| * This comparator is {@link Serializable}. |
| * |
| * @since 1.2 |
| */ |
| public static final Comparator CASE_INSENSITIVE_ORDER |
| = new CaseInsensitiveComparator(); |
| |
| public String () |
| { |
| init(); |
| } |
| |
| public String (String value) |
| { |
| data = value.data; |
| boffset = value.boffset; |
| count = value.count; |
| } |
| |
| public String (StringBuffer buffer) |
| { |
| synchronized (buffer) |
| { |
| buffer.shared = true; |
| init (buffer.value, 0, buffer.count, true); |
| } |
| } |
| |
| // This is used by gnu.gcj.runtime.StringBuffer, so it must have |
| // package-private protection. It is accessed via CNI and so avoids |
| // ordinary protection mechanisms. |
| String (gnu.gcj.runtime.StringBuffer buffer) |
| { |
| // No need to synchronize or mark the buffer, since we know it is |
| // only used once. |
| 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 int compareTo (Object obj) |
| { |
| return compareTo ((String)obj); |
| } |
| |
| public int compareToIgnoreCase (String str) |
| { |
| return this.toUpperCase().toLowerCase().compareTo( |
| str.toUpperCase().toLowerCase()); |
| } |
| |
| 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; |
| } |
| } |
| |
| /** |
| * Creates a substring of this String, starting at a specified index |
| * and ending at one character before a specified index. |
| * <p> |
| * To implement <code>CharSequence</code>. |
| * Calls <code>substring(beginIndex, endIndex)</code>. |
| * |
| * @param beginIndex index to start substring (base 0) |
| * @param endIndex index after the last character to be |
| * copied into the substring |
| * |
| * @return new String which is a substring of this String |
| * |
| * @exception StringIndexOutOfBoundsException |
| * if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex) |
| */ |
| public CharSequence subSequence(int beginIndex, int endIndex) |
| throws IndexOutOfBoundsException |
| { |
| return substring(beginIndex, endIndex); |
| } |
| |
| 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 (Locale locale); |
| public native String toUpperCase (Locale locale); |
| |
| public String toLowerCase () |
| { |
| // The JDK is a bit confused about what to do here. If we pass in |
| // the default Locale then special Locale handling might be |
| // invoked. However, the docs also say that Character.toLowerCase |
| // rules here. We go with the latter. |
| return toLowerCase (null); |
| } |
| |
| public String toUpperCase () |
| { |
| // The JDK is a bit confused about what to do here. If we pass in |
| // the default Locale then special Locale handling might be |
| // invoked. However, the docs also say that Character.toLowerCase |
| // rules here. We go with the latter. |
| return toUpperCase (null); |
| } |
| |
| 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 native String valueOf (int 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 static native void rehash (); |
| } |