Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » lang » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package java.lang;
   19   
   20   import java.io.Serializable;
   21   import java.io.UnsupportedEncodingException;
   22   import java.util.Comparator;
   23   import java.util.Formatter;
   24   import java.util.Locale;
   25   
   26   import java.util.regex.Pattern;
   27   
   28   import java.nio.ByteBuffer;
   29   import java.nio.CharBuffer;
   30   import java.nio.charset.Charset;
   31   import java.nio.charset.IllegalCharsetNameException;
   32   import java.nio.charset.UnsupportedCharsetException;
   33   import java.security.AccessController;
   34   import java.util.regex.PatternSyntaxException;
   35   
   36   import org.apache.harmony.kernel.vm.VM;
   37   import org.apache.harmony.luni.util.PriviAction;
   38   
   39   /**
   40    * An immutable sequence of characters/code units ({@code char}s). A
   41    * {@code String} is represented by array of UTF-16 values, such that
   42    * Unicode supplementary characters (code points) are stored/encoded as
   43    * surrogate pairs via Unicode code units ({@code char}).
   44    *
   45    * @see StringBuffer
   46    * @see StringBuilder
   47    * @see Charset
   48    * @since 1.0
   49    */
   50   public final class String implements Serializable, Comparable<String>,
   51           CharSequence {
   52   
   53       private static final long serialVersionUID = -6849794470754667710L;
   54   
   55       /**
   56        * An PrintStream used for System.out which performs the correct character
   57        * conversion for the console, since the console may use a different
   58        * conversion than the default file.encoding.
   59        */
   60       static class ConsolePrintStream extends java.io.PrintStream {
   61           private static String charset;
   62   
   63           static {
   64               charset = AccessController.doPrivileged(new PriviAction<String>(
   65                       "console.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$
   66               if (!Charset.isSupported(charset)) {
   67                   charset = "ISO-8859-1"; //$NON-NLS-1$
   68               }
   69           }
   70   
   71           /**
   72            * Create a ConsolePrintStream on the specified OutputStream, usually
   73            * System.out.
   74            * 
   75            * @param out
   76            *            the console OutputStream
   77            */
   78           public ConsolePrintStream(java.io.OutputStream out) {
   79               super(out, true);
   80   
   81           }
   82   
   83           /**
   84            * Override the print(String) method from PrintStream to perform the
   85            * character conversion using the console character converter.
   86            *
   87            * @param str
   88            *            the string to convert
   89            */
   90           @Override
   91           public void print(String str) {
   92               if (str == null) {
   93                   str = "null"; //$NON-NLS-1$
   94               }
   95   
   96               try {
   97                   write(str.getBytes(charset));
   98               } catch (java.io.IOException e) {
   99                   setError();
  100               }
  101           }
  102       }
  103   
  104       /**
  105        * CaseInsensitiveComparator compares Strings ignoring the case of the
  106        * characters.
  107        */
  108       private static final class CaseInsensitiveComparator implements
  109               Comparator<String>, Serializable {
  110           private static final long serialVersionUID = 8575799808933029326L;
  111   
  112           /**
  113            * Compare the two objects to determine the relative ordering.
  114            *
  115            * @param o1
  116            *            an Object to compare
  117            * @param o2
  118            *            an Object to compare
  119            * @return an int < 0 if object1 is less than object2, 0 if they are
  120            *         equal, and > 0 if object1 is greater
  121            *
  122            * @exception ClassCastException
  123            *                if objects are not the correct type
  124            */
  125           public int compare(String o1, String o2) {
  126               return o1.compareToIgnoreCase(o2);
  127           }
  128       }
  129   
  130       /**
  131        * A comparator ignoring the case of the characters.
  132        */
  133       public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
  134   
  135       private static final char[] ascii;
  136   
  137       private final char[] value;
  138   
  139       private final int offset;
  140   
  141       private final int count;
  142   
  143       private int hashCode;
  144   
  145       private static Charset DefaultCharset;
  146   
  147       private static Charset lastCharset;
  148   
  149       static {
  150           ascii = new char[128];
  151           for (int i = 0; i < ascii.length; i++) {
  152               ascii[i] = (char) i;
  153           }
  154       }
  155   
  156       /**
  157        * Creates an empty string.
  158        */
  159       public String() {
  160           value = new char[0];
  161           offset = 0;
  162           count = 0;
  163       }
  164   
  165       /*
  166        * Private constructor used for JIT optimization.
  167        */
  168       @SuppressWarnings("unused")
  169       private String(String s, char c) {
  170           offset = 0;
  171           value = new char[s.count + 1];
  172           count = s.count + 1;
  173           System.arraycopy(s.value, s.offset, value, 0, s.count);
  174           value[s.count] = c;
  175       }
  176   
  177       /**
  178        * Converts the byte array to a string using the default encoding as
  179        * specified by the file.encoding system property. If the system property is
  180        * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
  181        * is not available, an ASCII encoding is used.
  182        * 
  183        * @param data
  184        *            the byte array to convert to a string.
  185        */
  186       public String(byte[] data) {
  187           this(data, 0, data.length);
  188       }
  189   
  190       /**
  191        * Converts the byte array to a string, setting the high byte of every
  192        * character to the specified value.
  193        * 
  194        * @param data
  195        *            the byte array to convert to a string.
  196        * @param high
  197        *            the high byte to use.
  198        * @throws NullPointerException
  199        *             when {@code data} is {@code null}.
  200        * @deprecated Use {@link #String(byte[])} or
  201        *             {@link #String(byte[], String)} instead.
  202        */
  203       @Deprecated
  204       public String(byte[] data, int high) {
  205           this(data, high, 0, data.length);
  206       }
  207   
  208       /**
  209        * Converts the byte array to a string using the default encoding as
  210        * specified by the file.encoding system property. If the system property is
  211        * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
  212        * is not available, an ASCII encoding is used.
  213        * 
  214        * @param data
  215        *            the byte array to convert to a string.
  216        * @param start
  217        *            the starting offset in the byte array.
  218        * @param length
  219        *            the number of bytes to convert.
  220        * @throws NullPointerException
  221        *             when {@code data} is {@code null}.
  222        * @throws IndexOutOfBoundsException
  223        *             if {@code length < 0, start < 0} or {@code start + length >
  224        *             data.length}.
  225        */
  226       public String(byte[] data, int start, int length) {
  227           // start + length could overflow, start/length maybe MaxInt
  228           if (start >= 0 && 0 <= length && length <= data.length - start) {
  229               offset = 0;
  230               Charset charset = defaultCharset();
  231               int result;
  232               CharBuffer cb = charset
  233                       .decode(ByteBuffer.wrap(data, start, length));
  234               if ((result = cb.length()) > 0) {
  235                   value = cb.array();
  236                   count = result;
  237               } else {
  238                   count = 0;
  239                   value = new char[0];
  240               }
  241           } else {
  242               throw new StringIndexOutOfBoundsException();
  243           }
  244       }
  245   
  246       /**
  247        * Converts the byte array to a string, setting the high byte of every
  248        * character to the specified value.
  249        *
  250        * @param data
  251        *            the byte array to convert to a string.
  252        * @param high
  253        *            the high byte to use.
  254        * @param start
  255        *            the starting offset in the byte array.
  256        * @param length
  257        *            the number of bytes to convert.
  258        * @throws NullPointerException
  259        *             when {@code data} is {@code null}.
  260        * @throws IndexOutOfBoundsException
  261        *             if {@code length < 0, start < 0} or
  262        *             {@code start + length > data.length}
  263        *
  264        * @deprecated Use {@link #String(byte[], int, int)} instead.
  265        */
  266       @Deprecated
  267       public String(byte[] data, int high, int start, int length) {
  268           if (data != null) {
  269               // start + length could overflow, start/length maybe MaxInt
  270               if (start >= 0 && 0 <= length && length <= data.length - start) {
  271                   offset = 0;
  272                   value = new char[length];
  273                   count = length;
  274                   high <<= 8;
  275                   for (int i = 0; i < count; i++) {
  276                       value[i] = (char) (high + (data[start++] & 0xff));
  277                   }
  278               } else {
  279                   throw new StringIndexOutOfBoundsException();
  280               }
  281           } else {
  282               throw new NullPointerException();
  283           }
  284       }
  285   
  286       /**
  287        * Converts the byte array to a string using the specified encoding.
  288        * 
  289        * @param data
  290        *            the byte array to convert to a string.
  291        * @param start
  292        *            the starting offset in the byte array.
  293        * @param length
  294        *            the number of bytes to convert.
  295        * @param encoding
  296        *            the encoding.
  297        * @throws NullPointerException
  298        *             when {@code data} is {@code null}.
  299        * @throws IndexOutOfBoundsException
  300        *             if {@code length < 0, start < 0} or {@code start + length >
  301        *             data.length}.
  302        * @throws UnsupportedEncodingException
  303        *             if {@code encoding} is not supported.
  304        */
  305       public String(byte[] data, int start, int length, final String encoding)
  306               throws UnsupportedEncodingException {
  307           if (encoding == null) {
  308               throw new NullPointerException();
  309           }
  310           // start + length could overflow, start/length maybe MaxInt
  311           if (start >= 0 && 0 <= length && length <= data.length - start) {
  312               offset = 0;
  313               Charset charset = getCharset(encoding);
  314   
  315               int result;
  316           	CharBuffer cb;
  317               try {
  318               	cb = charset.decode(ByteBuffer.wrap(data, start, length));
  319               } catch (Exception e) {
  320               	// do nothing. according to spec: 
  321               	// behavior is unspecified for invalid array
  322               	cb = CharBuffer.wrap("\u003f".toCharArray()); //$NON-NLS-1$
  323               }
  324               if ((result = cb.length()) > 0) {
  325                   value = cb.array();
  326                   count = result;
  327               } else {
  328                   count = 0;
  329                   value = new char[0];
  330               }
  331           } else {
  332               throw new StringIndexOutOfBoundsException();
  333           }
  334       }
  335   
  336       /**
  337        * Converts the byte array to a string using the specified encoding.
  338        * 
  339        * @param data
  340        *            the byte array to convert to a string.
  341        * @param encoding
  342        *            the encoding.
  343        * @throws NullPointerException
  344        *             when {@code data} is {@code null}.
  345        * @throws UnsupportedEncodingException
  346        *             if {@code encoding} is not supported.
  347        */
  348       public String(byte[] data, String encoding) throws UnsupportedEncodingException {
  349           this(data, 0, data.length, encoding);
  350       }
  351       
  352       /**
  353        * Converts the byte array to a String using the specified encoding.
  354        * 
  355        * @param data
  356        *            the byte array to convert to a String
  357        * @param start
  358        *            the starting offset in the byte array
  359        * @param length
  360        *            the number of bytes to convert
  361        * @param encoding
  362        *            the encoding
  363        * 
  364        * @throws IndexOutOfBoundsException
  365        *             when <code>length < 0, start < 0</code> or
  366        *             <code>start + length > data.length</code>
  367        * @throws NullPointerException
  368        *             when data is null
  369        * 
  370        * @see #getBytes()
  371        * @see #getBytes(int, int, byte[], int)
  372        * @see #getBytes(String)
  373        * @see #valueOf(boolean)
  374        * @see #valueOf(char)
  375        * @see #valueOf(char[])
  376        * @see #valueOf(char[], int, int)
  377        * @see #valueOf(double)
  378        * @see #valueOf(float)
  379        * @see #valueOf(int)
  380        * @see #valueOf(long)
  381        * @see #valueOf(Object)
  382        * @since 1.6
  383        */
  384       public String(byte[] data, int start, int length, final Charset encoding) {
  385           if (encoding == null) {
  386               throw new NullPointerException();
  387           }
  388           // start + length could overflow, start/length maybe MaxInt
  389           if (start >= 0 && 0 <= length && length <= data.length - start) {
  390               offset = 0;
  391               lastCharset = encoding;
  392               
  393               CharBuffer cb = encoding
  394                       .decode(ByteBuffer.wrap(data, start, length));
  395               value = cb.array();
  396               count = cb.length();
  397           } else {
  398               throw new StringIndexOutOfBoundsException();
  399           }
  400       }
  401       
  402       /**
  403        * Converts the byte array to a String using the specified encoding.
  404        * 
  405        * @param data
  406        *            the byte array to convert to a String
  407        * @param encoding
  408        *            the encoding
  409        * 
  410        * @throws NullPointerException
  411        *             when data is null
  412        * 
  413        * @see #getBytes()
  414        * @see #getBytes(int, int, byte[], int)
  415        * @see #getBytes(String)
  416        * @see #valueOf(boolean)
  417        * @see #valueOf(char)
  418        * @see #valueOf(char[])
  419        * @see #valueOf(char[], int, int)
  420        * @see #valueOf(double)
  421        * @see #valueOf(float)
  422        * @see #valueOf(int)
  423        * @see #valueOf(long)
  424        * @see #valueOf(Object)
  425        * @since 1.6
  426        */
  427       public String(byte[] data, Charset encoding) {
  428           this(data, 0, data.length, encoding);
  429       }
  430   
  431       /**
  432        * Initializes this string to contain the characters in the specified
  433        * character array. Modifying the character array after creating the string
  434        * has no effect on the string.
  435        * 
  436        * @param data
  437        *            the array of characters.
  438        * @throws NullPointerException
  439        *             when {@code data} is {@code null}.
  440        */
  441       public String(char[] data) {
  442           this(data, 0, data.length);
  443       }
  444   
  445       /**
  446        * Initializes this string to contain the specified characters in the
  447        * character array. Modifying the character array after creating the string
  448        * has no effect on the string.
  449        * 
  450        * @param data
  451        *            the array of characters.
  452        * @param start
  453        *            the starting offset in the character array.
  454        * @param length
  455        *            the number of characters to use.
  456        * @throws NullPointerException
  457        *             when {@code data} is {@code null}.
  458        * @throws IndexOutOfBoundsException
  459        *             if {@code length < 0, start < 0} or {@code start + length >
  460        *             data.length}
  461        */
  462       public String(char[] data, int start, int length) {
  463           // range check everything so a new char[] is not created
  464           // start + length could overflow, start/length maybe MaxInt
  465           if (start >= 0 && 0 <= length && length <= data.length - start) {
  466               offset = 0;
  467               value = new char[length];
  468               count = length;
  469               System.arraycopy(data, start, value, 0, count);
  470           } else {
  471               throw new StringIndexOutOfBoundsException();
  472           }
  473       }
  474   
  475       /*
  476        * Internal version of string constructor. Does not range check, null check,
  477        * or copy the character array.
  478        */
  479       String(int start, int length, char[] data) {
  480           value = data;
  481           offset = start;
  482           count = length;
  483       }
  484   
  485       /**
  486        * Creates a {@code String} that is a copy of the specified string.
  487        * 
  488        * @param string
  489        *            the string to copy.
  490        */
  491       public String(String string) {
  492           value = string.value;
  493           offset = string.offset;
  494           count = string.count;
  495       }
  496   
  497       /*
  498        * Private constructor useful for JIT optimization.
  499        */
  500       @SuppressWarnings( { "unused", "nls" })
  501       private String(String s1, String s2) {
  502           if (s1 == null) {
  503               s1 = "null";
  504           }
  505           if (s2 == null) {
  506               s2 = "null";
  507           }
  508           count = s1.count + s2.count;
  509           value = new char[count];
  510           offset = 0;
  511           System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
  512           System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
  513       }
  514   
  515       /*
  516        * Private constructor useful for JIT optimization.
  517        */
  518       @SuppressWarnings( { "unused", "nls" })
  519       private String(String s1, String s2, String s3) {
  520           if (s1 == null) {
  521               s1 = "null";
  522           }
  523           if (s2 == null) {
  524               s2 = "null";
  525           }
  526           if (s3 == null) {
  527               s3 = "null";
  528           }
  529           count = s1.count + s2.count + s3.count;
  530           value = new char[count];
  531           offset = 0;
  532           System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
  533           System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
  534           System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count,
  535                   s3.count);
  536       }
  537   
  538       /**
  539        * Creates a {@code String} from the contents of the specified
  540        * {@code StringBuffer}.
  541        * 
  542        * @param stringbuffer
  543        *            the buffer to get the contents from.
  544        */
  545       public String(StringBuffer stringbuffer) {
  546           offset = 0;
  547           synchronized (stringbuffer) {
  548               value = stringbuffer.shareValue();
  549               count = stringbuffer.length();
  550           }
  551       }
  552   
  553       /**
  554        * Creates a {@code String} from the sub-array of Unicode code points.
  555        *
  556        * @param codePoints
  557        *            the array of Unicode code points to convert.
  558        * @param offset
  559        *            the inclusive index into {@code codePoints} to begin
  560        *            converting from.
  561        * @param count
  562        *            the number of elements in {@code codePoints} to copy.
  563        * @throws NullPointerException
  564        *             if {@code codePoints} is {@code null}.
  565        * @throws IllegalArgumentException
  566        *             if any of the elements of {@code codePoints} are not valid
  567        *             Unicode code points.
  568        * @throws IndexOutOfBoundsException
  569        *             if {@code offset} or {@code count} are not within the bounds
  570        *             of {@code codePoints}.
  571        * @since 1.5
  572        */
  573       public String(int[] codePoints, int offset, int count) {
  574           super();
  575           if (codePoints == null) {
  576               throw new NullPointerException();
  577           }
  578           if (offset < 0 || count < 0
  579                   || (long) offset + (long) count > codePoints.length) {
  580               throw new IndexOutOfBoundsException();
  581           }
  582           this.offset = 0;
  583           this.value = new char[count * 2];
  584           int end = offset + count;
  585           int c = 0;
  586           for (int i = offset; i < end; i++) {
  587               c += Character.toChars(codePoints[i], this.value, c);
  588           }
  589           this.count = c;
  590       }
  591   
  592       /**
  593        * Creates a {@code String} from the contents of the specified {@code
  594        * StringBuilder}.
  595        * 
  596        * @param sb
  597        *            the {@code StringBuilder} to copy the contents from.
  598        * @throws NullPointerException
  599        *             if {@code sb} is {@code null}.
  600        * @since 1.5
  601        */
  602       public String(StringBuilder sb) {
  603           if (sb == null) {
  604               throw new NullPointerException();
  605           }
  606           this.offset = 0;
  607           this.count = sb.length();
  608           this.value = new char[this.count];
  609           sb.getChars(0, this.count, this.value, 0);
  610       }
  611   
  612       /*
  613        * Creates a {@code String} that is s1 + v1. May be used by JIT code.
  614        */
  615       @SuppressWarnings("unused")
  616       private String(String s1, int v1) {
  617           if (s1 == null) {
  618               s1 = "null"; //$NON-NLS-1$
  619           }
  620           String s2 = String.valueOf(v1);
  621           int len = s1.count + s2.count;
  622           value = new char[len];
  623           offset = 0;
  624           System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
  625           System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
  626           count = len;
  627       }
  628   
  629       /**
  630        * Returns the character at the specified offset in this string.
  631        * 
  632        * @param index
  633        *            the zero-based index in this string.
  634        * @return the character at the index.
  635        * @throws IndexOutOfBoundsException
  636        *             if {@code index < 0} or {@code index >= length()}.
  637        */
  638       public char charAt(int index) {
  639           if (0 <= index && index < count) {
  640               return value[offset + index];
  641           }
  642           throw new StringIndexOutOfBoundsException();
  643       }
  644   
  645       // Optimized for ASCII
  646       private char compareValue(char ch) {
  647           if (ch < 128) {
  648               if ('A' <= ch && ch <= 'Z') {
  649                   return (char) (ch + ('a' - 'A'));
  650               }
  651               return ch;
  652           }
  653           return Character.toLowerCase(Character.toUpperCase(ch));
  654       }
  655   
  656       // Optimized for ASCII
  657       private char toLowerCase(char ch) {
  658           if (ch < 128) {
  659               if ('A' <= ch && ch <= 'Z') {
  660                   return (char) (ch + ('a' - 'A'));
  661               }
  662               return ch;
  663           }
  664           return Character.toLowerCase(ch);
  665       }
  666   
  667       // Optimized for ASCII
  668       private char toUpperCase(char ch) {
  669           if (ch < 128) {
  670               if ('a' <= ch && ch <= 'z') {
  671                   return (char) (ch - ('a' - 'A'));
  672               }
  673               return ch;
  674           }
  675           return Character.toUpperCase(ch);
  676       }
  677   
  678       /**
  679        * Compares the specified string to this string using the Unicode values of
  680        * the characters. Returns 0 if the strings contain the same characters in
  681        * the same order. Returns a negative integer if the first non-equal
  682        * character in this string has a Unicode value which is less than the
  683        * Unicode value of the character at the same position in the specified
  684        * string, or if this string is a prefix of the specified string. Returns a
  685        * positive integer if the first non-equal character in this string has a
  686        * Unicode value which is greater than the Unicode value of the character at
  687        * the same position in the specified string, or if the specified string is
  688        * a prefix of this string.
  689        * 
  690        * @param string
  691        *            the string to compare.
  692        * @return 0 if the strings are equal, a negative integer if this string is
  693        *         before the specified string, or a positive integer if this string
  694        *         is after the specified string.
  695        * @throws NullPointerException
  696        *             if {@code string} is {@code null}.
  697        */
  698       public int compareTo(String string) {
  699           // Code adapted from K&R, pg 101
  700           int o1 = offset, o2 = string.offset, result;
  701           int end = offset + (count < string.count ? count : string.count);
  702           char[] target = string.value;
  703           while (o1 < end) {
  704               if ((result = value[o1++] - target[o2++]) != 0) {
  705                   return result;
  706               }
  707           }
  708           return count - string.count;
  709       }
  710   
  711       /**
  712        * Compares the specified string to this string using the Unicode values of
  713        * the characters, ignoring case differences. Returns 0 if the strings
  714        * contain the same characters in the same order. Returns a negative integer
  715        * if the first non-equal character in this string has a Unicode value which
  716        * is less than the Unicode value of the character at the same position in
  717        * the specified string, or if this string is a prefix of the specified
  718        * string. Returns a positive integer if the first non-equal character in
  719        * this string has a Unicode value which is greater than the Unicode value
  720        * of the character at the same position in the specified string, or if the
  721        * specified string is a prefix of this string.
  722        * 
  723        * @param string
  724        *            the string to compare.
  725        * @return 0 if the strings are equal, a negative integer if this string is
  726        *         before the specified string, or a positive integer if this string
  727        *         is after the specified string.
  728        * @throws NullPointerException
  729        *             if {@code string} is {@code null}.
  730        */
  731       public int compareToIgnoreCase(String string) {
  732           int o1 = offset, o2 = string.offset, result;
  733           int end = offset + (count < string.count ? count : string.count);
  734           char c1, c2;
  735           char[] target = string.value;
  736           while (o1 < end) {
  737               if ((c1 = value[o1++]) == (c2 = target[o2++])) {
  738                   continue;
  739               }
  740               c1 = compareValue(c1);
  741               c2 = compareValue(c2);
  742               if ((result = c1 - c2) != 0) {
  743                   return result;
  744               }
  745           }
  746           return count - string.count;
  747       }
  748   
  749       /**
  750        * Concatenates this string and the specified string.
  751        * 
  752        * @param string
  753        *            the string to concatenate
  754        * @return a new string which is the concatenation of this string and the
  755        *         specified string.
  756        */
  757       public String concat(String string) {
  758           if (string.count > 0 && count > 0) {
  759               char[] buffer = new char[count + string.count];
  760               System.arraycopy(value, offset, buffer, 0, count);
  761               System.arraycopy(string.value, string.offset, buffer, count,
  762                       string.count);
  763               return new String(0, buffer.length, buffer);
  764           }
  765           return count == 0 ? string : this;
  766       }
  767   
  768       /**
  769        * Creates a new string containing the characters in the specified character
  770        * array. Modifying the character array after creating the string has no
  771        * effect on the string.
  772        * 
  773        * @param data
  774        *            the array of characters.
  775        * @return the new string.
  776        * @throws NullPointerException
  777        *             if {@code data} is {@code null}.
  778        */
  779       public static String copyValueOf(char[] data) {
  780           return new String(data, 0, data.length);
  781       }
  782   
  783       /**
  784        * Creates a new string containing the specified characters in the character
  785        * array. Modifying the character array after creating the string has no
  786        * effect on the string.
  787        * 
  788        * @param data
  789        *            the array of characters.
  790        * @param start
  791        *            the starting offset in the character array.
  792        * @param length
  793        *            the number of characters to use.
  794        * @return the new string.
  795        * @throws NullPointerException
  796        *             if {@code data} is {@code null}.
  797        * @throws IndexOutOfBoundsException
  798        *             if {@code length < 0, start < 0} or {@code start + length >
  799        *             data.length}.
  800        */
  801       public static String copyValueOf(char[] data, int start, int length) {
  802           return new String(data, start, length);
  803       }
  804   
  805       private Charset defaultCharset() {
  806           if (DefaultCharset == null) {
  807               String encoding = AccessController
  808                       .doPrivileged(new PriviAction<String>(
  809                               "file.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$
  810               // calling System.getProperty() may cause DefaultCharset to be
  811               // initialized
  812               try {
  813                   DefaultCharset = Charset.forName(encoding);
  814               } catch (IllegalCharsetNameException e) {
  815                   // Ignored
  816               } catch (UnsupportedCharsetException e) {
  817                   // Ignored
  818               }
  819   
  820               if (DefaultCharset == null) {
  821                   DefaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$
  822               }
  823           }
  824           return DefaultCharset;
  825       }
  826   
  827       /**
  828        * Compares the specified string to this string to determine if the
  829        * specified string is a suffix.
  830        * 
  831        * @param suffix
  832        *            the suffix to look for.
  833        * @return {@code true} if the specified string is a suffix of this string,
  834        *         {@code false} otherwise.
  835        * @throws NullPointerException
  836        *             if {@code suffix} is {@code null}.
  837        */
  838       public boolean endsWith(String suffix) {
  839           return regionMatches(count - suffix.count, suffix, 0, suffix.count);
  840       }
  841   
  842       /**
  843        * Compares the specified object to this string and returns true if they are
  844        * equal. The object must be an instance of string with the same characters
  845        * in the same order.
  846        * 
  847        * @param object
  848        *            the object to compare.
  849        * @return {@code true} if the specified object is equal to this string,
  850        *         {@code false} otherwise.
  851        * @see #hashCode
  852        */
  853       @Override
  854       public boolean equals(Object object) {
  855           if (object == this) {
  856               return true;
  857           }
  858           if (object instanceof String) {
  859               String s = (String) object;
  860               int hash = hashCode;  // Single read on hashCodes as they may change
  861               int shash = s.hashCode;
  862               if (count != s.count || (hash != shash && hash != 0 && shash != 0)) {
  863                   return false;
  864               }
  865               for (int i = 0; i < count; ++i) {
  866                   if (value[offset + i] != s.value[s.offset + i]) {
  867                       return false;
  868                   }
  869               }
  870               return true;
  871           }
  872           return false;
  873       }
  874   
  875       /**
  876        * Compares the specified string to this string ignoring the case of the
  877        * characters and returns true if they are equal.
  878        * 
  879        * @param string
  880        *            the string to compare.
  881        * @return {@code true} if the specified string is equal to this string,
  882        *         {@code false} otherwise.
  883        */
  884       public boolean equalsIgnoreCase(String string) {
  885           if (string == this) {
  886               return true;
  887           }
  888           if (string == null || count != string.count) {
  889               return false;
  890           }
  891   
  892           int o1 = offset, o2 = string.offset;
  893           int end = offset + count;
  894           char c1, c2;
  895           char[] target = string.value;
  896           while (o1 < end) {
  897               if ((c1 = value[o1++]) != (c2 = target[o2++])
  898                       && toUpperCase(c1) != toUpperCase(c2)
  899                       // Required for unicode that we test both cases
  900                       && toLowerCase(c1) != toLowerCase(c2)) {
  901                   return false;
  902               }
  903           }
  904           return true;
  905       }
  906   
  907       /**
  908        * Converts this string to a byte array using the default encoding as
  909        * specified by the file.encoding system property. If the system property is
  910        * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
  911        * is not available, an ASCII encoding is used.
  912        * 
  913        * @return the byte array encoding of this string.
  914        */
  915       public byte[] getBytes() {
  916           ByteBuffer buffer = defaultCharset().encode(
  917                   CharBuffer.wrap(this.value, this.offset, this.count));
  918           byte[] bytes = new byte[buffer.limit()];
  919           buffer.get(bytes);
  920           return bytes;
  921       }
  922   
  923       /**
  924        * Converts this string to a byte array, ignoring the high order bits of
  925        * each character.
  926        * 
  927        * @param start
  928        *            the starting offset of characters to copy.
  929        * @param end
  930        *            the ending offset of characters to copy.
  931        * @param data
  932        *            the destination byte array.
  933        * @param index
  934        *            the starting offset in the destination byte array.
  935        * @throws NullPointerException
  936        *             if {@code data} is {@code null}.
  937        * @throws IndexOutOfBoundsException
  938        *             if {@code start < 0}, {@code end > length()}, {@code index <
  939        *             0} or {@code end - start > data.length - index}.
  940        * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)}
  941        */
  942       @Deprecated
  943       public void getBytes(int start, int end, byte[] data, int index) {
  944           if (0 <= start && start <= end && end <= count) {
  945               end += offset;
  946               try {
  947                   for (int i = offset + start; i < end; i++) {
  948                       data[index++] = (byte) value[i];
  949                   }
  950               } catch (ArrayIndexOutOfBoundsException e) {
  951                   throw new StringIndexOutOfBoundsException();
  952               }
  953           } else {
  954               throw new StringIndexOutOfBoundsException();
  955           }
  956       }
  957   
  958       /**
  959        * Converts this string to a byte array using the specified encoding.
  960        * 
  961        * @param encoding
  962        *            the encoding to use.
  963        * @return the encoded byte array of this string.
  964        * @throws UnsupportedEncodingException
  965        *             if the encoding is not supported.
  966        */
  967       public byte[] getBytes(String encoding) throws UnsupportedEncodingException {
  968           ByteBuffer buffer = getCharset(encoding).encode(
  969                   CharBuffer.wrap(this.value, this.offset, this.count));
  970           byte[] bytes = new byte[buffer.limit()];
  971           buffer.get(bytes);
  972           return bytes;
  973       }
  974   
  975       private Charset getCharset(final String encoding)
  976               throws UnsupportedEncodingException {
  977           Charset charset = lastCharset;
  978           if (charset == null || !encoding.equalsIgnoreCase(charset.name())) {
  979               try {
  980                   charset = Charset.forName(encoding);
  981               } catch (IllegalCharsetNameException e) {
  982                   throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
  983                           encoding).initCause(e));
  984               } catch (UnsupportedCharsetException e) {
  985                   throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
  986                           encoding).initCause(e));
  987               }
  988               lastCharset = charset;
  989           }
  990           return charset;
  991       }
  992       
  993       /**
  994        * Converts this String to a byte encoding using the specified encoding.
  995        * 
  996        * @param encoding
  997        *            the encoding
  998        * @return the byte array encoding of this String
  999        * 
 1000        * @see String
 1001        * @since 1.6
 1002        */
 1003       public byte[] getBytes(Charset encoding) {
 1004           ByteBuffer buffer = encoding.encode(CharBuffer.wrap(this.value,
 1005                   this.offset, this.count));
 1006           byte[] bytes = new byte[buffer.limit()];
 1007           buffer.get(bytes);
 1008           return bytes;
 1009       }
 1010   
 1011       /**
 1012        * Copies the specified characters in this string to the character array
 1013        * starting at the specified offset in the character array.
 1014        * 
 1015        * @param start
 1016        *            the starting offset of characters to copy.
 1017        * @param end
 1018        *            the ending offset of characters to copy.
 1019        * @param buffer
 1020        *            the destination character array.
 1021        * @param index
 1022        *            the starting offset in the character array.
 1023        * @throws NullPointerException
 1024        *             if {@code buffer} is {@code null}.
 1025        * @throws IndexOutOfBoundsException
 1026        *             if {@code start < 0}, {@code end > length()}, {@code start >
 1027        *             end}, {@code index < 0}, {@code end - start > buffer.length -
 1028        *             index}
 1029        */
 1030       public void getChars(int start, int end, char[] buffer, int index) {
 1031           // NOTE last character not copied!
 1032           // Fast range check.
 1033           if (0 <= start && start <= end && end <= count) {
 1034               System.arraycopy(value, start + offset, buffer, index, end - start);
 1035           } else {
 1036               throw new StringIndexOutOfBoundsException();
 1037           }
 1038       }
 1039   
 1040       @Override
 1041       public int hashCode() {
 1042           if (hashCode == 0) {
 1043               if (count == 0) {
 1044                   return 0;
 1045               }
 1046               int hash = 0;
 1047               for (int i = offset; i < count + offset; i++) {
 1048                   hash = value[i] + ((hash << 5) - hash);
 1049               }
 1050               hashCode = hash;
 1051           }
 1052           return hashCode;
 1053       }
 1054   
 1055       /**
 1056        * Searches in this string for the first index of the specified character.
 1057        * The search for the character starts at the beginning and moves towards
 1058        * the end of this string.
 1059        * 
 1060        * @param c
 1061        *            the character to find.
 1062        * @return the index in this string of the specified character, -1 if the
 1063        *         character isn't found.
 1064        */
 1065       public int indexOf(int c) {
 1066           return indexOf(c, 0);
 1067       }
 1068   
 1069       /**
 1070        * Searches in this string for the index of the specified character. The
 1071        * search for the character starts at the specified offset and moves towards
 1072        * the end of this string.
 1073        * 
 1074        * @param c
 1075        *            the character to find.
 1076        * @param start
 1077        *            the starting offset.
 1078        * @return the index in this string of the specified character, -1 if the
 1079        *         character isn't found.
 1080        */
 1081       public int indexOf(int c, int start) {
 1082           if (start < count) {
 1083               if (start < 0) {
 1084                   start = 0;
 1085               }
 1086               for (int i = offset + start; i < offset + count; i++) {
 1087                   if (value[i] == c) {
 1088                       return i - offset;
 1089                   }
 1090               }
 1091           }
 1092           return -1;
 1093       }
 1094   
 1095       /**
 1096        * Searches in this string for the first index of the specified string. The
 1097        * search for the string starts at the beginning and moves towards the end
 1098        * of this string.
 1099        * 
 1100        * @param string
 1101        *            the string to find.
 1102        * @return the index of the first character of the specified string in this
 1103        *         string, -1 if the specified string is not a substring.
 1104        * @throws NullPointerException
 1105        *             if {@code string} is {@code null}.
 1106        */
 1107       public int indexOf(String string) {
 1108           return indexOf(string, 0);
 1109       }
 1110   
 1111       /**
 1112        * Searches in this string for the index of the specified string. The search
 1113        * for the string starts at the specified offset and moves towards the end
 1114        * of this string.
 1115        * 
 1116        * @param subString
 1117        *            the string to find.
 1118        * @param start
 1119        *            the starting offset.
 1120        * @return the index of the first character of the specified string in this
 1121        *         string, -1 if the specified string is not a substring.
 1122        * @throws NullPointerException
 1123        *             if {@code subString} is {@code null}.
 1124        */
 1125       public int indexOf(String subString, int start) {
 1126           if (start < 0) {
 1127               start = 0;
 1128           }
 1129           int subCount = subString.count;
 1130           if (subCount > 0) {
 1131               if (subCount + start > count) {
 1132                   return -1;
 1133               }
 1134               char[] target = subString.value;
 1135               int subOffset = subString.offset;
 1136               char firstChar = target[subOffset];
 1137               int end = subOffset + subCount;
 1138               while (true) {
 1139                   int i = indexOf(firstChar, start);
 1140                   if (i == -1 || subCount + i > count) {
 1141                       return -1; // handles subCount > count || start >= count
 1142                   }
 1143                   int o1 = offset + i, o2 = subOffset;
 1144                   while (++o2 < end && value[++o1] == target[o2]) {
 1145                       // Intentionally empty
 1146                   }
 1147                   if (o2 == end) {
 1148                       return i;
 1149                   }
 1150                   start = i + 1;
 1151               }
 1152           }
 1153           return start < count ? start : count;
 1154       }
 1155   
 1156       /**
 1157        * Searches an internal table of strings for a string equal to this string.
 1158        * If the string is not in the table, it is added. Returns the string
 1159        * contained in the table which is equal to this string. The same string
 1160        * object is always returned for strings which are equal.
 1161        * 
 1162        * @return the interned string equal to this string.
 1163        */
 1164       public String intern() {
 1165           return VM.intern(this);
 1166       }
 1167   
 1168       /**
 1169        * Searches in this string for the last index of the specified character.
 1170        * The search for the character starts at the end and moves towards the
 1171        * beginning of this string.
 1172        * 
 1173        * @param c
 1174        *            the character to find.
 1175        * @return the index in this string of the specified character, -1 if the
 1176        *         character isn't found.
 1177        */
 1178       public int lastIndexOf(int c) {
 1179           return lastIndexOf(c, count - 1);
 1180       }
 1181   
 1182       /**
 1183        * Searches in this string for the index of the specified character. The
 1184        * search for the character starts at the specified offset and moves towards
 1185        * the beginning of this string.
 1186        * 
 1187        * @param c
 1188        *            the character to find.
 1189        * @param start
 1190        *            the starting offset.
 1191        * @return the index in this string of the specified character, -1 if the
 1192        *         character isn't found.
 1193        */
 1194       public int lastIndexOf(int c, int start) {
 1195           if (start >= 0) {
 1196               if (start >= count) {
 1197                   start = count - 1;
 1198               }
 1199               for (int i = offset + start; i >= offset; --i) {
 1200                   if (value[i] == c) {
 1201                       return i - offset;
 1202                   }
 1203               }
 1204           }
 1205           return -1;
 1206       }
 1207   
 1208       /**
 1209        * Searches in this string for the last index of the specified string. The
 1210        * search for the string starts at the end and moves towards the beginning
 1211        * of this string.
 1212        * 
 1213        * @param string
 1214        *            the string to find.
 1215        * @return the index of the first character of the specified string in this
 1216        *         string, -1 if the specified string is not a substring.
 1217        * @throws NullPointerException
 1218        *             if {@code string} is {@code null}.
 1219        */
 1220       public int lastIndexOf(String string) {
 1221           // Use count instead of count - 1 so lastIndexOf("") answers count
 1222           return lastIndexOf(string, count);
 1223       }
 1224   
 1225       /**
 1226        * Searches in this string for the index of the specified string. The search
 1227        * for the string starts at the specified offset and moves towards the
 1228        * beginning of this string.
 1229        * 
 1230        * @param subString
 1231        *            the string to find.
 1232        * @param start
 1233        *            the starting offset.
 1234        * @return the index of the first character of the specified string in this
 1235        *         string , -1 if the specified string is not a substring.
 1236        * @throws NullPointerException
 1237        *             if {@code subString} is {@code null}.
 1238        */
 1239       public int lastIndexOf(String subString, int start) {
 1240           int subCount = subString.count;
 1241           if (subCount <= count && start >= 0) {
 1242               if (subCount > 0) {
 1243                   if (start > count - subCount) {
 1244                       start = count - subCount;
 1245                   }
 1246                   // count and subCount are both >= 1
 1247                   char[] target = subString.value;
 1248                   int subOffset = subString.offset;
 1249                   char firstChar = target[subOffset];
 1250                   int end = subOffset + subCount;
 1251                   while (true) {
 1252                       int i = lastIndexOf(firstChar, start);
 1253                       if (i == -1) {
 1254                           return -1;
 1255                       }
 1256                       int o1 = offset + i, o2 = subOffset;
 1257                       while (++o2 < end && value[++o1] == target[o2]) {
 1258                           // Intentionally empty
 1259                       }
 1260                       if (o2 == end) {
 1261                           return i;
 1262                       }
 1263                       start = i - 1;
 1264                   }
 1265               }
 1266               return start < count ? start : count;
 1267           }
 1268           return -1;
 1269       }
 1270   
 1271       /**
 1272        * Returns the size of this string.
 1273        * 
 1274        * @return the number of characters in this string.
 1275        */
 1276       public int length() {
 1277           return count;
 1278       }
 1279       
 1280       /**
 1281        * Answers if the size of this String is zero.
 1282        * 
 1283        * @return true if the size of this String is zero, false otherwise
 1284        * @since 1.6
 1285        */
 1286       public boolean isEmpty() {
 1287           return 0 == count;
 1288       }
 1289   
 1290       /**
 1291        * Compares the specified string to this string and compares the specified
 1292        * range of characters to determine if they are the same.
 1293        * 
 1294        * @param thisStart
 1295        *            the starting offset in this string.
 1296        * @param string
 1297        *            the string to compare.
 1298        * @param start
 1299        *            the starting offset in the specified string.
 1300        * @param length
 1301        *            the number of characters to compare.
 1302        * @return {@code true} if the ranges of characters are equal, {@code false}
 1303        *         otherwise
 1304        * @throws NullPointerException
 1305        *             if {@code string} is {@code null}.
 1306        */
 1307       public boolean regionMatches(int thisStart, String string, int start,
 1308               int length) {
 1309           if (string == null) {
 1310               throw new NullPointerException();
 1311           }
 1312           if (start < 0 || string.count - start < length) {
 1313               return false;
 1314           }
 1315           if (thisStart < 0 || count - thisStart < length) {
 1316               return false;
 1317           }
 1318           if (length <= 0) {
 1319               return true;
 1320           }
 1321           int o1 = offset + thisStart, o2 = string.offset + start;
 1322           for (int i = 0; i < length; ++i) {
 1323               if (value[o1 + i] != string.value[o2 + i]) {
 1324                   return false;
 1325               }
 1326           }
 1327           return true;
 1328       }
 1329   
 1330       /**
 1331        * Compares the specified string to this string and compares the specified
 1332        * range of characters to determine if they are the same. When ignoreCase is
 1333        * true, the case of the characters is ignored during the comparison.
 1334        * 
 1335        * @param ignoreCase
 1336        *            specifies if case should be ignored.
 1337        * @param thisStart
 1338        *            the starting offset in this string.
 1339        * @param string
 1340        *            the string to compare.
 1341        * @param start
 1342        *            the starting offset in the specified string.
 1343        * @param length
 1344        *            the number of characters to compare.
 1345        * @return {@code true} if the ranges of characters are equal, {@code false}
 1346        *         otherwise.
 1347        * @throws NullPointerException
 1348        *             if {@code string} is {@code null}.
 1349        */
 1350       public boolean regionMatches(boolean ignoreCase, int thisStart,
 1351               String string, int start, int length) {
 1352           if (!ignoreCase) {
 1353               return regionMatches(thisStart, string, start, length);
 1354           }
 1355   
 1356           if (string != null) {
 1357               if (thisStart < 0 || length > count - thisStart) {
 1358                   return false;
 1359               }
 1360               if (start < 0 || length > string.count - start) {
 1361                   return false;
 1362               }
 1363   
 1364               thisStart += offset;
 1365               start += string.offset;
 1366               int end = thisStart + length;
 1367               char c1, c2;
 1368               char[] target = string.value;
 1369               while (thisStart < end) {
 1370                   if ((c1 = value[thisStart++]) != (c2 = target[start++])
 1371                           && toUpperCase(c1) != toUpperCase(c2)
 1372                           // Required for unicode that we test both cases
 1373                           && toLowerCase(c1) != toLowerCase(c2)) {
 1374                       return false;
 1375                   }
 1376               }
 1377               return true;
 1378           }
 1379           throw new NullPointerException();
 1380       }
 1381   
 1382       /**
 1383        * Copies this string replacing occurrences of the specified character with
 1384        * another character.
 1385        * 
 1386        * @param oldChar
 1387        *            the character to replace.
 1388        * @param newChar
 1389        *            the replacement character.
 1390        * @return a new string with occurrences of oldChar replaced by newChar.
 1391        */
 1392       public String replace(char oldChar, char newChar) {
 1393           int index = indexOf(oldChar, 0);
 1394           if (index == -1) {
 1395               return this;
 1396           }
 1397   
 1398           char[] buffer = new char[count];
 1399           System.arraycopy(value, offset, buffer, 0, count);
 1400           do {
 1401               buffer[index++] = newChar;
 1402           } while ((index = indexOf(oldChar, index)) != -1);
 1403           return new String(0, count, buffer);
 1404       }
 1405       
 1406       /**
 1407        * Copies this string replacing occurrences of the specified target sequence
 1408        * with another sequence. The string is processed from the beginning to the
 1409        * end.
 1410        * 
 1411        * @param target
 1412        *            the sequence to replace.
 1413        * @param replacement
 1414        *            the replacement sequence.
 1415        * @return the resulting string.
 1416        * @throws NullPointerException
 1417        *             if {@code target} or {@code replacement} is {@code null}.
 1418        */
 1419       public String replace(CharSequence target, CharSequence replacement) {
 1420           if (target == null) {
 1421               throw new NullPointerException("target should not be null");
 1422           }
 1423           if (replacement == null) {
 1424               throw new NullPointerException("replacement should not be null");
 1425           }
 1426           String ts = target.toString();
 1427           int index = indexOf(ts, 0);
 1428   
 1429           if (index == -1)
 1430               return this;
 1431   
 1432           String rs = replacement.toString();
 1433           StringBuilder buffer = new StringBuilder(count);
 1434           int tl = target.length();
 1435           int tail = 0;
 1436           do {
 1437               buffer.append(value, offset + tail, index - tail);
 1438               buffer.append(rs);
 1439               tail = index + tl;
 1440           } while ((index = indexOf(ts, tail)) != -1);
 1441           //append trailing chars 
 1442           buffer.append(value, offset + tail, count - tail);
 1443   
 1444           return buffer.toString();
 1445       }
 1446   
 1447       /**
 1448        * Compares the specified string to this string to determine if the
 1449        * specified string is a prefix.
 1450        * 
 1451        * @param prefix
 1452        *            the string to look for.
 1453        * @return {@code true} if the specified string is a prefix of this string,
 1454        *         {@code false} otherwise
 1455        * @throws NullPointerException
 1456        *             if {@code prefix} is {@code null}.
 1457        */
 1458       public boolean startsWith(String prefix) {
 1459           return startsWith(prefix, 0);
 1460       }
 1461   
 1462       /**
 1463        * Compares the specified string to this string, starting at the specified
 1464        * offset, to determine if the specified string is a prefix.
 1465        * 
 1466        * @param prefix
 1467        *            the string to look for.
 1468        * @param start
 1469        *            the starting offset.
 1470        * @return {@code true} if the specified string occurs in this string at the
 1471        *         specified offset, {@code false} otherwise.
 1472        * @throws NullPointerException
 1473        *             if {@code prefix} is {@code null}.
 1474        */
 1475       public boolean startsWith(String prefix, int start) {
 1476           return regionMatches(start, prefix, 0, prefix.count);
 1477       }
 1478   
 1479       /**
 1480        * Copies a range of characters into a new string.
 1481        * 
 1482        * @param start
 1483        *            the offset of the first character.
 1484        * @return a new string containing the characters from start to the end of
 1485        *         the string.
 1486        * @throws IndexOutOfBoundsException
 1487        *             if {@code start < 0} or {@code start > length()}.
 1488        */
 1489       public String substring(int start) {
 1490           if (start == 0) {
 1491               return this;
 1492           }
 1493           if (0 <= start && start <= count) {
 1494               return new String(offset + start, count - start, value);
 1495           }
 1496           throw new StringIndexOutOfBoundsException(start);
 1497       }
 1498   
 1499       /**
 1500        * Copies a range of characters into a new string.
 1501        * 
 1502        * @param start
 1503        *            the offset of the first character.
 1504        * @param end
 1505        *            the offset one past the last character.
 1506        * @return a new string containing the characters from start to end - 1
 1507        * @throws IndexOutOfBoundsException
 1508        *             if {@code start < 0}, {@code start > end} or {@code end >
 1509        *             length()}.
 1510        */
 1511       public String substring(int start, int end) {
 1512           if (start == 0 && end == count) {
 1513               return this;
 1514           }
 1515           // NOTE last character not copied!
 1516           // Fast range check.
 1517           if (0 <= start && start <= end && end <= count) {
 1518               return new String(offset + start, end - start, value);
 1519           }
 1520           throw new StringIndexOutOfBoundsException();
 1521       }
 1522   
 1523       /**
 1524        * Copies the characters in this string to a character array.
 1525        * 
 1526        * @return a character array containing the characters of this string.
 1527        */
 1528       public char[] toCharArray() {
 1529           char[] buffer = new char[count];
 1530           System.arraycopy(value, offset, buffer, 0, count);
 1531           return buffer;
 1532       }
 1533   
 1534       /**
 1535        * Converts the characters in this string to lowercase, using the default
 1536        * Locale.
 1537        * 
 1538        * @return a new string containing the lowercase characters equivalent to
 1539        *         the characters in this string.
 1540        */
 1541       public String toLowerCase() {
 1542           return toLowerCase(Locale.getDefault());
 1543       }
 1544   
 1545       /**
 1546        * Converts the characters in this string to lowercase, using the specified
 1547        * Locale.
 1548        * 
 1549        * @param locale
 1550        *            the Locale to use.
 1551        * @return a new string containing the lowercase characters equivalent to
 1552        *         the characters in this string.
 1553        */
 1554       public String toLowerCase(Locale locale) {
 1555           for (int o = offset, end = offset + count; o < end; o++) {
 1556               char ch = value[o];
 1557               if (ch != toLowerCase(ch)) {
 1558                   char[] buffer = new char[count];
 1559                   int i = o - offset;
 1560                   // Not worth checking for i == 0 case
 1561                   System.arraycopy(value, offset, buffer, 0, i);
 1562                   // Turkish
 1563                   if (!"tr".equals(locale.getLanguage())) { //$NON-NLS-1$
 1564                       while (i < count) {
 1565                           buffer[i++] = toLowerCase(value[o++]);
 1566                       }
 1567                   } else {
 1568                       while (i < count) {
 1569                           buffer[i++] = (ch = value[o++]) != 0x49 ? toLowerCase(ch)
 1570                                   : (char) 0x131;
 1571                       }
 1572                   }
 1573                   return new String(0, count, buffer);
 1574               }
 1575           }
 1576           return this;
 1577       }
 1578   
 1579       /**
 1580        * Returns this string.
 1581        *
 1582        * @return this string.
 1583        */
 1584       @Override
 1585       public String toString() {
 1586           return this;
 1587       }
 1588   
 1589       /**
 1590        * Converts the characters in this string to uppercase, using the default
 1591        * Locale.
 1592        * 
 1593        * @return a new string containing the uppercase characters equivalent to
 1594        *         the characters in this string.
 1595        */
 1596       public String toUpperCase() {
 1597           return toUpperCase(Locale.getDefault());
 1598       }
 1599   
 1600       private static final char[] upperValues = "SS\u0000\u02bcN\u0000J\u030c\u0000\u0399\u0308\u0301\u03a5\u0308\u0301\u0535\u0552\u0000H\u0331\u0000T\u0308\u0000W\u030a\u0000Y\u030a\u0000A\u02be\u0000\u03a5\u0313\u0000\u03a5\u0313\u0300\u03a5\u0313\u0301\u03a5\u0313\u0342\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1fba\u0399\u0000\u0391\u0399\u0000\u0386\u0399\u0000\u0391\u0342\u0000\u0391\u0342\u0399\u0391\u0399\u0000\u1fca\u0399\u0000\u0397\u0399\u0000\u0389\u0399\u0000\u0397\u0342\u0000\u0397\u0342\u0399\u0397\u0399\u0000\u0399\u0308\u0300\u0399\u0308\u0301\u0399\u0342\u0000\u0399\u0308\u0342\u03a5\u0308\u0300\u03a5\u0308\u0301\u03a1\u0313\u0000\u03a5\u0342\u0000\u03a5\u0308\u0342\u1ffa\u0399\u0000\u03a9\u0399\u0000\u038f\u0399\u0000\u03a9\u0342\u0000\u03a9\u0342\u0399\u03a9\u0399\u0000FF\u0000FI\u0000FL\u0000FFIFFLST\u0000ST\u0000\u0544\u0546\u0000\u0544\u0535\u0000\u0544\u053b\u0000\u054e\u0546\u0000\u0544\u053d\u0000".value; //$NON-NLS-1$
 1601   
 1602       /**
 1603        * Return the index of the specified character into the upperValues table.
 1604        * The upperValues table contains three entries at each position. These
 1605        * three characters are the upper case conversion. If only two characters
 1606        * are used, the third character in the table is \u0000.
 1607        *
 1608        * @param ch
 1609        *            the char being converted to upper case
 1610        *
 1611        * @return the index into the upperValues table, or -1
 1612        */
 1613       private int upperIndex(int ch) {
 1614           int index = -1;
 1615           if (ch >= 0xdf) {
 1616               if (ch <= 0x587) {
 1617                   if (ch == 0xdf) {
 1618                       index = 0;
 1619                   } else if (ch <= 0x149) {
 1620                       if (ch == 0x149) {
 1621                           index = 1;
 1622                       }
 1623                   } else if (ch <= 0x1f0) {
 1624                       if (ch == 0x1f0) {
 1625                           index = 2;
 1626                       }
 1627                   } else if (ch <= 0x390) {
 1628                       if (ch == 0x390) {
 1629                           index = 3;
 1630                       }
 1631                   } else if (ch <= 0x3b0) {
 1632                       if (ch == 0x3b0) {
 1633                           index = 4;
 1634                       }
 1635                   } else if (ch <= 0x587) {
 1636                       if (ch == 0x587) {
 1637                           index = 5;
 1638                       }
 1639                   }
 1640               } else if (ch >= 0x1e96) {
 1641                   if (ch <= 0x1e9a) {
 1642                       index = 6 + ch - 0x1e96;
 1643                   } else if (ch >= 0x1f50 && ch <= 0x1ffc) {
 1644                       index = "\u000b\u0000\f\u0000\r\u0000\u000e\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>\u0000\u0000?@A\u0000BC\u0000\u0000\u0000\u0000D\u0000\u0000\u0000\u0000\u0000EFG\u0000HI\u0000\u0000\u0000\u0000J\u0000\u0000\u0000\u0000\u0000KL\u0000\u0000MN\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000OPQ\u0000RS\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000TUV\u0000WX\u0000\u0000\u0000\u0000Y".value[ch - 0x1f50]; //$NON-NLS-1$
 1645                       if (index == 0) {
 1646                           index = -1;
 1647                       }
 1648                   } else if (ch >= 0xfb00) {
 1649                       if (ch <= 0xfb06) {
 1650                           index = 90 + ch - 0xfb00;
 1651                       } else if (ch >= 0xfb13 && ch <= 0xfb17) {
 1652                           index = 97 + ch - 0xfb13;
 1653                       }
 1654                   }
 1655               }
 1656           }
 1657           return index;
 1658       }
 1659   
 1660       /**
 1661        * Converts the characters in this string to uppercase, using the specified
 1662        * Locale.
 1663        * 
 1664        * @param locale
 1665        *            the Locale to use.
 1666        * @return a new string containing the uppercase characters equivalent to
 1667        *         the characters in this string.
 1668        */
 1669       public String toUpperCase(Locale locale) {
 1670           boolean turkish = "tr".equals(locale.getLanguage()); //$NON-NLS-1$
 1671           char[] output = null;
 1672           int i = 0;
 1673           for (int o = offset, end = offset + count; o < end; o++) {
 1674               char ch = value[o];
 1675               int index = upperIndex(ch);
 1676               if (index == -1) {
 1677                   if (output != null && i >= output.length) {
 1678                       char[] newoutput = new char[output.length + (count / 6) + 2];
 1679                       System.arraycopy(output, 0, newoutput, 0, output.length);
 1680                       output = newoutput;
 1681                   }
 1682                   char upch = !turkish ? toUpperCase(ch)
 1683                           : (ch != 0x69 ? toUpperCase(ch)
 1684                                   : (char) 0x130);
 1685                   if (ch != upch) {
 1686                       if (output == null) {
 1687                           output = new char[count];
 1688                           i = o - offset;
 1689                           System.arraycopy(value, offset, output, 0, i);
 1690   
 1691                       }
 1692                       output[i++] = upch;
 1693                   } else if (output != null) {
 1694                       output[i++] = ch;
 1695                   }
 1696               } else {
 1697                   int target = index * 3;
 1698                   char val3 = upperValues[target + 2];
 1699                   if (output == null) {
 1700                       output = new char[count + (count / 6) + 2];
 1701                       i = o - offset;
 1702                       System.arraycopy(value, offset, output, 0, i);
 1703                   } else if (i + (val3 == 0 ? 1 : 2) >= output.length) {
 1704                       char[] newoutput = new char[output.length + (count / 6) + 3];
 1705                       System.arraycopy(output, 0, newoutput, 0, output.length);
 1706                       output = newoutput;
 1707                   }
 1708   
 1709                   char val = upperValues[target];
 1710                   output[i++] = val;
 1711                   val = upperValues[target + 1];
 1712                   output[i++] = val;
 1713                   if (val3 != 0) {
 1714                       output[i++] = val3;
 1715                   }
 1716               }
 1717           }
 1718           if (output == null) {
 1719               return this;
 1720           }
 1721           return output.length == i || output.length - i < 8 ? new String(0, i,
 1722                   output) : new String(output, 0, i);
 1723       }
 1724   
 1725       /**
 1726        * Copies this string removing white space characters from the beginning and
 1727        * end of the string.
 1728        * 
 1729        * @return a new string with characters <code><= \\u0020</code> removed from
 1730        *         the beginning and the end.
 1731        */
 1732       public String trim() {
 1733           int start = offset, last = offset + count - 1;
 1734           int end = last;
 1735           while ((start <= end) && (value[start] <= ' ')) {
 1736               start++;
 1737           }
 1738           while ((end >= start) && (value[end] <= ' ')) {
 1739               end--;
 1740           }
 1741           if (start == offset && end == last) {
 1742               return this;
 1743           }
 1744           return new String(start, end - start + 1, value);
 1745       }
 1746   
 1747       /**
 1748        * Creates a new string containing the characters in the specified character
 1749        * array. Modifying the character array after creating the string has no
 1750        * effect on the string.
 1751        * 
 1752        * @param data
 1753        *            the array of characters.
 1754        * @return the new string.
 1755        * @throws NullPointerException
 1756        *             if {@code data} is {@code null}.
 1757        */
 1758       public static String valueOf(char[] data) {
 1759           return new String(data, 0, data.length);
 1760       }
 1761   
 1762       /**
 1763        * Creates a new string containing the specified characters in the character
 1764        * array. Modifying the character array after creating the string has no
 1765        * effect on the string.
 1766        * 
 1767        * @param data
 1768        *            the array of characters.
 1769        * @param start
 1770        *            the starting offset in the character array.
 1771        * @param length
 1772        *            the number of characters to use.
 1773        * @return the new string.
 1774        * @throws IndexOutOfBoundsException
 1775        *             if {@code length < 0}, {@code start < 0} or {@code start +
 1776        *             length > data.length}
 1777        * @throws NullPointerException
 1778        *             if {@code data} is {@code null}.
 1779        */
 1780       public static String valueOf(char[] data, int start, int length) {
 1781           return new String(data, start, length);
 1782       }
 1783   
 1784       /**
 1785        * Converts the specified character to its string representation.
 1786        * 
 1787        * @param value
 1788        *            the character.
 1789        * @return the character converted to a string.
 1790        */
 1791       public static String valueOf(char value) {
 1792           String s;
 1793           if (value < 128) {
 1794               s = new String(value, 1, ascii);
 1795           } else {
 1796               s = new String(0, 1, new char[] { value });
 1797           }
 1798           s.hashCode = value;
 1799           return s;
 1800       }
 1801   
 1802       /**
 1803        * Converts the specified double to its string representation.
 1804        * 
 1805        * @param value
 1806        *            the double.
 1807        * @return the double converted to a string.
 1808        */
 1809       public static String valueOf(double value) {
 1810           return Double.toString(value);
 1811       }
 1812   
 1813       /**
 1814        * Converts the specified float to its string representation.
 1815        * 
 1816        * @param value
 1817        *            the float.
 1818        * @return the float converted to a string.
 1819        */
 1820       public static String valueOf(float value) {
 1821           return Float.toString(value);
 1822       }
 1823   
 1824       /**
 1825        * Converts the specified integer to its string representation.
 1826        * 
 1827        * @param value
 1828        *            the integer.
 1829        * @return the integer converted to a string.
 1830        */
 1831       public static String valueOf(int value) {
 1832           return Integer.toString(value);
 1833       }
 1834   
 1835       /**
 1836        * Converts the specified long to its string representation.
 1837        * 
 1838        * @param value
 1839        *            the long.
 1840        * @return the long converted to a string.
 1841        */
 1842       public static String valueOf(long value) {
 1843           return Long.toString(value);
 1844       }
 1845   
 1846       /**
 1847        * Converts the specified object to its string representation. If the object
 1848        * is null return the string {@code "null"}, otherwise use {@code
 1849        * toString()} to get the string representation.
 1850        * 
 1851        * @param value
 1852        *            the object.
 1853        * @return the object converted to a string, or the string {@code "null"}.
 1854        */
 1855       public static String valueOf(Object value) {
 1856           return value != null ? value.toString() : "null"; //$NON-NLS-1$
 1857       }
 1858   
 1859       /**
 1860        * Converts the specified boolean to its string representation. When the
 1861        * boolean is {@code true} return {@code "true"}, otherwise return {@code
 1862        * "false"}.
 1863        * 
 1864        * @param value
 1865        *            the boolean.
 1866        * @return the boolean converted to a string.
 1867        */
 1868       public static String valueOf(boolean value) {
 1869           return value ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$
 1870       }
 1871   
 1872       /**
 1873        * Returns whether the characters in the StringBuffer {@code strbuf} are the
 1874        * same as those in this string.
 1875        * 
 1876        * @param strbuf
 1877        *            the StringBuffer to compare this string to.
 1878        * @return {@code true} if the characters in {@code strbuf} are identical to
 1879        *         those in this string. If they are not, {@code false} will be
 1880        *         returned.
 1881        * @throws NullPointerException
 1882        *             if {@code strbuf} is {@code null}.
 1883        * @since 1.4
 1884        */
 1885       public boolean contentEquals(StringBuffer strbuf) {
 1886           synchronized (strbuf) {
 1887               int size = strbuf.length();
 1888               if (count != size) {
 1889                   return false;
 1890               }
 1891               return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
 1892                       size);
 1893           }
 1894       }
 1895   
 1896       /**
 1897        * Compares a {@code CharSequence} to this {@code String} to determine if
 1898        * their contents are equal.
 1899        *
 1900        * @param cs
 1901        *            the character sequence to compare to.
 1902        * @return {@code true} if equal, otherwise {@code false}
 1903        * @since 1.5
 1904        */
 1905       public boolean contentEquals(CharSequence cs) {
 1906           if (cs == null) {
 1907               throw new NullPointerException();
 1908           }
 1909   
 1910           int len = cs.length();
 1911   
 1912           if (len != count) {
 1913               return false;
 1914           }
 1915   
 1916           if (len == 0 && count == 0) {
 1917               return true; // since both are empty strings
 1918           }
 1919   
 1920           return regionMatches(0, cs.toString(), 0, len);
 1921       }
 1922   
 1923       /**
 1924        * Determines whether this string matches a given regular expression.
 1925        * 
 1926        * @param expr
 1927        *            the regular expression to be matched.
 1928        * @return {@code true} if the expression matches, otherwise {@code false}.
 1929        * @throws PatternSyntaxException
 1930        *             if the syntax of the supplied regular expression is not
 1931        *             valid.
 1932        * @throws NullPointerException
 1933        *             if {@code expr} is {@code null}.
 1934        * @since 1.4
 1935        */
 1936       public boolean matches(String expr) {
 1937           return Pattern.matches(expr, this);
 1938       }
 1939   
 1940       /**
 1941        * Replace any substrings within this string that match the supplied regular
 1942        * expression {@code expr}, with the string {@code substitute}.
 1943        * 
 1944        * @param expr
 1945        *            the regular expression to match.
 1946        * @param substitute
 1947        *            the string to replace the matching substring with.
 1948        * @return the new string.
 1949        * @throws PatternSyntaxException
 1950        *             if the syntax of the supplied regular expression is not
 1951        *             valid.
 1952        * @see Pattern
 1953        * @since 1.4
 1954        */
 1955       public String replaceAll(String expr, String substitute) {
 1956           return Pattern.compile(expr).matcher(this).replaceAll(substitute);
 1957       }
 1958   
 1959       /**
 1960        * Replace the first substring within this string that matches the supplied
 1961        * regular expression {@code expr}, with the string {@code substitute}.
 1962        * 
 1963        * @param expr
 1964        *            the regular expression to match.
 1965        * @param substitute
 1966        *            the string to replace the matching substring with.
 1967        * @return the new string.
 1968        * @throws PatternSyntaxException
 1969        *             if the syntax of the supplied regular expression is not
 1970        *             valid.
 1971        * @throws NullPointerException
 1972        *             if {@code strbuf} is {@code null}.
 1973        * @see Pattern
 1974        * @since 1.4
 1975        */
 1976       public String replaceFirst(String expr, String substitute) {
 1977           return Pattern.compile(expr).matcher(this).replaceFirst(substitute);
 1978       }
 1979   
 1980       /**
 1981        * Splits this string using the supplied regular expression {@code expr}.
 1982        * 
 1983        * @param expr
 1984        *            the regular expression used to divide the string.
 1985        * @return an array of Strings created by separating the string along
 1986        *         matches of the regular expression.
 1987        * @throws NullPointerException
 1988        *             if {@code expr} is {@code null}.
 1989        * @throws PatternSyntaxException
 1990        *             if the syntax of the supplied regular expression is not
 1991        *             valid.
 1992        * @see Pattern
 1993        * @since 1.4
 1994        */
 1995       public String[] split(String expr) {
 1996           return Pattern.compile(expr).split(this);
 1997       }
 1998   
 1999       /**
 2000        * Splits this string using the supplied regular expression {@code expr}.
 2001        * The parameter {@code max} controls the behavior how many times the
 2002        * pattern is applied to the string.
 2003        * 
 2004        * @param expr
 2005        *            the regular expression used to divide the string.
 2006        * @param max
 2007        *            the number of entries in the resulting array.
 2008        * @return an array of Strings created by separating the string along
 2009        *         matches of the regular expression.
 2010        * @throws NullPointerException
 2011        *             if {@code expr} is {@code null}.
 2012        * @throws PatternSyntaxException
 2013        *             if the syntax of the supplied regular expression is not
 2014        *             valid.
 2015        * @see Pattern#split(CharSequence, int)
 2016        * @since 1.4
 2017        */
 2018       public String[] split(String expr, int max) {
 2019           return Pattern.compile(expr).split(this, max);
 2020       }
 2021   
 2022       /**
 2023        * Has the same result as the substring function, but is present so that
 2024        * string may implement the CharSequence interface.
 2025        * 
 2026        * @param start
 2027        *            the offset the first character.
 2028        * @param end
 2029        *            the offset of one past the last character to include.
 2030        * @return the subsequence requested.
 2031        * @throws IndexOutOfBoundsException
 2032        *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
 2033        *             {@code end > length()}.
 2034        * @see java.lang.CharSequence#subSequence(int, int)
 2035        * @since 1.4
 2036        */
 2037       public CharSequence subSequence(int start, int end) {
 2038           return substring(start, end);
 2039       }
 2040   
 2041       /**
 2042        * Retrieves the Unicode code point (character) value at the specified
 2043        * {@code index}.
 2044        * 
 2045        * @param index
 2046        *            the index to the {@code char} code unit within this string.
 2047        * @return the Unicode code point value.
 2048        * @throws IndexOutOfBoundsException
 2049        *             if {@code index} is negative or greater than or equal to
 2050        *             {@code length()}.
 2051        * @see Character#codePointAt(char[], int, int)
 2052        * @since 1.5
 2053        */
 2054       public int codePointAt(int index) {
 2055           if (index < 0 || index >= count) {
 2056               throw new IndexOutOfBoundsException();
 2057           }
 2058           int s = index + offset;
 2059           return Character.codePointAt(value, s, offset + count);
 2060       }
 2061   
 2062       /**
 2063        * Retrieves the Unicode code point value that precedes the specified
 2064        * {@code index}.
 2065        * 
 2066        * @param index
 2067        *            the index to the {@code char} code unit within this string.
 2068        * @return the Unicode code point value.
 2069        * @throws IndexOutOfBoundsException
 2070        *             if {@code index} is less than 1 or greater than
 2071        *             {@code length()}.
 2072        * @see Character#codePointBefore(char[], int, int)
 2073        * @since 1.5
 2074        */
 2075       public int codePointBefore(int index) {
 2076           if (index < 1 || index > count) {
 2077               throw new IndexOutOfBoundsException();
 2078           }
 2079           int s = index + offset;
 2080           return Character.codePointBefore(value, s);
 2081       }
 2082   
 2083       /**
 2084        * Calculates the number of Unicode code points between {@code beginIndex}
 2085        * and {@code endIndex}.
 2086        * 
 2087        * @param beginIndex
 2088        *            the inclusive beginning index of the subsequence.
 2089        * @param endIndex
 2090        *            the exclusive end index of the subsequence.
 2091        * @return the number of Unicode code points in the subsequence.
 2092        * @throws IndexOutOfBoundsException
 2093        *             if {@code beginIndex} is negative or greater than {@code
 2094        *             endIndex} or {@code endIndex} is greater than {@code
 2095        *             length()}.
 2096        * @see Character#codePointCount(CharSequence, int, int)
 2097        * @since 1.5
 2098        */
 2099       public int codePointCount(int beginIndex, int endIndex) {
 2100           if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
 2101               throw new IndexOutOfBoundsException();
 2102           }
 2103           int s = beginIndex + offset;
 2104           return Character.codePointCount(value, s, endIndex - beginIndex);
 2105       }
 2106   
 2107       /**
 2108        * Determines if this {@code String} contains the sequence of characters in
 2109        * the {@code CharSequence} passed.
 2110        *
 2111        * @param cs
 2112        *            the character sequence to search for.
 2113        * @return {@code true} if the sequence of characters are contained in this
 2114        *         string, otherwise {@code false}.
 2115        * @since 1.5
 2116        */
 2117       public boolean contains(CharSequence cs) {
 2118           if (cs == null) {
 2119               throw new NullPointerException();
 2120           }
 2121           return indexOf(cs.toString()) >= 0;
 2122       }
 2123   
 2124       /**
 2125        * Returns the index within this object that is offset from {@code index} by
 2126        * {@code codePointOffset} code points.
 2127        *
 2128        * @param index
 2129        *            the index within this object to calculate the offset from.
 2130        * @param codePointOffset
 2131        *            the number of code points to count.
 2132        * @return the index within this object that is the offset.
 2133        * @throws IndexOutOfBoundsException
 2134        *             if {@code index} is negative or greater than {@code length()}
 2135        *             or if there aren't enough code points before or after {@code
 2136        *             index} to match {@code codePointOffset}.
 2137        * @since 1.5
 2138        */
 2139       public int offsetByCodePoints(int index, int codePointOffset) {
 2140           int s = index + offset;
 2141           int r = Character.offsetByCodePoints(value, offset, count, s,
 2142                   codePointOffset);
 2143           return r - offset;
 2144       }
 2145   
 2146       /**
 2147        * Returns a formatted string, using the supplied format and arguments,
 2148        * using the default locale.
 2149        * 
 2150        * @param format
 2151        *            a format string.
 2152        * @param args
 2153        *            arguments to replace format specifiers (may be none).
 2154        * @return the formatted string.
 2155        * @throws NullPointerException
 2156        *             if {@code format} is {@code null}.
 2157        * @throws java.util.IllegalFormatException
 2158        *             if the format is invalid.
 2159        * @see java.util.Formatter
 2160        * @since 1.5
 2161        */
 2162       public static String format(String format, Object... args) {
 2163           return format(Locale.getDefault(), format, args);
 2164       }
 2165   
 2166       /**
 2167        * Returns a formatted string, using the supplied format and arguments,
 2168        * accordingly to the specified locale.
 2169        * <p>
 2170        * Note that this is a convenience method. Using it involves creating an
 2171        * internal {@link java.util.Formatter} instance on-the-fly, which is
 2172        * somewhat costly in terms of memory and time. This is probably acceptable
 2173        * if you use the method only rarely, but if you rely on it for formatting a
 2174        * large number of strings, consider creating and reusing your own
 2175        * {@link java.util.Formatter} instance instead.
 2176        *
 2177        * @param loc
 2178        *            the locale to apply; {@code null} value means no localization.
 2179        * @param format
 2180        *            a format string.
 2181        * @param args
 2182        *            arguments to replace format specifiers (may be none).
 2183        * @return the formatted string.
 2184        * @throws NullPointerException
 2185        *             if {@code format} is {@code null}.
 2186        * @throws java.util.IllegalFormatException
 2187        *             if the format is invalid.
 2188        * @see java.util.Formatter
 2189        * @since 1.5
 2190        */
 2191       public static String format(Locale loc, String format, Object... args) {
 2192           if (format == null) {
 2193               throw new NullPointerException("null format argument");
 2194           }
 2195           int bufferSize = format.length()
 2196                   + (args == null ? 0 : args.length * 10);
 2197           Formatter f = new Formatter(new StringBuilder(bufferSize), loc);
 2198           return f.format(format, args).toString();
 2199       }
 2200   
 2201       /*
 2202        * An implementation of a String.indexOf that is supposed to perform
 2203        * substantially better than the default algorithm if the "needle" (the
 2204        * subString being searched for) is a constant string.
 2205        *
 2206        * For example, a JIT, upon encoutering a call to String.indexOf(String),
 2207        * where the needle is a constant string, may compute the values cache, md2
 2208        * and lastChar, and change the call to the following method.
 2209        */
 2210       @SuppressWarnings("unused")
 2211       private static int indexOf(String haystackString, String needleString,
 2212               int cache, int md2, char lastChar) {
 2213           char[] haystack = haystackString.value;
 2214           int haystackOffset = haystackString.offset;
 2215           int haystackLength = haystackString.count;
 2216           char[] needle = needleString.value;
 2217           int needleOffset = needleString.offset;
 2218           int needleLength = needleString.count;
 2219           int needleLengthMinus1 = needleLength - 1;
 2220           int haystackEnd = haystackOffset + haystackLength;
 2221           outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
 2222               if (lastChar == haystack[i]) {
 2223                   for (int j = 0; j < needleLengthMinus1; ++j) {
 2224                       if (needle[j + needleOffset] != haystack[i + j
 2225                               - needleLengthMinus1]) {
 2226                           int skip = 1;
 2227                           if ((cache & (1 << haystack[i])) == 0) {
 2228                               skip += j;
 2229                           }
 2230                           i += Math.max(md2, skip);
 2231                           continue outer_loop;
 2232                       }
 2233                   }
 2234                   return i - needleLengthMinus1 - haystackOffset;
 2235               }
 2236   
 2237               if ((cache & (1 << haystack[i])) == 0) {
 2238                   i += needleLengthMinus1;
 2239               }
 2240               i++;
 2241           }
 2242           return -1;
 2243       }
 2244   
 2245       /*
 2246        * Returns the character array for this string.
 2247        */
 2248       char[] getValue() {
 2249           return value;
 2250       }
 2251   }

Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » lang » [javadoc | source]