Class similar to StringBuffer, except that it can be used to construct multiple Strings
// Revised from ctc wstx
/**
* Class similar to {@link StringBuffer}, except that it can be used to
* construct multiple Strings, that will share same underlying character
* buffer. This is generally useful for closely related value Strings,
* such as attribute values of a single XML start element.
*/
public final class TextBuilder
{
private final static int MIN_LEN = 60;
private final static int MAX_LEN = 120;
private char[] mBuffer;
private int[] mBufferOffsets;
private int mBufferLen;
private String mResultString;
/**
* Number of complete entries in buffer, not including one currently
* being worked on.
*/
private int mEntryCount;
/*
///////////////////////////////////////////////
// Life-cycle:
///////////////////////////////////////////////
*/
public TextBuilder(int initialSize)
{
mBufferOffsets = new int[initialSize];
int charSize = (initialSize << 4); // multiply by 16 (-> def. 192 chars)
if (charSize < MIN_LEN) {
charSize = MIN_LEN;
} else if (charSize > MAX_LEN) {
charSize = MAX_LEN;
}
mBuffer = new char[charSize];
}
/**
* Method called before starting to (re)use the buffer, will discard
* any existing content, and start collecting new set of values.
*/
public void reset() {
mBufferLen = 0;
mEntryCount = 0;
mResultString = null;
}
/*
///////////////////////////////////////////////
// Accesors:
///////////////////////////////////////////////
*/
public boolean isEmpty() {
return mEntryCount == 0;
}
public int size() {
return mEntryCount;
}
public String getEntry(int index)
{
int len = mEntryCount;
/* Note: no checks, caller is to ensure index is ok. Acceptable
* since it's not externally exposed (only used by woodstox core)
*/
/*
if (index < 0 || index >= len) {
throw new IllegalArgumentException("Invalid index, "+index+"; current size: "+len+".");
}
*/
if (mResultString == null) {
mResultString = new String(mBuffer, 0, mBufferLen);
}
// Degenerate case; only one substring:
if (index == 0 && len == 1) {
return mResultString;
}
if (index == (len-1)) {
return mResultString.substring(mBufferOffsets[index]);
}
return mResultString.substring(mBufferOffsets[index],
mBufferOffsets[index+1]);
}
public int getOffset(int index) {
if (index >= mEntryCount) { // last entry
return mBufferLen;
}
return mBufferOffsets[index];
}
/**
* Method that gives access to underlying character buffer
*/
public char[] getCharBuffer() {
return mBuffer;
}
public int getCharSize() {
return mBufferLen;
}
/*
///////////////////////////////////////////////
// Mutators:
///////////////////////////////////////////////
*/
public void startNewEntry() {
// Not enough room for a new entry?
if (mEntryCount >= mBufferOffsets.length) {
int[] old = mBufferOffsets;
mBufferOffsets = new int[old.length << 1];
System.arraycopy(old, 0, mBufferOffsets, 0, old.length);
}
mBufferOffsets[mEntryCount] = mBufferLen;
++mEntryCount;
}
public void append(char c) {
if (mBuffer.length == mBufferLen) {
resize(1);
}
mBuffer[mBufferLen++] = c;
}
public void append(char[] src, int start, int len) {
if (len > (mBuffer.length - mBufferLen)) {
resize(len);
}
System.arraycopy(src, start, mBuffer, mBufferLen, len);
mBufferLen += len;
}
public void setBufferSize(int newSize) {
mBufferLen = newSize;
}
public char[] bufferFull(int needSpaceFor) {
mBufferLen = mBuffer.length;
resize(1);
return mBuffer;
}
/*
///////////////////////////////////////////////
// Debugging:
///////////////////////////////////////////////
*/
public String toString() {
return new String(mBuffer, 0, mBufferLen);
}
/*
///////////////////////////////////////////////
// Internal methods:
///////////////////////////////////////////////
*/
private void resize(int needSpaceFor) {
char[] old = mBuffer;
int oldLen = old.length;
int addition = oldLen >> 1; // Grow by 50%
needSpaceFor -= (oldLen - mBufferLen);
if (addition < needSpaceFor) {
addition = needSpaceFor;
}
mBuffer = new char[oldLen+addition];
System.arraycopy(old, 0, mBuffer, 0, mBufferLen);
}
}
Related examples in the same category