1. /*
  2. * @(#)AbstractStringBuilder.java 1.12 04/07/16
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang;
  8. import sun.misc.FloatingDecimal;
  9. /**
  10. * A mutable sequence of characters.
  11. * <p>
  12. * Implements a modifiable string. At any point in time it contains some
  13. * particular sequence of characters, but the length and content of the
  14. * sequence can be changed through certain method calls.
  15. *
  16. * @author Michael McCloskey
  17. * @version 1.12, 07/16/04
  18. * @since 1.5
  19. */
  20. abstract class AbstractStringBuilder implements Appendable, CharSequence {
  21. /**
  22. * The value is used for character storage.
  23. */
  24. char value[];
  25. /**
  26. * The count is the number of characters used.
  27. */
  28. int count;
  29. /**
  30. * This no-arg constructor is necessary for serialization of subclasses.
  31. */
  32. AbstractStringBuilder() {
  33. }
  34. /**
  35. * Creates an AbstractStringBuilder of the specified capacity.
  36. */
  37. AbstractStringBuilder(int capacity) {
  38. value = new char[capacity];
  39. }
  40. /**
  41. * Returns the length (character count).
  42. *
  43. * @return the length of the sequence of characters currently
  44. * represented by this object
  45. */
  46. public int length() {
  47. return count;
  48. }
  49. /**
  50. * Returns the current capacity. The capacity is the amount of storage
  51. * available for newly inserted characters, beyond which an allocation
  52. * will occur.
  53. *
  54. * @return the current capacity
  55. */
  56. public int capacity() {
  57. return value.length;
  58. }
  59. /**
  60. * Ensures that the capacity is at least equal to the specified minimum.
  61. * If the current capacity is less than the argument, then a new internal
  62. * array is allocated with greater capacity. The new capacity is the
  63. * larger of:
  64. * <ul>
  65. * <li>The <code>minimumCapacity</code> argument.
  66. * <li>Twice the old capacity, plus <code>2</code>.
  67. * </ul>
  68. * If the <code>minimumCapacity</code> argument is nonpositive, this
  69. * method takes no action and simply returns.
  70. *
  71. * @param minimumCapacity the minimum desired capacity.
  72. */
  73. public void ensureCapacity(int minimumCapacity) {
  74. if (minimumCapacity > value.length) {
  75. expandCapacity(minimumCapacity);
  76. }
  77. }
  78. /**
  79. * This implements the expansion semantics of ensureCapacity with no
  80. * size check or synchronization.
  81. */
  82. void expandCapacity(int minimumCapacity) {
  83. int newCapacity = (value.length + 1) * 2;
  84. if (newCapacity < 0) {
  85. newCapacity = Integer.MAX_VALUE;
  86. } else if (minimumCapacity > newCapacity) {
  87. newCapacity = minimumCapacity;
  88. }
  89. char newValue[] = new char[newCapacity];
  90. System.arraycopy(value, 0, newValue, 0, count);
  91. value = newValue;
  92. }
  93. /**
  94. * Attempts to reduce storage used for the character sequence.
  95. * If the buffer is larger than necessary to hold its current sequence of
  96. * characters, then it may be resized to become more space efficient.
  97. * Calling this method may, but is not required to, affect the value
  98. * returned by a subsequent call to the {@link #capacity()} method.
  99. */
  100. public void trimToSize() {
  101. if (count < value.length) {
  102. char[] newValue = new char[count];
  103. System.arraycopy(value, 0, newValue, 0, count);
  104. this.value = newValue;
  105. }
  106. }
  107. /**
  108. * Sets the length of the character sequence.
  109. * The sequence is changed to a new character sequence
  110. * whose length is specified by the argument. For every nonnegative
  111. * index <i>k</i> less than <code>newLength</code>, the character at
  112. * index <i>k</i> in the new character sequence is the same as the
  113. * character at index <i>k</i> in the old sequence if <i>k</i> is less
  114. * than the length of the old character sequence; otherwise, it is the
  115. * null character <code>'\u0000'</code>.
  116. *
  117. * In other words, if the <code>newLength</code> argument is less than
  118. * the current length, the length is changed to the specified length.
  119. * <p>
  120. * If the <code>newLength</code> argument is greater than or equal
  121. * to the current length, sufficient null characters
  122. * (<code>'\u0000'</code>) are appended so that
  123. * length becomes the <code>newLength</code> argument.
  124. * <p>
  125. * The <code>newLength</code> argument must be greater than or equal
  126. * to <code>0</code>.
  127. *
  128. * @param newLength the new length
  129. * @throws IndexOutOfBoundsException if the
  130. * <code>newLength</code> argument is negative.
  131. */
  132. public void setLength(int newLength) {
  133. if (newLength < 0)
  134. throw new StringIndexOutOfBoundsException(newLength);
  135. if (newLength > value.length)
  136. expandCapacity(newLength);
  137. if (count < newLength) {
  138. for (; count < newLength; count++)
  139. value[count] = '\0';
  140. } else {
  141. count = newLength;
  142. }
  143. }
  144. /**
  145. * Returns the <code>char</code> value in this sequence at the specified index.
  146. * The first <code>char</code> value is at index <code>0</code>, the next at index
  147. * <code>1</code>, and so on, as in array indexing.
  148. * <p>
  149. * The index argument must be greater than or equal to
  150. * <code>0</code>, and less than the length of this sequence.
  151. *
  152. * <p>If the <code>char</code> value specified by the index is a
  153. * <a href="Character.html#unicode">surrogate</a>, the surrogate
  154. * value is returned.
  155. *
  156. * @param index the index of the desired <code>char</code> value.
  157. * @return the <code>char</code> value at the specified index.
  158. * @throws IndexOutOfBoundsException if <code>index</code> is
  159. * negative or greater than or equal to <code>length()</code>.
  160. */
  161. public char charAt(int index) {
  162. if ((index < 0) || (index >= count))
  163. throw new StringIndexOutOfBoundsException(index);
  164. return value[index];
  165. }
  166. /**
  167. * Returns the character (Unicode code point) at the specified
  168. * index. The index refers to <code>char</code> values
  169. * (Unicode code units) and ranges from <code>0</code> to
  170. * {@link #length()}<code> - 1</code>.
  171. *
  172. * <p> If the <code>char</code> value specified at the given index
  173. * is in the high-surrogate range, the following index is less
  174. * than the length of this sequence, and the
  175. * <code>char</code> value at the following index is in the
  176. * low-surrogate range, then the supplementary code point
  177. * corresponding to this surrogate pair is returned. Otherwise,
  178. * the <code>char</code> value at the given index is returned.
  179. *
  180. * @param index the index to the <code>char</code> values
  181. * @return the code point value of the character at the
  182. * <code>index</code>
  183. * @exception IndexOutOfBoundsException if the <code>index</code>
  184. * argument is negative or not less than the length of this
  185. * sequence.
  186. */
  187. public int codePointAt(int index) {
  188. if ((index < 0) || (index >= count)) {
  189. throw new StringIndexOutOfBoundsException(index);
  190. }
  191. return Character.codePointAt(value, index);
  192. }
  193. /**
  194. * Returns the character (Unicode code point) before the specified
  195. * index. The index refers to <code>char</code> values
  196. * (Unicode code units) and ranges from <code>1</code> to {@link
  197. * #length()}.
  198. *
  199. * <p> If the <code>char</code> value at <code>(index - 1)</code>
  200. * is in the low-surrogate range, <code>(index - 2)</code> is not
  201. * negative, and the <code>char</code> value at <code>(index -
  202. * 2)</code> is in the high-surrogate range, then the
  203. * supplementary code point value of the surrogate pair is
  204. * returned. If the <code>char</code> value at <code>index -
  205. * 1</code> is an unpaired low-surrogate or a high-surrogate, the
  206. * surrogate value is returned.
  207. *
  208. * @param index the index following the code point that should be returned
  209. * @return the Unicode code point value before the given index.
  210. * @exception IndexOutOfBoundsException if the <code>index</code>
  211. * argument is less than 1 or greater than the length
  212. * of this sequence.
  213. */
  214. public int codePointBefore(int index) {
  215. int i = index - 1;
  216. if ((i < 0) || (i >= count)) {
  217. throw new StringIndexOutOfBoundsException(index);
  218. }
  219. return Character.codePointBefore(value, index);
  220. }
  221. /**
  222. * Returns the number of Unicode code points in the specified text
  223. * range of this sequence. The text range begins at the specified
  224. * <code>beginIndex</code> and extends to the <code>char</code> at
  225. * index <code>endIndex - 1</code>. Thus the length (in
  226. * <code>char</code>s) of the text range is
  227. * <code>endIndex-beginIndex</code>. Unpaired surrogates within
  228. * this sequence count as one code point each.
  229. *
  230. * @param beginIndex the index to the first <code>char</code> of
  231. * the text range.
  232. * @param endIndex the index after the last <code>char</code> of
  233. * the text range.
  234. * @return the number of Unicode code points in the specified text
  235. * range
  236. * @exception IndexOutOfBoundsException if the
  237. * <code>beginIndex</code> is negative, or <code>endIndex</code>
  238. * is larger than the length of this sequence, or
  239. * <code>beginIndex</code> is larger than <code>endIndex</code>.
  240. */
  241. public int codePointCount(int beginIndex, int endIndex) {
  242. if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
  243. throw new IndexOutOfBoundsException();
  244. }
  245. return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
  246. }
  247. /**
  248. * Returns the index within this sequence that is offset from the
  249. * given <code>index</code> by <code>codePointOffset</code> code
  250. * points. Unpaired surrogates within the text range given by
  251. * <code>index</code> and <code>codePointOffset</code> count as
  252. * one code point each.
  253. *
  254. * @param index the index to be offset
  255. * @param codePointOffset the offset in code points
  256. * @return the index within this sequence
  257. * @exception IndexOutOfBoundsException if <code>index</code>
  258. * is negative or larger then the length of this sequence,
  259. * or if <code>codePointOffset</code> is positive and the subsequence
  260. * starting with <code>index</code> has fewer than
  261. * <code>codePointOffset</code> code points,
  262. * or if <code>codePointOffset</code> is negative and the subsequence
  263. * before <code>index</code> has fewer than the absolute value of
  264. * <code>codePointOffset</code> code points.
  265. */
  266. public int offsetByCodePoints(int index, int codePointOffset) {
  267. if (index < 0 || index > count) {
  268. throw new IndexOutOfBoundsException();
  269. }
  270. return Character.offsetByCodePointsImpl(value, 0, count,
  271. index, codePointOffset);
  272. }
  273. /**
  274. * Characters are copied from this sequence into the
  275. * destination character array <code>dst</code>. The first character to
  276. * be copied is at index <code>srcBegin</code> the last character to
  277. * be copied is at index <code>srcEnd-1</code>. The total number of
  278. * characters to be copied is <code>srcEnd-srcBegin</code>. The
  279. * characters are copied into the subarray of <code>dst</code> starting
  280. * at index <code>dstBegin</code> and ending at index:
  281. * <p><blockquote><pre>
  282. * dstbegin + (srcEnd-srcBegin) - 1
  283. * </pre></blockquote>
  284. *
  285. * @param srcBegin start copying at this offset.
  286. * @param srcEnd stop copying at this offset.
  287. * @param dst the array to copy the data into.
  288. * @param dstBegin offset into <code>dst</code>.
  289. * @throws NullPointerException if <code>dst</code> is
  290. * <code>null</code>.
  291. * @throws IndexOutOfBoundsException if any of the following is true:
  292. * <ul>
  293. * <li><code>srcBegin</code> is negative
  294. * <li><code>dstBegin</code> is negative
  295. * <li>the <code>srcBegin</code> argument is greater than
  296. * the <code>srcEnd</code> argument.
  297. * <li><code>srcEnd</code> is greater than
  298. * <code>this.length()</code>.
  299. * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
  300. * <code>dst.length</code>
  301. * </ul>
  302. */
  303. public void getChars(int srcBegin, int srcEnd, char dst[],
  304. int dstBegin)
  305. {
  306. if (srcBegin < 0)
  307. throw new StringIndexOutOfBoundsException(srcBegin);
  308. if ((srcEnd < 0) || (srcEnd > count))
  309. throw new StringIndexOutOfBoundsException(srcEnd);
  310. if (srcBegin > srcEnd)
  311. throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
  312. System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
  313. }
  314. /**
  315. * The character at the specified index is set to <code>ch</code>. This
  316. * sequence is altered to represent a new character sequence that is
  317. * identical to the old character sequence, except that it contains the
  318. * character <code>ch</code> at position <code>index</code>.
  319. * <p>
  320. * The index argument must be greater than or equal to
  321. * <code>0</code>, and less than the length of this sequence.
  322. *
  323. * @param index the index of the character to modify.
  324. * @param ch the new character.
  325. * @throws IndexOutOfBoundsException if <code>index</code> is
  326. * negative or greater than or equal to <code>length()</code>.
  327. */
  328. public void setCharAt(int index, char ch) {
  329. if ((index < 0) || (index >= count))
  330. throw new StringIndexOutOfBoundsException(index);
  331. value[index] = ch;
  332. }
  333. /**
  334. * Appends the string representation of the <code>Object</code>
  335. * argument.
  336. * <p>
  337. * The argument is converted to a string as if by the method
  338. * <code>String.valueOf</code>, and the characters of that
  339. * string are then appended to this sequence.
  340. *
  341. * @param obj an <code>Object</code>.
  342. * @return a reference to this object.
  343. */
  344. public AbstractStringBuilder append(Object obj) {
  345. return append(String.valueOf(obj));
  346. }
  347. /**
  348. * Appends the specified string to this character sequence.
  349. * <p>
  350. * The characters of the <code>String</code> argument are appended, in
  351. * order, increasing the length of this sequence by the length of the
  352. * argument. If <code>str</code> is <code>null</code>, then the four
  353. * characters <code>"null"</code> are appended.
  354. * <p>
  355. * Let <i>n</i> be the length of this character sequence just prior to
  356. * execution of the <code>append</code> method. Then the character at
  357. * index <i>k</i> in the new character sequence is equal to the character
  358. * at index <i>k</i> in the old character sequence, if <i>k</i> is less
  359. * than <i>n</i> otherwise, it is equal to the character at index
  360. * <i>k-n</i> in the argument <code>str</code>.
  361. *
  362. * @param str a string.
  363. * @return a reference to this object.
  364. */
  365. public AbstractStringBuilder append(String str) {
  366. if (str == null) str = "null";
  367. int len = str.length();
  368. if (len == 0) return this;
  369. int newCount = count + len;
  370. if (newCount > value.length)
  371. expandCapacity(newCount);
  372. str.getChars(0, len, value, count);
  373. count = newCount;
  374. return this;
  375. }
  376. // Documentation in subclasses because of synchro difference
  377. public AbstractStringBuilder append(StringBuffer sb) {
  378. if (sb == null)
  379. return append("null");
  380. int len = sb.length();
  381. int newCount = count + len;
  382. if (newCount > value.length)
  383. expandCapacity(newCount);
  384. sb.getChars(0, len, value, count);
  385. count = newCount;
  386. return this;
  387. }
  388. // Documentation in subclasses because of synchro difference
  389. public AbstractStringBuilder append(CharSequence s) {
  390. if (s == null)
  391. s = "null";
  392. if (s instanceof String)
  393. return this.append((String)s);
  394. if (s instanceof StringBuffer)
  395. return this.append((StringBuffer)s);
  396. return this.append(s, 0, s.length());
  397. }
  398. /**
  399. * Appends a subsequence of the specified <code>CharSequence</code> to this
  400. * sequence.
  401. * <p>
  402. * Characters of the argument <code>s</code>, starting at
  403. * index <code>start</code>, are appended, in order, to the contents of
  404. * this sequence up to the (exclusive) index <code>end</code>. The length
  405. * of this sequence is increased by the value of <code>end - start</code>.
  406. * <p>
  407. * Let <i>n</i> be the length of this character sequence just prior to
  408. * execution of the <code>append</code> method. Then the character at
  409. * index <i>k</i> in this character sequence becomes equal to the
  410. * character at index <i>k</i> in this sequence, if <i>k</i> is less than
  411. * <i>n</i> otherwise, it is equal to the character at index
  412. * <i>k+start-n</i> in the argument <code>s</code>.
  413. * <p>
  414. * If <code>s</code> is <code>null</code>, then this method appends
  415. * characters as if the s parameter was a sequence containing the four
  416. * characters <code>"null"</code>.
  417. *
  418. * @param s the sequence to append.
  419. * @param start the starting index of the subsequence to be appended.
  420. * @param end the end index of the subsequence to be appended.
  421. * @return a reference to this object.
  422. * @throws IndexOutOfBoundsException if
  423. * <code>start</code> or <code>end</code> are negative, or
  424. * <code>start</code> is greater than <code>end</code> or
  425. * <code>end</code> is greater than <code>s.length()</code>
  426. */
  427. public AbstractStringBuilder append(CharSequence s, int start, int end) {
  428. if (s == null)
  429. s = "null";
  430. if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
  431. throw new IndexOutOfBoundsException(
  432. "start " + start + ", end " + end + ", s.length() "
  433. + s.length());
  434. int len = end - start;
  435. if (len == 0)
  436. return this;
  437. int newCount = count + len;
  438. if (newCount > value.length)
  439. expandCapacity(newCount);
  440. for (int i=start; i<end; i++)
  441. value[count++] = s.charAt(i);
  442. count = newCount;
  443. return this;
  444. }
  445. /**
  446. * Appends the string representation of the <code>char</code> array
  447. * argument to this sequence.
  448. * <p>
  449. * The characters of the array argument are appended, in order, to
  450. * the contents of this sequence. The length of this sequence
  451. * increases by the length of the argument.
  452. * <p>
  453. * The overall effect is exactly as if the argument were converted to
  454. * a string by the method {@link String#valueOf(char[])} and the
  455. * characters of that string were then {@link #append(String) appended}
  456. * to this character sequence.
  457. *
  458. * @param str the characters to be appended.
  459. * @return a reference to this object.
  460. */
  461. public AbstractStringBuilder append(char str[]) {
  462. int newCount = count + str.length;
  463. if (newCount > value.length)
  464. expandCapacity(newCount);
  465. System.arraycopy(str, 0, value, count, str.length);
  466. count = newCount;
  467. return this;
  468. }
  469. /**
  470. * Appends the string representation of a subarray of the
  471. * <code>char</code> array argument to this sequence.
  472. * <p>
  473. * Characters of the <code>char</code> array <code>str</code>, starting at
  474. * index <code>offset</code>, are appended, in order, to the contents
  475. * of this sequence. The length of this sequence increases
  476. * by the value of <code>len</code>.
  477. * <p>
  478. * The overall effect is exactly as if the arguments were converted to
  479. * a string by the method {@link String#valueOf(char[],int,int)} and the
  480. * characters of that string were then {@link #append(String) appended}
  481. * to this character sequence.
  482. *
  483. * @param str the characters to be appended.
  484. * @param offset the index of the first <code>char</code> to append.
  485. * @param len the number of <code>char</code>s to append.
  486. * @return a reference to this object.
  487. */
  488. public AbstractStringBuilder append(char str[], int offset, int len) {
  489. int newCount = count + len;
  490. if (newCount > value.length)
  491. expandCapacity(newCount);
  492. System.arraycopy(str, offset, value, count, len);
  493. count = newCount;
  494. return this;
  495. }
  496. /**
  497. * Appends the string representation of the <code>boolean</code>
  498. * argument to the sequence.
  499. * <p>
  500. * The argument is converted to a string as if by the method
  501. * <code>String.valueOf</code>, and the characters of that
  502. * string are then appended to this sequence.
  503. *
  504. * @param b a <code>boolean</code>.
  505. * @return a reference to this object.
  506. */
  507. public AbstractStringBuilder append(boolean b) {
  508. if (b) {
  509. int newCount = count + 4;
  510. if (newCount > value.length)
  511. expandCapacity(newCount);
  512. value[count++] = 't';
  513. value[count++] = 'r';
  514. value[count++] = 'u';
  515. value[count++] = 'e';
  516. } else {
  517. int newCount = count + 5;
  518. if (newCount > value.length)
  519. expandCapacity(newCount);
  520. value[count++] = 'f';
  521. value[count++] = 'a';
  522. value[count++] = 'l';
  523. value[count++] = 's';
  524. value[count++] = 'e';
  525. }
  526. return this;
  527. }
  528. /**
  529. * Appends the string representation of the <code>char</code>
  530. * argument to this sequence.
  531. * <p>
  532. * The argument is appended to the contents of this sequence.
  533. * The length of this sequence increases by <code>1</code>.
  534. * <p>
  535. * The overall effect is exactly as if the argument were converted to
  536. * a string by the method {@link String#valueOf(char)} and the character
  537. * in that string were then {@link #append(String) appended} to this
  538. * character sequence.
  539. *
  540. * @param c a <code>char</code>.
  541. * @return a reference to this object.
  542. */
  543. public AbstractStringBuilder append(char c) {
  544. int newCount = count + 1;
  545. if (newCount > value.length)
  546. expandCapacity(newCount);
  547. value[count++] = c;
  548. return this;
  549. }
  550. /**
  551. * Appends the string representation of the <code>int</code>
  552. * argument to this sequence.
  553. * <p>
  554. * The argument is converted to a string as if by the method
  555. * <code>String.valueOf</code>, and the characters of that
  556. * string are then appended to this sequence.
  557. *
  558. * @param i an <code>int</code>.
  559. * @return a reference to this object.
  560. */
  561. public AbstractStringBuilder append(int i) {
  562. if (i == Integer.MIN_VALUE) {
  563. append("-2147483648");
  564. return this;
  565. }
  566. int appendedLength = (i < 0) ? stringSizeOfInt(-i) + 1
  567. : stringSizeOfInt(i);
  568. int spaceNeeded = count + appendedLength;
  569. if (spaceNeeded > value.length)
  570. expandCapacity(spaceNeeded);
  571. Integer.getChars(i, spaceNeeded, value);
  572. count = spaceNeeded;
  573. return this;
  574. }
  575. final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
  576. 99999999, 999999999, Integer.MAX_VALUE };
  577. // Requires positive x
  578. static int stringSizeOfInt(int x) {
  579. for (int i=0; ; i++)
  580. if (x <= sizeTable[i])
  581. return i+1;
  582. }
  583. /**
  584. * Appends the string representation of the <code>long</code>
  585. * argument to this sequence.
  586. * <p>
  587. * The argument is converted to a string as if by the method
  588. * <code>String.valueOf</code>, and the characters of that
  589. * string are then appended to this sequence.
  590. *
  591. * @param l a <code>long</code>.
  592. * @return a reference to this object.
  593. */
  594. public AbstractStringBuilder append(long l) {
  595. if (l == Long.MIN_VALUE) {
  596. append("-9223372036854775808");
  597. return this;
  598. }
  599. int appendedLength = (l < 0) ? stringSizeOfLong(-l) + 1
  600. : stringSizeOfLong(l);
  601. int spaceNeeded = count + appendedLength;
  602. if (spaceNeeded > value.length)
  603. expandCapacity(spaceNeeded);
  604. Long.getChars(l, spaceNeeded, value);
  605. count = spaceNeeded;
  606. return this;
  607. }
  608. // Requires positive x
  609. static int stringSizeOfLong(long x) {
  610. long p = 10;
  611. for (int i=1; i<19; i++) {
  612. if (x < p)
  613. return i;
  614. p = 10*p;
  615. }
  616. return 19;
  617. }
  618. /**
  619. * Appends the string representation of the <code>float</code>
  620. * argument to this sequence.
  621. * <p>
  622. * The argument is converted to a string as if by the method
  623. * <code>String.valueOf</code>, and the characters of that
  624. * string are then appended to this string sequence.
  625. *
  626. * @param f a <code>float</code>.
  627. * @return a reference to this object.
  628. */
  629. public AbstractStringBuilder append(float f) {
  630. new FloatingDecimal(f).appendTo(this);
  631. return this;
  632. }
  633. /**
  634. * Appends the string representation of the <code>double</code>
  635. * argument to this sequence.
  636. * <p>
  637. * The argument is converted to a string as if by the method
  638. * <code>String.valueOf</code>, and the characters of that
  639. * string are then appended to this sequence.
  640. *
  641. * @param d a <code>double</code>.
  642. * @return a reference to this object.
  643. */
  644. public AbstractStringBuilder append(double d) {
  645. new FloatingDecimal(d).appendTo(this);
  646. return this;
  647. }
  648. /**
  649. * Removes the characters in a substring of this sequence.
  650. * The substring begins at the specified <code>start</code> and extends to
  651. * the character at index <code>end - 1</code> or to the end of the
  652. * sequence if no such character exists. If
  653. * <code>start</code> is equal to <code>end</code>, no changes are made.
  654. *
  655. * @param start The beginning index, inclusive.
  656. * @param end The ending index, exclusive.
  657. * @return This object.
  658. * @throws StringIndexOutOfBoundsException if <code>start</code>
  659. * is negative, greater than <code>length()</code>, or
  660. * greater than <code>end</code>.
  661. */
  662. public AbstractStringBuilder delete(int start, int end) {
  663. if (start < 0)
  664. throw new StringIndexOutOfBoundsException(start);
  665. if (end > count)
  666. end = count;
  667. if (start > end)
  668. throw new StringIndexOutOfBoundsException();
  669. int len = end - start;
  670. if (len > 0) {
  671. System.arraycopy(value, start+len, value, start, count-end);
  672. count -= len;
  673. }
  674. return this;
  675. }
  676. /**
  677. * Appends the string representation of the <code>codePoint</code>
  678. * argument to this sequence.
  679. *
  680. * <p> The argument is appended to the contents of this sequence.
  681. * The length of this sequence increases by
  682. * {@link Character#charCount(int) Character.charCount(codePoint)}.
  683. *
  684. * <p> The overall effect is exactly as if the argument were
  685. * converted to a <code>char</code> array by the method {@link
  686. * Character#toChars(int)} and the character in that array were
  687. * then {@link #append(char[]) appended} to this character
  688. * sequence.
  689. *
  690. * @param codePoint a Unicode code point
  691. * @return a reference to this object.
  692. * @exception IllegalArgumentException if the specified
  693. * <code>codePoint</code> isn't a valid Unicode code point
  694. */
  695. public AbstractStringBuilder appendCodePoint(int codePoint) {
  696. if (!Character.isValidCodePoint(codePoint)) {
  697. throw new IllegalArgumentException();
  698. }
  699. int n = 1;
  700. if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
  701. n++;
  702. }
  703. int newCount = count + n;
  704. if (newCount > value.length) {
  705. expandCapacity(newCount);
  706. }
  707. if (n == 1) {
  708. value[count++] = (char) codePoint;
  709. } else {
  710. Character.toSurrogates(codePoint, value, count);
  711. count += n;
  712. }
  713. return this;
  714. }
  715. /**
  716. * Removes the <code>char</code> at the specified position in this
  717. * sequence. This sequence is shortened by one <code>char</code>.
  718. *
  719. * <p>Note: If the character at the given index is a supplementary
  720. * character, this method does not remove the entire character. If
  721. * correct handling of supplementary characters is required,
  722. * determine the number of <code>char</code>s to remove by calling
  723. * <code>Character.charCount(thisSequence.codePointAt(index))</code>,
  724. * where <code>thisSequence</code> is this sequence.
  725. *
  726. * @param index Index of <code>char</code> to remove
  727. * @return This object.
  728. * @throws StringIndexOutOfBoundsException if the <code>index</code>
  729. * is negative or greater than or equal to
  730. * <code>length()</code>.
  731. */
  732. public AbstractStringBuilder deleteCharAt(int index) {
  733. if ((index < 0) || (index >= count))
  734. throw new StringIndexOutOfBoundsException(index);
  735. System.arraycopy(value, index+1, value, index, count-index-1);
  736. count--;
  737. return this;
  738. }
  739. /**
  740. * Replaces the characters in a substring of this sequence
  741. * with characters in the specified <code>String</code>. The substring
  742. * begins at the specified <code>start</code> and extends to the character
  743. * at index <code>end - 1</code> or to the end of the
  744. * sequence if no such character exists. First the
  745. * characters in the substring are removed and then the specified
  746. * <code>String</code> is inserted at <code>start</code>. (This
  747. * sequence will be lengthened to accommodate the
  748. * specified String if necessary.)
  749. *
  750. * @param start The beginning index, inclusive.
  751. * @param end The ending index, exclusive.
  752. * @param str String that will replace previous contents.
  753. * @return This object.
  754. * @throws StringIndexOutOfBoundsException if <code>start</code>
  755. * is negative, greater than <code>length()</code>, or
  756. * greater than <code>end</code>.
  757. */
  758. public AbstractStringBuilder replace(int start, int end, String str) {
  759. if (start < 0)
  760. throw new StringIndexOutOfBoundsException(start);
  761. if (end > count)
  762. end = count;
  763. if (start > end)
  764. throw new StringIndexOutOfBoundsException("start > end");
  765. int len = str.length();
  766. int newCount = count + len - (end - start);
  767. if (newCount > value.length)
  768. expandCapacity(newCount);
  769. System.arraycopy(value, end, value, start + len, count - end);
  770. str.getChars(value, start);
  771. count = newCount;
  772. return this;
  773. }
  774. /**
  775. * Returns a new <code>String</code> that contains a subsequence of
  776. * characters currently contained in this character sequence. The
  777. * substring begins at the specified index and extends to the end of
  778. * this sequence.
  779. *
  780. * @param start The beginning index, inclusive.
  781. * @return The new string.
  782. * @throws StringIndexOutOfBoundsException if <code>start</code> is
  783. * less than zero, or greater than the length of this object.
  784. */
  785. public String substring(int start) {
  786. return substring(start, count);
  787. }
  788. /**
  789. * Returns a new character sequence that is a subsequence of this sequence.
  790. *
  791. * <p> An invocation of this method of the form
  792. *
  793. * <blockquote><pre>
  794. * sb.subSequence(begin, end)</pre></blockquote>
  795. *
  796. * behaves in exactly the same way as the invocation
  797. *
  798. * <blockquote><pre>
  799. * sb.substring(begin, end)</pre></blockquote>
  800. *
  801. * This method is provided so that this class can
  802. * implement the {@link CharSequence} interface. </p>
  803. *
  804. * @param start the start index, inclusive.
  805. * @param end the end index, exclusive.
  806. * @return the specified subsequence.
  807. *
  808. * @throws IndexOutOfBoundsException
  809. * if <tt>start</tt> or <tt>end</tt> are negative,
  810. * if <tt>end</tt> is greater than <tt>length()</tt>,
  811. * or if <tt>start</tt> is greater than <tt>end</tt>
  812. * @spec JSR-51
  813. */
  814. public CharSequence subSequence(int start, int end) {
  815. return substring(start, end);
  816. }
  817. /**
  818. * Returns a new <code>String</code> that contains a subsequence of
  819. * characters currently contained in this sequence. The
  820. * substring begins at the specified <code>start</code> and
  821. * extends to the character at index <code>end - 1</code>.
  822. *
  823. * @param start The beginning index, inclusive.
  824. * @param end The ending index, exclusive.
  825. * @return The new string.
  826. * @throws StringIndexOutOfBoundsException if <code>start</code>
  827. * or <code>end</code> are negative or greater than
  828. * <code>length()</code>, or <code>start</code> is
  829. * greater than <code>end</code>.
  830. */
  831. public String substring(int start, int end) {
  832. if (start < 0)
  833. throw new StringIndexOutOfBoundsException(start);
  834. if (end > count)
  835. throw new StringIndexOutOfBoundsException(end);
  836. if (start > end)
  837. throw new StringIndexOutOfBoundsException(end - start);
  838. return new String(value, start, end - start);
  839. }
  840. /**
  841. * Inserts the string representation of a subarray of the <code>str</code>
  842. * array argument into this sequence. The subarray begins at the
  843. * specified <code>offset</code> and extends <code>len</code> <code>char</code>s.
  844. * The characters of the subarray are inserted into this sequence at
  845. * the position indicated by <code>index</code>. The length of this
  846. * sequence increases by <code>len</code> <code>char</code>s.
  847. *
  848. * @param index position at which to insert subarray.
  849. * @param str A <code>char</code> array.
  850. * @param offset the index of the first <code>char</code> in subarray to
  851. * be inserted.
  852. * @param len the number of <code>char</code>s in the subarray to
  853. * be inserted.
  854. * @return This object
  855. * @throws StringIndexOutOfBoundsException if <code>index</code>
  856. * is negative or greater than <code>length()</code>, or
  857. * <code>offset</code> or <code>len</code> are negative, or
  858. * <code>(offset+len)</code> is greater than
  859. * <code>str.length</code>.
  860. */
  861. public AbstractStringBuilder insert(int index, char str[], int offset,
  862. int len)
  863. {
  864. if ((index < 0) || (index > length()))
  865. throw new StringIndexOutOfBoundsException(index);
  866. if ((offset < 0) || (len < 0) || (offset > str.length - len))
  867. throw new StringIndexOutOfBoundsException(
  868. "offset " + offset + ", len " + len + ", str.length "
  869. + str.length);
  870. int newCount = count + len;
  871. if (newCount > value.length)
  872. expandCapacity(newCount);
  873. System.arraycopy(value, index, value, index + len, count - index);
  874. System.arraycopy(str, offset, value, index, len);
  875. count = newCount;
  876. return this;
  877. }
  878. /**
  879. * Inserts the string representation of the <code>Object</code>
  880. * argument into this character sequence.
  881. * <p>
  882. * The second argument is converted to a string as if by the method
  883. * <code>String.valueOf</code>, and the characters of that
  884. * string are then inserted into this sequence at the indicated
  885. * offset.
  886. * <p>
  887. * The offset argument must be greater than or equal to
  888. * <code>0</code>, and less than or equal to the length of this
  889. * sequence.
  890. *
  891. * @param offset the offset.
  892. * @param obj an <code>Object</code>.
  893. * @return a reference to this object.
  894. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  895. */
  896. public AbstractStringBuilder insert(int offset, Object obj) {
  897. return insert(offset, String.valueOf(obj));
  898. }
  899. /**
  900. * Inserts the string into this character sequence.
  901. * <p>
  902. * The characters of the <code>String</code> argument are inserted, in
  903. * order, into this sequence at the indicated offset, moving up any
  904. * characters originally above that position and increasing the length
  905. * of this sequence by the length of the argument. If
  906. * <code>str</code> is <code>null</code>, then the four characters
  907. * <code>"null"</code> are inserted into this sequence.
  908. * <p>
  909. * The character at index <i>k</i> in the new character sequence is
  910. * equal to:
  911. * <ul>
  912. * <li>the character at index <i>k</i> in the old character sequence, if
  913. * <i>k</i> is less than <code>offset</code>
  914. * <li>the character at index <i>k</i><code>-offset</code> in the
  915. * argument <code>str</code>, if <i>k</i> is not less than
  916. * <code>offset</code> but is less than <code>offset+str.length()</code>
  917. * <li>the character at index <i>k</i><code>-str.length()</code> in the
  918. * old character sequence, if <i>k</i> is not less than
  919. * <code>offset+str.length()</code>
  920. * </ul><p>
  921. * The offset argument must be greater than or equal to
  922. * <code>0</code>, and less than or equal to the length of this
  923. * sequence.
  924. *
  925. * @param offset the offset.
  926. * @param str a string.
  927. * @return a reference to this object.
  928. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  929. */
  930. public AbstractStringBuilder insert(int offset, String str) {
  931. if ((offset < 0) || (offset > length()))
  932. throw new StringIndexOutOfBoundsException(offset);
  933. if (str == null)
  934. str = "null";
  935. int len = str.length();
  936. int newCount = count + len;
  937. if (newCount > value.length)
  938. expandCapacity(newCount);
  939. System.arraycopy(value, offset, value, offset + len, count - offset);
  940. str.getChars(value, offset);
  941. count = newCount;
  942. return this;
  943. }
  944. /**
  945. * Inserts the string representation of the <code>char</code> array
  946. * argument into this sequence.
  947. * <p>
  948. * The characters of the array argument are inserted into the
  949. * contents of this sequence at the position indicated by
  950. * <code>offset</code>. The length of this sequence increases by
  951. * the length of the argument.
  952. * <p>
  953. * The overall effect is exactly as if the argument were converted to
  954. * a string by the method {@link String#valueOf(char[])} and the
  955. * characters of that string were then
  956. * {@link #insert(int,String) inserted} into this
  957. * character sequence at the position indicated by
  958. * <code>offset</code>.
  959. *
  960. * @param offset the offset.
  961. * @param str a character array.
  962. * @return a reference to this object.
  963. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  964. */
  965. public AbstractStringBuilder insert(int offset, char str[]) {
  966. if ((offset < 0) || (offset > length()))
  967. throw new StringIndexOutOfBoundsException(offset);
  968. int len = str.length;
  969. int newCount = count + len;
  970. if (newCount > value.length)
  971. expandCapacity(newCount);
  972. System.arraycopy(value, offset, value, offset + len, count - offset);
  973. System.arraycopy(str, 0, value, offset, len);
  974. count = newCount;
  975. return this;
  976. }
  977. /**
  978. * Inserts the specified <code>CharSequence</code> into this sequence.
  979. * <p>
  980. * The characters of the <code>CharSequence</code> argument are inserted,
  981. * in order, into this sequence at the indicated offset, moving up
  982. * any characters originally above that position and increasing the length
  983. * of this sequence by the length of the argument s.
  984. * <p>
  985. * The result of this method is exactly the same as if it were an
  986. * invocation of this object's insert(dstOffset, s, 0, s.length()) method.
  987. *
  988. * <p>If <code>s</code> is <code>null</code>, then the four characters
  989. * <code>"null"</code> are inserted into this sequence.
  990. *
  991. * @param dstOffset the offset.
  992. * @param s the sequence to be inserted
  993. * @return a reference to this object.
  994. * @throws IndexOutOfBoundsException if the offset is invalid.
  995. */
  996. public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
  997. if (s == null)
  998. s = "null";
  999. if (s instanceof String)
  1000. return this.insert(dstOffset, (String)s);
  1001. return this.insert(dstOffset, s, 0, s.length());
  1002. }
  1003. /**
  1004. * Inserts a subsequence of the specified <code>CharSequence</code> into
  1005. * this sequence.
  1006. * <p>
  1007. * The subsequence of the argument <code>s</code> specified by
  1008. * <code>start</code> and <code>end</code> are inserted,
  1009. * in order, into this sequence at the specified destination offset, moving
  1010. * up any characters originally above that position. The length of this
  1011. * sequence is increased by <code>end - start</code>.
  1012. * <p>
  1013. * The character at index <i>k</i> in this sequence becomes equal to:
  1014. * <ul>
  1015. * <li>the character at index <i>k</i> in this sequence, if
  1016. * <i>k</i> is less than <code>dstOffset</code>
  1017. * <li>the character at index <i>k</i><code>+start-dstOffset</code> in
  1018. * the argument <code>s</code>, if <i>k</i> is greater than or equal to
  1019. * <code>dstOffset</code> but is less than <code>dstOffset+end-start</code>
  1020. * <li>the character at index <i>k</i><code>-(end-start)</code> in this
  1021. * sequence, if <i>k</i> is greater than or equal to
  1022. * <code>dstOffset+end-start</code>
  1023. * </ul><p>
  1024. * The dstOffset argument must be greater than or equal to
  1025. * <code>0</code>, and less than or equal to the length of this
  1026. * sequence.
  1027. * <p>The start argument must be nonnegative, and not greater than
  1028. * <code>end</code>.
  1029. * <p>The end argument must be greater than or equal to
  1030. * <code>start</code>, and less than or equal to the length of s.
  1031. *
  1032. * <p>If <code>s</code> is <code>null</code>, then this method inserts
  1033. * characters as if the s parameter was a sequence containing the four
  1034. * characters <code>"null"</code>.
  1035. *
  1036. * @param dstOffset the offset in this sequence.
  1037. * @param s the sequence to be inserted.
  1038. * @param start the starting index of the subsequence to be inserted.
  1039. * @param end the end index of the subsequence to be inserted.
  1040. * @return a reference to this object.
  1041. * @throws IndexOutOfBoundsException if <code>dstOffset</code>
  1042. * is negative or greater than <code>this.length()</code>, or
  1043. * <code>start</code> or <code>end</code> are negative, or
  1044. * <code>start</code> is greater than <code>end</code> or
  1045. * <code>end</code> is greater than <code>s.length()</code>
  1046. */
  1047. public AbstractStringBuilder insert(int dstOffset, CharSequence s,
  1048. int start, int end) {
  1049. if (s == null)
  1050. s = "null";
  1051. if ((dstOffset < 0) || (dstOffset > this.length()))
  1052. throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
  1053. if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
  1054. throw new IndexOutOfBoundsException(
  1055. "start " + start + ", end " + end + ", s.length() "
  1056. + s.length());
  1057. int len = end - start;
  1058. if (len == 0)
  1059. return this;
  1060. int newCount = count + len;
  1061. if (newCount > value.length)
  1062. expandCapacity(newCount);
  1063. System.arraycopy(value, dstOffset, value, dstOffset + len,
  1064. count - dstOffset);
  1065. for (int i=start; i<end; i++)
  1066. value[dstOffset++] = s.charAt(i);
  1067. count = newCount;
  1068. return this;
  1069. }
  1070. /**
  1071. * Inserts the string representation of the <code>boolean</code>
  1072. * argument into this sequence.
  1073. * <p>
  1074. * The second argument is converted to a string as if by the method
  1075. * <code>String.valueOf</code>, and the characters of that
  1076. * string are then inserted into this sequence at the indicated
  1077. * offset.
  1078. * <p>
  1079. * The offset argument must be greater than or equal to
  1080. * <code>0</code>, and less than or equal to the length of this
  1081. * sequence.
  1082. *
  1083. * @param offset the offset.
  1084. * @param b a <code>boolean</code>.
  1085. * @return a reference to this object.
  1086. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  1087. */
  1088. public AbstractStringBuilder insert(int offset, boolean b) {
  1089. return insert(offset, String.valueOf(b));
  1090. }
  1091. /**
  1092. * Inserts the string representation of the <code>char</code>
  1093. * argument into this sequence.
  1094. * <p>
  1095. * The second argument is inserted into the contents of this sequence
  1096. * at the position indicated by <code>offset</code>. The length
  1097. * of this sequence increases by one.
  1098. * <p>
  1099. * The overall effect is exactly as if the argument were converted to
  1100. * a string by the method {@link String#valueOf(char)} and the character
  1101. * in that string were then {@link #insert(int, String) inserted} into
  1102. * this character sequence at the position indicated by
  1103. * <code>offset</code>.
  1104. * <p>
  1105. * The offset argument must be greater than or equal to
  1106. * <code>0</code>, and less than or equal to the length of this
  1107. * sequence.
  1108. *
  1109. * @param offset the offset.
  1110. * @param c a <code>char</code>.
  1111. * @return a reference to this object.
  1112. * @throws IndexOutOfBoundsException if the offset is invalid.
  1113. */
  1114. public AbstractStringBuilder insert(int offset, char c) {
  1115. int newCount = count + 1;
  1116. if (newCount > value.length)
  1117. expandCapacity(newCount);
  1118. System.arraycopy(value, offset, value, offset + 1, count - offset);
  1119. value[offset] = c;
  1120. count = newCount;
  1121. return this;
  1122. }
  1123. /**
  1124. * Inserts the string representation of the second <code>int</code>
  1125. * argument into this sequence.
  1126. * <p>
  1127. * The second argument is converted to a string as if by the method
  1128. * <code>String.valueOf</code>, and the characters of that
  1129. * string are then inserted into this sequence at the indicated
  1130. * offset.
  1131. * <p>
  1132. * The offset argument must be greater than or equal to
  1133. * <code>0</code>, and less than or equal to the length of this
  1134. * sequence.
  1135. *
  1136. * @param offset the offset.
  1137. * @param i an <code>int</code>.
  1138. * @return a reference to this object.
  1139. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  1140. */
  1141. public AbstractStringBuilder insert(int offset, int i) {
  1142. return insert(offset, String.valueOf(i));
  1143. }
  1144. /**
  1145. * Inserts the string representation of the <code>long</code>
  1146. * argument into this sequence.
  1147. * <p>
  1148. * The second argument is converted to a string as if by the method
  1149. * <code>String.valueOf</code>, and the characters of that
  1150. * string are then inserted into this sequence at the position
  1151. * indicated by <code>offset</code>.
  1152. * <p>
  1153. * The offset argument must be greater than or equal to
  1154. * <code>0</code>, and less than or equal to the length of this
  1155. * sequence.
  1156. *
  1157. * @param offset the offset.
  1158. * @param l a <code>long</code>.
  1159. * @return a reference to this object.
  1160. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  1161. */
  1162. public AbstractStringBuilder insert(int offset, long l) {
  1163. return insert(offset, String.valueOf(l));
  1164. }
  1165. /**
  1166. * Inserts the string representation of the <code>float</code>
  1167. * argument into this sequence.
  1168. * <p>
  1169. * The second argument is converted to a string as if by the method
  1170. * <code>String.valueOf</code>, and the characters of that
  1171. * string are then inserted into this sequence at the indicated
  1172. * offset.
  1173. * <p>
  1174. * The offset argument must be greater than or equal to
  1175. * <code>0</code>, and less than or equal to the length of this
  1176. * sequence.
  1177. *
  1178. * @param offset the offset.
  1179. * @param f a <code>float</code>.
  1180. * @return a reference to this object.
  1181. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  1182. */
  1183. public AbstractStringBuilder insert(int offset, float f) {
  1184. return insert(offset, String.valueOf(f));
  1185. }
  1186. /**
  1187. * Inserts the string representation of the <code>double</code>
  1188. * argument into this sequence.
  1189. * <p>
  1190. * The second argument is converted to a string as if by the method
  1191. * <code>String.valueOf</code>, and the characters of that
  1192. * string are then inserted into this sequence at the indicated
  1193. * offset.
  1194. * <p>
  1195. * The offset argument must be greater than or equal to
  1196. * <code>0</code>, and less than or equal to the length of this
  1197. * sequence.
  1198. *
  1199. * @param offset the offset.
  1200. * @param d a <code>double</code>.
  1201. * @return a reference to this object.
  1202. * @throws StringIndexOutOfBoundsException if the offset is invalid.
  1203. */
  1204. public AbstractStringBuilder insert(int offset, double d) {
  1205. return insert(offset, String.valueOf(d));
  1206. }
  1207. /**
  1208. * Returns the index within this string of the first occurrence of the
  1209. * specified substring. The integer returned is the smallest value
  1210. * <i>k</i> such that:
  1211. * <blockquote><pre>
  1212. * this.toString().startsWith(str, <i>k</i>)
  1213. * </pre></blockquote>
  1214. * is <code>true</code>.
  1215. *
  1216. * @param str any string.
  1217. * @return if the string argument occurs as a substring within this
  1218. * object, then the index of the first character of the first
  1219. * such substring is returned; if it does not occur as a
  1220. * substring, <code>-1</code> is returned.
  1221. * @throws java.lang.NullPointerException if <code>str</code> is
  1222. * <code>null</code>.
  1223. */
  1224. public int indexOf(String str) {
  1225. return indexOf(str, 0);
  1226. }
  1227. /**
  1228. * Returns the index within this string of the first occurrence of the
  1229. * specified substring, starting at the specified index. The integer
  1230. * returned is the smallest value <tt>k</tt> for which:
  1231. * <blockquote><pre>
  1232. * k >= Math.min(fromIndex, str.length()) &&
  1233. * this.toString().startsWith(str, k)
  1234. * </pre></blockquote>
  1235. * If no such value of <i>k</i> exists, then -1 is returned.
  1236. *
  1237. * @param str the substring for which to search.
  1238. * @param fromIndex the index from which to start the search.
  1239. * @return the index within this string of the first occurrence of the
  1240. * specified substring, starting at the specified index.
  1241. * @throws java.lang.NullPointerException if <code>str</code> is
  1242. * <code>null</code>.
  1243. */
  1244. public int indexOf(String str, int fromIndex) {
  1245. return String.indexOf(value, 0, count,
  1246. str.toCharArray(), 0, str.length(), fromIndex);
  1247. }
  1248. /**
  1249. * Returns the index within this string of the rightmost occurrence
  1250. * of the specified substring. The rightmost empty string "" is
  1251. * considered to occur at the index value <code>this.length()</code>.
  1252. * The returned index is the largest value <i>k</i> such that
  1253. * <blockquote><pre>
  1254. * this.toString().startsWith(str, k)
  1255. * </pre></blockquote>
  1256. * is true.
  1257. *
  1258. * @param str the substring to search for.
  1259. * @return if the string argument occurs one or more times as a substring
  1260. * within this object, then the index of the first character of
  1261. * the last such substring is returned. If it does not occur as
  1262. * a substring, <code>-1</code> is returned.
  1263. * @throws java.lang.NullPointerException if <code>str</code> is
  1264. * <code>null</code>.
  1265. */
  1266. public int lastIndexOf(String str) {
  1267. return lastIndexOf(str, count);
  1268. }
  1269. /**
  1270. * Returns the index within this string of the last occurrence of the
  1271. * specified substring. The integer returned is the largest value <i>k</i>
  1272. * such that:
  1273. * <blockquote><pre>
  1274. * k <= Math.min(fromIndex, str.length()) &&
  1275. * this.toString().startsWith(str, k)
  1276. * </pre></blockquote>
  1277. * If no such value of <i>k</i> exists, then -1 is returned.
  1278. *
  1279. * @param str the substring to search for.
  1280. * @param fromIndex the index to start the search from.
  1281. * @return the index within this sequence of the last occurrence of the
  1282. * specified substring.
  1283. * @throws java.lang.NullPointerException if <code>str</code> is
  1284. * <code>null</code>.
  1285. */
  1286. public int lastIndexOf(String str, int fromIndex) {
  1287. return String.lastIndexOf(value, 0, count,
  1288. str.toCharArray(), 0, str.length(), fromIndex);
  1289. }
  1290. /**
  1291. * Causes this character sequence to be replaced by the reverse of
  1292. * the sequence. If there are any surrogate pairs included in the
  1293. * sequence, these are treated as single characters for the
  1294. * reverse operation. Thus, the order of the high-low surrogates
  1295. * is never reversed.
  1296. *
  1297. * Let <i>n</i> be the character length of this character sequence
  1298. * (not the length in <code>char</code> values) just prior to
  1299. * execution of the <code>reverse</code> method. Then the
  1300. * character at index <i>k</i> in the new character sequence is
  1301. * equal to the character at index <i>n-k-1</i> in the old
  1302. * character sequence.
  1303. *
  1304. * <p>Note that the reverse operation may result in producing
  1305. * surrogate pairs that were unpaired low-surrogates and
  1306. * high-surrogates before the operation. For example, reversing
  1307. * "\uDC00\uD800" produces "\uD800\uDC00" which is
  1308. * a valid surrogate pair.
  1309. *
  1310. * @return a reference to this object.
  1311. */
  1312. public AbstractStringBuilder reverse() {
  1313. boolean hasSurrogate = false;
  1314. int n = count - 1;
  1315. for (int j = (n-1) >> 1; j >= 0; --j) {
  1316. char temp = value[j];
  1317. char temp2 = value[n - j];
  1318. if (!hasSurrogate) {
  1319. hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
  1320. || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
  1321. }
  1322. value[j] = temp2;
  1323. value[n - j] = temp;
  1324. }
  1325. if (hasSurrogate) {
  1326. // Reverse back all valid surrogate pairs
  1327. for (int i = 0; i < count - 1; i++) {
  1328. char c2 = value[i];
  1329. if (Character.isLowSurrogate(c2)) {
  1330. char c1 = value[i + 1];
  1331. if (Character.isHighSurrogate(c1)) {
  1332. value[i++] = c1;
  1333. value[i] = c2;
  1334. }
  1335. }
  1336. }
  1337. }
  1338. return this;
  1339. }
  1340. /**
  1341. * Returns a string representing the data in this sequence.
  1342. * A new <code>String</code> object is allocated and initialized to
  1343. * contain the character sequence currently represented by this
  1344. * object. This <code>String</code> is then returned. Subsequent
  1345. * changes to this sequence do not affect the contents of the
  1346. * <code>String</code>.
  1347. *
  1348. * @return a string representation of this sequence of characters.
  1349. */
  1350. public abstract String toString();
  1351. /**
  1352. * Needed by <tt>String</tt> for the contentEquals method.
  1353. */
  1354. final char[] getValue() {
  1355. return value;
  1356. }
  1357. }