/[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.38 by ericb, Thu Mar 7 07:33:32 2002 UTC revision 1.39 by ericb, Sat Mar 9 04:01:12 2002 UTC
# Line 38  exception statement from your version. * Line 38  exception statement from your version. *
38    
39  package java.lang;  package java.lang;
40    
41    import java.lang.ref.WeakReference;
42  import java.util.Comparator;  import java.util.Comparator;
43  import java.util.Hashtable;  import java.util.WeakHashMap;
44  import java.util.Locale;  import java.util.Locale;
45  import java.util.regex.Pattern;  import java.util.regex.Pattern;
 import gnu.java.io.EncodingManager;  
46  import java.io.Serializable;  import java.io.Serializable;
47  import java.io.UnsupportedEncodingException;  import java.io.UnsupportedEncodingException;
48  import java.io.CharConversionException;  import java.io.CharConversionException;
49    import gnu.java.io.EncodingManager;
50    import gnu.java.lang.CharData;
51    
52  /**  /**
53   * Strings represent an immutable set of characters.  All String literals   * Strings represent an immutable set of characters.  All String literals
# Line 70  import java.io.CharConversionException; Line 72  import java.io.CharConversionException;
72   * @author Paul N. Fisher   * @author Paul N. Fisher
73   * @author Eric Blake <ebb9@email.byu.edu>   * @author Eric Blake <ebb9@email.byu.edu>
74   * @since 1.0   * @since 1.0
75   * @status updated to 1.3, waiting on java.util.regex, and could use better   * @status updated to 1.4; but could use better data sharing via offset field
  *    data sharing  
76   */   */
77  public final class String implements Serializable, Comparable, CharSequence  public final class String implements Serializable, Comparable, CharSequence
78  {  {
# Line 82  public final class String implements Ser Line 83  public final class String implements Ser
83    private static final long serialVersionUID = -6849794470754667710L;    private static final long serialVersionUID = -6849794470754667710L;
84    
85    /**    /**
86     * Holds the references for each intern()'d String.     * Holds the references for each intern()'d String. If all references to
87     * Once a String has been intern()'d it cannot be GC'd.     * the string disappear, and the VM properly supports weak references,
88     *     * the String will be GC'd.
89     * @XXX Replace with a weak reference structure for 1.2     */
90      private static final WeakHashMap internTable = new WeakHashMap();
91    
92      /**
93       * Stores unicode multi-character uppercase expansion table.
94       * @see #toUpperCase(char)
95       * @see CharData#UPPER_EXPAND
96     */     */
97    private static final Hashtable internTable = new Hashtable();    private static final char[] upperExpand = CharData.UPPER_EXPAND.value;
98    
99      /**
100       * Stores unicode multi-character uppercase special casing table.
101       * @see #upperCaseExpansion(char)
102       * @see CharData#UPPER_SPECIAL
103       */
104      private static final char[] upperSpecial = CharData.UPPER_SPECIAL.value;
105    
106    /**    /**
107     * Characters which make up the String.     * Characters which make up the String.
# Line 186  public final class String implements Ser Line 200  public final class String implements Ser
200      // Since Strings are immutable, don't copy value.      // Since Strings are immutable, don't copy value.
201      value = str.value;      value = str.value;
202      count = str.count;      count = str.count;
203        cachedHashCode = str.cachedHashCode;
204    }    }
205    
206    /**    /**
# Line 253  public final class String implements Ser Line 268  public final class String implements Ser
268        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
269      this.count = count;      this.count = count;
270      value = new char[count];      value = new char[count];
271      for (int i = 0; i < count; i++)      hibyte <<= 8;
272        value[i] = (char) (((hibyte & 0xff) << 8) | (ascii[i + offset] & 0xff));      offset += count;
273        while (count > 0)
274          value[--count] = (char) (hibyte | (ascii[--offset] & 0xff));
275    }    }
276    
277    /**    /**
# Line 305  public final class String implements Ser Line 322  public final class String implements Ser
322    public String(byte[] data, int offset, int count, String encoding)    public String(byte[] data, int offset, int count, String encoding)
323      throws UnsupportedEncodingException      throws UnsupportedEncodingException
324    {    {
     // XXX Sun checks encoding for null, then checks negative bounds, then  
     // checks data for null, and finally searches for encoding.  
325      if (offset < 0 || count < 0 || offset + count > data.length)      if (offset < 0 || count < 0 || offset + count > data.length)
326        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
327      try      try
328        {        {
329            // XXX Consider using java.nio here.
330          value = EncodingManager.getDecoder(encoding)          value = EncodingManager.getDecoder(encoding)
331            .convertToChars(data, offset, count);            .convertToChars(data, offset, count);
332        }        }
# Line 368  public final class String implements Ser Line 384  public final class String implements Ser
384        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
385      try      try
386        {        {
387            // XXX Consider using java.nio here.
388          value = EncodingManager.getDecoder()          value = EncodingManager.getDecoder()
389            .convertToChars(data, offset, count);            .convertToChars(data, offset, count);
390        }        }
# Line 407  public final class String implements Ser Line 424  public final class String implements Ser
424     */     */
425    public String(StringBuffer buf)    public String(StringBuffer buf)
426    {    {
427      // XXX Synchronize on buf.      synchronized (buf)
428      count = buf.length();        {
429      value = new char[count];          count = buf.count;
430      buf.getChars(0, buf.length(), value, 0);          // Share unless buf is 3/4 empty.
431            if ((count << 2) < buf.value.length)
432              {
433                value = new char[count];
434                System.arraycopy(buf.value, 0, value, 0, count);
435              }
436            else
437              {
438                buf.shared = true;
439                value = buf.value;
440              }
441          }
442    }    }
443    
444    /**    /**
445     * Special constructor used when data can safely be shared, rather than     * Special constructor used when data can safely be shared, rather than
446     * cloning it now (such as from StringBuffer).     * cloning it.
447     *     *
448     * @param data the characters, not modifiable by users, non-null     * @param data the characters, not modifiable by users, non-null
449     * @param length number of characters in data     * @param length number of characters in data
# Line 462  public final class String implements Ser Line 490  public final class String implements Ser
490     * @param dstBegin index to start writing characters into dst     * @param dstBegin index to start writing characters into dst
491     * @throws NullPointerException if dst is null     * @throws NullPointerException if dst is null
492     * @throws IndexOutOfBoundsException if any indices are out of bounds     * @throws IndexOutOfBoundsException if any indices are out of bounds
493     *         (while unspecified, this is a StringIndexOutOfBoundsException)     *         (while unspecified, source problems cause a
494       *         StringIndexOutOfBoundsException, and dst problems cause an
495       *         ArrayIndexOutOfBoundsException)
496     */     */
497    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
498    {    {
499      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
         || dstBegin < 0 || dstBegin + srcEnd - srcBegin > dst.length)  
500        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
501      // XXX System.arraycopy this.      System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
     for (int i = srcBegin; i < srcEnd; i++)  
       dst[dstBegin + i - srcBegin] = value[i];  
502    }    }
503    
504    /**    /**
# Line 483  public final class String implements Ser Line 510  public final class String implements Ser
510     * @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
511     * @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
512     * @param dstBegin index to start writing characters into dst     * @param dstBegin index to start writing characters into dst
513     * @throws NullPointerException if dst is null     * @throws NullPointerException if dst is null and copy length is non-zero
514     * @throws IndexOutOfBoundsException if any indices are out of bounds     * @throws IndexOutOfBoundsException if any indices are out of bounds
515     *         (while unspecified, this is a StringIndexOutOfBoundsException)     *         (while unspecified, source problems cause a
516       *         StringIndexOutOfBoundsException, and dst problems cause an
517       *         ArrayIndexOutOfBoundsException)
518     * @see #getBytes()     * @see #getBytes()
519     * @see #getBytes(String)     * @see #getBytes(String)
520     * @deprecated use {@link #getBytes()}, which uses a char to byte encoder     * @deprecated use {@link #getBytes()}, which uses a char to byte encoder
521     */     */
522    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)
523    {    {
524      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count ||      if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
         dstBegin < 0 || dstBegin + srcEnd - srcBegin > dst.length)  
525        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
526      for (int i = srcBegin; i < srcEnd; i++)      dstBegin -= srcBegin;
527        dst[dstBegin + i - srcBegin] = (byte) value[i];      while (srcBegin < srcEnd)
528          dst[dstBegin++] = (byte) value[srcBegin++];
529    }    }
530    
531    /**    /**
# Line 517  public final class String implements Ser Line 546  public final class String implements Ser
546    {    {
547      try      try
548        {        {
549            // XXX Consider using java.nio here.
550          return EncodingManager.getEncoder(enc)          return EncodingManager.getEncoder(enc)
551            .convertToBytes(value, offset, count);            .convertToBytes(value, offset, count);
552        }        }
# Line 533  public final class String implements Ser Line 563  public final class String implements Ser
563     * {@link java.nio.charset.CharsetEncoder}.  The behavior is not specified if     * {@link java.nio.charset.CharsetEncoder}.  The behavior is not specified if
564     * the encoder encounters a problem; this implementation returns null.     * the encoder encounters a problem; this implementation returns null.
565     *     *
    * @param enc encoding name  
566     * @return the resulting byte array, or null on a problem     * @return the resulting byte array, or null on a problem
    * @throws NullPointerException if enc is null  
    * @throws UnsupportedEncodingException if encoding is not supported  
567     * @since 1.1     * @since 1.1
568     */     */
569    public byte[] getBytes()    public byte[] getBytes()
570    {    {
571      try      try
572        {        {
573            // XXX Consider using java.nio here.
574          return EncodingManager.getEncoder()          return EncodingManager.getEncoder()
575            .convertToBytes(value, offset, count);            .convertToBytes(value, offset, count);
576        }        }
# Line 568  public final class String implements Ser Line 596  public final class String implements Ser
596      String str2 = (String) anObject;      String str2 = (String) anObject;
597      if (count != str2.count)      if (count != str2.count)
598        return false;        return false;
599      for (int i = 0; i < count; i++)      if (value == str2.value)
600          return true;
601        int i = count;
602        while (--i >= 0)
603        if (value[i] != str2.value[i])        if (value[i] != str2.value[i])
604          return false;          return false;
605      return true;      return true;
# Line 585  public final class String implements Ser Line 616  public final class String implements Ser
616     */     */
617    public boolean contentEquals(StringBuffer buffer)    public boolean contentEquals(StringBuffer buffer)
618    {    {
619      // XXX Synchronize on buffer.      synchronized (buffer)
620      if (count != buffer.count)        {
621        return false;          if (count != buffer.count)
622      for (int i = 0; i < count; i++)            return false;
623        if (value[i] != buffer.value[i])          if (value == buffer.value)
624          return false;            return true; // Possible if shared.
625      return true;          int i = count;
626            while (--i >= 0)
627              if (value[i] != buffer.value[i])
628                return false;
629            return true;
630          }
631    }    }
632    
633    /**    /**
# Line 615  public final class String implements Ser Line 651  public final class String implements Ser
651    {    {
652      if (anotherString == null || count != anotherString.count)      if (anotherString == null || count != anotherString.count)
653        return false;        return false;
654      for (int i = 0; i < count; i++)      int i = count;
655        // Note that checking c1 != c2 is redundant, but avoids method calls.      while (--i >= 0)
656        if (value[i] != anotherString.value[i]        {
657            && (Character.toUpperCase(value[i])          char c1 = value[i];
658                != Character.toUpperCase(anotherString.value[i]))          char c2 = anotherString.value[i];
659            && (Character.toLowerCase(value[i])          // Note that checking c1 != c2 is redundant, but avoids method calls.
660                != Character.toLowerCase(anotherString.value[i])))          if (c1 != c2
661          return false;              && Character.toUpperCase(c1) != Character.toUpperCase(c2)
662                && Character.toLowerCase(c1) != Character.toLowerCase(c2))
663              return false;
664          }
665      return true;      return true;
666    }    }
667    
# Line 642  public final class String implements Ser Line 681  public final class String implements Ser
681     */     */
682    public int compareTo(String anotherString)    public int compareTo(String anotherString)
683    {    {
684      int min = Math.min(count, anotherString.count);      int i = Math.min(count, anotherString.count);
685      for (int i = 0; i < min; i++)      while (--i >= 0)
686        {        {
687          int result = value[i] - anotherString.value[i];          int result = value[i] - anotherString.value[i];
688          if (result != 0)          if (result != 0)
# Line 729  public final class String implements Ser Line 768  public final class String implements Ser
768      if (toffset < 0 || ooffset < 0 || toffset + len > count ||      if (toffset < 0 || ooffset < 0 || toffset + len > count ||
769          ooffset + len > other.count)          ooffset + len > other.count)
770        return false;        return false;
771      for (int i = 0; i < len; i++)      while (--len >= 0)
772        // Note that checking c1 != c2 is redundant when ignoreCase is true,        {
773        // but it avoids method calls.          char c1 = value[toffset++];
774        if (value[toffset + i] != other.value[ooffset + i]          char c2 = value[ooffset++];
775            && (! ignoreCase          // Note that checking c1 != c2 is redundant when ignoreCase is true,
776                || ((Character.toLowerCase(value[toffset + i])          // but it avoids method calls.
777                     != Character.toLowerCase(other.value[ooffset + i]))          if (c1 != c2
778                    && (Character.toUpperCase(value[toffset + i])              && (! ignoreCase
779                        != Character.toUpperCase(other.value[ooffset + i])))))                  || (Character.toLowerCase(c1) != Character.toLowerCase(c2)
780          return false;                      && (Character.toUpperCase(c1)
781                            != Character.toUpperCase(c2)))))
782              return false;
783          }
784      return true;      return true;
785    }    }
786    
# Line 756  public final class String implements Ser Line 798  public final class String implements Ser
798     */     */
799    public boolean startsWith(String prefix, int toffset)    public boolean startsWith(String prefix, int toffset)
800    {    {
801      if (toffset < 0 || toffset > count)      return regionMatches(false, toffset, prefix, 0, prefix.count);
       return false;  
     return prefix.count == 0  
       || regionMatches(toffset, prefix, 0, prefix.count);  
802    }    }
803    
804    /**    /**
# Line 773  public final class String implements Ser Line 812  public final class String implements Ser
812     */     */
813    public boolean startsWith(String prefix)    public boolean startsWith(String prefix)
814    {    {
815      return prefix.count == 0      return regionMatches(false, 0, prefix, 0, prefix.count);
       || regionMatches(0, prefix, 0, prefix.count);  
816    }    }
817    
818    /**    /**
# Line 788  public final class String implements Ser Line 826  public final class String implements Ser
826     */     */
827    public boolean endsWith(String suffix)    public boolean endsWith(String suffix)
828    {    {
829      return suffix.count == 0      return regionMatches(false, count - suffix.count, suffix, 0, suffix.count);
       || regionMatches(count - suffix.count, suffix, 0, suffix.count);  
830    }    }
831    
832    /**    /**
# Line 836  public final class String implements Ser Line 873  public final class String implements Ser
873    {    {
874      if (fromIndex < 0)      if (fromIndex < 0)
875        fromIndex = 0;        fromIndex = 0;
876      for (int i = fromIndex; i < count; i++)      for ( ; fromIndex < count; fromIndex++)
877        if (value[i] == ch)        if (value[fromIndex] == ch)
878          return i;          return fromIndex;
879      return -1;      return -1;
880    }    }
881    
# Line 867  public final class String implements Ser Line 904  public final class String implements Ser
904    {    {
905      if (fromIndex >= count)      if (fromIndex >= count)
906        fromIndex = count - 1;        fromIndex = count - 1;
907      for (int i = fromIndex; i >= 0; i--)      for ( ; fromIndex >= 0; fromIndex--)
908        if (value[i] == ch)        if (value[fromIndex] == ch)
909          return i;          return fromIndex;
910      return -1;      return -1;
911    }    }
912    
# Line 900  public final class String implements Ser Line 937  public final class String implements Ser
937    {    {
938      if (fromIndex < 0)      if (fromIndex < 0)
939        fromIndex = 0;        fromIndex = 0;
940      for (int i = fromIndex; i <= count; i++)      int limit = count - str.count;
941        if (regionMatches(i, str, 0, str.count))      for ( ; fromIndex <= limit; fromIndex++)
942          return i;        if (regionMatches(fromIndex, str, 0, str.count))
943            return fromIndex;
944      return -1;      return -1;
945    }    }
946    
# Line 931  public final class String implements Ser Line 969  public final class String implements Ser
969     */     */
970    public int lastIndexOf(String str, int fromIndex)    public int lastIndexOf(String str, int fromIndex)
971    {    {
972      if (fromIndex >= count)      fromIndex = Math.min(fromIndex, count - str.count);
973        fromIndex = count - str.count;      for ( ; fromIndex >= 0; fromIndex--)
974      for (int i = fromIndex; i >= 0; i--)        if (regionMatches(fromIndex, str, 0, str.count))
975        if (regionMatches(i, str, 0, str.count))          return fromIndex;
         return i;  
976      return -1;      return -1;
977    }    }
978    
# Line 968  public final class String implements Ser Line 1005  public final class String implements Ser
1005    {    {
1006      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
1007        throw new StringIndexOutOfBoundsException();        throw new StringIndexOutOfBoundsException();
1008      char[] newStr = new char[endIndex - beginIndex];      if (beginIndex == 0)
1009      System.arraycopy(value, beginIndex, newStr, 0, endIndex - beginIndex);        // Package constructor avoids an array copy.
1010      return new String(newStr);        return endIndex == count ? this : new String(value, endIndex);
1011        int len = endIndex - beginIndex;
1012        char[] newStr = new char[len];
1013        System.arraycopy(value, beginIndex, newStr, 0, len);
1014        // Package constructor avoids an array copy.
1015        return new String(newStr, len);
1016    }    }
1017    
1018    /**    /**
# Line 1002  public final class String implements Ser Line 1044  public final class String implements Ser
1044    {    {
1045      if (str.count == 0)      if (str.count == 0)
1046        return this;        return this;
1047        if (count == 0)
1048          return str;
1049      char[] newStr = new char[count + str.count];      char[] newStr = new char[count + str.count];
1050      System.arraycopy(this.value, 0, newStr, 0, count);      System.arraycopy(value, 0, newStr, 0, count);
1051      System.arraycopy(str.value, 0, newStr, count, str.count);      System.arraycopy(str.value, 0, newStr, count, str.count);
1052      return new String(newStr);      // Package constructor avoids an array copy.
1053        return new String(newStr, newStr.length);
1054    }    }
1055    
1056    /**    /**
# Line 1018  public final class String implements Ser Line 1063  public final class String implements Ser
1063     */     */
1064    public String replace(char oldChar, char newChar)    public String replace(char oldChar, char newChar)
1065    {    {
1066      int index = 0;      if (oldChar == newChar)
1067      for (; index < count; index++)        return this;
1068        int index = count;
1069        while (--index >= 0)
1070        if (value[index] == oldChar)        if (value[index] == oldChar)
1071          break;          break;
1072      if (index == count) return this;      if (index < 0)
1073      char[] newStr = new char[count];        return this;
1074      System.arraycopy(value, 0, newStr, 0, count);      char[] newStr = (char[]) value.clone();
1075      for (int i = index; i < count; i++)      do
1076        if (value[i] == oldChar)        if (value[index] == oldChar)
1077          newStr[i] = newChar;          value[index] = newChar;
1078      return new String(newStr);      while (--index >= 0);
1079        // Package constructor avoids an array copy.
1080        return new String(newStr, count);
1081    }    }
1082    
1083    /**    /**
# Line 1039  public final class String implements Ser Line 1088  public final class String implements Ser
1088     * @return true if the pattern matches     * @return true if the pattern matches
1089     * @throws NullPointerException if regex is null     * @throws NullPointerException if regex is null
1090     * @throws PatternSyntaxExceptions if regex is invalid     * @throws PatternSyntaxExceptions if regex is invalid
1091       * @see Pattern#matches(String, CharSequence)
1092     * @since 1.4     * @since 1.4
1093     * @XXX Add this method.     */
1094    public boolean matches(String regex)    public boolean matches(String regex)
1095    {    {
1096      return Pattern.matches(regex, this);      return Pattern.matches(regex, this);
1097    }    }
    */  
1098    
1099    /**    /**
1100     * Replaces the first substring match of the regular expression with a     * Replaces the first substring match of the regular expression with a
# Line 1057  public final class String implements Ser Line 1106  public final class String implements Ser
1106     * @return the modified string     * @return the modified string
1107     * @throws NullPointerException if regex or replacement is null     * @throws NullPointerException if regex or replacement is null
1108     * @throws PatternSyntaxExceptions if regex is invalid     * @throws PatternSyntaxExceptions if regex is invalid
1109       * @see #replaceAll(String, String)
1110       * @see Pattern#compile(String)
1111       * @see Pattern#matcher(CharSequence)
1112       * @see Matcher#replaceFirst(String)
1113     * @since 1.4     * @since 1.4
1114     * @XXX Add this method.     */
1115    public String replaceFirst(String regex, String replacement)    public String replaceFirst(String regex, String replacement)
1116    {    {
1117      return Pattern.compile(regex).matcher(this).replaceFirst(replacement);      return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
1118    }    }
    */  
1119    
1120    /**    /**
1121     * Replaces all matching substrings of the regular expression with a     * Replaces all matching substrings of the regular expression with a
# Line 1075  public final class String implements Ser Line 1127  public final class String implements Ser
1127     * @return the modified string     * @return the modified string
1128     * @throws NullPointerException if regex or replacement is null     * @throws NullPointerException if regex or replacement is null
1129     * @throws PatternSyntaxExceptions if regex is invalid     * @throws PatternSyntaxExceptions if regex is invalid
1130       * @see #replaceFirst(String, String)
1131       * @see Pattern#compile(String)
1132       * @see Pattern#matcher(CharSequence)
1133       * @see Matcher#replaceAll(String)
1134     * @since 1.4     * @since 1.4
1135     * @XXX Add this method.     */
1136    public String replaceAll(String regex, String replacement)    public String replaceAll(String regex, String replacement)
1137    {    {
1138      return Pattern.compile(regex).matcher(this).replaceFirst(replacement);      return Pattern.compile(regex).matcher(this).replaceAll(replacement);
1139    }    }
    */  
1140    
1141    /**    /**
1142     * Split this string around the matches of a regular expression. Each     * Split this string around the matches of a regular expression. Each
# Line 1113  public final class String implements Ser Line 1168  public final class String implements Ser
1168     * @return the array of split strings     * @return the array of split strings
1169     * @throws NullPointerException if regex or replacement is null     * @throws NullPointerException if regex or replacement is null
1170     * @throws PatternSyntaxExceptions if regex is invalid     * @throws PatternSyntaxExceptions if regex is invalid
1171       * @see Pattern#compile(String)
1172       * @see Pattern#split(CharSequence, int)
1173     * @since 1.4     * @since 1.4
1174     * @XXX Add this method.     */
1175    public String[] split(String regex, int limit)    public String[] split(String regex, int limit)
1176    {    {
1177      return Pattern.compile(regex).split(this, limit);      return Pattern.compile(regex).split(this, limit);
1178    }    }
    */  
1179    
1180    /**    /**
1181     * Split this string around the matches of a regular expression. Each     * Split this string around the matches of a regular expression. Each
# Line 1133  public final class String implements Ser Line 1189  public final class String implements Ser
1189     * @throws NullPointerException if regex or replacement is null     * @throws NullPointerException if regex or replacement is null
1190     * @throws PatternSyntaxExceptions if regex is invalid     * @throws PatternSyntaxExceptions if regex is invalid
1191     * @see #split(String, int)     * @see #split(String, int)
1192       * @see Pattern#compile(String)
1193       * @see Pattern#split(CharSequence, int)
1194     * @since 1.4     * @since 1.4
1195     * @XXX Add this method.     */
1196    public String[] split(String regex)    public String[] split(String regex)
1197    {    {
1198      return Pattern.compile(regex).split(this, 0);      return Pattern.compile(regex).split(this, 0);
1199    }    }
    */  
1200    
1201    /**    /**
1202     * Lowercases this String according to a particular locale. This uses     * Lowercases this String according to a particular locale. This uses
# Line 1148  public final class String implements Ser Line 1205  public final class String implements Ser
1205     *     *
1206     * @param loc locale to use     * @param loc locale to use
1207     * @return new lowercased String, or this if no characters were lowercased     * @return new lowercased String, or this if no characters were lowercased
1208       * @throws NullPointerException if loc is null
1209     * @see #toUpperCase(Locale)     * @see #toUpperCase(Locale)
1210     * @since 1.1     * @since 1.1
1211     */     */
1212    public String toLowerCase(Locale loc)    public String toLowerCase(Locale loc)
1213    {    {
1214      // XXX Fix this to follow Unicode rules.      // First, see if the current string is already lower case.
1215      char[] newStr = new char[count];      boolean turkish = "tr".equals(loc.getLanguage());
1216      for (int i = 0; i < count; i++)      int i = count;
1217        newStr[i] = Character.toLowerCase(value[i]);      while (--i >= 0)
1218      for (int i = 0; i < count; i++)        {
1219        if (value[i] != newStr[i])          char ch = value[i];
1220          return new String(newStr);          if ((turkish && ch == '\u0049')
1221      return this;              || ch != Character.toLowerCase(ch))
1222              break;
1223          }
1224        if (i < 0)
1225          return this;
1226    
1227        // Now we perform the conversion. Fortunately, there are no multi-character
1228        // lowercase expansions in Unicode 3.0.0.
1229        char[] newStr = (char[]) value.clone();
1230        do
1231          {
1232            char ch = value[i];
1233            // Hardcoded special case.
1234            newStr[i] = (turkish && ch == '\u0049') ? '\u0131'
1235              : Character.toLowerCase(ch);
1236          }
1237        while (--i >= 0);
1238        // Package constructor avoids an array copy.
1239        return new String(newStr, count);
1240    }    }
1241    
1242    /**    /**
# Line 1168  public final class String implements Ser Line 1244  public final class String implements Ser
1244     * applied to the platform's default Locale, so the resulting string may     * applied to the platform's default Locale, so the resulting string may
1245     * be a different length.     * be a different length.
1246     *     *
1247     * @return new lowercased String, or this if no characters where lowercased     * @return new lowercased String, or this if no characters were lowercased
1248     * @see #toLowerCase(Locale)     * @see #toLowerCase(Locale)
1249       * @see #toUpperCase()
1250     */     */
1251    public String toLowerCase()    public String toLowerCase()
1252    {    {
# Line 1183  public final class String implements Ser Line 1260  public final class String implements Ser
1260     *     *
1261     * @param loc locale to use     * @param loc locale to use
1262     * @return new uppercased String, or this if no characters were uppercased     * @return new uppercased String, or this if no characters were uppercased
1263       * @throws NullPointerException if loc is null
1264     * @see #toLowerCase(Locale)     * @see #toLowerCase(Locale)
1265     * @since 1.1     * @since 1.1
1266     */     */
1267    public String toUpperCase(Locale loc)    public String toUpperCase(Locale loc)
1268    {    {
1269      // XXX Fix this to follow Unicode rules.      // First, see how many characters we have to grow by, as well as if the
1270      char[] newStr = new char[count];      // current string is already upper case.
1271      for (int i = 0; i < count; i++)      boolean turkish = "tr".equals(loc.getLanguage());
1272        newStr[i] = Character.toUpperCase(value[i]);      int expand = 0;
1273      for (int i = 0; i < count; i++)      boolean unchanged = true;
1274        if (value[i] != newStr[i])      for (int i = count; --i >= 0; )
1275          return new String(newStr);        {
1276      return this;          char ch = value[i];
1277            expand += upperCaseExpansion(ch);
1278            unchanged = (unchanged && expand == 0
1279                         && ! (turkish && ch == '\u0069')
1280                         && ch == Character.toUpperCase(ch));
1281          }
1282        if (unchanged)
1283          return this;
1284    
1285        // Now we perform the conversion.
1286        if (expand == 0)
1287          {
1288            char[] newStr = (char[]) value.clone();
1289            for (int i = count; --i >= 0; )
1290              {
1291                char ch = value[i];
1292                // Hardcoded special case.
1293                newStr[i] = (turkish && ch == '\u0069') ? '\u0130'
1294                  : Character.toUpperCase(ch);
1295              }
1296            // Package constructor avoids an array copy.
1297            return new String(newStr, count);
1298          }
1299    
1300        // Expansion is necessary.
1301        char[] newStr = new char[count + expand];
1302        for (int i = 0, j = 0; i < count; )
1303          {
1304            char ch = value[i++];
1305            // Hardcoded special case.
1306            if (turkish && ch == '\u0069')
1307              {
1308                newStr[j++] = '\u0130';
1309                continue;
1310              }
1311            expand = upperCaseExpansion(ch);
1312            if (expand > 0)
1313              {
1314                int offset = upperCaseIndex(ch);
1315                while (expand-- >= 0)
1316                  newStr[j++] = upperExpand[offset++];
1317              }
1318            else
1319              newStr[j++] = Character.toUpperCase(ch);
1320          }
1321        // Package constructor avoids an array copy.
1322        return new String(newStr, newStr.length);
1323    }    }
1324    
1325    /**    /**
# Line 1203  public final class String implements Ser Line 1327  public final class String implements Ser
1327     * applied to the platform's default Locale, so the resulting string may     * applied to the platform's default Locale, so the resulting string may
1328     * be a different length.     * be a different length.
1329     *     *
1330     * @return new uppercased String, or this if no characters where uppercased     * @return new uppercased String, or this if no characters were uppercased
1331     * @see #toUpperCase(Locale)     * @see #toUpperCase(Locale)
1332       * @see #toLowerCase()
1333     */     */
1334    public String toUpperCase()    public String toUpperCase()
1335    {    {
# Line 1212  public final class String implements Ser Line 1337  public final class String implements Ser
1337    }    }
1338    
1339    /**    /**
1340     * Trims all characters less than or equal to ' ' (many ASCII control     * Trims all characters less than or equal to <code>'\u0020'</code>
1341     * characters, and all {@link Character#whitespace(char)}) from the     * (<code>' '</code>) from the beginning and end of this String. This
1342     * beginning and end of this String.     * includes many, but not all, ASCII control characters, and all
1343       * {@link Character#whitespace(char)}.
1344     *     *
1345     * @return new trimmed String, or this if nothing trimmed     * @return new trimmed String, or this if nothing trimmed
1346     */     */
# Line 1224  public final class String implements Ser Line 1350  public final class String implements Ser
1350        return this;        return this;
1351      int begin = 0;      int begin = 0;
1352      do      do
1353        {        if (begin == count)
1354          if (begin == count)          return "";
           return "";  
       }  
1355      while (value[begin++] <= '\u0020');      while (value[begin++] <= '\u0020');
1356      int end = count;      int end = count;
1357      while (value[--end] <= '\u0020');      while (value[--end] <= '\u0020');
# Line 1253  public final class String implements Ser Line 1377  public final class String implements Ser
1377     */     */
1378    public char[] toCharArray()    public char[] toCharArray()
1379    {    {
1380        if (count == value.length)
1381          return (char[]) value.clone();
1382      char[] copy = new char[count];      char[] copy = new char[count];
1383      System.arraycopy(value, 0, copy, 0, count);      System.arraycopy(value, 0, copy, 0, count);
1384      return copy;      return copy;
# Line 1283  public final class String implements Ser Line 1409  public final class String implements Ser
1409     */     */
1410    public static String valueOf(char[] data)    public static String valueOf(char[] data)
1411    {    {
1412      return new String(data, 0, data.length);      return new String(data);
1413    }    }
1414    
1415    /**    /**
# Line 1338  public final class String implements Ser Line 1464  public final class String implements Ser
1464     */     */
1465    public static String copyValueOf(char[] data)    public static String copyValueOf(char[] data)
1466    {    {
1467      return new String(data, 0, data.length);      return new String(data);
1468    }    }
1469    
1470    /**    /**
# Line 1360  public final class String implements Ser Line 1486  public final class String implements Ser
1486     */     */
1487    public static String valueOf(char c)    public static String valueOf(char c)
1488    {    {
1489      // XXX Share this array.      // Package constructor avoids an array copy.
1490      return new String(new char[] { c });      return new String(new char[] { c }, 1);
1491    }    }
1492    
1493    /**    /**
# Line 1420  public final class String implements Ser Line 1546  public final class String implements Ser
1546     * (s1.intern() == s2.intern()). All string literals and string-valued     * (s1.intern() == s2.intern()). All string literals and string-valued
1547     * constant expressions are already interned.     * constant expressions are already interned.
1548     *     *
1549     * @return intern'd String     * @return the interned String
1550     */     */
1551    public String intern()    public String intern()
1552    {    {
1553      // XXX Synchronize access to the table, to avoid races.      synchronized (internTable)
1554      Object o = internTable.get(this);        {
1555      if (o != null)          WeakReference ref = (WeakReference) internTable.get(this);
1556        return (String) o;          if (ref != null)
1557      internTable.put(this, this);            {
1558                String s = (String) ref.get();
1559                // If s is null, then no strong references exist to the String;
1560                // the weak hash map will soon delete the key.
1561                if (s != null)
1562                  return s;
1563              }
1564            internTable.put(this, new WeakReference(this));
1565          }
1566      return this;      return this;
1567    }    }
1568  }  
1569      /**
1570       * Helper function used to detect which characters have a multi-character
1571       * uppercase expansion. Note that this is only used in locations which
1572       * track one-to-many capitalization (java.lang.Character does not do this).
1573       * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the
1574       * longest uppercase expansion is three characters (a growth of 2 from the
1575       * lowercase character).
1576       *
1577       * @param ch the char to check
1578       * @return the number of characters to add when converting to uppercase
1579       * @see CharData#DIRECTION
1580       * @see CharData#UPPER_SPECIAL
1581       * @see #toUpperCase(Locale)
1582       */
1583      private static int upperCaseExpansion(char ch)
1584      {
1585        return Character.direction[Character.readChar(ch) >> 7] & 3;
1586      }
1587    
1588      /**
1589       * Helper function used to locate the offset in upperExpand given a
1590       * character with a multi-character expansion. The binary search is
1591       * optimized under the assumption that this method will only be called on
1592       * characters which exist in upperSpecial.
1593       *
1594       * @param ch the char to check
1595       * @return the index where its expansion begins
1596       * @see CharData#UPPER_SPECIAL
1597       * @see CharData#UPPER_EXPAND
1598       * @see #toUpperCase(Locale)
1599       */
1600      private static int upperCaseIndex(char ch)
1601      {
1602        // Simple binary search for the correct character.
1603        int low = 0;
1604        int hi = upperSpecial.length - 2;
1605        int mid = ((low + hi) >> 2) << 1;
1606        char c = upperSpecial[mid];
1607        while (ch != c)
1608          {
1609            if (ch < c)
1610              hi = mid - 2;
1611            else
1612              low = mid + 2;
1613            mid = ((low + hi) >> 2) << 1;
1614            c = upperSpecial[mid];
1615          }
1616        return upperSpecial[mid + 1];
1617      }
1618    } // class String

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

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