/[classpath]/classpath/java/lang/String.java
ViewVC logotype

Diff of /classpath/java/lang/String.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.37 by mark, Fri Feb 15 12:08:15 2002 UTC revision 1.38 by ericb, Thu Mar 7 07:33:32 2002 UTC
# Line 1  Line 1 
1  /* java.lang.String  /* String.java -- immutable character sequences; the object of string literals
2     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 7  GNU Classpath is free software; you can Line 7  GNU Classpath is free software; you can
7  it under the terms of the GNU General Public License as published by  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2, or (at your option)  the Free Software Foundation; either version 2, or (at your option)
9  any later version.  any later version.
10    
11  GNU Classpath is distributed in the hope that it will be useful, but  GNU Classpath is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Line 41  package java.lang; Line 41  package java.lang;
41  import java.util.Comparator;  import java.util.Comparator;
42  import java.util.Hashtable;  import java.util.Hashtable;
43  import java.util.Locale;  import java.util.Locale;
44    import java.util.regex.Pattern;
45  import gnu.java.io.EncodingManager;  import gnu.java.io.EncodingManager;
46  import java.io.*;  import java.io.Serializable;
47    import java.io.UnsupportedEncodingException;
48    import java.io.CharConversionException;
49    
50  /**  /**
51   * Strings represent an immutable set of characters.   * Strings represent an immutable set of characters.  All String literals
52   * Compliant with JDK 1.1.   * are instances of this class, and two string literals with the same contents
53     * refer to the same String object.
54     *
55     * <p>This class also includes a number of methods for manipulating the
56     * contents of strings (of course, creating a new object if there are any
57     * changes, as String is immutable). Case mapping relies on Unicode 3.0.0
58     * standards, where some character sequences have a different number of
59     * characters in the uppercase version than the lower case.
60     *
61     * <p>Strings are special, in that they are the only object with an overloaded
62     * operator. When you use '+' with at least one String argument, both
63     * arguments have String conversion performed on them, and another String (not
64     * guaranteed to be unique) results.
65     *
66     * <p>String is special-cased when doing data serialization - rather than
67     * listing the fields of this class, a String object is converted to a string
68     * literal in the object stream.
69   *   *
70   * @author Paul N. Fisher   * @author Paul N. Fisher
71   * @author Eric Blake <ebb9@email.byu.edu>   * @author Eric Blake <ebb9@email.byu.edu>
72   * @since JDK1.0   * @since 1.0
73     * @status updated to 1.3, waiting on java.util.regex, and could use better
74     *    data sharing
75   */   */
76  public final class String implements Comparable, CharSequence, Serializable {  public final class String implements Serializable, Comparable, CharSequence
77    {
78      /**
79       * This is probably not necessary because this class is special cased already
80       * but it will avoid showing up as a discrepancy when comparing SUIDs.
81       */
82      private static final long serialVersionUID = -6849794470754667710L;
83    
84    /**    /**
85     * Holds the references for each intern()'d String.     * Holds the references for each intern()'d String.
86     * Once a String has been intern()'d it cannot be GC'd.     * Once a String has been intern()'d it cannot be GC'd.
87     *     *
88     * @XXX Replace with a weak reference structure for 1.2     * @XXX Replace with a weak reference structure for 1.2
89     */     */
90    private static Hashtable internTable = new Hashtable();    private static final Hashtable internTable = new Hashtable();
91    
92    /**    /**
93     * Characters which make up the String.     * Characters which make up the String.
94     * Package access is granted for use by StringBuffer.     * Package access is granted for use by StringBuffer.
95     */     */
96    char[] value;    final char[] value;
97    
98    /**    /**
99     * Holds the number of characters in str[].  This number is generally     * Holds the number of characters in str[].  This number is generally
# Line 73  public final class String implements Com Line 101  public final class String implements Com
101     * with this String, then len will be equal to StringBuffer.length().     * with this String, then len will be equal to StringBuffer.length().
102     * Package access is granted for use by StringBuffer.     * Package access is granted for use by StringBuffer.
103     */     */
104    int count;    final int count;
105    
106    /**    /**
107     * Holds the starting position for characters in str[].  Since     * Holds the starting position for characters in str[].  Since
108     * substring()'s are common, the use of `offset' allows the operation     * substring()'s are common, the use of offset allows the operation
109     * to perform in O(1).     * to perform in O(1). Package access is granted for use by StringBuffer.
110     *     *
111     * @FIXME The use of offset has not been implemented.     * @XXX The use of offset has not been implemented.
112     */     */
113    private int offset;    final int offset = 0;
114    
115    /**    /**
116     * Caches the result of hashCode().  If this value is zero, the hashcode     * Caches the result of hashCode().  If this value is zero, the hashcode
# Line 104  public final class String implements Com Line 132  public final class String implements Com
132      private static final long serialVersionUID = 8575799808933029326L;      private static final long serialVersionUID = 8575799808933029326L;
133    
134      /**      /**
135       * The default private constructor generates unnecessary overhead       * The default private constructor generates unnecessary overhead.
136       */       */
137      CaseInsensitiveComparator() {}      CaseInsensitiveComparator() {}
138    
139      /**      /**
140       * Compares to Strings, using       * Compares to Strings, using
141       * <code>String.compareToIgnoreCase(String)</code>.       * <code>String.compareToIgnoreCase(String)</code>.
142       *       *
143       * @param o1 the first string       * @param o1 the first string
144       * @param o2 the second string       * @param o2 the second string
145       * @return &lt; 0, 0, or &gt; 0 depending on the case-insensitive       * @return &lt; 0, 0, or &gt; 0 depending on the case-insensitive
# Line 124  public final class String implements Com Line 152  public final class String implements Com
152      {      {
153        return ((String) o1).compareToIgnoreCase((String) o2);        return ((String) o1).compareToIgnoreCase((String) o2);
154      }      }
155    }    } // class CaseInsensitiveComparator
156    
157    /**    /**
158     * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>.     * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>.
159     * This comparator is {@link Serializable}.     * This comparator is {@link Serializable}. Note that it ignores Locale,
160       * for that, you want a Collator.
161     *     *
162       * @see Collator#compare(String, String)
163     * @since 1.2     * @since 1.2
164     */     */
165    public static final Comparator CASE_INSENSITIVE_ORDER    public static final Comparator CASE_INSENSITIVE_ORDER
166      = new CaseInsensitiveComparator();      = new CaseInsensitiveComparator();
167    
168    /**    /**
169     * Creates an empty String (length 0)     * Creates an empty String (length 0). Unless you really need a new object,
170       * consider using <code>""</code> instead.
171     */     */
172    public String() {    public String() {
173      value = new char[0];      value = new char[0];
174        count = 0;
175    }    }
176    
177    /**    /**
178     * Copies the contents of a String to a new String.     * Copies the contents of a String to a new String. Since Strings are
179     * Since Strings are immutable, only a shallow copy is performed.     * immutable, only a shallow copy is performed.
180     *     *
181     * @param str String to copy     * @param str String to copy
182     *     * @throws NullPointerException if value is null
    * @exception NullPointerException if `value' is null  
183     */     */
184    public String(String str) throws NullPointerException {    public String(String str)
185      // since Strings are immutable, there's no reason to    {
186      //  make a deep copy of `value'      // Since Strings are immutable, don't copy value.
187      value = str.value;      value = str.value;
188      count = str.count;      count = str.count;
189    }    }
190    
191    /**    /**
192     * Creates a new String using the character sequence represented by     * Creates a new String using the character sequence of the char array.
193     * the StringBuffer.     * Subsequent changes to data do not affect the String.
    *  
    * @param value StringBuffer to copy  
    *  
    * @exception NullPointerException if `value' is null  
    */  
   public String(StringBuffer buf) throws NullPointerException {  
     count = buf.length();  
     value = new char[count];  
     buf.getChars(0, buf.length(), value, 0);  
   }  
     
   /**  
    * Creates a new String using the character sequence of the char  
    * array.  
194     *     *
195     * @param data char array to copy     * @param data char array to copy
196     *     * @throws NullPointerException if data is null
    * @exception NullPointerException if `data' is null  
197     */     */
198    public String(char[] data) throws NullPointerException {    public String(char[] data)
199      {
200      count = data.length;      count = data.length;
201      value = new char[count];      value = (char[]) data.clone();
     System.arraycopy(data, 0, value, 0, data.length);  
202    }    }
203    
204    /**    /**
205     * Creates a new String using the character sequence of the char     * Creates a new String using the character sequence of a subarray of
206     * array, starting at the offset, and copying chars up     * characters. The string starts at offset, and copies count chars.
207     * to the count.     * Subsequent changes to data do not affect the String.
208     *     *
209     * @param data char array to copy     * @param data char array to copy
210     * @param offset position (base 0) to start copying out of `data'     * @param offset position (base 0) to start copying out of data
211     * @param count the number of characters from `data' to copy     * @param count the number of characters from data to copy
212     *     * @throws NullPointerException if data is null
213     * @exception NullPointerException if `data' is null     * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
214     * @exception StringIndexOutOfBoundsException     *         || offset + count > data.length)
215     *   if (offset < 0 || count < 0 || offset+count > data.length)     *         (while unspecified, this is a StringIndexOutOfBoundsException)
216     */     */
217    public String(char[] data, int offset, int count)    public String(char[] data, int offset, int count)
218         throws NullPointerException, IndexOutOfBoundsException {    {
219      if (offset < 0 || count < 0 || offset+count > data.length)      if (offset < 0 || count < 0 || offset + count > data.length)
220        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
221      this.count = count;      this.count = count;
222      value = new char[count];      value = new char[count];
# Line 208  public final class String implements Com Line 224  public final class String implements Com
224    }    }
225    
226    /**    /**
227     * Creates a new String using the byte array.     * Creates a new String using an 8-bit array of integer values, starting at
228     *     * an offset, and copying up to the count. Each character c, using
229     * Uses the default encoding for the system to decode the byte array, or if     * corresponding byte b, is created in the new String as if by performing:
    * that doesn't work, uses 8859_1.  
230     *     *
231     * @param data byte array to copy     * <pre>
232       * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff))
233       * </pre>
234     *     *
235     * @exception NullPointerException if `data' is null     * @param ascii array of integer values
236       * @param hibyte top byte of each Unicode character
237       * @param offset position (base 0) to start copying out of ascii
238       * @param count the number of characters from ascii to copy
239       * @throws NullPointerException if ascii is null
240       * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
241       *         || offset + count > ascii.length)
242       *         (while unspecified, this is a StringIndexOutOfBoundsException)
243       * @see #String(byte[])
244       * @see #String(byte[], String)
245       * @see #String(byte[], int, int)
246       * @see #String(byte[], int, int, String)
247       * @deprecated use {@link #String(byte[], int, int, String)} to perform
248       *             correct encoding
249     */     */
250    public String(byte[] data) throws NullPointerException {    public String(byte[] ascii, int hibyte, int offset, int count)
251      try {    {
252        value = EncodingManager.getDecoder().convertToChars(data);      if (offset < 0 || count < 0 || offset + count > ascii.length)
253      } catch (CharConversionException cce) {        throw new StringIndexOutOfBoundsException();
254        try {      this.count = count;
255          value = EncodingManager.getDecoder("8859_1").convertToChars(data);      value = new char[count];
256        } catch (IOException ioe) {      for (int i = 0; i < count; i++)
257          throw new Error(ioe.toString());        value[i] = (char) (((hibyte & 0xff) << 8) | (ascii[i + offset] & 0xff));
       }  
     }  
     count = value.length;  
258    }    }
259    
260    /**    /**
261     * Creates a new String using the byte array.     * Creates a new String using an 8-bit array of integer values. Each
262       * character c, using corresponding byte b, is created in the new String
263       * as if by performing:
264     *     *
265     * Uses the specified encoding type to decode the byte array, or if     * <pre>
266     * that doesn't work, uses 8859_1.     * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff))
267       * </pre>
268     *     *
269     * @param data byte array to copy     * @param ascii array of integer values
270     * @param encoding the name of the encoding to use     * @param hibyte top byte of each Unicode character
271     * @exception NullPointerException if `data' is null.     * @throws NullPointerException if ascii is null
272     * @exception UnsupportedEncodingException if the specified encoding is not     * @see #String(byte[])
273     *            found.     * @see #String(byte[], String)
274     */     * @see #String(byte[], int, int)
275    public String(byte[] data, String encoding)     * @see #String(byte[], int, int, String)
276      throws NullPointerException, UnsupportedEncodingException {     * @see #String(byte[], int, int, int)
277      try {     * @deprecated use {@link #String(byte[], String)} to perform
278        value = EncodingManager.getDecoder(encoding).convertToChars(data);     *             correct encoding
279      } catch (CharConversionException cce) {     */
280        try {    public String(byte[] ascii, int hibyte)
281          value = EncodingManager.getDecoder("8859_1").convertToChars(data);    {
282        } catch (IOException ioe) {      this(ascii, hibyte, 0, ascii.length);
         throw new Error(ioe.toString());  
       }  
     }  
     count = value.length;  
283    }    }
284    
285    /**    /**
286     * Creates a new String using the portion of the byte array starting at the     * Creates a new String using the portion of the byte array starting at the
287     * offset and ending at offset+count.     * offset and ending at offset + count. Uses the specified encoding type
288     *     * to decode the byte array, so the resulting string may be longer or
289     * Uses the specified encoding type to decode the byte array, or if     * shorter than the byte array. For more decoding control, use
290     * that doesn't work, uses 8859_1.     * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
291       * see {@link java.nio.charset.Charset}. The behavior is not specified if
292       * the decoder encounters invalid characters; this implementation throws
293       * an Error.
294     *     *
295     * @param data byte array to copy     * @param data byte array to copy
296     * @param offset the offset to start at     * @param offset the offset to start at
297     * @param count the number of characters in the array to use     * @param count the number of characters in the array to use
298     * @param encoding the name of the encoding to use     * @param encoding the name of the encoding to use
299     * @exception NullPointerException if `data' is null.     * @throws NullPointerException if data or encoding is null
300     * @exception IndexOutOfBoundsException if the specified offset or count is     * @throws IndexOutOfBoundsException if offset or count is incorrect
301     *            incorrect.     * @throws UnsupportedEncodingException if encoding is not found
302     * @exception UnsupportedEncodingException if the specified encoding is not     * @throws Error if the decoding fails
303     *            found.     * @since 1.1
304     */     */
305    public String(byte[] data, int offset, int count, String encoding)    public String(byte[] data, int offset, int count, String encoding)
306      throws NullPointerException, IndexOutOfBoundsException,      throws UnsupportedEncodingException
307      UnsupportedEncodingException {    {
308      if (offset < 0 || count < 0 || offset+count > data.length)      // XXX Sun checks encoding for null, then checks negative bounds, then
309        // checks data for null, and finally searches for encoding.
310        if (offset < 0 || count < 0 || offset + count > data.length)
311        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
312      try {      try
313        value = EncodingManager.getDecoder(encoding).convertToChars(data, offset,        {
314                                                                  count);          value = EncodingManager.getDecoder(encoding)
315      } catch (CharConversionException cce) {            .convertToChars(data, offset, count);
       try {  
         value = EncodingManager.getDecoder("8859_1").convertToChars(data, offset,  
                                                                   count);  
       } catch (IOException ioe) {  
         throw new Error(ioe.toString());  
316        }        }
317      }      catch (CharConversionException cce)
318      this.count = value.length;        {
319    }          throw new Error(cce);
   
   public String(byte[] data, int offset, int count)  
     throws NullPointerException, IndexOutOfBoundsException {  
     if (offset < 0 || count < 0 || offset+count > data.length)  
       throw new StringIndexOutOfBoundsException();  
     try {  
       value = EncodingManager.getDecoder().convertToChars(data, offset, count);  
     } catch (CharConversionException cce) {  
       try {  
         value = EncodingManager.getDecoder("8859_1").convertToChars(data, offset,  
                                                                   count);  
       } catch (IOException ioe) {  
         throw new Error(ioe.toString());  
320        }        }
     }  
321      this.count = value.length;      this.count = value.length;
322    }    }
323    
324    /**    /**
325     * Creates a new String using an 8-bit array of integer values.     * Creates a new String using the byte array. Uses the specified encoding
326     * Each character `c', using corresponding byte `b', is created     * type to decode the byte array, so the resulting string may be longer or
327     * in the new String by performing:     * shorter than the byte array. For more decoding control, use
328     *     * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
329     * <pre>     * see {@link java.nio.charset.Charset}. The behavior is not specified if
330     * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff))     * the decoder encounters invalid characters; this implementation throws
331     * </pre>     * an Error.
332     *     *
333     * @param ascii array of integer values     * @param data byte array to copy
334     * @param hibyte top byte of each Unicode character     * @param encoding the name of the encoding to use
335     *     * @throws NullPointerException if data or encoding is null
336     * @exception NullPointerException if `ascii' is null     * @throws UnsupportedEncodingException if encoding is not found
337     *     * @throws Error if the decoding fails
338     * @deprecated Use constructors with byte to char decoders.     * @see #String(byte[], int, int, String)
339       * @since 1.1
340     */     */
341    public String(byte[] ascii, int hibyte) throws NullPointerException {    public String(byte[] data, String encoding)
342      count = ascii.length;      throws UnsupportedEncodingException
343      value = new char[count];    {
344      for (int i = 0; i < count; i++)      this(data, 0, data.length, encoding);
       value[i] = (char) (((hibyte & 0xff) << 8) | (ascii[i] & 0xff));  
345    }    }
346    
347    /**    /**
348     * Creates a new String using an 8-bit array of integer values,     * Creates a new String using the portion of the byte array starting at the
349     * starting at an offset, and copying up to the count.     * offset and ending at offset + count. Uses the encoding of the platform's
350     * Each character `c', using corresponding byte `b', is created     * default charset, so the resulting string may be longer or shorter than
351     * in the new String by performing:     * the byte array. For more decoding control, use
352     *     * {@link java.nio.charset.CharsetDecoder}.  The behavior is not specified
353     * <pre>     * if the decoder encounters invalid characters; this implementation throws
354     * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff))     * an Error.
    * </pre>  
    *  
    * @param ascii array of integer values  
    * @param hibyte top byte of each Unicode character  
    * @param offset position (base 0) to start copying out of `ascii'  
    * @param count the number of characters from `ascii' to copy  
    *  
    * @exception NullPointerException if `ascii' is null  
    * @exception StringIndexOutOfBoundsException  
    *   if (offset < 0 || count < 0 || offset+count > ascii.length)  
355     *     *
356     * @deprecated Use constructors with byte to char decoders.     * @param data byte array to copy
357       * @param offset the offset to start at
358       * @param count the number of characters in the array to use
359       * @throws NullPointerException if data is null
360       * @throws IndexOutOfBoundsException if offset or count is incorrect
361       * @throws Error if the decoding fails
362       * @see #String(byte[], int, int, String)
363       * @since 1.1
364     */     */
365    public String(byte[] ascii, int hibyte, int offset, int count)    public String(byte[] data, int offset, int count)
366         throws NullPointerException, IndexOutOfBoundsException {    {
367      if (offset < 0 || count < 0 || offset+count > ascii.length)      if (offset < 0 || count < 0 || offset + count > data.length)
368        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
369      this.count = count;      try
370      value = new char[count];        {
371      for (int i = 0; i < count; i++)          value = EncodingManager.getDecoder()
372        value[i] = (char) (((hibyte & 0xff) << 8) | (ascii[i+offset] & 0xff));            .convertToChars(data, offset, count);
373          }
374        catch (CharConversionException cce)
375          {
376            throw new Error(cce);
377          }
378        this.count = value.length;
379    }    }
380    
381    /**    /**
382     * Special constructor used by StringBuffer, which results     * Creates a new String using the byte array. Uses the encoding of the
383     * in a new String which shares memory with a StringBuffer.     * platform's default charset, so the resulting string may be longer or
384       * shorter than the byte array. For more decoding control, use
385       * {@link java.nio.charset.CharsetDecoder}.  The behavior is not specified
386       * if the decoder encounters invalid characters; this implementation throws
387       * an Error.
388     *     *
389     * @param data internal pointer to StringBuffer character data     * @param data byte array to copy
390     * @param length number of characters in `data' (data.length is the     * @throws NullPointerException if data is null
391     * capacity of the StringBuffer)     * @throws Error if the decoding fails
392     */     * @see #String(byte[], int, int)
393    String(char[] data, int length) {     * @see #String(byte[], int, int, String)
394      value = data;     * @since 1.1
     count = length;  
   }  
   
   /**  
    * Returns `this'.  
395     */     */
396    public String toString() {    public String(byte[] data)
397      return this;    {
398        this(data, 0, data.length);
399    }    }
400    
401    /**    /**
402     * Predicate which compares anObject to this.     * Creates a new String using the character sequence represented by
403       * the StringBuffer. Subsequent changes to buf do not affect the String.
404     *     *
405     * @return true if anObject is a String and contains the     * @param buf StringBuffer to copy
406     * same character sequence as this String, else false     * @throws NullPointerException if buf is null
407     */     */
408    public boolean equals(Object anObject) {    public String(StringBuffer buf)
409      if (anObject == null) return false;    {
410      if (!(anObject instanceof String)) return false;      // XXX Synchronize on buf.
411      String str2 = (String) anObject;      count = buf.length();
412      if (count != str2.count) return false;      value = new char[count];
413      for (int i = 0; i < count; i++)      buf.getChars(0, buf.length(), value, 0);
       if (value[i] != str2.value[i]) return false;  
     return true;  
414    }    }
415    
416    /**    /**
417     * Compares the given StringBuffer to this String.     * Special constructor used when data can safely be shared, rather than
418     *     * cloning it now (such as from StringBuffer).
    * @return true if the given StringBuffer has the same character  
    * sequence as this String, else false  
    * @exception NullPointerException if the given StringBuffer is null  
419     *     *
420     * @since 1.4     * @param data the characters, not modifiable by users, non-null
421       * @param length number of characters in data
422     */     */
423    public boolean contentEquals(StringBuffer buffer) {    String(char[] data, int length)
424      if (count != buffer.count) return false;    {
425      for (int i = 0; i < count; i++)      value = data;
426        if (value[i] != buffer.value[i]) return false;      count = length;
     return true;  
427    }    }
428    
429    /**    /**
    * Computes the hashcode for this String, according to JLS, Appendix D.  
    *  
    * @return hashcode value of this String  
    */  
   public int hashCode() {  
     if (cachedHashCode != 0) return cachedHashCode;  
   
     /* compute the hash code using a local variable such that we're  
        reentrant */  
     int hashCode = 0;  
     for (int i = 0; i < count; i++)  
       hashCode = hashCode * 31 + value[i];  
   
     cachedHashCode = hashCode;  
     return hashCode;  
   }  
     
   /**  
430     * Returns the number of characters contained in this String.     * Returns the number of characters contained in this String.
431     *     *
432     * @return the length of this String.     * @return the length of this String
433     */     */
434    public int length() {    public int length()
435      {
436      return count;      return count;
437    }    }
438    
439    /**    /**
440     * Returns the character located at the specified index within     * Returns the character located at the specified index within this String.
    * this String.  
441     *     *
442     * @param index position of character to return (base 0)     * @param index position of character to return (base 0)
443     *     * @return character located at position index
444     * @return character located at position `index'     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= length()
445     *     *         (while unspecified, this is a StringIndexOutOfBoundsException)
    * @exception StringIndexOutOfBoundsException  
    *   if (index < 0 || index >= this.length())  
446     */     */
447    public char charAt(int index) throws IndexOutOfBoundsException {    public char charAt(int index)
448      if (index < 0 || index >= count)    {
449        if (index < 0 || index >= count)
450        throw new StringIndexOutOfBoundsException(index);        throw new StringIndexOutOfBoundsException(index);
451      return value[index];      return value[index];
452    }    }
# Line 467  public final class String implements Com Line 459  public final class String implements Com
459     * @param srcBegin index to begin copying characters from this String     * @param srcBegin index to begin copying characters from this String
460     * @param srcEnd index after the last character to be copied from this String     * @param srcEnd index after the last character to be copied from this String
461     * @param dst character array which this String is copied into     * @param dst character array which this String is copied into
462     * @param dstBegin index to start writing characters into `dst'     * @param dstBegin index to start writing characters into dst
463     *     * @throws NullPointerException if dst is null
464     * @exception NullPointerException if `dst' is null     * @throws IndexOutOfBoundsException if any indices are out of bounds
465     * @exception StringIndexOutOfBoundsException     *         (while unspecified, this is a StringIndexOutOfBoundsException)
    * if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > this.length() ||  
    *     dstBegin < 0 || dstBegin+(srcEnd-srcBegin) > dst.length)  
466     */     */
467    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
468         throws NullPointerException, IndexOutOfBoundsException {    {
469      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count ||      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count
470          dstBegin < 0 || dstBegin+(srcEnd-srcBegin) > dst.length)          || dstBegin < 0 || dstBegin + srcEnd - srcBegin > dst.length)
471        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
472        // XXX System.arraycopy this.
473      for (int i = srcBegin; i < srcEnd; i++)      for (int i = srcBegin; i < srcEnd; i++)
474        dst[dstBegin + i - srcBegin] = value[i];        dst[dstBegin + i - srcBegin] = value[i];
475    }    }
476    
477    /**    /**
478     * Copies the low byte of each character from this String starting     * Copies the low byte of each character from this String starting at a
479     * at a specified start index, ending at a specified stop index, to     * specified start index, ending at a specified stop index, to a byte array
480     * a byte array starting at a specified destination begin index.     * starting at a specified destination begin index.
481     *     *
482     * @param srcBegin index to being copying characters from this String     * @param srcBegin index to being copying characters from this String
483     * @param srcEnd index after the last character to be copied from this String     * @param srcEnd index after the last character to be copied from this String
484     * @param dst byte array which each low byte of this String is copied into     * @param dst byte array which each low byte of this String is copied into
485     * @param dstBegin index to start writing characters into `dst'     * @param dstBegin index to start writing characters into dst
486     *     * @throws NullPointerException if dst is null
487     * @exception NullPointerException if `dst' is null     * @throws IndexOutOfBoundsException if any indices are out of bounds
488     * @exception StringIndexOutOfBoundsException     *         (while unspecified, this is a StringIndexOutOfBoundsException)
489     * if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > this.length() ||     * @see #getBytes()
490     *     dstBegin < 0 || dstBegin+(srcEnd-srcBegin) > dst.length)     * @see #getBytes(String)
491     *     * @deprecated use {@link #getBytes()}, which uses a char to byte encoder
    * @deprecated Use a getBytes() which uses a char to byte encoder.  
492     */     */
493    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)
494         throws NullPointerException, IndexOutOfBoundsException {    {
495      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count ||      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count ||
496          dstBegin < 0 || dstBegin+(srcEnd-srcBegin) > dst.length)          dstBegin < 0 || dstBegin + srcEnd - srcBegin > dst.length)
497        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
498      for (int i = srcBegin; i < srcEnd; i++)      for (int i = srcBegin; i < srcEnd; i++)
499        dst[dstBegin + i - srcBegin] = (byte) value[i];        dst[dstBegin + i - srcBegin] = (byte) value[i];
500    }    }
501    
502    /**    /**
503     * Converts the Unicode characters in this String to a byte stream     * Converts the Unicode characters in this String to a byte array. Uses the
504     * using a specified encoding method.     * specified encoding method, so the result may be longer or shorter than
505       * the String. For more encoding control, use
506       * {@link java.nio.charset.CharsetEncoder}, and for valid character sets,
507       * see {@link java.nio.charset.Charset}. The behavior is not specified if
508       * the encoder encounters a problem; this implementation returns null.
509     *     *
510     * @param enc encoding name     * @param enc encoding name
511       * @return the resulting byte array, or null on a problem
512       * @throws NullPointerException if enc is null
513       * @throws UnsupportedEncodingException if encoding is not supported
514       * @since 1.1
515       */
516      public byte[] getBytes(String enc) throws UnsupportedEncodingException
517      {
518        try
519          {
520            return EncodingManager.getEncoder(enc)
521              .convertToBytes(value, offset, count);
522          }
523        catch (CharConversionException e)
524          {
525            return null;
526          }
527      }
528    
529      /**
530       * Converts the Unicode characters in this String to a byte array. Uses the
531       * encoding of the platform's default charset, so the result may be longer
532       * or shorter than the String. For more encoding control, use
533       * {@link java.nio.charset.CharsetEncoder}.  The behavior is not specified if
534       * the encoder encounters a problem; this implementation returns null.
535     *     *
536     * @return byte array representing the characters in this String using     * @param enc encoding name
537     * enc encoding, or null if the encoding fails     * @return the resulting byte array, or null on a problem
538     *     * @throws NullPointerException if enc is null
539     * @exception UnsupportedEncodingException if encoding is not supported     * @throws UnsupportedEncodingException if encoding is not supported
540       * @since 1.1
541     */     */
542    public byte[] getBytes(String enc) throws UnsupportedEncodingException {    public byte[] getBytes()
543      try {    {
544        return EncodingManager.getEncoder(enc).convertToBytes(value, offset, count);      try
545      } catch (CharConversionException e) {        {
546        return null;          return EncodingManager.getEncoder()
547      }            .convertToBytes(value, offset, count);
548          }
549        catch (CharConversionException e)
550          {
551            return null;
552          }
553    }    }
554    
555    /**    /**
556     * Converts the Unicode characters in this String to a byte stream     * Predicate which compares anObject to this. This is true only for Strings
557     * using the system's default encoding method.     * with the same character sequence.
558     *     *
559     * @return byte array representing the characters in this String using     * @param anObject the object to compare
560     * the default encoding, or null if the encoding fails     * @return true if anObject is semantically equal to this
561       * @see #compareTo(String)
562       * @see #equalsIgnoreCase(String)
563     */     */
564    public byte[] getBytes() {    public boolean equals(Object anObject)
565      try {    {
566        return EncodingManager.getEncoder().convertToBytes(value, offset, count);      if (! (anObject instanceof String))
567      } catch (CharConversionException e) {        return false;
568        return null;      String str2 = (String) anObject;
569      }      if (count != str2.count)
570    }            return false;
571        for (int i = 0; i < count; i++)
572          if (value[i] != str2.value[i])
573            return false;
574        return true;
575      }
576    
577    /**    /**
578     * Copies the contents of this String into a character array.     * Compares the given StringBuffer to this String. This is true if the
579       * StringBuffer has the same content as this String at this moment.
580     *     *
581     * @return character array containing the same character sequence as     * @param buffer the StringBuffer to compare to
582     *   this String.     * @return true if StringBuffer has the same character sequence
583       * @throws NullPointerException if the given StringBuffer is null
584       * @since 1.4
585     */     */
586    public char[] toCharArray() {    public boolean contentEquals(StringBuffer buffer)
587      char[] copy = new char[count];    {
588      if (value.length != count)      // XXX Synchronize on buffer.
589        System.err.println("value.length=" + value.length + " count=" + count);      if (count != buffer.count)
590      System.arraycopy(value, 0, copy, 0, count);        return false;
591      return copy;      for (int i = 0; i < count; i++)
592          if (value[i] != buffer.value[i])
593            return false;
594        return true;
595    }    }
596    
597    /**    /**
598     * Compares a String to this String, ignoring case.     * Compares a String to this String, ignoring case. This does not handle
599       * multi-character capitalization exceptions; instead the comparison is
600       * made on a character-by-character basis, and is true if:<br><ul>
601       * <li><code>c1 == c2</code></li>
602       * <li><code>Character.toUpperCase(c1)
603       *     == Character.toUpperCase(c2)</code></li>
604       * <li><code>Character.toLowerCase(c1)
605       *     == Character.toLowerCase(c2)</code></li>
606       * </ul>
607     *     *
608     * @param anotherString String to compare to this String     * @param anotherString String to compare to this String
609     *     * @return true if anotherString is equal, ignoring case
610     * @return true if `anotherString' and this String have the same     * @see #equals(Object)
611     *   character sequence, ignoring case, else false.     * @see Character#toUpperCase(char)
612       * @see Character#toLowerCase(char)
613     */     */
614    public boolean equalsIgnoreCase(String anotherString) {    public boolean equalsIgnoreCase(String anotherString)
615      {
616      if (anotherString == null || count != anotherString.count)      if (anotherString == null || count != anotherString.count)
617        return false;        return false;
618      for (int i = 0; i < count; i++)      for (int i = 0; i < count; i++)
619        if (value[i] == anotherString.value[i] ||        // Note that checking c1 != c2 is redundant, but avoids method calls.
620  Character.toUpperCase(value[i]) == Character.toUpperCase(anotherString.value[i]) ||        if (value[i] != anotherString.value[i]
621  Character.toLowerCase(value[i]) == Character.toLowerCase(anotherString.value[i]))            && (Character.toUpperCase(value[i])
622          continue;                != Character.toUpperCase(anotherString.value[i]))
623        else            && (Character.toLowerCase(value[i])
624          return false;                != Character.toLowerCase(anotherString.value[i])))
625            return false;
626      return true;      return true;
627    }    }
628    
629    /**    /**
630     * Compares this String and another String (case sensitive).     * Compares this String and another String (case sensitive,
631     *     * lexicographically). The result is less than 0 if this string sorts
632     * @return returns an integer less than, equal to, or greater than     * before the other, 0 if they are equal, and greater than 0 otherwise.
633     *   zero, if this String is found, respectively, to be less than,     * After any common starting sequence is skipped, the result is
634     *   to match, or be greater than `anotherString'.     * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings
635       * have characters remaining, or
636       * <code>this.length() - anotherString.length()</code> if one string is
637       * a subsequence of the other.
638       *
639       * @param anotherString the String to compare against
640       * @return the comparison
641       * @throws NullPointerException if anotherString is null
642     */     */
643    public int compareTo(String anotherString) throws NullPointerException {    public int compareTo(String anotherString)
644      {
645      int min = Math.min(count, anotherString.count);      int min = Math.min(count, anotherString.count);
646      for (int i = 0; i < min; i++) {      for (int i = 0; i < min; i++)
647        int result = value[i]-anotherString.value[i];        {
648        if (result != 0)          int result = value[i] - anotherString.value[i];
649          return result;          if (result != 0)
650      }            return result;
651      return count-anotherString.count;        }
652        return count - anotherString.count;
653    }    }
654    
655    /**    /**
656     * Behaves like <code>compareTo(java.lang.String)</code> unless the Object     * Behaves like <code>compareTo(java.lang.String)</code> unless the Object
657     * is not a <code>String</code>.  Then it throws a     * is not a <code>String</code>.  Then it throws a
658     * <code>ClassCastException</code>.     * <code>ClassCastException</code>.
    * @exception ClassCastException if the argument is not a  
    * <code>String</code>.  
659     *     *
660       * @param anotherString the object to compare against
661       * @return the comparison
662       * @throws NullPointerException if anotherString is null
663       * @throws ClassCastException if the argument is not a <code>String</code>
664     * @since 1.2     * @since 1.2
665     */     */
666    public int compareTo(Object o)    public int compareTo(Object o)
667    {    {
668      return compareTo((String)o);      return compareTo((String) o);
669    }    }
670    
671    /**    /**
672     * Compares this String and another String (case insensitive).     * Compares this String and another String (case insensitive). This
673     *     * comparison is <em>different</em> from equalsIgnoreCase, in that it uses
674     * @return returns an integer less than, equal to, or greater than     * <code>this.toUpperCase().toLowerCase()
675     *   zero, if this String is found, respectively, to be less than,     *    .compareTo(s.toUpperCase().toLowerCase())</code>, which can perform
676     *   to match, or be greater than the given String.     * multi-character capitalization expansions. However, this is still
677       * unsatisfactory for certain locales, in which case you should use
678       * {@link java.text.Collator}.
679     *     *
680       * @param s the string to compare against
681       * @return the comparison
682       * @see Collator#compare(String, String)
683     * @since 1.2     * @since 1.2
684     */     */
685    public int compareToIgnoreCase(String s)    public int compareToIgnoreCase(String s)
686    {    {
687      int min = Math.min(count, s.count);      return toUpperCase().toLowerCase().compareTo(s.toUpperCase()
688      for (int i = 0; i < min; i++)                                                   .toLowerCase());
     {  
       char c1 = Character.toLowerCase(Character.toUpperCase(value[i]));  
       char c2 = Character.toLowerCase(Character.toUpperCase(s.value[i]));  
       int result = c1 - c2;  
       if (result != 0)  
         return result;  
     }  
     return count-s.count;  
689    }    }
690    
691    /**    /**
692     * Predicate which determines if this String matches another String     * Predicate which determines if this String matches another String
693     * starting at a specified offset for each String and continuing     * starting at a specified offset for each String and continuing
694     * for a specified length.     * for a specified length. Indices out of bounds are harmless, and give
695       * a false result.
696     *     *
697     * @param toffset index to start comparison at for this String     * @param toffset index to start comparison at for this String
698     * @param other String to compare region to this String     * @param other String to compare region to this String
699     * @param oofset index to start comparison at for `other'     * @param oofset index to start comparison at for other
700     * @param len number of characters to compare     * @param len number of characters to compare
701     *     * @return true if regions match (case sensitive)
702     * @return true if regions match (case sensitive), false otherwise.     * @throws NullPointerException if other is null
    *  
    * @exception NullPointerException if `other' is null  
703     */     */
704    public boolean regionMatches(int toffset, String other, int ooffset,    public boolean regionMatches(int toffset, String other, int ooffset, int len)
705                                 int len)    {
        throws NullPointerException {  
706      return regionMatches(false, toffset, other, ooffset, len);      return regionMatches(false, toffset, other, ooffset, len);
707    }    }
708    
709    /**    /**
710     * Predicate which determines if this String matches another String     * Predicate which determines if this String matches another String
711     * starting at a specified offset for each String and continuing for     * starting at a specified offset for each String and continuing
712     * a specified length, optionally ignoring case.     * for a specified length, optionally ignoring case. Indices out of bounds
713       * are harmless, and give a false result. Case comparisons are based on
714       * <code>Character.toLowerCase()</code> and
715       * <code>Character.toUpperCase()</code>, not on multi-character
716       * capitalization expansions.
717     *     *
718     * @param ignoreCase true if case should be ignored in comparision     * @param ignoreCase true if case should be ignored in comparision
719     * @param toffset index to start comparison at for this String     * @param toffset index to start comparison at for this String
720     * @param other String to compare region to this String     * @param other String to compare region to this String
721     * @param oofset index to start comparison at for `other'     * @param oofset index to start comparison at for other
722     * @param len number of characters to compare     * @param len number of characters to compare
723     *     * @return true if regions match, false otherwise
724     * @return true if regions match, false otherwise.     * @throws NullPointerException if other is null
    *  
    * @exception NullPointerException if `other' is null  
725     */     */
726    public boolean regionMatches(boolean ignoreCase, int toffset, String other,    public boolean regionMatches(boolean ignoreCase, int toffset,
727                                 int ooffset, int len)                                 String other, int ooffset, int len)
728         throws NullPointerException {    {
729      if (toffset < 0 || ooffset < 0 || toffset+len > count ||      if (toffset < 0 || ooffset < 0 || toffset + len > count ||
730          ooffset+len > other.count)          ooffset + len > other.count)
731        return false;        return false;
732      for (int i = 0; i < len; i++)      for (int i = 0; i < len; i++)
733        if (ignoreCase)        // Note that checking c1 != c2 is redundant when ignoreCase is true,
734          if (value[toffset+i] == other.value[ooffset+i] ||        // but it avoids method calls.
735              Character.toLowerCase(value[toffset+i]) ==        if (value[toffset + i] != other.value[ooffset + i]
736              Character.toLowerCase(other.value[ooffset+i]) ||            && (! ignoreCase
737              Character.toUpperCase(value[toffset+i]) ==                || ((Character.toLowerCase(value[toffset + i])
738              Character.toUpperCase(other.value[ooffset+i]))                     != Character.toLowerCase(other.value[ooffset + i]))
739            continue;                    && (Character.toUpperCase(value[toffset + i])
740          else                        != Character.toUpperCase(other.value[ooffset + i])))))
741            return false;          return false;
       else  
         if (value[toffset+i] != other.value[ooffset+i])  
           return false;  
742      return true;      return true;
743    }    }
744    
745    /**    /**
746     * Predicate which determines if this String starts with a given prefix.     * Predicate which determines if this String contains the given prefix,
747     * If the prefix is an empty String, true is returned.     * beginning comparison at toffset. The result is false if toffset is
748     *     * negative or greater than this.length(), otherwise it is the same as
749     * @param prefex String to compare     * <code>this.subString(toffset).startsWith(prefix)</code>.
750     *     *
751     * @return true if this String starts with the character sequence     * @param prefix String to compare
752     *   represented by `prefix', else false.     * @param toffset offset for this String where comparison starts
753     *     * @return true if this String starts with prefix
754     * @exception NullPointerException if `prefix' is null     * @throws NullPointerException if prefix is null
755       * @see #regionMatches(boolean, int, String, int, int)
756     */     */
757    public boolean startsWith(String prefix) throws NullPointerException {    public boolean startsWith(String prefix, int toffset)
758      return (prefix.count == 0) ? true :    {
759        regionMatches(0, prefix, 0, prefix.count);      if (toffset < 0 || toffset > count)
760          return false;
761        return prefix.count == 0
762          || regionMatches(toffset, prefix, 0, prefix.count);
763    }    }
764      
765    /**    /**
766     * Predicate which determines if this String starts with a given     * Predicate which determines if this String starts with a given prefix.
    * prefix, beginning comparison using offset of this String.  
767     * If the prefix is an empty String, true is returned.     * If the prefix is an empty String, true is returned.
768     *     *
769     * @param prefix String to compare     * @param prefex String to compare
770     * @param toffset offset for this String where comparison starts     * @return true if this String starts with the prefix
771     *     * @throws NullPointerException if prefix is null
772     * @return true if this String starts with the character sequence     * @see #startsWith(String, int)
    *   represented by prefix, else false.  
    *  
    * @exception NullPointerException if `prefix' is null  
773     */     */
774    public boolean startsWith(String prefix, int toffset)    public boolean startsWith(String prefix)
775         throws NullPointerException {    {
776      if (toffset < 0 || toffset > count) return false;      return prefix.count == 0
777      return (prefix.count == 0) ? true :        || regionMatches(0, prefix, 0, prefix.count);
       regionMatches(toffset, prefix, 0, prefix.count);  
778    }    }
779      
780    /**    /**
781     * Predicate which determines if this String ends with a given suffix.     * Predicate which determines if this String ends with a given suffix.
782     * If the suffix is an empty String, true is returned.     * If the suffix is an empty String, true is returned.
783     *     *
784     * @param suffix String to compare     * @param suffix String to compare
785       * @return true if this String ends with the suffix
786       * @throws NullPointerException if suffix is null
787       * @see #regionMatches(boolean, int, String, int, int)
788       */
789      public boolean endsWith(String suffix)
790      {
791        return suffix.count == 0
792          || regionMatches(count - suffix.count, suffix, 0, suffix.count);
793      }
794    
795      /**
796       * Computes the hashcode for this String. This is done with int arithmetic,
797       * where ** represents exponentiation, by this formula:<br>
798       * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>.
799     *     *
800     * @return true if this String ends with the character sequence     * @return hashcode value of this String
    *   represented by prefix, else false.  
    *  
    * @exception NullPointerException if `suffix' is null  
801     */     */
802    public boolean endsWith(String suffix) throws NullPointerException {    public int hashCode()
803      return (suffix.count == 0) ? true :    {
804        regionMatches(count-suffix.count, suffix, 0, suffix.count);      if (cachedHashCode != 0)
805          return cachedHashCode;
806    
807        // Compute the hash code using a local variable to be reentrant.
808        int hashCode = 0;
809        for (int i = 0; i < count; i++)
810          hashCode = hashCode * 31 + value[i];
811        return cachedHashCode = hashCode;
812    }    }
813      
814    /**    /**
815     * Finds the first instance of a character in this String.     * Finds the first instance of a character in this String.
816     *     *
817     * @param ch character to find     * @param ch character to find
    *  
818     * @return location (base 0) of the character, or -1 if not found     * @return location (base 0) of the character, or -1 if not found
819     */     */
820    public int indexOf(int ch) {    public int indexOf(int ch)
821      {
822      return indexOf(ch, 0);      return indexOf(ch, 0);
823    }    }
824    
# Line 760  Character.toLowerCase(value[i]) == Chara Line 830  Character.toLowerCase(value[i]) == Chara
830     *     *
831     * @param ch character to find     * @param ch character to find
832     * @param fromIndex index to start the search     * @param fromIndex index to start the search
    *  
833     * @return location (base 0) of the character, or -1 if not found     * @return location (base 0) of the character, or -1 if not found
834     */     */
835    public int indexOf(int ch, int fromIndex) {    public int indexOf(int ch, int fromIndex)
836      if (fromIndex < 0) fromIndex = 0;    {
837        if (fromIndex < 0)
838          fromIndex = 0;
839      for (int i = fromIndex; i < count; i++)      for (int i = fromIndex; i < count; i++)
840        if (value[i] == ch)        if (value[i] == ch)
841          return i;          return i;
842      return -1;      return -1;
843    }    }
844    
845    /**    /**
846     * Finds the first instance of a String in this String.     * Finds the last instance of a character in this String.
    *  
    * @param str String to find  
    *  
    * @return location (base 0) of the String, or -1 if not found  
847     *     *
848     * @exception NullPointerException if `str' is null     * @param ch character to find
849       * @return location (base 0) of the character, or -1 if not found
850     */     */
851    public int indexOf(String str) throws NullPointerException {    public int lastIndexOf(int ch)
852      return indexOf(str, 0);    {
853        return lastIndexOf(ch, count - 1);
854    }    }
855    
856    /**    /**
857     * Finds the first instance of a String in this String, starting at     * Finds the last instance of a character in this String, starting at
858     * a given index.  If starting index is less than 0, the search     * a given index.  If starting index is greater than the maximum valid
859     * starts at the beginning of this String.  If the starting index     * index, then the search begins at the end of this String.  If the
860     * is greater than the length of this String, -1 is returned.     * starting index is less than zero, -1 is returned.
861     *     *
862     * @param str String to find     * @param ch character to find
863     * @param fromIndex index to start the search     * @param fromIndex index to start the search
864     *     * @return location (base 0) of the character, or -1 if not found
    * @return location (base 0) of the String, or -1 if not found  
    *  
    * @exception NullPointerException if `str' is null  
865     */     */
866    public int indexOf(String str, int fromIndex) throws NullPointerException {    public int lastIndexOf(int ch, int fromIndex)
867      if (fromIndex < 0) fromIndex = 0;    {
868      for (int i = fromIndex; i <= count; i++)      if (fromIndex >= count)
869        if (regionMatches(i, str, 0, str.count))        fromIndex = count - 1;
870          return i;      for (int i = fromIndex; i >= 0; i--)
871          if (value[i] == ch)
872            return i;
873      return -1;      return -1;
874    }    }
875    
876    /**    /**
877     * Finds the last instance of a character in this String.     * Finds the first instance of a String in this String.
    *  
    * @param ch character to find  
878     *     *
879     * @return location (base 0) of the character, or -1 if not found     * @param str String to find
880       * @return location (base 0) of the String, or -1 if not found
881       * @throws NullPointerException if str is null
882     */     */
883    public int lastIndexOf(int ch) {    public int indexOf(String str)
884      return lastIndexOf(ch, count-1);    {
885        return indexOf(str, 0);
886    }    }
887    
888    /**    /**
889     * Finds the last instance of a character in this String, starting at     * Finds the first instance of a String in this String, starting at
890     * a given index.  If starting index is greater than the maximum valid     * a given index.  If starting index is less than 0, the search
891     * index, then the search begins at the end of this String.  If the     * starts at the beginning of this String.  If the starting index
892     * starting index is less than zero, -1 is returned.     * is greater than the length of this String, -1 is returned.
893     *     *
894     * @param ch character to find     * @param str String to find
895     * @param fromIndex index to start the search     * @param fromIndex index to start the search
896     *     * @return location (base 0) of the String, or -1 if not found
897     * @return location (base 0) of the character, or -1 if not found     * @throws NullPointerException if str is null
898     */     */
899    public int lastIndexOf(int ch, int fromIndex) {    public int indexOf(String str, int fromIndex)
900      if (fromIndex >= count)    {
901        fromIndex = count-1;      if (fromIndex < 0)
902      for (int i = fromIndex; i >= 0; i--)        fromIndex = 0;
903        if (value[i] == ch)      for (int i = fromIndex; i <= count; i++)
904          return i;        if (regionMatches(i, str, 0, str.count))
905            return i;
906      return -1;      return -1;
907    }    }
908    
# Line 840  Character.toLowerCase(value[i]) == Chara Line 910  Character.toLowerCase(value[i]) == Chara
910     * Finds the last instance of a String in this String.     * Finds the last instance of a String in this String.
911     *     *
912     * @param str String to find     * @param str String to find
    *  
913     * @return location (base 0) of the String, or -1 if not found     * @return location (base 0) of the String, or -1 if not found
914     *     * @throws NullPointerException if str is null
    * @exception NullPointerException if `str' is null  
915     */     */
916    public int lastIndexOf(String str) throws NullPointerException {    public int lastIndexOf(String str)
917      return lastIndexOf(str, count-str.count);    {
918        return lastIndexOf(str, count - str.count);
919    }    }
920    
921    /**    /**
922     * Finds the last instance of a String in this String, starting at     * Finds the last instance of a String in this String, starting at
923     * a given index.  If starting index is greater than the maximum valid     * a given index.  If starting index is greater than the maximum valid
924     * index, then the search begins at the end of this String.  If the     * index, then the search begins at the end of this String.  If the
925     * starting index is less than zero, -1 is returned.     * starting index is less than zero, -1 is returned.
926     *     *
927     * @param str String to find     * @param str String to find
928     * @param fromIndex index to start the search     * @param fromIndex index to start the search
    *  
929     * @return location (base 0) of the String, or -1 if not found     * @return location (base 0) of the String, or -1 if not found
930     *     * @throws NullPointerException if str is null
    * @exception NullPointerException if `str' is null  
931     */     */
932    public int lastIndexOf(String str, int fromIndex)    public int lastIndexOf(String str, int fromIndex)
933      throws NullPointerException {    {
934      if (fromIndex >= count)      if (fromIndex >= count)
935        fromIndex = count - str.count;        fromIndex = count - str.count;
936      for (int i = fromIndex; i >= 0; i--)      for (int i = fromIndex; i >= 0; i--)
937        if (regionMatches(i, str, 0, str.count))        if (regionMatches(i, str, 0, str.count))
938          return i;          return i;
939      return -1;      return -1;
940    }    }
941        
942    /**    /**
943     * Creates a substring of this String, starting at a specified index     * Creates a substring of this String, starting at a specified index
944     * and ending at the end of this String.     * and ending at the end of this String.
945     *     *
946     * @param beginIndex index to start substring (base 0)     * @param begin index to start substring (base 0)
    *  
947     * @return new String which is a substring of this String     * @return new String which is a substring of this String
948     *     * @throws IndexOutOfBoundsException if begin &lt; 0 || begin &gt; length()
949     * @exception StringIndexOutOfBoundsException     *         (while unspecified, this is a StringIndexOutOfBoundsException)
    *   if (beginIndex < 0 || beginIndex > this.length())  
950     */     */
951    public String substring(int beginIndex) throws IndexOutOfBoundsException {    public String substring(int begin)
952      return substring(beginIndex, count);    {
953        return substring(begin, count);
954    }    }
955        
956    /**    /**
957     * Creates a substring of this String, starting at a specified index     * Creates a substring of this String, starting at a specified index
958     * and ending at one character before a specified index.     * and ending at one character before a specified index.
959     *     *
960     * @param beginIndex index to start substring (base 0)     * @param begin index to start substring (inclusive, base 0)
961     * @param endIndex index after the last character to be     * @param end index to end at (exclusive)
    *   copied into the substring  
    *  
962     * @return new String which is a substring of this String     * @return new String which is a substring of this String
963     *     * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
964     * @exception StringIndexOutOfBoundsException     *         || begin > end (while unspecified, this is a
965     *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)     *         StringIndexOutOfBoundsException)
966     */     */
967    public String substring(int beginIndex, int endIndex)    public String substring(int beginIndex, int endIndex)
968         throws IndexOutOfBoundsException {    {
969      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
970        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
971      char[] newStr = new char[endIndex-beginIndex];      char[] newStr = new char[endIndex - beginIndex];
972      System.arraycopy(value, beginIndex, newStr, 0, endIndex-beginIndex);      System.arraycopy(value, beginIndex, newStr, 0, endIndex - beginIndex);
973      return new String(newStr);      return new String(newStr);
974    }    }
975    
976    /**    /**
977     * Creates a substring of this String, starting at a specified index     * Creates a substring of this String, starting at a specified index
978     * and ending at one character before a specified index.     * and ending at one character before a specified index. This behaves like
979     * <p>     * <code>substring(beginIndex, endIndex)</code>.
    * 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  
980     *     *
981     * @exception StringIndexOutOfBoundsException     * @param beginIndex index to start substring (inclusive, base 0)
982     *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)     * @param endIndex index to end at (exclusive)
983       * @return new String which is a substring of this String
984       * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
985       *         || begin > end
986       * @since 1.4
987     */     */
988    public CharSequence subSequence(int beginIndex, int endIndex)    public CharSequence subSequence(int beginIndex, int endIndex)
989         throws IndexOutOfBoundsException {    {
990      return substring(beginIndex, endIndex);      return substring(beginIndex, endIndex);
991    }    }
992    
993    /**    /**
994     * Concatenates a String to this String.     * Concatenates a String to this String. This results in a new string unless
995       * one of the two originals is "".
996     *     *
997     * @param str String to append to this String     * @param str String to append to this String
    *  
998     * @return newly concatenated String     * @return newly concatenated String
999     *     * @throws NullPointerException if str is null
    * @exception NullPointerException if `str' is null  
1000     */     */
1001    public String concat(String str) throws NullPointerException {    public String concat(String str)
1002      if (str.count == 0) return this;    {
1003        if (str.count == 0)
1004          return this;
1005      char[] newStr = new char[count + str.count];      char[] newStr = new char[count + str.count];
1006      System.arraycopy(this.value, 0, newStr, 0, count);      System.arraycopy(this.value, 0, newStr, 0, count);
1007      System.arraycopy(str.value, 0, newStr, count, str.count);      System.arraycopy(str.value, 0, newStr, count, str.count);
# Line 948  Character.toLowerCase(value[i]) == Chara Line 1009  Character.toLowerCase(value[i]) == Chara
1009    }    }
1010    
1011    /**    /**
1012     * Replaces every instances of a character in this String with     * Replaces every instance of a character in this String with a new
1013     * a new character.     * character. If no replacements occur, this is returned.
1014     *     *
1015     * @param oldChar the old character to replace     * @param oldChar the old character to replace
1016     * @param newChar the new character to put in place of the old character     * @param newChar the new character
1017     *     * @return new String with all instances of oldChar replaced with newChar
    * @return new String with all instances of `oldChar' replaced with `newChar'  
1018     */     */
1019    public String replace(char oldChar, char newChar) {    public String replace(char oldChar, char newChar)
1020      {
1021      int index = 0;      int index = 0;
1022      for (; index < count; index++)      for (; index < count; index++)
1023        if (value[index] == oldChar)        if (value[index] == oldChar)
1024          break;          break;
1025      if (index == count) return this;      if (index == count) return this;
1026      char[] newStr = new char[count];      char[] newStr = new char[count];
1027      System.arraycopy(value, 0, newStr, 0, count);      System.arraycopy(value, 0, newStr, 0, count);
1028      for (int i = index; i < count; i++)      for (int i = index; i < count; i++)
1029        if (value[i] == oldChar)        if (value[i] == oldChar)
1030          newStr[i] = newChar;          newStr[i] = newChar;
1031      return new String(newStr);      return new String(newStr);
1032    }    }
1033    
1034    /**    /**
1035     * Lowercases this String.     * Test if this String matches a regular expression. This is shorthand for
1036       * <code>{@link Pattern}.matches(regex, this)</code>.
1037       *
1038       * @param regex the pattern to match
1039       * @return true if the pattern matches
1040       * @throws NullPointerException if regex is null
1041       * @throws PatternSyntaxExceptions if regex is invalid
1042       * @since 1.4
1043       * @XXX Add this method.
1044      public boolean matches(String regex)
1045      {
1046        return Pattern.matches(regex, this);
1047      }
1048       */
1049    
1050      /**
1051       * Replaces the first substring match of the regular expression with a
1052       * given replacement. This is shorthand for <code>{@link Pattern}
1053       *   .compile(regex).matcher(this).replaceFirst(replacement)</code>.
1054       *
1055       * @param regex the pattern to match
1056       * @param replacement the replacement string
1057       * @return the modified string
1058       * @throws NullPointerException if regex or replacement is null
1059       * @throws PatternSyntaxExceptions if regex is invalid
1060       * @since 1.4
1061       * @XXX Add this method.
1062      public String replaceFirst(String regex, String replacement)
1063      {
1064        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
1065      }
1066       */
1067    
1068      /**
1069       * Replaces all matching substrings of the regular expression with a
1070       * given replacement. This is shorthand for <code>{@link Pattern}
1071       *   .compile(regex).matcher(this).replaceAll(replacement)</code>.
1072       *
1073       * @param regex the pattern to match
1074       * @param replacement the replacement string
1075       * @return the modified string
1076       * @throws NullPointerException if regex or replacement is null
1077       * @throws PatternSyntaxExceptions if regex is invalid
1078       * @since 1.4
1079       * @XXX Add this method.
1080      public String replaceAll(String regex, String replacement)
1081      {
1082        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
1083      }
1084       */
1085    
1086      /**
1087       * Split this string around the matches of a regular expression. Each
1088       * element of the returned array is the largest block of characters not
1089       * terminated by the regular expression, in the order the matches are found.
1090       *
1091       * <p>The limit affects the length of the array. If it is positive, the
1092       * array will contain at most n elements (n - 1 pattern matches). If
1093       * negative, the array length is unlimited, but there can be trailing empty
1094       * entries. if 0, the array length is unlimited, and trailing empty entries
1095       * are discarded.
1096       *
1097       * <p>For example, splitting "boo:and:foo" yields:<br>
1098       * <table border=0>
1099       * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th>
1100       * <tr><td>":"</td>   <td>2</td>  <td>{ "boo", "and:foo" }</td></tr>
1101       * <tr><td>":"</td>   <td>t</td>  <td>{ "boo", "and", "foo" }</td></tr>
1102       * <tr><td>":"</td>   <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr>
1103       * <tr><td>"o"</td>   <td>5</td>  <td>{ "b", "", ":and:f", "", "" }</td></tr>
1104       * <tr><td>"o"</td>   <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr>
1105       * <tr><td>"o"</td>   <td>0</td>  <td>{ "b", "", ":and:f" }</td></tr>
1106       * </table>
1107       *
1108       * <p>This is shorthand for
1109       * <code>{@link Pattern}.compile(regex).split(this, limit)</code>.
1110       *
1111       * @param regex the pattern to match
1112       * @param limit the limit threshold
1113       * @return the array of split strings
1114       * @throws NullPointerException if regex or replacement is null
1115       * @throws PatternSyntaxExceptions if regex is invalid
1116       * @since 1.4
1117       * @XXX Add this method.
1118      public String[] split(String regex, int limit)
1119      {
1120        return Pattern.compile(regex).split(this, limit);
1121      }
1122       */
1123    
1124      /**
1125       * Split this string around the matches of a regular expression. Each
1126       * element of the returned array is the largest block of characters not
1127       * terminated by the regular expression, in the order the matches are found.
1128       * The array length is unlimited, and trailing empty entries are discarded,
1129       * as though calling <code>split(regex, 0)</code>.
1130       *
1131       * @param regex the pattern to match
1132       * @return the array of split strings
1133       * @throws NullPointerException if regex or replacement is null
1134       * @throws PatternSyntaxExceptions if regex is invalid
1135       * @see #split(String, int)
1136       * @since 1.4
1137       * @XXX Add this method.
1138      public String[] split(String regex)
1139      {
1140        return Pattern.compile(regex).split(this, 0);
1141      }
1142       */
1143    
1144      /**
1145       * Lowercases this String according to a particular locale. This uses
1146       * Unicode's special case mappings, as applied to the given Locale, so the
1147       * resulting string may be a different length.
1148     *     *
1149     * @return new lowercased String,     * @param loc locale to use
1150     *   or `this' if no characters where lowercased     * @return new lowercased String, or this if no characters were lowercased
1151       * @see #toUpperCase(Locale)
1152       * @since 1.1
1153     */     */
1154    public String toLowerCase() {    public String toLowerCase(Locale loc)
1155      {
1156        // XXX Fix this to follow Unicode rules.
1157      char[] newStr = new char[count];      char[] newStr = new char[count];
1158      for (int i = 0; i < count; i++)      for (int i = 0; i < count; i++)
1159        newStr[i] = Character.toLowerCase(value[i]);        newStr[i] = Character.toLowerCase(value[i]);
1160      for (int i = 0; i < count; i++)      for (int i = 0; i < count; i++)
1161        if (value[i] != newStr[i])        if (value[i] != newStr[i])
1162          return new String(newStr);          return new String(newStr);
1163      return this;      return this;
1164    }    }
1165    
1166    /**    /**
1167     * Lowercases this String according to a particular locale.     * Lowercases this String. This uses Unicode's special case mappings, as
1168     * In general, this method has the same results as toLowerCase().     * applied to the platform's default Locale, so the resulting string may
1169     *     * be a different length.
    * @param loc locale to use  
1170     *     *
1171     * @return new lowercased String, or `this' if no characters were lowercased     * @return new lowercased String, or this if no characters where lowercased
1172       * @see #toLowerCase(Locale)
1173     */     */
1174    public String toLowerCase(Locale loc) {    public String toLowerCase()
1175      return toLowerCase();    {
1176        return toLowerCase(Locale.getDefault());
1177    }    }
1178    
1179    /**    /**
1180     * Uppercases this String.     * Uppercases this String according to a particular locale. This uses
1181       * Unicode's special case mappings, as applied to the given Locale, so the
1182       * resulting string may be a different length.
1183     *     *
1184     * @return new uppercased String, or `this' if no characters were uppercased     * @param loc locale to use
1185       * @return new uppercased String, or this if no characters were uppercased
1186       * @see #toLowerCase(Locale)
1187       * @since 1.1
1188     */     */
1189    public String toUpperCase() {    public String toUpperCase(Locale loc)
1190      {
1191        // XXX Fix this to follow Unicode rules.
1192      char[] newStr = new char[count];      char[] newStr = new char[count];
1193      for (int i = 0; i < count; i++)      for (int i = 0; i < count; i++)
1194        newStr[i] = Character.toUpperCase(value[i]);        newStr[i] = Character.toUpperCase(value[i]);
1195      for (int i = 0; i < count; i++)      for (int i = 0; i < count; i++)
1196        if (value[i] != newStr[i])        if (value[i] != newStr[i])
1197          return new String(newStr);          return new String(newStr);
1198      return this;      return this;
1199    }    }
1200    
1201    /**    /**
1202     * Uppercases this String according to a particular locale.     * Uppercases this String. This uses Unicode's special case mappings, as
1203     * In general, this method has the same results as toUpperCase().     * applied to the platform's default Locale, so the resulting string may
1204       * be a different length.
1205     *     *
1206     * @param loc locale to use     * @return new uppercased String, or this if no characters where uppercased
1207     *     * @see #toUpperCase(Locale)
    * @return new uppercased String, or `this' if no characters were uppercased  
1208     */     */
1209    public String toUpperCase(Locale loc) {    public String toUpperCase()
1210      return toUpperCase();    {
1211        return toUpperCase(Locale.getDefault());
1212    }    }
1213      
1214    /**    /**
1215     * Trims all ASCII control characters (includes whitespace) from     * Trims all characters less than or equal to ' ' (many ASCII control
1216     * the beginning and end of this String.     * characters, and all {@link Character#whitespace(char)}) from the
1217       * beginning and end of this String.
1218     *     *
1219     * @return new trimmed String, or `this' if the String was empty     * @return new trimmed String, or this if nothing trimmed
    *   or contained characters greater than '\u0020' at index zero,  
    *   and index this.length()-1.  
1220     */     */
1221    public String trim() {    public String trim()
1222      if (count == 0 || (value[0] > '\u0020' && value[count-1] > '\u0020'))    {
1223        if (count == 0 || (value[0] > '\u0020' && value[count - 1] > '\u0020'))
1224        return this;        return this;
1225      int begin = 0;      int begin = 0;
1226      for (;; begin++)      do
1227        {        {
1228          if (begin == count)          if (begin == count)
1229            return "";            return "";
         if (value[begin] > '\u0020')  
           break;  
1230        }        }
1231        while (value[begin++] <= '\u0020');
1232      int end = count;      int end = count;
1233      for (;;)      while (value[--end] <= '\u0020');
1234        if (value[--end] > '\u0020')  
         break;  
1235      return substring(begin, end + 1);      return substring(begin, end + 1);
1236    }    }
1237    
1238    /**    /**
1239     * Returns a String representation of an Object.     * Returns this, as it is already a String!
1240     *     *
1241     * @param obj the Object     * @return this
1242       */
1243      public String toString()
1244      {
1245        return this;
1246      }
1247    
1248      /**
1249       * Copies the contents of this String into a character array. Subsequent
1250       * changes to the array do not affect the String.
1251     *     *
1252     * @return "null" if `obj' is null, else `obj.toString()'     * @return character array copying the String
1253     */     */
1254    public static String valueOf(Object obj) {    public char[] toCharArray()
1255      return (obj == null) ? "null" : obj.toString();    {
1256        char[] copy = new char[count];
1257        System.arraycopy(value, 0, copy, 0, count);
1258        return copy;
1259    }    }
1260    
1261    /**    /**
1262     * Returns a String representation of a character array.     * Returns a String representation of an Object. This is "null" if the
1263       * object is null, otherwise it is <code>obj.toString()</code> (which
1264       * can be null).
1265     *     *
1266     * @param data the character array     * @param obj the Object
1267       * @return the string conversion of obj
1268       */
1269      public static String valueOf(Object obj)
1270      {
1271        return obj == null ? "null" : obj.toString();
1272      }
1273    
1274      /**
1275       * Returns a String representation of a character array. Subsequent
1276       * changes to the array do not affect the String.
1277     *     *
1278     * @return a String containing the same character sequence as `data'     * @param data the character array
1279       * @return a String containing the same character sequence as data
1280       * @throws NullPointerException if data is null
1281       * @see #valueOf(char[], int, int)
1282       * @see #String(char[])
1283     */     */
1284    public static String valueOf(char[] data) throws NullPointerException {    public static String valueOf(char[] data)
1285      return new String(data);    {
1286        return new String(data, 0, data.length);
1287    }    }
1288    
1289    /**    /**
1290     * Returns a String representing the character sequence of the char     * Returns a String representing the character sequence of the char array,
1291     * array, starting at the specified offset, and copying chars up     * starting at the specified offset, and copying chars up to the specified
1292     * to the specified count.     * count. Subsequent changes to the array do not affect the String.
1293     *     *
1294     * @param data character array     * @param data character array
1295     * @param offset position (base 0) to start copying out of `data'     * @param offset position (base 0) to start copying out of data
1296     * @param count the number of characters from `data' to copy     * @param count the number of characters from data to copy
1297     *     * @return String containing the chars from data[offset..offset+count]
1298     * @return String containing the chars from `data[offset..offset+count]'     * @throws NullPointerException if data is null
1299     *     * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
1300     * @exception StringIndexOutOfBoundsException     *         || offset + count > data.length)
1301     *   if (offset < 0 || count < 0 || offset+count > data.length)     *         (while unspecified, this is a StringIndexOutOfBoundsException)
1302       * @see #String(char[], int, int)
1303     */     */
1304    public static String valueOf(char[] data, int offset, int count)    public static String valueOf(char[] data, int offset, int count)
1305         throws NullPointerException, IndexOutOfBoundsException {    {
1306        return new String(data, offset, count);
1307      }
1308    
1309      /**
1310       * Returns a String representing the character sequence of the char array,
1311       * starting at the specified offset, and copying chars up to the specified
1312       * count. Subsequent changes to the array do not affect the String.
1313       *
1314       * @param data character array
1315       * @param offset position (base 0) to start copying out of data
1316       * @param count the number of characters from data to copy
1317       * @return String containing the chars from data[offset..offset+count]
1318       * @throws NullPointerException if data is null
1319       * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
1320       *         || offset + count > data.length)
1321       *         (while unspecified, this is a StringIndexOutOfBoundsException)
1322       * @see #String(char[], int, int)
1323       */
1324      public static String copyValueOf(char[] data, int offset, int count)
1325      {
1326      return new String(data, offset, count);      return new String(data, offset, count);
1327    }    }
1328    
1329    /**    /**
1330       * Returns a String representation of a character array. Subsequent
1331       * changes to the array do not affect the String.
1332       *
1333       * @param data the character array
1334       * @return a String containing the same character sequence as data
1335       * @throws NullPointerException if data is null
1336       * @see #copyValueOf(char[], int, int)
1337       * @see #String(char[])
1338       */
1339      public static String copyValueOf(char[] data)
1340      {
1341        return new String(data, 0, data.length);
1342      }
1343    
1344      /**
1345     * Returns a String representing a boolean.     * Returns a String representing a boolean.
1346     *     *
1347     * @param b the boolean     * @param b the boolean
1348     *     * @return "true" if b is true, else "false"
    * @return "true" if `b' is true, else "false"  
1349     */     */
1350    public static String valueOf(boolean b) {    public static String valueOf(boolean b)
1351      return (b) ? "true" : "false";    {
1352        return b ? "true" : "false";
1353    }    }
1354    
1355    /**    /**
1356     * Returns a String representing a character.     * Returns a String representing a character.
    *  
    * @param c the character  
1357     *     *
1358     * @return String containing the single character `c'.     * @param c the character
1359       * @return String containing the single character c
1360     */     */
1361    public static String valueOf(char c) {    public static String valueOf(char c)
1362      {
1363        // XXX Share this array.
1364      return new String(new char[] { c });      return new String(new char[] { c });
1365    }    }
1366    
# Line 1118  Character.toLowerCase(value[i]) == Chara Line 1368  Character.toLowerCase(value[i]) == Chara
1368     * Returns a String representing an integer.     * Returns a String representing an integer.
1369     *     *
1370     * @param i the integer     * @param i the integer
1371     *     * @return String containing the integer in base 10
1372     * @return Integer.toString(i)     * @see Integer#toString(int)
1373     */     */
1374    public static String valueOf(int i) {    public static String valueOf(int i)
1375      {
1376      // See Integer to understand why we call the two-arg variant.      // See Integer to understand why we call the two-arg variant.
1377      return Integer.toString(i, 10);      return Integer.toString(i, 10);
1378    }    }
# Line 1130  Character.toLowerCase(value[i]) == Chara Line 1381  Character.toLowerCase(value[i]) == Chara
1381     * Returns a String representing a long.     * Returns a String representing a long.
1382     *     *
1383     * @param i the long     * @param i the long
1384     *     * @return String containing the long in base 10
1385     * @return Long.toString(i)     * @see Long#toString(long)
1386     */     */
1387    public static String valueOf(long l) {    public static String valueOf(long l)
1388      {
1389      return Long.toString(l);      return Long.toString(l);
1390    }    }
1391    
# Line 1141  Character.toLowerCase(value[i]) == Chara Line 1393  Character.toLowerCase(value[i]) == Chara
1393     * Returns a String representing a float.     * Returns a String representing a float.
1394     *     *
1395     * @param i the float     * @param i the float
1396     *     * @return String containing the float
1397     * @return Float.toString(i)     * @see Float#toString(float)
1398     */     */
1399    public static String valueOf(float f) {    public static String valueOf(float f)
1400      {
1401      return Float.toString(f);      return Float.toString(f);
1402    }    }
1403    
# Line 1152  Character.toLowerCase(value[i]) == Chara Line 1405  Character.toLowerCase(value[i]) == Chara
1405     * Returns a String representing a double.     * Returns a String representing a double.
1406     *     *
1407     * @param i the double     * @param i the double
1408     *     * @return String containing the double
1409     * @return Double.toString(i)     * @see Double#toString(double)
1410     */     */
1411    public static String valueOf(double d) {    public static String valueOf(double d)
1412      {
1413      return Double.toString(d);      return Double.toString(d);
1414    }    }
1415    
1416    /**    /**
1417     * Fetches this String from the intern hashtable.     * Fetches this String from the intern hashtable. If two Strings are
1418     * If two Strings are considered equal, by the equals() method,     * considered equal, by the equals() method, then intern() will return the
1419     * then intern() will return the same String instance.     * same String instance. ie. if (s1.equals(s2)) then
1420     * ie. if (s1.equals(s2)) then (s1.intern() == s2.intern())     * (s1.intern() == s2.intern()). All string literals and string-valued
1421       * constant expressions are already interned.
1422     *     *
1423     * @return intern'd String     * @return intern'd String
1424     */     */
1425    public String intern() {    public String intern()
1426      {
1427        // XXX Synchronize access to the table, to avoid races.
1428      Object o = internTable.get(this);      Object o = internTable.get(this);
1429      if (o != null) return (String) o;      if (o != null)
1430          return (String) o;
1431      internTable.put(this, this);      internTable.put(this, this);
1432      return this;      return this;
1433    }    }
   
   /**  
    * Creates a string from the character array. The array is first copied.  
    *  
    * @param data the array of characters  
    *  
    * @return a String object that contains the characters of the character array  
    */  
     
   public static String copyValueOf(char[] data) {  
     char[] duplicate = (char[]) data.clone();  
     return new String(duplicate);  
   }  
   
   /**  
    * Creates a string from the specifed character subarray. The array is first copied.  
    *  
    * @param data the array of characters  
    * @param offset the array index indicating the start of the subarray  
    * @param count the number of characters to use for the subarray  
    *  
    * @return a String object that contains the characters of the character subarray  
    */  
     
   public static String copyValueOf(char[] data, int offset, int count) {  
     char[] duplicate = new char[count];  
     System.arraycopy(duplicate, 0, data, offset, count);  
     return new String(duplicate);  
   }  
1434  }  }

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26