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