Home | History | Annotate | Download | only in utils
      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 */
     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 */
     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 	 */
     54 	final char[] getValue () {
     55 		return chars;
     56 	}
     57 
     58 	/** Constructs an instance with an initial capacity of {@code 16}.
     59 	 *
     60 	 * @see #capacity() */
     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() */
     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}. */
     82 	public StringBuilder (CharSequence seq) {
     83 		this(seq.toString());
     84 	}
     85 
     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}. */
     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 
    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 
    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 
    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 
    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 
    147 	final void append0 (char ch) {
    148 		if (length == chars.length) {
    149 			enlargeBuffer(length + 1);
    150 		}
    151 		chars[length++] = ch;
    152 	}
    153 
    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 
    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 */
    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()}. */
    193 	public char charAt (int index) {
    194 		if (index < 0 || index >= length) {
    195 			throw new StringIndexOutOfBoundsException(index);
    196 		}
    197 		return chars[index];
    198 	}
    199 
    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 
    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. */
    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}. */
    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 
    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 
    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 
    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 
    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 
    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. */
    324 	public int length () {
    325 		return length;
    326 	}
    327 
    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 
    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 
    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()}. */
    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 */
    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()}. */
    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()}. */
    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
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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) */
    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) */
    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) */
    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) */
    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) */
    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. */
    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. */
    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. */
    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. */
    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) */
    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) */
    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. */
    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[]) */
    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) */
    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. */
    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 
    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}. */
    948 	public StringBuilder append (CharSequence csq, int start, int end) {
    949 		append0(csq, start, end);
    950 		return this;
    951 	}
    952 
    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) */
    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}. */
    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. */
    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) */
   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) */
   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) */
   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) */
   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) */
   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) */
   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) */
   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()}. */
   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[]) */
   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) */
   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() */
   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) */
   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}. */
   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}. */
   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}. */
   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. */
   1203 	public StringBuilder reverse () {
   1204 		reverse0();
   1205 		return this;
   1206 	}
   1207 
   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 
   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