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