Source for java.lang.StringBuffer

   1: /* StringBuffer.java -- Growable strings
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
   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: package java.lang;
  40: 
  41: import java.io.Serializable;
  42: 
  43: /**
  44:  * <code>StringBuffer</code> represents a changeable <code>String</code>.
  45:  * It provides the operations required to modify the
  46:  * <code>StringBuffer</code>, including insert, replace, delete, append,
  47:  * and reverse. It is thread-safe; meaning that all modifications to a buffer
  48:  * are in synchronized methods.
  49:  *
  50:  * <p><code>StringBuffer</code>s are variable-length in nature, so even if
  51:  * you initialize them to a certain size, they can still grow larger than
  52:  * that. <em>Capacity</em> indicates the number of characters the
  53:  * <code>StringBuffer</code> can have in it before it has to grow (growing
  54:  * the char array is an expensive operation involving <code>new</code>).
  55:  *
  56:  * <p>Incidentally, compilers often implement the String operator "+"
  57:  * by using a <code>StringBuffer</code> operation:<br>
  58:  * <code>a + b</code><br>
  59:  * is the same as<br>
  60:  * <code>new StringBuffer().append(a).append(b).toString()</code>.
  61:  *
  62:  * <p>Classpath's StringBuffer is capable of sharing memory with Strings for
  63:  * efficiency.  This will help when a StringBuffer is converted to a String
  64:  * and the StringBuffer is not changed after that (quite common when performing
  65:  * string concatenation).
  66:  *
  67:  * @author Paul Fisher
  68:  * @author John Keiser
  69:  * @author Tom Tromey
  70:  * @author Eric Blake (ebb9@email.byu.edu)
  71:  * @see String
  72:  * @since 1.0
  73:  * @status updated to 1.4
  74:  */
  75: public final class StringBuffer
  76:   implements Serializable, CharSequence, Appendable
  77: {
  78:   // Implementation note: if you change this class, you usually will
  79:   // want to change StringBuilder as well.
  80: 
  81:   /**
  82:    * Compatible with JDK 1.0+.
  83:    */
  84:   private static final long serialVersionUID = 3388685877147921107L;
  85: 
  86:   /**
  87:    * Index of next available character (and thus the size of the current
  88:    * string contents).  Note that this has permissions set this way so that
  89:    * String can get the value.
  90:    *
  91:    * @serial the number of characters in the buffer
  92:    */
  93:   int count;
  94: 
  95:   /**
  96:    * The buffer.  Note that this has permissions set this way so that String
  97:    * can get the value.
  98:    *
  99:    * @serial the buffer
 100:    */
 101:   char[] value;
 102: 
 103:   /**
 104:    * True if the buffer is shared with another object (StringBuffer or
 105:    * String); this means the buffer must be copied before writing to it again.
 106:    * Note that this has permissions set this way so that String can get the
 107:    * value.
 108:    *
 109:    * @serial whether the buffer is shared
 110:    */
 111:   boolean shared;
 112: 
 113:   /**
 114:    * The default capacity of a buffer.
 115:    */
 116:   private static final int DEFAULT_CAPACITY = 16;
 117: 
 118:   /**
 119:    * Create a new StringBuffer with default capacity 16.
 120:    */
 121:   public StringBuffer()
 122:   {
 123:     this(DEFAULT_CAPACITY);
 124:   }
 125: 
 126:   /**
 127:    * Create an empty <code>StringBuffer</code> with the specified initial
 128:    * capacity.
 129:    *
 130:    * @param capacity the initial capacity
 131:    * @throws NegativeArraySizeException if capacity is negative
 132:    */
 133:   public StringBuffer(int capacity)
 134:   {
 135:     value = new char[capacity];
 136:   }
 137: 
 138:   /**
 139:    * Create a new <code>StringBuffer</code> with the characters in the
 140:    * specified <code>String</code>. Initial capacity will be the size of the
 141:    * String plus 16.
 142:    *
 143:    * @param str the <code>String</code> to convert
 144:    * @throws NullPointerException if str is null
 145:    */
 146:   public StringBuffer(String str)
 147:   {
 148:     // Unfortunately, because the size is 16 larger, we cannot share.
 149:     count = str.count;
 150:     value = new char[count + DEFAULT_CAPACITY];
 151:     str.getChars(0, count, value, 0);
 152:   }
 153: 
 154:   /**
 155:    * Create a new <code>StringBuffer</code> with the characters from the
 156:    * specified <code>CharSequence</code>. Initial capacity will be the
 157:    * size of the CharSequence plus 16.
 158:    *
 159:    * @param seq the <code>String</code> to convert
 160:    * @throws NullPointerException if str is null
 161:    * @since 1.5
 162:    */
 163:   public StringBuffer(CharSequence seq)
 164:   {
 165:     count = Math.max(0, seq.length());
 166:     value = new char[count + DEFAULT_CAPACITY];
 167:     for (int i = 0; i < count; ++i)
 168:       value[i] = seq.charAt(i);
 169:   }
 170: 
 171:   /**
 172:    * Get the length of the <code>String</code> this <code>StringBuffer</code>
 173:    * would create. Not to be confused with the <em>capacity</em> of the
 174:    * <code>StringBuffer</code>.
 175:    *
 176:    * @return the length of this <code>StringBuffer</code>
 177:    * @see #capacity()
 178:    * @see #setLength(int)
 179:    */
 180:   public synchronized int length()
 181:   {
 182:     return count;
 183:   }
 184: 
 185:   /**
 186:    * Get the total number of characters this <code>StringBuffer</code> can
 187:    * support before it must be grown.  Not to be confused with <em>length</em>.
 188:    *
 189:    * @return the capacity of this <code>StringBuffer</code>
 190:    * @see #length()
 191:    * @see #ensureCapacity(int)
 192:    */
 193:   public synchronized int capacity()
 194:   {
 195:     return value.length;
 196:   }
 197: 
 198:   /**
 199:    * Increase the capacity of this <code>StringBuffer</code>. This will
 200:    * ensure that an expensive growing operation will not occur until
 201:    * <code>minimumCapacity</code> is reached. The buffer is grown to the
 202:    * larger of <code>minimumCapacity</code> and
 203:    * <code>capacity() * 2 + 2</code>, if it is not already large enough.
 204:    *
 205:    * @param minimumCapacity the new capacity
 206:    * @see #capacity()
 207:    */
 208:   public synchronized void ensureCapacity(int minimumCapacity)
 209:   {
 210:     ensureCapacity_unsynchronized(minimumCapacity);
 211:   }
 212: 
 213:   /**
 214:    * Set the length of this StringBuffer. If the new length is greater than
 215:    * the current length, all the new characters are set to '\0'. If the new
 216:    * length is less than the current length, the first <code>newLength</code>
 217:    * characters of the old array will be preserved, and the remaining
 218:    * characters are truncated.
 219:    *
 220:    * @param newLength the new length
 221:    * @throws IndexOutOfBoundsException if the new length is negative
 222:    *         (while unspecified, this is a StringIndexOutOfBoundsException)
 223:    * @see #length()
 224:    */
 225:   public synchronized void setLength(int newLength)
 226:   {
 227:     if (newLength < 0)
 228:       throw new StringIndexOutOfBoundsException(newLength);
 229: 
 230:     int valueLength = value.length;
 231: 
 232:     /* Always call ensureCapacity_unsynchronized in order to preserve
 233:        copy-on-write semantics.  */
 234:     ensureCapacity_unsynchronized(newLength);
 235: 
 236:     if (newLength < valueLength)
 237:       {
 238:         /* If the StringBuffer's value just grew, then we know that
 239:            value is newly allocated and the region between count and
 240:            newLength is filled with '\0'.  */
 241:     count = newLength;
 242:       }
 243:     else
 244:       {
 245:     /* The StringBuffer's value doesn't need to grow.  However,
 246:        we should clear out any cruft that may exist.  */
 247:     while (count < newLength)
 248:           value[count++] = '\0';
 249:       }
 250:   }
 251: 
 252:   /**
 253:    * Get the character at the specified index.
 254:    *
 255:    * @param index the index of the character to get, starting at 0
 256:    * @return the character at the specified index
 257:    * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
 258:    */
 259:   public synchronized char charAt(int index)
 260:   {
 261:     if (index < 0 || index >= count)
 262:       throw new StringIndexOutOfBoundsException(index);
 263:     return value[index];
 264:   }
 265: 
 266:   /**
 267:    * Get the code point at the specified index.  This is like #charAt(int),
 268:    * but if the character is the start of a surrogate pair, and the
 269:    * following character completes the pair, then the corresponding
 270:    * supplementary code point is returned.
 271:    * @param index the index of the codepoint to get, starting at 0
 272:    * @return the codepoint at the specified index
 273:    * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
 274:    * @since 1.5
 275:    */
 276:   public synchronized int codePointAt(int index)
 277:   {
 278:     return Character.codePointAt(value, index, count);
 279:   }
 280: 
 281:   /**
 282:    * Get the code point before the specified index.  This is like
 283:    * #codePointAt(int), but checks the characters at <code>index-1</code> and
 284:    * <code>index-2</code> to see if they form a supplementary code point.
 285:    * @param index the index just past the codepoint to get, starting at 0
 286:    * @return the codepoint at the specified index
 287:    * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
 288:    * @since 1.5
 289:    */
 290:   public synchronized int codePointBefore(int index)
 291:   {
 292:     // Character.codePointBefore() doesn't perform this check.  We
 293:     // could use the CharSequence overload, but this is just as easy.
 294:     if (index >= count)
 295:       throw new IndexOutOfBoundsException();
 296:     return Character.codePointBefore(value, index, 1);
 297:   }
 298: 
 299:   /**
 300:    * Get the specified array of characters. <code>srcOffset - srcEnd</code>
 301:    * characters will be copied into the array you pass in.
 302:    *
 303:    * @param srcOffset the index to start copying from (inclusive)
 304:    * @param srcEnd the index to stop copying from (exclusive)
 305:    * @param dst the array to copy into
 306:    * @param dstOffset the index to start copying into
 307:    * @throws NullPointerException if dst is null
 308:    * @throws IndexOutOfBoundsException if any source or target indices are
 309:    *         out of range (while unspecified, source problems cause a
 310:    *         StringIndexOutOfBoundsException, and dest problems cause an
 311:    *         ArrayIndexOutOfBoundsException)
 312:    * @see System#arraycopy(Object, int, Object, int, int)
 313:    */
 314:   public synchronized void getChars(int srcOffset, int srcEnd,
 315:                                     char[] dst, int dstOffset)
 316:   {
 317:     if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
 318:       throw new StringIndexOutOfBoundsException();
 319:     System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
 320:   }
 321: 
 322:   /**
 323:    * Set the character at the specified index.
 324:    *
 325:    * @param index the index of the character to set starting at 0
 326:    * @param ch the value to set that character to
 327:    * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
 328:    *         (while unspecified, this is a StringIndexOutOfBoundsException)
 329:    */
 330:   public synchronized void setCharAt(int index, char ch)
 331:   {
 332:     if (index < 0 || index >= count)
 333:       throw new StringIndexOutOfBoundsException(index);
 334:     // Call ensureCapacity to enforce copy-on-write.
 335:     ensureCapacity_unsynchronized(count);
 336:     value[index] = ch;
 337:   }
 338: 
 339:   /**
 340:    * Append the <code>String</code> value of the argument to this
 341:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 342:    * to <code>String</code>.
 343:    *
 344:    * @param obj the <code>Object</code> to convert and append
 345:    * @return this <code>StringBuffer</code>
 346:    * @see String#valueOf(Object)
 347:    * @see #append(String)
 348:    */
 349:   public StringBuffer append(Object obj)
 350:   {
 351:     return append(obj == null ? "null" : obj.toString());
 352:   }
 353: 
 354:   /**
 355:    * Append the <code>String</code> to this <code>StringBuffer</code>. If
 356:    * str is null, the String "null" is appended.
 357:    *
 358:    * @param str the <code>String</code> to append
 359:    * @return this <code>StringBuffer</code>
 360:    */
 361:   public synchronized StringBuffer append(String str)
 362:   {
 363:     if (str == null)
 364:       str = "null";
 365:     int len = str.count;
 366:     ensureCapacity_unsynchronized(count + len);
 367:     str.getChars(0, len, value, count);
 368:     count += len;
 369:     return this;
 370:   }
 371: 
 372:   /**
 373:    * Append the <code>StringBuffer</code> value of the argument to this
 374:    * <code>StringBuffer</code>. This behaves the same as
 375:    * <code>append((Object) stringBuffer)</code>, except it is more efficient.
 376:    *
 377:    * @param stringBuffer the <code>StringBuffer</code> to convert and append
 378:    * @return this <code>StringBuffer</code>
 379:    * @see #append(Object)
 380:    * @since 1.4
 381:    */
 382:   public synchronized StringBuffer append(StringBuffer stringBuffer)
 383:   {
 384:     if (stringBuffer == null)
 385:       return append("null");
 386:     synchronized (stringBuffer)
 387:       {
 388:         int len = stringBuffer.count;
 389:         ensureCapacity_unsynchronized(count + len);
 390:         System.arraycopy(stringBuffer.value, 0, value, count, len);
 391:         count += len;
 392:       }
 393:     return this;
 394:   }
 395: 
 396:   /**
 397:    * Append the <code>char</code> array to this <code>StringBuffer</code>.
 398:    * This is similar (but more efficient) than
 399:    * <code>append(new String(data))</code>, except in the case of null.
 400:    *
 401:    * @param data the <code>char[]</code> to append
 402:    * @return this <code>StringBuffer</code>
 403:    * @throws NullPointerException if <code>str</code> is <code>null</code>
 404:    * @see #append(char[], int, int)
 405:    */
 406:   public StringBuffer append(char[] data)
 407:   {
 408:     return append(data, 0, data.length);
 409:   }
 410: 
 411:   /**
 412:    * Append part of the <code>char</code> array to this
 413:    * <code>StringBuffer</code>. This is similar (but more efficient) than
 414:    * <code>append(new String(data, offset, count))</code>, except in the case
 415:    * of null.
 416:    *
 417:    * @param data the <code>char[]</code> to append
 418:    * @param offset the start location in <code>str</code>
 419:    * @param count the number of characters to get from <code>str</code>
 420:    * @return this <code>StringBuffer</code>
 421:    * @throws NullPointerException if <code>str</code> is <code>null</code>
 422:    * @throws IndexOutOfBoundsException if offset or count is out of range
 423:    *         (while unspecified, this is a StringIndexOutOfBoundsException)
 424:    */
 425:   public synchronized StringBuffer append(char[] data, int offset, int count)
 426:   {
 427:     if (offset < 0 || count < 0 || offset > data.length - count)
 428:       throw new StringIndexOutOfBoundsException();
 429:     ensureCapacity_unsynchronized(this.count + count);
 430:     System.arraycopy(data, offset, value, this.count, count);
 431:     this.count += count;
 432:     return this;
 433:   }
 434: 
 435:   /**
 436:    * Append the code point to this <code>StringBuffer</code>.
 437:    * This is like #append(char), but will append two characters
 438:    * if a supplementary code point is given.
 439:    *
 440:    * @param code the code point to append
 441:    * @return this <code>StringBuffer</code>
 442:    * @see Character#toChars(int, char[], int)
 443:    * @since 1.5
 444:    */
 445:   public synchronized StringBuffer appendCodePoint(int code)
 446:   {
 447:     int len = Character.charCount(code);
 448:     ensureCapacity_unsynchronized(count + len);
 449:     Character.toChars(code, value, count);
 450:     count += len;
 451:     return this;
 452:   }
 453: 
 454:   /**
 455:    * Append the <code>String</code> value of the argument to this
 456:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 457:    * to <code>String</code>.
 458:    *
 459:    * @param bool the <code>boolean</code> to convert and append
 460:    * @return this <code>StringBuffer</code>
 461:    * @see String#valueOf(boolean)
 462:    */
 463:   public StringBuffer append(boolean bool)
 464:   {
 465:     return append(bool ? "true" : "false");
 466:   }
 467: 
 468:   /**
 469:    * Append the <code>char</code> to this <code>StringBuffer</code>.
 470:    *
 471:    * @param ch the <code>char</code> to append
 472:    * @return this <code>StringBuffer</code>
 473:    */
 474:   public synchronized StringBuffer append(char ch)
 475:   {
 476:     ensureCapacity_unsynchronized(count + 1);
 477:     value[count++] = ch;
 478:     return this;
 479:   }
 480: 
 481:   /**
 482:    * Append the <code>CharSequence</code> value of the argument to this
 483:    * <code>StringBuffer</code>.
 484:    *
 485:    * @param seq the <code>CharSequence</code> to append
 486:    * @return this <code>StringBuffer</code>
 487:    * @see #append(Object)
 488:    * @since 1.5
 489:    */
 490:   public synchronized StringBuffer append(CharSequence seq)
 491:   {
 492:     if (seq == null)
 493:       seq = "null";
 494:     return append(seq, 0, seq.length());
 495:   }
 496: 
 497:   /**
 498:    * Append the specified subsequence of the <code>CharSequence</code>
 499:    * argument to this <code>StringBuffer</code>.
 500:    *
 501:    * @param seq the <code>CharSequence</code> to append
 502:    * @param start the starting index
 503:    * @param end one past the ending index
 504:    * @return this <code>StringBuffer</code>
 505:    * @see #append(Object)
 506:    * @since 1.5
 507:    */
 508:   public synchronized StringBuffer append(CharSequence seq, int start, int end)
 509:   {
 510:     if (seq == null)
 511:       seq = "null";
 512:     if (start < 0 || end < 0 || start > end || end > seq.length())
 513:       throw new IndexOutOfBoundsException();
 514:     ensureCapacity_unsynchronized(this.count + end - start);
 515:     for (int i = start; i < end; ++i)
 516:       value[count++] = seq.charAt(i);
 517:     return this;
 518:   }
 519: 
 520:   /**
 521:    * Append the <code>String</code> value of the argument to this
 522:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 523:    * to <code>String</code>.
 524:    *
 525:    * @param inum the <code>int</code> to convert and append
 526:    * @return this <code>StringBuffer</code>
 527:    * @see String#valueOf(int)
 528:    */
 529:   // GCJ LOCAL: this is native for efficiency.
 530:   public native StringBuffer append (int inum);
 531: 
 532:   /**
 533:    * Append the <code>String</code> value of the argument to this
 534:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 535:    * to <code>String</code>.
 536:    *
 537:    * @param lnum the <code>long</code> to convert and append
 538:    * @return this <code>StringBuffer</code>
 539:    * @see String#valueOf(long)
 540:    */
 541:   public StringBuffer append(long lnum)
 542:   {
 543:     return append(Long.toString(lnum, 10));
 544:   }
 545: 
 546:   /**
 547:    * Append the <code>String</code> value of the argument to this
 548:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 549:    * to <code>String</code>.
 550:    *
 551:    * @param fnum the <code>float</code> to convert and append
 552:    * @return this <code>StringBuffer</code>
 553:    * @see String#valueOf(float)
 554:    */
 555:   public StringBuffer append(float fnum)
 556:   {
 557:     return append(Float.toString(fnum));
 558:   }
 559: 
 560:   /**
 561:    * Append the <code>String</code> value of the argument to this
 562:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 563:    * to <code>String</code>.
 564:    *
 565:    * @param dnum the <code>double</code> to convert and append
 566:    * @return this <code>StringBuffer</code>
 567:    * @see String#valueOf(double)
 568:    */
 569:   public StringBuffer append(double dnum)
 570:   {
 571:     return append(Double.toString(dnum));
 572:   }
 573: 
 574:   /**
 575:    * Delete characters from this <code>StringBuffer</code>.
 576:    * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
 577:    * harmless for end to be larger than length().
 578:    *
 579:    * @param start the first character to delete
 580:    * @param end the index after the last character to delete
 581:    * @return this <code>StringBuffer</code>
 582:    * @throws StringIndexOutOfBoundsException if start or end are out of bounds
 583:    * @since 1.2
 584:    */
 585:   public synchronized StringBuffer delete(int start, int end)
 586:   {
 587:     if (start < 0 || start > count || start > end)
 588:       throw new StringIndexOutOfBoundsException(start);
 589:     if (end > count)
 590:       end = count;
 591:     // This will unshare if required.
 592:     ensureCapacity_unsynchronized(count);
 593:     if (count - end != 0)
 594:       System.arraycopy(value, end, value, start, count - end);
 595:     count -= end - start;
 596:     return this;
 597:   }
 598: 
 599:   /**
 600:    * Delete a character from this <code>StringBuffer</code>.
 601:    *
 602:    * @param index the index of the character to delete
 603:    * @return this <code>StringBuffer</code>
 604:    * @throws StringIndexOutOfBoundsException if index is out of bounds
 605:    * @since 1.2
 606:    */
 607:   public StringBuffer deleteCharAt(int index)
 608:   {
 609:     return delete(index, index + 1);
 610:   }
 611: 
 612:   /**
 613:    * Replace characters between index <code>start</code> (inclusive) and
 614:    * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
 615:    * is larger than the size of this StringBuffer, all characters after
 616:    * <code>start</code> are replaced.
 617:    *
 618:    * @param start the beginning index of characters to delete (inclusive)
 619:    * @param end the ending index of characters to delete (exclusive)
 620:    * @param str the new <code>String</code> to insert
 621:    * @return this <code>StringBuffer</code>
 622:    * @throws StringIndexOutOfBoundsException if start or end are out of bounds
 623:    * @throws NullPointerException if str is null
 624:    * @since 1.2
 625:    */
 626:   public synchronized StringBuffer replace(int start, int end, String str)
 627:   {
 628:     if (start < 0 || start > count || start > end)
 629:       throw new StringIndexOutOfBoundsException(start);
 630: 
 631:     int len = str.count;
 632:     // Calculate the difference in 'count' after the replace.
 633:     int delta = len - (end > count ? count : end) + start;
 634:     ensureCapacity_unsynchronized(count + delta);
 635: 
 636:     if (delta != 0 && end < count)
 637:       System.arraycopy(value, end, value, end + delta, count - end);
 638: 
 639:     str.getChars(0, len, value, start);
 640:     count += delta;
 641:     return this;
 642:   }
 643: 
 644:   /**
 645:    * Creates a substring of this StringBuffer, starting at a specified index
 646:    * and ending at the end of this StringBuffer.
 647:    *
 648:    * @param beginIndex index to start substring (base 0)
 649:    * @return new String which is a substring of this StringBuffer
 650:    * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
 651:    * @see #substring(int, int)
 652:    * @since 1.2
 653:    */
 654:   public String substring(int beginIndex)
 655:   {
 656:     return substring(beginIndex, count);
 657:   }
 658: 
 659:   /**
 660:    * Creates a substring of this StringBuffer, starting at a specified index
 661:    * and ending at one character before a specified index. This is implemented
 662:    * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
 663:    * the CharSequence interface.
 664:    *
 665:    * @param beginIndex index to start at (inclusive, base 0)
 666:    * @param endIndex index to end at (exclusive)
 667:    * @return new String which is a substring of this StringBuffer
 668:    * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
 669:    *         bounds
 670:    * @see #substring(int, int)
 671:    * @since 1.4
 672:    */
 673:   public CharSequence subSequence(int beginIndex, int endIndex)
 674:   {
 675:     return substring(beginIndex, endIndex);
 676:   }
 677: 
 678:   /**
 679:    * Creates a substring of this StringBuffer, starting at a specified index
 680:    * and ending at one character before a specified index.
 681:    *
 682:    * @param beginIndex index to start at (inclusive, base 0)
 683:    * @param endIndex index to end at (exclusive)
 684:    * @return new String which is a substring of this StringBuffer
 685:    * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
 686:    *         of bounds
 687:    * @since 1.2
 688:    */
 689:   public synchronized String substring(int beginIndex, int endIndex)
 690:   {
 691:     int len = endIndex - beginIndex;
 692:     if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
 693:       throw new StringIndexOutOfBoundsException();
 694:     if (len == 0)
 695:       return "";
 696:     // Don't copy unless substring is smaller than 1/4 of the buffer.
 697:     boolean share_buffer = ((len << 2) >= value.length);
 698:     if (share_buffer)
 699:       this.shared = true;
 700:     // Package constructor avoids an array copy.
 701:     return new String(value, beginIndex, len, share_buffer);
 702:   }
 703: 
 704:   /**
 705:    * Insert a subarray of the <code>char[]</code> argument into this
 706:    * <code>StringBuffer</code>.
 707:    *
 708:    * @param offset the place to insert in this buffer
 709:    * @param str the <code>char[]</code> to insert
 710:    * @param str_offset the index in <code>str</code> to start inserting from
 711:    * @param len the number of characters to insert
 712:    * @return this <code>StringBuffer</code>
 713:    * @throws NullPointerException if <code>str</code> is <code>null</code>
 714:    * @throws StringIndexOutOfBoundsException if any index is out of bounds
 715:    * @since 1.2
 716:    */
 717:   public synchronized StringBuffer insert(int offset,
 718:                                           char[] str, int str_offset, int len)
 719:   {
 720:     if (offset < 0 || offset > count || len < 0
 721:         || str_offset < 0 || str_offset > str.length - len)
 722:       throw new StringIndexOutOfBoundsException();
 723:     ensureCapacity_unsynchronized(count + len);
 724:     System.arraycopy(value, offset, value, offset + len, count - offset);
 725:     System.arraycopy(str, str_offset, value, offset, len);
 726:     count += len;
 727:     return this;
 728:   }
 729: 
 730:   /**
 731:    * Insert the <code>String</code> value of the argument into this
 732:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 733:    * to <code>String</code>.
 734:    *
 735:    * @param offset the place to insert in this buffer
 736:    * @param obj the <code>Object</code> to convert and insert
 737:    * @return this <code>StringBuffer</code>
 738:    * @exception StringIndexOutOfBoundsException if offset is out of bounds
 739:    * @see String#valueOf(Object)
 740:    */
 741:   public StringBuffer insert(int offset, Object obj)
 742:   {
 743:     return insert(offset, obj == null ? "null" : obj.toString());
 744:   }
 745: 
 746:   /**
 747:    * Insert the <code>String</code> argument into this
 748:    * <code>StringBuffer</code>. If str is null, the String "null" is used
 749:    * instead.
 750:    *
 751:    * @param offset the place to insert in this buffer
 752:    * @param str the <code>String</code> to insert
 753:    * @return this <code>StringBuffer</code>
 754:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 755:    */
 756:   public synchronized StringBuffer insert(int offset, String str)
 757:   {
 758:     if (offset < 0 || offset > count)
 759:       throw new StringIndexOutOfBoundsException(offset);
 760:     if (str == null)
 761:       str = "null";
 762:     int len = str.count;
 763:     ensureCapacity_unsynchronized(count + len);
 764:     System.arraycopy(value, offset, value, offset + len, count - offset);
 765:     str.getChars(0, len, value, offset);
 766:     count += len;
 767:     return this;
 768:   }
 769: 
 770:   /**
 771:    * Insert the <code>CharSequence</code> argument into this
 772:    * <code>StringBuffer</code>.  If the sequence is null, the String
 773:    * "null" is used instead.
 774:    *
 775:    * @param offset the place to insert in this buffer
 776:    * @param sequence the <code>CharSequence</code> to insert
 777:    * @return this <code>StringBuffer</code>
 778:    * @throws IndexOutOfBoundsException if offset is out of bounds
 779:    * @since 1.5
 780:    */
 781:   public synchronized StringBuffer insert(int offset, CharSequence sequence)
 782:   {
 783:     if (sequence == null)
 784:       sequence = "null";
 785:     return insert(offset, sequence, 0, sequence.length());
 786:   }
 787: 
 788:   /**
 789:    * Insert a subsequence of the <code>CharSequence</code> argument into this
 790:    * <code>StringBuffer</code>.  If the sequence is null, the String
 791:    * "null" is used instead.
 792:    *
 793:    * @param offset the place to insert in this buffer
 794:    * @param sequence the <code>CharSequence</code> to insert
 795:    * @param start the starting index of the subsequence
 796:    * @param end one past the ending index of the subsequence
 797:    * @return this <code>StringBuffer</code>
 798:    * @throws IndexOutOfBoundsException if offset, start,
 799:    * or end are out of bounds
 800:    * @since 1.5
 801:    */
 802:   public synchronized StringBuffer insert(int offset, CharSequence sequence,
 803:                       int start, int end)
 804:   {
 805:     if (sequence == null)
 806:       sequence = "null";
 807:     if (start < 0 || end < 0 || start > end || end > sequence.length())
 808:       throw new IndexOutOfBoundsException();
 809:     int len = end - start;
 810:     ensureCapacity_unsynchronized(count + len);
 811:     System.arraycopy(value, offset, value, offset + len, count - offset);
 812:     for (int i = start; i < end; ++i)
 813:       value[offset++] = sequence.charAt(i);
 814:     count += len;
 815:     return this;
 816:   }
 817: 
 818:   /**
 819:    * Insert the <code>char[]</code> argument into this
 820:    * <code>StringBuffer</code>.
 821:    *
 822:    * @param offset the place to insert in this buffer
 823:    * @param data the <code>char[]</code> to insert
 824:    * @return this <code>StringBuffer</code>
 825:    * @throws NullPointerException if <code>data</code> is <code>null</code>
 826:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 827:    * @see #insert(int, char[], int, int)
 828:    */
 829:   public StringBuffer insert(int offset, char[] data)
 830:   {
 831:     return insert(offset, data, 0, data.length);
 832:   }
 833: 
 834:   /**
 835:    * Insert the <code>String</code> value of the argument into this
 836:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 837:    * to <code>String</code>.
 838:    *
 839:    * @param offset the place to insert in this buffer
 840:    * @param bool the <code>boolean</code> to convert and insert
 841:    * @return this <code>StringBuffer</code>
 842:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 843:    * @see String#valueOf(boolean)
 844:    */
 845:   public StringBuffer insert(int offset, boolean bool)
 846:   {
 847:     return insert(offset, bool ? "true" : "false");
 848:   }
 849: 
 850:   /**
 851:    * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
 852:    *
 853:    * @param offset the place to insert in this buffer
 854:    * @param ch the <code>char</code> to insert
 855:    * @return this <code>StringBuffer</code>
 856:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 857:    */
 858:   public synchronized StringBuffer insert(int offset, char ch)
 859:   {
 860:     if (offset < 0 || offset > count)
 861:       throw new StringIndexOutOfBoundsException(offset);
 862:     ensureCapacity_unsynchronized(count + 1);
 863:     System.arraycopy(value, offset, value, offset + 1, count - offset);
 864:     value[offset] = ch;
 865:     count++;
 866:     return this;
 867:   }
 868: 
 869:   /**
 870:    * Insert the <code>String</code> value of the argument into this
 871:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 872:    * to <code>String</code>.
 873:    *
 874:    * @param offset the place to insert in this buffer
 875:    * @param inum the <code>int</code> to convert and insert
 876:    * @return this <code>StringBuffer</code>
 877:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 878:    * @see String#valueOf(int)
 879:    */
 880:   public StringBuffer insert(int offset, int inum)
 881:   {
 882:     return insert(offset, String.valueOf(inum));
 883:   }
 884: 
 885:   /**
 886:    * Insert the <code>String</code> value of the argument into this
 887:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 888:    * to <code>String</code>.
 889:    *
 890:    * @param offset the place to insert in this buffer
 891:    * @param lnum the <code>long</code> to convert and insert
 892:    * @return this <code>StringBuffer</code>
 893:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 894:    * @see String#valueOf(long)
 895:    */
 896:   public StringBuffer insert(int offset, long lnum)
 897:   {
 898:     return insert(offset, Long.toString(lnum, 10));
 899:   }
 900: 
 901:   /**
 902:    * Insert the <code>String</code> value of the argument into this
 903:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 904:    * to <code>String</code>.
 905:    *
 906:    * @param offset the place to insert in this buffer
 907:    * @param fnum the <code>float</code> to convert and insert
 908:    * @return this <code>StringBuffer</code>
 909:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 910:    * @see String#valueOf(float)
 911:    */
 912:   public StringBuffer insert(int offset, float fnum)
 913:   {
 914:     return insert(offset, Float.toString(fnum));
 915:   }
 916: 
 917:   /**
 918:    * Insert the <code>String</code> value of the argument into this
 919:    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
 920:    * to <code>String</code>.
 921:    *
 922:    * @param offset the place to insert in this buffer
 923:    * @param dnum the <code>double</code> to convert and insert
 924:    * @return this <code>StringBuffer</code>
 925:    * @throws StringIndexOutOfBoundsException if offset is out of bounds
 926:    * @see String#valueOf(double)
 927:    */
 928:   public StringBuffer insert(int offset, double dnum)
 929:   {
 930:     return insert(offset, Double.toString(dnum));
 931:   }
 932: 
 933:   /**
 934:    * Finds the first instance of a substring in this StringBuffer.
 935:    *
 936:    * @param str String to find
 937:    * @return location (base 0) of the String, or -1 if not found
 938:    * @throws NullPointerException if str is null
 939:    * @see #indexOf(String, int)
 940:    * @since 1.4
 941:    */
 942:   public int indexOf(String str)
 943:   {
 944:     return indexOf(str, 0);
 945:   }
 946: 
 947:   /**
 948:    * Finds the first instance of a String in this StringBuffer, starting at
 949:    * a given index.  If starting index is less than 0, the search starts at
 950:    * the beginning of this String.  If the starting index is greater than the
 951:    * length of this String, or the substring is not found, -1 is returned.
 952:    *
 953:    * @param str String to find
 954:    * @param fromIndex index to start the search
 955:    * @return location (base 0) of the String, or -1 if not found
 956:    * @throws NullPointerException if str is null
 957:    * @since 1.4
 958:    */
 959:   public synchronized int indexOf(String str, int fromIndex)
 960:   {
 961:     if (fromIndex < 0)
 962:       fromIndex = 0;
 963:     int limit = count - str.count;
 964:     for ( ; fromIndex <= limit; fromIndex++)
 965:       if (regionMatches(fromIndex, str))
 966:         return fromIndex;
 967:     return -1;
 968:   }
 969: 
 970:   /**
 971:    * Finds the last instance of a substring in this StringBuffer.
 972:    *
 973:    * @param str String to find
 974:    * @return location (base 0) of the String, or -1 if not found
 975:    * @throws NullPointerException if str is null
 976:    * @see #lastIndexOf(String, int)
 977:    * @since 1.4
 978:    */
 979:   public int lastIndexOf(String str)
 980:   {
 981:     return lastIndexOf(str, count - str.count);
 982:   }
 983: 
 984:   /**
 985:    * Finds the last instance of a String in this StringBuffer, starting at a
 986:    * given index.  If starting index is greater than the maximum valid index,
 987:    * then the search begins at the end of this String.  If the starting index
 988:    * is less than zero, or the substring is not found, -1 is returned.
 989:    *
 990:    * @param str String to find
 991:    * @param fromIndex index to start the search
 992:    * @return location (base 0) of the String, or -1 if not found
 993:    * @throws NullPointerException if str is null
 994:    * @since 1.4
 995:    */
 996:   public synchronized int lastIndexOf(String str, int fromIndex)
 997:   {
 998:     fromIndex = Math.min(fromIndex, count - str.count);
 999:     for ( ; fromIndex >= 0; fromIndex--)
1000:       if (regionMatches(fromIndex, str))
1001:         return fromIndex;
1002:     return -1;
1003:   }
1004: 
1005:   /**
1006:    * Reverse the characters in this StringBuffer. The same sequence of
1007:    * characters exists, but in the reverse index ordering.
1008:    *
1009:    * @return this <code>StringBuffer</code>
1010:    */
1011:   public synchronized StringBuffer reverse()
1012:   {
1013:     // Call ensureCapacity to enforce copy-on-write.
1014:     ensureCapacity_unsynchronized(count);
1015:     for (int i = count >> 1, j = count - i; --i >= 0; ++j)
1016:       {
1017:         char c = value[i];
1018:         value[i] = value[j];
1019:         value[j] = c;
1020:       }
1021:     return this;
1022:   }
1023: 
1024:   /**
1025:    * Convert this <code>StringBuffer</code> to a <code>String</code>. The
1026:    * String is composed of the characters currently in this StringBuffer. Note
1027:    * that the result is a copy, and that future modifications to this buffer
1028:    * do not affect the String.
1029:    *
1030:    * @return the characters in this StringBuffer
1031:    */
1032:   public String toString()
1033:   {
1034:     // The string will set this.shared = true.
1035:     return new String(this);
1036:   }
1037: 
1038:   /**
1039:    * This may reduce the amount of memory used by the StringBuffer,
1040:    * by resizing the internal array to remove unused space.  However,
1041:    * this method is not required to resize, so this behavior cannot
1042:    * be relied upon.
1043:    * @since 1.5
1044:    */
1045:   public synchronized void trimToSize()
1046:   {
1047:     int wouldSave = value.length - count;
1048:     // Some random heuristics: if we save less than 20 characters, who
1049:     // cares.
1050:     if (wouldSave < 20)
1051:       return;
1052:     // If we save more than 200 characters, shrink.
1053:     // If we save more than 1/4 of the buffer, shrink.
1054:     if (wouldSave > 200 || wouldSave * 4 > value.length)
1055:       {
1056:     char[] newValue = new char[count];
1057:     System.arraycopy(value, 0, newValue, 0, count);
1058:     value = newValue;
1059:       }
1060:   }
1061: 
1062:   /**
1063:    * Return the number of code points between two indices in the
1064:    * <code>StringBuffer</code>.  An unpaired surrogate counts as a
1065:    * code point for this purpose.  Characters outside the indicated
1066:    * range are not examined, even if the range ends in the middle of a
1067:    * surrogate pair.
1068:    *
1069:    * @param start the starting index
1070:    * @param end one past the ending index
1071:    * @return the number of code points
1072:    * @since 1.5
1073:    */
1074:   public synchronized int codePointCount(int start, int end)
1075:   {
1076:     if (start < 0 || end >= count || start > end)
1077:       throw new StringIndexOutOfBoundsException();
1078: 
1079:     int count = 0;
1080:     while (start < end)
1081:       {
1082:     char base = value[start];
1083:     if (base < Character.MIN_HIGH_SURROGATE
1084:         || base > Character.MAX_HIGH_SURROGATE
1085:         || start == end
1086:         || start == count
1087:         || value[start + 1] < Character.MIN_LOW_SURROGATE
1088:         || value[start + 1] > Character.MAX_LOW_SURROGATE)
1089:       {
1090:         // Nothing.
1091:       }
1092:     else
1093:       {
1094:         // Surrogate pair.
1095:         ++start;
1096:       }
1097:     ++start;
1098:     ++count;
1099:       }
1100:     return count;
1101:   }
1102: 
1103:   /**
1104:    * Starting at the given index, this counts forward by the indicated
1105:    * number of code points, and then returns the resulting index.  An
1106:    * unpaired surrogate counts as a single code point for this
1107:    * purpose.
1108:    *
1109:    * @param start the starting index
1110:    * @param codePoints the number of code points
1111:    * @return the resulting index
1112:    * @since 1.5
1113:    */
1114:   public synchronized int offsetByCodePoints(int start, int codePoints)
1115:   {
1116:     while (codePoints > 0)
1117:       {
1118:     char base = value[start];
1119:     if (base < Character.MIN_HIGH_SURROGATE
1120:         || base > Character.MAX_HIGH_SURROGATE
1121:         || start == count
1122:         || value[start + 1] < Character.MIN_LOW_SURROGATE
1123:         || value[start + 1] > Character.MAX_LOW_SURROGATE)
1124:       {
1125:         // Nothing.
1126:       }
1127:     else
1128:       {
1129:         // Surrogate pair.
1130:         ++start;
1131:       }
1132:     ++start;
1133:     --codePoints;
1134:       }
1135:     return start;
1136:   }
1137: 
1138:   /**
1139:    * An unsynchronized version of ensureCapacity, used internally to avoid
1140:    * the cost of a second lock on the same object. This also has the side
1141:    * effect of duplicating the array, if it was shared (to form copy-on-write
1142:    * semantics).
1143:    *
1144:    * @param minimumCapacity the minimum capacity
1145:    * @see #ensureCapacity(int)
1146:    */
1147:   private void ensureCapacity_unsynchronized(int minimumCapacity)
1148:   {
1149:     if (shared || minimumCapacity > value.length)
1150:       {
1151:         // We don't want to make a larger vector when `shared' is
1152:         // set.  If we do, then setLength becomes very inefficient
1153:         // when repeatedly reusing a StringBuffer in a loop.
1154:         int max = (minimumCapacity > value.length
1155:                    ? value.length * 2 + 2
1156:                    : value.length);
1157:         minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
1158:         char[] nb = new char[minimumCapacity];
1159:         System.arraycopy(value, 0, nb, 0, count);
1160:         value = nb;
1161:         shared = false;
1162:       }
1163:   }
1164: 
1165:   /**
1166:    * Predicate which determines if a substring of this matches another String
1167:    * starting at a specified offset for each String and continuing for a
1168:    * specified length. This is more efficient than creating a String to call
1169:    * indexOf on.
1170:    *
1171:    * @param toffset index to start comparison at for this String
1172:    * @param other non-null String to compare to region of this
1173:    * @return true if regions match, false otherwise
1174:    * @see #indexOf(String, int)
1175:    * @see #lastIndexOf(String, int)
1176:    * @see String#regionMatches(boolean, int, String, int, int)
1177:    */
1178:   // GCJ LOCAL: native for gcj.
1179:   private native boolean regionMatches(int toffset, String other);
1180: }