Replace FastStringBuffer with java.lang.StringBuilder.

Phil Hudson suggested in Feburary 2009 that "[FastStringBuffer] should
be removed with all references to it replaced with
java.lang.StringBuilder once enough confidence in this change has been
gained."  After almost a year of using FastStringBuffer as a delagate
for StringBuilder, that confidence has indeed been gained.

One subtlety for use of StringBuilder: there is no

    StringBuilder(char)

constructor, so use

    StringBuilder(String.valueOf(c))

to construct a new StringBuilder containing a single char.  Otherwise
that char will get promoted to an int, and you will invoke

    StringBuilder(int capacity)

which will "swallow" the first character that you thought you were adding.
parent 06c32169
......@@ -96,7 +96,7 @@ public abstract class AbstractString extends AbstractVector
if (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL ||
Symbol.PRINT_READABLY.symbolValue(thread) != NIL)
{
FastStringBuffer sb = new FastStringBuffer('"');
StringBuilder sb = new StringBuilder("\"");
for (int i = beginIndex; i < endIndex; i++) {
char c = charAt(i);
if (c == '\"' || c == '\\')
......
......@@ -151,7 +151,7 @@ public abstract class AbstractVector extends AbstractArray
protected void badIndex(int index, int limit)
{
FastStringBuffer sb = new FastStringBuffer("Invalid array index ");
StringBuilder sb = new StringBuilder("Invalid array index ");
sb.append(index);
sb.append(" for ");
sb.append(writeToString());
......@@ -209,7 +209,7 @@ public abstract class AbstractVector extends AbstractArray
final LispThread thread = LispThread.currentThread();
if (Symbol.PRINT_READABLY.symbolValue(thread) != NIL)
{
FastStringBuffer sb = new FastStringBuffer("#(");
StringBuilder sb = new StringBuilder("#(");
final int limit = length();
for (int i = 0; i < limit; i++)
{
......
......@@ -73,7 +73,7 @@ public class BuiltInClass extends LispClass
@Override
public String writeToString()
{
FastStringBuffer sb = new FastStringBuffer("#<BUILT-IN-CLASS ");
StringBuilder sb = new StringBuilder("#<BUILT-IN-CLASS ");
sb.append(symbol.writeToString());
sb.append('>');
return sb.toString();
......
......@@ -336,7 +336,7 @@ public final class Complex extends LispObject
@Override
public String writeToString()
{
FastStringBuffer sb = new FastStringBuffer("#C(");
StringBuilder sb = new StringBuilder("#C(");
sb.append(realpart.writeToString());
sb.append(' ');
sb.append(imagpart.writeToString());
......
......@@ -576,7 +576,7 @@ public final class Cons extends LispObject
maxLevel = ((Fixnum)printLevel).value;
else
maxLevel = Integer.MAX_VALUE;
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
if (car == Symbol.QUOTE)
{
if (cdr instanceof Cons)
......
......@@ -572,12 +572,12 @@ public final class DoubleFloat extends LispObject
public String writeToString()
{
if (value == Double.POSITIVE_INFINITY) {
FastStringBuffer sb = new FastStringBuffer("#.");
StringBuilder sb = new StringBuilder("#.");
sb.append(Symbol.DOUBLE_FLOAT_POSITIVE_INFINITY.writeToString());
return sb.toString();
}
if (value == Double.NEGATIVE_INFINITY) {
FastStringBuffer sb = new FastStringBuffer("#.");
StringBuilder sb = new StringBuilder("#.");
sb.append(Symbol.DOUBLE_FLOAT_NEGATIVE_INFINITY.writeToString());
return sb.toString();
}
......
......@@ -73,7 +73,7 @@ public final class FaslReader
{
final Readtable rt = FaslReadtable.getInstance();
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
try
{
while (true) {
......@@ -222,7 +222,7 @@ public final class FaslReader
final Readtable rt = FaslReadtable.getInstance();
final boolean suppress =
(Symbol.READ_SUPPRESS.symbolValue(thread) != NIL);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
try
{
while (true) {
......@@ -474,8 +474,8 @@ public final class FaslReader
public LispObject execute(Stream stream, char c, int n)
{
FastStringBuffer sb =
new FastStringBuffer("Illegal # macro character: #\\");
StringBuilder sb =
new StringBuilder("Illegal # macro character: #\\");
String s = LispCharacter.charToName(c);
if (s != null)
sb.append(s);
......
/*
* FastStringBuffer.java
*
* Copyright (C) 1998-2005 Peter Graves
* Copyright (C) 2008 Phil Hudson
* $Id$
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package org.armedbear.lisp;
/**
* An adaptor of the Java 1.5 java.lang.StringBuilder.
*
* "This class should be removed with all references to it replaced
* with java.lang.StringBuilder once enough confidence in this change
* has been gained." -- Phil Hudson 20090202 via <armedbear-j-devel>.
*/
public final class FastStringBuffer implements Appendable, CharSequence
{
private static final int SPARE_CAPACITY = 128;
private final StringBuilder builder;
public FastStringBuffer()
{
this(SPARE_CAPACITY);
}
public FastStringBuffer(String s)
{
builder = new StringBuilder(s);
}
public FastStringBuffer(char c)
{
this(String.valueOf(c));
}
public FastStringBuffer(int length) throws NegativeArraySizeException
{
builder = new StringBuilder(length);
}
public final int length()
{
return builder.length();
}
public final int capacity()
{
return builder.capacity();
}
public final char charAt(int index)
{
return builder.charAt(index);
}
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
{
builder.getChars(srcBegin, srcEnd, dst, dstBegin);
}
public void setCharAt(int index, char c)
{
builder.setCharAt(index, c);
}
public void ensureCapacity(int minimumCapacity)
{
builder.ensureCapacity(minimumCapacity);
}
public FastStringBuffer append(String s)
{
builder.append(s);
return this;
}
public FastStringBuffer append(char[] chars)
{
builder.append(chars);
return this;
}
public FastStringBuffer append(char[] chars, int offset, int len)
{
builder.append(chars, offset, len);
return this;
}
public FastStringBuffer append(Object object)
{
return append(String.valueOf(object));
}
public FastStringBuffer append(char c)
{
builder.append(c);
return this;
}
public final FastStringBuffer append(int n)
{
return append(String.valueOf(n));
}
public final FastStringBuffer append(long n)
{
return append(String.valueOf(n));
}
public void setLength(int newLength) throws IndexOutOfBoundsException
{
builder.setLength(newLength);
}
public FastStringBuffer reverse()
{
builder.reverse();
return this;
}
@Override
public final String toString()
{
return builder.toString();
}
public final char[] toCharArray()
{
return toString().toCharArray();
}
public CharSequence subSequence(int start, int end)
{
return builder.subSequence(start, end);
}
public FastStringBuffer append(CharSequence seq)
{
builder.append(seq);
return this;
}
public FastStringBuffer append(CharSequence seq, int start, int end)
{
builder.append(seq, start, end);
return this;
}
}
......@@ -946,7 +946,7 @@ public final class Fixnum extends LispInteger
String s = Integer.toString(value, base).toUpperCase();
if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL)
{
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
switch (base)
{
case 2:
......
......@@ -234,7 +234,7 @@ public abstract class HashTable extends LispObject
error(new PrintNotReadable(list(Keyword.OBJECT, this)));
return null; // Not reached.
}
FastStringBuffer sb = new FastStringBuffer(getTest().writeToString());
StringBuilder sb = new StringBuilder(getTest().writeToString());
sb.append(' ');
sb.append(Symbol.HASH_TABLE.writeToString());
sb.append(' ');
......
......@@ -259,7 +259,7 @@ public final class Interpreter
catch (UnhandledCondition c) {
final String separator =
System.getProperty("line.separator");
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
sb.append(separator);
sb.append("Caught ");
sb.append(c.getCondition().typeOf().writeToString());
......@@ -541,7 +541,7 @@ public final class Interpreter
private static String banner()
{
final String sep = System.getProperty("line.separator");
FastStringBuffer sb = new FastStringBuffer("Armed Bear Common Lisp ");
StringBuilder sb = new StringBuilder("Armed Bear Common Lisp ");
sb.append(Version.getVersion());
if (build != null) {
sb.append(" (built ");
......
......@@ -323,7 +323,7 @@ public final class Java
throw new NoSuchMethodException();
}
catch (NoSuchMethodException e) {
FastStringBuffer sb = new FastStringBuffer("No such method: ");
StringBuilder sb = new StringBuilder("No such method: ");
sb.append(c.getName());
sb.append('.');
sb.append(methodName);
......
......@@ -96,7 +96,7 @@ public class JavaClass extends LispClass {
}
public String writeToString() {
FastStringBuffer sb = new FastStringBuffer("#<JAVA-CLASS ");
StringBuilder sb = new StringBuilder("#<JAVA-CLASS ");
sb.append(javaClass.getCanonicalName());
sb.append('>');
return sb.toString();
......
......@@ -303,8 +303,8 @@ public final class JavaObject extends LispObject {
final String s;
if(obj != null) {
Class<?> c = obj.getClass();
FastStringBuffer sb
= new FastStringBuffer(c.isArray() ? "jarray" : c.getName());
StringBuilder sb
= new StringBuilder(c.isArray() ? "jarray" : c.getName());
sb.append(' ');
String ts = obj.toString();
if(ts.length() > 32) { //random value, should be chosen sensibly
......@@ -436,8 +436,8 @@ public final class JavaObject extends LispObject {
public static String describeJavaObject(final JavaObject javaObject)
{
final Object obj = javaObject.getObject();
final FastStringBuffer sb =
new FastStringBuffer(javaObject.writeToString());
final StringBuilder sb =
new StringBuilder(javaObject.writeToString());
sb.append(" is an object of type ");
sb.append(Symbol.JAVA_OBJECT.writeToString());
sb.append(".");
......
......@@ -1063,7 +1063,7 @@ public final class Lisp
public static final Symbol gensym(String prefix, LispThread thread)
{
FastStringBuffer sb = new FastStringBuffer(prefix);
StringBuilder sb = new StringBuilder(prefix);
SpecialBinding binding = thread.getSpecialBinding(Symbol.GENSYM_COUNTER);
final LispObject oldValue;
if (binding != null) {
......@@ -1676,7 +1676,7 @@ public final class Lisp
{
if (start < 0 || end < 0 || start > end || end > length)
{
FastStringBuffer sb = new FastStringBuffer("The bounding indices ");
StringBuilder sb = new StringBuilder("The bounding indices ");
sb.append(start);
sb.append(" and ");
sb.append(end);
......
......@@ -96,7 +96,7 @@ public final class LispCharacter extends LispObject
@Override
public LispObject getDescription()
{
FastStringBuffer sb = new FastStringBuffer("character #\\");
StringBuilder sb = new StringBuilder("character #\\");
sb.append(value);
sb.append(" char-code #x");
sb.append(Integer.toHexString(value));
......@@ -240,7 +240,7 @@ public final class LispCharacter extends LispObject
// false."
boolean printEscape =
printReadably || (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
if (printEscape)
{
sb.append("#\\");
......
......@@ -77,8 +77,8 @@ public abstract class LispClass extends StandardObject
return c;
if (errorp)
{
FastStringBuffer sb =
new FastStringBuffer("There is no class named ");
StringBuilder sb =
new StringBuilder("There is no class named ");
sb.append(name.writeToString());
sb.append('.');
return error(new LispError(sb.toString()));
......
......@@ -64,7 +64,7 @@ public class LispObject //extends Lisp
public LispObject getDescription()
{
FastStringBuffer sb = new FastStringBuffer("An object of type ");
StringBuilder sb = new StringBuilder("An object of type ");
sb.append(typeOf().writeToString());
sb.append(" at #x");
sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase());
......@@ -682,7 +682,7 @@ public class LispObject //extends Lisp
public String unreadableString(String s, boolean identity)
{
FastStringBuffer sb = new FastStringBuffer("#<");
StringBuilder sb = new StringBuilder("#<");
sb.append(s);
if (identity) {
sb.append(" {");
......
......@@ -74,7 +74,7 @@ public final class LispReader
{
final LispThread thread = LispThread.currentThread();
final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
try
{
while (true) {
......@@ -222,7 +222,7 @@ public final class LispReader
final LispThread thread = LispThread.currentThread();
final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread);
final boolean suppress = Symbol.READ_SUPPRESS.symbolValue(thread) != NIL;
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
try
{
while (true) {
......@@ -467,7 +467,7 @@ public final class LispReader
public LispObject execute(Stream stream, char c, int n)
{
FastStringBuffer sb = new FastStringBuffer("Illegal # macro character: #\\");
StringBuilder sb = new StringBuilder("Illegal # macro character: #\\");
String s = LispCharacter.charToName(c);
if (s != null)
sb.append(s);
......
......@@ -187,8 +187,8 @@ public final class Load
verbose, print, false, returnLastResult);
}
catch (FaslVersionMismatch e) {
FastStringBuffer sb =
new FastStringBuffer("Incorrect fasl version: ");
StringBuilder sb =
new StringBuilder("Incorrect fasl version: ");
sb.append(truename);
return error(new SimpleError(sb.toString()));
}
......@@ -301,8 +301,8 @@ public final class Load
return loadFileFromStream(pathname, truename, stream,
verbose, print, auto);
} catch (FaslVersionMismatch e) {
FastStringBuffer sb =
new FastStringBuffer("; Incorrect fasl version: ");
StringBuilder sb =
new StringBuilder("; Incorrect fasl version: ");
sb.append(truename);
System.err.println(sb.toString());
} finally {
......@@ -483,7 +483,7 @@ public final class Load
public static String getLoadVerbosePrefix(int loadDepth)
{
FastStringBuffer sb = new FastStringBuffer(";");
StringBuilder sb = new StringBuilder(";");
for (int i = loadDepth - 1; i-- > 0;)
sb.append(' ');
return sb.toString();
......
......@@ -203,7 +203,7 @@ public final class LogicalPathname extends Pathname
@Override
protected String getDirectoryNamestring()
{
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
// "If a pathname is converted to a namestring, the symbols NIL and
// :UNSPECIFIC cause the field to be treated as if it were empty. That
// is, both NIL and :UNSPECIFIC cause the component not to appear in
......@@ -244,7 +244,7 @@ public final class LogicalPathname extends Pathname
final LispThread thread = LispThread.currentThread();
boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL);
boolean printEscape = (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
if (printReadably || printEscape)
sb.append("#P\"");
sb.append(host.getStringValue());
......
......@@ -88,7 +88,7 @@ public final class Package extends LispObject
public LispObject getDescription()
{
if (name != null) {
FastStringBuffer sb = new FastStringBuffer("The ");
StringBuilder sb = new StringBuilder("The ");
sb.append(name);
sb.append(" package");
return new SimpleString(sb);
......@@ -405,8 +405,8 @@ public final class Package extends LispObject
if (sym == null)
sym = s;
else if (sym != s) {
FastStringBuffer sb =
new FastStringBuffer("Uninterning the symbol ");
StringBuilder sb =
new StringBuilder("Uninterning the symbol ");
sb.append(symbol.getQualifiedName());
sb.append(" causes a name conflict between ");
sb.append(sym.getQualifiedName());
......@@ -442,7 +442,7 @@ public final class Package extends LispObject
return; // Nothing to do.
Symbol sym = findAccessibleSymbol(symbol.name);
if (sym != null && sym != symbol) {
FastStringBuffer sb = new FastStringBuffer("The symbol ");
StringBuilder sb = new StringBuilder("The symbol ");
sb.append(sym.getQualifiedName());
sb.append(" is already accessible in package ");
sb.append(name);
......@@ -461,7 +461,7 @@ public final class Package extends LispObject
if (symbol.getPackage() != this) {
Symbol sym = findAccessibleSymbol(symbol.name);
if (sym != symbol) {
FastStringBuffer sb = new FastStringBuffer("The symbol ");
StringBuilder sb = new StringBuilder("The symbol ");
sb.append(symbol.getQualifiedName());
sb.append(" is not accessible in package ");
sb.append(name);
......@@ -482,7 +482,7 @@ public final class Package extends LispObject
pkg.shadowingSymbols.get(symbolName) == sym) {
// OK.
} else {
FastStringBuffer sb = new FastStringBuffer("The symbol ");
StringBuilder sb = new StringBuilder("The symbol ");
sb.append(sym.getQualifiedName());
sb.append(" is already accessible in package ");
sb.append(pkg.getName());
......@@ -501,7 +501,7 @@ public final class Package extends LispObject
if (externalSymbols.get(symbol.name) == symbol)
// Symbol is already exported; there's nothing to do.
return;
FastStringBuffer sb = new FastStringBuffer("The symbol ");
StringBuilder sb = new StringBuilder("The symbol ");
sb.append(symbol.getQualifiedName());
sb.append(" is not accessible in package ");
sb.append(name);
......@@ -528,7 +528,7 @@ public final class Package extends LispObject
usedPackages = usedPackages.cdr();
}
}
FastStringBuffer sb = new FastStringBuffer("The symbol ");
StringBuilder sb = new StringBuilder("The symbol ");
sb.append(symbol.getQualifiedName());
sb.append(" is not accessible in package ");
sb.append(name);
......@@ -825,7 +825,7 @@ public final class Package extends LispObject
public String writeToString()
{
if (_PRINT_FASL_.symbolValue() != NIL && name != null) {
FastStringBuffer sb = new FastStringBuffer("#.(FIND-PACKAGE \"");
StringBuilder sb = new StringBuilder("#.(FIND-PACKAGE \"");
sb.append(name);
sb.append("\")");
return sb.toString();
......@@ -836,7 +836,7 @@ public final class Package extends LispObject
@Override
public String toString() {
if (name != null) {
FastStringBuffer sb = new FastStringBuffer("#<PACKAGE \"");
StringBuilder sb = new StringBuilder("#<PACKAGE \"");
sb.append(name);
sb.append("\">");
return sb.toString();
......
......@@ -470,7 +470,7 @@ public class Pathname extends LispObject {
if (directory instanceof AbstractString) {
Debug.assertTrue(false);
}
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
// "If a pathname is converted to a namestring, the symbols NIL and
// :UNSPECIFIC cause the field to be treated as if it were empty. That
// is, both NIL and :UNSPECIFIC cause the component not to appear in
......@@ -498,7 +498,7 @@ public class Pathname extends LispObject {
sb.append("!/");
i = 1;
}
FastStringBuffer prefix = new FastStringBuffer();
StringBuilder prefix = new StringBuilder();
for (; i < jars.length; i++) {
prefix.append("jar:");
if (i == 0) {
......@@ -568,7 +568,7 @@ public class Pathname extends LispObject {
protected String getDirectoryNamestring() {
validateDirectory(true);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
// "If a pathname is converted to a namestring, the symbols NIL and
// :UNSPECIFIC cause the field to be treated as if it were empty. That
// is, both NIL and :UNSPECIFIC cause the component not to appear in
......@@ -733,7 +733,7 @@ public class Pathname extends LispObject {
} else {
useNamestring = false;
}
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
if (useNamestring) {
if (printReadably || printEscape) {
sb.append("#P\"");
......@@ -1182,7 +1182,7 @@ public class Pathname extends LispObject {
LispObject second = temp.car();
if (second == Keyword.UP || second == Keyword.BACK) {
if (signalError) {
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
sb.append(first.writeToString());
sb.append(" may not be followed immediately by ");
sb.append(second.writeToString());
......@@ -1683,7 +1683,7 @@ public class Pathname extends LispObject {
}
error:
if (errorIfDoesNotExist) {
FastStringBuffer sb = new FastStringBuffer("The file ");
StringBuilder sb = new StringBuilder("The file ");
sb.append(pathname.writeToString());
sb.append(" does not exist.");
return error(new FileError(sb.toString(), pathname));
......@@ -1957,7 +1957,7 @@ public class Pathname extends LispObject {
@Override
public LispObject execute(LispObject arg) {
Pathname p = coerceToPathname(arg);
FastStringBuffer sb = new FastStringBuffer();
StringBuilder sb = new StringBuilder();
if (p.name instanceof AbstractString) {
sb.append(p.name.getStringValue());
} else if (p.name == Keyword.WILD) {
......
......@@ -2178,8 +2178,8 @@ public final class Primitives
int rank = array.getRank();
if (rank != args.length - 1)
{
FastStringBuffer sb =
new FastStringBuffer("ARRAY-IN-BOUNDS-P: ");
StringBuilder sb =
new StringBuilder("ARRAY-IN-BOUNDS-P: ");
sb.append("wrong number of subscripts (");
sb.append(args.length - 1);
sb.append(") for array of rank ");
......@@ -2235,8 +2235,8 @@ public final class Primitives
array = checkArray( arg);
if (array.getRank() == 0)
return array.AREF(0);
FastStringBuffer sb =
new FastStringBuffer("Wrong number of subscripts (0) for array of rank ");
StringBuilder sb =
new StringBuilder("Wrong number of subscripts (0) for array of rank ");
sb.append(array.getRank());
sb.append('.');
return error(new ProgramError(sb.toString()));
......@@ -2945,7 +2945,7 @@ public final class Primitives
int n = ((Fixnum)arg).value;
if (n >= 0)
{
FastStringBuffer sb = new FastStringBuffer('G');
StringBuilder sb = new StringBuilder("G");
sb.append(n); // Decimal representation.
return new Symbol(new SimpleString(sb));
}
......@@ -2955,7 +2955,7 @@ public final class Primitives
BigInteger n = ((Bignum)arg).value;
if (n.signum() >= 0)
{
FastStringBuffer sb = new FastStringBuffer('G');
StringBuilder sb = new StringBuilder("G");
sb.append(n.toString()); // Decimal representation.
return new Symbol(new SimpleString(sb));
}
......@@ -4109,7 +4109,7 @@ public final class Primitives
final int start = Fixnum.getValue(second);
if (start < 0)