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 native char charAt(int index);
    577 
    578     private StringIndexOutOfBoundsException indexAndLength(int index) {
    579         throw new StringIndexOutOfBoundsException(this, index);
    580     }
    581 
    582     private StringIndexOutOfBoundsException startEndAndLength(int start, int end) {
    583         throw new StringIndexOutOfBoundsException(this, start, end - start);
    584     }
    585 
    586     private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) {
    587         throw new StringIndexOutOfBoundsException(arrayLength, offset, count);
    588     }
    589 
    590     /**
    591      * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode
    592      * case folds, but it's what the RI uses.
    593      */
    594     private char foldCase(char ch) {
    595         if (ch < 128) {
    596             if ('A' <= ch && ch <= 'Z') {
    597                 return (char) (ch + ('a' - 'A'));
    598             }
    599             return ch;
    600         }
    601         return Character.toLowerCase(Character.toUpperCase(ch));
    602     }
    603 
    604     /**
    605      * Compares the specified string to this string using the Unicode values of
    606      * the characters. Returns 0 if the strings contain the same characters in
    607      * the same order. Returns a negative integer if the first non-equal
    608      * character in this string has a Unicode value which is less than the
    609      * Unicode value of the character at the same position in the specified
    610      * string, or if this string is a prefix of the specified string. Returns a
    611      * positive integer if the first non-equal character in this string has a
    612      * Unicode value which is greater than the Unicode value of the character at
    613      * the same position in the specified string, or if the specified string is
    614      * a prefix of this string.
    615      *
    616      * @param string
    617      *            the string to compare.
    618      * @return 0 if the strings are equal, a negative integer if this string is
    619      *         before the specified string, or a positive integer if this string
    620      *         is after the specified string.
    621      * @throws NullPointerException
    622      *             if {@code string} is {@code null}.
    623      */
    624     public native int compareTo(String string);
    625 
    626     /**
    627      * Compares the specified string to this string using the Unicode values of
    628      * the characters, ignoring case differences. Returns 0 if the strings
    629      * contain the same characters in the same order. Returns a negative integer
    630      * if the first non-equal character in this string has a Unicode value which
    631      * is less than the Unicode value of the character at the same position in
    632      * the specified string, or if this string is a prefix of the specified
    633      * string. Returns a positive integer if the first non-equal character in
    634      * this string has a Unicode value which is greater than the Unicode value
    635      * of the character at the same position in the specified string, or if the
    636      * specified string is a prefix of this string.
    637      *
    638      * @param string
    639      *            the string to compare.
    640      * @return 0 if the strings are equal, a negative integer if this string is
    641      *         before the specified string, or a positive integer if this string
    642      *         is after the specified string.
    643      * @throws NullPointerException
    644      *             if {@code string} is {@code null}.
    645      */
    646     public int compareToIgnoreCase(String string) {
    647         int o1 = offset, o2 = string.offset, result;
    648         int end = offset + (count < string.count ? count : string.count);
    649         char c1, c2;
    650         char[] target = string.value;
    651         while (o1 < end) {
    652             if ((c1 = value[o1++]) == (c2 = target[o2++])) {
    653                 continue;
    654             }
    655             c1 = foldCase(c1);
    656             c2 = foldCase(c2);
    657             if ((result = c1 - c2) != 0) {
    658                 return result;
    659             }
    660         }
    661         return count - string.count;
    662     }
    663 
    664     /**
    665      * Concatenates this string and the specified string.
    666      *
    667      * @param string
    668      *            the string to concatenate
    669      * @return a new string which is the concatenation of this string and the
    670      *         specified string.
    671      */
    672     public String concat(String string) {
    673         if (string.count > 0 && count > 0) {
    674             char[] buffer = new char[count + string.count];
    675             System.arraycopy(value, offset, buffer, 0, count);
    676             System.arraycopy(string.value, string.offset, buffer, count, string.count);
    677             return new String(0, buffer.length, buffer);
    678         }
    679         return count == 0 ? string : this;
    680     }
    681 
    682     /**
    683      * Creates a new string containing the characters in the specified character
    684      * array. Modifying the character array after creating the string has no
    685      * effect on the string.
    686      *
    687      * @param data
    688      *            the array of characters.
    689      * @return the new string.
    690      * @throws NullPointerException
    691      *             if {@code data} is {@code null}.
    692      */
    693     public static String copyValueOf(char[] data) {
    694         return new String(data, 0, data.length);
    695     }
    696 
    697     /**
    698      * Creates a new string containing the specified characters in the character
    699      * array. Modifying the character array after creating the string has no
    700      * effect on the string.
    701      *
    702      * @param data
    703      *            the array of characters.
    704      * @param start
    705      *            the starting offset in the character array.
    706      * @param length
    707      *            the number of characters to use.
    708      * @return the new string.
    709      * @throws NullPointerException
    710      *             if {@code data} is {@code null}.
    711      * @throws IndexOutOfBoundsException
    712      *             if {@code length < 0, start < 0} or {@code start + length >
    713      *             data.length}.
    714      */
    715     public static String copyValueOf(char[] data, int start, int length) {
    716         return new String(data, start, length);
    717     }
    718 
    719     /**
    720      * Compares the specified string to this string to determine if the
    721      * specified string is a suffix.
    722      *
    723      * @param suffix
    724      *            the suffix to look for.
    725      * @return {@code true} if the specified string is a suffix of this string,
    726      *         {@code false} otherwise.
    727      * @throws NullPointerException
    728      *             if {@code suffix} is {@code null}.
    729      */
    730     public boolean endsWith(String suffix) {
    731         return regionMatches(count - suffix.count, suffix, 0, suffix.count);
    732     }
    733 
    734     /**
    735      * Compares the specified object to this string and returns true if they are
    736      * equal. The object must be an instance of string with the same characters
    737      * in the same order.
    738      *
    739      * @param object
    740      *            the object to compare.
    741      * @return {@code true} if the specified object is equal to this string,
    742      *         {@code false} otherwise.
    743      * @see #hashCode
    744      */
    745     @Override public native boolean equals(Object object);
    746 
    747     /**
    748      * Compares the specified string to this string ignoring the case of the
    749      * characters and returns true if they are equal.
    750      *
    751      * @param string
    752      *            the string to compare.
    753      * @return {@code true} if the specified string is equal to this string,
    754      *         {@code false} otherwise.
    755      */
    756     @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
    757     public boolean equalsIgnoreCase(String string) {
    758         if (string == this) {
    759             return true;
    760         }
    761         if (string == null || count != string.count) {
    762             return false;
    763         }
    764         int o1 = offset, o2 = string.offset;
    765         int end = offset + count;
    766         char[] target = string.value;
    767         while (o1 < end) {
    768             char c1 = value[o1++];
    769             char c2 = target[o2++];
    770             if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
    771                 return false;
    772             }
    773         }
    774         return true;
    775     }
    776 
    777     /**
    778      * Mangles this string into a byte array by stripping the high order bits from
    779      * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead.
    780      *
    781      * @param start
    782      *            the starting offset of characters to copy.
    783      * @param end
    784      *            the ending offset of characters to copy.
    785      * @param data
    786      *            the destination byte array.
    787      * @param index
    788      *            the starting offset in the destination byte array.
    789      * @throws NullPointerException
    790      *             if {@code data} is {@code null}.
    791      * @throws IndexOutOfBoundsException
    792      *             if {@code start < 0}, {@code end > length()}, {@code index <
    793      *             0} or {@code end - start > data.length - index}.
    794      * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)}
    795      */
    796     @Deprecated
    797     public void getBytes(int start, int end, byte[] data, int index) {
    798         // Note: last character not copied!
    799         if (start >= 0 && start <= end && end <= count) {
    800             end += offset;
    801             try {
    802                 for (int i = offset + start; i < end; i++) {
    803                     data[index++] = (byte) value[i];
    804                 }
    805             } catch (ArrayIndexOutOfBoundsException ignored) {
    806                 throw failedBoundsCheck(data.length, index, end - start);
    807             }
    808         } else {
    809             throw startEndAndLength(start, end);
    810         }
    811     }
    812 
    813     /**
    814      * Returns a new byte array containing the characters of this string encoded using the
    815      * system's {@link java.nio.charset.Charset#defaultCharset default charset}.
    816      *
    817      * <p>The behavior when this string cannot be represented in the system's default charset
    818      * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android),
    819      * all strings can be encoded.
    820      */
    821     public byte[] getBytes() {
    822         return getBytes(Charset.defaultCharset());
    823     }
    824 
    825     /**
    826      * Returns a new byte array containing the characters of this string encoded using the
    827      * named charset.
    828      *
    829      * <p>The behavior when this string cannot be represented in the named charset
    830      * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control.
    831      *
    832      * @throws UnsupportedEncodingException if the charset is not supported
    833      */
    834     public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
    835         return getBytes(Charset.forNameUEE(charsetName));
    836     }
    837 
    838     /**
    839      * Returns a new byte array containing the characters of this string encoded using the
    840      * given charset.
    841      *
    842      * <p>The behavior when this string cannot be represented in the given charset
    843      * is to replace malformed input and unmappable characters with the charset's default
    844      * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control.
    845      *
    846      * @since 1.6
    847      */
    848     public byte[] getBytes(Charset charset) {
    849         String canonicalCharsetName = charset.name();
    850         if (canonicalCharsetName.equals("UTF-8")) {
    851             return Charsets.toUtf8Bytes(value, offset, count);
    852         } else if (canonicalCharsetName.equals("ISO-8859-1")) {
    853             return Charsets.toIsoLatin1Bytes(value, offset, count);
    854         } else if (canonicalCharsetName.equals("US-ASCII")) {
    855             return Charsets.toAsciiBytes(value, offset, count);
    856         } else if (canonicalCharsetName.equals("UTF-16BE")) {
    857             return Charsets.toBigEndianUtf16Bytes(value, offset, count);
    858         } else {
    859             CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
    860             ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
    861             byte[] bytes = new byte[buffer.limit()];
    862             buffer.get(bytes);
    863             return bytes;
    864         }
    865     }
    866 
    867     /**
    868      * Copies the specified characters in this string to the character array
    869      * starting at the specified offset in the character array.
    870      *
    871      * @param start
    872      *            the starting offset of characters to copy.
    873      * @param end
    874      *            the ending offset of characters to copy.
    875      * @param buffer
    876      *            the destination character array.
    877      * @param index
    878      *            the starting offset in the character array.
    879      * @throws NullPointerException
    880      *             if {@code buffer} is {@code null}.
    881      * @throws IndexOutOfBoundsException
    882      *             if {@code start < 0}, {@code end > length()}, {@code start >
    883      *             end}, {@code index < 0}, {@code end - start > buffer.length -
    884      *             index}
    885      */
    886     public void getChars(int start, int end, char[] buffer, int index) {
    887         // Note: last character not copied!
    888         if (start >= 0 && start <= end && end <= count) {
    889             System.arraycopy(value, start + offset, buffer, index, end - start);
    890         } else {
    891             // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE.
    892             throw startEndAndLength(start, end);
    893         }
    894     }
    895 
    896     /**
    897      * Version of getChars without bounds checks, for use by other classes
    898      * within the java.lang package only.  The caller is responsible for
    899      * ensuring that start >= 0 && start <= end && end <= count.
    900      */
    901     void _getChars(int start, int end, char[] buffer, int index) {
    902         // NOTE last character not copied!
    903         System.arraycopy(value, start + offset, buffer, index, end - start);
    904     }
    905 
    906     @Override public int hashCode() {
    907         int hash = hashCode;
    908         if (hash == 0) {
    909             if (count == 0) {
    910                 return 0;
    911             }
    912             final int end = count + offset;
    913             final char[] chars = value;
    914             for (int i = offset; i < end; ++i) {
    915                 hash = 31*hash + chars[i];
    916             }
    917             hashCode = hash;
    918         }
    919         return hash;
    920     }
    921 
    922     /**
    923      * Searches in this string for the first index of the specified character.
    924      * The search for the character starts at the beginning and moves towards
    925      * the end of this string.
    926      *
    927      * @param c
    928      *            the character to find.
    929      * @return the index in this string of the specified character, -1 if the
    930      *         character isn't found.
    931      */
    932     public int indexOf(int c) {
    933         // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep.
    934         if (c > 0xffff) {
    935             return indexOfSupplementary(c, 0);
    936         }
    937         return fastIndexOf(c, 0);
    938     }
    939 
    940     /**
    941      * Searches in this string for the index of the specified character. The
    942      * search for the character starts at the specified offset and moves towards
    943      * the end of this string.
    944      *
    945      * @param c
    946      *            the character to find.
    947      * @param start
    948      *            the starting offset.
    949      * @return the index in this string of the specified character, -1 if the
    950      *         character isn't found.
    951      */
    952     public int indexOf(int c, int start) {
    953         if (c > 0xffff) {
    954             return indexOfSupplementary(c, start);
    955         }
    956         return fastIndexOf(c, start);
    957     }
    958 
    959     private native int fastIndexOf(int c, int start);
    960 
    961     private int indexOfSupplementary(int c, int start) {
    962         if (!Character.isSupplementaryCodePoint(c)) {
    963             return -1;
    964         }
    965         char[] chars = Character.toChars(c);
    966         String needle = new String(0, chars.length, chars);
    967         return indexOf(needle, start);
    968     }
    969 
    970     /**
    971      * Searches in this string for the first index of the specified string. The
    972      * search for the string starts at the beginning and moves towards the end
    973      * of this string.
    974      *
    975      * @param string
    976      *            the string to find.
    977      * @return the index of the first character of the specified string in this
    978      *         string, -1 if the specified string is not a substring.
    979      * @throws NullPointerException
    980      *             if {@code string} is {@code null}.
    981      */
    982     public int indexOf(String string) {
    983         int start = 0;
    984         int subCount = string.count;
    985         int _count = count;
    986         if (subCount > 0) {
    987             if (subCount > _count) {
    988                 return -1;
    989             }
    990             char[] target = string.value;
    991             int subOffset = string.offset;
    992             char firstChar = target[subOffset];
    993             int end = subOffset + subCount;
    994             while (true) {
    995                 int i = indexOf(firstChar, start);
    996                 if (i == -1 || subCount + i > _count) {
    997                     return -1; // handles subCount > count || start >= count
    998                 }
    999                 int o1 = offset + i, o2 = subOffset;
   1000                 char[] _value = value;
   1001                 while (++o2 < end && _value[++o1] == target[o2]) {
   1002                     // Intentionally empty
   1003                 }
   1004                 if (o2 == end) {
   1005                     return i;
   1006                 }
   1007                 start = i + 1;
   1008             }
   1009         }
   1010         return start < _count ? start : _count;
   1011     }
   1012 
   1013     /**
   1014      * Searches in this string for the index of the specified string. The search
   1015      * for the string starts at the specified offset and moves towards the end
   1016      * of this string.
   1017      *
   1018      * @param subString
   1019      *            the string to find.
   1020      * @param start
   1021      *            the starting offset.
   1022      * @return the index of the first character of the specified string in this
   1023      *         string, -1 if the specified string is not a substring.
   1024      * @throws NullPointerException
   1025      *             if {@code subString} is {@code null}.
   1026      */
   1027     public int indexOf(String subString, int start) {
   1028         if (start < 0) {
   1029             start = 0;
   1030         }
   1031         int subCount = subString.count;
   1032         int _count = count;
   1033         if (subCount > 0) {
   1034             if (subCount + start > _count) {
   1035                 return -1;
   1036             }
   1037             char[] target = subString.value;
   1038             int subOffset = subString.offset;
   1039             char firstChar = target[subOffset];
   1040             int end = subOffset + subCount;
   1041             while (true) {
   1042                 int i = indexOf(firstChar, start);
   1043                 if (i == -1 || subCount + i > _count) {
   1044                     return -1; // handles subCount > count || start >= count
   1045                 }
   1046                 int o1 = offset + i, o2 = subOffset;
   1047                 char[] _value = value;
   1048                 while (++o2 < end && _value[++o1] == target[o2]) {
   1049                     // Intentionally empty
   1050                 }
   1051                 if (o2 == end) {
   1052                     return i;
   1053                 }
   1054                 start = i + 1;
   1055             }
   1056         }
   1057         return start < _count ? start : _count;
   1058     }
   1059 
   1060     /**
   1061      * Returns an interned string equal to this string. The VM maintains an internal set of
   1062      * unique strings. All string literals found in loaded classes'
   1063      * constant pools are automatically interned. Manually-interned strings are only weakly
   1064      * referenced, so calling {@code intern} won't lead to unwanted retention.
   1065      *
   1066      * <p>Interning is typically used because it guarantees that for interned strings
   1067      * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to
   1068      * {@code a == b}. (This is not true of non-interned strings.)
   1069      *
   1070      * <p>Many applications find it simpler and more convenient to use an explicit
   1071      * {@link java.util.HashMap} to implement their own pools.
   1072      */
   1073     public native String intern();
   1074 
   1075     /**
   1076      * Returns true if the length of this string is 0.
   1077      *
   1078      * @since 1.6
   1079      */
   1080     public native boolean isEmpty();
   1081 
   1082     /**
   1083      * Returns the last index of the code point {@code c}, or -1.
   1084      * The search for the character starts at the end and moves towards the
   1085      * beginning of this string.
   1086      */
   1087     public int lastIndexOf(int c) {
   1088         if (c > 0xffff) {
   1089             return lastIndexOfSupplementary(c, Integer.MAX_VALUE);
   1090         }
   1091         int _count = count;
   1092         int _offset = offset;
   1093         char[] _value = value;
   1094         for (int i = _offset + _count - 1; i >= _offset; --i) {
   1095             if (_value[i] == c) {
   1096                 return i - _offset;
   1097             }
   1098         }
   1099         return -1;
   1100     }
   1101 
   1102     /**
   1103      * Returns the last index of the code point {@code c}, or -1.
   1104      * The search for the character starts at offset {@code start} and moves towards
   1105      * the beginning of this string.
   1106      */
   1107     public int lastIndexOf(int c, int start) {
   1108         if (c > 0xffff) {
   1109             return lastIndexOfSupplementary(c, start);
   1110         }
   1111         int _count = count;
   1112         int _offset = offset;
   1113         char[] _value = value;
   1114         if (start >= 0) {
   1115             if (start >= _count) {
   1116                 start = _count - 1;
   1117             }
   1118             for (int i = _offset + start; i >= _offset; --i) {
   1119                 if (_value[i] == c) {
   1120                     return i - _offset;
   1121                 }
   1122             }
   1123         }
   1124         return -1;
   1125     }
   1126 
   1127     private int lastIndexOfSupplementary(int c, int start) {
   1128         if (!Character.isSupplementaryCodePoint(c)) {
   1129             return -1;
   1130         }
   1131         char[] chars = Character.toChars(c);
   1132         String needle = new String(0, chars.length, chars);
   1133         return lastIndexOf(needle, start);
   1134     }
   1135 
   1136     /**
   1137      * Searches in this string for the last index of the specified string. The
   1138      * search for the string starts at the end and moves towards the beginning
   1139      * of this string.
   1140      *
   1141      * @param string
   1142      *            the string to find.
   1143      * @return the index of the first character of the specified string in this
   1144      *         string, -1 if the specified string is not a substring.
   1145      * @throws NullPointerException
   1146      *             if {@code string} is {@code null}.
   1147      */
   1148     public int lastIndexOf(String string) {
   1149         // Use count instead of count - 1 so lastIndexOf("") returns count
   1150         return lastIndexOf(string, count);
   1151     }
   1152 
   1153     /**
   1154      * Searches in this string for the index of the specified string. The search
   1155      * for the string starts at the specified offset and moves towards the
   1156      * beginning of this string.
   1157      *
   1158      * @param subString
   1159      *            the string to find.
   1160      * @param start
   1161      *            the starting offset.
   1162      * @return the index of the first character of the specified string in this
   1163      *         string , -1 if the specified string is not a substring.
   1164      * @throws NullPointerException
   1165      *             if {@code subString} is {@code null}.
   1166      */
   1167     public int lastIndexOf(String subString, int start) {
   1168         int subCount = subString.count;
   1169         if (subCount <= count && start >= 0) {
   1170             if (subCount > 0) {
   1171                 if (start > count - subCount) {
   1172                     start = count - subCount;
   1173                 }
   1174                 // count and subCount are both >= 1
   1175                 char[] target = subString.value;
   1176                 int subOffset = subString.offset;
   1177                 char firstChar = target[subOffset];
   1178                 int end = subOffset + subCount;
   1179                 while (true) {
   1180                     int i = lastIndexOf(firstChar, start);
   1181                     if (i == -1) {
   1182                         return -1;
   1183                     }
   1184                     int o1 = offset + i, o2 = subOffset;
   1185                     while (++o2 < end && value[++o1] == target[o2]) {
   1186                         // Intentionally empty
   1187                     }
   1188                     if (o2 == end) {
   1189                         return i;
   1190                     }
   1191                     start = i - 1;
   1192                 }
   1193             }
   1194             return start < count ? start : count;
   1195         }
   1196         return -1;
   1197     }
   1198 
   1199     /**
   1200      * Returns the size of this string.
   1201      *
   1202      * @return the number of characters in this string.
   1203      */
   1204     public native int length();
   1205 
   1206     /**
   1207      * Compares the specified string to this string and compares the specified
   1208      * range of characters to determine if they are the same.
   1209      *
   1210      * @param thisStart
   1211      *            the starting offset in this string.
   1212      * @param string
   1213      *            the string to compare.
   1214      * @param start
   1215      *            the starting offset in the specified string.
   1216      * @param length
   1217      *            the number of characters to compare.
   1218      * @return {@code true} if the ranges of characters are equal, {@code false}
   1219      *         otherwise
   1220      * @throws NullPointerException
   1221      *             if {@code string} is {@code null}.
   1222      */
   1223     public boolean regionMatches(int thisStart, String string, int start, int length) {
   1224         if (string == null) {
   1225             throw new NullPointerException("string == null");
   1226         }
   1227         if (start < 0 || string.count - start < length) {
   1228             return false;
   1229         }
   1230         if (thisStart < 0 || count - thisStart < length) {
   1231             return false;
   1232         }
   1233         if (length <= 0) {
   1234             return true;
   1235         }
   1236         int o1 = offset + thisStart, o2 = string.offset + start;
   1237         char[] value1 = value;
   1238         char[] value2 = string.value;
   1239         for (int i = 0; i < length; ++i) {
   1240             if (value1[o1 + i] != value2[o2 + i]) {
   1241                 return false;
   1242             }
   1243         }
   1244         return true;
   1245     }
   1246 
   1247     /**
   1248      * Compares the specified string to this string and compares the specified
   1249      * range of characters to determine if they are the same. When ignoreCase is
   1250      * true, the case of the characters is ignored during the comparison.
   1251      *
   1252      * @param ignoreCase
   1253      *            specifies if case should be ignored.
   1254      * @param thisStart
   1255      *            the starting offset in this string.
   1256      * @param string
   1257      *            the string to compare.
   1258      * @param start
   1259      *            the starting offset in the specified string.
   1260      * @param length
   1261      *            the number of characters to compare.
   1262      * @return {@code true} if the ranges of characters are equal, {@code false}
   1263      *         otherwise.
   1264      * @throws NullPointerException
   1265      *             if {@code string} is {@code null}.
   1266      */
   1267     public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) {
   1268         if (!ignoreCase) {
   1269             return regionMatches(thisStart, string, start, length);
   1270         }
   1271         if (string == null) {
   1272             throw new NullPointerException("string == null");
   1273         }
   1274         if (thisStart < 0 || length > count - thisStart) {
   1275             return false;
   1276         }
   1277         if (start < 0 || length > string.count - start) {
   1278             return false;
   1279         }
   1280         thisStart += offset;
   1281         start += string.offset;
   1282         int end = thisStart + length;
   1283         char[] target = string.value;
   1284         while (thisStart < end) {
   1285             char c1 = value[thisStart++];
   1286             char c2 = target[start++];
   1287             if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
   1288                 return false;
   1289             }
   1290         }
   1291         return true;
   1292     }
   1293 
   1294     /**
   1295      * Copies this string replacing occurrences of the specified character with
   1296      * another character.
   1297      *
   1298      * @param oldChar
   1299      *            the character to replace.
   1300      * @param newChar
   1301      *            the replacement character.
   1302      * @return a new string with occurrences of oldChar replaced by newChar.
   1303      */
   1304     public String replace(char oldChar, char newChar) {
   1305         char[] buffer = value;
   1306         int _offset = offset;
   1307         int _count = count;
   1308 
   1309         int idx = _offset;
   1310         int last = _offset + _count;
   1311         boolean copied = false;
   1312         while (idx < last) {
   1313             if (buffer[idx] == oldChar) {
   1314                 if (!copied) {
   1315                     char[] newBuffer = new char[_count];
   1316                     System.arraycopy(buffer, _offset, newBuffer, 0, _count);
   1317                     buffer = newBuffer;
   1318                     idx -= _offset;
   1319                     last -= _offset;
   1320                     copied = true;
   1321                 }
   1322                 buffer[idx] = newChar;
   1323             }
   1324             idx++;
   1325         }
   1326 
   1327         return copied ? new String(0, count, buffer) : this;
   1328     }
   1329 
   1330     /**
   1331      * Copies this string replacing occurrences of the specified target sequence
   1332      * with another sequence. The string is processed from the beginning to the
   1333      * end.
   1334      *
   1335      * @param target
   1336      *            the sequence to replace.
   1337      * @param replacement
   1338      *            the replacement sequence.
   1339      * @return the resulting string.
   1340      * @throws NullPointerException
   1341      *             if {@code target} or {@code replacement} is {@code null}.
   1342      */
   1343     public String replace(CharSequence target, CharSequence replacement) {
   1344         if (target == null) {
   1345             throw new NullPointerException("target == null");
   1346         }
   1347         if (replacement == null) {
   1348             throw new NullPointerException("replacement == null");
   1349         }
   1350 
   1351         String targetString = target.toString();
   1352         int matchStart = indexOf(targetString, 0);
   1353         if (matchStart == -1) {
   1354             // If there's nothing to replace, return the original string untouched.
   1355             return this;
   1356         }
   1357 
   1358         String replacementString = replacement.toString();
   1359 
   1360         // The empty target matches at the start and end and between each character.
   1361         int targetLength = targetString.length();
   1362         if (targetLength == 0) {
   1363             int resultLength = (count + 2) * replacementString.length();
   1364             StringBuilder result = new StringBuilder(resultLength);
   1365             result.append(replacementString);
   1366             for (int i = offset; i < count; ++i) {
   1367                 result.append(value[i]);
   1368                 result.append(replacementString);
   1369             }
   1370             return result.toString();
   1371         }
   1372 
   1373         StringBuilder result = new StringBuilder(count);
   1374         int searchStart = 0;
   1375         do {
   1376             // Copy characters before the match...
   1377             result.append(value, offset + searchStart, matchStart - searchStart);
   1378             // Insert the replacement...
   1379             result.append(replacementString);
   1380             // And skip over the match...
   1381             searchStart = matchStart + targetLength;
   1382         } while ((matchStart = indexOf(targetString, searchStart)) != -1);
   1383         // Copy any trailing chars...
   1384         result.append(value, offset + searchStart, count - searchStart);
   1385         return result.toString();
   1386     }
   1387 
   1388     /**
   1389      * Compares the specified string to this string to determine if the
   1390      * specified string is a prefix.
   1391      *
   1392      * @param prefix
   1393      *            the string to look for.
   1394      * @return {@code true} if the specified string is a prefix of this string,
   1395      *         {@code false} otherwise
   1396      * @throws NullPointerException
   1397      *             if {@code prefix} is {@code null}.
   1398      */
   1399     public boolean startsWith(String prefix) {
   1400         return startsWith(prefix, 0);
   1401     }
   1402 
   1403     /**
   1404      * Compares the specified string to this string, starting at the specified
   1405      * offset, to determine if the specified string is a prefix.
   1406      *
   1407      * @param prefix
   1408      *            the string to look for.
   1409      * @param start
   1410      *            the starting offset.
   1411      * @return {@code true} if the specified string occurs in this string at the
   1412      *         specified offset, {@code false} otherwise.
   1413      * @throws NullPointerException
   1414      *             if {@code prefix} is {@code null}.
   1415      */
   1416     public boolean startsWith(String prefix, int start) {
   1417         return regionMatches(start, prefix, 0, prefix.count);
   1418     }
   1419 
   1420     /**
   1421      * Returns a string containing a suffix of this string. The returned string
   1422      * shares this string's <a href="#backing_array">backing array</a>.
   1423      *
   1424      * @param start
   1425      *            the offset of the first character.
   1426      * @return a new string containing the characters from start to the end of
   1427      *         the string.
   1428      * @throws IndexOutOfBoundsException
   1429      *             if {@code start < 0} or {@code start > length()}.
   1430      */
   1431     public String substring(int start) {
   1432         if (start == 0) {
   1433             return this;
   1434         }
   1435         if (start >= 0 && start <= count) {
   1436             return new String(offset + start, count - start, value);
   1437         }
   1438         throw indexAndLength(start);
   1439     }
   1440 
   1441     /**
   1442      * Returns a string containing a subsequence of characters from this string.
   1443      * The returned string shares this string's <a href="#backing_array">backing
   1444      * array</a>.
   1445      *
   1446      * @param start
   1447      *            the offset of the first character.
   1448      * @param end
   1449      *            the offset one past the last character.
   1450      * @return a new string containing the characters from start to end - 1
   1451      * @throws IndexOutOfBoundsException
   1452      *             if {@code start < 0}, {@code start > end} or {@code end >
   1453      *             length()}.
   1454      */
   1455     public String substring(int start, int end) {
   1456         if (start == 0 && end == count) {
   1457             return this;
   1458         }
   1459         // NOTE last character not copied!
   1460         // Fast range check.
   1461         if (start >= 0 && start <= end && end <= count) {
   1462             return new String(offset + start, end - start, value);
   1463         }
   1464         throw startEndAndLength(start, end);
   1465     }
   1466 
   1467     /**
   1468      * Copies the characters in this string to a character array.
   1469      *
   1470      * @return a character array containing the characters of this string.
   1471      */
   1472     public char[] toCharArray() {
   1473         char[] buffer = new char[count];
   1474         System.arraycopy(value, offset, buffer, 0, count);
   1475         return buffer;
   1476     }
   1477 
   1478     /**
   1479      * Converts this string to lower case, using the rules of the user's default locale.
   1480      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1481      *
   1482      * @return a new lower case string, or {@code this} if it's already all lower case.
   1483      */
   1484     public String toLowerCase() {
   1485         return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count);
   1486     }
   1487 
   1488     /**
   1489      * Converts this string to lower case, using the rules of {@code locale}.
   1490      *
   1491      * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
   1492      * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
   1493      * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
   1494      * correct case mapping of Greek characters: any locale will do.
   1495      *
   1496      * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
   1497      * for full details of context- and language-specific special cases.
   1498      *
   1499      * @return a new lower case string, or {@code this} if it's already all lower case.
   1500      */
   1501     public String toLowerCase(Locale locale) {
   1502         return CaseMapper.toLowerCase(locale, this, value, offset, count);
   1503     }
   1504 
   1505     /**
   1506      * Returns this string.
   1507      */
   1508     @Override
   1509     public String toString() {
   1510         return this;
   1511     }
   1512 
   1513     /**
   1514      * Converts this this string to upper case, using the rules of the user's default locale.
   1515      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1516      *
   1517      * @return a new upper case string, or {@code this} if it's already all upper case.
   1518      */
   1519     public String toUpperCase() {
   1520         return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
   1521     }
   1522 
   1523     /**
   1524      * Converts this this string to upper case, using the rules of {@code locale}.
   1525      *
   1526      * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
   1527      * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
   1528      * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
   1529      * correct case mapping of Greek characters: any locale will do.
   1530      *
   1531      * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
   1532      * for full details of context- and language-specific special cases.
   1533      *
   1534      * @return a new upper case string, or {@code this} if it's already all upper case.
   1535      */
   1536     public String toUpperCase(Locale locale) {
   1537         return CaseMapper.toUpperCase(locale, this, value, offset, count);
   1538     }
   1539 
   1540     /**
   1541      * Copies this string removing white space characters from the beginning and
   1542      * end of the string.
   1543      *
   1544      * @return a new string with characters <code><= \\u0020</code> removed from
   1545      *         the beginning and the end.
   1546      */
   1547     public String trim() {
   1548         int start = offset, last = offset + count - 1;
   1549         int end = last;
   1550         while ((start <= end) && (value[start] <= ' ')) {
   1551             start++;
   1552         }
   1553         while ((end >= start) && (value[end] <= ' ')) {
   1554             end--;
   1555         }
   1556         if (start == offset && end == last) {
   1557             return this;
   1558         }
   1559         return new String(start, end - start + 1, value);
   1560     }
   1561 
   1562     /**
   1563      * Creates a new string containing the characters in the specified character
   1564      * array. Modifying the character array after creating the string has no
   1565      * effect on the string.
   1566      *
   1567      * @param data
   1568      *            the array of characters.
   1569      * @return the new string.
   1570      * @throws NullPointerException
   1571      *             if {@code data} is {@code null}.
   1572      */
   1573     public static String valueOf(char[] data) {
   1574         return new String(data, 0, data.length);
   1575     }
   1576 
   1577     /**
   1578      * Creates a new string containing the specified characters in the character
   1579      * array. Modifying the character array after creating the string has no
   1580      * effect on the string.
   1581      *
   1582      * @param data
   1583      *            the array of characters.
   1584      * @param start
   1585      *            the starting offset in the character array.
   1586      * @param length
   1587      *            the number of characters to use.
   1588      * @return the new string.
   1589      * @throws IndexOutOfBoundsException
   1590      *             if {@code length < 0}, {@code start < 0} or {@code start +
   1591      *             length > data.length}
   1592      * @throws NullPointerException
   1593      *             if {@code data} is {@code null}.
   1594      */
   1595     public static String valueOf(char[] data, int start, int length) {
   1596         return new String(data, start, length);
   1597     }
   1598 
   1599     /**
   1600      * Converts the specified character to its string representation.
   1601      *
   1602      * @param value
   1603      *            the character.
   1604      * @return the character converted to a string.
   1605      */
   1606     public static String valueOf(char value) {
   1607         String s;
   1608         if (value < 128) {
   1609             s = new String(value, 1, ASCII);
   1610         } else {
   1611             s = new String(0, 1, new char[] { value });
   1612         }
   1613         s.hashCode = value;
   1614         return s;
   1615     }
   1616 
   1617     /**
   1618      * Converts the specified double to its string representation.
   1619      *
   1620      * @param value
   1621      *            the double.
   1622      * @return the double converted to a string.
   1623      */
   1624     public static String valueOf(double value) {
   1625         return Double.toString(value);
   1626     }
   1627 
   1628     /**
   1629      * Converts the specified float to its string representation.
   1630      *
   1631      * @param value
   1632      *            the float.
   1633      * @return the float converted to a string.
   1634      */
   1635     public static String valueOf(float value) {
   1636         return Float.toString(value);
   1637     }
   1638 
   1639     /**
   1640      * Converts the specified integer to its string representation.
   1641      *
   1642      * @param value
   1643      *            the integer.
   1644      * @return the integer converted to a string.
   1645      */
   1646     public static String valueOf(int value) {
   1647         return Integer.toString(value);
   1648     }
   1649 
   1650     /**
   1651      * Converts the specified long to its string representation.
   1652      *
   1653      * @param value
   1654      *            the long.
   1655      * @return the long converted to a string.
   1656      */
   1657     public static String valueOf(long value) {
   1658         return Long.toString(value);
   1659     }
   1660 
   1661     /**
   1662      * Converts the specified object to its string representation. If the object
   1663      * is null return the string {@code "null"}, otherwise use {@code
   1664      * toString()} to get the string representation.
   1665      *
   1666      * @param value
   1667      *            the object.
   1668      * @return the object converted to a string, or the string {@code "null"}.
   1669      */
   1670     public static String valueOf(Object value) {
   1671         return value != null ? value.toString() : "null";
   1672     }
   1673 
   1674     /**
   1675      * Converts the specified boolean to its string representation. When the
   1676      * boolean is {@code true} return {@code "true"}, otherwise return {@code
   1677      * "false"}.
   1678      *
   1679      * @param value
   1680      *            the boolean.
   1681      * @return the boolean converted to a string.
   1682      */
   1683     public static String valueOf(boolean value) {
   1684         return value ? "true" : "false";
   1685     }
   1686 
   1687     /**
   1688      * Returns whether the characters in the StringBuffer {@code strbuf} are the
   1689      * same as those in this string.
   1690      *
   1691      * @param strbuf
   1692      *            the StringBuffer to compare this string to.
   1693      * @return {@code true} if the characters in {@code strbuf} are identical to
   1694      *         those in this string. If they are not, {@code false} will be
   1695      *         returned.
   1696      * @throws NullPointerException
   1697      *             if {@code strbuf} is {@code null}.
   1698      * @since 1.4
   1699      */
   1700     public boolean contentEquals(StringBuffer strbuf) {
   1701         synchronized (strbuf) {
   1702             int size = strbuf.length();
   1703             if (count != size) {
   1704                 return false;
   1705             }
   1706             return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
   1707                     size);
   1708         }
   1709     }
   1710 
   1711     /**
   1712      * Compares a {@code CharSequence} to this {@code String} to determine if
   1713      * their contents are equal.
   1714      *
   1715      * @param cs
   1716      *            the character sequence to compare to.
   1717      * @return {@code true} if equal, otherwise {@code false}
   1718      * @since 1.5
   1719      */
   1720     public boolean contentEquals(CharSequence cs) {
   1721         if (cs == null) {
   1722             throw new NullPointerException("cs == null");
   1723         }
   1724 
   1725         int len = cs.length();
   1726 
   1727         if (len != count) {
   1728             return false;
   1729         }
   1730 
   1731         if (len == 0 && count == 0) {
   1732             return true; // since both are empty strings
   1733         }
   1734 
   1735         return regionMatches(0, cs.toString(), 0, len);
   1736     }
   1737 
   1738     /**
   1739      * Tests whether this string matches the given {@code regularExpression}. This method returns
   1740      * true only if the regular expression matches the <i>entire</i> input string. A common mistake is
   1741      * to assume that this method behaves like {@link #contains}; if you want to match anywhere
   1742      * within the input string, you need to add {@code .*} to the beginning and end of your
   1743      * regular expression. See {@link Pattern#matches}.
   1744      *
   1745      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1746      * efficient to reuse a compiled {@code Pattern}.
   1747      *
   1748      * @throws PatternSyntaxException
   1749      *             if the syntax of the supplied regular expression is not
   1750      *             valid.
   1751      * @throws NullPointerException if {@code regularExpression == null}
   1752      * @since 1.4
   1753      */
   1754     public boolean matches(String regularExpression) {
   1755         return Pattern.matches(regularExpression, this);
   1756     }
   1757 
   1758     /**
   1759      * Replaces all matches for {@code regularExpression} within this string with the given
   1760      * {@code replacement}.
   1761      * See {@link Pattern} for regular expression syntax.
   1762      *
   1763      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1764      * efficient to reuse a compiled {@code Pattern}.
   1765      *
   1766      * @throws PatternSyntaxException
   1767      *             if the syntax of the supplied regular expression is not
   1768      *             valid.
   1769      * @throws NullPointerException if {@code regularExpression == null}
   1770      * @see Pattern
   1771      * @since 1.4
   1772      */
   1773     public String replaceAll(String regularExpression, String replacement) {
   1774         return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
   1775     }
   1776 
   1777     /**
   1778      * Replaces the first match for {@code regularExpression} within this string with the given
   1779      * {@code replacement}.
   1780      * See {@link Pattern} for regular expression syntax.
   1781      *
   1782      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1783      * efficient to reuse a compiled {@code Pattern}.
   1784      *
   1785      * @throws PatternSyntaxException
   1786      *             if the syntax of the supplied regular expression is not
   1787      *             valid.
   1788      * @throws NullPointerException if {@code regularExpression == null}
   1789      * @see Pattern
   1790      * @since 1.4
   1791      */
   1792     public String replaceFirst(String regularExpression, String replacement) {
   1793         return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement);
   1794     }
   1795 
   1796     /**
   1797      * Splits this string using the supplied {@code regularExpression}.
   1798      * Equivalent to {@code split(regularExpression, 0)}.
   1799      * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
   1800      * See {@link Pattern} for regular expression syntax.
   1801      *
   1802      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1803      * efficient to reuse a compiled {@code Pattern}.
   1804      *
   1805      * @throws NullPointerException if {@code regularExpression ==  null}
   1806      * @throws PatternSyntaxException
   1807      *             if the syntax of the supplied regular expression is not
   1808      *             valid.
   1809      * @see Pattern
   1810      * @since 1.4
   1811      */
   1812     public String[] split(String regularExpression) {
   1813         return split(regularExpression, 0);
   1814     }
   1815 
   1816     /**
   1817      * Splits this string using the supplied {@code regularExpression}.
   1818      * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
   1819      * See {@link Pattern} for regular expression syntax.
   1820      *
   1821      * <p>If the same regular expression is to be used for multiple operations, it may be more
   1822      * efficient to reuse a compiled {@code Pattern}.
   1823      *
   1824      * @throws NullPointerException if {@code regularExpression ==  null}
   1825      * @throws PatternSyntaxException
   1826      *             if the syntax of the supplied regular expression is not
   1827      *             valid.
   1828      * @since 1.4
   1829      */
   1830     public String[] split(String regularExpression, int limit) {
   1831         String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
   1832         return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
   1833     }
   1834 
   1835     /**
   1836      * Has the same result as the substring function, but is present so that
   1837      * string may implement the CharSequence interface.
   1838      *
   1839      * @param start
   1840      *            the offset the first character.
   1841      * @param end
   1842      *            the offset of one past the last character to include.
   1843      * @return the subsequence requested.
   1844      * @throws IndexOutOfBoundsException
   1845      *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
   1846      *             {@code end > length()}.
   1847      * @see java.lang.CharSequence#subSequence(int, int)
   1848      * @since 1.4
   1849      */
   1850     public CharSequence subSequence(int start, int end) {
   1851         return substring(start, end);
   1852     }
   1853 
   1854     /**
   1855      * Returns the Unicode code point at the given {@code index}.
   1856      *
   1857      * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()}
   1858      * @see Character#codePointAt(char[], int, int)
   1859      * @since 1.5
   1860      */
   1861     public int codePointAt(int index) {
   1862         if (index < 0 || index >= count) {
   1863             throw indexAndLength(index);
   1864         }
   1865         return Character.codePointAt(value, offset + index, offset + count);
   1866     }
   1867 
   1868     /**
   1869      * Returns the Unicode code point that precedes the given {@code index}.
   1870      *
   1871      * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()}
   1872      * @see Character#codePointBefore(char[], int, int)
   1873      * @since 1.5
   1874      */
   1875     public int codePointBefore(int index) {
   1876         if (index < 1 || index > count) {
   1877             throw indexAndLength(index);
   1878         }
   1879         return Character.codePointBefore(value, offset + index, offset);
   1880     }
   1881 
   1882     /**
   1883      * Calculates the number of Unicode code points between {@code start}
   1884      * and {@code end}.
   1885      *
   1886      * @param start
   1887      *            the inclusive beginning index of the subsequence.
   1888      * @param end
   1889      *            the exclusive end index of the subsequence.
   1890      * @return the number of Unicode code points in the subsequence.
   1891      * @throws IndexOutOfBoundsException
   1892      *         if {@code start < 0 || end > length() || start > end}
   1893      * @see Character#codePointCount(CharSequence, int, int)
   1894      * @since 1.5
   1895      */
   1896     public int codePointCount(int start, int end) {
   1897         if (start < 0 || end > count || start > end) {
   1898             throw startEndAndLength(start, end);
   1899         }
   1900         return Character.codePointCount(value, offset + start, end - start);
   1901     }
   1902 
   1903     /**
   1904      * Determines if this {@code String} contains the sequence of characters in
   1905      * the {@code CharSequence} passed.
   1906      *
   1907      * @param cs
   1908      *            the character sequence to search for.
   1909      * @return {@code true} if the sequence of characters are contained in this
   1910      *         string, otherwise {@code false}.
   1911      * @since 1.5
   1912      */
   1913     public boolean contains(CharSequence cs) {
   1914         if (cs == null) {
   1915             throw new NullPointerException("cs == null");
   1916         }
   1917         return indexOf(cs.toString()) >= 0;
   1918     }
   1919 
   1920     /**
   1921      * Returns the index within this object that is offset from {@code index} by
   1922      * {@code codePointOffset} code points.
   1923      *
   1924      * @param index
   1925      *            the index within this object to calculate the offset from.
   1926      * @param codePointOffset
   1927      *            the number of code points to count.
   1928      * @return the index within this object that is the offset.
   1929      * @throws IndexOutOfBoundsException
   1930      *             if {@code index} is negative or greater than {@code length()}
   1931      *             or if there aren't enough code points before or after {@code
   1932      *             index} to match {@code codePointOffset}.
   1933      * @since 1.5
   1934      */
   1935     public int offsetByCodePoints(int index, int codePointOffset) {
   1936         int s = index + offset;
   1937         int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset);
   1938         return r - offset;
   1939     }
   1940 
   1941     /**
   1942      * Returns a localized formatted string, using the supplied format and arguments,
   1943      * using the user's default locale.
   1944      *
   1945      * <p>If you're formatting a string other than for human
   1946      * consumption, you should use the {@code format(Locale, String, Object...)}
   1947      * overload and supply {@code Locale.US}. See
   1948      * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
   1949      *
   1950      * @param format the format string (see {@link java.util.Formatter#format})
   1951      * @param args
   1952      *            the list of arguments passed to the formatter. If there are
   1953      *            more arguments than required by {@code format},
   1954      *            additional arguments are ignored.
   1955      * @return the formatted string.
   1956      * @throws NullPointerException if {@code format == null}
   1957      * @throws java.util.IllegalFormatException
   1958      *             if the format is invalid.
   1959      * @since 1.5
   1960      */
   1961     public static String format(String format, Object... args) {
   1962         return format(Locale.getDefault(), format, args);
   1963     }
   1964 
   1965     /**
   1966      * Returns a formatted string, using the supplied format and arguments,
   1967      * localized to the given locale.
   1968      *
   1969      * @param locale
   1970      *            the locale to apply; {@code null} value means no localization.
   1971      * @param format the format string (see {@link java.util.Formatter#format})
   1972      * @param args
   1973      *            the list of arguments passed to the formatter. If there are
   1974      *            more arguments than required by {@code format},
   1975      *            additional arguments are ignored.
   1976      * @return the formatted string.
   1977      * @throws NullPointerException if {@code format == null}
   1978      * @throws java.util.IllegalFormatException
   1979      *             if the format is invalid.
   1980      * @since 1.5
   1981      */
   1982     public static String format(Locale locale, String format, Object... args) {
   1983         if (format == null) {
   1984             throw new NullPointerException("format == null");
   1985         }
   1986         int bufferSize = format.length() + (args == null ? 0 : args.length * 10);
   1987         Formatter f = new Formatter(new StringBuilder(bufferSize), locale);
   1988         return f.format(format, args).toString();
   1989     }
   1990 
   1991     /*
   1992      * An implementation of a String.indexOf that is supposed to perform
   1993      * substantially better than the default algorithm if the "needle" (the
   1994      * subString being searched for) is a constant string.
   1995      *
   1996      * For example, a JIT, upon encountering a call to String.indexOf(String),
   1997      * where the needle is a constant string, may compute the values cache, md2
   1998      * and lastChar, and change the call to the following method.
   1999      */
   2000     @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
   2001     @SuppressWarnings("unused")
   2002     private static int indexOf(String haystackString, String needleString,
   2003             int cache, int md2, char lastChar) {
   2004         char[] haystack = haystackString.value;
   2005         int haystackOffset = haystackString.offset;
   2006         int haystackLength = haystackString.count;
   2007         char[] needle = needleString.value;
   2008         int needleOffset = needleString.offset;
   2009         int needleLength = needleString.count;
   2010         int needleLengthMinus1 = needleLength - 1;
   2011         int haystackEnd = haystackOffset + haystackLength;
   2012         outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
   2013             if (lastChar == haystack[i]) {
   2014                 for (int j = 0; j < needleLengthMinus1; ++j) {
   2015                     if (needle[j + needleOffset] != haystack[i + j
   2016                             - needleLengthMinus1]) {
   2017                         int skip = 1;
   2018                         if ((cache & (1 << haystack[i])) == 0) {
   2019                             skip += j;
   2020                         }
   2021                         i += Math.max(md2, skip);
   2022                         continue outer_loop;
   2023                     }
   2024                 }
   2025                 return i - needleLengthMinus1 - haystackOffset;
   2026             }
   2027 
   2028             if ((cache & (1 << haystack[i])) == 0) {
   2029                 i += needleLengthMinus1;
   2030             }
   2031             i++;
   2032         }
   2033         return -1;
   2034     }
   2035 }
   2036