package java.lang;
/**
* An expandable string of characters. Actually not very expandable!
* 09/25/2001 added number formatting thanks to Martin E. Nielsen.
* You must ensure that the buffer is large enough to take the formatted
* number.
*<P>
* @author <a href="mailto:martin@egholm-nielsen.dk">Martin E. Nielsen</a>
* @author Sven Köhler
*/
public final class StringBuffer
{
private static final int INITIAL_CAPACITY = 10;
private static final int CAPACITY_INCREMENT_NUM = 3; //numerator of the increment factor
private static final int CAPACITY_INCREMENT_DEN = 2; //denominator of the increment factor
private char[] characters;
private int curLen = 0;
public void ensureCapacity(int minCapacity)
{
int cl = characters.length;
if (cl < minCapacity)
{
cl = cl * CAPACITY_INCREMENT_NUM / CAPACITY_INCREMENT_DEN + 1;
while (cl < minCapacity)
cl = cl * CAPACITY_INCREMENT_NUM / CAPACITY_INCREMENT_DEN + 1;
char[] newData = new char[cl];
System.arraycopy(characters, 0, newData, 0, curLen);
characters = newData;
}
}
public StringBuffer ()
{
characters = new char[INITIAL_CAPACITY];
}
public StringBuffer (String aString)
{
characters = aString.toCharArray();
curLen = aString.length();
}
public StringBuffer (int length)
{
if (length < 0)
throw new NegativeArraySizeException("length is negative");
characters = new char[length];
}
public synchronized StringBuffer delete(int start, int end)
{
if (start < 0 || start > curLen)
throw new StringIndexOutOfBoundsException(start);
if (end < start)
throw new StringIndexOutOfBoundsException();
if (end > curLen)
end = curLen;
System.arraycopy(characters, end, characters, start, curLen - end);
curLen -= end - start;
return this;
}
public StringBuffer append (String s)
{
return this.appendInternal(s);
}
public StringBuffer append (Object aObject)
{
return this.appendInternal(String.valueOf(aObject));
}
public StringBuffer append (boolean aBoolean)
{
return this.appendInternal(String.valueOf(aBoolean));
}
public synchronized StringBuffer append (char aChar)
{
int newLen = curLen +1;
ensureCapacity(newLen);
characters[curLen] = aChar;
curLen = newLen;
return this;
}
public StringBuffer append(char[] c)
{
return this.append(c, 0, c.length);
}
public synchronized StringBuffer append(char[] c, int off, int len)
{
int newLen = curLen + len;
ensureCapacity(newLen);
for (int i=0; i<len; i++)
characters[curLen + i] = c[off + i];
curLen = newLen;
return this;
}
public StringBuffer append(CharSequence cs)
{
return this.append(cs, 0, cs.length());
}
public synchronized StringBuffer append(CharSequence cs, int start, int end)
{
int len = end - start;
int newLen = curLen + len;
ensureCapacity(newLen);
for (int i=0; i<len; i++)
characters[curLen + i] = cs.charAt(start + i);
curLen = newLen;
return this;
}
public synchronized StringBuffer append (int i)
{
int intLen = StringUtils.exactStringLength(i, 10);
int newLen = curLen + intLen;
ensureCapacity(newLen);
StringUtils.getIntChars(characters, newLen, i, 10);
curLen = newLen;
return this;
}
public synchronized StringBuffer append (long aLong)
{
int intLen = StringUtils.exactStringLength(aLong, 10);
int newLen = curLen + intLen;
ensureCapacity(newLen);
StringUtils.getLongChars(characters, newLen, aLong, 10);
curLen = newLen;
return this;
}
public synchronized StringBuffer append (float aFloat)
{
ensureCapacity(curLen + StringUtils.MAX_FLOAT_CHARS);
curLen = StringUtils.getFloatChars(aFloat, characters, curLen);
return this;
}
public synchronized StringBuffer append (double aDouble)
{
ensureCapacity(curLen + StringUtils.MAX_DOUBLE_CHARS);
curLen = StringUtils.getDoubleChars(aDouble, characters, curLen);
return this;
}
/**
* Appends a string with no null checking
*/
private StringBuffer appendInternal(String s) {
if (s == null)
s = "null";
// Reminder: compact code more important than speed
char[] sc = s.characters;
int sl = sc.length;
int newlen = curLen + sl;
this.ensureCapacity(newlen);
System.arraycopy (sc, 0, characters, curLen, sl);
curLen = newlen;
return this;
}
public int indexOf(String str) {
return indexOf(str, 0);
}
public synchronized int indexOf(String str, int fromIndex) {
return String.indexOf(characters, 0, curLen,
str.characters, 0, str.characters.length, fromIndex);
}
public synchronized int lastIndexOf(String str) {
// Note, synchronization achieved via other invocations
return lastIndexOf(str, curLen);
}
public synchronized int lastIndexOf(String str, int fromIndex) {
return String.lastIndexOf(characters, 0, curLen,
str.characters, 0, str.characters.length, fromIndex);
}
@Override
public synchronized String toString()
{
return new String (characters, 0, curLen);
}
public synchronized char charAt(int i)
{
if (i < 0 || i >= curLen)
throw new StringIndexOutOfBoundsException(i);
return characters[i];
}
public synchronized void setCharAt(int i, char ch)
{
if (i < 0 || i >= curLen)
throw new StringIndexOutOfBoundsException(i);
characters[i] = ch;
}
public synchronized int length()
{
return curLen;
}
/**
* Retrieves the contents of the StringBuffer in the form of an array of characters.
*/
public synchronized char[] getChars()
{
char[] r = new char[curLen];
System.arraycopy(characters, 0, r, 0, curLen);
return r;
}
public synchronized String substring(int start) {
return substring(start, curLen);
}
public String substring(int start, int end) {
if (start < 0 || start > curLen)
throw new StringIndexOutOfBoundsException(start);
if (end > curLen)
throw new StringIndexOutOfBoundsException(end);
if (end < start)
throw new StringIndexOutOfBoundsException(end - start);
int len = end - start;
return new String(characters, start, len);
}
}