• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package com.badlogic.gdx.utils;
19 
20 import java.util.Arrays;
21 
22 /** A {@link java.lang.StringBuilder} that implements equals and hashcode.
23  * @see CharSequence
24  * @see Appendable
25  * @see java.lang.StringBuilder
26  * @see String */
27 public class StringBuilder implements Appendable, CharSequence {
28 	static final int INITIAL_CAPACITY = 16;
29 
30 	public char[] chars;
31 	public int length;
32 
33 	private static final char[] digits = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
34 
35 	/** @return the number of characters required to represent the specified value with the specified radix */
numChars(int value, int radix)36 	public static int numChars (int value, int radix) {
37 		int result = (value < 0) ? 2 : 1;
38 		while ((value /= radix) != 0)
39 			++result;
40 		return result;
41 	}
42 
43 	/** @return the number of characters required to represent the specified value with the specified radix */
numChars(long value, int radix)44 	public static int numChars (long value, int radix) {
45 		int result = (value < 0) ? 2 : 1;
46 		while ((value /= radix) != 0)
47 			++result;
48 		return result;
49 	}
50 
51 	/*
52 	 * Returns the character array.
53 	 */
getValue()54 	final char[] getValue () {
55 		return chars;
56 	}
57 
58 	/** Constructs an instance with an initial capacity of {@code 16}.
59 	 *
60 	 * @see #capacity() */
StringBuilder()61 	public StringBuilder () {
62 		chars = new char[INITIAL_CAPACITY];
63 	}
64 
65 	/** Constructs an instance with the specified capacity.
66 	 *
67 	 * @param capacity the initial capacity to use.
68 	 * @throws NegativeArraySizeException if the specified {@code capacity} is negative.
69 	 * @see #capacity() */
StringBuilder(int capacity)70 	public StringBuilder (int capacity) {
71 		if (capacity < 0) {
72 			throw new NegativeArraySizeException();
73 		}
74 		chars = new char[capacity];
75 	}
76 
77 	/** Constructs an instance that's initialized with the contents of the specified {@code CharSequence}. The capacity of the new
78 	 * builder will be the length of the {@code CharSequence} plus 16.
79 	 *
80 	 * @param seq the {@code CharSequence} to copy into the builder.
81 	 * @throws NullPointerException if {@code seq} is {@code null}. */
StringBuilder(CharSequence seq)82 	public StringBuilder (CharSequence seq) {
83 		this(seq.toString());
84 	}
85 
StringBuilder(StringBuilder builder)86 	public StringBuilder (StringBuilder builder) {
87 		length = builder.length;
88 		chars = new char[length + INITIAL_CAPACITY];
89 		System.arraycopy(builder.chars, 0, chars, 0, length);
90 	}
91 
92 	/** Constructs an instance that's initialized with the contents of the specified {@code String}. The capacity of the new builder
93 	 * will be the length of the {@code String} plus 16.
94 	 *
95 	 * @param string the {@code String} to copy into the builder.
96 	 * @throws NullPointerException if {@code str} is {@code null}. */
StringBuilder(String string)97 	public StringBuilder (String string) {
98 		length = string.length();
99 		chars = new char[length + INITIAL_CAPACITY];
100 		string.getChars(0, length, chars, 0);
101 	}
102 
enlargeBuffer(int min)103 	private void enlargeBuffer (int min) {
104 		int newSize = (chars.length >> 1) + chars.length + 2;
105 		char[] newData = new char[min > newSize ? min : newSize];
106 		System.arraycopy(chars, 0, newData, 0, length);
107 		chars = newData;
108 	}
109 
appendNull()110 	final void appendNull () {
111 		int newSize = length + 4;
112 		if (newSize > chars.length) {
113 			enlargeBuffer(newSize);
114 		}
115 		chars[length++] = 'n';
116 		chars[length++] = 'u';
117 		chars[length++] = 'l';
118 		chars[length++] = 'l';
119 	}
120 
append0(char[] value)121 	final void append0 (char[] value) {
122 		int newSize = length + value.length;
123 		if (newSize > chars.length) {
124 			enlargeBuffer(newSize);
125 		}
126 		System.arraycopy(value, 0, chars, length, value.length);
127 		length = newSize;
128 	}
129 
append0(char[] value, int offset, int length)130 	final void append0 (char[] value, int offset, int length) {
131 		// Force null check of chars first!
132 		if (offset > value.length || offset < 0) {
133 			throw new ArrayIndexOutOfBoundsException("Offset out of bounds: " + offset);
134 		}
135 		if (length < 0 || value.length - offset < length) {
136 			throw new ArrayIndexOutOfBoundsException("Length out of bounds: " + length);
137 		}
138 
139 		int newSize = this.length + length;
140 		if (newSize > chars.length) {
141 			enlargeBuffer(newSize);
142 		}
143 		System.arraycopy(value, offset, chars, this.length, length);
144 		this.length = newSize;
145 	}
146 
append0(char ch)147 	final void append0 (char ch) {
148 		if (length == chars.length) {
149 			enlargeBuffer(length + 1);
150 		}
151 		chars[length++] = ch;
152 	}
153 
append0(String string)154 	final void append0 (String string) {
155 		if (string == null) {
156 			appendNull();
157 			return;
158 		}
159 		int adding = string.length();
160 		int newSize = length + adding;
161 		if (newSize > chars.length) {
162 			enlargeBuffer(newSize);
163 		}
164 		string.getChars(0, adding, chars, length);
165 		length = newSize;
166 	}
167 
append0(CharSequence s, int start, int end)168 	final void append0 (CharSequence s, int start, int end) {
169 		if (s == null) {
170 			s = "null";
171 		}
172 		if (start < 0 || end < 0 || start > end || end > s.length()) {
173 			throw new IndexOutOfBoundsException();
174 		}
175 
176 		append0(s.subSequence(start, end).toString());
177 	}
178 
179 	/** Returns the number of characters that can be held without growing.
180 	 *
181 	 * @return the capacity
182 	 * @see #ensureCapacity
183 	 * @see #length */
capacity()184 	public int capacity () {
185 		return chars.length;
186 	}
187 
188 	/** Retrieves the character at the {@code index}.
189 	 *
190 	 * @param index the index of the character to retrieve.
191 	 * @return the char value.
192 	 * @throws IndexOutOfBoundsException if {@code index} is negative or greater than or equal to the current {@link #length()}. */
charAt(int index)193 	public char charAt (int index) {
194 		if (index < 0 || index >= length) {
195 			throw new StringIndexOutOfBoundsException(index);
196 		}
197 		return chars[index];
198 	}
199 
delete0(int start, int end)200 	final void delete0 (int start, int end) {
201 		if (start >= 0) {
202 			if (end > length) {
203 				end = length;
204 			}
205 			if (end == start) {
206 				return;
207 			}
208 			if (end > start) {
209 				int count = length - end;
210 				if (count >= 0) System.arraycopy(chars, end, chars, start, count);
211 				length -= end - start;
212 				return;
213 			}
214 		}
215 		throw new StringIndexOutOfBoundsException();
216 	}
217 
deleteCharAt0(int location)218 	final void deleteCharAt0 (int location) {
219 		if (0 > location || location >= length) {
220 			throw new StringIndexOutOfBoundsException(location);
221 		}
222 		int count = length - location - 1;
223 		if (count > 0) {
224 			System.arraycopy(chars, location + 1, chars, location, count);
225 		}
226 		length--;
227 	}
228 
229 	/** Ensures that this object has a minimum capacity available before requiring the internal buffer to be enlarged. The general
230 	 * policy of this method is that if the {@code minimumCapacity} is larger than the current {@link #capacity()}, then the
231 	 * capacity will be increased to the largest value of either the {@code minimumCapacity} or the current capacity multiplied by
232 	 * two plus two. Although this is the general policy, there is no guarantee that the capacity will change.
233 	 *
234 	 * @param min the new minimum capacity to set. */
ensureCapacity(int min)235 	public void ensureCapacity (int min) {
236 		if (min > chars.length) {
237 			int twice = (chars.length << 1) + 2;
238 			enlargeBuffer(twice > min ? twice : min);
239 		}
240 	}
241 
242 	/** Copies the requested sequence of characters to the {@code char[]} passed starting at {@code destStart}.
243 	 *
244 	 * @param start the inclusive start index of the characters to copy.
245 	 * @param end the exclusive end index of the characters to copy.
246 	 * @param dest the {@code char[]} to copy the characters to.
247 	 * @param destStart the inclusive start index of {@code dest} to begin copying to.
248 	 * @throws IndexOutOfBoundsException if the {@code start} is negative, the {@code destStart} is negative, the {@code start} is
249 	 *            greater than {@code end}, the {@code end} is greater than the current {@link #length()} or
250 	 *            {@code destStart + end - begin} is greater than {@code dest.length}. */
getChars(int start, int end, char[] dest, int destStart)251 	public void getChars (int start, int end, char[] dest, int destStart) {
252 		if (start > length || end > length || start > end) {
253 			throw new StringIndexOutOfBoundsException();
254 		}
255 		System.arraycopy(chars, start, dest, destStart, end - start);
256 	}
257 
insert0(int index, char[] value)258 	final void insert0 (int index, char[] value) {
259 		if (0 > index || index > length) {
260 			throw new StringIndexOutOfBoundsException(index);
261 		}
262 		if (value.length != 0) {
263 			move(value.length, index);
264 			System.arraycopy(value, 0, value, index, value.length);
265 			length += value.length;
266 		}
267 	}
268 
insert0(int index, char[] value, int start, int length)269 	final void insert0 (int index, char[] value, int start, int length) {
270 		if (0 <= index && index <= length) {
271 			// start + length could overflow, start/length maybe MaxInt
272 			if (start >= 0 && 0 <= length && length <= value.length - start) {
273 				if (length != 0) {
274 					move(length, index);
275 					System.arraycopy(value, start, chars, index, length);
276 					this.length += length;
277 				}
278 				return;
279 			}
280 			throw new StringIndexOutOfBoundsException("offset " + start + ", length " + length + ", char[].length " + value.length);
281 		}
282 		throw new StringIndexOutOfBoundsException(index);
283 	}
284 
insert0(int index, char ch)285 	final void insert0 (int index, char ch) {
286 		if (0 > index || index > length) {
287 			// RI compatible exception type
288 			throw new ArrayIndexOutOfBoundsException(index);
289 		}
290 		move(1, index);
291 		chars[index] = ch;
292 		length++;
293 	}
294 
insert0(int index, String string)295 	final void insert0 (int index, String string) {
296 		if (0 <= index && index <= length) {
297 			if (string == null) {
298 				string = "null";
299 			}
300 			int min = string.length();
301 			if (min != 0) {
302 				move(min, index);
303 				string.getChars(0, min, chars, index);
304 				length += min;
305 			}
306 		} else {
307 			throw new StringIndexOutOfBoundsException(index);
308 		}
309 	}
310 
insert0(int index, CharSequence s, int start, int end)311 	final void insert0 (int index, CharSequence s, int start, int end) {
312 		if (s == null) {
313 			s = "null";
314 		}
315 		if (index < 0 || index > length || start < 0 || end < 0 || start > end || end > s.length()) {
316 			throw new IndexOutOfBoundsException();
317 		}
318 		insert0(index, s.subSequence(start, end).toString());
319 	}
320 
321 	/** The current length.
322 	 *
323 	 * @return the number of characters contained in this instance. */
length()324 	public int length () {
325 		return length;
326 	}
327 
move(int size, int index)328 	private void move (int size, int index) {
329 		if (chars.length - length >= size) {
330 			System.arraycopy(chars, index, chars, index + size, length - index); // index == count case is no-op
331 			return;
332 		}
333 		int a = length + size, b = (chars.length << 1) + 2;
334 		int newSize = a > b ? a : b;
335 		char[] newData = new char[newSize];
336 		System.arraycopy(chars, 0, newData, 0, index);
337 		// index == count case is no-op
338 		System.arraycopy(chars, index, newData, index + size, length - index);
339 		chars = newData;
340 	}
341 
replace0(int start, int end, String string)342 	final void replace0 (int start, int end, String string) {
343 		if (start >= 0) {
344 			if (end > length) {
345 				end = length;
346 			}
347 			if (end > start) {
348 				int stringLength = string.length();
349 				int diff = end - start - stringLength;
350 				if (diff > 0) { // replacing with fewer characters
351 					// index == count case is no-op
352 					System.arraycopy(chars, end, chars, start + stringLength, length - end);
353 				} else if (diff < 0) {
354 					// replacing with more characters...need some room
355 					move(-diff, end);
356 				}
357 				string.getChars(0, stringLength, chars, start);
358 				length -= diff;
359 				return;
360 			}
361 			if (start == end) {
362 				if (string == null) {
363 					throw new NullPointerException();
364 				}
365 				insert0(start, string);
366 				return;
367 			}
368 		}
369 		throw new StringIndexOutOfBoundsException();
370 	}
371 
reverse0()372 	final void reverse0 () {
373 		if (length < 2) {
374 			return;
375 		}
376 		int end = length - 1;
377 		char frontHigh = chars[0];
378 		char endLow = chars[end];
379 		boolean allowFrontSur = true, allowEndSur = true;
380 		for (int i = 0, mid = length / 2; i < mid; i++, --end) {
381 			char frontLow = chars[i + 1];
382 			char endHigh = chars[end - 1];
383 			boolean surAtFront = allowFrontSur && frontLow >= 0xdc00 && frontLow <= 0xdfff && frontHigh >= 0xd800
384 				&& frontHigh <= 0xdbff;
385 			if (surAtFront && length < 3) {
386 				return;
387 			}
388 			boolean surAtEnd = allowEndSur && endHigh >= 0xd800 && endHigh <= 0xdbff && endLow >= 0xdc00 && endLow <= 0xdfff;
389 			allowFrontSur = allowEndSur = true;
390 			if (surAtFront == surAtEnd) {
391 				if (surAtFront) {
392 					// both surrogates
393 					chars[end] = frontLow;
394 					chars[end - 1] = frontHigh;
395 					chars[i] = endHigh;
396 					chars[i + 1] = endLow;
397 					frontHigh = chars[i + 2];
398 					endLow = chars[end - 2];
399 					i++;
400 					end--;
401 				} else {
402 					// neither surrogates
403 					chars[end] = frontHigh;
404 					chars[i] = endLow;
405 					frontHigh = frontLow;
406 					endLow = endHigh;
407 				}
408 			} else {
409 				if (surAtFront) {
410 					// surrogate only at the front
411 					chars[end] = frontLow;
412 					chars[i] = endLow;
413 					endLow = endHigh;
414 					allowFrontSur = false;
415 				} else {
416 					// surrogate only at the end
417 					chars[end] = frontHigh;
418 					chars[i] = endHigh;
419 					frontHigh = frontLow;
420 					allowEndSur = false;
421 				}
422 			}
423 		}
424 		if ((length & 1) == 1 && (!allowFrontSur || !allowEndSur)) {
425 			chars[end] = allowFrontSur ? endLow : frontHigh;
426 		}
427 	}
428 
429 	/** Sets the character at the {@code index}.
430 	 *
431 	 * @param index the zero-based index of the character to replace.
432 	 * @param ch the character to set.
433 	 * @throws IndexOutOfBoundsException if {@code index} is negative or greater than or equal to the current {@link #length()}. */
setCharAt(int index, char ch)434 	public void setCharAt (int index, char ch) {
435 		if (0 > index || index >= length) {
436 			throw new StringIndexOutOfBoundsException(index);
437 		}
438 		chars[index] = ch;
439 	}
440 
441 	/** Sets the current length to a new value. If the new length is larger than the current length, then the new characters at the
442 	 * end of this object will contain the {@code char} value of {@code \u0000}.
443 	 *
444 	 * @param newLength the new length of this StringBuilder.
445 	 * @exception IndexOutOfBoundsException if {@code length < 0}.
446 	 * @see #length */
setLength(int newLength)447 	public void setLength (int newLength) {
448 		if (newLength < 0) {
449 			throw new StringIndexOutOfBoundsException(newLength);
450 		}
451 		if (newLength > chars.length) {
452 			enlargeBuffer(newLength);
453 		} else {
454 			if (length < newLength) {
455 				Arrays.fill(chars, length, newLength, (char)0);
456 			}
457 		}
458 		length = newLength;
459 	}
460 
461 	/** Returns the String value of the subsequence from the {@code start} index to the current end.
462 	 *
463 	 * @param start the inclusive start index to begin the subsequence.
464 	 * @return a String containing the subsequence.
465 	 * @throws StringIndexOutOfBoundsException if {@code start} is negative or greater than the current {@link #length()}. */
substring(int start)466 	public String substring (int start) {
467 		if (0 <= start && start <= length) {
468 			if (start == length) {
469 				return "";
470 			}
471 
472 			// Remove String sharing for more performance
473 			return new String(chars, start, length - start);
474 		}
475 		throw new StringIndexOutOfBoundsException(start);
476 	}
477 
478 	/** Returns the String value of the subsequence from the {@code start} index to the {@code end} index.
479 	 *
480 	 * @param start the inclusive start index to begin the subsequence.
481 	 * @param end the exclusive end index to end the subsequence.
482 	 * @return a String containing the subsequence.
483 	 * @throws StringIndexOutOfBoundsException if {@code start} is negative, greater than {@code end} or if {@code end} is greater
484 	 *            than the current {@link #length()}. */
substring(int start, int end)485 	public String substring (int start, int end) {
486 		if (0 <= start && start <= end && end <= length) {
487 			if (start == end) {
488 				return "";
489 			}
490 
491 			// Remove String sharing for more performance
492 			return new String(chars, start, end - start);
493 		}
494 		throw new StringIndexOutOfBoundsException();
495 	}
496 
497 	/** Returns the current String representation.
498 	 *
499 	 * @return a String containing the characters in this instance. */
500 	@Override
toString()501 	public String toString () {
502 		if (length == 0) return "";
503 		return new String(chars, 0, length);
504 	}
505 
506 	/** Returns a {@code CharSequence} of the subsequence from the {@code start} index to the {@code end} index.
507 	 *
508 	 * @param start the inclusive start index to begin the subsequence.
509 	 * @param end the exclusive end index to end the subsequence.
510 	 * @return a CharSequence containing the subsequence.
511 	 * @throws IndexOutOfBoundsException if {@code start} is negative, greater than {@code end} or if {@code end} is greater than
512 	 *            the current {@link #length()}.
513 	 * @since 1.4 */
subSequence(int start, int end)514 	public CharSequence subSequence (int start, int end) {
515 		return substring(start, end);
516 	}
517 
518 	/** Searches for the first index of the specified character. The search for the character starts at the beginning and moves
519 	 * towards the end.
520 	 *
521 	 * @param string the string to find.
522 	 * @return the index of the specified character, -1 if the character isn't found.
523 	 * @see #lastIndexOf(String)
524 	 * @since 1.4 */
indexOf(String string)525 	public int indexOf (String string) {
526 		return indexOf(string, 0);
527 	}
528 
529 	/** Searches for the index of the specified character. The search for the character starts at the specified offset and moves
530 	 * towards the end.
531 	 *
532 	 * @param subString the string to find.
533 	 * @param start the starting offset.
534 	 * @return the index of the specified character, -1 if the character isn't found
535 	 * @see #lastIndexOf(String,int)
536 	 * @since 1.4 */
indexOf(String subString, int start)537 	public int indexOf (String subString, int start) {
538 		if (start < 0) {
539 			start = 0;
540 		}
541 		int subCount = subString.length();
542 		if (subCount > 0) {
543 			if (subCount + start > length) {
544 				return -1;
545 			}
546 			char firstChar = subString.charAt(0);
547 			while (true) {
548 				int i = start;
549 				boolean found = false;
550 				for (; i < length; i++) {
551 					if (chars[i] == firstChar) {
552 						found = true;
553 						break;
554 					}
555 				}
556 				if (!found || subCount + i > length) {
557 					return -1; // handles subCount > count || start >= count
558 				}
559 				int o1 = i, o2 = 0;
560 				while (++o2 < subCount && chars[++o1] == subString.charAt(o2)) {
561 					// Intentionally empty
562 				}
563 				if (o2 == subCount) {
564 					return i;
565 				}
566 				start = i + 1;
567 			}
568 		}
569 		return start < length || start == 0 ? start : length;
570 	}
571 
572 	/** Searches for the last index of the specified character. The search for the character starts at the end and moves towards the
573 	 * beginning.
574 	 *
575 	 * @param string the string to find.
576 	 * @return the index of the specified character, -1 if the character isn't found.
577 	 * @throws NullPointerException if {@code string} is {@code null}.
578 	 * @see String#lastIndexOf(java.lang.String)
579 	 * @since 1.4 */
lastIndexOf(String string)580 	public int lastIndexOf (String string) {
581 		return lastIndexOf(string, length);
582 	}
583 
584 	/** Searches for the index of the specified character. The search for the character starts at the specified offset and moves
585 	 * towards the beginning.
586 	 *
587 	 * @param subString the string to find.
588 	 * @param start the starting offset.
589 	 * @return the index of the specified character, -1 if the character isn't found.
590 	 * @throws NullPointerException if {@code subString} is {@code null}.
591 	 * @see String#lastIndexOf(String,int)
592 	 * @since 1.4 */
lastIndexOf(String subString, int start)593 	public int lastIndexOf (String subString, int start) {
594 		int subCount = subString.length();
595 		if (subCount <= length && start >= 0) {
596 			if (subCount > 0) {
597 				if (start > length - subCount) {
598 					start = length - subCount; // count and subCount are both
599 				}
600 				// >= 1
601 				char firstChar = subString.charAt(0);
602 				while (true) {
603 					int i = start;
604 					boolean found = false;
605 					for (; i >= 0; --i) {
606 						if (chars[i] == firstChar) {
607 							found = true;
608 							break;
609 						}
610 					}
611 					if (!found) {
612 						return -1;
613 					}
614 					int o1 = i, o2 = 0;
615 					while (++o2 < subCount && chars[++o1] == subString.charAt(o2)) {
616 						// Intentionally empty
617 					}
618 					if (o2 == subCount) {
619 						return i;
620 					}
621 					start = i - 1;
622 				}
623 			}
624 			return start < length ? start : length;
625 		}
626 		return -1;
627 	}
628 
629 	/** Trims off any extra capacity beyond the current length. Note, this method is NOT guaranteed to change the capacity of this
630 	 * object.
631 	 *
632 	 * @since 1.5 */
trimToSize()633 	public void trimToSize () {
634 		if (length < chars.length) {
635 			char[] newValue = new char[length];
636 			System.arraycopy(chars, 0, newValue, 0, length);
637 			chars = newValue;
638 		}
639 	}
640 
641 	/** Retrieves the Unicode code point value at the {@code index}.
642 	 *
643 	 * @param index the index to the {@code char} code unit.
644 	 * @return the Unicode code point value.
645 	 * @throws IndexOutOfBoundsException if {@code index} is negative or greater than or equal to {@link #length()}.
646 	 * @see Character
647 	 * @see Character#codePointAt(char[], int, int)
648 	 * @since 1.5 */
codePointAt(int index)649 	public int codePointAt (int index) {
650 		if (index < 0 || index >= length) {
651 			throw new StringIndexOutOfBoundsException(index);
652 		}
653 		return Character.codePointAt(chars, index, length);
654 	}
655 
656 	/** Retrieves the Unicode code point value that precedes the {@code index}.
657 	 *
658 	 * @param index the index to the {@code char} code unit within this object.
659 	 * @return the Unicode code point value.
660 	 * @throws IndexOutOfBoundsException if {@code index} is less than 1 or greater than {@link #length()}.
661 	 * @see Character
662 	 * @see Character#codePointBefore(char[], int, int)
663 	 * @since 1.5 */
codePointBefore(int index)664 	public int codePointBefore (int index) {
665 		if (index < 1 || index > length) {
666 			throw new StringIndexOutOfBoundsException(index);
667 		}
668 		return Character.codePointBefore(chars, index);
669 	}
670 
671 	/** Calculates the number of Unicode code points between {@code beginIndex} and {@code endIndex}.
672 	 *
673 	 * @param beginIndex the inclusive beginning index of the subsequence.
674 	 * @param endIndex the exclusive end index of the subsequence.
675 	 * @return the number of Unicode code points in the subsequence.
676 	 * @throws IndexOutOfBoundsException if {@code beginIndex} is negative or greater than {@code endIndex} or {@code endIndex} is
677 	 *            greater than {@link #length()}.
678 	 * @see Character
679 	 * @see Character#codePointCount(char[], int, int)
680 	 * @since 1.5 */
codePointCount(int beginIndex, int endIndex)681 	public int codePointCount (int beginIndex, int endIndex) {
682 		if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) {
683 			throw new StringIndexOutOfBoundsException();
684 		}
685 		return Character.codePointCount(chars, beginIndex, endIndex - beginIndex);
686 	}
687 
688 	/** Returns the index that is offset {@code codePointOffset} code points from {@code index}.
689 	 *
690 	 * @param index the index to calculate the offset from.
691 	 * @param codePointOffset the number of code points to count.
692 	 * @return the index that is {@code codePointOffset} code points away from index.
693 	 * @throws IndexOutOfBoundsException if {@code index} is negative or greater than {@link #length()} or if there aren't enough
694 	 *            code points before or after {@code index} to match {@code codePointOffset}.
695 	 * @see Character
696 	 * @see Character#offsetByCodePoints(char[], int, int, int, int)
697 	 * @since 1.5 */
offsetByCodePoints(int index, int codePointOffset)698 	public int offsetByCodePoints (int index, int codePointOffset) {
699 		return Character.offsetByCodePoints(chars, 0, length, index, codePointOffset);
700 	}
701 
702 	/** Appends the string representation of the specified {@code boolean} value. The {@code boolean} value is converted to a String
703 	 * according to the rule defined by {@link String#valueOf(boolean)}.
704 	 *
705 	 * @param b the {@code boolean} value to append.
706 	 * @return this builder.
707 	 * @see String#valueOf(boolean) */
append(boolean b)708 	public StringBuilder append (boolean b) {
709 		append0(b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
710 		return this;
711 	}
712 
713 	/** Appends the string representation of the specified {@code char} value. The {@code char} value is converted to a string
714 	 * according to the rule defined by {@link String#valueOf(char)}.
715 	 *
716 	 * @param c the {@code char} value to append.
717 	 * @return this builder.
718 	 * @see String#valueOf(char) */
append(char c)719 	public StringBuilder append (char c) {
720 		append0(c);
721 		return this;
722 	}
723 
724 	/** Appends the string representation of the specified {@code int} value. The {@code int} value is converted to a string without
725 	 * memory allocation.
726 	 *
727 	 * @param value the {@code int} value to append.
728 	 * @return this builder.
729 	 * @see String#valueOf(int) */
append(int value)730 	public StringBuilder append (int value) {
731 		return append(value, 0);
732 	}
733 
734 	/** Appends the string representation of the specified {@code int} value. The {@code int} value is converted to a string without
735 	 * memory allocation.
736 	 *
737 	 * @param value the {@code int} value to append.
738 	 * @param minLength the minimum number of characters to add
739 	 * @return this builder.
740 	 * @see String#valueOf(int) */
append(int value, int minLength)741 	public StringBuilder append (int value, int minLength) {
742 		return append(value, minLength, '0');
743 	}
744 
745 	/** Appends the string representation of the specified {@code int} value. The {@code int} value is converted to a string without
746 	 * memory allocation.
747 	 *
748 	 * @param value the {@code int} value to append.
749 	 * @param minLength the minimum number of characters to add
750 	 * @param prefix the character to use as prefix
751 	 * @return this builder.
752 	 * @see String#valueOf(int) */
append(int value, final int minLength, final char prefix)753 	public StringBuilder append (int value, final int minLength, final char prefix) {
754 		if (value == Integer.MIN_VALUE) {
755 			append0("-2147483648");
756 			return this;
757 		}
758 		if (value < 0) {
759 			append0('-');
760 			value = -value;
761 		}
762 		if (minLength > 1) {
763 			for (int j = minLength - numChars(value, 10); j > 0; --j)
764 				append(prefix);
765 		}
766 		if (value >= 10000) {
767 			if (value >= 1000000000) append0(digits[(int)((long)value % 10000000000L / 1000000000L)]);
768 			if (value >= 100000000) append0(digits[value % 1000000000 / 100000000]);
769 			if (value >= 10000000) append0(digits[value % 100000000 / 10000000]);
770 			if (value >= 1000000) append0(digits[value % 10000000 / 1000000]);
771 			if (value >= 100000) append0(digits[value % 1000000 / 100000]);
772 			append0(digits[value % 100000 / 10000]);
773 		}
774 		if (value >= 1000) append0(digits[value % 10000 / 1000]);
775 		if (value >= 100) append0(digits[value % 1000 / 100]);
776 		if (value >= 10) append0(digits[value % 100 / 10]);
777 		append0(digits[value % 10]);
778 		return this;
779 	}
780 
781 	/** Appends the string representation of the specified {@code long} value. The {@code long} value is converted to a string
782 	 * without memory allocation.
783 	 *
784 	 * @param value the {@code long} value.
785 	 * @return this builder. */
append(long value)786 	public StringBuilder append (long value) {
787 		return append(value, 0);
788 	}
789 
790 	/** Appends the string representation of the specified {@code long} value. The {@code long} value is converted to a string
791 	 * without memory allocation.
792 	 *
793 	 * @param value the {@code long} value.
794 	 * @param minLength the minimum number of characters to add
795 	 * @return this builder. */
append(long value, int minLength)796 	public StringBuilder append (long value, int minLength) {
797 		return append(value, minLength, '0');
798 	}
799 
800 	/** Appends the string representation of the specified {@code long} value. The {@code long} value is converted to a string
801 	 * without memory allocation.
802 	 *
803 	 * @param value the {@code long} value.
804 	 * @param minLength the minimum number of characters to add
805 	 * @param prefix the character to use as prefix
806 	 * @return this builder. */
append(long value, int minLength, char prefix)807 	public StringBuilder append (long value, int minLength, char prefix) {
808 		if (value == Long.MIN_VALUE) {
809 			append0("-9223372036854775808");
810 			return this;
811 		}
812 		if (value < 0L) {
813 			append0('-');
814 			value = -value;
815 		}
816 		if (minLength > 1) {
817 			for (int j = minLength - numChars(value, 10); j > 0; --j)
818 				append(prefix);
819 		}
820 		if (value >= 10000) {
821 			if (value >= 1000000000000000000L) append0(digits[(int)(value % 10000000000000000000D / 1000000000000000000L)]);
822 			if (value >= 100000000000000000L) append0(digits[(int)(value % 1000000000000000000L / 100000000000000000L)]);
823 			if (value >= 10000000000000000L) append0(digits[(int)(value % 100000000000000000L / 10000000000000000L)]);
824 			if (value >= 1000000000000000L) append0(digits[(int)(value % 10000000000000000L / 1000000000000000L)]);
825 			if (value >= 100000000000000L) append0(digits[(int)(value % 1000000000000000L / 100000000000000L)]);
826 			if (value >= 10000000000000L) append0(digits[(int)(value % 100000000000000L / 10000000000000L)]);
827 			if (value >= 1000000000000L) append0(digits[(int)(value % 10000000000000L / 1000000000000L)]);
828 			if (value >= 100000000000L) append0(digits[(int)(value % 1000000000000L / 100000000000L)]);
829 			if (value >= 10000000000L) append0(digits[(int)(value % 100000000000L / 10000000000L)]);
830 			if (value >= 1000000000L) append0(digits[(int)(value % 10000000000L / 1000000000L)]);
831 			if (value >= 100000000L) append0(digits[(int)(value % 1000000000L / 100000000L)]);
832 			if (value >= 10000000L) append0(digits[(int)(value % 100000000L / 10000000L)]);
833 			if (value >= 1000000L) append0(digits[(int)(value % 10000000L / 1000000L)]);
834 			if (value >= 100000L) append0(digits[(int)(value % 1000000L / 100000L)]);
835 			append0(digits[(int)(value % 100000L / 10000L)]);
836 		}
837 		if (value >= 1000L) append0(digits[(int)(value % 10000L / 1000L)]);
838 		if (value >= 100L) append0(digits[(int)(value % 1000L / 100L)]);
839 		if (value >= 10L) append0(digits[(int)(value % 100L / 10L)]);
840 		append0(digits[(int)(value % 10L)]);
841 		return this;
842 	}
843 
844 	/** Appends the string representation of the specified {@code float} value. The {@code float} value is converted to a string
845 	 * according to the rule defined by {@link String#valueOf(float)}.
846 	 *
847 	 * @param f the {@code float} value to append.
848 	 * @return this builder. */
append(float f)849 	public StringBuilder append (float f) {
850 		append0(Float.toString(f));
851 		return this;
852 	}
853 
854 	/** Appends the string representation of the specified {@code double} value. The {@code double} value is converted to a string
855 	 * according to the rule defined by {@link String#valueOf(double)}.
856 	 *
857 	 * @param d the {@code double} value to append.
858 	 * @return this builder.
859 	 * @see String#valueOf(double) */
append(double d)860 	public StringBuilder append (double d) {
861 		append0(Double.toString(d));
862 		return this;
863 	}
864 
865 	/** Appends the string representation of the specified {@code Object}. The {@code Object} value is converted to a string
866 	 * according to the rule defined by {@link String#valueOf(Object)}.
867 	 *
868 	 * @param obj the {@code Object} to append.
869 	 * @return this builder.
870 	 * @see String#valueOf(Object) */
append(Object obj)871 	public StringBuilder append (Object obj) {
872 		if (obj == null) {
873 			appendNull();
874 		} else {
875 			append0(obj.toString());
876 		}
877 		return this;
878 	}
879 
880 	/** Appends the contents of the specified string. If the string is {@code null}, then the string {@code "null"} is appended.
881 	 *
882 	 * @param str the string to append.
883 	 * @return this builder. */
append(String str)884 	public StringBuilder append (String str) {
885 		append0(str);
886 		return this;
887 	}
888 
889 	/** Appends the string representation of the specified {@code char[]}. The {@code char[]} is converted to a string according to
890 	 * the rule defined by {@link String#valueOf(char[])}.
891 	 *
892 	 * @param ch the {@code char[]} to append..
893 	 * @return this builder.
894 	 * @see String#valueOf(char[]) */
append(char[] ch)895 	public StringBuilder append (char[] ch) {
896 		append0(ch);
897 		return this;
898 	}
899 
900 	/** Appends the string representation of the specified subset of the {@code char[]}. The {@code char[]} value is converted to a
901 	 * String according to the rule defined by {@link String#valueOf(char[],int,int)}.
902 	 *
903 	 * @param str the {@code char[]} to append.
904 	 * @param offset the inclusive offset index.
905 	 * @param len the number of characters.
906 	 * @return this builder.
907 	 * @throws ArrayIndexOutOfBoundsException if {@code offset} and {@code len} do not specify a valid subsequence.
908 	 * @see String#valueOf(char[],int,int) */
append(char[] str, int offset, int len)909 	public StringBuilder append (char[] str, int offset, int len) {
910 		append0(str, offset, len);
911 		return this;
912 	}
913 
914 	/** Appends the string representation of the specified {@code CharSequence}. If the {@code CharSequence} is {@code null}, then
915 	 * the string {@code "null"} is appended.
916 	 *
917 	 * @param csq the {@code CharSequence} to append.
918 	 * @return this builder. */
append(CharSequence csq)919 	public StringBuilder append (CharSequence csq) {
920 		if (csq == null) {
921 			appendNull();
922 		} else if (csq instanceof StringBuilder) {
923 			StringBuilder builder = (StringBuilder)csq;
924 			append0(builder.chars, 0, builder.length);
925 		} else {
926 			append0(csq.toString());
927 		}
928 		return this;
929 	}
930 
append(StringBuilder builder)931 	public StringBuilder append (StringBuilder builder) {
932 		if (builder == null)
933 			appendNull();
934 		else
935 			append0(builder.chars, 0, builder.length);
936 		return this;
937 	}
938 
939 	/** Appends the string representation of the specified subsequence of the {@code CharSequence}. If the {@code CharSequence} is
940 	 * {@code null}, then the string {@code "null"} is used to extract the subsequence from.
941 	 *
942 	 * @param csq the {@code CharSequence} to append.
943 	 * @param start the beginning index.
944 	 * @param end the ending index.
945 	 * @return this builder.
946 	 * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code start} is greater than {@code end} or
947 	 *            {@code end} is greater than the length of {@code csq}. */
append(CharSequence csq, int start, int end)948 	public StringBuilder append (CharSequence csq, int start, int end) {
949 		append0(csq, start, end);
950 		return this;
951 	}
952 
append(StringBuilder builder, int start, int end)953 	public StringBuilder append (StringBuilder builder, int start, int end) {
954 		if (builder == null)
955 			appendNull();
956 		else
957 			append0(builder.chars, start, end);
958 		return this;
959 	}
960 
961 	/** Appends the encoded Unicode code point. The code point is converted to a {@code char[]} as defined by
962 	 * {@link Character#toChars(int)}.
963 	 *
964 	 * @param codePoint the Unicode code point to encode and append.
965 	 * @return this builder.
966 	 * @see Character#toChars(int) */
appendCodePoint(int codePoint)967 	public StringBuilder appendCodePoint (int codePoint) {
968 		append0(Character.toChars(codePoint));
969 		return this;
970 	}
971 
972 	/** Deletes a sequence of characters specified by {@code start} and {@code end}. Shifts any remaining characters to the left.
973 	 *
974 	 * @param start the inclusive start index.
975 	 * @param end the exclusive end index.
976 	 * @return this builder.
977 	 * @throws StringIndexOutOfBoundsException if {@code start} is less than zero, greater than the current length or greater than
978 	 *            {@code end}. */
delete(int start, int end)979 	public StringBuilder delete (int start, int end) {
980 		delete0(start, end);
981 		return this;
982 	}
983 
984 	/** Deletes the character at the specified index. shifts any remaining characters to the left.
985 	 *
986 	 * @param index the index of the character to delete.
987 	 * @return this builder.
988 	 * @throws StringIndexOutOfBoundsException if {@code index} is less than zero or is greater than or equal to the current
989 	 *            length. */
deleteCharAt(int index)990 	public StringBuilder deleteCharAt (int index) {
991 		deleteCharAt0(index);
992 		return this;
993 	}
994 
995 	/** Inserts the string representation of the specified {@code boolean} value at the specified {@code offset}. The
996 	 * {@code boolean} value is converted to a string according to the rule defined by {@link String#valueOf(boolean)}.
997 	 *
998 	 * @param offset the index to insert at.
999 	 * @param b the {@code boolean} value to insert.
1000 	 * @return this builder.
1001 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length}.
1002 	 * @see String#valueOf(boolean) */
insert(int offset, boolean b)1003 	public StringBuilder insert (int offset, boolean b) {
1004 		insert0(offset, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
1005 		return this;
1006 	}
1007 
1008 	/** Inserts the string representation of the specified {@code char} value at the specified {@code offset}. The {@code char}
1009 	 * value is converted to a string according to the rule defined by {@link String#valueOf(char)}.
1010 	 *
1011 	 * @param offset the index to insert at.
1012 	 * @param c the {@code char} value to insert.
1013 	 * @return this builder.
1014 	 * @throws IndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1015 	 * @see String#valueOf(char) */
insert(int offset, char c)1016 	public StringBuilder insert (int offset, char c) {
1017 		insert0(offset, c);
1018 		return this;
1019 	}
1020 
1021 	/** Inserts the string representation of the specified {@code int} value at the specified {@code offset}. The {@code int} value
1022 	 * is converted to a String according to the rule defined by {@link String#valueOf(int)}.
1023 	 *
1024 	 * @param offset the index to insert at.
1025 	 * @param i the {@code int} value to insert.
1026 	 * @return this builder.
1027 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1028 	 * @see String#valueOf(int) */
insert(int offset, int i)1029 	public StringBuilder insert (int offset, int i) {
1030 		insert0(offset, Integer.toString(i));
1031 		return this;
1032 	}
1033 
1034 	/** Inserts the string representation of the specified {@code long} value at the specified {@code offset}. The {@code long}
1035 	 * value is converted to a String according to the rule defined by {@link String#valueOf(long)}.
1036 	 *
1037 	 * @param offset the index to insert at.
1038 	 * @param l the {@code long} value to insert.
1039 	 * @return this builder.
1040 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {code length()}.
1041 	 * @see String#valueOf(long) */
insert(int offset, long l)1042 	public StringBuilder insert (int offset, long l) {
1043 		insert0(offset, Long.toString(l));
1044 		return this;
1045 	}
1046 
1047 	/** Inserts the string representation of the specified {@code float} value at the specified {@code offset}. The {@code float}
1048 	 * value is converted to a string according to the rule defined by {@link String#valueOf(float)}.
1049 	 *
1050 	 * @param offset the index to insert at.
1051 	 * @param f the {@code float} value to insert.
1052 	 * @return this builder.
1053 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1054 	 * @see String#valueOf(float) */
insert(int offset, float f)1055 	public StringBuilder insert (int offset, float f) {
1056 		insert0(offset, Float.toString(f));
1057 		return this;
1058 	}
1059 
1060 	/** Inserts the string representation of the specified {@code double} value at the specified {@code offset}. The {@code double}
1061 	 * value is converted to a String according to the rule defined by {@link String#valueOf(double)}.
1062 	 *
1063 	 * @param offset the index to insert at.
1064 	 * @param d the {@code double} value to insert.
1065 	 * @return this builder.
1066 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1067 	 * @see String#valueOf(double) */
insert(int offset, double d)1068 	public StringBuilder insert (int offset, double d) {
1069 		insert0(offset, Double.toString(d));
1070 		return this;
1071 	}
1072 
1073 	/** Inserts the string representation of the specified {@code Object} at the specified {@code offset}. The {@code Object} value
1074 	 * is converted to a String according to the rule defined by {@link String#valueOf(Object)}.
1075 	 *
1076 	 * @param offset the index to insert at.
1077 	 * @param obj the {@code Object} to insert.
1078 	 * @return this builder.
1079 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1080 	 * @see String#valueOf(Object) */
insert(int offset, Object obj)1081 	public StringBuilder insert (int offset, Object obj) {
1082 		insert0(offset, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
1083 		return this;
1084 	}
1085 
1086 	/** Inserts the specified string at the specified {@code offset}. If the specified string is null, then the String
1087 	 * {@code "null"} is inserted.
1088 	 *
1089 	 * @param offset the index to insert at.
1090 	 * @param str the {@code String} to insert.
1091 	 * @return this builder.
1092 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}. */
insert(int offset, String str)1093 	public StringBuilder insert (int offset, String str) {
1094 		insert0(offset, str);
1095 		return this;
1096 	}
1097 
1098 	/** Inserts the string representation of the specified {@code char[]} at the specified {@code offset}. The {@code char[]} value
1099 	 * is converted to a String according to the rule defined by {@link String#valueOf(char[])}.
1100 	 *
1101 	 * @param offset the index to insert at.
1102 	 * @param ch the {@code char[]} to insert.
1103 	 * @return this builder.
1104 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1105 	 * @see String#valueOf(char[]) */
insert(int offset, char[] ch)1106 	public StringBuilder insert (int offset, char[] ch) {
1107 		insert0(offset, ch);
1108 		return this;
1109 	}
1110 
1111 	/** Inserts the string representation of the specified subsequence of the {@code char[]} at the specified {@code offset}. The
1112 	 * {@code char[]} value is converted to a String according to the rule defined by {@link String#valueOf(char[],int,int)}.
1113 	 *
1114 	 * @param offset the index to insert at.
1115 	 * @param str the {@code char[]} to insert.
1116 	 * @param strOffset the inclusive index.
1117 	 * @param strLen the number of characters.
1118 	 * @return this builder.
1119 	 * @throws StringIndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}, or
1120 	 *            {@code strOffset} and {@code strLen} do not specify a valid subsequence.
1121 	 * @see String#valueOf(char[],int,int) */
insert(int offset, char[] str, int strOffset, int strLen)1122 	public StringBuilder insert (int offset, char[] str, int strOffset, int strLen) {
1123 		insert0(offset, str, strOffset, strLen);
1124 		return this;
1125 	}
1126 
1127 	/** Inserts the string representation of the specified {@code CharSequence} at the specified {@code offset}. The
1128 	 * {@code CharSequence} is converted to a String as defined by {@link CharSequence#toString()}. If {@code s} is {@code null},
1129 	 * then the String {@code "null"} is inserted.
1130 	 *
1131 	 * @param offset the index to insert at.
1132 	 * @param s the {@code CharSequence} to insert.
1133 	 * @return this builder.
1134 	 * @throws IndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}.
1135 	 * @see CharSequence#toString() */
insert(int offset, CharSequence s)1136 	public StringBuilder insert (int offset, CharSequence s) {
1137 		insert0(offset, s == null ? "null" : s.toString()); //$NON-NLS-1$
1138 		return this;
1139 	}
1140 
1141 	/** Inserts the string representation of the specified subsequence of the {@code CharSequence} at the specified {@code offset}.
1142 	 * The {@code CharSequence} is converted to a String as defined by {@link CharSequence#subSequence(int, int)}. If the
1143 	 * {@code CharSequence} is {@code null}, then the string {@code "null"} is used to determine the subsequence.
1144 	 *
1145 	 * @param offset the index to insert at.
1146 	 * @param s the {@code CharSequence} to insert.
1147 	 * @param start the start of the subsequence of the character sequence.
1148 	 * @param end the end of the subsequence of the character sequence.
1149 	 * @return this builder.
1150 	 * @throws IndexOutOfBoundsException if {@code offset} is negative or greater than the current {@code length()}, or
1151 	 *            {@code start} and {@code end} do not specify a valid subsequence.
1152 	 * @see CharSequence#subSequence(int, int) */
insert(int offset, CharSequence s, int start, int end)1153 	public StringBuilder insert (int offset, CharSequence s, int start, int end) {
1154 		insert0(offset, s, start, end);
1155 		return this;
1156 	}
1157 
1158 	/** Replaces the specified subsequence in this builder with the specified string.
1159 	 *
1160 	 * @param start the inclusive begin index.
1161 	 * @param end the exclusive end index.
1162 	 * @param str the replacement string.
1163 	 * @return this builder.
1164 	 * @throws StringIndexOutOfBoundsException if {@code start} is negative, greater than the current {@code length()} or greater
1165 	 *            than {@code end}.
1166 	 * @throws NullPointerException if {@code str} is {@code null}. */
replace(int start, int end, String str)1167 	public StringBuilder replace (int start, int end, String str) {
1168 		replace0(start, end, str);
1169 		return this;
1170 	}
1171 
1172 	/** Replaces all instances of {@code find} with {@code replace}. */
replace(String find, String replace)1173 	public StringBuilder replace (String find, String replace) {
1174 		int findLength = find.length(), replaceLength = replace.length();
1175 		int index = 0;
1176 		while (true) {
1177 			index = indexOf(find, index);
1178 			if (index == -1) break;
1179 			replace0(index, index + findLength, replace);
1180 			index += replaceLength;
1181 		}
1182 		return this;
1183 	}
1184 
1185 	/** Replaces all instances of {@code find} with {@code replace}. */
replace(char find, String replace)1186 	public StringBuilder replace (char find, String replace) {
1187 		int replaceLength = replace.length();
1188 		int index = 0;
1189 		while (true) {
1190 			while (true) {
1191 				if (index == length) return this;
1192 				if (chars[index] == find) break;
1193 				index++;
1194 			}
1195 			replace0(index, index + 1, replace);
1196 			index += replaceLength;
1197 		}
1198 	}
1199 
1200 	/** Reverses the order of characters in this builder.
1201 	 *
1202 	 * @return this buffer. */
reverse()1203 	public StringBuilder reverse () {
1204 		reverse0();
1205 		return this;
1206 	}
1207 
hashCode()1208 	public int hashCode () {
1209 		final int prime = 31;
1210 		int result = 1;
1211 		result = prime + length;
1212 		result = prime * result + Arrays.hashCode(chars);
1213 		return result;
1214 	}
1215 
equals(Object obj)1216 	public boolean equals (Object obj) {
1217 		if (this == obj) return true;
1218 		if (obj == null) return false;
1219 		if (getClass() != obj.getClass()) return false;
1220 		StringBuilder other = (StringBuilder)obj;
1221 		int length = this.length;
1222 		if (length != other.length) return false;
1223 		char[] chars = this.chars;
1224 		char[] chars2 = other.chars;
1225 		if (chars == chars2) return true;
1226 		if (chars == null || chars2 == null) return false;
1227 		for (int i = 0; i < length; i++)
1228 			if (chars[i] != chars2[i]) return false;
1229 		return true;
1230 	}
1231 }
1232