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