AbstractStringBuilder.java
0001 /**
0002 * @(#)AbstractStringBuilder.java 1.15 05/11/17
0003 *
0004 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
0005 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
0006 */
0007
0008 package java.lang;
0009
0010 import sun.misc.FloatingDecimal;
0011 import java.util.Arrays;
0012
0013 /***
0014 * A mutable sequence of characters.
0015 * <p>
0016 * Implements a modifiable string. At any point in time it contains some
0017 * particular sequence of characters, but the length and content of the
0018 * sequence can be changed through certain method calls.
0019 *
0020 * @author Michael McCloskey
0021 * @version 1.15, 11/17/05
0022 * @since 1.5
0023 */
0024 abstract class AbstractStringBuilder implements Appendable, CharSequence {
0025 /***
0026 * The value is used for character storage.
0027 */
0028 char value[];
0029
0030 /***
0031 * The count is the number of characters used.
0032 */
0033 int count;
0034
0035 /***
0036 * This no-arg constructor is necessary for serialization of subclasses.
0037 */
0038 AbstractStringBuilder() {
0039 }
0040
0041 /***
0042 * Creates an AbstractStringBuilder of the specified capacity.
0043 */
0044 AbstractStringBuilder(int capacity) {
0045 value = new char[capacity];
0046 }
0047
0048 /***
0049 * Returns the length (character count).
0050 *
0051 * @return the length of the sequence of characters currently
0052 * represented by this object
0053 */
0054 public int length() {
0055 return count;
0056 }
0057
0058 /***
0059 * Returns the current capacity. The capacity is the amount of storage
0060 * available for newly inserted characters, beyond which an allocation
0061 * will occur.
0062 *
0063 * @return the current capacity
0064 */
0065 public int capacity() {
0066 return value.length;
0067 }
0068
0069 /***
0070 * Ensures that the capacity is at least equal to the specified minimum.
0071 * If the current capacity is less than the argument, then a new internal
0072 * array is allocated with greater capacity. The new capacity is the
0073 * larger of:
0074 * <ul>
0075 * <li>The <code>minimumCapacity</code> argument.
0076 * <li>Twice the old capacity, plus <code>2</code>.
0077 * </ul>
0078 * If the <code>minimumCapacity</code> argument is nonpositive, this
0079 * method takes no action and simply returns.
0080 *
0081 * @param minimumCapacity the minimum desired capacity.
0082 */
0083 public void ensureCapacity(int minimumCapacity) {
0084 if (minimumCapacity > value.length) {
0085 expandCapacity(minimumCapacity);
0086 }
0087 }
0088
0089 /***
0090 * This implements the expansion semantics of ensureCapacity with no
0091 * size check or synchronization.
0092 */
0093 void expandCapacity(int minimumCapacity) {
0094 int newCapacity = (value.length + 1) * 2;
0095 if (newCapacity < 0) {
0096 newCapacity = Integer.MAX_VALUE;
0097 } else if (minimumCapacity > newCapacity) {
0098 newCapacity = minimumCapacity;
0099 }
0100 value = Arrays.copyOf(value, newCapacity);
0101 }
0102
0103 /***
0104 * Attempts to reduce storage used for the character sequence.
0105 * If the buffer is larger than necessary to hold its current sequence of
0106 * characters, then it may be resized to become more space efficient.
0107 * Calling this method may, but is not required to, affect the value
0108 * returned by a subsequent call to the {@link #capacity()} method.
0109 */
0110 public void trimToSize() {
0111 if (count < value.length) {
0112 value = Arrays.copyOf(value, count);
0113 }
0114 }
0115
0116 /***
0117 * Sets the length of the character sequence.
0118 * The sequence is changed to a new character sequence
0119 * whose length is specified by the argument. For every nonnegative
0120 * index <i>k</i> less than <code>newLength</code>, the character at
0121 * index <i>k</i> in the new character sequence is the same as the
0122 * character at index <i>k</i> in the old sequence if <i>k</i> is less
0123 * than the length of the old character sequence; otherwise, it is the
0124 * null character <code>'\u0000'</code>.
0125 *
0126 * In other words, if the <code>newLength</code> argument is less than
0127 * the current length, the length is changed to the specified length.
0128 * <p>
0129 * If the <code>newLength</code> argument is greater than or equal
0130 * to the current length, sufficient null characters
0131 * (<code>'\u0000'</code>) are appended so that
0132 * length becomes the <code>newLength</code> argument.
0133 * <p>
0134 * The <code>newLength</code> argument must be greater than or equal
0135 * to <code>0</code>.
0136 *
0137 * @param newLength the new length
0138 * @throws IndexOutOfBoundsException if the
0139 * <code>newLength</code> argument is negative.
0140 */
0141 public void setLength(int newLength) {
0142 if (newLength < 0)
0143 throw new StringIndexOutOfBoundsException(newLength);
0144 if (newLength > value.length)
0145 expandCapacity(newLength);
0146
0147 if (count < newLength) {
0148 for (; count < newLength; count++)
0149 value[count] = '\0';
0150 } else {
0151 count = newLength;
0152 }
0153 }
0154
0155 /***
0156 * Returns the <code>char</code> value in this sequence at the specified index.
0157 * The first <code>char</code> value is at index <code>0</code>, the next at index
0158 * <code>1</code>, and so on, as in array indexing.
0159 * <p>
0160 * The index argument must be greater than or equal to
0161 * <code>0</code>, and less than the length of this sequence.
0162 *
0163 * <p>If the <code>char</code> value specified by the index is a
0164 * <a href="Character.html#unicode">surrogate</a>, the surrogate
0165 * value is returned.
0166 *
0167 * @param index the index of the desired <code>char</code> value.
0168 * @return the <code>char</code> value at the specified index.
0169 * @throws IndexOutOfBoundsException if <code>index</code> is
0170 * negative or greater than or equal to <code>length()</code>.
0171 */
0172 public char charAt(int index) {
0173 if ((index < 0) || (index >= count))
0174 throw new StringIndexOutOfBoundsException(index);
0175 return value[index];
0176 }
0177
0178 /***
0179 * Returns the character (Unicode code point) at the specified
0180 * index. The index refers to <code>char</code> values
0181 * (Unicode code units) and ranges from <code>0</code> to
0182 * {@link #length()}<code> - 1</code>.
0183 *
0184 * <p> If the <code>char</code> value specified at the given index
0185 * is in the high-surrogate range, the following index is less
0186 * than the length of this sequence, and the
0187 * <code>char</code> value at the following index is in the
0188 * low-surrogate range, then the supplementary code point
0189 * corresponding to this surrogate pair is returned. Otherwise,
0190 * the <code>char</code> value at the given index is returned.
0191 *
0192 * @param index the index to the <code>char</code> values
0193 * @return the code point value of the character at the
0194 * <code>index</code>
0195 * @exception IndexOutOfBoundsException if the <code>index</code>
0196 * argument is negative or not less than the length of this
0197 * sequence.
0198 */
0199 public int codePointAt(int index) {
0200 if ((index < 0) || (index >= count)) {
0201 throw new StringIndexOutOfBoundsException(index);
0202 }
0203 return Character.codePointAt(value, index);
0204 }
0205
0206 /***
0207 * Returns the character (Unicode code point) before the specified
0208 * index. The index refers to <code>char</code> values
0209 * (Unicode code units) and ranges from <code>1</code> to {@link
0210 * #length()}.
0211 *
0212 * <p> If the <code>char</code> value at <code>(index - 1)</code>
0213 * is in the low-surrogate range, <code>(index - 2)</code> is not
0214 * negative, and the <code>char</code> value at <code>(index -
0215 * 2)</code> is in the high-surrogate range, then the
0216 * supplementary code point value of the surrogate pair is
0217 * returned. If the <code>char</code> value at <code>index -
0218 * 1</code> is an unpaired low-surrogate or a high-surrogate, the
0219 * surrogate value is returned.
0220 *
0221 * @param index the index following the code point that should be returned
0222 * @return the Unicode code point value before the given index.
0223 * @exception IndexOutOfBoundsException if the <code>index</code>
0224 * argument is less than 1 or greater than the length
0225 * of this sequence.
0226 */
0227 public int codePointBefore(int index) {
0228 int i = index - 1;
0229 if ((i < 0) || (i >= count)) {
0230 throw new StringIndexOutOfBoundsException(index);
0231 }
0232 return Character.codePointBefore(value, index);
0233 }
0234
0235 /***
0236 * Returns the number of Unicode code points in the specified text
0237 * range of this sequence. The text range begins at the specified
0238 * <code>beginIndex</code> and extends to the <code>char</code> at
0239 * index <code>endIndex - 1</code>. Thus the length (in
0240 * <code>char</code>s) of the text range is
0241 * <code>endIndex-beginIndex</code>. Unpaired surrogates within
0242 * this sequence count as one code point each.
0243 *
0244 * @param beginIndex the index to the first <code>char</code> of
0245 * the text range.
0246 * @param endIndex the index after the last <code>char</code> of
0247 * the text range.
0248 * @return the number of Unicode code points in the specified text
0249 * range
0250 * @exception IndexOutOfBoundsException if the
0251 * <code>beginIndex</code> is negative, or <code>endIndex</code>
0252 * is larger than the length of this sequence, or
0253 * <code>beginIndex</code> is larger than <code>endIndex</code>.
0254 */
0255 public int codePointCount(int beginIndex, int endIndex) {
0256 if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
0257 throw new IndexOutOfBoundsException();
0258 }
0259 return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
0260 }
0261
0262 /***
0263 * Returns the index within this sequence that is offset from the
0264 * given <code>index</code> by <code>codePointOffset</code> code
0265 * points. Unpaired surrogates within the text range given by
0266 * <code>index</code> and <code>codePointOffset</code> count as
0267 * one code point each.
0268 *
0269 * @param index the index to be offset
0270 * @param codePointOffset the offset in code points
0271 * @return the index within this sequence
0272 * @exception IndexOutOfBoundsException if <code>index</code>
0273 * is negative or larger then the length of this sequence,
0274 * or if <code>codePointOffset</code> is positive and the subsequence
0275 * starting with <code>index</code> has fewer than
0276 * <code>codePointOffset</code> code points,
0277 * or if <code>codePointOffset</code> is negative and the subsequence
0278 * before <code>index</code> has fewer than the absolute value of
0279 * <code>codePointOffset</code> code points.
0280 */
0281 public int offsetByCodePoints(int index, int codePointOffset) {
0282 if (index < 0 || index > count) {
0283 throw new IndexOutOfBoundsException();
0284 }
0285 return Character.offsetByCodePointsImpl(value, 0, count,
0286 index, codePointOffset);
0287 }
0288
0289 /***
0290 * Characters are copied from this sequence into the
0291 * destination character array <code>dst</code>. The first character to
0292 * be copied is at index <code>srcBegin</code>; the last character to
0293 * be copied is at index <code>srcEnd-1</code>. The total number of
0294 * characters to be copied is <code>srcEnd-srcBegin</code>. The
0295 * characters are copied into the subarray of <code>dst</code> starting
0296 * at index <code>dstBegin</code> and ending at index:
0297 * <p><blockquote><pre>
0298 * dstbegin + (srcEnd-srcBegin) - 1
0299 * </pre></blockquote>
0300 *
0301 * @param srcBegin start copying at this offset.
0302 * @param srcEnd stop copying at this offset.
0303 * @param dst the array to copy the data into.
0304 * @param dstBegin offset into <code>dst</code>.
0305 * @throws NullPointerException if <code>dst</code> is
0306 * <code>null</code>.
0307 * @throws IndexOutOfBoundsException if any of the following is true:
0308 * <ul>
0309 * <li><code>srcBegin</code> is negative
0310 * <li><code>dstBegin</code> is negative
0311 * <li>the <code>srcBegin</code> argument is greater than
0312 * the <code>srcEnd</code> argument.
0313 * <li><code>srcEnd</code> is greater than
0314 * <code>this.length()</code>.
0315 * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
0316 * <code>dst.length</code>
0317 * </ul>
0318 */
0319 public void getChars(int srcBegin, int srcEnd, char dst[],
0320 int dstBegin)
0321 {
0322 if (srcBegin < 0)
0323 throw new StringIndexOutOfBoundsException(srcBegin);
0324 if ((srcEnd < 0) || (srcEnd > count))
0325 throw new StringIndexOutOfBoundsException(srcEnd);
0326 if (srcBegin > srcEnd)
0327 throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
0328 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
0329 }
0330
0331 /***
0332 * The character at the specified index is set to <code>ch</code>. This
0333 * sequence is altered to represent a new character sequence that is
0334 * identical to the old character sequence, except that it contains the
0335 * character <code>ch</code> at position <code>index</code>.
0336 * <p>
0337 * The index argument must be greater than or equal to
0338 * <code>0</code>, and less than the length of this sequence.
0339 *
0340 * @param index the index of the character to modify.
0341 * @param ch the new character.
0342 * @throws IndexOutOfBoundsException if <code>index</code> is
0343 * negative or greater than or equal to <code>length()</code>.
0344 */
0345 public void setCharAt(int index, char ch) {
0346 if ((index < 0) || (index >= count))
0347 throw new StringIndexOutOfBoundsException(index);
0348 value[index] = ch;
0349 }
0350
0351 /***
0352 * Appends the string representation of the <code>Object</code>
0353 * argument.
0354 * <p>
0355 * The argument is converted to a string as if by the method
0356 * <code>String.valueOf</code>, and the characters of that
0357 * string are then appended to this sequence.
0358 *
0359 * @param obj an <code>Object</code>.
0360 * @return a reference to this object.
0361 */
0362 public AbstractStringBuilder append(Object obj) {
0363 return append(String.valueOf(obj));
0364 }
0365
0366 /***
0367 * Appends the specified string to this character sequence.
0368 * <p>
0369 * The characters of the <code>String</code> argument are appended, in
0370 * order, increasing the length of this sequence by the length of the
0371 * argument. If <code>str</code> is <code>null</code>, then the four
0372 * characters <code>"null"</code> are appended.
0373 * <p>
0374 * Let <i>n</i> be the length of this character sequence just prior to
0375 * execution of the <code>append</code> method. Then the character at
0376 * index <i>k</i> in the new character sequence is equal to the character
0377 * at index <i>k</i> in the old character sequence, if <i>k</i> is less
0378 * than <i>n</i>; otherwise, it is equal to the character at index
0379 * <i>k-n</i> in the argument <code>str</code>.
0380 *
0381 * @param str a string.
0382 * @return a reference to this object.
0383 */
0384 public AbstractStringBuilder append(String str) {
0385 if (str == null) str = "null";
0386 int len = str.length();
0387 if (len == 0) return this;
0388 int newCount = count + len;
0389 if (newCount > value.length)
0390 expandCapacity(newCount);
0391 str.getChars(0, len, value, count);
0392 count = newCount;
0393 return this;
0394 }
0395
0396 // Documentation in subclasses because of synchro difference
0397 public AbstractStringBuilder append(StringBuffer sb) {
0398 if (sb == null)
0399 return append("null");
0400 int len = sb.length();
0401 int newCount = count + len;
0402 if (newCount > value.length)
0403 expandCapacity(newCount);
0404 sb.getChars(0, len, value, count);
0405 count = newCount;
0406 return this;
0407 }
0408
0409 // Documentation in subclasses because of synchro difference
0410 public AbstractStringBuilder append(CharSequence s) {
0411 if (s == null)
0412 s = "null";
0413 if (s instanceof String)
0414 return this.append((String)s);
0415 if (s instanceof StringBuffer)
0416 return this.append((StringBuffer)s);
0417 return this.append(s, 0, s.length());
0418 }
0419
0420 /***
0421 * Appends a subsequence of the specified <code>CharSequence</code> to this
0422 * sequence.
0423 * <p>
0424 * Characters of the argument <code>s</code>, starting at
0425 * index <code>start</code>, are appended, in order, to the contents of
0426 * this sequence up to the (exclusive) index <code>end</code>. The length
0427 * of this sequence is increased by the value of <code>end - start</code>.
0428 * <p>
0429 * Let <i>n</i> be the length of this character sequence just prior to
0430 * execution of the <code>append</code> method. Then the character at
0431 * index <i>k</i> in this character sequence becomes equal to the
0432 * character at index <i>k</i> in this sequence, if <i>k</i> is less than
0433 * <i>n</i>; otherwise, it is equal to the character at index
0434 * <i>k+start-n</i> in the argument <code>s</code>.
0435 * <p>
0436 * If <code>s</code> is <code>null</code>, then this method appends
0437 * characters as if the s parameter was a sequence containing the four
0438 * characters <code>"null"</code>.
0439 *
0440 * @param s the sequence to append.
0441 * @param start the starting index of the subsequence to be appended.
0442 * @param end the end index of the subsequence to be appended.
0443 * @return a reference to this object.
0444 * @throws IndexOutOfBoundsException if
0445 * <code>start</code> or <code>end</code> are negative, or
0446 * <code>start</code> is greater than <code>end</code> or
0447 * <code>end</code> is greater than <code>s.length()</code>
0448 */
0449 public AbstractStringBuilder append(CharSequence s, int start, int end) {
0450 if (s == null)
0451 s = "null";
0452 if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
0453 throw new IndexOutOfBoundsException(
0454 "start " + start + ", end " + end + ", s.length() "
0455 + s.length());
0456 int len = end - start;
0457 if (len == 0)
0458 return this;
0459 int newCount = count + len;
0460 if (newCount > value.length)
0461 expandCapacity(newCount);
0462 for (int i=start; i<end; i++)
0463 value[count++] = s.charAt(i);
0464 count = newCount;
0465 return this;
0466 }
0467
0468 /***
0469 * Appends the string representation of the <code>char</code> array
0470 * argument to this sequence.
0471 * <p>
0472 * The characters of the array argument are appended, in order, to
0473 * the contents of this sequence. The length of this sequence
0474 * increases by the length of the argument.
0475 * <p>
0476 * The overall effect is exactly as if the argument were converted to
0477 * a string by the method {@link String#valueOf(char[])} and the
0478 * characters of that string were then {@link #append(String) appended}
0479 * to this character sequence.
0480 *
0481 * @param str the characters to be appended.
0482 * @return a reference to this object.
0483 */
0484 public AbstractStringBuilder append(char str[]) {
0485 int newCount = count + str.length;
0486 if (newCount > value.length)
0487 expandCapacity(newCount);
0488 System.arraycopy(str, 0, value, count, str.length);
0489 count = newCount;
0490 return this;
0491 }
0492
0493 /***
0494 * Appends the string representation of a subarray of the
0495 * <code>char</code> array argument to this sequence.
0496 * <p>
0497 * Characters of the <code>char</code> array <code>str</code>, starting at
0498 * index <code>offset</code>, are appended, in order, to the contents
0499 * of this sequence. The length of this sequence increases
0500 * by the value of <code>len</code>.
0501 * <p>
0502 * The overall effect is exactly as if the arguments were converted to
0503 * a string by the method {@link String#valueOf(char[],int,int)} and the
0504 * characters of that string were then {@link #append(String) appended}
0505 * to this character sequence.
0506 *
0507 * @param str the characters to be appended.
0508 * @param offset the index of the first <code>char</code> to append.
0509 * @param len the number of <code>char</code>s to append.
0510 * @return a reference to this object.
0511 */
0512 public AbstractStringBuilder append(char str[], int offset, int len) {
0513 int newCount = count + len;
0514 if (newCount > value.length)
0515 expandCapacity(newCount);
0516 System.arraycopy(str, offset, value, count, len);
0517 count = newCount;
0518 return this;
0519 }
0520
0521 /***
0522 * Appends the string representation of the <code>boolean</code>
0523 * argument to the sequence.
0524 * <p>
0525 * The argument is converted to a string as if by the method
0526 * <code>String.valueOf</code>, and the characters of that
0527 * string are then appended to this sequence.
0528 *
0529 * @param b a <code>boolean</code>.
0530 * @return a reference to this object.
0531 */
0532 public AbstractStringBuilder append(boolean b) {
0533 if (b) {
0534 int newCount = count + 4;
0535 if (newCount > value.length)
0536 expandCapacity(newCount);
0537 value[count++] = 't';
0538 value[count++] = 'r';
0539 value[count++] = 'u';
0540 value[count++] = 'e';
0541 } else {
0542 int newCount = count + 5;
0543 if (newCount > value.length)
0544 expandCapacity(newCount);
0545 value[count++] = 'f';
0546 value[count++] = 'a';
0547 value[count++] = 'l';
0548 value[count++] = 's';
0549 value[count++] = 'e';
0550 }
0551 return this;
0552 }
0553
0554 /***
0555 * Appends the string representation of the <code>char</code>
0556 * argument to this sequence.
0557 * <p>
0558 * The argument is appended to the contents of this sequence.
0559 * The length of this sequence increases by <code>1</code>.
0560 * <p>
0561 * The overall effect is exactly as if the argument were converted to
0562 * a string by the method {@link String#valueOf(char)} and the character
0563 * in that string were then {@link #append(String) appended} to this
0564 * character sequence.
0565 *
0566 * @param c a <code>char</code>.
0567 * @return a reference to this object.
0568 */
0569 public AbstractStringBuilder append(char c) {
0570 int newCount = count + 1;
0571 if (newCount > value.length)
0572 expandCapacity(newCount);
0573 value[count++] = c;
0574 return this;
0575 }
0576
0577 /***
0578 * Appends the string representation of the <code>int</code>
0579 * argument to this sequence.
0580 * <p>
0581 * The argument is converted to a string as if by the method
0582 * <code>String.valueOf</code>, and the characters of that
0583 * string are then appended to this sequence.
0584 *
0585 * @param i an <code>int</code>.
0586 * @return a reference to this object.
0587 */
0588 public AbstractStringBuilder append(int i) {
0589 if (i == Integer.MIN_VALUE) {
0590 append("-2147483648");
0591 return this;
0592 }
0593 int appendedLength = (i < 0) ? stringSizeOfInt(-i) + 1
0594 : stringSizeOfInt(i);
0595 int spaceNeeded = count + appendedLength;
0596 if (spaceNeeded > value.length)
0597 expandCapacity(spaceNeeded);
0598 Integer.getChars(i, spaceNeeded, value);
0599 count = spaceNeeded;
0600 return this;
0601 }
0602
0603 final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
0604 99999999, 999999999, Integer.MAX_VALUE };
0605
0606 // Requires positive x
0607 static int stringSizeOfInt(int x) {
0608 for (int i=0; ; i++)
0609 if (x <= sizeTable[i])
0610 return i+1;
0611 }
0612
0613 /***
0614 * Appends the string representation of the <code>long</code>
0615 * argument to this sequence.
0616 * <p>
0617 * The argument is converted to a string as if by the method
0618 * <code>String.valueOf</code>, and the characters of that
0619 * string are then appended to this sequence.
0620 *
0621 * @param l a <code>long</code>.
0622 * @return a reference to this object.
0623 */
0624 public AbstractStringBuilder append(long l) {
0625 if (l == Long.MIN_VALUE) {
0626 append("-9223372036854775808");
0627 return this;
0628 }
0629 int appendedLength = (l < 0) ? stringSizeOfLong(-l) + 1
0630 : stringSizeOfLong(l);
0631 int spaceNeeded = count + appendedLength;
0632 if (spaceNeeded > value.length)
0633 expandCapacity(spaceNeeded);
0634 Long.getChars(l, spaceNeeded, value);
0635 count = spaceNeeded;
0636 return this;
0637 }
0638
0639 // Requires positive x
0640 static int stringSizeOfLong(long x) {
0641 long p = 10;
0642 for (int i=1; i<19; i++) {
0643 if (x < p)
0644 return i;
0645 p = 10*p;
0646 }
0647 return 19;
0648 }
0649
0650 /***
0651 * Appends the string representation of the <code>float</code>
0652 * argument to this sequence.
0653 * <p>
0654 * The argument is converted to a string as if by the method
0655 * <code>String.valueOf</code>, and the characters of that
0656 * string are then appended to this string sequence.
0657 *
0658 * @param f a <code>float</code>.
0659 * @return a reference to this object.
0660 */
0661 public AbstractStringBuilder append(float f) {
0662 new FloatingDecimal(f).appendTo(this);
0663 return this;
0664 }
0665
0666 /***
0667 * Appends the string representation of the <code>double</code>
0668 * argument to this sequence.
0669 * <p>
0670 * The argument is converted to a string as if by the method
0671 * <code>String.valueOf</code>, and the characters of that
0672 * string are then appended to this sequence.
0673 *
0674 * @param d a <code>double</code>.
0675 * @return a reference to this object.
0676 */
0677 public AbstractStringBuilder append(double d) {
0678 new FloatingDecimal(d).appendTo(this);
0679 return this;
0680 }
0681
0682 /***
0683 * Removes the characters in a substring of this sequence.
0684 * The substring begins at the specified <code>start</code> and extends to
0685 * the character at index <code>end - 1</code> or to the end of the
0686 * sequence if no such character exists. If
0687 * <code>start</code> is equal to <code>end</code>, no changes are made.
0688 *
0689 * @param start The beginning index, inclusive.
0690 * @param end The ending index, exclusive.
0691 * @return This object.
0692 * @throws StringIndexOutOfBoundsException if <code>start</code>
0693 * is negative, greater than <code>length()</code>, or
0694 * greater than <code>end</code>.
0695 */
0696 public AbstractStringBuilder delete(int start, int end) {
0697 if (start < 0)
0698 throw new StringIndexOutOfBoundsException(start);
0699 if (end > count)
0700 end = count;
0701 if (start > end)
0702 throw new StringIndexOutOfBoundsException();
0703 int len = end - start;
0704 if (len > 0) {
0705 System.arraycopy(value, start+len, value, start, count-end);
0706 count -= len;
0707 }
0708 return this;
0709 }
0710
0711 /***
0712 * Appends the string representation of the <code>codePoint</code>
0713 * argument to this sequence.
0714 *
0715 * <p> The argument is appended to the contents of this sequence.
0716 * The length of this sequence increases by
0717 * {@link Character#charCount(int) Character.charCount(codePoint)}.
0718 *
0719 * <p> The overall effect is exactly as if the argument were
0720 * converted to a <code>char</code> array by the method {@link
0721 * Character#toChars(int)} and the character in that array were
0722 * then {@link #append(char[]) appended} to this character
0723 * sequence.
0724 *
0725 * @param codePoint a Unicode code point
0726 * @return a reference to this object.
0727 * @exception IllegalArgumentException if the specified
0728 * <code>codePoint</code> isn't a valid Unicode code point
0729 */
0730 public AbstractStringBuilder appendCodePoint(int codePoint) {
0731 if (!Character.isValidCodePoint(codePoint)) {
0732 throw new IllegalArgumentException();
0733 }
0734 int n = 1;
0735 if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
0736 n++;
0737 }
0738 int newCount = count + n;
0739 if (newCount > value.length) {
0740 expandCapacity(newCount);
0741 }
0742 if (n == 1) {
0743 value[count++] = (char) codePoint;
0744 } else {
0745 Character.toSurrogates(codePoint, value, count);
0746 count += n;
0747 }
0748 return this;
0749 }
0750
0751 /***
0752 * Removes the <code>char</code> at the specified position in this
0753 * sequence. This sequence is shortened by one <code>char</code>.
0754 *
0755 * <p>Note: If the character at the given index is a supplementary
0756 * character, this method does not remove the entire character. If
0757 * correct handling of supplementary characters is required,
0758 * determine the number of <code>char</code>s to remove by calling
0759 * <code>Character.charCount(thisSequence.codePointAt(index))</code>,
0760 * where <code>thisSequence</code> is this sequence.
0761 *
0762 * @param index Index of <code>char</code> to remove
0763 * @return This object.
0764 * @throws StringIndexOutOfBoundsException if the <code>index</code>
0765 * is negative or greater than or equal to
0766 * <code>length()</code>.
0767 */
0768 public AbstractStringBuilder deleteCharAt(int index) {
0769 if ((index < 0) || (index >= count))
0770 throw new StringIndexOutOfBoundsException(index);
0771 System.arraycopy(value, index+1, value, index, count-index-1);
0772 count--;
0773 return this;
0774 }
0775
0776 /***
0777 * Replaces the characters in a substring of this sequence
0778 * with characters in the specified <code>String</code>. The substring
0779 * begins at the specified <code>start</code> and extends to the character
0780 * at index <code>end - 1</code> or to the end of the
0781 * sequence if no such character exists. First the
0782 * characters in the substring are removed and then the specified
0783 * <code>String</code> is inserted at <code>start</code>. (This
0784 * sequence will be lengthened to accommodate the
0785 * specified String if necessary.)
0786 *
0787 * @param start The beginning index, inclusive.
0788 * @param end The ending index, exclusive.
0789 * @param str String that will replace previous contents.
0790 * @return This object.
0791 * @throws StringIndexOutOfBoundsException if <code>start</code>
0792 * is negative, greater than <code>length()</code>, or
0793 * greater than <code>end</code>.
0794 */
0795 public AbstractStringBuilder replace(int start, int end, String str) {
0796 if (start < 0)
0797 throw new StringIndexOutOfBoundsException(start);
0798 if (start > count)
0799 throw new StringIndexOutOfBoundsException("start > length()");
0800 if (start > end)
0801 throw new StringIndexOutOfBoundsException("start > end");
0802
0803 if (end > count)
0804 end = count;
0805 int len = str.length();
0806 int newCount = count + len - (end - start);
0807 if (newCount > value.length)
0808 expandCapacity(newCount);
0809
0810 System.arraycopy(value, end, value, start + len, count - end);
0811 str.getChars(value, start);
0812 count = newCount;
0813 return this;
0814 }
0815
0816 /***
0817 * Returns a new <code>String</code> that contains a subsequence of
0818 * characters currently contained in this character sequence. The
0819 * substring begins at the specified index and extends to the end of
0820 * this sequence.
0821 *
0822 * @param start The beginning index, inclusive.
0823 * @return The new string.
0824 * @throws StringIndexOutOfBoundsException if <code>start</code> is
0825 * less than zero, or greater than the length of this object.
0826 */
0827 public String substring(int start) {
0828 return substring(start, count);
0829 }
0830
0831 /***
0832 * Returns a new character sequence that is a subsequence of this sequence.
0833 *
0834 * <p> An invocation of this method of the form
0835 *
0836 * <blockquote><pre>
0837 * sb.subSequence(begin, end)</pre></blockquote>
0838 *
0839 * behaves in exactly the same way as the invocation
0840 *
0841 * <blockquote><pre>
0842 * sb.substring(begin, end)</pre></blockquote>
0843 *
0844 * This method is provided so that this class can
0845 * implement the {@link CharSequence} interface. </p>
0846 *
0847 * @param start the start index, inclusive.
0848 * @param end the end index, exclusive.
0849 * @return the specified subsequence.
0850 *
0851 * @throws IndexOutOfBoundsException
0852 * if <tt>start</tt> or <tt>end</tt> are negative,
0853 * if <tt>end</tt> is greater than <tt>length()</tt>,
0854 * or if <tt>start</tt> is greater than <tt>end</tt>
0855 * @spec JSR-51
0856 */
0857 public CharSequence subSequence(int start, int end) {
0858 return substring(start, end);
0859 }
0860
0861 /***
0862 * Returns a new <code>String</code> that contains a subsequence of
0863 * characters currently contained in this sequence. The
0864 * substring begins at the specified <code>start</code> and
0865 * extends to the character at index <code>end - 1</code>.
0866 *
0867 * @param start The beginning index, inclusive.
0868 * @param end The ending index, exclusive.
0869 * @return The new string.
0870 * @throws StringIndexOutOfBoundsException if <code>start</code>
0871 * or <code>end</code> are negative or greater than
0872 * <code>length()</code>, or <code>start</code> is
0873 * greater than <code>end</code>.
0874 */
0875 public String substring(int start, int end) {
0876 if (start < 0)
0877 throw new StringIndexOutOfBoundsException(start);
0878 if (end > count)
0879 throw new StringIndexOutOfBoundsException(end);
0880 if (start > end)
0881 throw new StringIndexOutOfBoundsException(end - start);
0882 return new String(value, start, end - start);
0883 }
0884
0885 /***
0886 * Inserts the string representation of a subarray of the <code>str</code>
0887 * array argument into this sequence. The subarray begins at the
0888 * specified <code>offset</code> and extends <code>len</code> <code>char</code>s.
0889 * The characters of the subarray are inserted into this sequence at
0890 * the position indicated by <code>index</code>. The length of this
0891 * sequence increases by <code>len</code> <code>char</code>s.
0892 *
0893 * @param index position at which to insert subarray.
0894 * @param str A <code>char</code> array.
0895 * @param offset the index of the first <code>char</code> in subarray to
0896 * be inserted.
0897 * @param len the number of <code>char</code>s in the subarray to
0898 * be inserted.
0899 * @return This object
0900 * @throws StringIndexOutOfBoundsException if <code>index</code>
0901 * is negative or greater than <code>length()</code>, or
0902 * <code>offset</code> or <code>len</code> are negative, or
0903 * <code>(offset+len)</code> is greater than
0904 * <code>str.length</code>.
0905 */
0906 public AbstractStringBuilder insert(int index, char str[], int offset,
0907 int len)
0908 {
0909 if ((index < 0) || (index > length()))
0910 throw new StringIndexOutOfBoundsException(index);
0911 if ((offset < 0) || (len < 0) || (offset > str.length - len))
0912 throw new StringIndexOutOfBoundsException(
0913 "offset " + offset + ", len " + len + ", str.length "
0914 + str.length);
0915 int newCount = count + len;
0916 if (newCount > value.length)
0917 expandCapacity(newCount);
0918 System.arraycopy(value, index, value, index + len, count - index);
0919 System.arraycopy(str, offset, value, index, len);
0920 count = newCount;
0921 return this;
0922 }
0923
0924 /***
0925 * Inserts the string representation of the <code>Object</code>
0926 * argument into this character sequence.
0927 * <p>
0928 * The second argument is converted to a string as if by the method
0929 * <code>String.valueOf</code>, and the characters of that
0930 * string are then inserted into this sequence at the indicated
0931 * offset.
0932 * <p>
0933 * The offset argument must be greater than or equal to
0934 * <code>0</code>, and less than or equal to the length of this
0935 * sequence.
0936 *
0937 * @param offset the offset.
0938 * @param obj an <code>Object</code>.
0939 * @return a reference to this object.
0940 * @throws StringIndexOutOfBoundsException if the offset is invalid.
0941 */
0942 public AbstractStringBuilder insert(int offset, Object obj) {
0943 return insert(offset, String.valueOf(obj));
0944 }
0945
0946 /***
0947 * Inserts the string into this character sequence.
0948 * <p>
0949 * The characters of the <code>String</code> argument are inserted, in
0950 * order, into this sequence at the indicated offset, moving up any
0951 * characters originally above that position and increasing the length
0952 * of this sequence by the length of the argument. If
0953 * <code>str</code> is <code>null</code>, then the four characters
0954 * <code>"null"</code> are inserted into this sequence.
0955 * <p>
0956 * The character at index <i>k</i> in the new character sequence is
0957 * equal to:
0958 * <ul>
0959 * <li>the character at index <i>k</i> in the old character sequence, if
0960 * <i>k</i> is less than <code>offset</code>
0961 * <li>the character at index <i>k</i><code>-offset</code> in the
0962 * argument <code>str</code>, if <i>k</i> is not less than
0963 * <code>offset</code> but is less than <code>offset+str.length()</code>
0964 * <li>the character at index <i>k</i><code>-str.length()</code> in the
0965 * old character sequence, if <i>k</i> is not less than
0966 * <code>offset+str.length()</code>
0967 * </ul><p>
0968 * The offset argument must be greater than or equal to
0969 * <code>0</code>, and less than or equal to the length of this
0970 * sequence.
0971 *
0972 * @param offset the offset.
0973 * @param str a string.
0974 * @return a reference to this object.
0975 * @throws StringIndexOutOfBoundsException if the offset is invalid.
0976 */
0977 public AbstractStringBuilder insert(int offset, String str) {
0978 if ((offset < 0) || (offset > length()))
0979 throw new StringIndexOutOfBoundsException(offset);
0980 if (str == null)
0981 str = "null";
0982 int len = str.length();
0983 int newCount = count + len;
0984 if (newCount > value.length)
0985 expandCapacity(newCount);
0986 System.arraycopy(value, offset, value, offset + len, count - offset);
0987 str.getChars(value, offset);
0988 count = newCount;
0989 return this;
0990 }
0991
0992 /***
0993 * Inserts the string representation of the <code>char</code> array
0994 * argument into this sequence.
0995 * <p>
0996 * The characters of the array argument are inserted into the
0997 * contents of this sequence at the position indicated by
0998 * <code>offset</code>. The length of this sequence increases by
0999 * the length of the argument.
1000 * <p>
1001 * The overall effect is exactly as if the argument were converted to
1002 * a string by the method {@link String#valueOf(char[])} and the
1003 * characters of that string were then
1004 * {@link #insert(int,String) inserted} into this
1005 * character sequence at the position indicated by
1006 * <code>offset</code>.
1007 *
1008 * @param offset the offset.
1009 * @param str a character array.
1010 * @return a reference to this object.
1011 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1012 */
1013 public AbstractStringBuilder insert(int offset, char str[]) {
1014 if ((offset < 0) || (offset > length()))
1015 throw new StringIndexOutOfBoundsException(offset);
1016 int len = str.length;
1017 int newCount = count + len;
1018 if (newCount > value.length)
1019 expandCapacity(newCount);
1020 System.arraycopy(value, offset, value, offset + len, count - offset);
1021 System.arraycopy(str, 0, value, offset, len);
1022 count = newCount;
1023 return this;
1024 }
1025
1026 /***
1027 * Inserts the specified <code>CharSequence</code> into this sequence.
1028 * <p>
1029 * The characters of the <code>CharSequence</code> argument are inserted,
1030 * in order, into this sequence at the indicated offset, moving up
1031 * any characters originally above that position and increasing the length
1032 * of this sequence by the length of the argument s.
1033 * <p>
1034 * The result of this method is exactly the same as if it were an
1035 * invocation of this object's insert(dstOffset, s, 0, s.length()) method.
1036 *
1037 * <p>If <code>s</code> is <code>null</code>, then the four characters
1038 * <code>"null"</code> are inserted into this sequence.
1039 *
1040 * @param dstOffset the offset.
1041 * @param s the sequence to be inserted
1042 * @return a reference to this object.
1043 * @throws IndexOutOfBoundsException if the offset is invalid.
1044 */
1045 public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
1046 if (s == null)
1047 s = "null";
1048 if (s instanceof String)
1049 return this.insert(dstOffset, (String)s);
1050 return this.insert(dstOffset, s, 0, s.length());
1051 }
1052
1053 /***
1054 * Inserts a subsequence of the specified <code>CharSequence</code> into
1055 * this sequence.
1056 * <p>
1057 * The subsequence of the argument <code>s</code> specified by
1058 * <code>start</code> and <code>end</code> are inserted,
1059 * in order, into this sequence at the specified destination offset, moving
1060 * up any characters originally above that position. The length of this
1061 * sequence is increased by <code>end - start</code>.
1062 * <p>
1063 * The character at index <i>k</i> in this sequence becomes equal to:
1064 * <ul>
1065 * <li>the character at index <i>k</i> in this sequence, if
1066 * <i>k</i> is less than <code>dstOffset</code>
1067 * <li>the character at index <i>k</i><code>+start-dstOffset</code> in
1068 * the argument <code>s</code>, if <i>k</i> is greater than or equal to
1069 * <code>dstOffset</code> but is less than <code>dstOffset+end-start</code>
1070 * <li>the character at index <i>k</i><code>-(end-start)</code> in this
1071 * sequence, if <i>k</i> is greater than or equal to
1072 * <code>dstOffset+end-start</code>
1073 * </ul><p>
1074 * The dstOffset argument must be greater than or equal to
1075 * <code>0</code>, and less than or equal to the length of this
1076 * sequence.
1077 * <p>The start argument must be nonnegative, and not greater than
1078 * <code>end</code>.
1079 * <p>The end argument must be greater than or equal to
1080 * <code>start</code>, and less than or equal to the length of s.
1081 *
1082 * <p>If <code>s</code> is <code>null</code>, then this method inserts
1083 * characters as if the s parameter was a sequence containing the four
1084 * characters <code>"null"</code>.
1085 *
1086 * @param dstOffset the offset in this sequence.
1087 * @param s the sequence to be inserted.
1088 * @param start the starting index of the subsequence to be inserted.
1089 * @param end the end index of the subsequence to be inserted.
1090 * @return a reference to this object.
1091 * @throws IndexOutOfBoundsException if <code>dstOffset</code>
1092 * is negative or greater than <code>this.length()</code>, or
1093 * <code>start</code> or <code>end</code> are negative, or
1094 * <code>start</code> is greater than <code>end</code> or
1095 * <code>end</code> is greater than <code>s.length()</code>
1096 */
1097 public AbstractStringBuilder insert(int dstOffset, CharSequence s,
1098 int start, int end) {
1099 if (s == null)
1100 s = "null";
1101 if ((dstOffset < 0) || (dstOffset > this.length()))
1102 throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
1103 if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
1104 throw new IndexOutOfBoundsException(
1105 "start " + start + ", end " + end + ", s.length() "
1106 + s.length());
1107 int len = end - start;
1108 if (len == 0)
1109 return this;
1110 int newCount = count + len;
1111 if (newCount > value.length)
1112 expandCapacity(newCount);
1113 System.arraycopy(value, dstOffset, value, dstOffset + len,
1114 count - dstOffset);
1115 for (int i=start; i<end; i++)
1116 value[dstOffset++] = s.charAt(i);
1117 count = newCount;
1118 return this;
1119 }
1120
1121 /***
1122 * Inserts the string representation of the <code>boolean</code>
1123 * argument into this sequence.
1124 * <p>
1125 * The second argument is converted to a string as if by the method
1126 * <code>String.valueOf</code>, and the characters of that
1127 * string are then inserted into this sequence at the indicated
1128 * offset.
1129 * <p>
1130 * The offset argument must be greater than or equal to
1131 * <code>0</code>, and less than or equal to the length of this
1132 * sequence.
1133 *
1134 * @param offset the offset.
1135 * @param b a <code>boolean</code>.
1136 * @return a reference to this object.
1137 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1138 */
1139 public AbstractStringBuilder insert(int offset, boolean b) {
1140 return insert(offset, String.valueOf(b));
1141 }
1142
1143 /***
1144 * Inserts the string representation of the <code>char</code>
1145 * argument into this sequence.
1146 * <p>
1147 * The second argument is inserted into the contents of this sequence
1148 * at the position indicated by <code>offset</code>. The length
1149 * of this sequence increases by one.
1150 * <p>
1151 * The overall effect is exactly as if the argument were converted to
1152 * a string by the method {@link String#valueOf(char)} and the character
1153 * in that string were then {@link #insert(int, String) inserted} into
1154 * this character sequence at the position indicated by
1155 * <code>offset</code>.
1156 * <p>
1157 * The offset argument must be greater than or equal to
1158 * <code>0</code>, and less than or equal to the length of this
1159 * sequence.
1160 *
1161 * @param offset the offset.
1162 * @param c a <code>char</code>.
1163 * @return a reference to this object.
1164 * @throws IndexOutOfBoundsException if the offset is invalid.
1165 */
1166 public AbstractStringBuilder insert(int offset, char c) {
1167 int newCount = count + 1;
1168 if (newCount > value.length)
1169 expandCapacity(newCount);
1170 System.arraycopy(value, offset, value, offset + 1, count - offset);
1171 value[offset] = c;
1172 count = newCount;
1173 return this;
1174 }
1175
1176 /***
1177 * Inserts the string representation of the second <code>int</code>
1178 * argument into this sequence.
1179 * <p>
1180 * The second argument is converted to a string as if by the method
1181 * <code>String.valueOf</code>, and the characters of that
1182 * string are then inserted into this sequence at the indicated
1183 * offset.
1184 * <p>
1185 * The offset argument must be greater than or equal to
1186 * <code>0</code>, and less than or equal to the length of this
1187 * sequence.
1188 *
1189 * @param offset the offset.
1190 * @param i an <code>int</code>.
1191 * @return a reference to this object.
1192 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1193 */
1194 public AbstractStringBuilder insert(int offset, int i) {
1195 return insert(offset, String.valueOf(i));
1196 }
1197
1198 /***
1199 * Inserts the string representation of the <code>long</code>
1200 * argument into this sequence.
1201 * <p>
1202 * The second argument is converted to a string as if by the method
1203 * <code>String.valueOf</code>, and the characters of that
1204 * string are then inserted into this sequence at the position
1205 * indicated by <code>offset</code>.
1206 * <p>
1207 * The offset argument must be greater than or equal to
1208 * <code>0</code>, and less than or equal to the length of this
1209 * sequence.
1210 *
1211 * @param offset the offset.
1212 * @param l a <code>long</code>.
1213 * @return a reference to this object.
1214 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1215 */
1216 public AbstractStringBuilder insert(int offset, long l) {
1217 return insert(offset, String.valueOf(l));
1218 }
1219
1220 /***
1221 * Inserts the string representation of the <code>float</code>
1222 * argument into this sequence.
1223 * <p>
1224 * The second argument is converted to a string as if by the method
1225 * <code>String.valueOf</code>, and the characters of that
1226 * string are then inserted into this sequence at the indicated
1227 * offset.
1228 * <p>
1229 * The offset argument must be greater than or equal to
1230 * <code>0</code>, and less than or equal to the length of this
1231 * sequence.
1232 *
1233 * @param offset the offset.
1234 * @param f a <code>float</code>.
1235 * @return a reference to this object.
1236 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1237 */
1238 public AbstractStringBuilder insert(int offset, float f) {
1239 return insert(offset, String.valueOf(f));
1240 }
1241
1242 /***
1243 * Inserts the string representation of the <code>double</code>
1244 * argument into this sequence.
1245 * <p>
1246 * The second argument is converted to a string as if by the method
1247 * <code>String.valueOf</code>, and the characters of that
1248 * string are then inserted into this sequence at the indicated
1249 * offset.
1250 * <p>
1251 * The offset argument must be greater than or equal to
1252 * <code>0</code>, and less than or equal to the length of this
1253 * sequence.
1254 *
1255 * @param offset the offset.
1256 * @param d a <code>double</code>.
1257 * @return a reference to this object.
1258 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1259 */
1260 public AbstractStringBuilder insert(int offset, double d) {
1261 return insert(offset, String.valueOf(d));
1262 }
1263
1264 /***
1265 * Returns the index within this string of the first occurrence of the
1266 * specified substring. The integer returned is the smallest value
1267 * <i>k</i> such that:
1268 * <blockquote><pre>
1269 * this.toString().startsWith(str, <i>k</i>)
1270 * </pre></blockquote>
1271 * is <code>true</code>.
1272 *
1273 * @param str any string.
1274 * @return if the string argument occurs as a substring within this
1275 * object, then the index of the first character of the first
1276 * such substring is returned; if it does not occur as a
1277 * substring, <code>-1</code> is returned.
1278 * @throws java.lang.NullPointerException if <code>str</code> is
1279 * <code>null</code>.
1280 */
1281 public int indexOf(String str) {
1282 return indexOf(str, 0);
1283 }
1284
1285 /***
1286 * Returns the index within this string of the first occurrence of the
1287 * specified substring, starting at the specified index. The integer
1288 * returned is the smallest value <tt>k</tt> for which:
1289 * <blockquote><pre>
1290 * k >= Math.min(fromIndex, str.length()) &&
1291 * this.toString().startsWith(str, k)
1292 * </pre></blockquote>
1293 * If no such value of <i>k</i> exists, then -1 is returned.
1294 *
1295 * @param str the substring for which to search.
1296 * @param fromIndex the index from which to start the search.
1297 * @return the index within this string of the first occurrence of the
1298 * specified substring, starting at the specified index.
1299 * @throws java.lang.NullPointerException if <code>str</code> is
1300 * <code>null</code>.
1301 */
1302 public int indexOf(String str, int fromIndex) {
1303 return String.indexOf(value, 0, count,
1304 str.toCharArray(), 0, str.length(), fromIndex);
1305 }
1306
1307 /***
1308 * Returns the index within this string of the rightmost occurrence
1309 * of the specified substring. The rightmost empty string "" is
1310 * considered to occur at the index value <code>this.length()</code>.
1311 * The returned index is the largest value <i>k</i> such that
1312 * <blockquote><pre>
1313 * this.toString().startsWith(str, k)
1314 * </pre></blockquote>
1315 * is true.
1316 *
1317 * @param str the substring to search for.
1318 * @return if the string argument occurs one or more times as a substring
1319 * within this object, then the index of the first character of
1320 * the last such substring is returned. If it does not occur as
1321 * a substring, <code>-1</code> is returned.
1322 * @throws java.lang.NullPointerException if <code>str</code> is
1323 * <code>null</code>.
1324 */
1325 public int lastIndexOf(String str) {
1326 return lastIndexOf(str, count);
1327 }
1328
1329 /***
1330 * Returns the index within this string of the last occurrence of the
1331 * specified substring. The integer returned is the largest value <i>k</i>
1332 * such that:
1333 * <blockquote><pre>
1334 * k <= Math.min(fromIndex, str.length()) &&
1335 * this.toString().startsWith(str, k)
1336 * </pre></blockquote>
1337 * If no such value of <i>k</i> exists, then -1 is returned.
1338 *
1339 * @param str the substring to search for.
1340 * @param fromIndex the index to start the search from.
1341 * @return the index within this sequence of the last occurrence of the
1342 * specified substring.
1343 * @throws java.lang.NullPointerException if <code>str</code> is
1344 * <code>null</code>.
1345 */
1346 public int lastIndexOf(String str, int fromIndex) {
1347 return String.lastIndexOf(value, 0, count,
1348 str.toCharArray(), 0, str.length(), fromIndex);
1349 }
1350
1351 /***
1352 * Causes this character sequence to be replaced by the reverse of
1353 * the sequence. If there are any surrogate pairs included in the
1354 * sequence, these are treated as single characters for the
1355 * reverse operation. Thus, the order of the high-low surrogates
1356 * is never reversed.
1357 *
1358 * Let <i>n</i> be the character length of this character sequence
1359 * (not the length in <code>char</code> values) just prior to
1360 * execution of the <code>reverse</code> method. Then the
1361 * character at index <i>k</i> in the new character sequence is
1362 * equal to the character at index <i>n-k-1</i> in the old
1363 * character sequence.
1364 *
1365 * <p>Note that the reverse operation may result in producing
1366 * surrogate pairs that were unpaired low-surrogates and
1367 * high-surrogates before the operation. For example, reversing
1368 * "\uDC00\uD800" produces "\uD800\uDC00" which is
1369 * a valid surrogate pair.
1370 *
1371 * @return a reference to this object.
1372 */
1373 public AbstractStringBuilder reverse() {
1374 boolean hasSurrogate = false;
1375 int n = count - 1;
1376 for (int j = (n-1) >> 1; j >= 0; --j) {
1377 char temp = value[j];
1378 char temp2 = value[n - j];
1379 if (!hasSurrogate) {
1380 hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
1381 || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
1382 }
1383 value[j] = temp2;
1384 value[n - j] = temp;
1385 }
1386 if (hasSurrogate) {
1387 // Reverse back all valid surrogate pairs
1388 for (int i = 0; i < count - 1; i++) {
1389 char c2 = value[i];
1390 if (Character.isLowSurrogate(c2)) {
1391 char c1 = value[i + 1];
1392 if (Character.isHighSurrogate(c1)) {
1393 value[i++] = c1;
1394 value[i] = c2;
1395 }
1396 }
1397 }
1398 }
1399 return this;
1400 }
1401
1402 /***
1403 * Returns a string representing the data in this sequence.
1404 * A new <code>String</code> object is allocated and initialized to
1405 * contain the character sequence currently represented by this
1406 * object. This <code>String</code> is then returned. Subsequent
1407 * changes to this sequence do not affect the contents of the
1408 * <code>String</code>.
1409 *
1410 * @return a string representation of this sequence of characters.
1411 */
1412 public abstract String toString();
1413
1414 /***
1415 * Needed by <tt>String</tt> for the contentEquals method.
1416 */
1417 final char[] getValue() {
1418 return value;
1419 }
1420
1421 }