package org.emdev.common.lang; import java.util.Arrays; /** * The Class StrBuilder. * * Copy of some methods from java.lang.StringBuilder with access to internal buffer. */ public class StrBuilder { static final int INITIAL_CAPACITY = 16; private char[] value; private int count; private boolean shared; public StrBuilder() { value = new char[INITIAL_CAPACITY]; } public StrBuilder(int capacity) { if (capacity < 0) { throw new NegativeArraySizeException(); } value = new char[capacity]; } private void enlargeBuffer(int min) { int newCount = ((value.length >> 1) + value.length) + 2; char[] newData = new char[min > newCount ? min : newCount]; System.arraycopy(value, 0, newData, 0, count); value = newData; shared = false; } /** * Sets the current length to a new value. If the new length is larger than * the current length, then the new characters at the end of this object * will contain the {@code char} value of {@code \u0000}. * * @param length * the new length of this StringBuffer. * @exception IndexOutOfBoundsException * if {@code length < 0}. * @see #length */ public void setLength(int length) { if (length < 0) { throw new StringIndexOutOfBoundsException("length < 0: " + length); } if (length > value.length) { enlargeBuffer(length); } else { if (shared) { char[] newData = new char[value.length]; System.arraycopy(value, 0, newData, 0, count); value = newData; shared = false; } else { if (count < length) { Arrays.fill(value, count, length, (char) 0); } } } count = length; } /** * The current length. * * @return the number of characters contained in this instance. */ public int length() { return count; } /* * Returns the character array. */ public final char[] getValue() { return value; } /* * Returns the underlying buffer and sets the shared flag. */ public final char[] shareValue() { shared = true; return value; } /** * Appends the string representation of the specified subset of the {@code * char[]}. The {@code char[]} value is converted to a String according to * the rule defined by {@link String#valueOf(char[],int,int)}. * * @param str * the {@code char[]} to append. * @param offset * the inclusive offset index. * @param len * the number of characters. * @return this builder. * @throws ArrayIndexOutOfBoundsException * if {@code offset} and {@code len} do not specify a valid * subsequence. * @see String#valueOf(char[],int,int) */ public StrBuilder append(char[] str, int offset, int len) { append0(str, offset, len); return this; } /** * Appends the string representation of the specified {@code char} value. * The {@code char} value is converted to a string according to the rule * defined by {@link String#valueOf(char)}. * * @param c * the {@code char} value to append. * @return this builder. * @see String#valueOf(char) */ public StrBuilder append(char c) { append0(c); return this; } final void append0(char[] chars, int offset, int length) { if ((offset | length) < 0 || offset > chars.length || chars.length - offset < length) { throw new ArrayIndexOutOfBoundsException(); } int newCount = count + length; if (newCount > value.length) { enlargeBuffer(newCount); } System.arraycopy(chars, offset, value, count, length); count = newCount; } final void append0(char ch) { if (count == value.length) { enlargeBuffer(count + 1); } value[count++] = ch; } @Override public String toString() { return new String(value, 0, count); } }