Home | History | Annotate | Download | only in lang
      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.nio.ByteBuffer;
     23 import java.nio.CharBuffer;
     24 import java.nio.charset.Charset;
     25 import java.nio.charset.Charsets;
     26 import java.util.Arrays;
     27 import java.util.Comparator;
     28 import java.util.Formatter;
     29 import java.util.Locale;
     30 import java.util.regex.Pattern;
     31 import libcore.util.EmptyArray;
     32 
     33 /**
     34  * An immutable sequence of characters/code units ({@code char}s). A
     35  * {@code String} is represented by array of UTF-16 values, such that
     36  * Unicode supplementary characters (code points) are stored/encoded as
     37  * surrogate pairs via Unicode code units ({@code char}).
     38  *
     39  * <a name="backing_array"><h3>Backing Arrays</h3></a>
     40  * This class is implemented using a char[]. The length of the array may exceed
     41  * the length of the string. For example, the string "Hello" may be backed by
     42  * the array {@code ['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']} with
     43  * offset 0 and length 5.
     44  *
     45  * <p>Multiple strings can share the same char[] because strings are immutable.
     46  * The {@link #substring} method <strong>always</strong> returns a string that
     47  * shares the backing array of its source string. Generally this is an
     48  * optimization: fewer character arrays need to be allocated, and less copying
     49  * is necessary. But this can also lead to unwanted heap retention. Taking a
     50  * short substring of long string means that the long shared char[] won't be
     51  * garbage until both strings are garbage. This typically happens when parsing
     52  * small substrings out of a large input. To avoid this where necessary, call
     53  * {@code new String(longString.subString(...))}. The string copy constructor
     54  * always ensures that the backing array is no larger than necessary.
     55  *
     56  * @see StringBuffer
     57  * @see StringBuilder
     58  * @see Charset
     59  * @since 1.0
     60  */
     61 public final class String implements Serializable, Comparable<String>, CharSequence {
     62 
     63     private static final long serialVersionUID = -6849794470754667710L;
     64 
     65     private static final char REPLACEMENT_CHAR = (char) 0xfffd;
     66 
     67     /**
     68      * CaseInsensitiveComparator compares Strings ignoring the case of the
     69      * characters.
     70      */
     71     private static final class CaseInsensitiveComparator implements
     72             Comparator<String>, Serializable {
     73         private static final long serialVersionUID = 8575799808933029326L;
     74 
     75         /**
     76          * Compare the two objects to determine the relative ordering.
     77          *
     78          * @param o1
     79          *            an Object to compare
     80          * @param o2
     81          *            an Object to compare
     82          * @return an int < 0 if object1 is less than object2, 0 if they are
     83          *         equal, and > 0 if object1 is greater
     84          *
     85          * @exception ClassCastException
     86          *                if objects are not the correct type
     87          */
     88         public int compare(String o1, String o2) {
     89             return o1.compareToIgnoreCase(o2);
     90         }
     91     }
     92 
     93     /**
     94      * A comparator ignoring the case of the characters.
     95      */
     96     public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
     97 
     98     private static final char[] ASCII;
     99     static {
    100         ASCII = new char[128];
    101         for (int i = 0; i < ASCII.length; ++i) {
    102             ASCII[i] = (char) i;
    103         }
    104     }
    105 
    106     private final char[] value;
    107 
    108     private final int offset;
    109 
    110     private final int count;
    111 
    112     private int hashCode;
    113 
    114     /**
    115      * Creates an empty string.
    116      */
    117     public String() {
    118         value = EmptyArray.CHAR;
    119         offset = 0;
    120         count = 0;
    121     }
    122 
    123     /*
    124      * Private constructor used for JIT optimization.
    125      */
    126     @SuppressWarnings("unused")
    127     private String(String s, char c) {
    128         offset = 0;
    129         value = new char[s.count + 1];
    130         count = s.count + 1;
    131         System.arraycopy(s.value, s.offset, value, 0, s.count);
    132         value[s.count] = c;
    133     }
    134 
    135     /**
    136      * Converts the byte array to a string using the system's
    137      * {@link java.nio.charset.Charset#defaultCharset default charset}.
    138      */
    139     @FindBugsSuppressWarnings("DM_DEFAULT_ENCODING")
    140     public String(byte[] data) {
    141         this(data, 0, data.length);
    142     }
    143 
    144     /**
    145      * Converts the byte array to a string, setting the high byte of every
    146      * character to the specified value.
    147      *
    148      * @param data
    149      *            the byte array to convert to a string.
    150      * @param high
    151      *            the high byte to use.
    152      * @throws NullPointerException
    153      *             if {@code data == null}.
    154      * @deprecated Use {@link #String(byte[])} or {@link #String(byte[], String)} instead.
    155      */
    156     @Deprecated
    157     public String(byte[] data, int high) {
    158         this(data, high, 0, data.length);
    159     }
    160 
    161     /**
    162      * Converts a subsequence of the byte array to a string using the system's
    163      * {@link java.nio.charset.Charset#defaultCharset default charset}.
    164      *
    165      * @throws NullPointerException
    166      *             if {@code data == null}.
    167      * @throws IndexOutOfBoundsException
    168      *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
    169      */
    170     public String(byte[] data, int offset, int byteCount) {
    171         this(data, offset, byteCount, Charset.defaultCharset());
    172     }
    173 
    174     /**
    175      * Converts the byte array to a string, setting the high byte of every
    176      * character to {@code high}.
    177      *
    178      * @throws NullPointerException
    179      *             if {@code data == null}.
    180      * @throws IndexOutOfBoundsException
    181      *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
    182      *
    183      * @deprecated Use {@link #String(byte[], int, int)} instead.
    184      */
    185     @Deprecated
    186     public String(byte[] data, int high, int offset, int byteCount) {
    187         if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
    188             throw failedBoundsCheck(data.length, offset, byteCount);
    189         }
    190         this.offset = 0;
    191         this.value = new char[byteCount];
    192         this.count = byteCount;
    193         high <<= 8;
    194         for (int i = 0; i < count; i++) {
    195             value[i] = (char) (high + (data[offset++] & 0xff));
    196         }
    197     }
    198 
    199     /**
    200      * Converts the byte array to a string using the named charset.
    201      *
    202      * <p>The behavior when the bytes cannot be decoded by the named charset
    203      * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
    204      *
    205      * @throws NullPointerException
    206      *             if {@code data == null}.
    207      * @throws IndexOutOfBoundsException
    208      *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
    209      * @throws UnsupportedEncodingException
    210      *             if the named charset is not supported.
    211      */
    212     public String(byte[] data, int offset, int byteCount, String charsetName) throws UnsupportedEncodingException {
    213         this(data, offset, byteCount, Charset.forNameUEE(charsetName));
    214     }
    215 
    216     /**
    217      * Converts the byte array to a string using the named charset.
    218      *
    219      * <p>The behavior when the bytes cannot be decoded by the named charset
    220      * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
    221      *
    222      * @throws NullPointerException
    223      *             if {@code data == null}.
    224      * @throws UnsupportedEncodingException
    225      *             if {@code charsetName} is not supported.
    226      */
    227     public String(byte[] data, String charsetName) throws UnsupportedEncodingException {
    228         this(data, 0, data.length, Charset.forNameUEE(charsetName));
    229     }
    230 
    231     /**
    232      * Converts the byte array to a string using the given charset.
    233      *
    234      * <p>The behavior when the bytes cannot be decoded by the given charset
    235      * is to replace malformed input and unmappable characters with the charset's default
    236      * replacement string. Use {@link java.nio.charset.CharsetDecoder} for more control.
    237      *
    238      * @throws IndexOutOfBoundsException
    239      *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
    240      * @throws NullPointerException
    241      *             if {@code data == null}
    242      *
    243      * @since 1.6
    244      */
    245     public String(byte[] data, int offset, int byteCount, Charset charset) {
    246         if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
    247             throw failedBoundsCheck(data.length, offset, byteCount);
    248         }
    249 
    250         // We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because 'count' and
    251         // 'value' are final.
    252         String canonicalCharsetName = charset.name();
    253         if (canonicalCharsetName.equals("UTF-8")) {
    254             byte[] d = data;
    255             char[] v = new char[byteCount];
    256 
    257             int idx = offset;
    258             int last = offset + byteCount;
    259             int s = 0;
    260 outer:
    261             while (idx < last) {
    262                 byte b0 = d[idx++];
    263                 if ((b0 & 0x80) == 0) {
    264                     // 0xxxxxxx
    265                     // Range:  U-00000000 - U-0000007F
    266                     int val = b0 & 0xff;
    267                     v[s++] = (char) val;
    268                 } else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) ||
    269                         ((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe) == 0xfc)) {
    270                     int utfCount = 1;
    271                     if ((b0 & 0xf0) == 0xe0) utfCount = 2;
    272                     else if ((b0 & 0xf8) == 0xf0) utfCount = 3;
    273                     else if ((b0 & 0xfc) == 0xf8) utfCount = 4;
    274                     else if ((b0 & 0xfe) == 0xfc) utfCount = 5;
    275 
    276                     // 110xxxxx (10xxxxxx)+
    277                     // Range:  U-00000080 - U-000007FF (count == 1)
    278                     // Range:  U-00000800 - U-0000FFFF (count == 2)
    279                     // Range:  U-00010000 - U-001FFFFF (count == 3)
    280                     // Range:  U-00200000 - U-03FFFFFF (count == 4)
    281                     // Range:  U-04000000 - U-7FFFFFFF (count == 5)
    282 
    283                     if (idx + utfCount > last) {
    284                         v[s++] = REPLACEMENT_CHAR;
    285                         continue;
    286                     }
    287 
    288                     // Extract usable bits from b0
    289                     int val = b0 & (0x1f >> (utfCount - 1));
    290                     for (int i = 0; i < utfCount; ++i) {
    291                         byte b = d[idx++];
    292                         if ((b & 0xc0) != 0x80) {
    293                             v[s++] = REPLACEMENT_CHAR;
    294                             idx--; // Put the input char back
    295                             continue outer;
    296                         }
    297                         // Push new bits in from the right side
    298                         val <<= 6;
    299                         val |= b & 0x3f;
    300                     }
    301 
    302                     // Note: Java allows overlong char
    303                     // specifications To disallow, check that val
    304                     // is greater than or equal to the minimum
    305                     // value for each count:
    306                     //
    307                     // count    min value
    308                     // -----   ----------
    309                     //   1           0x80
    310                     //   2          0x800
    311                     //   3        0x10000
    312                     //   4       0x200000
    313                     //   5      0x4000000
    314 
    315                     // Allow surrogate values (0xD800 - 0xDFFF) to
    316                     // be specified using 3-byte UTF values only
    317                     if ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) {
    318                         v[s++] = REPLACEMENT_CHAR;
    319                         continue;
    320                     }
    321 
    322                     // Reject chars greater than the Unicode maximum of U+10FFFF.
    323                     if (val > 0x10FFFF) {
    324                         v[s++] = REPLACEMENT_CHAR;
    325                         continue;
    326                     }
    327 
    328                     // Encode chars from U+10000 up as surrogate pairs
    329                     if (val < 0x10000) {
    330                         v[s++] = (char) val;
    331                     } else {
    332                         int x = val & 0xffff;
    333                         int u = (val >> 16) & 0x1f;
    334                         int w = (u - 1) & 0xffff;
    335                         int hi = 0xd800 | (w << 6) | (x >> 10);
    336                         int lo = 0xdc00 | (x & 0x3ff);
    337                         v[s++] = (char) hi;
    338                         v[s++] = (char) lo;
    339                     }
    340                 } else {
    341                     // Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xff
    342                     v[s++] = REPLACEMENT_CHAR;
    343                 }
    344             }
    345 
    346             if (s == byteCount) {
    347                 // We guessed right, so we can use our temporary array as-is.
    348                 this.offset = 0;
    349                 this.value = v;
    350                 this.count = s;
    351             } else {
    352                 // Our temporary array was too big, so reallocate and copy.
    353                 this.offset = 0;
    354                 this.value = new char[s];
    355                 this.count = s;
    356                 System.arraycopy(v, 0, value, 0, s);
    357             }
    358         } else if (canonicalCharsetName.equals("ISO-8859-1")) {
    359             this.offset = 0;
    360             this.value = new char[byteCount];
    361             this.count = byteCount;
    362             Charsets.isoLatin1BytesToChars(data, offset, byteCount, value);
    363         } else if (canonicalCharsetName.equals("US-ASCII")) {
    364             this.offset = 0;
    365             this.value = new char[byteCount];
    366             this.count = byteCount;
    367             Charsets.asciiBytesToChars(data, offset, byteCount, value);
    368         } else {
    369             CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));
    370             this.offset = 0;
    371             this.count = cb.length();
    372             if (count > 0) {
    373                 // We could use cb.array() directly, but that would mean we'd have to trust
    374                 // the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later,
    375                 // which would break String's immutability guarantee. It would also tend to
    376                 // mean that we'd be wasting memory because CharsetDecoder doesn't trim the
    377                 // array. So we copy.
    378                 this.value = new char[count];
    379                 System.arraycopy(cb.array(), 0, value, 0, count);
    380             } else {
    381                 this.value = EmptyArray.CHAR;
    382             }
    383         }
    384     }
    385 
    386     /**
    387      * Converts the byte array to a String using the given charset.
    388      *
    389      * @throws NullPointerException if {@code data == null}
    390      * @since 1.6
    391      */
    392     public String(byte[] data, Charset charset) {
    393         this(data, 0, data.length, charset);
    394     }
    395 
    396     /**
    397      * Initializes this string to contain the characters in the specified
    398      * character array. Modifying the character array after creating the string
    399      * has no effect on the string.
    400      *
    401      * @throws NullPointerException if {@code data == null}
    402      */
    403     public String(char[] data) {
    404         this(data, 0, data.length);
    405     }
    406 
    407     /**
    408      * Initializes this string to contain the specified characters in the
    409      * character array. Modifying the character array after creating the string
    410      * has no effect on the string.
    411      *
    412      * @throws NullPointerException
    413      *             if {@code data == null}.
    414      * @throws IndexOutOfBoundsException
    415      *             if {@code charCount < 0 || offset < 0 || offset + charCount > data.length}
    416      */
    417     public String(char[] data, int offset, int charCount) {
    418         if ((offset | charCount) < 0 || charCount > data.length - offset) {
    419             throw failedBoundsCheck(data.length, offset, charCount);
    420         }
    421         this.offset = 0;
    422         this.value = new char[charCount];
    423         this.count = charCount;
    424         System.arraycopy(data, offset, value, 0, count);
    425     }
    426 
    427     /*
    428      * Internal version of the String(char[], int, int) constructor.
    429      * Does not range check, null check, or copy the character array.
    430      */
    431     String(int offset, int charCount, char[] chars) {
    432         this.value = chars;
    433         this.offset = offset;
    434         this.count = charCount;
    435     }
    436 
    437     /**
    438      * Constructs a new string with the same sequence of characters as {@code
    439      * toCopy}. The returned string's <a href="#backing_array">backing array</a>
    440      * is no larger than necessary.
    441      */
    442     public String(String toCopy) {
    443         value = (toCopy.value.length == toCopy.count)
    444                 ? toCopy.value
    445                 : Arrays.copyOfRange(toCopy.value, toCopy.offset, toCopy.offset + toCopy.length());
    446         offset = 0;
    447         count = value.length;
    448     }
    449 
    450     /*
    451      * Private constructor useful for JIT optimization.
    452      */
    453     @SuppressWarnings( { "unused", "nls" })
    454     private String(String s1, String s2) {
    455         if (s1 == null) {
    456             s1 = "null";
    457         }
    458         if (s2 == null) {
    459             s2 = "null";
    460         }
    461         count = s1.count + s2.count;
    462         value = new char[count];
    463         offset = 0;
    464         System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
    465         System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
    466     }
    467 
    468     /*
    469      * Private constructor useful for JIT optimization.
    470      */
    471     @SuppressWarnings( { "unused", "nls" })
    472     private String(String s1, String s2, String s3) {
    473         if (s1 == null) {
    474             s1 = "null";
    475         }
    476         if (s2 == null) {
    477             s2 = "null";
    478         }
    479         if (s3 == null) {
    480             s3 = "null";
    481         }
    482         count = s1.count + s2.count + s3.count;
    483         value = new char[count];
    484         offset = 0;
    485         System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
    486         System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
    487         System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count, s3.count);
    488     }
    489 
    490     /**
    491      * Creates a {@code String} from the contents of the specified
    492      * {@code StringBuffer}.
    493      */
    494     public String(StringBuffer stringBuffer) {
    495         offset = 0;
    496         synchronized (stringBuffer) {
    497             value = stringBuffer.shareValue();
    498             count = stringBuffer.length();
    499         }
    500     }
    501 
    502     /**
    503      * Creates a {@code String} from the sub-array of Unicode code points.
    504      *
    505      * @throws NullPointerException
    506      *             if {@code codePoints == null}.
    507      * @throws IllegalArgumentException
    508      *             if any of the elements of {@code codePoints} are not valid
    509      *             Unicode code points.
    510      * @throws IndexOutOfBoundsException
    511      *             if {@code offset} or {@code count} are not within the bounds
    512      *             of {@code codePoints}.
    513      * @since 1.5
    514      */
    515     public String(int[] codePoints, int offset, int count) {
    516         if (codePoints == null) {
    517             throw new NullPointerException("codePoints == null");
    518         }
    519         if ((offset | count) < 0 || count > codePoints.length - offset) {
    520             throw failedBoundsCheck(codePoints.length, offset, count);
    521         }
    522         this.offset = 0;
    523         this.value = new char[count * 2];
    524         int end = offset + count;
    525         int c = 0;
    526         for (int i = offset; i < end; i++) {
    527             c += Character.toChars(codePoints[i], this.value, c);
    528         }
    529         this.count = c;
    530     }
    531 
    532     /**
    533      * Creates a {@code String} from the contents of the specified {@code
    534      * StringBuilder}.
    535      *
    536      * @throws NullPointerException
    537      *             if {@code stringBuilder == null}.
    538      * @since 1.5
    539      */
    540     public String(StringBuilder stringBuilder) {
    541         if (stringBuilder == null) {
    542             throw new NullPointerException("stringBuilder == null");
    543         }
    544         this.offset = 0;
    545         this.count = stringBuilder.length();
    546         this.value = new char[this.count];
    547         stringBuilder.getChars(0, this.count, this.value, 0);
    548     }
    549 
    550     /*
    551      * Creates a {@code String} that is s1 + v1. May be used by JIT code.
    552      */
    553     @SuppressWarnings("unused")
    554     private String(String s1, int v1) {
    555         if (s1 == null) {
    556             s1 = "null";
    557         }
    558         String s2 = String.valueOf(v1);
    559         int len = s1.count + s2.count;
    560         value = new char[len];
    561         offset = 0;
    562         System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
    563         System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
    564         count = len;
    565     }
    566 
    567     /**
    568      * Returns the character at the specified offset in this string.
    569      *
    570      * @param index
    571      *            the zero-based index in this string.
    572      * @return the character at the index.
    573      * @throws IndexOutOfBoundsException
    574      *             if {@code index < 0} or {@code index >= length()}.
    575      */
    576     public char charAt(int index) {
    577         if (index < 0 || index >= count) {
    578             throw indexAndLength(index);
    579         }
    580         return value[offset + index];
    581     }
    582 
    583     private StringIndexOutOfBoundsException indexAndLength(int index) {
    584         throw new StringIndexOutOfBoundsException(this, index);
    585     }
    586 
    587     private StringIndexOutOfBoundsException startEndAndLength(int start, int end) {
    588         throw new StringIndexOutOfBoundsException(this, start, end - start);
    589     }
    590 
    591     private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) {
    592         throw new StringIndexOutOfBoundsException(arrayLength, offset, count);
    593     }
    594 
    595     /**
    596      * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode
    597      * case folds, but it's what the RI uses.
    598      */
    599     private char foldCase(char ch) {
    600         if (ch < 128) {
    601             if ('A' <= ch && ch <= 'Z') {
    602                 return (char) (ch + ('a' - 'A'));
    603             }
    604             return ch;
    605         }
    606         return Character.toLowerCase(Character.toUpperCase(ch));
    607     }
    608 
    609     /**
    610      * Compares the specified string to this string using the Unicode values of
    611      * the characters. Returns 0 if the strings contain the same characters in
    612      * the same order. Returns a negative integer if the first non-equal
    613      * character in this string has a Unicode value which is less than the
    614      * Unicode value of the character at the same position in the specified
    615      * string, or if this string is a prefix of the specified string. Returns a
    616      * positive integer if the first non-equal character in this string has a
    617      * Unicode value which is greater than the Unicode value of the character at
    618      * the same position in the specified string, or if the specified string is
    619      * a prefix of this string.
    620      *
    621      * @param string
    622      *            the string to compare.
    623      * @return 0 if the strings are equal, a negative integer if this string is
    624      *         before the specified string, or a positive integer if this string
    625      *         is after the specified string.
    626      * @throws NullPointerException
    627      *             if {@code string} is {@code null}.
    628      */
    629     public native int compareTo(String string);
    630 
    631     /**
    632      * Compares the specified string to this string using the Unicode values of
    633      * the characters, ignoring case differences. Returns 0 if the strings
    634      * contain the same characters in the same order. Returns a negative integer
    635      * if the first non-equal character in this string has a Unicode value which
    636      * is less than the Unicode value of the character at the same position in
    637      * the specified string, or if this string is a prefix of the specified
    638      * string. Returns a positive integer if the first non-equal character in
    639      * this string has a Unicode value which is greater than the Unicode value
    640      * of the character at the same position in the specified string, or if the
    641      * specified string is a prefix of this string.
    642      *
    643      * @param string
    644      *            the string to compare.
    645      * @return 0 if the strings are equal, a negative integer if this string is
    646      *         before the specified string, or a positive integer if this string
    647      *         is after the specified string.
    648      * @throws NullPointerException
    649      *             if {@code string} is {@code null}.
    650      */
    651     public int compareToIgnoreCase(String string) {
    652         int o1 = offset, o2 = string.offset, result;
    653         int end = offset + (count < string.count ? count : string.count);
    654         char c1, c2;
    655         char[] target = string.value;
    656         while (o1 < end) {
    657             if ((c1 = value[o1++]) == (c2 = target[o2++])) {
    658                 continue;
    659             }
    660             c1 = foldCase(c1);
    661             c2 = foldCase(c2);
    662             if ((result = c1 - c2) != 0) {
    663                 return result;
    664             }
    665         }
    666         return count - string.count;
    667     }
    668 
    669     /**
    670      * Concatenates this string and the specified string.
    671      *
    672      * @param string
    673      *            the string to concatenate
    674      * @return a new string which is the concatenation of this string and the
    675      *         specified string.
    676      */
    677     public String concat(String string) {
    678         if (string.count > 0 && count > 0) {
    679             char[] buffer = new char[count + string.count];
    680             System.arraycopy(value, offset, buffer, 0, count);
    681             System.arraycopy(string.value, string.offset, buffer, count, string.count);
    682             return new String(0, buffer.length, buffer);
    683         }
    684         return count == 0 ? string : this;
    685     }
    686 
    687     /**
    688      * Creates a new string containing the characters in the specified character
    689      * array. Modifying the character array after creating the string has no
    690      * effect on the string.
    691      *
    692      * @param data
    693      *            the array of characters.
    694      * @return the new string.
    695      * @throws NullPointerException
    696      *             if {@code data} is {@code null}.
    697      */
    698     public static String copyValueOf(char[] data) {
    699         return new String(data, 0, data.length);
    700     }
    701 
    702     /**
    703      * Creates a new string containing the specified characters in the character
    704      * array. Modifying the character array after creating the string has no
    705      * effect on the string.
    706      *
    707      * @param data
    708      *            the array of characters.
    709      * @param start
    710      *            the starting offset in the character array.
    711      * @param length
    712      *            the number of characters to use.
    713      * @return the new string.
    714      * @throws NullPointerException
    715      *             if {@code data} is {@code null}.
    716      * @throws IndexOutOfBoundsException
    717      *             if {@code length < 0, start < 0} or {@code start + length >
    718      *             data.length}.
    719      */
    720     public static String copyValueOf(char[] data, int start, int length) {
    721         return new String(data, start, length);
    722     }
    723 
    724     /**
    725      * Compares the specified string to this string to determine if the
    726      * specified string is a suffix.
    727      *
    728      * @param suffix
    729      *            the suffix to look for.
    730      * @return {@code true} if the specified string is a suffix of this string,
    731      *         {@code false} otherwise.
    732      * @throws NullPointerException
    733      *             if {@code suffix} is {@code null}.
    734      */
    735     public boolean endsWith(String suffix) {
    736         return regionMatches(count - suffix.count, suffix, 0, suffix.count);
    737     }
    738 
    739     /**
    740      * Compares the specified object to this string and returns true if they are
    741      * equal. The object must be an instance of string with the same characters
    742      * in the same order.
    743      *
    744      * @param object
    745      *            the object to compare.
    746      * @return {@code true} if the specified object is equal to this string,
    747      *         {@code false} otherwise.
    748      * @see #hashCode
    749      */
    750     @Override public native boolean equals(Object object);
    751 
    752     /**
    753      * Compares the specified string to this string ignoring the case of the
    754      * characters and returns true if they are equal.
    755      *
    756      * @param string
    757      *            the string to compare.
    758      * @return {@code true} if the specified string is equal to this string,
    759      *         {@code false} otherwise.
    760      */
    761     @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
    762     public boolean equalsIgnoreCase(String string) {
    763         if (string == this) {
    764             return true;
    765         }
    766         if (string == null || count != string.count) {
    767             return false;
    768         }
    769         int o1 = offset, o2 = string.offset;
    770         int end = offset + count;
    771         char[] target = string.value;
    772         while (o1 < end) {
    773             char c1 = value[o1++];
    774             char c2 = target[o2++];
    775             if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
    776                 return false;
    777             }
    778         }
    779         return true;
    780     }
    781 
    782     /**
    783      * Mangles this string into a byte array by stripping the high order bits from
    784      * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead.
    785      *
    786      * @param start
    787      *            the starting offset of characters to copy.
    788      * @param end
    789      *            the ending offset of characters to copy.
    790      * @param data
    791      *            the destination byte array.
    792      * @param index
    793      *            the starting offset in the destination byte array.
    794      * @throws NullPointerException
    795      *             if {@code data} is {@code null}.
    796      * @throws IndexOutOfBoundsException
    797      *             if {@code start < 0}, {@code end > length()}, {@code index <
    798      *             0} or {@code end - start > data.length - index}.
    799      * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} instead.
    800      */
    801     @Deprecated
    802     public void getBytes(int start, int end, byte[] data, int index) {
    803         // Note: last character not copied!
    804         if (start >= 0 && start <= end && end <= count) {
    805             end += offset;
    806             try {
    807                 for (int i = offset + start; i < end; i++) {
    808                     data[index++] = (byte) value[i];
    809                 }
    810             } catch (ArrayIndexOutOfBoundsException ignored) {
    811                 throw failedBoundsCheck(data.length, index, end - start);
    812             }
    813         } else {
    814             throw startEndAndLength(start, end);
    815         }
    816     }
    817 
    818     /**
    819      * Returns a new byte array containing the characters of this string encoded using the
    820      * system's {@link java.nio.charset.Charset#defaultCharset default charset}.
    821      *
    822      * <p>The behavior when this string cannot be represented in the system's default charset
    823      * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android),
    824      * all strings can be encoded.
    825      */
    826     public byte[] getBytes() {
    827         return getBytes(Charset.defaultCharset());
    828     }
    829 
    830     /**
    831      * Returns a new byte array containing the characters of this string encoded using the
    832      * named charset.
    833      *
    834      * <p>The behavior when this string cannot be represented in the named charset
    835      * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control.
    836      *
    837      * @throws UnsupportedEncodingException if the charset is not supported
    838      */
    839     public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
    840         return getBytes(Charset.forNameUEE(charsetName));
    841     }
    842 
    843     /**
    844      * Returns a new byte array containing the characters of this string encoded using the
    845      * given charset.
    846      *
    847      * <p>The behavior when this string cannot be represented in the given charset
    848      * is to replace malformed input and unmappable characters with the charset's default
    849      * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control.
    850      *
    851      * @since 1.6
    852      */
    853     public byte[] getBytes(Charset charset) {
    854         String canonicalCharsetName = charset.name();
    855         if (canonicalCharsetName.equals("UTF-8")) {
    856             return Charsets.toUtf8Bytes(value, offset, count);
    857         } else if (canonicalCharsetName.equals("ISO-8859-1")) {
    858             return Charsets.toIsoLatin1Bytes(value, offset, count);
    859         } else if (canonicalCharsetName.equals("US-ASCII")) {
    860             return Charsets.toAsciiBytes(value, offset, count);
    861         } else if (canonicalCharsetName.equals("UTF-16BE")) {
    862             return Charsets.toBigEndianUtf16Bytes(value, offset, count);
    863         } else {
    864             CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
    865             ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
    866             byte[] bytes = new byte[buffer.limit()];
    867             buffer.get(bytes);
    868             return bytes;
    869         }
    870     }
    871 
    872     /**
    873      * Copies the specified characters in this string to the character array
    874      * starting at the specified offset in the character array.
    875      *
    876      * @param start
    877      *            the starting offset of characters to copy.
    878      * @param end
    879      *            the ending offset of characters to copy.
    880      * @param buffer
    881      *            the destination character array.
    882      * @param index
    883      *            the starting offset in the character array.
    884      * @throws NullPointerException
    885      *             if {@code buffer} is {@code null}.
    886      * @throws IndexOutOfBoundsException
    887      *             if {@code start < 0}, {@code end > length()}, {@code start >
    888      *             end}, {@code index < 0}, {@code end - start > buffer.length -
    889      *             index}
    890      */
    891     public void getChars(int start, int end, char[] buffer, int index) {
    892         // Note: last character not copied!
    893         if (start >= 0 && start <= end && end <= count) {
    894             System.arraycopy(value, start + offset, buffer, index, end - start);
    895         } else {
    896             // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE.
    897             throw startEndAndLength(start, end);
    898         }
    899     }
    900 
    901     /**
    902      * Version of getChars without bounds checks, for use by other classes
    903      * within the java.lang package only.  The caller is responsible for
    904      * ensuring that start >= 0 && start <= end && end <= count.
    905      */
    906     void _getChars(int start, int end, char[] buffer, int index) {
    907         // NOTE last character not copied!
    908         System.arraycopy(value, start + offset, buffer, index, end - start);
    909     }
    910 
    911     @Override public int hashCode() {
    912         int hash = hashCode;
    913         if (hash == 0) {
    914             if (count == 0) {
    915                 return 0;
    916             }
    917             final int end = count + offset;
    918             final char[] chars = value;
    919             for (int i = offset; i < end; ++i) {
    920                 hash = 31*hash + chars[i];
    921             }
    922             hashCode = hash;
    923         }
    924         return hash;
    925     }
    926 
    927     /**
    928      * Searches in this string for the first index of the specified character.
    929      * The search for the character starts at the beginning and moves towards
    930      * the end of this string.
    931      *
    932      * @param c
    933      *            the character to find.
    934      * @return the index in this string of the specified character, -1 if the
    935      *         character isn't found.
    936      */
    937     public int indexOf(int c) {
    938         // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep.
    939         if (c > 0xffff) {
    940             return indexOfSupplementary(c, 0);
    941         }
    942         return fastIndexOf(c, 0);
    943     }
    944 
    945     /**
    946      * Searches in this string for the index of the specified character. The
    947      * search for the character starts at the specified offset and moves towards
    948      * the end of this string.
    949      *
    950      * @param c
    951      *            the character to find.
    952      * @param start
    953      *            the starting offset.
    954      * @return the index in this string of the specified character, -1 if the
    955      *         character isn't found.
    956      */
    957     public int indexOf(int c, int start) {
    958         if (c > 0xffff) {
    959             return indexOfSupplementary(c, start);
    960         }
    961         return fastIndexOf(c, start);
    962     }
    963 
    964     private native int fastIndexOf(int c, int start);
    965 
    966     private int indexOfSupplementary(int c, int start) {
    967         if (!Character.isSupplementaryCodePoint(c)) {
    968             return -1;
    969         }
    970         char[] chars = Character.toChars(c);
    971         String needle = new String(0, chars.length, chars);
    972         return indexOf(needle, start);
    973     }
    974 
    975     /**
    976      * Searches in this string for the first index of the specified string. The
    977      * search for the string starts at the beginning and moves towards the end
    978      * of this string.
    979      *
    980      * @param string
    981      *            the string to find.
    982      * @return the index of the first character of the specified string in this
    983      *         string, -1 if the specified string is not a substring.
    984      * @throws NullPointerException
    985      *             if {@code string} is {@code null}.
    986      */
    987     public int indexOf(String string) {
    988         int start = 0;
    989         int subCount = string.count;
    990         int _count = count;
    991         if (subCount > 0) {
    992             if (subCount > _count) {
    993                 return -1;
    994             }
    995             char[] target = string.value;
    996             int subOffset = string.offset;
    997             char firstChar = target[subOffset];
    998             int end = subOffset + subCount;
    999             while (true) {
   1000                 int i = indexOf(firstChar, start);
   1001                 if (i == -1 || subCount + i > _count) {
   1002                     return -1; // handles subCount > count || start >= count
   1003                 }
   1004                 int o1 = offset + i, o2 = subOffset;
   1005                 char[] _value = value;
   1006                 while (++o2 < end && _value[++o1] == target[o2]) {
   1007                     // Intentionally empty
   1008                 }
   1009                 if (o2 == end) {
   1010                     return i;
   1011                 }
   1012                 start = i + 1;
   1013             }
   1014         }
   1015         return start < _count ? start : _count;
   1016     }
   1017 
   1018     /**
   1019      * Searches in this string for the index of the specified string. The search
   1020      * for the string starts at the specified offset and moves towards the end
   1021      * of this string.
   1022      *
   1023      * @param subString
   1024      *            the string to find.
   1025      * @param start
   1026      *            the starting offset.
   1027      * @return the index of the first character of the specified string in this
   1028      *         string, -1 if the specified string is not a substring.
   1029      * @throws NullPointerException
   1030      *             if {@code subString} is {@code null}.
   1031      */
   1032     public int indexOf(String subString, int start) {
   1033         if (start < 0) {
   1034             start = 0;
   1035         }
   1036         int subCount = subString.count;
   1037         int _count = count;
   1038         if (subCount > 0) {
   1039             if (subCount + start > _count) {
   1040                 return -1;
   1041             }
   1042             char[] target = subString.value;
   1043             int subOffset = subString.offset;
   1044             char firstChar = target[subOffset];
   1045             int end = subOffset + subCount;
   1046             while (true) {
   1047                 int i = indexOf(firstChar, start);
   1048                 if (i == -1 || subCount + i > _count) {
   1049                     return -1; // handles subCount > count || start >= count
   1050                 }
   1051                 int o1 = offset + i, o2 = subOffset;
   1052                 char[] _value = value;
   1053                 while (++o2 < end && _value[++o1] == target[o2]) {
   1054                     // Intentionally empty
   1055                 }
   1056                 if (o2 == end) {
   1057                     return i;
   1058                 }
   1059                 start = i + 1;
   1060             }
   1061         }
   1062         return start < _count ? start : _count;
   1063     }
   1064 
   1065     /**
   1066      * Returns an interned string equal to this string. The VM maintains an internal set of
   1067      * unique strings. All string literals found in loaded classes'
   1068      * constant pools are automatically interned. Manually-interned strings are only weakly
   1069      * referenced, so calling {@code intern} won't lead to unwanted retention.
   1070      *
   1071      * <p>Interning is typically used because it guarantees that for interned strings
   1072      * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to
   1073      * {@code a == b}. (This is not true of non-interned strings.)
   1074      *
   1075      * <p>Many applications find it simpler and more convenient to use an explicit
   1076      * {@link java.util.HashMap} to implement their own pools.
   1077      */
   1078     public native String intern();
   1079 
   1080     /**
   1081      * Returns true if the length of this string is 0.
   1082      *
   1083      * @since 1.6
   1084      */
   1085     public boolean isEmpty() {
   1086         return count == 0;
   1087     }
   1088 
   1089     /**
   1090      * Returns the last index of the code point {@code c}, or -1.
   1091      * The search for the character starts at the end and moves towards the
   1092      * beginning of this string.
   1093      */
   1094     public int lastIndexOf(int c) {
   1095         if (c > 0xffff) {
   1096             return lastIndexOfSupplementary(c, Integer.MAX_VALUE);
   1097         }
   1098         int _count = count;
   1099         int _offset = offset;
   1100         char[] _value = value;
   1101         for (int i = _offset + _count - 1; i >= _offset; --i) {
   1102             if (_value[i] == c) {
   1103                 return i - _offset;
   1104             }
   1105         }
   1106         return -1;
   1107     }
   1108 
   1109     /**
   1110      * Returns the last index of the code point {@code c}, or -1.
   1111      * The search for the character starts at offset {@code start} and moves towards
   1112      * the beginning of this string.
   1113      */
   1114     public int lastIndexOf(int c, int start) {
   1115         if (c > 0xffff) {
   1116             return lastIndexOfSupplementary(c, start);
   1117         }
   1118         int _count = count;
   1119         int _offset = offset;
   1120         char[] _value = value;
   1121         if (start >= 0) {
   1122             if (start >= _count) {
   1123                 start = _count - 1;
   1124             }
   1125             for (int i = _offset + start; i >= _offset; --i) {
   1126                 if (_value[i] == c) {
   1127                     return i - _offset;
   1128                 }
   1129             }
   1130         }
   1131         return -1;
   1132     }
   1133 
   1134     private int lastIndexOfSupplementary(int c, int start) {
   1135         if (!Character.isSupplementaryCodePoint(c)) {
   1136             return -1;
   1137         }
   1138         char[] chars = Character.toChars(c);
   1139         String needle = new String(0, chars.length, chars);
   1140         return lastIndexOf(needle, start);
   1141     }
   1142 
   1143     /**
   1144      * Searches in this string for the last index of the specified string. The
   1145      * search for the string starts at the end and moves towards the beginning
   1146      * of this string.
   1147      *
   1148      * @param string
   1149      *            the string to find.
   1150      * @return the index of the first character of the specified string in this
   1151      *         string, -1 if the specified string is not a substring.
   1152      * @throws NullPointerException
   1153      *             if {@code string} is {@code null}.
   1154      */
   1155     public int lastIndexOf(String string) {
   1156         // Use count instead of count - 1 so lastIndexOf("") returns count
   1157         return lastIndexOf(string, count);
   1158     }
   1159 
   1160     /**
   1161      * Searches in this string for the index of the specified string. The search
   1162      * for the string starts at the specified offset and moves towards the
   1163      * beginning of this string.
   1164      *
   1165      * @param subString
   1166      *            the string to find.
   1167      * @param start
   1168      *            the starting offset.
   1169      * @return the index of the first character of the specified string in this
   1170      *         string , -1 if the specified string is not a substring.
   1171      * @throws NullPointerException
   1172      *             if {@code subString} is {@code null}.
   1173      */
   1174     public int lastIndexOf(String subString, int start) {
   1175         int subCount = subString.count;
   1176         if (subCount <= count && start >= 0) {
   1177             if (subCount > 0) {
   1178                 if (start > count - subCount) {
   1179                     start = count - subCount;
   1180                 }
   1181                 // count and subCount are both >= 1
   1182                 char[] target = subString.value;
   1183                 int subOffset = subString.offset;
   1184                 char firstChar = target[subOffset];
   1185                 int end = subOffset + subCount;
   1186                 while (true) {
   1187                     int i = lastIndexOf(firstChar, start);
   1188                     if (i == -1) {
   1189                         return -1;
   1190                     }
   1191                     int o1 = offset + i, o2 = subOffset;
   1192                     while (++o2 < end && value[++o1] == target[o2]) {
   1193                         // Intentionally empty
   1194                     }
   1195                     if (o2 == end) {
   1196                         return i;
   1197                     }
   1198                     start = i - 1;
   1199                 }
   1200             }
   1201             return start < count ? start : count;
   1202         }
   1203         return -1;
   1204     }
   1205 
   1206     /**
   1207      * Returns the number of characters in this string.
   1208      */
   1209     public int length() {
   1210         return count;
   1211     }
   1212 
   1213     /**
   1214      * Compares the specified string to this string and compares the specified
   1215      * range of characters to determine if they are the same.
   1216      *
   1217      * @param thisStart
   1218      *            the starting offset in this string.
   1219      * @param string
   1220      *            the string to compare.
   1221      * @param start
   1222      *            the starting offset in the specified string.
   1223      * @param length
   1224      *            the number of characters to compare.
   1225      * @return {@code true} if the ranges of characters are equal, {@code false}
   1226      *         otherwise
   1227      * @throws NullPointerException
   1228      *             if {@code string} is {@code null}.
   1229      */
   1230     public boolean regionMatches(int thisStart, String string, int start, int length) {
   1231         if (string == null) {
   1232             throw new NullPointerException("string == null");
   1233         }
   1234         if (start < 0 || string.count - start < length) {
   1235             return false;
   1236         }
   1237         if (thisStart < 0 || count - thisStart < length) {
   1238             return false;
   1239         }
   1240         if (length <= 0) {
   1241             return true;
   1242         }
   1243         int o1 = offset + thisStart, o2 = string.offset + start;
   1244         char[] value1 = value;
   1245         char[] value2 = string.value;
   1246         for (int i = 0; i < length; ++i) {
   1247             if (value1[o1 + i] != value2[o2 + i]) {
   1248                 return false;
   1249             }
   1250         }
   1251         return true;
   1252     }
   1253 
   1254     /**
   1255      * Compares the specified string to this string and compares the specified
   1256      * range of characters to determine if they are the same. When ignoreCase is
   1257      * true, the case of the characters is ignored during the comparison.
   1258      *
   1259      * @param ignoreCase
   1260      *            specifies if case should be ignored.
   1261      * @param thisStart
   1262      *            the starting offset in this string.
   1263      * @param string
   1264      *            the string to compare.
   1265      * @param start
   1266      *            the starting offset in the specified string.
   1267      * @param length
   1268      *            the number of characters to compare.
   1269      * @return {@code true} if the ranges of characters are equal, {@code false}
   1270      *         otherwise.
   1271      * @throws NullPointerException
   1272      *             if {@code string} is {@code null}.
   1273      */
   1274     public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) {
   1275         if (!ignoreCase) {
   1276             return regionMatches(thisStart, string, start, length);
   1277         }
   1278         if (string == null) {
   1279             throw new NullPointerException("string == null");
   1280         }
   1281         if (thisStart < 0 || length > count - thisStart) {
   1282             return false;
   1283         }
   1284         if (start < 0 || length > string.count - start) {
   1285             return false;
   1286         }
   1287         thisStart += offset;
   1288         start += string.offset;
   1289         int end = thisStart + length;
   1290         char[] target = string.value;
   1291         while (thisStart < end) {
   1292             char c1 = value[thisStart++];
   1293             char c2 = target[start++];
   1294             if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
   1295                 return false;
   1296             }
   1297         }
   1298         return true;
   1299     }
   1300 
   1301     /**
   1302      * Copies this string replacing occurrences of the specified character with
   1303      * another character.
   1304      *
   1305      * @param oldChar
   1306      *            the character to replace.
   1307      * @param newChar
   1308      *            the replacement character.
   1309      * @return a new string with occurrences of oldChar replaced by newChar.
   1310      */
   1311     public String replace(char oldChar, char newChar) {
   1312         char[] buffer = value;
   1313         int _offset = offset;
   1314         int _count = count;
   1315 
   1316         int idx = _offset;
   1317         int last = _offset + _count;
   1318         boolean copied = false;
   1319         while (idx < last) {
   1320             if (buffer[idx] == oldChar) {
   1321                 if (!copied) {
   1322                     char[] newBuffer = new char[_count];
   1323                     System.arraycopy(buffer, _offset, newBuffer, 0, _count);
   1324                     buffer = newBuffer;
   1325                     idx -= _offset;
   1326                     last -= _offset;
   1327                     copied = true;
   1328                 }
   1329                 buffer[idx] = newChar;
   1330             }
   1331             idx++;
   1332         }
   1333 
   1334         return copied ? new String(0, count, buffer) : this;
   1335     }
   1336 
   1337     /**
   1338      * Copies this string replacing occurrences of the specified target sequence
   1339      * with another sequence. The string is processed from the beginning to the
   1340      * end.
   1341      *
   1342      * @param target
   1343      *            the sequence to replace.
   1344      * @param replacement
   1345      *            the replacement sequence.
   1346      * @return the resulting string.
   1347      * @throws NullPointerException
   1348      *             if {@code target} or {@code replacement} is {@code null}.
   1349      */
   1350     public String replace(CharSequence target, CharSequence replacement) {
   1351         if (target == null) {
   1352             throw new NullPointerException("target == null");
   1353         }
   1354         if (replacement == null) {
   1355             throw new NullPointerException("replacement == null");
   1356         }
   1357 
   1358         String targetString = target.toString();
   1359         int matchStart = indexOf(targetString, 0);
   1360         if (matchStart == -1) {
   1361             // If there's nothing to replace, return the original string untouched.
   1362             return this;
   1363         }
   1364 
   1365         String replacementString = replacement.toString();
   1366 
   1367         // The empty target matches at the start and end and between each character.
   1368         int targetLength = targetString.length();
   1369         if (targetLength == 0) {
   1370             // The result contains the original 'count' characters, a copy of the
   1371             // replacement string before every one of those characters, and a final
   1372             // copy of the replacement string at the end.
   1373             int resultLength = count + (count + 1) * replacementString.length();
   1374             StringBuilder result = new StringBuilder(resultLength);
   1375             result.append(replacementString);
   1376             int end = offset + count;
   1377             for (int i = offset; i != end; ++i) {
   1378                 result.append(value[i]);
   1379                 result.append(replacementString);
   1380             }
   1381             return result.toString();
   1382         }
   1383 
   1384         StringBuilder result = new StringBuilder(count);
   1385         int searchStart = 0;
   1386         do {
   1387             // Copy characters before the match...
   1388             result.append(value, offset + searchStart, matchStart - searchStart);
   1389             // Insert the replacement...
   1390             result.append(replacementString);
   1391             // And skip over the match...
   1392             searchStart = matchStart + targetLength;
   1393         } while ((matchStart = indexOf(targetString, searchStart)) != -1);
   1394         // Copy any trailing chars...
   1395         result.append(value, offset + searchStart, count - searchStart);
   1396         return result.toString();
   1397     }
   1398 
   1399     /**
   1400      * Compares the specified string to this string to determine if the
   1401      * specified string is a prefix.
   1402      *
   1403      * @param prefix
   1404      *            the string to look for.
   1405      * @return {@code true} if the specified string is a prefix of this string,
   1406      *         {@code false} otherwise
   1407      * @throws NullPointerException
   1408      *             if {@code prefix} is {@code null}.
   1409      */
   1410     public boolean startsWith(String prefix) {
   1411         return startsWith(prefix, 0);
   1412     }
   1413 
   1414     /**
   1415      * Compares the specified string to this string, starting at the specified
   1416      * offset, to determine if the specified string is a prefix.
   1417      *
   1418      * @param prefix
   1419      *            the string to look for.
   1420      * @param start
   1421      *            the starting offset.
   1422      * @return {@code true} if the specified string occurs in this string at the
   1423      *         specified offset, {@code false} otherwise.
   1424      * @throws NullPointerException
   1425      *             if {@code prefix} is {@code null}.
   1426      */
   1427     public boolean startsWith(String prefix, int start) {
   1428         return regionMatches(start, prefix, 0, prefix.count);
   1429     }
   1430 
   1431     /**
   1432      * Returns a string containing a suffix of this string. The returned string
   1433      * shares this string's <a href="#backing_array">backing array</a>.
   1434      *
   1435      * @param start
   1436      *            the offset of the first character.
   1437      * @return a new string containing the characters from start to the end of
   1438      *         the string.
   1439      * @throws IndexOutOfBoundsException
   1440      *             if {@code start < 0} or {@code start > length()}.
   1441      */
   1442     public String substring(int start) {
   1443         if (start == 0) {
   1444             return this;
   1445         }
   1446         if (start >= 0 && start <= count) {
   1447             return new String(offset + start, count - start, value);
   1448         }
   1449         throw indexAndLength(start);
   1450     }
   1451 
   1452     /**
   1453      * Returns a string containing a subsequence of characters from this string.
   1454      * The returned string shares this string's <a href="#backing_array">backing
   1455      * array</a>.
   1456      *
   1457      * @param start
   1458      *            the offset of the first character.
   1459      * @param end
   1460      *            the offset one past the last character.
   1461      * @return a new string containing the characters from start to end - 1
   1462      * @throws IndexOutOfBoundsException
   1463      *             if {@code start < 0}, {@code start > end} or {@code end >
   1464      *             length()}.
   1465      */
   1466     public String substring(int start, int end) {
   1467         if (start == 0 && end == count) {
   1468             return this;
   1469         }
   1470         // NOTE last character not copied!
   1471         // Fast range check.
   1472         if (start >= 0 && start <= end && end <= count) {
   1473             return new String(offset + start, end - start, value);
   1474         }
   1475         throw startEndAndLength(start, end);
   1476     }
   1477 
   1478     /**
   1479      * Returns a new {@code char} array containing a copy of the characters in this string.
   1480      * This is expensive and rarely useful. If you just want to iterate over the characters in
   1481      * the string, use {@link #charAt} instead.
   1482      */
   1483     public char[] toCharArray() {
   1484         char[] buffer = new char[count];
   1485         System.arraycopy(value, offset, buffer, 0, count);
   1486         return buffer;
   1487     }
   1488 
   1489     /**
   1490      * Converts this string to lower case, using the rules of the user's default locale.
   1491      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1492      *
   1493      * @return a new lower case string, or {@code this} if it's already all lower case.
   1494      */
   1495     public String toLowerCase() {
   1496         return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count);
   1497     }
   1498 
   1499     /**
   1500      * Converts this string to lower case, using the rules of {@code locale}.
   1501      *
   1502      * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
   1503      * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
   1504      * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
   1505      * correct case mapping of Greek characters: any locale will do.
   1506      *
   1507      * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
   1508      * for full details of context- and language-specific special cases.
   1509      *
   1510      * @return a new lower case string, or {@code this} if it's already all lower case.
   1511      */
   1512     public String toLowerCase(Locale locale) {
   1513         return CaseMapper.toLowerCase(locale, this, value, offset, count);
   1514     }
   1515 
   1516     /**
   1517      * Returns this string.
   1518      */
   1519     @Override
   1520     public String toString() {
   1521         return this;
   1522     }
   1523 
   1524     /**
   1525      * Converts this this string to upper case, using the rules of the user's default locale.
   1526      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1527      *
   1528      * @return a new upper case string, or {@code this} if it's already all upper case.
   1529      */
   1530     public String toUpperCase() {
   1531         return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
   1532     }
   1533 
   1534     /**
   1535      * Converts this this string to upper case, using the rules of {@code locale}.
   1536      *
   1537      * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
   1538      * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
   1539      * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
   1540      * correct case mapping of Greek characters: any locale will do.
   1541      *
   1542      * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
   1543      * for full details of context- and language-specific special cases.
   1544      *
   1545      * @return a new upper case string, or {@code this} if it's already all upper case.
   1546      */
   1547     public String toUpperCase(Locale locale) {
   1548         return CaseMapper.toUpperCase(locale, this, value, offset, count);
   1549     }
   1550 
   1551     /**
   1552      * Copies this string removing white space characters from the beginning and
   1553      * end of the string.
   1554      *
   1555      * @return a new string with characters <code><= \\u0020</code> removed from
   1556      *         the beginning and the end.
   1557      */
   1558     public String trim() {
   1559         int start = offset, last = offset + count - 1;
   1560         int end = last;
   1561         while ((start <= end) && (value[start] <= ' ')) {
   1562             start++;
   1563         }
   1564         while ((end >= start) && (value[end] <= ' ')) {
   1565             end--;
   1566         }
   1567         if (start == offset && end == last) {
   1568             return this;
   1569         }
   1570         return new String(start, end - start + 1, value);
   1571     }
   1572 
   1573     /**
   1574      * Creates a new string containing the characters in the specified character
   1575      * array. Modifying the character array after creating the string has no
   1576      * effect on the string.
   1577      *
   1578      * @param data
   1579      *            the array of characters.
   1580      * @return the new string.
   1581      * @throws NullPointerException
   1582      *             if {@code data} is {@code null}.
   1583      */
   1584     public static String valueOf(char[] data) {
   1585         return new String(data, 0, data.length);
   1586     }
   1587 
   1588     /**
   1589      * Creates a new string containing the specified characters in the character
   1590      * array. Modifying the character array after creating the string has no
   1591      * effect on the string.
   1592      *
   1593      * @param data
   1594      *            the array of characters.
   1595      * @param start
   1596      *            the starting offset in the character array.
   1597      * @param length
   1598      *            the number of characters to use.
   1599      * @return the new string.
   1600      * @throws IndexOutOfBoundsException
   1601      *             if {@code length < 0}, {@code start < 0} or {@code start +
   1602      *             length > data.length}
   1603      * @throws NullPointerException
   1604      *             if {@code data} is {@code null}.
   1605      */
   1606     public static String valueOf(char[] data, int start, int length) {
   1607         return new String(data, start, length);
   1608     }
   1609 
   1610     /**
   1611      * Converts the specified character to its string representation.
   1612      *
   1613      * @param value
   1614      *            the character.
   1615      * @return the character converted to a string.
   1616      */
   1617     public static String valueOf(char value) {
   1618         String s;
   1619         if (value < 128) {
   1620             s = new String(value, 1, ASCII);
   1621         } else {
   1622             s = new String(0, 1, new char[] { value });
   1623         }
   1624         s.hashCode = value;
   1625         return s;
   1626     }
   1627 
   1628     /**
   1629      * Converts the specified double to its string representation.
   1630      *
   1631      * @param value
   1632      *            the double.
   1633      * @return the double converted to a string.
   1634      */
   1635     public static String valueOf(double value) {
   1636         return Double.toString(value);
   1637     }
   1638 
   1639     /**
   1640      * Converts the specified float to its string representation.
   1641      *
   1642      * @param value
   1643      *            the float.
   1644      * @return the float converted to a string.
   1645      */
   1646     public static String valueOf(float value) {
   1647         return Float.toString(value);
   1648     }
   1649 
   1650     /**
   1651      * Converts the specified integer to its string representation.
   1652      *
   1653      * @param value
   1654      *            the integer.
   1655      * @return the integer converted to a string.
   1656      */
   1657     public static String valueOf(int value) {
   1658         return Integer.toString(value);
   1659     }
   1660 
   1661     /**
   1662      * Converts the specified long to its string representation.
   1663      *
   1664      * @param value
   1665      *            the long.
   1666      * @return the long converted to a string.
   1667      */
   1668     public static String valueOf(long value) {
   1669         return Long.toString(value);
   1670     }
   1671 
   1672     /**
   1673      * Converts the specified object to its string representation. If the object
   1674      * is null return the string {@code "null"}, otherwise use {@code
   1675      * toString()} to get the string representation.
   1676      *
   1677      * @param value
   1678      *            the object.
   1679      * @return the object converted to a string, or the string {@code "null"}.
   1680      */
   1681     public static String valueOf(Object value) {
   1682         return value != null ? value.toString() : "null";
   1683     }
   1684 
   1685     /**
   1686      * Converts the specified boolean to its string representation. When the
   1687      * boolean is {@code true} return {@code "true"}, otherwise return {@code
   1688      * "false"}.
   1689      *
   1690      * @param value
   1691      *            the boolean.
   1692      * @return the boolean converted to a string.
   1693      */
   1694     public static String valueOf(boolean value) {
   1695         return value ? "true" : "false";
   1696     }
   1697 
   1698     /**
   1699      * Returns whether the characters in the StringBuffer {@code strbuf} are the
   1700      * same as those in this string.
   1701      *
   1702      * @param strbuf
   1703      *            the StringBuffer to compare this string to.
   1704      * @return {@code true} if the characters in {@code strbuf} are identical to
   1705      *         those in this string. If they are not, {@code false} will be
   1706      *         returned.
   1707      * @throws NullPointerException
   1708      *             if {@code strbuf} is {@code null}.
   1709      * @since 1.4
   1710      */
   1711     public boolean contentEquals(StringBuffer strbuf) {
   1712         synchronized (strbuf) {
   1713             int size = strbuf.length();
   1714             if (count != size) {
   1715                 return false;
   1716             }
   1717             return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
   1718                     size);
   1719         }
   1720     }
   1721 
   1722     /**
   1723      * Compares a {@code CharSequence} to this {@code String} to determine if
   1724      * their contents are equal.
   1725      *
   1726      * @param cs
   1727      *            the character sequence to compare to.
   1728      * @return {@code true} if equal, otherwise {@code false}
   1729      * @since 1.5
   1730      */
   1731     public boolean contentEquals(CharSequence cs) {
   1732         if (cs == null) {
   1733             throw new NullPointerException("cs == null");
   1734         }
   1735 
   1736         int len = cs.length();
   1737 
   1738         if (len != count) {
   1739             return false;
   1740         }
   1741 
   1742         if (len == 0 && count == 0) {
   1743             return true; // since both are empty strings
   1744         }
   1745 
   1746         return regionMatches(0, cs.toString(), 0, len);
   1747     }
   1748 
   1749     /**
   1750      * Tests whether this string matches the given {@code regularExpression}. This method returns
   1751      * true only if the regular expression matches the <i>entire</i> input string. A common mistake is
   1752      * to assume that this method behaves like {@link #contains}; if you want to match anywhere
   1753      * within the input string, you need to add {@code .*} to the beginning and end of your
   1754      * regular expression. See {@link Pattern#matches}.
   1755      *
   1756      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1757      * efficient to reuse a compiled {@code Pattern}.
   1758      *
   1759      * @throws PatternSyntaxException
   1760      *             if the syntax of the supplied regular expression is not
   1761      *             valid.
   1762      * @throws NullPointerException if {@code regularExpression == null}
   1763      * @since 1.4
   1764      */
   1765     public boolean matches(String regularExpression) {
   1766         return Pattern.matches(regularExpression, this);
   1767     }
   1768 
   1769     /**
   1770      * Replaces all matches for {@code regularExpression} within this string with the given
   1771      * {@code replacement}.
   1772      * See {@link Pattern} for regular expression syntax.
   1773      *
   1774      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1775      * efficient to reuse a compiled {@code Pattern}.
   1776      *
   1777      * @throws PatternSyntaxException
   1778      *             if the syntax of the supplied regular expression is not
   1779      *             valid.
   1780      * @throws NullPointerException if {@code regularExpression == null}
   1781      * @see Pattern
   1782      * @since 1.4
   1783      */
   1784     public String replaceAll(String regularExpression, String replacement) {
   1785         return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
   1786     }
   1787 
   1788     /**
   1789      * Replaces the first match for {@code regularExpression} within this string with the given
   1790      * {@code replacement}.
   1791      * See {@link Pattern} for regular expression syntax.
   1792      *
   1793      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1794      * efficient to reuse a compiled {@code Pattern}.
   1795      *
   1796      * @throws PatternSyntaxException
   1797      *             if the syntax of the supplied regular expression is not
   1798      *             valid.
   1799      * @throws NullPointerException if {@code regularExpression == null}
   1800      * @see Pattern
   1801      * @since 1.4
   1802      */
   1803     public String replaceFirst(String regularExpression, String replacement) {
   1804         return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement);
   1805     }
   1806 
   1807     /**
   1808      * Splits this string using the supplied {@code regularExpression}.
   1809      * Equivalent to {@code split(regularExpression, 0)}.
   1810      * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
   1811      * See {@link Pattern} for regular expression syntax.
   1812      *
   1813      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1814      * efficient to reuse a compiled {@code Pattern}.
   1815      *
   1816      * @throws NullPointerException if {@code regularExpression ==  null}
   1817      * @throws PatternSyntaxException
   1818      *             if the syntax of the supplied regular expression is not
   1819      *             valid.
   1820      * @see Pattern
   1821      * @since 1.4
   1822      */
   1823     public String[] split(String regularExpression) {
   1824         return split(regularExpression, 0);
   1825     }
   1826 
   1827     /**
   1828      * Splits this string using the supplied {@code regularExpression}.
   1829      * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
   1830      * See {@link Pattern} for regular expression syntax.
   1831      *
   1832      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1833      * efficient to reuse a compiled {@code Pattern}.
   1834      *
   1835      * @throws NullPointerException if {@code regularExpression ==  null}
   1836      * @throws PatternSyntaxException
   1837      *             if the syntax of the supplied regular expression is not
   1838      *             valid.
   1839      * @since 1.4
   1840      */
   1841     public String[] split(String regularExpression, int limit) {
   1842         String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
   1843         return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
   1844     }
   1845 
   1846     /**
   1847      * Has the same result as the substring function, but is present so that
   1848      * string may implement the CharSequence interface.
   1849      *
   1850      * @param start
   1851      *            the offset the first character.
   1852      * @param end
   1853      *            the offset of one past the last character to include.
   1854      * @return the subsequence requested.
   1855      * @throws IndexOutOfBoundsException
   1856      *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
   1857      *             {@code end > length()}.
   1858      * @see java.lang.CharSequence#subSequence(int, int)
   1859      * @since 1.4
   1860      */
   1861     public CharSequence subSequence(int start, int end) {
   1862         return substring(start, end);
   1863     }
   1864 
   1865     /**
   1866      * Returns the Unicode code point at the given {@code index}.
   1867      *
   1868      * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()}
   1869      * @see Character#codePointAt(char[], int, int)
   1870      * @since 1.5
   1871      */
   1872     public int codePointAt(int index) {
   1873         if (index < 0 || index >= count) {
   1874             throw indexAndLength(index);
   1875         }
   1876         return Character.codePointAt(value, offset + index, offset + count);
   1877     }
   1878 
   1879     /**
   1880      * Returns the Unicode code point that precedes the given {@code index}.
   1881      *
   1882      * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()}
   1883      * @see Character#codePointBefore(char[], int, int)
   1884      * @since 1.5
   1885      */
   1886     public int codePointBefore(int index) {
   1887         if (index < 1 || index > count) {
   1888             throw indexAndLength(index);
   1889         }
   1890         return Character.codePointBefore(value, offset + index, offset);
   1891     }
   1892 
   1893     /**
   1894      * Calculates the number of Unicode code points between {@code start}
   1895      * and {@code end}.
   1896      *
   1897      * @param start
   1898      *            the inclusive beginning index of the subsequence.
   1899      * @param end
   1900      *            the exclusive end index of the subsequence.
   1901      * @return the number of Unicode code points in the subsequence.
   1902      * @throws IndexOutOfBoundsException
   1903      *         if {@code start < 0 || end > length() || start > end}
   1904      * @see Character#codePointCount(CharSequence, int, int)
   1905      * @since 1.5
   1906      */
   1907     public int codePointCount(int start, int end) {
   1908         if (start < 0 || end > count || start > end) {
   1909             throw startEndAndLength(start, end);
   1910         }
   1911         return Character.codePointCount(value, offset + start, end - start);
   1912     }
   1913 
   1914     /**
   1915      * Determines if this {@code String} contains the sequence of characters in
   1916      * the {@code CharSequence} passed.
   1917      *
   1918      * @param cs
   1919      *            the character sequence to search for.
   1920      * @return {@code true} if the sequence of characters are contained in this
   1921      *         string, otherwise {@code false}.
   1922      * @since 1.5
   1923      */
   1924     public boolean contains(CharSequence cs) {
   1925         if (cs == null) {
   1926             throw new NullPointerException("cs == null");
   1927         }
   1928         return indexOf(cs.toString()) >= 0;
   1929     }
   1930 
   1931     /**
   1932      * Returns the index within this object that is offset from {@code index} by
   1933      * {@code codePointOffset} code points.
   1934      *
   1935      * @param index
   1936      *            the index within this object to calculate the offset from.
   1937      * @param codePointOffset
   1938      *            the number of code points to count.
   1939      * @return the index within this object that is the offset.
   1940      * @throws IndexOutOfBoundsException
   1941      *             if {@code index} is negative or greater than {@code length()}
   1942      *             or if there aren't enough code points before or after {@code
   1943      *             index} to match {@code codePointOffset}.
   1944      * @since 1.5
   1945      */
   1946     public int offsetByCodePoints(int index, int codePointOffset) {
   1947         int s = index + offset;
   1948         int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset);
   1949         return r - offset;
   1950     }
   1951 
   1952     /**
   1953      * Returns a localized formatted string, using the supplied format and arguments,
   1954      * using the user's default locale.
   1955      *
   1956      * <p>If you're formatting a string other than for human
   1957      * consumption, you should use the {@code format(Locale, String, Object...)}
   1958      * overload and supply {@code Locale.US}. See
   1959      * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1960      *
   1961      * @param format the format string (see {@link java.util.Formatter#format})
   1962      * @param args
   1963      *            the list of arguments passed to the formatter. If there are
   1964      *            more arguments than required by {@code format},
   1965      *            additional arguments are ignored.
   1966      * @return the formatted string.
   1967      * @throws NullPointerException if {@code format == null}
   1968      * @throws java.util.IllegalFormatException
   1969      *             if the format is invalid.
   1970      * @since 1.5
   1971      */
   1972     public static String format(String format, Object... args) {
   1973         return format(Locale.getDefault(), format, args);
   1974     }
   1975 
   1976     /**
   1977      * Returns a formatted string, using the supplied format and arguments,
   1978      * localized to the given locale.
   1979      *
   1980      * @param locale
   1981      *            the locale to apply; {@code null} value means no localization.
   1982      * @param format the format string (see {@link java.util.Formatter#format})
   1983      * @param args
   1984      *            the list of arguments passed to the formatter. If there are
   1985      *            more arguments than required by {@code format},
   1986      *            additional arguments are ignored.
   1987      * @return the formatted string.
   1988      * @throws NullPointerException if {@code format == null}
   1989      * @throws java.util.IllegalFormatException
   1990      *             if the format is invalid.
   1991      * @since 1.5
   1992      */
   1993     public static String format(Locale locale, String format, Object... args) {
   1994         if (format == null) {
   1995             throw new NullPointerException("format == null");
   1996         }
   1997         int bufferSize = format.length() + (args == null ? 0 : args.length * 10);
   1998         Formatter f = new Formatter(new StringBuilder(bufferSize), locale);
   1999         return f.format(format, args).toString();
   2000     }
   2001 
   2002     /*
   2003      * An implementation of a String.indexOf that is supposed to perform
   2004      * substantially better than the default algorithm if the "needle" (the
   2005      * subString being searched for) is a constant string.
   2006      *
   2007      * For example, a JIT, upon encountering a call to String.indexOf(String),
   2008      * where the needle is a constant string, may compute the values cache, md2
   2009      * and lastChar, and change the call to the following method.
   2010      */
   2011     @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
   2012     @SuppressWarnings("unused")
   2013     private static int indexOf(String haystackString, String needleString,
   2014             int cache, int md2, char lastChar) {
   2015         char[] haystack = haystackString.value;
   2016         int haystackOffset = haystackString.offset;
   2017         int haystackLength = haystackString.count;
   2018         char[] needle = needleString.value;
   2019         int needleOffset = needleString.offset;
   2020         int needleLength = needleString.count;
   2021         int needleLengthMinus1 = needleLength - 1;
   2022         int haystackEnd = haystackOffset + haystackLength;
   2023         outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
   2024             if (lastChar == haystack[i]) {
   2025                 for (int j = 0; j < needleLengthMinus1; ++j) {
   2026                     if (needle[j + needleOffset] != haystack[i + j
   2027                             - needleLengthMinus1]) {
   2028                         int skip = 1;
   2029                         if ((cache & (1 << haystack[i])) == 0) {
   2030                             skip += j;
   2031                         }
   2032                         i += Math.max(md2, skip);
   2033                         continue outer_loop;
   2034                     }
   2035                 }
   2036                 return i - needleLengthMinus1 - haystackOffset;
   2037             }
   2038 
   2039             if ((cache & (1 << haystack[i])) == 0) {
   2040                 i += needleLengthMinus1;
   2041             }
   2042             i++;
   2043         }
   2044         return -1;
   2045     }
   2046 }
   2047