/**
  * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
  *
  * @param offset the place to insert in this buffer
  * @param ch the <code>char</code> to insert
  * @return this <code>StringBuffer</code>
  * @throws StringIndexOutOfBoundsException if offset is out of bounds
  */
 public synchronized StringBuffer insert(int offset, char ch) {
   if (offset < 0 || offset > count) throw new StringIndexOutOfBoundsException(offset);
   ensureCapacity_unsynchronized(count + 1);
   System.arraycopy(value, offset, value, offset + 1, count - offset);
   value[offset] = ch;
   count++;
   return this;
 }
 /**
  * Append part of the <code>char</code> array to this <code>StringBuffer</code>. This is similar
  * (but more efficient) than <code>append(new String(data, offset, count))</code>, except in the
  * case of null.
  *
  * @param data the <code>char[]</code> to append
  * @param offset the start location in <code>str</code>
  * @param count the number of characters to get from <code>str</code>
  * @return this <code>StringBuffer</code>
  * @throws NullPointerException if <code>str</code> is <code>null</code>
  * @throws IndexOutOfBoundsException if offset or count is out of range (while unspecified, this
  *     is a StringIndexOutOfBoundsException)
  */
 public synchronized StringBuffer append(char[] data, int offset, int count) {
   if (offset < 0 || count < 0 || offset > data.length - count)
     throw new StringIndexOutOfBoundsException();
   ensureCapacity_unsynchronized(this.count + count);
   System.arraycopy(data, offset, value, this.count, count);
   this.count += count;
   return this;
 }
 /**
  * Append the <code>String</code> to this <code>StringBuffer</code>. If str is null, the String
  * "null" is appended.
  *
  * @param str the <code>String</code> to append
  * @return this <code>StringBuffer</code>
  */
 public synchronized StringBuffer append(String str) {
   if (str == null) str = "null";
   int len = str.count;
   ensureCapacity_unsynchronized(count + len);
   str.getChars(0, len, value, count);
   count += len;
   return this;
 }
 /**
  * Insert a subarray of the <code>char[]</code> argument into this <code>StringBuffer</code>.
  *
  * @param offset the place to insert in this buffer
  * @param str the <code>char[]</code> to insert
  * @param str_offset the index in <code>str</code> to start inserting from
  * @param len the number of characters to insert
  * @return this <code>StringBuffer</code>
  * @throws NullPointerException if <code>str</code> is <code>null</code>
  * @throws StringIndexOutOfBoundsException if any index is out of bounds
  * @since 1.2
  */
 public synchronized StringBuffer insert(int offset, char[] str, int str_offset, int len) {
   if (offset < 0 || offset > count || len < 0 || str_offset < 0 || str_offset > str.length - len)
     throw new StringIndexOutOfBoundsException();
   ensureCapacity_unsynchronized(count + len);
   System.arraycopy(value, offset, value, offset + len, count - offset);
   System.arraycopy(str, str_offset, value, offset, len);
   count += len;
   return this;
 }
 /**
  * Delete characters from this <code>StringBuffer</code>. <code>delete(10, 12)</code> will delete
  * 10 and 11, but not 12. It is harmless for end to be larger than length().
  *
  * @param start the first character to delete
  * @param end the index after the last character to delete
  * @return this <code>StringBuffer</code>
  * @throws StringIndexOutOfBoundsException if start or end are out of bounds
  * @since 1.2
  */
 public synchronized StringBuffer delete(int start, int end) {
   if (start < 0 || start > count || start > end) throw new StringIndexOutOfBoundsException(start);
   if (end > count) end = count;
   // This will unshare if required.
   ensureCapacity_unsynchronized(count);
   if (count - end != 0) System.arraycopy(value, end, value, start, count - end);
   count -= end - start;
   return this;
 }
 /**
  * Reverse the characters in this StringBuffer. The same sequence of characters exists, but in the
  * reverse index ordering.
  *
  * @return this <code>StringBuffer</code>
  */
 public synchronized StringBuffer reverse() {
   // Call ensureCapacity to enforce copy-on-write.
   ensureCapacity_unsynchronized(count);
   for (int i = count >> 1, j = count - i; --i >= 0; ++j) {
     char c = value[i];
     value[i] = value[j];
     value[j] = c;
   }
   return this;
 }
 /**
  * Insert the <code>String</code> argument into this <code>StringBuffer</code>. If str is null,
  * the String "null" is used instead.
  *
  * @param offset the place to insert in this buffer
  * @param str the <code>String</code> to insert
  * @return this <code>StringBuffer</code>
  * @throws StringIndexOutOfBoundsException if offset is out of bounds
  */
 public synchronized StringBuffer insert(int offset, String str) {
   if (offset < 0 || offset > count) throw new StringIndexOutOfBoundsException(offset);
   if (str == null) str = "null";
   int len = str.count;
   ensureCapacity_unsynchronized(count + len);
   System.arraycopy(value, offset, value, offset + len, count - offset);
   str.getChars(0, len, value, offset);
   count += len;
   return this;
 }
 /**
  * Append the <code>StringBuffer</code> value of the argument to this <code>StringBuffer</code>.
  * This behaves the same as <code>append((Object) stringBuffer)</code>, except it is more
  * efficient.
  *
  * @param stringBuffer the <code>StringBuffer</code> to convert and append
  * @return this <code>StringBuffer</code>
  * @see #append(Object)
  * @since 1.4
  */
 public synchronized StringBuffer append(StringBuffer stringBuffer) {
   if (stringBuffer == null) return append("null");
   synchronized (stringBuffer) {
     int len = stringBuffer.count;
     ensureCapacity_unsynchronized(count + len);
     System.arraycopy(stringBuffer.value, 0, value, count, len);
     count += len;
   }
   return this;
 }
  /**
   * Replace characters between index <code>start</code> (inclusive) and <code>end</code>
   * (exclusive) with <code>str</code>. If <code>end</code> is larger than the size of this
   * StringBuffer, all characters after <code>start</code> are replaced.
   *
   * @param start the beginning index of characters to delete (inclusive)
   * @param end the ending index of characters to delete (exclusive)
   * @param str the new <code>String</code> to insert
   * @return this <code>StringBuffer</code>
   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
   * @throws NullPointerException if str is null
   * @since 1.2
   */
  public synchronized StringBuffer replace(int start, int end, String str) {
    if (start < 0 || start > count || start > end) throw new StringIndexOutOfBoundsException(start);

    int len = str.count;
    // Calculate the difference in 'count' after the replace.
    int delta = len - (end > count ? count : end) + start;
    ensureCapacity_unsynchronized(count + delta);

    if (delta != 0 && end < count) System.arraycopy(value, end, value, end + delta, count - end);

    str.getChars(0, len, value, start);
    count += delta;
    return this;
  }
  /**
   * Set the length of this StringBuffer. If the new length is greater than the current length, all
   * the new characters are set to '\0'. If the new length is less than the current length, the
   * first <code>newLength</code> characters of the old array will be preserved, and the remaining
   * characters are truncated.
   *
   * @param newLength the new length
   * @throws IndexOutOfBoundsException if the new length is negative (while unspecified, this is a
   *     StringIndexOutOfBoundsException)
   * @see #length()
   */
  public synchronized void setLength(int newLength) {
    if (newLength < 0) throw new StringIndexOutOfBoundsException(newLength);

    int valueLength = value.length;

    /* Always call ensureCapacity_unsynchronized in order to preserve
    copy-on-write semantics.  */
    ensureCapacity_unsynchronized(newLength);

    if (newLength < valueLength) {
      /* If the StringBuffer's value just grew, then we know that
      value is newly allocated and the region between count and
      newLength is filled with '\0'.  */
      count = newLength;
    } else {
      /* The StringBuffer's value doesn't need to grow.  However,
      we should clear out any cruft that may exist.  */
      while (count < newLength) value[count++] = '\0';
    }
  }
 /**
  * Append the <code>char</code> to this <code>StringBuffer</code>.
  *
  * @param ch the <code>char</code> to append
  * @return this <code>StringBuffer</code>
  */
 public synchronized StringBuffer append(char ch) {
   ensureCapacity_unsynchronized(count + 1);
   value[count++] = ch;
   return this;
 }
 /**
  * Set the character at the specified index.
  *
  * @param index the index of the character to set starting at 0
  * @param ch the value to set that character to
  * @throws IndexOutOfBoundsException if index is negative or &gt;= length() (while unspecified,
  *     this is a StringIndexOutOfBoundsException)
  */
 public synchronized void setCharAt(int index, char ch) {
   if (index < 0 || index >= count) throw new StringIndexOutOfBoundsException(index);
   // Call ensureCapacity to enforce copy-on-write.
   ensureCapacity_unsynchronized(count);
   value[index] = ch;
 }
 /**
  * Increase the capacity of this <code>StringBuffer</code>. This will ensure that an expensive
  * growing operation will not occur until <code>minimumCapacity</code> is reached. The buffer is
  * grown to the larger of <code>minimumCapacity</code> and <code>capacity() * 2 + 2</code>, if it
  * is not already large enough.
  *
  * @param minimumCapacity the new capacity
  * @see #capacity()
  */
 public synchronized void ensureCapacity(int minimumCapacity) {
   ensureCapacity_unsynchronized(minimumCapacity);
 }