GNU Classpath (0.98) | |
Frames | No Frames |
1: /* String.java -- immutable character sequences; the object of string literals 2: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.lang; 41: 42: import gnu.java.lang.CharData; 43: import gnu.java.lang.CPStringBuilder; 44: 45: import java.io.Serializable; 46: import java.io.UnsupportedEncodingException; 47: import java.nio.ByteBuffer; 48: import java.nio.CharBuffer; 49: import java.nio.charset.CharacterCodingException; 50: import java.nio.charset.Charset; 51: import java.nio.charset.CharsetDecoder; 52: import java.nio.charset.CharsetEncoder; 53: import java.nio.charset.CodingErrorAction; 54: import java.nio.charset.IllegalCharsetNameException; 55: import java.nio.charset.UnsupportedCharsetException; 56: import java.text.Collator; 57: import java.util.Comparator; 58: import java.util.Formatter; 59: import java.util.Locale; 60: import java.util.regex.Matcher; 61: import java.util.regex.Pattern; 62: import java.util.regex.PatternSyntaxException; 63: 64: /** 65: * Strings represent an immutable set of characters. All String literals 66: * are instances of this class, and two string literals with the same contents 67: * refer to the same String object. 68: * 69: * <p>This class also includes a number of methods for manipulating the 70: * contents of strings (of course, creating a new object if there are any 71: * changes, as String is immutable). Case mapping relies on Unicode 3.0.0 72: * standards, where some character sequences have a different number of 73: * characters in the uppercase version than the lower case. 74: * 75: * <p>Strings are special, in that they are the only object with an overloaded 76: * operator. When you use '+' with at least one String argument, both 77: * arguments have String conversion performed on them, and another String (not 78: * guaranteed to be unique) results. 79: * 80: * <p>String is special-cased when doing data serialization - rather than 81: * listing the fields of this class, a String object is converted to a string 82: * literal in the object stream. 83: * 84: * @author Paul N. Fisher 85: * @author Eric Blake (ebb9@email.byu.edu) 86: * @author Per Bothner (bothner@cygnus.com) 87: * @author Tom Tromey (tromey@redhat.com) 88: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 89: * @since 1.0 90: * @status updated to 1.4; but could use better data sharing via offset field 91: */ 92: public final class String 93: implements Serializable, Comparable<String>, CharSequence 94: { 95: // WARNING: String is a CORE class in the bootstrap cycle. See the comments 96: // in vm/reference/java/lang/Runtime for implications of this fact. 97: 98: /** 99: * This is probably not necessary because this class is special cased already 100: * but it will avoid showing up as a discrepancy when comparing SUIDs. 101: */ 102: private static final long serialVersionUID = -6849794470754667710L; 103: 104: /** 105: * Stores unicode multi-character uppercase expansion table. 106: * @see #toUpperCase(Locale) 107: * @see CharData#UPPER_EXPAND 108: */ 109: private static final char[] upperExpand 110: = zeroBasedStringValue(CharData.UPPER_EXPAND); 111: 112: /** 113: * Stores unicode multi-character uppercase special casing table. 114: * @see #upperCaseExpansion(char) 115: * @see CharData#UPPER_SPECIAL 116: */ 117: private static final char[] upperSpecial 118: = zeroBasedStringValue(CharData.UPPER_SPECIAL); 119: 120: /** 121: * Characters which make up the String. 122: * Package access is granted for use by StringBuffer. 123: */ 124: final char[] value; 125: 126: /** 127: * Holds the number of characters in value. This number is generally 128: * the same as value.length, but can be smaller because substrings and 129: * StringBuffers can share arrays. Package visible for use by trusted code. 130: */ 131: final int count; 132: 133: /** 134: * Caches the result of hashCode(). If this value is zero, the hashcode 135: * is considered uncached (even if 0 is the correct hash value). 136: */ 137: private int cachedHashCode; 138: 139: /** 140: * Holds the starting position for characters in value[]. Since 141: * substring()'s are common, the use of offset allows the operation 142: * to perform in O(1). Package access is granted for use by StringBuffer. 143: */ 144: final int offset; 145: 146: /** 147: * An implementation for {@link #CASE_INSENSITIVE_ORDER}. 148: * This must be {@link Serializable}. The class name is dictated by 149: * compatibility with Sun's JDK. 150: */ 151: private static final class CaseInsensitiveComparator 152: implements Comparator<String>, Serializable 153: { 154: /** 155: * Compatible with JDK 1.2. 156: */ 157: private static final long serialVersionUID = 8575799808933029326L; 158: 159: /** 160: * The default private constructor generates unnecessary overhead. 161: */ 162: CaseInsensitiveComparator() {} 163: 164: /** 165: * Compares to Strings, using 166: * <code>String.compareToIgnoreCase(String)</code>. 167: * 168: * @param o1 the first string 169: * @param o2 the second string 170: * @return < 0, 0, or > 0 depending on the case-insensitive 171: * comparison of the two strings. 172: * @throws NullPointerException if either argument is null 173: * @throws ClassCastException if either argument is not a String 174: * @see #compareToIgnoreCase(String) 175: */ 176: public int compare(String o1, String o2) 177: { 178: return o1.compareToIgnoreCase(o2); 179: } 180: } // class CaseInsensitiveComparator 181: 182: /** 183: * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>. 184: * This comparator is {@link Serializable}. Note that it ignores Locale, 185: * for that, you want a Collator. 186: * 187: * @see Collator#compare(String, String) 188: * @since 1.2 189: */ 190: public static final Comparator<String> CASE_INSENSITIVE_ORDER 191: = new CaseInsensitiveComparator(); 192: 193: /** 194: * Creates an empty String (length 0). Unless you really need a new object, 195: * consider using <code>""</code> instead. 196: */ 197: public String() 198: { 199: value = "".value; 200: offset = 0; 201: count = 0; 202: } 203: 204: /** 205: * Copies the contents of a String to a new String. Since Strings are 206: * immutable, only a shallow copy is performed. 207: * 208: * @param str String to copy 209: * @throws NullPointerException if value is null 210: */ 211: public String(String str) 212: { 213: value = str.value; 214: offset = str.offset; 215: count = str.count; 216: cachedHashCode = str.cachedHashCode; 217: } 218: 219: /** 220: * Creates a new String using the character sequence of the char array. 221: * Subsequent changes to data do not affect the String. 222: * 223: * @param data char array to copy 224: * @throws NullPointerException if data is null 225: */ 226: public String(char[] data) 227: { 228: this(data, 0, data.length, false); 229: } 230: 231: /** 232: * Creates a new String using the character sequence of a subarray of 233: * characters. The string starts at offset, and copies count chars. 234: * Subsequent changes to data do not affect the String. 235: * 236: * @param data char array to copy 237: * @param offset position (base 0) to start copying out of data 238: * @param count the number of characters from data to copy 239: * @throws NullPointerException if data is null 240: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 241: * || offset + count < 0 (overflow) 242: * || offset + count > data.length) 243: * (while unspecified, this is a StringIndexOutOfBoundsException) 244: */ 245: public String(char[] data, int offset, int count) 246: { 247: this(data, offset, count, false); 248: } 249: 250: /** 251: * Creates a new String using an 8-bit array of integer values, starting at 252: * an offset, and copying up to the count. Each character c, using 253: * corresponding byte b, is created in the new String as if by performing: 254: * 255: * <pre> 256: * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) 257: * </pre> 258: * 259: * @param ascii array of integer values 260: * @param hibyte top byte of each Unicode character 261: * @param offset position (base 0) to start copying out of ascii 262: * @param count the number of characters from ascii to copy 263: * @throws NullPointerException if ascii is null 264: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 265: * || offset + count < 0 (overflow) 266: * || offset + count > ascii.length) 267: * (while unspecified, this is a StringIndexOutOfBoundsException) 268: * @see #String(byte[]) 269: * @see #String(byte[], String) 270: * @see #String(byte[], int, int) 271: * @see #String(byte[], int, int, String) 272: * @deprecated use {@link #String(byte[], int, int, String)} to perform 273: * correct encoding 274: */ 275: public String(byte[] ascii, int hibyte, int offset, int count) 276: { 277: if (offset < 0) 278: throw new StringIndexOutOfBoundsException("offset: " + offset); 279: if (count < 0) 280: throw new StringIndexOutOfBoundsException("count: " + count); 281: // equivalent to: offset + count < 0 || offset + count > ascii.length 282: if (ascii.length - offset < count) 283: throw new StringIndexOutOfBoundsException("offset + count: " 284: + (offset + count)); 285: value = new char[count]; 286: this.offset = 0; 287: this.count = count; 288: hibyte <<= 8; 289: offset += count; 290: while (--count >= 0) 291: value[count] = (char) (hibyte | (ascii[--offset] & 0xff)); 292: } 293: 294: /** 295: * Creates a new String using an 8-bit array of integer values. Each 296: * character c, using corresponding byte b, is created in the new String 297: * as if by performing: 298: * 299: * <pre> 300: * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) 301: * </pre> 302: * 303: * @param ascii array of integer values 304: * @param hibyte top byte of each Unicode character 305: * @throws NullPointerException if ascii is null 306: * @see #String(byte[]) 307: * @see #String(byte[], String) 308: * @see #String(byte[], int, int) 309: * @see #String(byte[], int, int, String) 310: * @see #String(byte[], int, int, int) 311: * @deprecated use {@link #String(byte[], String)} to perform 312: * correct encoding 313: */ 314: public String(byte[] ascii, int hibyte) 315: { 316: this(ascii, hibyte, 0, ascii.length); 317: } 318: 319: /** 320: * Creates a new String using the portion of the byte array starting at the 321: * offset and ending at offset + count. Uses the specified encoding type 322: * to decode the byte array, so the resulting string may be longer or 323: * shorter than the byte array. For more decoding control, use 324: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 325: * see {@link java.nio.charset.Charset}. The behavior is not specified if 326: * the decoder encounters invalid characters; this implementation throws 327: * an Error. 328: * 329: * @param data byte array to copy 330: * @param offset the offset to start at 331: * @param count the number of bytes in the array to use 332: * @param encoding the name of the encoding to use 333: * @throws NullPointerException if data or encoding is null 334: * @throws IndexOutOfBoundsException if offset or count is incorrect 335: * (while unspecified, this is a StringIndexOutOfBoundsException) 336: * @throws UnsupportedEncodingException if encoding is not found 337: * @throws Error if the decoding fails 338: * @since 1.1 339: */ 340: public String(byte[] data, int offset, int count, final String encoding) 341: throws UnsupportedEncodingException 342: { 343: this(data, offset, count, stringToCharset(encoding)); 344: } 345: 346: /** 347: * Wrapper method to convert exceptions resulting from 348: * the selection of a {@link java.nio.charset.Charset} based on 349: * a String. 350: * 351: * @throws UnsupportedEncodingException if encoding is not found 352: */ 353: private static final Charset stringToCharset(final String encoding) 354: throws UnsupportedEncodingException 355: { 356: try 357: { 358: return Charset.forName(encoding); 359: } 360: catch(IllegalCharsetNameException e) 361: { 362: throw new UnsupportedEncodingException("Encoding: "+encoding+ 363: " not found."); 364: } 365: catch(UnsupportedCharsetException e) 366: { 367: throw new UnsupportedEncodingException("Encoding: "+encoding+ 368: " not found."); 369: } 370: } 371: 372: /** 373: * Creates a new String using the portion of the byte array starting at the 374: * offset and ending at offset + count. Uses the specified encoding type 375: * to decode the byte array, so the resulting string may be longer or 376: * shorter than the byte array. For more decoding control, use 377: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 378: * see {@link java.nio.charset.Charset}. Malformed input and unmappable 379: * character sequences are replaced with the default replacement string 380: * provided by the {@link java.nio.charset.Charset}. 381: * 382: * @param data byte array to copy 383: * @param offset the offset to start at 384: * @param count the number of bytes in the array to use 385: * @param encoding the encoding to use 386: * @throws NullPointerException if data or encoding is null 387: * @throws IndexOutOfBoundsException if offset or count is incorrect 388: * (while unspecified, this is a StringIndexOutOfBoundsException) 389: * @since 1.6 390: */ 391: public String(byte[] data, int offset, int count, Charset encoding) 392: { 393: if (offset < 0) 394: throw new StringIndexOutOfBoundsException("offset: " + offset); 395: if (count < 0) 396: throw new StringIndexOutOfBoundsException("count: " + count); 397: // equivalent to: offset + count < 0 || offset + count > data.length 398: if (data.length - offset < count) 399: throw new StringIndexOutOfBoundsException("offset + count: " 400: + (offset + count)); 401: try 402: { 403: CharsetDecoder csd = encoding.newDecoder(); 404: csd.onMalformedInput(CodingErrorAction.REPLACE); 405: csd.onUnmappableCharacter(CodingErrorAction.REPLACE); 406: CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); 407: if(cbuf.hasArray()) 408: { 409: value = cbuf.array(); 410: this.offset = cbuf.position(); 411: this.count = cbuf.remaining(); 412: } else { 413: // Doubt this will happen. But just in case. 414: value = new char[cbuf.remaining()]; 415: cbuf.get(value); 416: this.offset = 0; 417: this.count = value.length; 418: } 419: } 420: catch(CharacterCodingException e) 421: { 422: // This shouldn't ever happen. 423: throw (InternalError) new InternalError().initCause(e); 424: } 425: } 426: 427: /** 428: * Creates a new String using the byte array. Uses the specified encoding 429: * type to decode the byte array, so the resulting string may be longer or 430: * shorter than the byte array. For more decoding control, use 431: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 432: * see {@link java.nio.charset.Charset}. The behavior is not specified if 433: * the decoder encounters invalid characters; this implementation throws 434: * an Error. 435: * 436: * @param data byte array to copy 437: * @param encoding the name of the encoding to use 438: * @throws NullPointerException if data or encoding is null 439: * @throws UnsupportedEncodingException if encoding is not found 440: * @throws Error if the decoding fails 441: * @see #String(byte[], int, int, String) 442: * @since 1.1 443: */ 444: public String(byte[] data, String encoding) 445: throws UnsupportedEncodingException 446: { 447: this(data, 0, data.length, encoding); 448: } 449: 450: /** 451: * Creates a new String using the byte array. Uses the specified encoding 452: * type to decode the byte array, so the resulting string may be longer or 453: * shorter than the byte array. For more decoding control, use 454: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 455: * see {@link java.nio.charset.Charset}. Malformed input and unmappable 456: * character sequences are replaced with the default replacement string 457: * provided by the {@link java.nio.charset.Charset}. 458: * 459: * @param data byte array to copy 460: * @param encoding the name of the encoding to use 461: * @throws NullPointerException if data or encoding is null 462: * @see #String(byte[], int, int, java.nio.Charset) 463: * @since 1.6 464: */ 465: public String(byte[] data, Charset encoding) 466: { 467: this(data, 0, data.length, encoding); 468: } 469: 470: /** 471: * Creates a new String using the portion of the byte array starting at the 472: * offset and ending at offset + count. Uses the encoding of the platform's 473: * default charset, so the resulting string may be longer or shorter than 474: * the byte array. For more decoding control, use 475: * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified 476: * if the decoder encounters invalid characters; this implementation throws 477: * an Error. 478: * 479: * @param data byte array to copy 480: * @param offset the offset to start at 481: * @param count the number of bytes in the array to use 482: * @throws NullPointerException if data is null 483: * @throws IndexOutOfBoundsException if offset or count is incorrect 484: * @throws Error if the decoding fails 485: * @see #String(byte[], int, int, String) 486: * @since 1.1 487: */ 488: public String(byte[] data, int offset, int count) 489: { 490: if (offset < 0) 491: throw new StringIndexOutOfBoundsException("offset: " + offset); 492: if (count < 0) 493: throw new StringIndexOutOfBoundsException("count: " + count); 494: // equivalent to: offset + count < 0 || offset + count > data.length 495: if (data.length - offset < count) 496: throw new StringIndexOutOfBoundsException("offset + count: " 497: + (offset + count)); 498: int o, c; 499: char[] v; 500: String encoding; 501: try 502: { 503: encoding = System.getProperty("file.encoding"); 504: CharsetDecoder csd = Charset.forName(encoding).newDecoder(); 505: csd.onMalformedInput(CodingErrorAction.REPLACE); 506: csd.onUnmappableCharacter(CodingErrorAction.REPLACE); 507: CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); 508: if(cbuf.hasArray()) 509: { 510: v = cbuf.array(); 511: o = cbuf.position(); 512: c = cbuf.remaining(); 513: } else { 514: // Doubt this will happen. But just in case. 515: v = new char[cbuf.remaining()]; 516: cbuf.get(v); 517: o = 0; 518: c = v.length; 519: } 520: } catch(Exception ex){ 521: // If anything goes wrong (System property not set, 522: // NIO provider not available, etc) 523: // Default to the 'safe' encoding ISO8859_1 524: v = new char[count]; 525: o = 0; 526: c = count; 527: for (int i=0;i<count;i++) 528: v[i] = (char)data[offset+i]; 529: } 530: this.value = v; 531: this.offset = o; 532: this.count = c; 533: } 534: 535: /** 536: * Creates a new String using the byte array. Uses the encoding of the 537: * platform's default charset, so the resulting string may be longer or 538: * shorter than the byte array. For more decoding control, use 539: * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified 540: * if the decoder encounters invalid characters; this implementation throws 541: * an Error. 542: * 543: * @param data byte array to copy 544: * @throws NullPointerException if data is null 545: * @throws Error if the decoding fails 546: * @see #String(byte[], int, int) 547: * @see #String(byte[], int, int, String) 548: * @since 1.1 549: */ 550: public String(byte[] data) 551: { 552: this(data, 0, data.length); 553: } 554: 555: /** 556: * Creates a new String using the character sequence represented by 557: * the StringBuffer. Subsequent changes to buf do not affect the String. 558: * 559: * @param buffer StringBuffer to copy 560: * @throws NullPointerException if buffer is null 561: */ 562: public String(StringBuffer buffer) 563: { 564: synchronized (buffer) 565: { 566: offset = 0; 567: count = buffer.count; 568: // Share unless buffer is 3/4 empty. 569: if ((count << 2) < buffer.value.length) 570: { 571: value = new char[count]; 572: VMSystem.arraycopy(buffer.value, 0, value, 0, count); 573: } 574: else 575: { 576: buffer.shared = true; 577: value = buffer.value; 578: } 579: } 580: } 581: 582: /** 583: * Creates a new String using the character sequence represented by 584: * the StringBuilder. Subsequent changes to buf do not affect the String. 585: * 586: * @param buffer StringBuilder to copy 587: * @throws NullPointerException if buffer is null 588: */ 589: public String(StringBuilder buffer) 590: { 591: this(buffer.value, 0, buffer.count); 592: } 593: 594: /** 595: * Special constructor which can share an array when safe to do so. 596: * 597: * @param data the characters to copy 598: * @param offset the location to start from 599: * @param count the number of characters to use 600: * @param dont_copy true if the array is trusted, and need not be copied 601: * @throws NullPointerException if chars is null 602: * @throws StringIndexOutOfBoundsException if bounds check fails 603: */ 604: String(char[] data, int offset, int count, boolean dont_copy) 605: { 606: if (offset < 0) 607: throw new StringIndexOutOfBoundsException("offset: " + offset); 608: if (count < 0) 609: throw new StringIndexOutOfBoundsException("count: " + count); 610: // equivalent to: offset + count < 0 || offset + count > data.length 611: if (data.length - offset < count) 612: throw new StringIndexOutOfBoundsException("offset + count: " 613: + (offset + count)); 614: if (dont_copy) 615: { 616: value = data; 617: this.offset = offset; 618: } 619: else 620: { 621: value = new char[count]; 622: VMSystem.arraycopy(data, offset, value, 0, count); 623: this.offset = 0; 624: } 625: this.count = count; 626: } 627: 628: /** 629: * Creates a new String containing the characters represented in the 630: * given subarray of Unicode code points. 631: * @param codePoints the entire array of code points 632: * @param offset the start of the subarray 633: * @param count the length of the subarray 634: * 635: * @throws IllegalArgumentException if an invalid code point is found 636: * in the codePoints array 637: * @throws IndexOutOfBoundsException if offset is negative or offset + count 638: * is greater than the length of the array. 639: */ 640: public String(int[] codePoints, int offset, int count) 641: { 642: // FIXME: This implementation appears to give correct internal 643: // representation of the String because: 644: // - length() is correct 645: // - getting a char[] from toCharArray() and testing 646: // Character.codePointAt() on all the characters in that array gives 647: // the appropriate results 648: // however printing the String gives incorrect results. This may be 649: // due to printing method errors (such as incorrectly looping through 650: // the String one char at a time rather than one "character" at a time. 651: 652: if (offset < 0) 653: throw new IndexOutOfBoundsException(); 654: int end = offset + count; 655: int pos = 0; 656: // This creates a char array that is long enough for all of the code 657: // points to represent supplementary characters. This is more than likely 658: // a waste of storage, so we use it only temporarily and then copy the 659: // used portion into the value array. 660: char[] temp = new char[2 * codePoints.length]; 661: for (int i = offset; i < end; i++) 662: { 663: pos += Character.toChars(codePoints[i], temp, pos); 664: } 665: this.count = pos; 666: this.value = new char[pos]; 667: System.arraycopy(temp, 0, value, 0, pos); 668: this.offset = 0; 669: } 670: 671: /** 672: * Returns the number of characters contained in this String. 673: * 674: * @return the length of this String 675: */ 676: public int length() 677: { 678: return count; 679: } 680: 681: /** 682: * Returns the character located at the specified index within this String. 683: * 684: * @param index position of character to return (base 0) 685: * @return character located at position index 686: * @throws IndexOutOfBoundsException if index < 0 || index >= length() 687: * (while unspecified, this is a StringIndexOutOfBoundsException) 688: */ 689: public char charAt(int index) 690: { 691: if (index < 0 || index >= count) 692: throw new StringIndexOutOfBoundsException(index); 693: return value[offset + index]; 694: } 695: 696: /** 697: * Get the code point at the specified index. This is like #charAt(int), 698: * but if the character is the start of a surrogate pair, and the 699: * following character completes the pair, then the corresponding 700: * supplementary code point is returned. 701: * @param index the index of the codepoint to get, starting at 0 702: * @return the codepoint at the specified index 703: * @throws IndexOutOfBoundsException if index is negative or >= length() 704: * @since 1.5 705: */ 706: public synchronized int codePointAt(int index) 707: { 708: // Use the CharSequence overload as we get better range checking 709: // this way. 710: return Character.codePointAt(this, index); 711: } 712: 713: /** 714: * Get the code point before the specified index. This is like 715: * #codePointAt(int), but checks the characters at <code>index-1</code> and 716: * <code>index-2</code> to see if they form a supplementary code point. 717: * @param index the index just past the codepoint to get, starting at 0 718: * @return the codepoint at the specified index 719: * @throws IndexOutOfBoundsException if index is negative or >= length() 720: * (while unspecified, this is a StringIndexOutOfBoundsException) 721: * @since 1.5 722: */ 723: public synchronized int codePointBefore(int index) 724: { 725: // Use the CharSequence overload as we get better range checking 726: // this way. 727: return Character.codePointBefore(this, index); 728: } 729: 730: /** 731: * Copies characters from this String starting at a specified start index, 732: * ending at a specified stop index, to a character array starting at 733: * a specified destination begin index. 734: * 735: * @param srcBegin index to begin copying characters from this String 736: * @param srcEnd index after the last character to be copied from this String 737: * @param dst character array which this String is copied into 738: * @param dstBegin index to start writing characters into dst 739: * @throws NullPointerException if dst is null 740: * @throws IndexOutOfBoundsException if any indices are out of bounds 741: * (while unspecified, source problems cause a 742: * StringIndexOutOfBoundsException, and dst problems cause an 743: * ArrayIndexOutOfBoundsException) 744: */ 745: public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) 746: { 747: if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) 748: throw new StringIndexOutOfBoundsException(); 749: VMSystem.arraycopy(value, srcBegin + offset, 750: dst, dstBegin, srcEnd - srcBegin); 751: } 752: 753: /** 754: * Copies the low byte of each character from this String starting at a 755: * specified start index, ending at a specified stop index, to a byte array 756: * starting at a specified destination begin index. 757: * 758: * @param srcBegin index to being copying characters from this String 759: * @param srcEnd index after the last character to be copied from this String 760: * @param dst byte array which each low byte of this String is copied into 761: * @param dstBegin index to start writing characters into dst 762: * @throws NullPointerException if dst is null and copy length is non-zero 763: * @throws IndexOutOfBoundsException if any indices are out of bounds 764: * (while unspecified, source problems cause a 765: * StringIndexOutOfBoundsException, and dst problems cause an 766: * ArrayIndexOutOfBoundsException) 767: * @see #getBytes() 768: * @see #getBytes(String) 769: * @deprecated use {@link #getBytes()}, which uses a char to byte encoder 770: */ 771: public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) 772: { 773: if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) 774: throw new StringIndexOutOfBoundsException(); 775: int i = srcEnd - srcBegin; 776: srcBegin += offset; 777: while (--i >= 0) 778: dst[dstBegin++] = (byte) value[srcBegin++]; 779: } 780: 781: /** 782: * Converts the Unicode characters in this String to a byte array. Uses the 783: * specified encoding method, so the result may be longer or shorter than 784: * the String. For more encoding control, use 785: * {@link java.nio.charset.CharsetEncoder}, and for valid character sets, 786: * see {@link java.nio.charset.Charset}. Unsupported characters get 787: * replaced by an encoding specific byte. 788: * 789: * @param enc encoding name 790: * @return the resulting byte array 791: * @throws NullPointerException if enc is null 792: * @throws UnsupportedEncodingException if encoding is not supported 793: * @since 1.1 794: */ 795: public byte[] getBytes(final String enc) 796: throws UnsupportedEncodingException 797: { 798: return getBytes(stringToCharset(enc)); 799: } 800: 801: /** 802: * Converts the Unicode characters in this String to a byte array. Uses the 803: * specified encoding method, so the result may be longer or shorter than 804: * the String. For more encoding control, use 805: * {@link java.nio.charset.CharsetEncoder}, and for valid character sets, 806: * see {@link java.nio.charset.Charset}. Unsupported characters get 807: * replaced by the {@link java.nio.charset.Charset}'s default replacement. 808: * 809: * @param enc encoding name 810: * @return the resulting byte array 811: * @throws NullPointerException if enc is null 812: * @since 1.6 813: */ 814: public byte[] getBytes(Charset enc) 815: { 816: try 817: { 818: CharsetEncoder cse = enc.newEncoder(); 819: cse.onMalformedInput(CodingErrorAction.REPLACE); 820: cse.onUnmappableCharacter(CodingErrorAction.REPLACE); 821: ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count)); 822: if(bbuf.hasArray()) 823: return bbuf.array(); 824: 825: // Doubt this will happen. But just in case. 826: byte[] bytes = new byte[bbuf.remaining()]; 827: bbuf.get(bytes); 828: return bytes; 829: } 830: catch(CharacterCodingException e) 831: { 832: // This shouldn't ever happen. 833: throw (InternalError) new InternalError().initCause(e); 834: } 835: } 836: 837: /** 838: * Converts the Unicode characters in this String to a byte array. Uses the 839: * encoding of the platform's default charset, so the result may be longer 840: * or shorter than the String. For more encoding control, use 841: * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get 842: * replaced by an encoding specific byte. 843: * 844: * @return the resulting byte array, or null on a problem 845: * @since 1.1 846: */ 847: public byte[] getBytes() 848: { 849: try 850: { 851: return getBytes(System.getProperty("file.encoding")); 852: } catch(Exception e) { 853: // XXX - Throw an error here? 854: // For now, default to the 'safe' encoding. 855: byte[] bytes = new byte[count]; 856: for(int i=0;i<count;i++) 857: bytes[i] = (byte)((value[offset+i] <= 0xFF)? 858: value[offset+i]:'?'); 859: return bytes; 860: } 861: } 862: 863: /** 864: * Predicate which compares anObject to this. This is true only for Strings 865: * with the same character sequence. 866: * 867: * @param anObject the object to compare 868: * @return true if anObject is semantically equal to this 869: * @see #compareTo(String) 870: * @see #equalsIgnoreCase(String) 871: */ 872: public boolean equals(Object anObject) 873: { 874: if (! (anObject instanceof String)) 875: return false; 876: String str2 = (String) anObject; 877: if (count != str2.count) 878: return false; 879: if (value == str2.value && offset == str2.offset) 880: return true; 881: int i = count; 882: int x = offset; 883: int y = str2.offset; 884: while (--i >= 0) 885: if (value[x++] != str2.value[y++]) 886: return false; 887: return true; 888: } 889: 890: /** 891: * Compares the given StringBuffer to this String. This is true if the 892: * StringBuffer has the same content as this String at this moment. 893: * 894: * @param buffer the StringBuffer to compare to 895: * @return true if StringBuffer has the same character sequence 896: * @throws NullPointerException if the given StringBuffer is null 897: * @since 1.4 898: */ 899: public boolean contentEquals(StringBuffer buffer) 900: { 901: synchronized (buffer) 902: { 903: if (count != buffer.count) 904: return false; 905: if (value == buffer.value) 906: return true; // Possible if shared. 907: int i = count; 908: int x = offset + count; 909: while (--i >= 0) 910: if (value[--x] != buffer.value[i]) 911: return false; 912: return true; 913: } 914: } 915: 916: /** 917: * Compares the given CharSequence to this String. This is true if 918: * the CharSequence has the same content as this String at this 919: * moment. 920: * 921: * @param seq the CharSequence to compare to 922: * @return true if CharSequence has the same character sequence 923: * @throws NullPointerException if the given CharSequence is null 924: * @since 1.5 925: */ 926: public boolean contentEquals(CharSequence seq) 927: { 928: if (seq.length() != count) 929: return false; 930: for (int i = 0; i < count; ++i) 931: if (value[offset + i] != seq.charAt(i)) 932: return false; 933: return true; 934: } 935: 936: /** 937: * Compares a String to this String, ignoring case. This does not handle 938: * multi-character capitalization exceptions; instead the comparison is 939: * made on a character-by-character basis, and is true if:<br><ul> 940: * <li><code>c1 == c2</code></li> 941: * <li><code>Character.toUpperCase(c1) 942: * == Character.toUpperCase(c2)</code></li> 943: * <li><code>Character.toLowerCase(c1) 944: * == Character.toLowerCase(c2)</code></li> 945: * </ul> 946: * 947: * @param anotherString String to compare to this String 948: * @return true if anotherString is equal, ignoring case 949: * @see #equals(Object) 950: * @see Character#toUpperCase(char) 951: * @see Character#toLowerCase(char) 952: */ 953: public boolean equalsIgnoreCase(String anotherString) 954: { 955: if (anotherString == null || count != anotherString.count) 956: return false; 957: int i = count; 958: int x = offset; 959: int y = anotherString.offset; 960: while (--i >= 0) 961: { 962: char c1 = value[x++]; 963: char c2 = anotherString.value[y++]; 964: // Note that checking c1 != c2 is redundant, but avoids method calls. 965: if (c1 != c2 966: && Character.toUpperCase(c1) != Character.toUpperCase(c2) 967: && Character.toLowerCase(c1) != Character.toLowerCase(c2)) 968: return false; 969: } 970: return true; 971: } 972: 973: /** 974: * Compares this String and another String (case sensitive, 975: * lexicographically). The result is less than 0 if this string sorts 976: * before the other, 0 if they are equal, and greater than 0 otherwise. 977: * After any common starting sequence is skipped, the result is 978: * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings 979: * have characters remaining, or 980: * <code>this.length() - anotherString.length()</code> if one string is 981: * a subsequence of the other. 982: * 983: * @param anotherString the String to compare against 984: * @return the comparison 985: * @throws NullPointerException if anotherString is null 986: */ 987: public int compareTo(String anotherString) 988: { 989: int i = Math.min(count, anotherString.count); 990: int x = offset; 991: int y = anotherString.offset; 992: while (--i >= 0) 993: { 994: int result = value[x++] - anotherString.value[y++]; 995: if (result != 0) 996: return result; 997: } 998: return count - anotherString.count; 999: } 1000: 1001: /** 1002: * Compares this String and another String (case insensitive). This 1003: * comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores 1004: * locale and multi-characater capitalization, and compares characters 1005: * after performing 1006: * <code>Character.toLowerCase(Character.toUpperCase(c))</code> on each 1007: * character of the string. This is unsatisfactory for locale-based 1008: * comparison, in which case you should use {@link java.text.Collator}. 1009: * 1010: * @param str the string to compare against 1011: * @return the comparison 1012: * @see Collator#compare(String, String) 1013: * @since 1.2 1014: */ 1015: public int compareToIgnoreCase(String str) 1016: { 1017: int i = Math.min(count, str.count); 1018: int x = offset; 1019: int y = str.offset; 1020: while (--i >= 0) 1021: { 1022: int result = Character.toLowerCase(Character.toUpperCase(value[x++])) 1023: - Character.toLowerCase(Character.toUpperCase(str.value[y++])); 1024: if (result != 0) 1025: return result; 1026: } 1027: return count - str.count; 1028: } 1029: 1030: /** 1031: * Predicate which determines if this String matches another String 1032: * starting at a specified offset for each String and continuing 1033: * for a specified length. Indices out of bounds are harmless, and give 1034: * a false result. 1035: * 1036: * @param toffset index to start comparison at for this String 1037: * @param other String to compare region to this String 1038: * @param ooffset index to start comparison at for other 1039: * @param len number of characters to compare 1040: * @return true if regions match (case sensitive) 1041: * @throws NullPointerException if other is null 1042: */ 1043: public boolean regionMatches(int toffset, String other, int ooffset, int len) 1044: { 1045: return regionMatches(false, toffset, other, ooffset, len); 1046: } 1047: 1048: /** 1049: * Predicate which determines if this String matches another String 1050: * starting at a specified offset for each String and continuing 1051: * for a specified length, optionally ignoring case. Indices out of bounds 1052: * are harmless, and give a false result. Case comparisons are based on 1053: * <code>Character.toLowerCase()</code> and 1054: * <code>Character.toUpperCase()</code>, not on multi-character 1055: * capitalization expansions. 1056: * 1057: * @param ignoreCase true if case should be ignored in comparision 1058: * @param toffset index to start comparison at for this String 1059: * @param other String to compare region to this String 1060: * @param ooffset index to start comparison at for other 1061: * @param len number of characters to compare 1062: * @return true if regions match, false otherwise 1063: * @throws NullPointerException if other is null 1064: */ 1065: public boolean regionMatches(boolean ignoreCase, int toffset, 1066: String other, int ooffset, int len) 1067: { 1068: if (toffset < 0 || ooffset < 0 || toffset + len > count 1069: || ooffset + len > other.count) 1070: return false; 1071: toffset += offset; 1072: ooffset += other.offset; 1073: while (--len >= 0) 1074: { 1075: char c1 = value[toffset++]; 1076: char c2 = other.value[ooffset++]; 1077: // Note that checking c1 != c2 is redundant when ignoreCase is true, 1078: // but it avoids method calls. 1079: if (c1 != c2 1080: && (! ignoreCase 1081: || (Character.toLowerCase(c1) != Character.toLowerCase(c2) 1082: && (Character.toUpperCase(c1) 1083: != Character.toUpperCase(c2))))) 1084: return false; 1085: } 1086: return true; 1087: } 1088: 1089: /** 1090: * Predicate which determines if this String contains the given prefix, 1091: * beginning comparison at toffset. The result is false if toffset is 1092: * negative or greater than this.length(), otherwise it is the same as 1093: * <code>this.substring(toffset).startsWith(prefix)</code>. 1094: * 1095: * @param prefix String to compare 1096: * @param toffset offset for this String where comparison starts 1097: * @return true if this String starts with prefix 1098: * @throws NullPointerException if prefix is null 1099: * @see #regionMatches(boolean, int, String, int, int) 1100: */ 1101: public boolean startsWith(String prefix, int toffset) 1102: { 1103: return regionMatches(false, toffset, prefix, 0, prefix.count); 1104: } 1105: 1106: /** 1107: * Predicate which determines if this String starts with a given prefix. 1108: * If the prefix is an empty String, true is returned. 1109: * 1110: * @param prefix String to compare 1111: * @return true if this String starts with the prefix 1112: * @throws NullPointerException if prefix is null 1113: * @see #startsWith(String, int) 1114: */ 1115: public boolean startsWith(String prefix) 1116: { 1117: return regionMatches(false, 0, prefix, 0, prefix.count); 1118: } 1119: 1120: /** 1121: * Predicate which determines if this String ends with a given suffix. 1122: * If the suffix is an empty String, true is returned. 1123: * 1124: * @param suffix String to compare 1125: * @return true if this String ends with the suffix 1126: * @throws NullPointerException if suffix is null 1127: * @see #regionMatches(boolean, int, String, int, int) 1128: */ 1129: public boolean endsWith(String suffix) 1130: { 1131: return regionMatches(false, count - suffix.count, suffix, 0, suffix.count); 1132: } 1133: 1134: /** 1135: * Computes the hashcode for this String. This is done with int arithmetic, 1136: * where ** represents exponentiation, by this formula:<br> 1137: * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>. 1138: * 1139: * @return hashcode value of this String 1140: */ 1141: public int hashCode() 1142: { 1143: if (cachedHashCode != 0) 1144: return cachedHashCode; 1145: 1146: // Compute the hash code using a local variable to be reentrant. 1147: int hashCode = 0; 1148: int limit = count + offset; 1149: for (int i = offset; i < limit; i++) 1150: hashCode = hashCode * 31 + value[i]; 1151: return cachedHashCode = hashCode; 1152: } 1153: 1154: /** 1155: * Finds the first instance of a character in this String. 1156: * 1157: * @param ch character to find 1158: * @return location (base 0) of the character, or -1 if not found 1159: */ 1160: public int indexOf(int ch) 1161: { 1162: return indexOf(ch, 0); 1163: } 1164: 1165: /** 1166: * Finds the first instance of a character in this String, starting at 1167: * a given index. If starting index is less than 0, the search 1168: * starts at the beginning of this String. If the starting index 1169: * is greater than the length of this String, -1 is returned. 1170: * 1171: * @param ch character to find 1172: * @param fromIndex index to start the search 1173: * @return location (base 0) of the character, or -1 if not found 1174: */ 1175: public int indexOf(int ch, int fromIndex) 1176: { 1177: if ((char) ch != ch) 1178: return -1; 1179: if (fromIndex < 0) 1180: fromIndex = 0; 1181: int i = fromIndex + offset; 1182: for ( ; fromIndex < count; fromIndex++) 1183: if (value[i++] == ch) 1184: return fromIndex; 1185: return -1; 1186: } 1187: 1188: /** 1189: * Finds the last instance of a character in this String. 1190: * 1191: * @param ch character to find 1192: * @return location (base 0) of the character, or -1 if not found 1193: */ 1194: public int lastIndexOf(int ch) 1195: { 1196: return lastIndexOf(ch, count - 1); 1197: } 1198: 1199: /** 1200: * Finds the last instance of a character in this String, starting at 1201: * a given index. If starting index is greater than the maximum valid 1202: * index, then the search begins at the end of this String. If the 1203: * starting index is less than zero, -1 is returned. 1204: * 1205: * @param ch character to find 1206: * @param fromIndex index to start the search 1207: * @return location (base 0) of the character, or -1 if not found 1208: */ 1209: public int lastIndexOf(int ch, int fromIndex) 1210: { 1211: if ((char) ch != ch) 1212: return -1; 1213: if (fromIndex >= count) 1214: fromIndex = count - 1; 1215: int i = fromIndex + offset; 1216: for ( ; fromIndex >= 0; fromIndex--) 1217: if (value[i--] == ch) 1218: return fromIndex; 1219: return -1; 1220: } 1221: 1222: /** 1223: * Finds the first instance of a String in this String. 1224: * 1225: * @param str String to find 1226: * @return location (base 0) of the String, or -1 if not found 1227: * @throws NullPointerException if str is null 1228: */ 1229: public int indexOf(String str) 1230: { 1231: return indexOf(str, 0); 1232: } 1233: 1234: /** 1235: * Finds the first instance of a String in this String, starting at 1236: * a given index. If starting index is less than 0, the search 1237: * starts at the beginning of this String. If the starting index 1238: * is greater than the length of this String, -1 is returned. 1239: * 1240: * @param str String to find 1241: * @param fromIndex index to start the search 1242: * @return location (base 0) of the String, or -1 if not found 1243: * @throws NullPointerException if str is null 1244: */ 1245: public int indexOf(String str, int fromIndex) 1246: { 1247: if (fromIndex < 0) 1248: fromIndex = 0; 1249: int limit = count - str.count; 1250: for ( ; fromIndex <= limit; fromIndex++) 1251: if (regionMatches(fromIndex, str, 0, str.count)) 1252: return fromIndex; 1253: return -1; 1254: } 1255: 1256: /** 1257: * Finds the last instance of a String in this String. 1258: * 1259: * @param str String to find 1260: * @return location (base 0) of the String, or -1 if not found 1261: * @throws NullPointerException if str is null 1262: */ 1263: public int lastIndexOf(String str) 1264: { 1265: return lastIndexOf(str, count - str.count); 1266: } 1267: 1268: /** 1269: * Finds the last instance of a String in this String, starting at 1270: * a given index. If starting index is greater than the maximum valid 1271: * index, then the search begins at the end of this String. If the 1272: * starting index is less than zero, -1 is returned. 1273: * 1274: * @param str String to find 1275: * @param fromIndex index to start the search 1276: * @return location (base 0) of the String, or -1 if not found 1277: * @throws NullPointerException if str is null 1278: */ 1279: public int lastIndexOf(String str, int fromIndex) 1280: { 1281: fromIndex = Math.min(fromIndex, count - str.count); 1282: for ( ; fromIndex >= 0; fromIndex--) 1283: if (regionMatches(fromIndex, str, 0, str.count)) 1284: return fromIndex; 1285: return -1; 1286: } 1287: 1288: /** 1289: * Creates a substring of this String, starting at a specified index 1290: * and ending at the end of this String. 1291: * 1292: * @param begin index to start substring (base 0) 1293: * @return new String which is a substring of this String 1294: * @throws IndexOutOfBoundsException if begin < 0 || begin > length() 1295: * (while unspecified, this is a StringIndexOutOfBoundsException) 1296: */ 1297: public String substring(int begin) 1298: { 1299: return substring(begin, count); 1300: } 1301: 1302: /** 1303: * Creates a substring of this String, starting at a specified index 1304: * and ending at one character before a specified index. 1305: * 1306: * @param beginIndex index to start substring (inclusive, base 0) 1307: * @param endIndex index to end at (exclusive) 1308: * @return new String which is a substring of this String 1309: * @throws IndexOutOfBoundsException if begin < 0 || end > length() 1310: * || begin > end (while unspecified, this is a 1311: * StringIndexOutOfBoundsException) 1312: */ 1313: public String substring(int beginIndex, int endIndex) 1314: { 1315: if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) 1316: throw new StringIndexOutOfBoundsException(); 1317: if (beginIndex == 0 && endIndex == count) 1318: return this; 1319: int len = endIndex - beginIndex; 1320: // Package constructor avoids an array copy. 1321: return new String(value, beginIndex + offset, len, 1322: (len << 2) >= value.length); 1323: } 1324: 1325: /** 1326: * Creates a substring of this String, starting at a specified index 1327: * and ending at one character before a specified index. This behaves like 1328: * <code>substring(begin, end)</code>. 1329: * 1330: * @param begin index to start substring (inclusive, base 0) 1331: * @param end index to end at (exclusive) 1332: * @return new String which is a substring of this String 1333: * @throws IndexOutOfBoundsException if begin < 0 || end > length() 1334: * || begin > end 1335: * @since 1.4 1336: */ 1337: public CharSequence subSequence(int begin, int end) 1338: { 1339: return substring(begin, end); 1340: } 1341: 1342: /** 1343: * Concatenates a String to this String. This results in a new string unless 1344: * one of the two originals is "". 1345: * 1346: * @param str String to append to this String 1347: * @return newly concatenated String 1348: * @throws NullPointerException if str is null 1349: */ 1350: public String concat(String str) 1351: { 1352: if (str.count == 0) 1353: return this; 1354: if (count == 0) 1355: return str; 1356: char[] newStr = new char[count + str.count]; 1357: VMSystem.arraycopy(value, offset, newStr, 0, count); 1358: VMSystem.arraycopy(str.value, str.offset, newStr, count, str.count); 1359: // Package constructor avoids an array copy. 1360: return new String(newStr, 0, newStr.length, true); 1361: } 1362: 1363: /** 1364: * Replaces every instance of a character in this String with a new 1365: * character. If no replacements occur, this is returned. 1366: * 1367: * @param oldChar the old character to replace 1368: * @param newChar the new character 1369: * @return new String with all instances of oldChar replaced with newChar 1370: */ 1371: public String replace(char oldChar, char newChar) 1372: { 1373: if (oldChar == newChar) 1374: return this; 1375: int i = count; 1376: int x = offset - 1; 1377: while (--i >= 0) 1378: if (value[++x] == oldChar) 1379: break; 1380: if (i < 0) 1381: return this; 1382: char[] newStr = toCharArray(); 1383: newStr[x - offset] = newChar; 1384: while (--i >= 0) 1385: if (value[++x] == oldChar) 1386: newStr[x - offset] = newChar; 1387: // Package constructor avoids an array copy. 1388: return new String(newStr, 0, count, true); 1389: } 1390: 1391: /** 1392: * Test if this String matches a regular expression. This is shorthand for 1393: * <code>{@link Pattern}.matches(regex, this)</code>. 1394: * 1395: * @param regex the pattern to match 1396: * @return true if the pattern matches 1397: * @throws NullPointerException if regex is null 1398: * @throws PatternSyntaxException if regex is invalid 1399: * @see Pattern#matches(String, CharSequence) 1400: * @since 1.4 1401: */ 1402: public boolean matches(String regex) 1403: { 1404: return Pattern.matches(regex, this); 1405: } 1406: 1407: /** 1408: * Replaces the first substring match of the regular expression with a 1409: * given replacement. This is shorthand for <code>{@link Pattern} 1410: * .compile(regex).matcher(this).replaceFirst(replacement)</code>. 1411: * 1412: * @param regex the pattern to match 1413: * @param replacement the replacement string 1414: * @return the modified string 1415: * @throws NullPointerException if regex or replacement is null 1416: * @throws PatternSyntaxException if regex is invalid 1417: * @see #replaceAll(String, String) 1418: * @see Pattern#compile(String) 1419: * @see Pattern#matcher(CharSequence) 1420: * @see Matcher#replaceFirst(String) 1421: * @since 1.4 1422: */ 1423: public String replaceFirst(String regex, String replacement) 1424: { 1425: return Pattern.compile(regex).matcher(this).replaceFirst(replacement); 1426: } 1427: 1428: /** 1429: * Replaces all matching substrings of the regular expression with a 1430: * given replacement. This is shorthand for <code>{@link Pattern} 1431: * .compile(regex).matcher(this).replaceAll(replacement)</code>. 1432: * 1433: * @param regex the pattern to match 1434: * @param replacement the replacement string 1435: * @return the modified string 1436: * @throws NullPointerException if regex or replacement is null 1437: * @throws PatternSyntaxException if regex is invalid 1438: * @see #replaceFirst(String, String) 1439: * @see Pattern#compile(String) 1440: * @see Pattern#matcher(CharSequence) 1441: * @see Matcher#replaceAll(String) 1442: * @since 1.4 1443: */ 1444: public String replaceAll(String regex, String replacement) 1445: { 1446: return Pattern.compile(regex).matcher(this).replaceAll(replacement); 1447: } 1448: 1449: /** 1450: * Split this string around the matches of a regular expression. Each 1451: * element of the returned array is the largest block of characters not 1452: * terminated by the regular expression, in the order the matches are found. 1453: * 1454: * <p>The limit affects the length of the array. If it is positive, the 1455: * array will contain at most n elements (n - 1 pattern matches). If 1456: * negative, the array length is unlimited, but there can be trailing empty 1457: * entries. if 0, the array length is unlimited, and trailing empty entries 1458: * are discarded. 1459: * 1460: * <p>For example, splitting "boo:and:foo" yields:<br> 1461: * <table border=0> 1462: * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th> 1463: * <tr><td>":"</td> <td>2</td> <td>{ "boo", "and:foo" }</td></tr> 1464: * <tr><td>":"</td> <td>t</td> <td>{ "boo", "and", "foo" }</td></tr> 1465: * <tr><td>":"</td> <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr> 1466: * <tr><td>"o"</td> <td>5</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> 1467: * <tr><td>"o"</td> <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> 1468: * <tr><td>"o"</td> <td>0</td> <td>{ "b", "", ":and:f" }</td></tr> 1469: * </table> 1470: * 1471: * <p>This is shorthand for 1472: * <code>{@link Pattern}.compile(regex).split(this, limit)</code>. 1473: * 1474: * @param regex the pattern to match 1475: * @param limit the limit threshold 1476: * @return the array of split strings 1477: * @throws NullPointerException if regex or replacement is null 1478: * @throws PatternSyntaxException if regex is invalid 1479: * @see Pattern#compile(String) 1480: * @see Pattern#split(CharSequence, int) 1481: * @since 1.4 1482: */ 1483: public String[] split(String regex, int limit) 1484: { 1485: return Pattern.compile(regex).split(this, limit); 1486: } 1487: 1488: /** 1489: * Split this string around the matches of a regular expression. Each 1490: * element of the returned array is the largest block of characters not 1491: * terminated by the regular expression, in the order the matches are found. 1492: * The array length is unlimited, and trailing empty entries are discarded, 1493: * as though calling <code>split(regex, 0)</code>. 1494: * 1495: * @param regex the pattern to match 1496: * @return the array of split strings 1497: * @throws NullPointerException if regex or replacement is null 1498: * @throws PatternSyntaxException if regex is invalid 1499: * @see #split(String, int) 1500: * @see Pattern#compile(String) 1501: * @see Pattern#split(CharSequence, int) 1502: * @since 1.4 1503: */ 1504: public String[] split(String regex) 1505: { 1506: return Pattern.compile(regex).split(this, 0); 1507: } 1508: 1509: /** 1510: * Convert string to lower case for a Turkish locale that requires special 1511: * handling of '\u0049' 1512: */ 1513: private String toLowerCaseTurkish() 1514: { 1515: // First, see if the current string is already lower case. 1516: int i = count; 1517: int x = offset - 1; 1518: while (--i >= 0) 1519: { 1520: char ch = value[++x]; 1521: if ((ch == '\u0049') || ch != Character.toLowerCase(ch)) 1522: break; 1523: } 1524: if (i < 0) 1525: return this; 1526: 1527: // Now we perform the conversion. Fortunately, there are no multi-character 1528: // lowercase expansions in Unicode 3.0.0. 1529: char[] newStr = new char[count]; 1530: VMSystem.arraycopy(value, offset, newStr, 0, x - offset); 1531: do 1532: { 1533: char ch = value[x]; 1534: // Hardcoded special case. 1535: if (ch != '\u0049') 1536: { 1537: newStr[x - offset] = Character.toLowerCase(ch); 1538: } 1539: else 1540: { 1541: newStr[x - offset] = '\u0131'; 1542: } 1543: x++; 1544: } 1545: while (--i >= 0); 1546: // Package constructor avoids an array copy. 1547: return new String(newStr, 0, count, true); 1548: } 1549: 1550: /** 1551: * Lowercases this String according to a particular locale. This uses 1552: * Unicode's special case mappings, as applied to the given Locale, so the 1553: * resulting string may be a different length. 1554: * 1555: * @param loc locale to use 1556: * @return new lowercased String, or this if no characters were lowercased 1557: * @throws NullPointerException if loc is null 1558: * @see #toUpperCase(Locale) 1559: * @since 1.1 1560: */ 1561: public String toLowerCase(Locale loc) 1562: { 1563: // First, see if the current string is already lower case. 1564: 1565: // Is loc turkish? String equality test is ok as Locale.language is interned 1566: if ("tr" == loc.getLanguage()) 1567: { 1568: return toLowerCaseTurkish(); 1569: } 1570: else 1571: { 1572: int i = count; 1573: int x = offset - 1; 1574: while (--i >= 0) 1575: { 1576: char ch = value[++x]; 1577: if (ch != Character.toLowerCase(ch)) 1578: break; 1579: } 1580: if (i < 0) 1581: return this; 1582: 1583: // Now we perform the conversion. Fortunately, there are no 1584: // multi-character lowercase expansions in Unicode 3.0.0. 1585: char[] newStr = new char[count]; 1586: VMSystem.arraycopy(value, offset, newStr, 0, x - offset); 1587: do 1588: { 1589: char ch = value[x]; 1590: // Hardcoded special case. 1591: newStr[x - offset] = Character.toLowerCase(ch); 1592: x++; 1593: } 1594: while (--i >= 0); 1595: // Package constructor avoids an array copy. 1596: return new String(newStr, 0, count, true); 1597: } 1598: } 1599: 1600: /** 1601: * Lowercases this String. This uses Unicode's special case mappings, as 1602: * applied to the platform's default Locale, so the resulting string may 1603: * be a different length. 1604: * 1605: * @return new lowercased String, or this if no characters were lowercased 1606: * @see #toLowerCase(Locale) 1607: * @see #toUpperCase() 1608: */ 1609: public String toLowerCase() 1610: { 1611: return toLowerCase(Locale.getDefault()); 1612: } 1613: 1614: /** 1615: * Uppercase this string for a Turkish locale 1616: */ 1617: private String toUpperCaseTurkish() 1618: { 1619: // First, see how many characters we have to grow by, as well as if the 1620: // current string is already upper case. 1621: int expand = 0; 1622: boolean unchanged = true; 1623: int i = count; 1624: int x = i + offset; 1625: while (--i >= 0) 1626: { 1627: char ch = value[--x]; 1628: expand += upperCaseExpansion(ch); 1629: unchanged = (unchanged && expand == 0 1630: && ch != '\u0069' 1631: && ch == Character.toUpperCase(ch)); 1632: } 1633: if (unchanged) 1634: return this; 1635: 1636: // Now we perform the conversion. 1637: i = count; 1638: if (expand == 0) 1639: { 1640: char[] newStr = new char[count]; 1641: VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); 1642: while (--i >= 0) 1643: { 1644: char ch = value[x]; 1645: // Hardcoded special case. 1646: if (ch != '\u0069') 1647: { 1648: newStr[x - offset] = Character.toUpperCase(ch); 1649: } 1650: else 1651: { 1652: newStr[x - offset] = '\u0130'; 1653: } 1654: x++; 1655: } 1656: // Package constructor avoids an array copy. 1657: return new String(newStr, 0, count, true); 1658: } 1659: 1660: // Expansion is necessary. 1661: char[] newStr = new char[count + expand]; 1662: int j = 0; 1663: while (--i >= 0) 1664: { 1665: char ch = value[x++]; 1666: // Hardcoded special case. 1667: if (ch == '\u0069') 1668: { 1669: newStr[j++] = '\u0130'; 1670: continue; 1671: } 1672: expand = upperCaseExpansion(ch); 1673: if (expand > 0) 1674: { 1675: int index = upperCaseIndex(ch); 1676: while (expand-- >= 0) 1677: newStr[j++] = upperExpand[index++]; 1678: } 1679: else 1680: newStr[j++] = Character.toUpperCase(ch); 1681: } 1682: // Package constructor avoids an array copy. 1683: return new String(newStr, 0, newStr.length, true); 1684: } 1685: 1686: /** 1687: * Uppercases this String according to a particular locale. This uses 1688: * Unicode's special case mappings, as applied to the given Locale, so the 1689: * resulting string may be a different length. 1690: * 1691: * @param loc locale to use 1692: * @return new uppercased String, or this if no characters were uppercased 1693: * @throws NullPointerException if loc is null 1694: * @see #toLowerCase(Locale) 1695: * @since 1.1 1696: */ 1697: public String toUpperCase(Locale loc) 1698: { 1699: // First, see how many characters we have to grow by, as well as if the 1700: // current string is already upper case. 1701: 1702: // Is loc turkish? String equality test is ok as Locale.language is interned 1703: if ("tr" == loc.getLanguage()) 1704: { 1705: return toUpperCaseTurkish(); 1706: } 1707: else 1708: { 1709: int expand = 0; 1710: boolean unchanged = true; 1711: int i = count; 1712: int x = i + offset; 1713: while (--i >= 0) 1714: { 1715: char ch = value[--x]; 1716: expand += upperCaseExpansion(ch); 1717: unchanged = (unchanged && expand == 0 1718: && ch == Character.toUpperCase(ch)); 1719: } 1720: if (unchanged) 1721: return this; 1722: 1723: // Now we perform the conversion. 1724: i = count; 1725: if (expand == 0) 1726: { 1727: char[] newStr = new char[count]; 1728: VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); 1729: while (--i >= 0) 1730: { 1731: char ch = value[x]; 1732: newStr[x - offset] = Character.toUpperCase(ch); 1733: x++; 1734: } 1735: // Package constructor avoids an array copy. 1736: return new String(newStr, 0, count, true); 1737: } 1738: 1739: // Expansion is necessary. 1740: char[] newStr = new char[count + expand]; 1741: int j = 0; 1742: while (--i >= 0) 1743: { 1744: char ch = value[x++]; 1745: expand = upperCaseExpansion(ch); 1746: if (expand > 0) 1747: { 1748: int index = upperCaseIndex(ch); 1749: while (expand-- >= 0) 1750: newStr[j++] = upperExpand[index++]; 1751: } 1752: else 1753: newStr[j++] = Character.toUpperCase(ch); 1754: } 1755: // Package constructor avoids an array copy. 1756: return new String(newStr, 0, newStr.length, true); 1757: } 1758: } 1759: /** 1760: * Uppercases this String. This uses Unicode's special case mappings, as 1761: * applied to the platform's default Locale, so the resulting string may 1762: * be a different length. 1763: * 1764: * @return new uppercased String, or this if no characters were uppercased 1765: * @see #toUpperCase(Locale) 1766: * @see #toLowerCase() 1767: */ 1768: public String toUpperCase() 1769: { 1770: return toUpperCase(Locale.getDefault()); 1771: } 1772: 1773: /** 1774: * Trims all characters less than or equal to <code>'\u0020'</code> 1775: * (<code>' '</code>) from the beginning and end of this String. This 1776: * includes many, but not all, ASCII control characters, and all 1777: * {@link Character#isWhitespace(char)}. 1778: * 1779: * @return new trimmed String, or this if nothing trimmed 1780: */ 1781: public String trim() 1782: { 1783: int limit = count + offset; 1784: if (count == 0 || (value[offset] > '\u0020' 1785: && value[limit - 1] > '\u0020')) 1786: return this; 1787: int begin = offset; 1788: do 1789: if (begin == limit) 1790: return ""; 1791: while (value[begin++] <= '\u0020'); 1792: 1793: int end = limit; 1794: while (value[--end] <= '\u0020') 1795: ; 1796: return substring(begin - offset - 1, end - offset + 1); 1797: } 1798: 1799: /** 1800: * Returns this, as it is already a String! 1801: * 1802: * @return this 1803: */ 1804: public String toString() 1805: { 1806: return this; 1807: } 1808: 1809: /** 1810: * Copies the contents of this String into a character array. Subsequent 1811: * changes to the array do not affect the String. 1812: * 1813: * @return character array copying the String 1814: */ 1815: public char[] toCharArray() 1816: { 1817: char[] copy = new char[count]; 1818: VMSystem.arraycopy(value, offset, copy, 0, count); 1819: return copy; 1820: } 1821: 1822: /** 1823: * Returns a String representation of an Object. This is "null" if the 1824: * object is null, otherwise it is <code>obj.toString()</code> (which 1825: * can be null). 1826: * 1827: * @param obj the Object 1828: * @return the string conversion of obj 1829: */ 1830: public static String valueOf(Object obj) 1831: { 1832: return obj == null ? "null" : obj.toString(); 1833: } 1834: 1835: /** 1836: * Returns a String representation of a character array. Subsequent 1837: * changes to the array do not affect the String. 1838: * 1839: * @param data the character array 1840: * @return a String containing the same character sequence as data 1841: * @throws NullPointerException if data is null 1842: * @see #valueOf(char[], int, int) 1843: * @see #String(char[]) 1844: */ 1845: public static String valueOf(char[] data) 1846: { 1847: return valueOf (data, 0, data.length); 1848: } 1849: 1850: /** 1851: * Returns a String representing the character sequence of the char array, 1852: * starting at the specified offset, and copying chars up to the specified 1853: * count. Subsequent changes to the array do not affect the String. 1854: * 1855: * @param data character array 1856: * @param offset position (base 0) to start copying out of data 1857: * @param count the number of characters from data to copy 1858: * @return String containing the chars from data[offset..offset+count] 1859: * @throws NullPointerException if data is null 1860: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 1861: * || offset + count > data.length) 1862: * (while unspecified, this is a StringIndexOutOfBoundsException) 1863: * @see #String(char[], int, int) 1864: */ 1865: public static String valueOf(char[] data, int offset, int count) 1866: { 1867: return new String(data, offset, count, false); 1868: } 1869: 1870: /** 1871: * Returns a String representing the character sequence of the char array, 1872: * starting at the specified offset, and copying chars up to the specified 1873: * count. Subsequent changes to the array do not affect the String. 1874: * 1875: * @param data character array 1876: * @param offset position (base 0) to start copying out of data 1877: * @param count the number of characters from data to copy 1878: * @return String containing the chars from data[offset..offset+count] 1879: * @throws NullPointerException if data is null 1880: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 1881: * || offset + count < 0 (overflow) 1882: * || offset + count < 0 (overflow) 1883: * || offset + count > data.length) 1884: * (while unspecified, this is a StringIndexOutOfBoundsException) 1885: * @see #String(char[], int, int) 1886: */ 1887: public static String copyValueOf(char[] data, int offset, int count) 1888: { 1889: return new String(data, offset, count, false); 1890: } 1891: 1892: /** 1893: * Returns a String representation of a character array. Subsequent 1894: * changes to the array do not affect the String. 1895: * 1896: * @param data the character array 1897: * @return a String containing the same character sequence as data 1898: * @throws NullPointerException if data is null 1899: * @see #copyValueOf(char[], int, int) 1900: * @see #String(char[]) 1901: */ 1902: public static String copyValueOf(char[] data) 1903: { 1904: return copyValueOf (data, 0, data.length); 1905: } 1906: 1907: /** 1908: * Returns a String representing a boolean. 1909: * 1910: * @param b the boolean 1911: * @return "true" if b is true, else "false" 1912: */ 1913: public static String valueOf(boolean b) 1914: { 1915: return b ? "true" : "false"; 1916: } 1917: 1918: /** 1919: * Returns a String representing a character. 1920: * 1921: * @param c the character 1922: * @return String containing the single character c 1923: */ 1924: public static String valueOf(char c) 1925: { 1926: // Package constructor avoids an array copy. 1927: return new String(new char[] { c }, 0, 1, true); 1928: } 1929: 1930: /** 1931: * Returns a String representing an integer. 1932: * 1933: * @param i the integer 1934: * @return String containing the integer in base 10 1935: * @see Integer#toString(int) 1936: */ 1937: public static String valueOf(int i) 1938: { 1939: // See Integer to understand why we call the two-arg variant. 1940: return Integer.toString(i, 10); 1941: } 1942: 1943: /** 1944: * Returns a String representing a long. 1945: * 1946: * @param l the long 1947: * @return String containing the long in base 10 1948: * @see Long#toString(long) 1949: */ 1950: public static String valueOf(long l) 1951: { 1952: return Long.toString(l); 1953: } 1954: 1955: /** 1956: * Returns a String representing a float. 1957: * 1958: * @param f the float 1959: * @return String containing the float 1960: * @see Float#toString(float) 1961: */ 1962: public static String valueOf(float f) 1963: { 1964: return Float.toString(f); 1965: } 1966: 1967: /** 1968: * Returns a String representing a double. 1969: * 1970: * @param d the double 1971: * @return String containing the double 1972: * @see Double#toString(double) 1973: */ 1974: public static String valueOf(double d) 1975: { 1976: return Double.toString(d); 1977: } 1978: 1979: 1980: /** @since 1.5 */ 1981: public static String format(Locale locale, String format, Object... args) 1982: { 1983: Formatter f = new Formatter(locale); 1984: return f.format(format, args).toString(); 1985: } 1986: 1987: /** @since 1.5 */ 1988: public static String format(String format, Object... args) 1989: { 1990: return format(Locale.getDefault(), format, args); 1991: } 1992: 1993: /** 1994: * If two Strings are considered equal, by the equals() method, 1995: * then intern() will return the same String instance. ie. 1996: * if (s1.equals(s2)) then (s1.intern() == s2.intern()). 1997: * All string literals and string-valued constant expressions 1998: * are already interned. 1999: * 2000: * @return the interned String 2001: */ 2002: public String intern() 2003: { 2004: return VMString.intern(this); 2005: } 2006: 2007: /** 2008: * Return the number of code points between two indices in the 2009: * <code>String</code>. An unpaired surrogate counts as a 2010: * code point for this purpose. Characters outside the indicated 2011: * range are not examined, even if the range ends in the middle of a 2012: * surrogate pair. 2013: * 2014: * @param start the starting index 2015: * @param end one past the ending index 2016: * @return the number of code points 2017: * @since 1.5 2018: */ 2019: public synchronized int codePointCount(int start, int end) 2020: { 2021: if (start < 0 || end > count || start > end) 2022: throw new StringIndexOutOfBoundsException(); 2023: 2024: start += offset; 2025: end += offset; 2026: int count = 0; 2027: while (start < end) 2028: { 2029: char base = value[start]; 2030: if (base < Character.MIN_HIGH_SURROGATE 2031: || base > Character.MAX_HIGH_SURROGATE 2032: || start == end 2033: || start == count 2034: || value[start + 1] < Character.MIN_LOW_SURROGATE 2035: || value[start + 1] > Character.MAX_LOW_SURROGATE) 2036: { 2037: // Nothing. 2038: } 2039: else 2040: { 2041: // Surrogate pair. 2042: ++start; 2043: } 2044: ++start; 2045: ++count; 2046: } 2047: return count; 2048: } 2049: 2050: /** 2051: * Helper function used to detect which characters have a multi-character 2052: * uppercase expansion. Note that this is only used in locations which 2053: * track one-to-many capitalization (java.lang.Character does not do this). 2054: * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the 2055: * longest uppercase expansion is three characters (a growth of 2 from the 2056: * lowercase character). 2057: * 2058: * @param ch the char to check 2059: * @return the number of characters to add when converting to uppercase 2060: * @see CharData#DIRECTION 2061: * @see CharData#UPPER_SPECIAL 2062: * @see #toUpperCase(Locale) 2063: */ 2064: private static int upperCaseExpansion(char ch) 2065: { 2066: return Character.direction[0][Character.readCodePoint((int)ch) >> 7] & 3; 2067: } 2068: 2069: /** 2070: * Helper function used to locate the offset in upperExpand given a 2071: * character with a multi-character expansion. The binary search is 2072: * optimized under the assumption that this method will only be called on 2073: * characters which exist in upperSpecial. 2074: * 2075: * @param ch the char to check 2076: * @return the index where its expansion begins 2077: * @see CharData#UPPER_SPECIAL 2078: * @see CharData#UPPER_EXPAND 2079: * @see #toUpperCase(Locale) 2080: */ 2081: private static int upperCaseIndex(char ch) 2082: { 2083: // Simple binary search for the correct character. 2084: int low = 0; 2085: int hi = upperSpecial.length - 2; 2086: int mid = ((low + hi) >> 2) << 1; 2087: char c = upperSpecial[mid]; 2088: while (ch != c) 2089: { 2090: if (ch < c) 2091: hi = mid - 2; 2092: else 2093: low = mid + 2; 2094: mid = ((low + hi) >> 2) << 1; 2095: c = upperSpecial[mid]; 2096: } 2097: return upperSpecial[mid + 1]; 2098: } 2099: 2100: /** 2101: * Returns the value array of the given string if it is zero based or a 2102: * copy of it that is zero based (stripping offset and making length equal 2103: * to count). Used for accessing the char[]s of gnu.java.lang.CharData. 2104: * Package private for use in Character. 2105: */ 2106: static char[] zeroBasedStringValue(String s) 2107: { 2108: char[] value; 2109: 2110: if (s.offset == 0 && s.count == s.value.length) 2111: value = s.value; 2112: else 2113: { 2114: int count = s.count; 2115: value = new char[count]; 2116: VMSystem.arraycopy(s.value, s.offset, value, 0, count); 2117: } 2118: 2119: return value; 2120: } 2121: 2122: /** 2123: * Returns true iff this String contains the sequence of Characters 2124: * described in s. 2125: * @param s the CharSequence 2126: * @return true iff this String contains s 2127: * 2128: * @since 1.5 2129: */ 2130: public boolean contains (CharSequence s) 2131: { 2132: return this.indexOf(s.toString()) != -1; 2133: } 2134: 2135: /** 2136: * Returns a string that is this string with all instances of the sequence 2137: * represented by <code>target</code> replaced by the sequence in 2138: * <code>replacement</code>. 2139: * @param target the sequence to be replaced 2140: * @param replacement the sequence used as the replacement 2141: * @return the string constructed as above 2142: */ 2143: public String replace (CharSequence target, CharSequence replacement) 2144: { 2145: String targetString = target.toString(); 2146: String replaceString = replacement.toString(); 2147: int targetLength = target.length(); 2148: int replaceLength = replacement.length(); 2149: 2150: int startPos = this.indexOf(targetString); 2151: CPStringBuilder result = new CPStringBuilder(this); 2152: while (startPos != -1) 2153: { 2154: // Replace the target with the replacement 2155: result.replace(startPos, startPos + targetLength, replaceString); 2156: 2157: // Search for a new occurrence of the target 2158: startPos = result.indexOf(targetString, startPos + replaceLength); 2159: } 2160: return result.toString(); 2161: } 2162: 2163: /** 2164: * Return the index into this String that is offset from the given index by 2165: * <code>codePointOffset</code> code points. 2166: * @param index the index at which to start 2167: * @param codePointOffset the number of code points to offset 2168: * @return the index into this String that is <code>codePointOffset</code> 2169: * code points offset from <code>index</code>. 2170: * 2171: * @throws IndexOutOfBoundsException if index is negative or larger than the 2172: * length of this string. 2173: * @throws IndexOutOfBoundsException if codePointOffset is positive and the 2174: * substring starting with index has fewer than codePointOffset code points. 2175: * @throws IndexOutOfBoundsException if codePointOffset is negative and the 2176: * substring ending with index has fewer than (-codePointOffset) code points. 2177: * @since 1.5 2178: */ 2179: public int offsetByCodePoints(int index, int codePointOffset) 2180: { 2181: if (index < 0 || index > count) 2182: throw new IndexOutOfBoundsException(); 2183: 2184: return Character.offsetByCodePoints(value, offset, count, offset + index, 2185: codePointOffset); 2186: } 2187: 2188: /** 2189: * Returns true if, and only if, {@link #length()} 2190: * is <code>0</code>. 2191: * 2192: * @return true if the length of the string is zero. 2193: * @since 1.6 2194: */ 2195: public boolean isEmpty() 2196: { 2197: return count == 0; 2198: } 2199: 2200: }
GNU Classpath (0.98) |