Source for java.lang.String

   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 &lt; 0, 0, or &gt; 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 &lt; 0 || count &lt; 0
 241:    *         || offset + count &lt; 0 (overflow)
 242:    *         || offset + count &gt; 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 &amp; 0xff) &lt;&lt; 8) | (b &amp; 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 &lt; 0 || count &lt; 0
 265:    *         || offset + count &lt; 0 (overflow)
 266:    *         || offset + count &gt; 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 &amp; 0xff) &lt;&lt; 8) | (b &amp; 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 &lt; 0 || index &gt;= 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 &gt;= 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 &gt;= 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 &lt; 0 || begin &gt; 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 &lt; 0 || end &gt; length()
1310:    *         || begin &gt; 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 &lt; 0 || end &gt; length()
1334:    *         || begin &gt; 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 &lt; 0 || count &lt; 0
1861:    *         || offset + count &gt; 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 &lt; 0 || count &lt; 0
1881:    *         || offset + count &lt; 0 (overflow)
1882:    *         || offset + count &lt; 0 (overflow)
1883:    *         || offset + count &gt; 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: }