| GNU Classpath (0.95) | |
| 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: 44: import java.io.Serializable; 45: import java.io.UnsupportedEncodingException; 46: import java.nio.ByteBuffer; 47: import java.nio.CharBuffer; 48: import java.nio.charset.CharacterCodingException; 49: import java.nio.charset.Charset; 50: import java.nio.charset.CharsetDecoder; 51: import java.nio.charset.CharsetEncoder; 52: import java.nio.charset.CodingErrorAction; 53: import java.nio.charset.IllegalCharsetNameException; 54: import java.nio.charset.UnsupportedCharsetException; 55: import java.text.Collator; 56: import java.util.Comparator; 57: import java.util.Formatter; 58: import java.util.Locale; 59: import java.util.regex.Matcher; 60: import java.util.regex.Pattern; 61: import java.util.regex.PatternSyntaxException; 62: 63: /** 64: * Strings represent an immutable set of characters. All String literals 65: * are instances of this class, and two string literals with the same contents 66: * refer to the same String object. 67: * 68: * <p>This class also includes a number of methods for manipulating the 69: * contents of strings (of course, creating a new object if there are any 70: * changes, as String is immutable). Case mapping relies on Unicode 3.0.0 71: * standards, where some character sequences have a different number of 72: * characters in the uppercase version than the lower case. 73: * 74: * <p>Strings are special, in that they are the only object with an overloaded 75: * operator. When you use '+' with at least one String argument, both 76: * arguments have String conversion performed on them, and another String (not 77: * guaranteed to be unique) results. 78: * 79: * <p>String is special-cased when doing data serialization - rather than 80: * listing the fields of this class, a String object is converted to a string 81: * literal in the object stream. 82: * 83: * @author Paul N. Fisher 84: * @author Eric Blake (ebb9@email.byu.edu) 85: * @author Per Bothner (bothner@cygnus.com) 86: * @author Tom Tromey (tromey@redhat.com) 87: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 88: * @since 1.0 89: * @status updated to 1.4; but could use better data sharing via offset field 90: */ 91: public final class String 92: implements Serializable, Comparable<String>, CharSequence 93: { 94: // WARNING: String is a CORE class in the bootstrap cycle. See the comments 95: // in vm/reference/java/lang/Runtime for implications of this fact. 96: 97: /** 98: * This is probably not necessary because this class is special cased already 99: * but it will avoid showing up as a discrepancy when comparing SUIDs. 100: */ 101: private static final long serialVersionUID = -6849794470754667710L; 102: 103: /** 104: * Stores unicode multi-character uppercase expansion table. 105: * @see #toUpperCase(Locale) 106: * @see CharData#UPPER_EXPAND 107: */ 108: private static final char[] upperExpand 109: = zeroBasedStringValue(CharData.UPPER_EXPAND); 110: 111: /** 112: * Stores unicode multi-character uppercase special casing table. 113: * @see #upperCaseExpansion(char) 114: * @see CharData#UPPER_SPECIAL 115: */ 116: private static final char[] upperSpecial 117: = zeroBasedStringValue(CharData.UPPER_SPECIAL); 118: 119: /** 120: * Characters which make up the String. 121: * Package access is granted for use by StringBuffer. 122: */ 123: final char[] value; 124: 125: /** 126: * Holds the number of characters in value. This number is generally 127: * the same as value.length, but can be smaller because substrings and 128: * StringBuffers can share arrays. Package visible for use by trusted code. 129: */ 130: final int count; 131: 132: /** 133: * Caches the result of hashCode(). If this value is zero, the hashcode 134: * is considered uncached (even if 0 is the correct hash value). 135: */ 136: private int cachedHashCode; 137: 138: /** 139: * Holds the starting position for characters in value[]. Since 140: * substring()'s are common, the use of offset allows the operation 141: * to perform in O(1). Package access is granted for use by StringBuffer. 142: */ 143: final int offset; 144: 145: /** 146: * An implementation for {@link #CASE_INSENSITIVE_ORDER}. 147: * This must be {@link Serializable}. The class name is dictated by 148: * compatibility with Sun's JDK. 149: */ 150: private static final class CaseInsensitiveComparator 151: implements Comparator<String>, Serializable 152: { 153: /** 154: * Compatible with JDK 1.2. 155: */ 156: private static final long serialVersionUID = 8575799808933029326L; 157: 158: /** 159: * The default private constructor generates unnecessary overhead. 160: */ 161: CaseInsensitiveComparator() {} 162: 163: /** 164: * Compares to Strings, using 165: * <code>String.compareToIgnoreCase(String)</code>. 166: * 167: * @param o1 the first string 168: * @param o2 the second string 169: * @return < 0, 0, or > 0 depending on the case-insensitive 170: * comparison of the two strings. 171: * @throws NullPointerException if either argument is null 172: * @throws ClassCastException if either argument is not a String 173: * @see #compareToIgnoreCase(String) 174: */ 175: public int compare(String o1, String o2) 176: { 177: return o1.compareToIgnoreCase(o2); 178: } 179: } // class CaseInsensitiveComparator 180: 181: /** 182: * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>. 183: * This comparator is {@link Serializable}. Note that it ignores Locale, 184: * for that, you want a Collator. 185: * 186: * @see Collator#compare(String, String) 187: * @since 1.2 188: */ 189: public static final Comparator<String> CASE_INSENSITIVE_ORDER 190: = new CaseInsensitiveComparator(); 191: 192: /** 193: * Creates an empty String (length 0). Unless you really need a new object, 194: * consider using <code>""</code> instead. 195: */ 196: public String() 197: { 198: value = "".value; 199: offset = 0; 200: count = 0; 201: } 202: 203: /** 204: * Copies the contents of a String to a new String. Since Strings are 205: * immutable, only a shallow copy is performed. 206: * 207: * @param str String to copy 208: * @throws NullPointerException if value is null 209: */ 210: public String(String str) 211: { 212: value = str.value; 213: offset = str.offset; 214: count = str.count; 215: cachedHashCode = str.cachedHashCode; 216: } 217: 218: /** 219: * Creates a new String using the character sequence of the char array. 220: * Subsequent changes to data do not affect the String. 221: * 222: * @param data char array to copy 223: * @throws NullPointerException if data is null 224: */ 225: public String(char[] data) 226: { 227: this(data, 0, data.length, false); 228: } 229: 230: /** 231: * Creates a new String using the character sequence of a subarray of 232: * characters. The string starts at offset, and copies count chars. 233: * Subsequent changes to data do not affect the String. 234: * 235: * @param data char array to copy 236: * @param offset position (base 0) to start copying out of data 237: * @param count the number of characters from data to copy 238: * @throws NullPointerException if data is null 239: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 240: * || offset + count < 0 (overflow) 241: * || offset + count > data.length) 242: * (while unspecified, this is a StringIndexOutOfBoundsException) 243: */ 244: public String(char[] data, int offset, int count) 245: { 246: this(data, offset, count, false); 247: } 248: 249: /** 250: * Creates a new String using an 8-bit array of integer values, starting at 251: * an offset, and copying up to the count. Each character c, using 252: * corresponding byte b, is created in the new String as if by performing: 253: * 254: * <pre> 255: * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) 256: * </pre> 257: * 258: * @param ascii array of integer values 259: * @param hibyte top byte of each Unicode character 260: * @param offset position (base 0) to start copying out of ascii 261: * @param count the number of characters from ascii to copy 262: * @throws NullPointerException if ascii is null 263: * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 264: * || offset + count < 0 (overflow) 265: * || offset + count > ascii.length) 266: * (while unspecified, this is a StringIndexOutOfBoundsException) 267: * @see #String(byte[]) 268: * @see #String(byte[], String) 269: * @see #String(byte[], int, int) 270: * @see #String(byte[], int, int, String) 271: * @deprecated use {@link #String(byte[], int, int, String)} to perform 272: * correct encoding 273: */ 274: public String(byte[] ascii, int hibyte, int offset, int count) 275: { 276: if (offset < 0) 277: throw new StringIndexOutOfBoundsException("offset: " + offset); 278: if (count < 0) 279: throw new StringIndexOutOfBoundsException("count: " + count); 280: // equivalent to: offset + count < 0 || offset + count > ascii.length 281: if (ascii.length - offset < count) 282: throw new StringIndexOutOfBoundsException("offset + count: " 283: + (offset + count)); 284: value = new char[count]; 285: this.offset = 0; 286: this.count = count; 287: hibyte <<= 8; 288: offset += count; 289: while (--count >= 0) 290: value[count] = (char) (hibyte | (ascii[--offset] & 0xff)); 291: } 292: 293: /** 294: * Creates a new String using an 8-bit array of integer values. Each 295: * character c, using corresponding byte b, is created in the new String 296: * as if by performing: 297: * 298: * <pre> 299: * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) 300: * </pre> 301: * 302: * @param ascii array of integer values 303: * @param hibyte top byte of each Unicode character 304: * @throws NullPointerException if ascii is null 305: * @see #String(byte[]) 306: * @see #String(byte[], String) 307: * @see #String(byte[], int, int) 308: * @see #String(byte[], int, int, String) 309: * @see #String(byte[], int, int, int) 310: * @deprecated use {@link #String(byte[], String)} to perform 311: * correct encoding 312: */ 313: public String(byte[] ascii, int hibyte) 314: { 315: this(ascii, hibyte, 0, ascii.length); 316: } 317: 318: /** 319: * Creates a new String using the portion of the byte array starting at the 320: * offset and ending at offset + count. Uses the specified encoding type 321: * to decode the byte array, so the resulting string may be longer or 322: * shorter than the byte array. For more decoding control, use 323: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 324: * see {@link java.nio.charset.Charset}. The behavior is not specified if 325: * the decoder encounters invalid characters; this implementation throws 326: * an Error. 327: * 328: * @param data byte array to copy 329: * @param offset the offset to start at 330: * @param count the number of bytes in the array to use 331: * @param encoding the name of the encoding to use 332: * @throws NullPointerException if data or encoding is null 333: * @throws IndexOutOfBoundsException if offset or count is incorrect 334: * (while unspecified, this is a StringIndexOutOfBoundsException) 335: * @throws UnsupportedEncodingException if encoding is not found 336: * @throws Error if the decoding fails 337: * @since 1.1 338: */ 339: public String(byte[] data, int offset, int count, String encoding) 340: throws UnsupportedEncodingException 341: { 342: if (offset < 0) 343: throw new StringIndexOutOfBoundsException("offset: " + offset); 344: if (count < 0) 345: throw new StringIndexOutOfBoundsException("count: " + count); 346: // equivalent to: offset + count < 0 || offset + count > data.length 347: if (data.length - offset < count) 348: throw new StringIndexOutOfBoundsException("offset + count: " 349: + (offset + count)); 350: try 351: { 352: CharsetDecoder csd = Charset.forName(encoding).newDecoder(); 353: csd.onMalformedInput(CodingErrorAction.REPLACE); 354: csd.onUnmappableCharacter(CodingErrorAction.REPLACE); 355: CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); 356: if(cbuf.hasArray()) 357: { 358: value = cbuf.array(); 359: this.offset = cbuf.position(); 360: this.count = cbuf.remaining(); 361: } else { 362: // Doubt this will happen. But just in case. 363: value = new char[cbuf.remaining()]; 364: cbuf.get(value); 365: this.offset = 0; 366: this.count = value.length; 367: } 368: } catch(CharacterCodingException e){ 369: throw new UnsupportedEncodingException("Encoding: "+encoding+ 370: " not found."); 371: } catch(IllegalCharsetNameException e){ 372: throw new UnsupportedEncodingException("Encoding: "+encoding+ 373: " not found."); 374: } catch(UnsupportedCharsetException e){ 375: throw new UnsupportedEncodingException("Encoding: "+encoding+ 376: " not found."); 377: } 378: } 379: 380: /** 381: * Creates a new String using the byte array. Uses the specified encoding 382: * type to decode the byte array, so the resulting string may be longer or 383: * shorter than the byte array. For more decoding control, use 384: * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, 385: * see {@link java.nio.charset.Charset}. The behavior is not specified if 386: * the decoder encounters invalid characters; this implementation throws 387: * an Error. 388: * 389: * @param data byte array to copy 390: * @param encoding the name of the encoding to use 391: * @throws NullPointerException if data or encoding is null 392: * @throws UnsupportedEncodingException if encoding is not found 393: * @throws Error if the decoding fails 394: * @see #String(byte[], int, int, String) 395: * @since 1.1 396: */ 397: public String(byte[] data, String encoding) 398: throws UnsupportedEncodingException 399: { 400: this(data, 0, data.length, encoding); 401: } 402: 403: /** 404: * Creates a new String using the portion of the byte array starting at the 405: * offset and ending at offset + count. Uses the encoding of the platform's 406: * default charset, so the resulting string may be longer or shorter than 407: * the byte array. For more decoding control, use 408: * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified 409: * if the decoder encounters invalid characters; this implementation throws 410: * an Error. 411: * 412: * @param data byte array to copy 413: * @param offset the offset to start at 414: * @param count the number of bytes in the array to use 415: * @throws NullPointerException if data is null 416: * @throws IndexOutOfBoundsException if offset or count is incorrect 417: * @throws Error if the decoding fails 418: * @see #String(byte[], int, int, String) 419: * @since 1.1 420: */ 421: public String(byte[] data, int offset, int count) 422: { 423: if (offset < 0) 424: throw new StringIndexOutOfBoundsException("offset: " + offset); 425: if (count < 0) 426: throw new StringIndexOutOfBoundsException("count: " + count); 427: // equivalent to: offset + count < 0 || offset + count > data.length 428: if (data.length - offset < count) 429: throw new StringIndexOutOfBoundsException("offset + count: " 430: + (offset + count)); 431: int o, c; 432: char[] v; 433: String encoding; 434: try 435: { 436: encoding = System.getProperty("file.encoding"); 437: CharsetDecoder csd = Charset.forName(encoding).newDecoder(); 438: csd.onMalformedInput(CodingErrorAction.REPLACE); 439: csd.onUnmappableCharacter(CodingErrorAction.REPLACE); 440: CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); 441: if(cbuf.hasArray()) 442: { 443: v = cbuf.array(); 444: o = cbuf.position(); 445: c = cbuf.remaining(); 446: } else { 447: // Doubt this will happen. But just in case. 448: v = new char[cbuf.remaining()]; 449: cbuf.get(v); 450: o = 0; 451: c = v.length; 452: } 453: } catch(Exception ex){ 454: // If anything goes wrong (System property not set, 455: // NIO provider not available, etc) 456: // Default to the 'safe' encoding ISO8859_1 457: v = new char[count]; 458: o = 0; 459: c = count; 460: for (int i=0;i<count;i++) 461: v[i] = (char)data[offset+i]; 462: } 463: this.value = v; 464: this.offset = o; 465: this.count = c; 466: } 467: 468: /** 469: * Creates a new String using the byte array. Uses the encoding of the 470: * platform's default charset, so the resulting string may be longer or 471: * shorter than the byte array. For more decoding control, use 472: * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified 473: * if the decoder encounters invalid characters; this implementation throws 474: * an Error. 475: * 476: * @param data byte array to copy 477: * @throws NullPointerException if data is null 478: * @throws Error if the decoding fails 479: * @see #String(byte[], int, int) 480: * @see #String(byte[], int, int, String) 481: * @since 1.1 482: */ 483: public String(byte[] data) 484: { 485: this(data, 0, data.length); 486: } 487: 488: /** 489: * Creates a new String using the character sequence represented by 490: * the StringBuffer. Subsequent changes to buf do not affect the String. 491: * 492: * @param buffer StringBuffer to copy 493: * @throws NullPointerException if buffer is null 494: */ 495: public String(StringBuffer buffer) 496: { 497: synchronized (buffer) 498: { 499: offset = 0; 500: count = buffer.count; 501: // Share unless buffer is 3/4 empty. 502: if ((count << 2) < buffer.value.length) 503: { 504: value = new char[count]; 505: VMSystem.arraycopy(buffer.value, 0, value, 0, count); 506: } 507: else 508: { 509: buffer.shared = true; 510: value = buffer.value; 511: } 512: } 513: } 514: 515: /** 516: * Creates a new String using the character sequence represented by 517: * the StringBuilder. Subsequent changes to buf do not affect the String. 518: * 519: * @param buffer StringBuilder to copy 520: * @throws NullPointerException if buffer is null 521: */ 522: public String(StringBuilder buffer) 523: { 524: this(buffer.value, 0, buffer.count); 525: } 526: 527: /** 528: * Special constructor which can share an array when safe to do so. 529: * 530: * @param data the characters to copy 531: * @param offset the location to start from 532: * @param count the number of characters to use 533: * @param dont_copy true if the array is trusted, and need not be copied 534: * @throws NullPointerException if chars is null 535: * @throws StringIndexOutOfBoundsException if bounds check fails 536: */ 537: String(char[] data, int offset, int count, boolean dont_copy) 538: { 539: if (offset < 0) 540: throw new StringIndexOutOfBoundsException("offset: " + offset); 541: if (count < 0) 542: throw new StringIndexOutOfBoundsException("count: " + count); 543: // equivalent to: offset + count < 0 || offset + count > data.length 544: if (data.length - offset < count) 545: throw new StringIndexOutOfBoundsException("offset + count: " 546: + (offset + count)); 547: if (dont_copy) 548: { 549: value = data; 550: this.offset = offset; 551: } 552: else 553: { 554: value = new char[count]; 555: VMSystem.arraycopy(data, offset, value, 0, count); 556: this.offset = 0; 557: } 558: this.count = count; 559: } 560: 561: /** 562: * Creates a new String containing the characters represented in the 563: * given subarray of Unicode code points. 564: * @param codePoints the entire array of code points 565: * @param offset the start of the subarray 566: * @param count the length of the subarray 567: * 568: * @throws IllegalArgumentException if an invalid code point is found 569: * in the codePoints array 570: * @throws IndexOutOfBoundsException if offset is negative or offset + count 571: * is greater than the length of the array. 572: */ 573: public String(int[] codePoints, int offset, int count) 574: { 575: // FIXME: This implementation appears to give correct internal 576: // representation of the String because: 577: // - length() is correct 578: // - getting a char[] from toCharArray() and testing 579: // Character.codePointAt() on all the characters in that array gives 580: // the appropriate results 581: // however printing the String gives incorrect results. This may be 582: // due to printing method errors (such as incorrectly looping through 583: // the String one char at a time rather than one "character" at a time. 584: 585: if (offset < 0) 586: throw new IndexOutOfBoundsException(); 587: int end = offset + count; 588: int pos = 0; 589: // This creates a char array that is long enough for all of the code 590: // points to represent supplementary characters. This is more than likely 591: // a waste of storage, so we use it only temporarily and then copy the 592: // used portion into the value array. 593: char[] temp = new char[2 * codePoints.length]; 594: for (int i = offset; i < end; i++) 595: { 596: pos += Character.toChars(codePoints[i], temp, pos); 597: } 598: this.count = pos; 599: this.value = new char[pos]; 600: System.arraycopy(temp, 0, value, 0, pos); 601: this.offset = 0; 602: } 603: 604: /** 605: * Returns the number of characters contained in this String. 606: * 607: * @return the length of this String 608: */ 609: public int length() 610: { 611: return count; 612: } 613: 614: /** 615: * Returns the character located at the specified index within this String. 616: * 617: * @param index position of character to return (base 0) 618: * @return character located at position index 619: * @throws IndexOutOfBoundsException if index < 0 || index >= length() 620: * (while unspecified, this is a StringIndexOutOfBoundsException) 621: */ 622: public char charAt(int index) 623: { 624: if (index < 0 || index >= count) 625: throw new StringIndexOutOfBoundsException(index); 626: return value[offset + index]; 627: } 628: 629: /** 630: * Get the code point at the specified index. This is like #charAt(int), 631: * but if the character is the start of a surrogate pair, and the 632: * following character completes the pair, then the corresponding 633: * supplementary code point is returned. 634: * @param index the index of the codepoint to get, starting at 0 635: * @return the codepoint at the specified index 636: * @throws IndexOutOfBoundsException if index is negative or >= length() 637: * @since 1.5 638: */ 639: public synchronized int codePointAt(int index) 640: { 641: // Use the CharSequence overload as we get better range checking 642: // this way. 643: return Character.codePointAt(this, index); 644: } 645: 646: /** 647: * Get the code point before the specified index. This is like 648: * #codePointAt(int), but checks the characters at <code>index-1</code> and 649: * <code>index-2</code> to see if they form a supplementary code point. 650: * @param index the index just past the codepoint to get, starting at 0 651: * @return the codepoint at the specified index 652: * @throws IndexOutOfBoundsException if index is negative or >= length() 653: * (while unspecified, this is a StringIndexOutOfBoundsException) 654: * @since 1.5 655: */ 656: public synchronized int codePointBefore(int index) 657: { 658: // Use the CharSequence overload as we get better range checking 659: // this way. 660: return Character.codePointBefore(this, index); 661: } 662: 663: /** 664: * Copies characters from this String starting at a specified start index, 665: * ending at a specified stop index, to a character array starting at 666: * a specified destination begin index. 667: * 668: * @param srcBegin index to begin copying characters from this String 669: * @param srcEnd index after the last character to be copied from this String 670: * @param dst character array which this String is copied into 671: * @param dstBegin index to start writing characters into dst 672: * @throws NullPointerException if dst is null 673: * @throws IndexOutOfBoundsException if any indices are out of bounds 674: * (while unspecified, source problems cause a 675: * StringIndexOutOfBoundsException, and dst problems cause an 676: * ArrayIndexOutOfBoundsException) 677: */ 678: public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) 679: { 680: if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) 681: throw new StringIndexOutOfBoundsException(); 682: VMSystem.arraycopy(value, srcBegin + offset, 683: dst, dstBegin, srcEnd - srcBegin); 684: } 685: 686: /** 687: * Copies the low byte of each character from this String starting at a 688: * specified start index, ending at a specified stop index, to a byte array 689: * starting at a specified destination begin index. 690: * 691: * @param srcBegin index to being copying characters from this String 692: * @param srcEnd index after the last character to be copied from this String 693: * @param dst byte array which each low byte of this String is copied into 694: * @param dstBegin index to start writing characters into dst 695: * @throws NullPointerException if dst is null and copy length is non-zero 696: * @throws IndexOutOfBoundsException if any indices are out of bounds 697: * (while unspecified, source problems cause a 698: * StringIndexOutOfBoundsException, and dst problems cause an 699: * ArrayIndexOutOfBoundsException) 700: * @see #getBytes() 701: * @see #getBytes(String) 702: * @deprecated use {@link #getBytes()}, which uses a char to byte encoder 703: */ 704: public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) 705: { 706: if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) 707: throw new StringIndexOutOfBoundsException(); 708: int i = srcEnd - srcBegin; 709: srcBegin += offset; 710: while (--i >= 0) 711: dst[dstBegin++] = (byte) value[srcBegin++]; 712: } 713: 714: /** 715: * Converts the Unicode characters in this String to a byte array. Uses the 716: * specified encoding method, so the result may be longer or shorter than 717: * the String. For more encoding control, use 718: * {@link java.nio.charset.CharsetEncoder}, and for valid character sets, 719: * see {@link java.nio.charset.Charset}. Unsupported characters get 720: * replaced by an encoding specific byte. 721: * 722: * @param enc encoding name 723: * @return the resulting byte array 724: * @throws NullPointerException if enc is null 725: * @throws UnsupportedEncodingException if encoding is not supported 726: * @since 1.1 727: */ 728: public byte[] getBytes(String enc) throws UnsupportedEncodingException 729: { 730: try 731: { 732: CharsetEncoder cse = Charset.forName(enc).newEncoder(); 733: cse.onMalformedInput(CodingErrorAction.REPLACE); 734: cse.onUnmappableCharacter(CodingErrorAction.REPLACE); 735: ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count)); 736: if(bbuf.hasArray()) 737: return bbuf.array(); 738: 739: // Doubt this will happen. But just in case. 740: byte[] bytes = new byte[bbuf.remaining()]; 741: bbuf.get(bytes); 742: return bytes; 743: } 744: catch(IllegalCharsetNameException e) 745: { 746: throw new UnsupportedEncodingException("Encoding: " + enc 747: + " not found."); 748: } 749: catch(UnsupportedCharsetException e) 750: { 751: throw new UnsupportedEncodingException("Encoding: " + enc 752: + " not found."); 753: } 754: catch(CharacterCodingException e) 755: { 756: // This shouldn't ever happen. 757: throw (InternalError) new InternalError().initCause(e); 758: } 759: } 760: 761: /** 762: * Converts the Unicode characters in this String to a byte array. Uses the 763: * encoding of the platform's default charset, so the result may be longer 764: * or shorter than the String. For more encoding control, use 765: * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get 766: * replaced by an encoding specific byte. 767: * 768: * @return the resulting byte array, or null on a problem 769: * @since 1.1 770: */ 771: public byte[] getBytes() 772: { 773: try 774: { 775: return getBytes(System.getProperty("file.encoding")); 776: } catch(Exception e) { 777: // XXX - Throw an error here? 778: // For now, default to the 'safe' encoding. 779: byte[] bytes = new byte[count]; 780: for(int i=0;i<count;i++) 781: bytes[i] = (byte)((value[offset+i] <= 0xFF)? 782: value[offset+i]:'?'); 783: return bytes; 784: } 785: } 786: 787: /** 788: * Predicate which compares anObject to this. This is true only for Strings 789: * with the same character sequence. 790: * 791: * @param anObject the object to compare 792: * @return true if anObject is semantically equal to this 793: * @see #compareTo(String) 794: * @see #equalsIgnoreCase(String) 795: */ 796: public boolean equals(Object anObject) 797: { 798: if (! (anObject instanceof String)) 799: return false; 800: String str2 = (String) anObject; 801: if (count != str2.count) 802: return false; 803: if (value == str2.value && offset == str2.offset) 804: return true; 805: int i = count; 806: int x = offset; 807: int y = str2.offset; 808: while (--i >= 0) 809: if (value[x++] != str2.value[y++]) 810: return false; 811: return true; 812: } 813: 814: /** 815: * Compares the given StringBuffer to this String. This is true if the 816: * StringBuffer has the same content as this String at this moment. 817: * 818: * @param buffer the StringBuffer to compare to 819: * @return true if StringBuffer has the same character sequence 820: * @throws NullPointerException if the given StringBuffer is null 821: * @since 1.4 822: */ 823: public boolean contentEquals(StringBuffer buffer) 824: { 825: synchronized (buffer) 826: { 827: if (count != buffer.count) 828: return false; 829: if (value == buffer.value) 830: return true; // Possible if shared. 831: int i = count; 832: int x = offset + count; 833: while (--i >= 0) 834: if (value[--x] != buffer.value[i]) 835: return false; 836: return true; 837: } 838: }