1 /*
2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.lang;
27 
28 import java.util.Arrays;
29 import java.util.Spliterator;
30 import java.util.function.Consumer;
31 import java.util.function.IntConsumer;
32 import java.util.stream.Stream;
33 import java.util.stream.StreamSupport;
34 import jdk.internal.HotSpotIntrinsicCandidate;
35 import jdk.internal.vm.annotation.IntrinsicCandidate;
36 
37 import static java.lang.String.UTF16;
38 import static java.lang.String.LATIN1;
39 
40 public final class StringUTF16 {
41 
newBytesFor(int len)42     public static byte[] newBytesFor(int len) {
43         if (len < 0) {
44             throw new NegativeArraySizeException();
45         }
46         if (len > MAX_LENGTH) {
47             throw new OutOfMemoryError("UTF16 String size is " + len +
48                                        ", should be less than " + MAX_LENGTH);
49         }
50         return new byte[len << 1];
51     }
52 
53     @HotSpotIntrinsicCandidate
54     // intrinsic performs no bounds checks
putChar(byte[] val, int index, int c)55     static void putChar(byte[] val, int index, int c) {
56         assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
57         index <<= 1;
58         val[index++] = (byte)(c >> HI_BYTE_SHIFT);
59         val[index]   = (byte)(c >> LO_BYTE_SHIFT);
60     }
61 
62     @HotSpotIntrinsicCandidate
63     // intrinsic performs no bounds checks
getChar(byte[] val, int index)64     public static char getChar(byte[] val, int index) {
65         assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
66         index <<= 1;
67         return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
68                       ((val[index]   & 0xff) << LO_BYTE_SHIFT));
69     }
70 
71     // BEGIN Android-added: Pass String instead of byte[]; implement in terms of charAt().
72     // @IntrinsicCandidate
73     // intrinsic performs no bounds checks
74     /*
75     static char getChar(byte[] val, int index) {
76         assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
77         index <<= 1;
78         return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
79                       ((val[index]   & 0xff) << LO_BYTE_SHIFT));
80      */
81     @IntrinsicCandidate
82     static char getChar(String val, int index) {
83         return val.charAt(index);
84     }
85     // END Android-added: Pass String instead of byte[]; implement in terms of charAt().
86 
87     public static int length(byte[] value) {
88         return value.length >> 1;
89     }
90 
91     // BEGIN Android-added: Pass String instead of byte[].
92     /*
93     public static int length(byte[] value) {
94         return value.length >> 1;
95      */
96     public static int length(String value) {
97         return value.length();
98     }
99     // END Android-added: Pass String instead of byte[].
100 
101     private static int codePointAt(byte[] value, int index, int end, boolean checked) {
102         assert index < end;
103         if (checked) {
104             checkIndex(index, value);
105         }
106         char c1 = getChar(value, index);
107         if (Character.isHighSurrogate(c1) && ++index < end) {
108             if (checked) {
109                 checkIndex(index, value);
110             }
111             char c2 = getChar(value, index);
112             if (Character.isLowSurrogate(c2)) {
113                return Character.toCodePoint(c1, c2);
114             }
115         }
116         return c1;
117     }
118 
119     public static int codePointAt(byte[] value, int index, int end) {
120        return codePointAt(value, index, end, false /* unchecked */);
121     }
122 
123     private static int codePointBefore(byte[] value, int index, boolean checked) {
124         --index;
125         if (checked) {
126             checkIndex(index, value);
127         }
128         char c2 = getChar(value, index);
129         if (Character.isLowSurrogate(c2) && index > 0) {
130             --index;
131             if (checked) {
132                 checkIndex(index, value);
133             }
134             char c1 = getChar(value, index);
135             if (Character.isHighSurrogate(c1)) {
136                return Character.toCodePoint(c1, c2);
137             }
138         }
139         return c2;
140     }
141 
142     public static int codePointBefore(byte[] value, int index) {
143         return codePointBefore(value, index, false /* unchecked */);
144     }
145 
146     private static int codePointCount(byte[] value, int beginIndex, int endIndex, boolean checked) {
147         assert beginIndex <= endIndex;
148         int count = endIndex - beginIndex;
149         int i = beginIndex;
150         if (checked && i < endIndex) {
151             checkBoundsBeginEnd(i, endIndex, value);
152         }
153         for (; i < endIndex - 1; ) {
154             if (Character.isHighSurrogate(getChar(value, i++)) &&
155                 Character.isLowSurrogate(getChar(value, i))) {
156                 count--;
157                 i++;
158             }
159         }
160         return count;
161     }
162 
163     public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
164         return codePointCount(value, beginIndex, endIndex, false /* unchecked */);
165     }
166 
167     public static char[] toChars(byte[] value) {
168         char[] dst = new char[value.length >> 1];
169         getChars(value, 0, dst.length, dst, 0);
170         return dst;
171     }
172 
173     @HotSpotIntrinsicCandidate
174     public static byte[] toBytes(char[] value, int off, int len) {
175         byte[] val = newBytesFor(len);
176         for (int i = 0; i < len; i++) {
177             putChar(val, i, value[off]);
178             off++;
179         }
180         return val;
181     }
182 
183     public static byte[] compress(char[] val, int off, int len) {
184         byte[] ret = new byte[len];
185         if (compress(val, off, ret, 0, len) == len) {
186             return ret;
187         }
188         return null;
189     }
190 
191     public static byte[] compress(byte[] val, int off, int len) {
192         byte[] ret = new byte[len];
193         if (compress(val, off, ret, 0, len) == len) {
194             return ret;
195         }
196         return null;
197     }
198 
199     // compressedCopy char[] -> byte[]
200     @HotSpotIntrinsicCandidate
201     public static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
202         for (int i = 0; i < len; i++) {
203             char c = src[srcOff];
204             if (c > 0xFF) {
205                 len = 0;
206                 break;
207             }
208             dst[dstOff] = (byte)c;
209             srcOff++;
210             dstOff++;
211         }
212         return len;
213     }
214 
215     // compressedCopy byte[] -> byte[]
216     @HotSpotIntrinsicCandidate
217     public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
218         // We need a range check here because 'getChar' has no checks
219         checkBoundsOffCount(srcOff, len, src);
220         for (int i = 0; i < len; i++) {
221             char c = getChar(src, srcOff);
222             if (c > 0xFF) {
223                 len = 0;
224                 break;
225             }
226             dst[dstOff] = (byte)c;
227             srcOff++;
228             dstOff++;
229         }
230         return len;
231     }
232 
233     public static byte[] toBytes(int[] val, int index, int len) {
234         final int end = index + len;
235         // Pass 1: Compute precise size of char[]
236         int n = len;
237         for (int i = index; i < end; i++) {
238             int cp = val[i];
239             if (Character.isBmpCodePoint(cp))
240                 continue;
241             else if (Character.isValidCodePoint(cp))
242                 n++;
243             else throw new IllegalArgumentException(Integer.toString(cp));
244         }
245         // Pass 2: Allocate and fill in <high, low> pair
246         byte[] buf = newBytesFor(n);
247         for (int i = index, j = 0; i < end; i++, j++) {
248             int cp = val[i];
249             if (Character.isBmpCodePoint(cp)) {
250                 putChar(buf, j, cp);
251             } else {
252                 putChar(buf, j++, Character.highSurrogate(cp));
253                 putChar(buf, j, Character.lowSurrogate(cp));
254             }
255         }
256         return buf;
257     }
258 
259     public static byte[] toBytes(char c) {
260         byte[] result = new byte[2];
261         putChar(result, 0, c);
262         return result;
263     }
264 
265     static byte[] toBytesSupplementary(int cp) {
266         byte[] result = new byte[4];
267         putChar(result, 0, Character.highSurrogate(cp));
268         putChar(result, 1, Character.lowSurrogate(cp));
269         return result;
270     }
271 
272     @HotSpotIntrinsicCandidate
273     public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
274         // We need a range check here because 'getChar' has no checks
275         if (srcBegin < srcEnd) {
276             checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value);
277         }
278         for (int i = srcBegin; i < srcEnd; i++) {
279             dst[dstBegin++] = getChar(value, i);
280         }
281     }
282 
283     /* @see java.lang.String.getBytes(int, int, byte[], int) */
284     public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
285         srcBegin <<= 1;
286         srcEnd <<= 1;
287         for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) {
288             dst[dstBegin++] = value[i];
289         }
290     }
291 
292     @HotSpotIntrinsicCandidate
293     public static boolean equals(byte[] value, byte[] other) {
294         if (value.length == other.length) {
295             int len = value.length >> 1;
296             for (int i = 0; i < len; i++) {
297                 if (getChar(value, i) != getChar(other, i)) {
298                     return false;
299                 }
300             }
301             return true;
302         }
303         return false;
304     }
305 
306     @HotSpotIntrinsicCandidate
307     public static int compareTo(byte[] value, byte[] other) {
308         int len1 = length(value);
309         int len2 = length(other);
310         return compareValues(value, other, len1, len2);
311     }
312 
313     /*
314      * Checks the boundary and then compares the byte arrays.
315      */
316     public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
317         checkOffset(len1, value);
318         checkOffset(len2, other);
319 
320         return compareValues(value, other, len1, len2);
321     }
322 
323     private static int compareValues(byte[] value, byte[] other, int len1, int len2) {
324         int lim = Math.min(len1, len2);
325         for (int k = 0; k < lim; k++) {
326             char c1 = getChar(value, k);
327             char c2 = getChar(other, k);
328             if (c1 != c2) {
329                 return c1 - c2;
330             }
331         }
332         return len1 - len2;
333     }
334 
335     @HotSpotIntrinsicCandidate
336     public static int compareToLatin1(byte[] value, byte[] other) {
337         return -StringLatin1.compareToUTF16(other, value);
338     }
339 
340     public static int compareToLatin1(byte[] value, byte[] other, int len1, int len2) {
341         return -StringLatin1.compareToUTF16(other, value, len2, len1);
342     }
343 
344     public static int compareToCI(byte[] value, byte[] other) {
345         int len1 = length(value);
346         int len2 = length(other);
347         int lim = Math.min(len1, len2);
348         for (int k = 0; k < lim; k++) {
349             char c1 = getChar(value, k);
350             char c2 = getChar(other, k);
351             if (c1 != c2) {
352                 c1 = Character.toUpperCase(c1);
353                 c2 = Character.toUpperCase(c2);
354                 if (c1 != c2) {
355                     c1 = Character.toLowerCase(c1);
356                     c2 = Character.toLowerCase(c2);
357                     if (c1 != c2) {
358                         return c1 - c2;
359                     }
360                 }
361             }
362         }
363         return len1 - len2;
364     }
365 
366     public static int compareToCI_Latin1(byte[] value, byte[] other) {
367         return -StringLatin1.compareToCI_UTF16(other, value);
368     }
369 
370     public static int hashCode(byte[] value) {
371         int h = 0;
372         int length = value.length >> 1;
373         for (int i = 0; i < length; i++) {
374             h = 31 * h + getChar(value, i);
375         }
376         return h;
377     }
378 
379     public static int indexOf(byte[] value, int ch, int fromIndex) {
380         int max = value.length >> 1;
381         if (fromIndex < 0) {
382             fromIndex = 0;
383         } else if (fromIndex >= max) {
384             // Note: fromIndex might be near -1>>>1.
385             return -1;
386         }
387         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
388             // handle most cases here (ch is a BMP code point or a
389             // negative value (invalid code point))
390             return indexOfChar(value, ch, fromIndex, max);
391         } else {
392             return indexOfSupplementary(value, ch, fromIndex, max);
393         }
394     }
395 
396     // Android-removed: Removed unused code.
397     /*
398     @HotSpotIntrinsicCandidate
399     public static int indexOf(byte[] value, byte[] str) {
400         if (str.length == 0) {
401             return 0;
402         }
403         if (value.length < str.length) {
404             return -1;
405         }
406         return indexOfUnsafe(value, length(value), str, length(str), 0);
407     }
408     */
409 
410     @HotSpotIntrinsicCandidate
411     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
412     // public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
413     public static int indexOf(byte[] value, int valueCount, String str, int strCount, int fromIndex) {
414         checkBoundsBeginEnd(fromIndex, valueCount, value);
415         // checkBoundsBeginEnd(0, strCount, str);
416         String.checkBoundsBeginEnd(0, strCount, str.length());
417         return indexOfUnsafe(value, valueCount, str, strCount, fromIndex);
418     }
419 
420     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
421     // private static int indexOfUnsafe(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
422     private static int indexOfUnsafe(byte[] value, int valueCount, String str, int strCount, int fromIndex) {
423         assert fromIndex >= 0;
424         assert strCount > 0;
425         // assert strCount <= length(str);
426         assert strCount <= str.length();
427         assert valueCount >= strCount;
428         // char first = getChar(str, 0);
429         char first = str.charAt(0);
430         int max = (valueCount - strCount);
431         for (int i = fromIndex; i <= max; i++) {
432             // Look for first character.
433             if (getChar(value, i) != first) {
434                 while (++i <= max && getChar(value, i) != first);
435             }
436             // Found first character, now look at the rest of value
437             if (i <= max) {
438                 int j = i + 1;
439                 int end = j + strCount - 1;
440                 // Android-changed: Use str.charAt because String doesn't store char in java level.
441                 // for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
442                 for (int k = 1; j < end && getChar(value, j) == str.charAt(k); j++, k++);
443                 if (j == end) {
444                     // Found whole string.
445                     return i;
446                 }
447             }
448         }
449         return -1;
450     }
451 
452     // Android-removed: Removed unused code.
453     /**
454      * Handles indexOf Latin1 substring in UTF16 string.
455      *
456     @HotSpotIntrinsicCandidate
457     public static int indexOfLatin1(byte[] value, byte[] str) {
458         if (str.length == 0) {
459             return 0;
460         }
461         if (length(value) < str.length) {
462             return -1;
463         }
464         return indexOfLatin1Unsafe(value, length(value), str, str.length, 0);
465     }
466     */
467 
468     @HotSpotIntrinsicCandidate
469     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
470     // public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
471     public static int indexOfLatin1(byte[] src, int srcCount, String tgt, int tgtCount, int fromIndex) {
472         checkBoundsBeginEnd(fromIndex, srcCount, src);
473         // String.checkBoundsBeginEnd(0, tgtCount, tgt.length);
474         String.checkBoundsBeginEnd(0, tgtCount, tgt.length());
475         return indexOfLatin1Unsafe(src, srcCount, tgt, tgtCount, fromIndex);
476     }
477 
478     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
479     // public static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
480     public static int indexOfLatin1Unsafe(byte[] src, int srcCount, String tgt, int tgtCount, int fromIndex) {
481         assert fromIndex >= 0;
482         assert tgtCount > 0;
483         // assert tgtCount <= tgt.length;
484         assert tgtCount <= tgt.length();
485         assert srcCount >= tgtCount;
486         // char first = (char)(tgt[0] & 0xff);
487         char first = tgt.charAt(0);
488         int max = (srcCount - tgtCount);
489         for (int i = fromIndex; i <= max; i++) {
490             // Look for first character.
491             if (getChar(src, i) != first) {
492                 while (++i <= max && getChar(src, i) != first);
493             }
494             // Found first character, now look at the rest of v2
495             if (i <= max) {
496                 int j = i + 1;
497                 int end = j + tgtCount - 1;
498                 for (int k = 1;
499                      // j < end && getChar(src, j) == (tgt[k] & 0xff);
500                      j < end && getChar(src, j) == tgt.charAt(k);
501                      j++, k++);
502                 if (j == end) {
503                     // Found whole string.
504                     return i;
505                 }
506             }
507         }
508         return -1;
509     }
510 
511     @HotSpotIntrinsicCandidate
512     private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
513         checkBoundsBeginEnd(fromIndex, max, value);
514         return indexOfCharUnsafe(value, ch, fromIndex, max);
515     }
516 
517     private static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) {
518         for (int i = fromIndex; i < max; i++) {
519             if (getChar(value, i) == ch) {
520                 return i;
521             }
522         }
523         return -1;
524     }
525 
526     /**
527      * Handles (rare) calls of indexOf with a supplementary character.
528      */
529     private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) {
530         if (Character.isValidCodePoint(ch)) {
531             final char hi = Character.highSurrogate(ch);
532             final char lo = Character.lowSurrogate(ch);
533             checkBoundsBeginEnd(fromIndex, max, value);
534             for (int i = fromIndex; i < max - 1; i++) {
535                 if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
536                     return i;
537                 }
538             }
539         }
540         return -1;
541     }
542 
543     // srcCoder == UTF16 && tgtCoder == UTF16
544     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
545     public static int lastIndexOf(byte[] src, int srcCount,
546                                   // byte[] tgt, int tgtCount, int fromIndex) {
547                                   String tgt, int tgtCount, int fromIndex) {
548         assert fromIndex >= 0;
549         assert tgtCount > 0;
550         // assert tgtCount <= length(tgt);
551         assert tgtCount <= tgt.length();
552         int min = tgtCount - 1;
553         int i = min + fromIndex;
554         int strLastIndex = tgtCount - 1;
555 
556         // checkIndex(strLastIndex, tgt);
557         // char strLastChar = getChar(tgt, strLastIndex);
558         String.checkIndex(strLastIndex, tgt.length());
559         char strLastChar = tgt.charAt(strLastIndex);
560 
561         checkIndex(i, src);
562 
563     startSearchForLastChar:
564         while (true) {
565             while (i >= min && getChar(src, i) != strLastChar) {
566                 i--;
567             }
568             if (i < min) {
569                 return -1;
570             }
571             int j = i - 1;
572             int start = j - strLastIndex;
573             int k = strLastIndex - 1;
574             while (j > start) {
575                 // if (getChar(src, j--) != getChar(tgt, k--)) {
576                 if (getChar(src, j--) != tgt.charAt(k--)) {
577                     i--;
578                     continue startSearchForLastChar;
579                 }
580             }
581             return start + 1;
582         }
583     }
584 
585     public static int lastIndexOf(byte[] value, int ch, int fromIndex) {
586         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
587             // handle most cases here (ch is a BMP code point or a
588             // negative value (invalid code point))
589             int i = Math.min(fromIndex, (value.length >> 1) - 1);
590             for (; i >= 0; i--) {
591                 if (getChar(value, i) == ch) {
592                     return i;
593                 }
594             }
595             return -1;
596         } else {
597             return lastIndexOfSupplementary(value, ch, fromIndex);
598         }
599     }
600 
601     /**
602      * Handles (rare) calls of lastIndexOf with a supplementary character.
603      */
604     private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) {
605         if (Character.isValidCodePoint(ch)) {
606             char hi = Character.highSurrogate(ch);
607             char lo = Character.lowSurrogate(ch);
608             int i = Math.min(fromIndex, (value.length >> 1) - 2);
609             for (; i >= 0; i--) {
610                 if (getChar(value, i) == hi && getChar(value, i + 1) == lo) {
611                     return i;
612                 }
613             }
614         }
615         return -1;
616     }
617 
618     public static String replace(byte[] value, char oldChar, char newChar) {
619         int len = value.length >> 1;
620         int i = -1;
621         while (++i < len) {
622             if (getChar(value, i) == oldChar) {
623                 break;
624             }
625         }
626         if (i < len) {
627             byte buf[] = new byte[value.length];
628             for (int j = 0; j < i; j++) {
629                 putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
630             }
631             while (i < len) {
632                 char c = getChar(value, i);
633                 putChar(buf, i, c == oldChar ? newChar : c);
634                 i++;
635            }
636            // Check if we should try to compress to latin1
637            if (String.COMPACT_STRINGS &&
638                !StringLatin1.canEncode(oldChar) &&
639                StringLatin1.canEncode(newChar)) {
640                byte[] val = compress(buf, 0, len);
641                if (val != null) {
642                    return new String(val, LATIN1);
643                }
644            }
645            return new String(buf, UTF16);
646         }
647         return null;
648     }
649 
650     // BEGIN Android-removed: Removed unused code.
651     /*
652     public static boolean regionMatchesCI(byte[] value, int toffset,
653                                           byte[] other, int ooffset, int len) {
654         int last = toffset + len;
655         assert toffset >= 0 && ooffset >= 0;
656         assert ooffset + len <= length(other);
657         assert last <= length(value);
658         while (toffset < last) {
659             char c1 = getChar(value, toffset++);
660             char c2 = getChar(other, ooffset++);
661             if (c1 == c2) {
662                 continue;
663             }
664             // try converting both characters to uppercase.
665             // If the results match, then the comparison scan should
666             // continue.
667             char u1 = Character.toUpperCase(c1);
668             char u2 = Character.toUpperCase(c2);
669             if (u1 == u2) {
670                 continue;
671             }
672             // Unfortunately, conversion to uppercase does not work properly
673             // for the Georgian alphabet, which has strange rules about case
674             // conversion.  So we need to make one last check before
675             // exiting.
676             if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
677                 continue;
678             }
679             return false;
680         }
681         return true;
682     }
683 
684     public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,
685                                                  byte[] other, int ooffset,
686                                                  int len) {
687         return StringLatin1.regionMatchesCI_UTF16(other, ooffset, value, toffset, len);
688     }
689 
690     public static String toLowerCase(String str, byte[] value, Locale locale) {
691         if (locale == null) {
692             throw new NullPointerException();
693         }
694         int first;
695         boolean hasSurr = false;
696         final int len = value.length >> 1;
697 
698         // Now check if there are any characters that need to be changed, or are surrogate
699         for (first = 0 ; first < len; first++) {
700             int cp = (int)getChar(value, first);
701             if (Character.isSurrogate((char)cp)) {
702                 hasSurr = true;
703                 break;
704             }
705             if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
706                 break;
707             }
708         }
709         if (first == len)
710             return str;
711         byte[] result = new byte[value.length];
712         System.arraycopy(value, 0, result, 0, first << 1);  // Just copy the first few
713                                                             // lowerCase characters.
714         String lang = locale.getLanguage();
715         if (lang == "tr" || lang == "az" || lang == "lt") {
716             return toLowerCaseEx(str, value, result, first, locale, true);
717         }
718         if (hasSurr) {
719             return toLowerCaseEx(str, value, result, first, locale, false);
720         }
721         int bits = 0;
722         for (int i = first; i < len; i++) {
723             int cp = (int)getChar(value, i);
724             if (cp == '\u03A3' ||                       // GREEK CAPITAL LETTER SIGMA
725                 Character.isSurrogate((char)cp)) {
726                 return toLowerCaseEx(str, value, result, i, locale, false);
727             }
728             if (cp == '\u0130') {                       // LATIN CAPITAL LETTER I WITH DOT ABOVE
729                 return toLowerCaseEx(str, value, result, i, locale, true);
730             }
731             cp = Character.toLowerCase(cp);
732             if (!Character.isBmpCodePoint(cp)) {
733                 return toLowerCaseEx(str, value, result, i, locale, false);
734             }
735             bits |= cp;
736             putChar(result, i, cp);
737         }
738         if (bits > 0xFF) {
739             return new String(result, UTF16);
740         } else {
741             return newString(result, 0, len);
742         }
743     }
744 
745     private static String toLowerCaseEx(String str, byte[] value,
746                                         byte[] result, int first, Locale locale,
747                                         boolean localeDependent) {
748         assert(result.length == value.length);
749         assert(first >= 0);
750         int resultOffset = first;
751         int length = value.length >> 1;
752         int srcCount;
753         for (int i = first; i < length; i += srcCount) {
754             int srcChar = getChar(value, i);
755             int lowerChar;
756             char[] lowerCharArray;
757             srcCount = 1;
758             if (Character.isSurrogate((char)srcChar)) {
759                 srcChar = codePointAt(value, i, length);
760                 srcCount = Character.charCount(srcChar);
761             }
762             if (localeDependent ||
763                 srcChar == '\u03A3' ||  // GREEK CAPITAL LETTER SIGMA
764                 srcChar == '\u0130') {  // LATIN CAPITAL LETTER I WITH DOT ABOVE
765                 lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
766             } else {
767                 lowerChar = Character.toLowerCase(srcChar);
768             }
769             if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
770                 putChar(result, resultOffset++, lowerChar);
771             } else {
772                 if (lowerChar == Character.ERROR) {
773                     lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
774                 } else {
775                     lowerCharArray = Character.toChars(lowerChar);
776                 }
777                 /* Grow result if needed *
778                 int mapLen = lowerCharArray.length;
779                 if (mapLen > srcCount) {
780                     byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
781                     System.arraycopy(result, 0, result2, 0, resultOffset << 1);
782                     result = result2;
783                 }
784                 assert resultOffset >= 0;
785                 assert resultOffset + mapLen <= length(result);
786                 for (int x = 0; x < mapLen; ++x) {
787                     putChar(result, resultOffset++, lowerCharArray[x]);
788                 }
789             }
790         }
791         return newString(result, 0, resultOffset);
792     }
793 
794     public static String toUpperCase(String str, byte[] value, Locale locale) {
795         if (locale == null) {
796             throw new NullPointerException();
797         }
798         int first;
799         boolean hasSurr = false;
800         final int len = value.length >> 1;
801 
802         // Now check if there are any characters that need to be changed, or are surrogate
803         for (first = 0 ; first < len; first++) {
804             int cp = (int)getChar(value, first);
805             if (Character.isSurrogate((char)cp)) {
806                 hasSurr = true;
807                 break;
808             }
809             if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
810                 break;
811             }
812         }
813         if (first == len) {
814             return str;
815         }
816         byte[] result = new byte[value.length];
817         System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
818                                                            // upperCase characters.
819         String lang = locale.getLanguage();
820         if (lang == "tr" || lang == "az" || lang == "lt") {
821             return toUpperCaseEx(str, value, result, first, locale, true);
822         }
823         if (hasSurr) {
824             return toUpperCaseEx(str, value, result, first, locale, false);
825         }
826         int bits = 0;
827         for (int i = first; i < len; i++) {
828             int cp = (int)getChar(value, i);
829             if (Character.isSurrogate((char)cp)) {
830                 return toUpperCaseEx(str, value, result, i, locale, false);
831             }
832             cp = Character.toUpperCaseEx(cp);
833             if (!Character.isBmpCodePoint(cp)) {    // Character.ERROR is not bmp
834                 return toUpperCaseEx(str, value, result, i, locale, false);
835             }
836             bits |= cp;
837             putChar(result, i, cp);
838         }
839         if (bits > 0xFF) {
840             return new String(result, UTF16);
841         } else {
842             return newString(result, 0, len);
843         }
844     }
845 
846     private static String toUpperCaseEx(String str, byte[] value,
847                                         byte[] result, int first,
848                                         Locale locale, boolean localeDependent)
849     {
850         assert(result.length == value.length);
851         assert(first >= 0);
852         int resultOffset = first;
853         int length = value.length >> 1;
854         int srcCount;
855         for (int i = first; i < length; i += srcCount) {
856             int srcChar = getChar(value, i);
857             int upperChar;
858             char[] upperCharArray;
859             srcCount = 1;
860             if (Character.isSurrogate((char)srcChar)) {
861                 srcChar = codePointAt(value, i, length);
862                 srcCount = Character.charCount(srcChar);
863             }
864             if (localeDependent) {
865                 upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
866             } else {
867                 upperChar = Character.toUpperCaseEx(srcChar);
868             }
869             if (Character.isBmpCodePoint(upperChar)) {
870                 putChar(result, resultOffset++, upperChar);
871             } else {
872                 if (upperChar == Character.ERROR) {
873                     if (localeDependent) {
874                         upperCharArray =
875                             ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
876                     } else {
877                         upperCharArray = Character.toUpperCaseCharArray(srcChar);
878                     }
879                 } else {
880                     upperCharArray = Character.toChars(upperChar);
881                 }
882                 /* Grow result if needed *
883                 int mapLen = upperCharArray.length;
884                 if (mapLen > srcCount) {
885                     byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
886                     System.arraycopy(result, 0, result2, 0, resultOffset << 1);
887                     result = result2;
888                 }
889                 assert resultOffset >= 0;
890                 assert resultOffset + mapLen <= length(result);
891                 for (int x = 0; x < mapLen; ++x) {
892                     putChar(result, resultOffset++, upperCharArray[x]);
893                 }
894             }
895         }
896         return newString(result, 0, resultOffset);
897     }
898     */
899     // END Android-removed: Removed unused code.
900 
901     public static String trim(byte[] value) {
902         int length = value.length >> 1;
903         int len = length;
904         int st = 0;
905         while (st < len && getChar(value, st) <= ' ') {
906             st++;
907         }
908         while (st < len && getChar(value, len - 1) <= ' ') {
909             len--;
910         }
911         return ((st > 0) || (len < length )) ?
912             // Android-changed: Avoid byte[] allocation.
913             // new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
914             StringFactory.newStringFromUtf16Bytes(value, st << 1, len - st) :
915             null;
916     }
917 
918     // BEGIN Android-changed: Pass String instead of byte[].
919     /*
920     public static int indexOfNonWhitespace(byte[] value) {
921         int length = value.length >> 1;
922      */
923     public static int indexOfNonWhitespace(String value) {
924         int length = value.length();
925         int left = 0;
926         while (left < length) {
927             /*
928             int codepoint = codePointAt(value, left, length);
929              */
930             int codepoint = value.codePointAt(left);
931             // END Android-changed: Pass String instead of byte[].
932             if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
933                 break;
934             }
935             left += Character.charCount(codepoint);
936         }
937         return left;
938     }
939 
940     // BEGIN Android-changed: Pass String instead of byte[].
941     /*
942     public static int lastIndexOfNonWhitespace(byte[] value) {
943         int length = value.length >> 1;
944         int right = length;
945      */
946     public static int lastIndexOfNonWhitespace(String value) {
947         int right = value.length();
948         while (0 < right) {
949             /*
950             int codepoint = codePointBefore(value, right);
951              */
952             int codepoint = value.codePointBefore(right);
953             // END Android-changed: Pass String instead of byte[].
954             if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
955                 break;
956             }
957             right -= Character.charCount(codepoint);
958         }
959         return right;
960     }
961 
962     // BEGIN Android-changed: Pass String instead of byte[].
963     /*
964     public static String strip(byte[] value) {
965         int length = value.length >> 1;
966      */
967     public static String strip(String value) {
968         int length = value.length();
969         // END Android-changed: Pass String instead of byte[].
970         int left = indexOfNonWhitespace(value);
971         if (left == length) {
972             return "";
973         }
974         int right = lastIndexOfNonWhitespace(value);
975         return ((left > 0) || (right < length)) ? newString(value, left, right - left) : null;
976     }
977 
978     // BEGIN Android-changed: Pass String instead of byte[].
979     /*
980     public static String stripLeading(byte[] value) {
981         int length = value.length >> 1;
982      */
983     public static String stripLeading(String value) {
984         int length = value.length();
985         // END Android-changed: Pass String instead of byte[].
986         int left = indexOfNonWhitespace(value);
987         if (left == length) {
988             return "";
989         }
990         return (left != 0) ? newString(value, left, length - left) : null;
991     }
992 
993     // BEGIN Android-changed: Pass String instead of byte[].
994     /*
995     public static String stripTrailing(byte[] value) {
996         int length = value.length >> 1;
997      */
998     public static String stripTrailing(String value) {
999         int length = value.length();
1000         // END Android-changed: Pass String instead of byte[].
1001         int right = lastIndexOfNonWhitespace(value);
1002         if (right == 0) {
1003             return "";
1004         }
1005         return (right != length) ? newString(value, 0, right) : null;
1006     }
1007 
1008     private final static class LinesSpliterator implements Spliterator<String> {
1009         // BEGIN Android-changed: Pass String instead of byte[].
1010         /*
1011         private byte[] value;
1012          */
1013         private String value;
1014         // END Android-changed: Pass String instead of byte[].
1015         private int index;        // current index, modified on advance/split
1016         private final int fence;  // one past last index
1017 
1018         // BEGIN Android-changed: Pass String instead of byte[].
1019         /*
1020         LinesSpliterator(byte[] value) {
1021             this(value, 0, value.length >>> 1);
1022         */
1023         LinesSpliterator(String value) {
1024             this(value, 0, value.length());
1025             // END Android-changed: Pass String instead of byte[].
1026         }
1027 
1028         // BEGIN Android-changed: Pass String instead of byte[].
1029         /*
1030         LinesSpliterator(byte[] value, int start, int length) {
1031          */
1032         LinesSpliterator(String value, int start, int length) {
1033             // END Android-changed: Pass String instead of byte[].
1034             this.value = value;
1035             this.index = start;
1036             this.fence = start + length;
1037         }
1038 
1039         private int indexOfLineSeparator(int start) {
1040             for (int current = start; current < fence; current++) {
1041                 char ch = getChar(value, current);
1042                 if (ch == '\n' || ch == '\r') {
1043                     return current;
1044                 }
1045             }
1046             return fence;
1047         }
1048 
1049         private int skipLineSeparator(int start) {
1050             if (start < fence) {
1051                 if (getChar(value, start) == '\r') {
1052                     int next = start + 1;
1053                     if (next < fence && getChar(value, next) == '\n') {
1054                         return next + 1;
1055                     }
1056                 }
1057                 return start + 1;
1058             }
1059             return fence;
1060         }
1061 
1062         private String next() {
1063             int start = index;
1064             int end = indexOfLineSeparator(start);
1065             index = skipLineSeparator(end);
1066             return newString(value, start, end - start);
1067         }
1068 
1069         @Override
1070         public boolean tryAdvance(Consumer<? super String> action) {
1071             if (action == null) {
1072                 throw new NullPointerException("tryAdvance action missing");
1073             }
1074             if (index != fence) {
1075                 action.accept(next());
1076                 return true;
1077             }
1078             return false;
1079         }
1080 
1081         @Override
1082         public void forEachRemaining(Consumer<? super String> action) {
1083             if (action == null) {
1084                 throw new NullPointerException("forEachRemaining action missing");
1085             }
1086             while (index != fence) {
1087                 action.accept(next());
1088             }
1089         }
1090 
1091         @Override
1092         public Spliterator<String> trySplit() {
1093             int half = (fence + index) >>> 1;
1094             int mid = skipLineSeparator(indexOfLineSeparator(half));
1095             if (mid < fence) {
1096                 int start = index;
1097                 index = mid;
1098                 return new LinesSpliterator(value, start, mid - start);
1099             }
1100             return null;
1101         }
1102 
1103         @Override
1104         public long estimateSize() {
1105             return fence - index + 1;
1106         }
1107 
1108         @Override
1109         public int characteristics() {
1110             return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
1111         }
1112     }
1113 
1114     // BEGIN Android-changed: Pass String instead of byte[].
1115     /*
1116     static Stream<String> lines(byte[] value) {
1117      */
1118     static Stream<String> lines(String value) {
1119         return StreamSupport.stream(new LinesSpliterator(value), false);
1120         // END Android-changed: Pass String instead of byte[].
1121     }
1122 
1123     private static void putChars(byte[] val, int index, char[] str, int off, int end) {
1124         while (off < end) {
1125             putChar(val, index++, str[off++]);
1126         }
1127     }
1128 
1129     public static String newString(byte[] val, int index, int len) {
1130         // Android-changed: Skip compression check because ART's StringFactory will do so.
1131         /*
1132         if (String.COMPACT_STRINGS) {
1133             byte[] buf = compress(val, index, len);
1134             if (buf != null) {
1135                 return new String(buf, LATIN1);
1136             }
1137         }
1138         int last = index + len;
1139         return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
1140         */
1141         return StringFactory.newStringFromUtf16Bytes(val, index << 1, len);
1142     }
1143 
1144     // BEGIN Android-added: Pass String instead of byte[]; implement in terms of substring().
1145     /*
1146     public static String newString(byte[] val, int index, int len) {
1147         if (String.COMPACT_STRINGS) {
1148             byte[] buf = compress(val, index, len);
1149             if (buf != null) {
1150                 return new String(buf, LATIN1);
1151             }
1152         }
1153         int last = index + len;
1154         return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
1155     }
1156      */
1157     public static String newString(String val, int index, int len) {
1158         return val.substring(index, index + len);
1159     }
1160     // END Android-added: Pass String instead of byte[]; implement in terms of substring().
1161 
1162     public static void fillNull(byte[] val, int index, int end) {
1163         Arrays.fill(val, index << 1, end << 1, (byte)0);
1164     }
1165 
1166     static class CharsSpliterator implements Spliterator.OfInt {
1167         private final byte[] array;
1168         private int index;        // current index, modified on advance/split
1169         private final int fence;  // one past last index
1170         private final int cs;
1171 
1172         CharsSpliterator(byte[] array, int acs) {
1173             this(array, 0, array.length >> 1, acs);
1174         }
1175 
1176         CharsSpliterator(byte[] array, int origin, int fence, int acs) {
1177             this.array = array;
1178             this.index = origin;
1179             this.fence = fence;
1180             this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
1181                       | Spliterator.SUBSIZED;
1182         }
1183 
1184         @Override
1185         public OfInt trySplit() {
1186             int lo = index, mid = (lo + fence) >>> 1;
1187             return (lo >= mid)
1188                    ? null
1189                    : new CharsSpliterator(array, lo, index = mid, cs);
1190         }
1191 
1192         @Override
1193         public void forEachRemaining(IntConsumer action) {
1194             byte[] a; int i, hi; // hoist accesses and checks from loop
1195             if (action == null)
1196                 throw new NullPointerException();
1197             if (((a = array).length >> 1) >= (hi = fence) &&
1198                 (i = index) >= 0 && i < (index = hi)) {
1199                 do {
1200                     action.accept(charAt(a, i));
1201                 } while (++i < hi);
1202             }
1203         }
1204 
1205         @Override
1206         public boolean tryAdvance(IntConsumer action) {
1207             if (action == null)
1208                 throw new NullPointerException();
1209             int i = index;
1210             if (i >= 0 && i < fence) {
1211                 action.accept(charAt(array, i));
1212                 index++;
1213                 return true;
1214             }
1215             return false;
1216         }
1217 
1218         @Override
1219         public long estimateSize() { return (long)(fence - index); }
1220 
1221         @Override
1222         public int characteristics() {
1223             return cs;
1224         }
1225     }
1226 
1227     static class CodePointsSpliterator implements Spliterator.OfInt {
1228         private final byte[] array;
1229         private int index;        // current index, modified on advance/split
1230         private final int fence;  // one past last index
1231         private final int cs;
1232 
1233         CodePointsSpliterator(byte[] array, int acs) {
1234             this(array, 0, array.length >> 1, acs);
1235         }
1236 
1237         CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
1238             this.array = array;
1239             this.index = origin;
1240             this.fence = fence;
1241             this.cs = acs | Spliterator.ORDERED;
1242         }
1243 
1244         @Override
1245         public OfInt trySplit() {
1246             int lo = index, mid = (lo + fence) >>> 1;
1247             if (lo >= mid)
1248                 return null;
1249 
1250             int midOneLess;
1251             // If the mid-point intersects a surrogate pair
1252             if (Character.isLowSurrogate(charAt(array, mid)) &&
1253                 Character.isHighSurrogate(charAt(array, midOneLess = (mid -1)))) {
1254                 // If there is only one pair it cannot be split
1255                 if (lo >= midOneLess)
1256                     return null;
1257                 // Shift the mid-point to align with the surrogate pair
1258                 return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
1259             }
1260             return new CodePointsSpliterator(array, lo, index = mid, cs);
1261         }
1262 
1263         @Override
1264         public void forEachRemaining(IntConsumer action) {
1265             byte[] a; int i, hi; // hoist accesses and checks from loop
1266             if (action == null)
1267                 throw new NullPointerException();
1268             if (((a = array).length >> 1) >= (hi = fence) &&
1269                 (i = index) >= 0 && i < (index = hi)) {
1270                 do {
1271                     i = advance(a, i, hi, action);
1272                 } while (i < hi);
1273             }
1274         }
1275 
1276         @Override
1277         public boolean tryAdvance(IntConsumer action) {
1278             if (action == null)
1279                 throw new NullPointerException();
1280             if (index >= 0 && index < fence) {
1281                 index = advance(array, index, fence, action);
1282                 return true;
1283             }
1284             return false;
1285         }
1286 
1287         // Advance one code point from the index, i, and return the next
1288         // index to advance from
1289         private static int advance(byte[] a, int i, int hi, IntConsumer action) {
1290             char c1 = charAt(a, i++);
1291             int cp = c1;
1292             if (Character.isHighSurrogate(c1) && i < hi) {
1293                 char c2 = charAt(a, i);
1294                 if (Character.isLowSurrogate(c2)) {
1295                     i++;
1296                     cp = Character.toCodePoint(c1, c2);
1297                 }
1298             }
1299             action.accept(cp);
1300             return i;
1301         }
1302 
1303         @Override
1304         public long estimateSize() { return (long)(fence - index); }
1305 
1306         @Override
1307         public int characteristics() {
1308             return cs;
1309         }
1310     }
1311 
1312     static class CharsSpliteratorForString implements Spliterator.OfInt {
1313         // BEGIN Android-changed: Pass String instead of byte[].
1314         /*
1315         private final byte[] array;
1316          */
1317         private final String array;
1318         // END Android-changed: Pass String instead of byte[].
1319         private int index;        // current index, modified on advance/split
1320         private final int fence;  // one past last index
1321         private final int cs;
1322 
1323         // BEGIN Android-changed: Pass String instead of byte[].
1324         /*
1325         CharsSpliterator(byte[] array, int acs) {
1326             this(array, 0, array.length >> 1, acs);
1327          */
1328         CharsSpliteratorForString(String array, int acs) {
1329             this(array, 0, array.length(), acs);
1330             // END Android-changed: Pass String instead of byte[].
1331         }
1332 
1333         // BEGIN Android-changed: Pass String instead of byte[].
1334         /*
1335         CharsSpliterator(byte[] array, int origin, int fence, int acs) {
1336          */
1337         CharsSpliteratorForString(String array, int origin, int fence, int acs) {
1338             // END Android-changed: Pass String instead of byte[].
1339             this.array = array;
1340             this.index = origin;
1341             this.fence = fence;
1342             this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
1343                 | Spliterator.SUBSIZED;
1344         }
1345 
1346         @Override
1347         public OfInt trySplit() {
1348             int lo = index, mid = (lo + fence) >>> 1;
1349             return (lo >= mid)
1350                 ? null
1351                 : new CharsSpliteratorForString(array, lo, index = mid, cs);
1352         }
1353 
1354         @Override
1355         public void forEachRemaining(IntConsumer action) {
1356             // BEGIN Android-changed: Pass String instead of byte[].
1357             /*
1358             byte[] a; int i, hi; // hoist accesses and checks from loop
1359              */
1360             String a; int i, hi; // hoist accesses and checks from loop
1361             // END Android-changed: Pass String instead of byte[].
1362             if (action == null)
1363                 throw new NullPointerException();
1364             // BEGIN Android-changed: Pass String instead of byte[].
1365             /*
1366             if (((a = array).length >> 1) >= (hi = fence) &&
1367              */
1368             if (((a = array).length()) >= (hi = fence) &&
1369                 // END Android-changed: Pass String instead of byte[].
1370                 (i = index) >= 0 && i < (index = hi)) {
1371                 do {
1372                     action.accept(charAt(a, i));
1373                 } while (++i < hi);
1374             }
1375         }
1376 
1377         @Override
1378         public boolean tryAdvance(IntConsumer action) {
1379             if (action == null)
1380                 throw new NullPointerException();
1381             int i = index;
1382             if (i >= 0 && i < fence) {
1383                 action.accept(charAt(array, i));
1384                 index++;
1385                 return true;
1386             }
1387             return false;
1388         }
1389 
1390         @Override
1391         public long estimateSize() { return (long)(fence - index); }
1392 
1393         @Override
1394         public int characteristics() {
1395             return cs;
1396         }
1397     }
1398 
1399     static class CodePointsSpliteratorForString implements Spliterator.OfInt {
1400         // BEGIN Android-changed: Pass String instead of byte[].
1401         /*
1402         private final byte[] array;
1403          */
1404         private final String array;
1405         // END Android-changed: Pass String instead of byte[].
1406         private int index;        // current index, modified on advance/split
1407         private final int fence;  // one past last index
1408         private final int cs;
1409 
1410         // BEGIN Android-changed: Pass String instead of byte[].
1411         /*
1412         CodePointsSpliterator(byte[] array, int acs) {
1413             this(array, 0, array.length >> 1, acs);
1414          */
1415         CodePointsSpliteratorForString(String array, int acs) {
1416             this(array, 0, array.length(), acs);
1417             // END Android-changed: Pass String instead of byte[].
1418         }
1419 
1420         // BEGIN Android-changed: Pass String instead of byte[].
1421         /*
1422         CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
1423          */
1424         CodePointsSpliteratorForString(String array, int origin, int fence, int acs) {
1425             // END Android-changed: Pass String instead of byte[].
1426             this.array = array;
1427             this.index = origin;
1428             this.fence = fence;
1429             this.cs = acs | Spliterator.ORDERED;
1430         }
1431 
1432         @Override
1433         public OfInt trySplit() {
1434             int lo = index, mid = (lo + fence) >>> 1;
1435             if (lo >= mid)
1436                 return null;
1437 
1438             int midOneLess;
1439             // If the mid-point intersects a surrogate pair
1440             if (Character.isLowSurrogate(charAt(array, mid)) &&
1441                 Character.isHighSurrogate(charAt(array, midOneLess = (mid -1)))) {
1442                 // If there is only one pair it cannot be split
1443                 if (lo >= midOneLess)
1444                     return null;
1445                 // Shift the mid-point to align with the surrogate pair
1446                 return new CodePointsSpliteratorForString(array, lo, index = midOneLess, cs);
1447             }
1448             return new CodePointsSpliteratorForString(array, lo, index = mid, cs);
1449         }
1450 
1451         @Override
1452         public void forEachRemaining(IntConsumer action) {
1453             // BEGIN Android-changed: Pass String instead of byte[].
1454             /*
1455             byte[] a; int i, hi; // hoist accesses and checks from loop
1456              */
1457             String a; int i, hi; // hoist accesses and checks from loop
1458             // END Android-changed: Pass String instead of byte[].
1459             if (action == null)
1460                 throw new NullPointerException();
1461             // BEGIN Android-changed: Pass String instead of byte[].
1462             /*
1463             if (((a = array).length >> 1) >= (hi = fence) &&
1464              */
1465             if (((a = array).length()) >= (hi = fence) &&
1466                 // END Android-changed: Pass String instead of byte[].
1467                 (i = index) >= 0 && i < (index = hi)) {
1468                 do {
1469                     i = advance(a, i, hi, action);
1470                 } while (i < hi);
1471             }
1472         }
1473 
1474         @Override
1475         public boolean tryAdvance(IntConsumer action) {
1476             if (action == null)
1477                 throw new NullPointerException();
1478             if (index >= 0 && index < fence) {
1479                 index = advance(array, index, fence, action);
1480                 return true;
1481             }
1482             return false;
1483         }
1484 
1485         // Advance one code point from the index, i, and return the next
1486         // index to advance from
1487         // BEGIN Android-changed: Pass String instead of byte[].
1488         /*
1489         private static int advance(byte[] a, int i, int hi, IntConsumer action) {
1490          */
1491         private static int advance(String a, int i, int hi, IntConsumer action) {
1492             // END Android-changed: Pass String instead of byte[].
1493             char c1 = charAt(a, i++);
1494             int cp = c1;
1495             if (Character.isHighSurrogate(c1) && i < hi) {
1496                 char c2 = charAt(a, i);
1497                 if (Character.isLowSurrogate(c2)) {
1498                     i++;
1499                     cp = Character.toCodePoint(c1, c2);
1500                 }
1501             }
1502             action.accept(cp);
1503             return i;
1504         }
1505 
1506         @Override
1507         public long estimateSize() { return (long)(fence - index); }
1508 
1509         @Override
1510         public int characteristics() {
1511             return cs;
1512         }
1513     }
1514 
1515     ////////////////////////////////////////////////////////////////
1516 
1517     public static void putCharSB(byte[] val, int index, int c) {
1518         checkIndex(index, val);
1519         putChar(val, index, c);
1520     }
1521 
1522     public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
1523         checkBoundsBeginEnd(index, index + end - off, val);
1524         putChars(val, index, ca, off, end);
1525     }
1526 
1527     public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
1528         checkBoundsBeginEnd(index, index + end - off, val);
1529         for (int i = off; i < end; i++) {
1530             putChar(val, index++, s.charAt(i));
1531         }
1532     }
1533 
1534     public static int codePointAtSB(byte[] val, int index, int end) {
1535         return codePointAt(val, index, end, true /* checked */);
1536     }
1537 
1538     public static int codePointBeforeSB(byte[] val, int index) {
1539         return codePointBefore(val, index, true /* checked */);
1540     }
1541 
1542     public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
1543         return codePointCount(val, beginIndex, endIndex, true /* checked */);
1544     }
1545 
1546     public static int getChars(int i, int begin, int end, byte[] value) {
1547         checkBoundsBeginEnd(begin, end, value);
1548         int pos = getChars(i, end, value);
1549         assert begin == pos;
1550         return pos;
1551     }
1552 
1553     public static int getChars(long l, int begin, int end, byte[] value) {
1554         checkBoundsBeginEnd(begin, end, value);
1555         int pos = getChars(l, end, value);
1556         assert begin == pos;
1557         return pos;
1558     }
1559 
1560     public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
1561         checkBoundsOffCount(0, len, v2);
1562         for (int i = 0; i < len; i++) {
1563             if ((char)(v1[i] & 0xff) != getChar(v2, i)) {
1564                 return false;
1565             }
1566         }
1567         return true;
1568     }
1569 
1570     public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
1571         checkOffset(len, value);
1572         for (int i = 0; i < len; i++) {
1573             if (getChar(value, i) != cs.charAt(i)) {
1574                 return false;
1575             }
1576         }
1577         return true;
1578     }
1579 
1580     public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
1581         int end = i + 4;
1582         checkBoundsBeginEnd(i, end, value);
1583         putChar(value, i++, c1);
1584         putChar(value, i++, c2);
1585         putChar(value, i++, c3);
1586         putChar(value, i++, c4);
1587         assert(i == end);
1588         return end;
1589     }
1590 
1591     public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
1592         int end = i + 5;
1593         checkBoundsBeginEnd(i, end, value);
1594         putChar(value, i++, c1);
1595         putChar(value, i++, c2);
1596         putChar(value, i++, c3);
1597         putChar(value, i++, c4);
1598         putChar(value, i++, c5);
1599         assert(i == end);
1600         return end;
1601     }
1602 
1603     public static char charAt(byte[] value, int index) {
1604         checkIndex(index, value);
1605         return getChar(value, index);
1606     }
1607 
1608     // BEGIN Android-added: Pass String instead of byte[].
1609     public static char charAt(String value, int index) {
1610         checkIndex(index, value);
1611         return getChar(value, index);
1612     }
1613     // END Android-added: Pass String instead of byte[].
1614 
1615     public static void reverse(byte[] val, int count) {
1616         checkOffset(count, val);
1617         int n = count - 1;
1618         boolean hasSurrogates = false;
1619         for (int j = (n-1) >> 1; j >= 0; j--) {
1620             int k = n - j;
1621             char cj = getChar(val, j);
1622             char ck = getChar(val, k);
1623             putChar(val, j, ck);
1624             putChar(val, k, cj);
1625             if (Character.isSurrogate(cj) ||
1626                 Character.isSurrogate(ck)) {
1627                 hasSurrogates = true;
1628             }
1629         }
1630         if (hasSurrogates) {
1631             reverseAllValidSurrogatePairs(val, count);
1632         }
1633     }
1634 
1635     /** Outlined helper method for reverse() */
1636     private static void reverseAllValidSurrogatePairs(byte[] val, int count) {
1637         for (int i = 0; i < count - 1; i++) {
1638             char c2 = getChar(val, i);
1639             if (Character.isLowSurrogate(c2)) {
1640                 char c1 = getChar(val, i + 1);
1641                 if (Character.isHighSurrogate(c1)) {
1642                     putChar(val, i++, c1);
1643                     putChar(val, i, c2);
1644                 }
1645             }
1646         }
1647     }
1648 
1649     // inflatedCopy byte[] -> byte[]
1650     public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
1651         // We need a range check here because 'putChar' has no checks
1652         checkBoundsOffCount(dstOff, len, dst);
1653         for (int i = 0; i < len; i++) {
1654             putChar(dst, dstOff++, src[srcOff++] & 0xff);
1655         }
1656     }
1657 
1658     // srcCoder == UTF16 && tgtCoder == LATIN1
1659     // Android-changed: libcore doesn't store String as Latin1 or UTF16 byte[] field.
1660     public static int lastIndexOfLatin1(byte[] src, int srcCount,
1661                                         // byte[] tgt, int tgtCount, int fromIndex) {
1662                                         String tgt, int tgtCount, int fromIndex) {
1663         assert fromIndex >= 0;
1664         assert tgtCount > 0;
1665         // assert tgtCount <= tgt.length;
1666         assert tgtCount <= tgt.length();
1667         int min = tgtCount - 1;
1668         int i = min + fromIndex;
1669         int strLastIndex = tgtCount - 1;
1670 
1671         // char strLastChar = (char)(tgt[strLastIndex] & 0xff);
1672         char strLastChar = tgt.charAt(strLastIndex);
1673 
1674         checkIndex(i, src);
1675 
1676     startSearchForLastChar:
1677         while (true) {
1678             while (i >= min && getChar(src, i) != strLastChar) {
1679                 i--;
1680             }
1681             if (i < min) {
1682                 return -1;
1683             }
1684             int j = i - 1;
1685             int start = j - strLastIndex;
1686             int k = strLastIndex - 1;
1687             while (j > start) {
1688                 // if (getChar(src, j--) != (tgt[k--] & 0xff)) {
1689                 if (getChar(src, j--) != tgt.charAt(k--)) {
1690                     i--;
1691                     continue startSearchForLastChar;
1692                 }
1693             }
1694             return start + 1;
1695         }
1696     }
1697 
1698     ////////////////////////////////////////////////////////////////
1699 
1700     // Android-changed: Android is always little endian.
1701     /*
1702     private static native boolean isBigEndian();
1703 
1704     static final int HI_BYTE_SHIFT;
1705     static final int LO_BYTE_SHIFT;
1706     static {
1707         if (isBigEndian()) {
1708             HI_BYTE_SHIFT = 8;
1709             LO_BYTE_SHIFT = 0;
1710         } else {
1711             HI_BYTE_SHIFT = 0;
1712             LO_BYTE_SHIFT = 8;
1713         }
1714     }
1715     */
1716     static final int HI_BYTE_SHIFT = 0;
1717     static final int LO_BYTE_SHIFT = 8;
1718 
1719     static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
1720 
1721     // Used by trusted callers.  Assumes all necessary bounds checks have
1722     // been done by the caller.
1723 
1724     /**
1725      * This is a variant of {@link Integer#getChars(int, int, byte[])}, but for
1726      * UTF-16 coder.
1727      *
1728      * @param i     value to convert
1729      * @param index next index, after the least significant digit
1730      * @param buf   target buffer, UTF16-coded.
1731      * @return index of the most significant digit or minus sign, if present
1732      */
1733     static int getChars(int i, int index, byte[] buf) {
1734         int q, r;
1735         int charPos = index;
1736 
1737         boolean negative = (i < 0);
1738         if (!negative) {
1739             i = -i;
1740         }
1741 
1742         // Get 2 digits/iteration using ints
1743         while (i <= -100) {
1744             q = i / 100;
1745             r = (q * 100) - i;
1746             i = q;
1747             putChar(buf, --charPos, Integer.DigitOnes[r]);
1748             putChar(buf, --charPos, Integer.DigitTens[r]);
1749         }
1750 
1751         // We know there are at most two digits left at this point.
1752         q = i / 10;
1753         r = (q * 10) - i;
1754         putChar(buf, --charPos, '0' + r);
1755 
1756         // Whatever left is the remaining digit.
1757         if (q < 0) {
1758             putChar(buf, --charPos, '0' - q);
1759         }
1760 
1761         if (negative) {
1762             putChar(buf, --charPos, '-');
1763         }
1764         return charPos;
1765     }
1766 
1767     /**
1768      * This is a variant of {@link Long#getChars(long, int, byte[])}, but for
1769      * UTF-16 coder.
1770      *
1771      * @param i     value to convert
1772      * @param index next index, after the least significant digit
1773      * @param buf   target buffer, UTF16-coded.
1774      * @return index of the most significant digit or minus sign, if present
1775      */
1776     static int getChars(long i, int index, byte[] buf) {
1777         long q;
1778         int r;
1779         int charPos = index;
1780 
1781         boolean negative = (i < 0);
1782         if (!negative) {
1783             i = -i;
1784         }
1785 
1786         // Get 2 digits/iteration using longs until quotient fits into an int
1787         while (i <= Integer.MIN_VALUE) {
1788             q = i / 100;
1789             r = (int)((q * 100) - i);
1790             i = q;
1791             putChar(buf, --charPos, Integer.DigitOnes[r]);
1792             putChar(buf, --charPos, Integer.DigitTens[r]);
1793         }
1794 
1795         // Get 2 digits/iteration using ints
1796         int q2;
1797         int i2 = (int)i;
1798         while (i2 <= -100) {
1799             q2 = i2 / 100;
1800             r  = (q2 * 100) - i2;
1801             i2 = q2;
1802             putChar(buf, --charPos, Integer.DigitOnes[r]);
1803             putChar(buf, --charPos, Integer.DigitTens[r]);
1804         }
1805 
1806         // We know there are at most two digits left at this point.
1807         q2 = i2 / 10;
1808         r  = (q2 * 10) - i2;
1809         putChar(buf, --charPos, '0' + r);
1810 
1811         // Whatever left is the remaining digit.
1812         if (q2 < 0) {
1813             putChar(buf, --charPos, '0' - q2);
1814         }
1815 
1816         if (negative) {
1817             putChar(buf, --charPos, '-');
1818         }
1819         return charPos;
1820     }
1821     // End of trusted methods.
1822 
1823     public static void checkIndex(int off, byte[] val) {
1824         String.checkIndex(off, length(val));
1825     }
1826 
1827     // BEGIN Android-added: Pass String instead of byte[].
1828     public static void checkIndex(int off, String val) {
1829         String.checkIndex(off, length(val));
1830     }
1831     // END Android-added: Pass String instead of byte[].
1832 
1833     public static void checkOffset(int off, byte[] val) {
1834         String.checkOffset(off, length(val));
1835     }
1836 
1837     public static void checkBoundsBeginEnd(int begin, int end, byte[] val) {
1838         String.checkBoundsBeginEnd(begin, end, length(val));
1839     }
1840 
1841     public static void checkBoundsOffCount(int offset, int count, byte[] val) {
1842         String.checkBoundsOffCount(offset, count, length(val));
1843     }
1844 
1845 }
1846