/*
* © Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.commons.util;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* Fast String buffer.</P>
* This class has almost all the methods found in the standard <CODE>StringBuffer</CODE>
* but is faster for many reasons :<BR>
* <UL>
* <LI>It has no synchronized methods => don't access a buffer from differents
* threads!
* <LI>It cannot be shared (shared attribute does not exist)
* <LI>The memory allocation scheme is different
* </UL>
* It also has bonus methods which are very helpful.
* @ibm-api
*/
public class FastStringBuffer {
/** The value is used for character storage. */
private char[] value;
/** The count is the number of characters in the buffer. */
private int count;
/** The delta for incrementing the size of the buffer */
private static final int DELTA = 128;
/** Minimum printable ASCII character */
private static final int ASCII_MIN = 32;
/** Maximum printable ASCII character */
private static final int ASCII_MAX = 126;
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of DELTA characters.
*/
public FastStringBuffer() {
this(DELTA);
}
/**
* Constructs a string buffer with no characters in it and an
* initial capacity specified by the <code>length</code> argument.
* @param length the initial capacity.
*/
public FastStringBuffer(int length) {
value = new char[length];
count = 0;
}
/**
* Constructs a string buffer from an array of characters.
* The array is not initially copied into the string buffer, but rather referenced.
* @param buffer of characters to be managed by this class
* @param count, the number (in char) of useful information contained in the array.
* @exception IllegalArgumentException , if buffer parameter is null.
*/
public FastStringBuffer(char[] buffer, int count) {
if (buffer==null){
throw new java.lang.IllegalArgumentException("Can't pass null value"); //$NLS-FastStringBuffer.FastStringBuffer.NullValue.Exception-1$
}
value=buffer;
this.count=count<0?0:count;
}
/**
* Constructs a string buffer so that it represents the same
* sequence of characters as the string argument. The initial
* capacity of the string buffer is <code>DELTA</code> plus the length
* of the string argument.
* @param str the initial contents of the buffer.
*/
public FastStringBuffer(String str) {
this(str.length() + DELTA);
append(str);
}
/**
* Returns the length (character count) of this string buffer.
* @return the number of characters in this string buffer.
*/
public final int length() {
return count;
}
/**
* Returns the current capacity of the String buffer. The capacity
* is the amount of storage available for newly inserted
* characters; beyond which an allocation will occur.
* @return the current capacity of this string buffer.
*/
public final int capacity() {
return value.length;
}
/**
* Expand the capacity of the StringBuffer.
* @param the minimum capacity needed
*/
private final void expandCapacity(int minimumCapacity) {
int newCapacity = Math.max( (value.length + 1) * 2, minimumCapacity );
if( newCapacity-value.length<DELTA ) {
newCapacity = value.length+DELTA;
}
char newValue[] = new char[newCapacity];
System.arraycopy(value, 0, newValue, 0, count);
value = newValue;
}
/**
* Returns the character at a specific index in this string buffer.
* <p>
* The first character of a string buffer is at index
* <code>0</code>, the next at index <code>1</code>, and so on, for
* array indexing.
* <p>
* The index argument must be greater than or equal to
* <code>0</code>, and less than the length of this string buffer.
*
* @param index the index of the desired character.
* @return the character at the specified index of this string buffer.
* @see com.ibm.jscript.util.FastStringBuffer#length()
* @exception StringIndexOutOfBoundsException if the index is invalid.
* @see com.ibm.jscript.util.StringBuffer#length() */
public final char charAt(int index) {
/*#IF DEBUG*/
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
/*#ENDIF*/
return value[index];
}
/**
* Characters are copied from this string buffer into the
* destination character array <code>dst</code>. The first character to
* be copied is at index <code>srcBegin</code>; the last character to
* be copied is at index <code>srcEnd-1.</code> The total number of
* characters to be copied is <code>srcEnd-srcBegin</code>. The
* characters are copied into the subarray of <code>dst</code> starting
* at index <code>dstBegin</code> and ending at index:
* <p><blockquote><pre>
* dstbegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
* @param srcBegin start copying at this offset in the string buffer.
* @param srcEnd stop copying at this offset in the string buffer.
* @param dst the array to copy the data into.
* @param dstBegin offset into <code>dst</code>.
* @exception StringIndexOutOfBoundsException if there is an invalid
* index into the buffer.
*/
public final void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
/*#IF DEBUG*/
if ((srcBegin < 0) || (srcBegin >= count)) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if ((srcEnd < 0) || (srcEnd > count)) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
/*#ENDIF*/
if (srcBegin < srcEnd) {
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
}
/**
* The character at the specified index of tiis string buffer is set
* to <code>ch</code>.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than the length of this string buffer.
*
* @param index the index of the character to modify.
* @param ch the new character.
* @exception StringIndexOutOfBoundsException if the index is invalid.
* @see com.ibm.jscript.util.StringBuffer#length()
*/
public final void setCharAt(int index, char ch) {
/*#IF DEBUG*/
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
/*#ENDIF*/
value[index] = ch;
}
/**
* Appends the string representation of the <code>Object</code>
* argument to this string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param obj an <code>Object</code>.
* @return this string buffer.
* @see com.ibm.jscript.util.String#valueOf(java.lang.Object)
* @see com.ibm.jscript.util.StringBuffer#append(java.lang.String)
*/
public final FastStringBuffer append(Object obj) {
return append(String.valueOf(obj));
}
/**
* Appends the string to this string buffer.
* <p>
* The characters of the <code>String</code> argument are appended, in
* order, to the contents of this string buffer, increasing the
* length of this string buffer by the length of the argument.
*
* @param str a string.
* @return this string buffer.
*/
public final FastStringBuffer append(String str) {
if (str == null) {
str = String.valueOf(str);
}
int len = str.length();
int newcount = count + len;
if (newcount > value.length) {
expandCapacity(newcount);
}
str.getChars(0, len, value, count);
count = newcount;
return this;
}
/**
* Appends the string representation of the <code>char</code> array
* argument to this string buffer.
* <p>
* The characters of the array argument are appended, in order, to
* the contents of this string buffer. The length of this string
* buffer increases by the length of the argument.
*
* @param str the characters to be appended.
* @return this string buffer.
*/
public final FastStringBuffer append(char str[]) {
int len = str.length;
int newcount = count + len;
if (newcount > value.length) {
expandCapacity(newcount);
}
System.arraycopy(str, 0, value, count, len);
count = newcount;
return this;
}
/**
* Appends the string representation of a subarray of the
* <code>char</code> array argument to this string buffer.
* <p>
* Characters of the character array <code>str</code>, starting at
* index <code>offset</code>, are appended, in order, to the contents
* of this string buffer. The length of this string buffer increases
* by the value of <code>len</code>.
*
* @param str the characters to be appended.
* @param offset the index of the first character to append.
* @param len the number of characters to append.
* @return this string buffer.
*/
public final FastStringBuffer append(char str[], int offset, int len) {
int newcount = count + len;
if (newcount > value.length) {
expandCapacity(newcount);
}
System.arraycopy(str, offset, value, count, len);
count = newcount;
return this;
}
/**
* Appends the string representation of the <code>boolean</code>
* argument to the string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param b a <code>boolean</code>.
* @return this string buffer.
* @see com.ibm.jscript.util.String#valueOf(boolean)
* @see com.ibm.jscript.util.StringBuffer#append(java.lang.String)
*/
public final FastStringBuffer append(boolean b) {
return append(String.valueOf(b));
}
/**
* Appends the string representation of the <code>char</code>
* argument to this string buffer.
* <p>
* The argument is appended to the contents of this string buffer.
* The length of this string buffer increases by <code>1</code>.
*
* @param ch a <code>char</code>.
* @return this string buffer.
*/
public final FastStringBuffer append(char c) {
int newcount = count + 1;
if (newcount > value.length) {
expandCapacity(newcount);
}
value[count++] = c;
return this;
}
/**
* Appends the string representation of the <code>int</code>
* argument to this string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param i an <code>int</code>.
* @return this string buffer.
* @see com.ibm.jscript.util.String#valueOf(int)
* @see com.ibm.jscript.util.StringBuffer#append(java.lang.String)
*/
public final FastStringBuffer append(int i) {
return append(String.valueOf(i));
}
/**
* Appends the string representation of the <code>long</code>
* argument to this string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param l a <code>long</code>.
* @return this string buffer.
*/
public final FastStringBuffer append(long l) {
return append(String.valueOf(l));
}
/**
* Appends the string representation of the <code>float</code>
* argument to this string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param f a <code>float</code>.
* @return this string buffer.
*/
public final FastStringBuffer append(float f) {
return append(String.valueOf(f));
}
/**
* Appends the string representation of the <code>double</code>
* argument to this string buffer.
* <p>
* The argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then appended to this string buffer.
*
* @param d a <code>double</code>.
* @return this string buffer.
*/
public final FastStringBuffer append(double d) {
return append(String.valueOf(d));
}
/**
* Inserts the string representation of the <code>Object</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b an <code>Object</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, Object obj) {
return insert(offset, String.valueOf(obj));
}
/**
* Inserts the string into this string buffer.
* <p>
* The characters of the <code>String</code> argument are inserted, in
* order, into this string buffer at the indicated offset. The length
* of this string buffer is increased by the length of the argument.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param str a string.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, String str) {
/*#IF DEBUG*/
if ((offset < 0) || (offset > count)) {
throw new StringIndexOutOfBoundsException();
}
/*#ENDIF*/
int len = str.length();
int newcount = count + len;
if (newcount > value.length) {
expandCapacity(newcount);
}
System.arraycopy(value, offset, value, offset + len, count - offset);
str.getChars(0, len, value, offset);
count = newcount;
return this;
}
/**
* Inserts the string representation of the <code>char</code> array
* argument into this string buffer.
* <p>
* The characters of the array argument are inserted into the
* contents of this string buffer at the position indicated by
* <code>offset</code>. The length of this string buffer increases by
* the length of the argument.
*
* @param offset the offset.
* @param ch a character array.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, char str[]) {
/*#IF DEBUG*/
if ((offset < 0) || (offset > count)) {
throw new StringIndexOutOfBoundsException();
}
/*#ENDIF*/
int len = str.length;
int newcount = count + len;
if (newcount > value.length) {
expandCapacity(newcount);
}
System.arraycopy(value, offset, value, offset + len, count - offset);
System.arraycopy(str, 0, value, offset, len);
count = newcount;
return this;
}
/**
* Inserts the string representation of the <code>boolean</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b a <code>boolean</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, boolean b) {
return insert(offset, String.valueOf(b));
}
/**
* Inserts the string representation of the <code>char</code>
* argument into this string buffer.
* <p>
* The second argument is inserted into the contents of this string
* buffer at the position indicated by <code>offset</code>. The length
* of this string buffer increases by one.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param ch a <code>char</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, char c) {
int newcount = count + 1;
if (newcount > value.length) {
expandCapacity(newcount);
}
System.arraycopy(value, offset, value, offset + 1, count - offset);
value[offset] = c;
count = newcount;
return this;
}
/**
* Inserts the string representation of the second <code>int</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b an <code>int</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, int i) {
return insert(offset, String.valueOf(i));
}
/**
* Inserts the string representation of the <code>long</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b a <code>long</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, long l) {
return insert(offset, String.valueOf(l));
}
/**
* Inserts the string representation of the <code>float</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b a <code>float</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, float f) {
return insert(offset, String.valueOf(f));
}
/**
* Inserts the string representation of the <code>double</code>
* argument into this string buffer.
* <p>
* The second argument is converted to a string as if by the method
* <code>String.valueOf</code>, and the characters of that
* string are then inserted into this string buffer at the indicated
* offset.
* <p>
* The offset argument must be greater than or equal to
* <code>0</code>, and less than or equal to the length of this
* string buffer.
*
* @param offset the offset.
* @param b a <code>double</code>.
* @return this string buffer.
* @exception StringIndexOutOfBoundsException if the offset is invalid.
*/
public final FastStringBuffer insert(int offset, double d) {
return insert(offset, String.valueOf(d));
}
/**
* The character sequence contained in this string buffer is
* replaced by the reverse of the sequence.
*
* @return this string buffer.
*/
public final FastStringBuffer reverse() {
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; --j) {
char temp = value[j];
value[j] = value[n - j];
value[n - j] = temp;
}
return this;
}
/**
* Converts to a string representing the data in this string buffer.
* A new <code>String</code> object is allocated and initialized to
* contain the character sequence currently represented by this
* string buffer. This <code>String</code> is then returned. Subsequent
* changes to the string buffer do not affect the contents of the
* <code>String</code>.
*
* @return a string representation of the string buffer.
*/
public String toString() {
return new String(this.value, 0, count);
}
///////////////////////////////////////////////////////////////////////////
//
// BONUS CONSTRUCTORS & METHODS
//
// These methods are specific to <CODE>TStringBuffer</CODE> and cannot be
// found in the standard <CODE>StringBuffer</CODE>.
//
///////////////////////////////////////////////////////////////////////////
/**
* Constructs a string buffer so that it represents the same
* sequence of characters as the string argument. The initial
* capacity of the string buffer is <code>DELTA</code> plus the length
* of the string argument.
* @param str the initial contents of the buffer.
* @param srcBegin start copying at this offset in the string.
* @param srcEnd stop copying at this offset in the string.
*/
public FastStringBuffer(String str, int srcBegin, int srcEnd) {
this(DELTA + srcEnd-srcBegin );
append(str,srcBegin,srcEnd);
}
/**
* Clear the content of the buffer.
* Simply the count is reseted. No allocation is done.
*/
public final void clear() {
count = 0;
}
/**
* Compare the buffer to a string.
*/
public boolean equals( String str ) {
if( str!=null && str.length()==count ) {
for( int i=0; i<count; i++ ) {
if( value[i]!=str.charAt(i) ) {
return false;
}
}
return true;
}
return false;
}
/**
*
*/
public final boolean startsWith( char c ) {
return count>0 && value[0]==c;
}
/**
* Append a repeated character string.
* @param toRepeat the string to repeat
* @param count the number of repetition
*/
public final void repeat( String toRepeat, int count ) {
for( int i=0; i<count; i++ ) {
append(toRepeat);
}
}
/**
* Append a repeated character.
* @param toRepeat the character to repeat
* @param count the number of repetition
*/
public final void repeat( char toRepeat, int count ) {
for( int i=0; i<count; i++ ) {
append(toRepeat);
}
}
/**
*
*/
public final FastStringBuffer append( FastStringBuffer b, int srcBegin, int srcEnd ) {
if (b == null) {
return this;
}
if( srcBegin>=srcEnd ) {
return this;
}
// Ensure that the buffer is zied enough
int newcount = count + srcEnd-srcBegin;
if (newcount > value.length) {
expandCapacity(newcount);
}
// Copy the desired characters
b.getChars(srcBegin, srcEnd, value, count);
count = newcount;
return this;
}
public final FastStringBuffer append( FastStringBuffer b ) {
if( b!=null ) {
append( b, 0, b.length() );
}
return this;
}
/**
*
*/
public final FastStringBuffer append( String str, int srcBegin, int srcEnd ) {
// Null value has a representation!
if (str == null) {
str = String.valueOf(str);
}
// Ensure that the buffer is sized enough
int newcount = count + srcEnd-srcBegin;
if (newcount > value.length) {
expandCapacity(newcount);
}
// Copy the desired characters
str.getChars(srcBegin, srcEnd, value, count);
count = newcount;
return this;
}
/**
* Load the content of a IO reader.
*/
public final FastStringBuffer load( Reader r ) {
clear();
return append(r);
}
/**
* Append the content of a IO reader.
*/
public final FastStringBuffer append( Reader r ) {
char[] b = new char[8192];
int len = 0;
try {
while( (len=r.read(b))>0 ) {
append( b, 0, len );
}
} catch( IOException e ) {
throw new RuntimeException(e.getMessage());
}
return this;
}
/**
* Save the content to a writer.
*/
public final void save( Writer w ) {
try {
w.write(value,0,count);
} catch( IOException e ) {
throw new RuntimeException(e.getMessage());
}
}
public final void flush( Writer w ) throws IOException {
w.write(value,0,count);
}
/**
* Convert the buffer to an array of chars.
* @return an array of chars containing all the chars
*/
public final char[] toCharArray() {
char[] c = new char[count];
System.arraycopy( this.value, 0, c, 0, count );
return c;
}
/**
* Extract a part of the string buffer to a string.
* @return the substring
*/
public final String substring( int first, int last ) {
return new String(this.value, first, last-first);
}
/**
* Delete a part of the buffer.
*/
public final void delete( int begin, int end ) {
// /*#IF DEBUG*/
// if ((begin < 0) || (begin >= count)) {
// throw new StringIndexOutOfBoundsException(begin);
// }
// if ((end < 0) || (end > count)) {
// throw new StringIndexOutOfBoundsException(end);
// }
// if (end<begin) {
// throw new StringIndexOutOfBoundsException(end);
// }
// /*#ENDIF*/
if (begin < end) {
System.arraycopy(value, end, value, begin, count-end);
count -= (end-begin);
}
}
/**
* Replace a buffer part.
*/
public final void replace( int begin, int end, String replace ) {
delete( begin, end );
insert( begin, replace );
}
/**
* Replace a buffer part.
*/
public final void replace( int begin, int end, char[] replace ) {
delete( begin, end );
insert( begin, replace );
}
/**
* Replace a buffer part.
*/
public final void replace( int begin, int end, FastStringBuffer replace ) {
delete( begin, end );
insert( begin, replace.toString() ); // TODO: optimize it ?
}
/**
* Replace a set of Strings.
*/
public final void replace( String oldString, String newString ) {
int pos = 0;
while(pos<length()) {
pos = indexOf(oldString,pos);
if( pos>=0 ) {
replace( pos, pos+oldString.length(), newString );
pos += newString.length();
} else {
return;
}
}
}
/**
* Search an instance of a char.
*/
public int indexOf( char c, int begin ) {
for( int i=begin; i<count; i++ ) {
if( value[i]==c ) {
return i;
}
}
return -1;
}
public int indexOf( char c ) {
return indexOf(c,0);
}
/**
* Search an instance of a string.
*/
public int indexOf( String string, int begin ) {
int length = string.length();
if( length>0 ) {
char fc = string.charAt(0);
mainloop:
for( int i=begin; i<=count-length; i++ ) {
// Check for the first character
if( value[i]==fc ) {
// And compare each others
for( int j=1; j<length; j++ ) {
if( value[i+j]!=string.charAt(j) ) {
continue mainloop; // next match
}
}
// Ok, found at i
return i;
}
}
}
return -1;
}
public int indexOf( String string ) {
return indexOf(string,0);
}
/**
* Search the last instance of a char.
*/
public int lastIndexOf( char c, int end ) {
for( int i=end; i>=0; i-- ) {
if( value[i]==c ) {
return i;
}
}
return -1;
}
public int lastIndexOf( char c ) {
return lastIndexOf(c,count-1);
}
/**
* Get the last character contained in the buffer
* @return the last character, '\0' if the buffer is empty
*/
public char getLastChar() {
if( count>0 ) {
return value[count-1];
}
return '\0';
}
/**
* Append a formatted string.
* A call to <CODE>TString.toString()</CODE> is made for each object. By this
* way, arrays are properly dumped.
* modified by dhan
*/
// public final FastStringBuffer appendFormat( String fmt, Object[] args) {
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt) {
// Object[] args = new Object[] {};
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt, Object p1) {
// Object[] args = new Object[] {p1};
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt, Object p1, Object p2) {
// Object[] args = new Object[] {p1,p2};
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt, Object p1, Object p2, Object p3) {
// Object[] args = new Object[] {p1,p2,p3};
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt, Object p1, Object p2, Object p3, Object p4) {
// Object[] args = new Object[] {p1,p2,p3,p4};
// return appendFormatp(fmt,args);
// }
// public final FastStringBuffer appendFormat( String fmt, Object p1, Object p2, Object p3, Object p4, Object p5) {
// Object[] args = new Object[] {p1,p2,p3,p4,p5};
// return appendFormatp(fmt,args);
// }
public final FastStringBuffer appendFormat( String fmt, Object... args) {
if( fmt!=null ) {
int pos = 0; int fmtLength = fmt.length(); int nextObject = 0; boolean not_valid = false;
while(true) {
// check if previous loop found a valid string format of {0} to {8}
if (not_valid == true) {
nextObject++; not_valid = false;
}
nextObject = fmt.indexOf('{', nextObject);
if( nextObject<0 ) {
nextObject = fmtLength;
}
// Copy the part of the string
if( nextObject>pos ) {
int newcount = count + nextObject-pos;
if (newcount > value.length) {
expandCapacity(newcount);
}
fmt.getChars(pos, nextObject, value, count);
count = newcount;
pos = nextObject;
}
// Parse the '{' or stop the search
if (pos < fmtLength) {
if (pos < fmtLength-2) {
char c1 = fmt.charAt(pos+1);
if (Character.isDigit(c1)) {
char c2 = fmt.charAt(pos+2);
if (Character.isDigit(c2) && (pos < fmtLength-1)) {
char c3 = fmt.charAt(pos+3);
if (c3 == '}') {
int index = c1 - '0';
index = c2 - '0' + (index * 10);
not_valid = addArg(args, index);
// if not valid argument add the symbol ({#}) back in
if(not_valid) {
append(fmt.substring(pos, pos+4));
}
pos = pos + 4;
nextObject = pos;
} else {
not_valid = true;
}
} else if (c2 == '}') {
int index = c1 - '0';
//index = c2 - '0' + (index * 10);
not_valid = addArg(args, index);
// if not valid argument add the symbol ({#}) back in
if(not_valid) {
append(fmt.substring(pos, pos+3));
}
pos = pos + 3;
nextObject = pos;
} else {
not_valid = true;
}
} else {
not_valid = true;
}
} else {
not_valid = true;
}
} else {
not_valid = true;
break;
}
}
}
return this;
} // end appendFormat
/*
* Returns whether valid string has been added to the buffer.
* This boolean is the not_valid flag that is used when parsing
* the format message.
* Adds argument (String) value to buffer if the argument exists (this
* includes null values), returning false (! not_valid -> is valid).
* If the index for the args is out of the valid range (when not enough
* arguments have been provided) true (not_valid) is returned.
*
* @param args
* @param index
* @return whether argument is invalid
*/
private final boolean addArg(Object args[], int index) {
if(index >= args.length) {
return(true);
}
if(args[index] != null) {
append(args[index].toString());
} else {
append("null"); //$NON-NLS-1$
}
return(false);
}
public final FastStringBuffer prt( String fmt, Object p1, Object p2, Object p3, Object p4, Object p5 ) {
// if( prtIndent!=null ) {
// append( prtIndent );
// }
appendFormat( fmt, p1, p2, p3, p4, p5 );
append( '\n' );
return this;
}
public final FastStringBuffer prt( String fmt, Object p1, Object p2, Object p3, Object p4 ) {
return prt( fmt, p1, p2, p3, p4, null );
}
public final FastStringBuffer prt( String fmt, Object p1, Object p2, Object p3 ) {
return prt( fmt, p1, p2, p3, null, null );
}
public final FastStringBuffer prt( String fmt, Object p1, Object p2 ) {
return prt( fmt, p1, p2, null, null, null );
}
public final FastStringBuffer prt( String fmt, Object p1 ) {
return prt( fmt, p1, null, null, null, null );
}
public final FastStringBuffer prt( String fmt ) {
return prt( fmt, null, null, null, null, null );
}
/**
* Append a java string to the buffer.
* All the java escape charcters are transformed.
*/
public FastStringBuffer appendJavaString(String s, boolean addQuotes) {
if( addQuotes ) {
append( '"' );
}
int length = s.length();
for( int i=0; i<length; i++ ) {
char c = s.charAt(i);
switch(c) {
case '\b': append( "\\b" ); break; //$NON-NLS-1$
case '\t': append( "\\t" ); break; //$NON-NLS-1$
case '\n': append( "\\n" ); break; //$NON-NLS-1$
case '\f': append( "\\f" ); break; //$NON-NLS-1$
case '\r': append( "\\r" ); break; //$NON-NLS-1$
case '\'': append( "\\'" ); break; //$NON-NLS-1$
case '\"': append( "\\\"" ); break; //$NON-NLS-1$
case '\\': append( "\\\\" ); break; //$NON-NLS-1$
default : {
if((c<ASCII_MIN) || (c > ASCII_MAX)) {
append( "\\u" ); //$NON-NLS-1$
append( StringUtil.toUnsignedHex(c,4) );
} else {
append(c);
}
}
}
}
if( addQuotes ) {
append( '"' );
}
return this;
}
//test cases by Doochan
/*
public static void main( String[] arg ) {
Object[] args = {"[0]","[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]", "[9]","[10]",
"[11]","[12]","[13]","[14]", "[15]"};
Object[] args2 = new String[100];
for (int x=0; x<args2.length; x++) {
String str = "[" + x + "]";
args2[x] = str;
//System.out.println(args2[x]);
}
System.out.println("TStringBuffer2"); // $NON-NLS-1$
System.out.println(TString.format(" %% % {%} {x} { } {8} {0} {1} {2} {} }{{{}}} {{{2}}{3}} {", "[0]","[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]") + "no space"); // $NON-NLS-1$ $NON-NLS-2$
System.out.println(TString.format("", "[0]","[1]"));
System.out.println(TString.format(" ", "[0]","[1]"));
System.out.println(TString.format(" ", "[0]","[1]"));
System.out.println(TString.format(" This example has none ", "[0]","[1]")); // $NON-NLS-1$
System.out.println(TString.format("{", "[0]","[1]"));
System.out.println(TString.format("{{", "[0]", "[1}"));
System.out.println(TString.format("{{0", "[0]", "[1}"));
System.out.println(TString.format("{1}", "[0]","[1]"));
System.out.println(TString.format("{}", "[0]","[1]"));
System.out.println(TString.format("{0}", "[0]","[1]"));
System.out.println(TString.format("{0 }", "[0]","[1]"));
//System.out.println(TString2.format("{ }", "[0]","[1]"));
System.out.println(TString.format("{1}{2 }","[0]", "[1]","[2]"));
System.out.println(TString.format("{2} ", "[0]","[1]", "[2]"));
System.out.println(TString.format("{0} {a} {b { c {0 { 0 1}", "[0]","[1]")); // $NON-NLS-1$
System.out.println(TString.format("{1}is {{{{a test{{2}", "[0]", "[1]", "[2]", "[3]", "[4]")); // $NON-NLS-1$
System.out.println(TString.format("1", "[0]", "[1]", "[2]", "[3]", "[4]"));
System.out.println(TString.format("{0} is a {0}{1}test{2}", "[0]", "[1]", "[2]", "[3]", "[4]")); // $NON-NLS-1$
System.out.println(TString.format("0}{ is a {1{2}{3test{ ", "[0]", "[1]", "[2]", "[3]", "[4]")); // $NON-NLS-1$
System.out.println(TString.format("My name,{0},is{}{1},{2},}}3},{3}},{4{{},{4}", "[0]", "[1]", "[2]", "[3]", "[4]")); // $NON-NLS-1$
//testing modified brian's code
System.out.println(TString.format("%1 %0 %2 %11 %10 %12 %% %", args));
System.out.println(TString.format("I am a boy %1 so %13 is true %11", args)); // $NON-NLS-1$
System.out.println(TString.format("I am a boy {0} so {13} is true {11}", args2)); // $NON-NLS-1$
System.out.println(TString.format("I am a boy {1} so {15} is true {99}{{ ", args2)); // $NON-NLS-1$
System.out.println(TString.format("I am a boy {2} so {15} is true {17}{1", args2)); // $NON-NLS-1$
System.out.println(TString.format("I am a boy {2} so {15} is true {17}{ {}", args2)); // $NON-NLS-1$
System.out.println(TString.format("I am a boy {2} {{{so {15} is true {17}{100}", args2)); // $NON-NLS-1$
System.out.println(TString.format("", args2));
System.out.println(TString.format(" ", args2));
System.out.println(TString.format("{}", args2));
System.out.println(TString.format("{ }", args2));
System.out.println(TString.format("{1}", args2));
System.out.println(TString.format("{{", args2));
System.out.println(TString.format("}}{{", args2));
System.out.println(TString.format("--This example has none--", args2)); // $NON-NLS-1$
System.out.println(TString.format("{", args2));
System.out.println(TString.format(" ", args2));
System.out.println(TString.format(" {", args2));
System.out.println(TString.format("{ {", args2));
System.out.println(TString.format("{1} {", args2));
System.out.println(TString.format("{ 2} {", args2));
System.out.println(TString.format("{2 } {0}", args2));
System.out.println(TString.format("{ ", args2));
}
*/
/*
public static void main( String[] arg ) {
test( "{0} is a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is %%a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a {0}{1}test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "% is a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a test%", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a test%", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
test( "{0} is a test{1}", ">1<", ">2<", ">3<", ">4<", ">5<" );
TStringBuffer b = new TStringBuffer(256);
long ts1 = System.currentTimeMillis();
for( int i=0; i<10000; i++ ) {
b.clear();
b.oldAppendFormat("My format 1",null,null,null,null,null);
b.oldAppendFormat("My format {0} is {1}",null,null,null,null,null);
b.oldAppendFormat("this is a big string {0} with some format inside {1}",null,null,null,null,null);
}
long ts2 = System.currentTimeMillis();
for( int i=0; i<10000; i++ ) {
b.clear();
b.appendFormat("My format 1",null,null,null,null,null);
b.appendFormat("My format {0} is {1}",null,null,null,null,null);
b.appendFormat("this is a big string {0} with some format inside {1}",null,null,null,null,null);
}
long ts3 = System.currentTimeMillis();
TDiag.trace( "Old format={0}", TString.toString(ts2-ts1) );
TDiag.trace( "New format={0}", TString.toString(ts3-ts2) );
}
private static void test( String fmt, Object p1, Object p2, Object p3, Object p4, Object p5 ) {
TStringBuffer b = new TStringBuffer(256);
String s1 = b.appendFormat(fmt,p1,p2,p3,p4,p5).toString();
b.clear();
String s2 = b.oldAppendFormat(fmt,p1,p2,p3,p4,p5).toString();
if( !s1.equals(s2) ) {
com.ibm.workplace.designer.util.TDiag.getOutputStream().println( "Error in fmt '"+fmt+"'" );
com.ibm.workplace.designer.util.TDiag.getOutputStream().println( " "+s1 );
com.ibm.workplace.designer.util.TDiag.getOutputStream().println( " "+s2 );
}
}
public final TStringBuffer oldAppendFormat( String fmt, Object p1, Object p2, Object p3, Object p4, Object p5 ) {
for( int i=0; i<fmt.length(); ) {
char c = fmt.charAt(i++);
if( c=='%' ) {
if( i<fmt.length() ) {
c = fmt.charAt(i++);
switch( c ) {
case '1': {
if(p1!=null) {
append(TString.toString(p1));
}
} break;
case '2': {
if(p2!=null) {
append(TString.toString(p2));
}
} break;
case '3': {
if(p3!=null) {
append(TString.toString(p3));
}
} break;
case '4': {
if(p4!=null) {
append(TString.toString(p4));
}
} break;
case '5': {
if(p5!=null) {
append(TString.toString(p5));
}
} break;
case '%': {
append('%');
} break;
}
}
} else {
append(c);
}
}
return this;
}
*/
}