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