AppenderHelperpublic class AppenderHelper extends Object The AppenderHelper class works around several inefficencies
in the Java distribution.
The following items really need to be added to Java to eliminate
the use of AppenderHelper:
- Object needs the method
appendTo(StringBuffer,int)
- The classes in the Java distribution need to improve their conversions to Strings
(As an aside, there should really be an Appender interface, which
StringBuffer implements with all the append methods defined.)
Instead, AppenderHelper supports the efficient appending of object's string
representation to a StringBuffer. Basically this means that all the basic
data types have their own conversion algorithms in this class which are
considerably more efficient than the Java ones (except char which, of course,
doesn't need conversion) and, in addition, several classes also have
specialized conversion algorithms.
In addition, the whole thing is fully extensible (though I would prefer that
it were made redundant by correct implementations in Java).
As an example
StringBuffer s = new StringBuffer();
s.append(567);
maps to
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
a.append(s,567);
The difference is that in the first StringBuffer append, the StringBuffer
append first asks Integer to convert the int 567 into a String. This conversion
is not very efficient, and apart from being not as fast as it could be, also
creates another temporary StringBuffer during the conversion (which in turn creates
another internal char array). So for appending one int to the StringBuffer
we get three temporary objects, the space they use, and a not particularly
optimized conversion algorithm.
On the other hand, in the second AppenderHelper example, we create no extra
objects at all, and use an optimized conversion algorithm. Which means that even
though we have to call the StringBuffer append(char) lots of times, it is
still faster and uses less resources from the VM (and yes, the two are related,
one reason it is faster is because it uses less VM resources).
The easisest way to add support for using AppenderHelper with classes
you have control over is to implement the Appendable interface.
For classes you do not control, you need to implement an AppendConverter
class, and register it with the AppenderHelper.
But NOTE that if you do not need efficient conversion of objects (because
you do not do much StringBuffer appending, or it happens in a part of the
application that has plenty of spare time and resources), then there is no
need to change the way you do things at the moment.
AppenderHelper can be used in a very similar way to StringBuffer, e.g.
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
a.append(s,567).append(s," is ").append(s,33.5).append(s,'%');
and there is also a StringBufferWrapper class if you are feeling really lazy.
All data type conversions are specifically optimized by AppenderHelper.
In addition, the classes specifically optimized by AppenderHelper (and so
which do not need AppendConverter classes for them) are: all the classes
coresponding to the basic datatypes (e.g. Integer, etc.); Object; java.util.Vector.
Note however that subclasses of these types are not specially optimized unless
the correct overloaded append method is called, i.e. if java.util.Stack were not
registered (which it is) then
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
java.util.Stack stack = new java.util.Stack();
a.append(s,stack);
would be optimized because that calls the
AppenderHelper.append(StringBuffer,java.util.Vector) method, but
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
java.util.Stack stack = new java.util.Stack();
a.append(s,(Object) stack);
would not be optimized because that calls the
AppenderHelper.append(StringBuffer,Object) method, which
requires the passed object's class to be registered for the correct AppendConverter
to be used.
AppenderHelper is an application (i.e. has a runnable main method)
which can be run to see examples of the improvements it brings. |
Fields Summary |
---|
public static AppenderHelper | SINGLETON | public static int | DEFAULT_DEPTH | public static final char[] | TRUEchar array holding the characters for the string "true". | public static final char[] | FALSEchar array holding the characters for the string "false". | public static final char[] | NULLchar array holding the characters for the string "null". | public static final char[] | NEGATIVE_INFINITYchar array holding the characters for the string "-Infinity". | public static final char[] | POSITIVE_INFINITYchar array holding the characters for the string "Infinity". | public static final char[] | NaNchar array holding the characters for the string "NaN". | public static final char[] | DOUBLE_ZEROchar array holding the characters for the string "0.0". | public static final char[] | DOUBLE_ZERO2char array holding the characters for the string "0.00". | public static final char[] | DOUBLE_ZERO0char array holding the characters for the string "0.". | public static final char[] | DOT_ZEROchar array holding the characters for the string ".0". | public static final char[] | COMMA_SPACEchar array holding the characters for the string ", ". | private static final long | doubleSignMask | private static final long | doubleExpMask | private static final long | doubleFractMask | private static final int | doubleExpShift | private static final int | doubleExpBias | private static final int | floatSignMask | private static final int | floatExpMask | private static final int | floatFractMask | private static final int | floatExpShift | private static final int | floatExpBias | private static final Hashtable | append_map | private static final Hashtable | clsname_cache | private static final char[] | charForDigit | private static final float[] | f_magnitudes | private static final double[] | d_magnitudes | public static final char[] | ZEROS |
Constructors Summary |
---|
protected AppenderHelper()AppenderHelper is a singleton, so the constructor is just narrowed
in scope to disallow external classes to create further instances.
Subclasses can create new instances (required in order to allow them
to create instances of themselves), but should refrain from doing so.
|
Methods Summary |
---|
public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Appendable o)Appends the string representation of the
Appendable argument to the string buffer. Does so by calling the
appendTo method of the Appendable.
if (o == null)
{
s.append(NULL);
return this;
}
o.appendTo(s, DEFAULT_DEPTH);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Appendable o, int depth)Appends the string representation of the
Appendable argument to the string buffer. Does so by calling the
appendTo method of the Appendable.
if (o == null)
{
s.append(NULL);
return this;
}
if (depth <= 0)
appendDepth0To(s,o);
else
o.appendTo(s, depth);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Boolean o)Appends the string representation of the
Boolean argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.booleanValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Byte o)Appends the string representation of the
Byte argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.byteValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Character o)Appends the string representation of the
Character argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.charValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Double o)Appends the string representation of the
Double argument to the string buffer.
return append(s,o.doubleValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Float o)Appends the string representation of the
Float argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.floatValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Integer o)Appends the string representation of the
Integer argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.intValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Long o)Appends the string representation of the
Long argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.longValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Object o)Appends the string representation of the
Object argument to the string buffer. If o is an Appendable, this will
delegate the append to the appendTo method.
If o has a registered append mapping, then this will delegate the append
to the registered AppendConverter object.
return append(s, o, DEFAULT_DEPTH);
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, char[] c)Appends the string representation of the
char array argument to the string buffer.
if (c == null)
{
s.append(NULL);
return this;
}
s.append(c);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Object o, int depth)Appends the string representation of the
Object argument to the string buffer. If o is an Appendable, this will
delegate the append to the appendTo method.
If o has a registered append mapping, then this will delegate the append
to the registered AppendConverter object.
if (o == null)
{
s.append(NULL);
return this;
}
if (depth <= 0)
appendDepth0To(s,o);
else if (o instanceof Appendable)
((Appendable) o).appendTo(s, depth);
else
{
AppendConverter h = (AppendConverter) append_map.get(o.getClass());
if (h == null)
s.append(o);
else
h.appendObj(this, s, o, depth);
}
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.Short o)Appends the string representation of the
Short argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
return append(s,o.shortValue());
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.lang.String o)Appends the string representation of the
String argument to the string buffer.
if (o == null)
{
s.append(NULL);
return this;
}
s.append(o);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.util.Vector o)Appends a java.util.Vector to a StringBuffer.
Since Vector is an object containing other objects, the contained objects
are also appended to the StringBuffer. These appended objects are also asked
to be appended by the AppenderHelper object.
append(s, o, DEFAULT_DEPTH);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, java.util.Vector o, int depth)Appends a java.util.Vector to a StringBuffer.
Since Vector is an object containing other objects, the contained objects
are also appended to the StringBuffer. These appended objects are also asked
to be appended by the AppenderHelper object.
The depth parameter specifies how deep the contained objects
network should be asked to appended to the StringBuffer. A depth of 0
means just use a default representation of the object with no further
contained objects asked to rpresent themselves.
if (o == null)
{
s.append(NULL);
return this;
}
if (depth <= 0)
{
appendDepth0To(s,o);
}
else
{
depth--;
int size = o.size();
s.append('[");
if (size != 0)
{
this.append(s, o.elementAt(0), depth);
for (int i = 1; i < size; i++)
{
s.append(COMMA_SPACE);
this.append(s, o.elementAt(i), depth);
}
}
s.append(']");
}
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, boolean b)Appends the string representation of the
boolean argument to the string buffer.
if (b)
s.append(TRUE);
else
s.append(FALSE);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, char[] c, int offset, int len)Appends the string representation of a subarray of the
char array argument to the string buffer.
if (c == null)
{
s.append(NULL);
return this;
}
s.append(c,offset,len);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, char c)Appends the character to the string buffer.
s.append(c);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, double d)Appends the string representation of the
double argument to the string buffer.
if (d == Double.NEGATIVE_INFINITY)
s.append(NEGATIVE_INFINITY);
else if (d == Double.POSITIVE_INFINITY)
s.append(POSITIVE_INFINITY);
else if (d != d)
s.append(NaN);
else if (d == 0.0)
{
if ( (Double.doubleToLongBits(d) & doubleSignMask) != 0)
s.append('-");
s.append(DOUBLE_ZERO);
}
else
{
if (d < 0)
{
s.append('-");
d = -d;
}
if (d >= 0.001 && d < 0.01)
{
long i = (long) (d * 1E20);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO2);
appendFractDigits(s, i,-1);
}
else if (d >= 0.01 && d < 0.1)
{
long i = (long) (d * 1E19);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO);
appendFractDigits(s, i,-1);
}
else if (d >= 0.1 && d < 1)
{
long i = (long) (d * 1E18);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO0);
appendFractDigits(s, i,-1);
}
else if (d >= 1 && d < 10)
{
long i = (long) (d * 1E17);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,1);
}
else if (d >= 10 && d < 100)
{
long i = (long) (d * 1E16);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,2);
}
else if (d >= 100 && d < 1000)
{
long i = (long) (d * 1E15);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,3);
}
else if (d >= 1000 && d < 10000)
{
long i = (long) (d * 1E14);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,4);
}
else if (d >= 10000 && d < 100000)
{
long i = (long) (d * 1E13);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,5);
}
else if (d >= 100000 && d < 1000000)
{
long i = (long) (d * 1E12);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,6);
}
else if (d >= 1000000 && d < 10000000)
{
long i = (long) (d * 1E11);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,7);
}
else
{
int magnitude = magnitude(d);
long i;
if (magnitude < -305)
i = (long) (d*1E18 / d_magnitudes[magnitude + 324]);
else
i = (long) (d / d_magnitudes[magnitude + 323 - 17]);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i, 1);
s.append('E");
append(s,magnitude);
}
}
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, float d)Appends the string representation of the
float argument to the string buffer.
if (d == Float.NEGATIVE_INFINITY)
s.append(NEGATIVE_INFINITY);
else if (d == Float.POSITIVE_INFINITY)
s.append(POSITIVE_INFINITY);
else if (d != d)
s.append(NaN);
else if (d == 0.0)
{
if ( (Float.floatToIntBits(d) & floatSignMask) != 0)
s.append('-");
s.append(DOUBLE_ZERO);
}
else
{
if (d < 0)
{
s.append('-");
d = -d;
}
if (d >= 0.001F && d < 0.01F)
{
long i = (long) (d * 1E12F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO2);
appendFractDigits(s, i,-1);
}
else if (d >= 0.01F && d < 0.1F)
{
long i = (long) (d * 1E11F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO);
appendFractDigits(s, i,-1);
}
else if (d >= 0.1F && d < 1F)
{
long i = (long) (d * 1E10F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
s.append(DOUBLE_ZERO0);
appendFractDigits(s, i,-1);
}
else if (d >= 1F && d < 10F)
{
long i = (long) (d * 1E9F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,1);
}
else if (d >= 10F && d < 100F)
{
long i = (long) (d * 1E8F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,2);
}
else if (d >= 100F && d < 1000F)
{
long i = (long) (d * 1E7F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,3);
}
else if (d >= 1000F && d < 10000F)
{
long i = (long) (d * 1E6F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,4);
}
else if (d >= 10000F && d < 100000F)
{
long i = (long) (d * 1E5F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,5);
}
else if (d >= 100000F && d < 1000000F)
{
long i = (long) (d * 1E4F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,6);
}
else if (d >= 1000000F && d < 10000000F)
{
long i = (long) (d * 1E3F);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i,7);
}
else
{
int magnitude = magnitude(d);
long i;
if (magnitude < -35)
i = (long) (d*1E10F / f_magnitudes[magnitude + 45]);
else
i = (long) (d / f_magnitudes[magnitude + 44 - 9]);
i = i%100 >= 50 ? (i/100) + 1 : i/100;
appendFractDigits(s, i, 1);
s.append('E");
append(s,magnitude);
}
}
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, long i)Appends the string representation of the
long argument to the string buffer.
if (i < 0)
{
if (i == Long.MIN_VALUE)
{
//cannot make this positive due to integer overflow
s.append("-9223372036854775808");
return this;
}
s.append('-");
i = -i;
}
long mag = magnitude(i);
long c;
while ( mag > 1 )
{
c = i/mag;
s.append(charForDigit[(int) c]);
c *= mag;
if ( c <= i)
i -= c;
mag /= 10;
}
s.append(charForDigit[(int) i]);
return this;
| public tuning.stringconvert.AppenderHelper | append(java.lang.StringBuffer s, int i)
if (i < 0)
{
if (i == Integer.MIN_VALUE)
{
//cannot make this positive due to integer overflow
s.append("-2147483648");
return this;
}
s.append('-");
i = -i;
}
int mag;
int c;
if (i < 10)
{
//one digit
s.append(charForDigit[i]);
return this;
}
else if (i < 100)
{
//two digits
s.append(charForDigit[i/10]);
s.append(charForDigit[i%10]);
return this;
}
else if (i < 1000)
{
//three digits
s.append(charForDigit[i/100]);
s.append(charForDigit[(c=i%100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 10000)
{
//four digits
s.append(charForDigit[i/1000]);
s.append(charForDigit[(c=i%1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 100000)
{
//five digits
s.append(charForDigit[i/10000]);
s.append(charForDigit[(c=i%10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 1000000)
{
//six digits
s.append(charForDigit[i/100000]);
s.append(charForDigit[(c=i%100000)/10000]);
s.append(charForDigit[(c%=10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 10000000)
{
//seven digits
s.append(charForDigit[i/1000000]);
s.append(charForDigit[(c=i%1000000)/100000]);
s.append(charForDigit[(c%=100000)/10000]);
s.append(charForDigit[(c%=10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 100000000)
{
//eight digits
s.append(charForDigit[i/10000000]);
s.append(charForDigit[(c=i%10000000)/1000000]);
s.append(charForDigit[(c%=1000000)/100000]);
s.append(charForDigit[(c%=100000)/10000]);
s.append(charForDigit[(c%=10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else if (i < 1000000000)
{
//nine digits
s.append(charForDigit[i/100000000]);
s.append(charForDigit[(c=i%100000000)/10000000]);
s.append(charForDigit[(c%=10000000)/1000000]);
s.append(charForDigit[(c%=1000000)/100000]);
s.append(charForDigit[(c%=100000)/10000]);
s.append(charForDigit[(c%=10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
else
{
//ten digits
s.append(charForDigit[i/1000000000]);
s.append(charForDigit[(c=i%1000000000)/100000000]);
s.append(charForDigit[(c%=100000000)/10000000]);
s.append(charForDigit[(c%=10000000)/1000000]);
s.append(charForDigit[(c%=1000000)/100000]);
s.append(charForDigit[(c%=100000)/10000]);
s.append(charForDigit[(c%=10000)/1000]);
s.append(charForDigit[(c%=1000)/100]);
s.append(charForDigit[(c%=100)/10]);
s.append(charForDigit[c%10]);
return this;
}
| private static void | appendAsUnsignedHexadecimal(java.lang.StringBuffer s, int iin)
long i = iin;
if (i < 0)
i += 4294967296L;
long mag = magnitude16(i);
long c;
while ( mag > 1 )
{
c = i/mag;
s.append(charForDigit[(int) c]);
c *= mag;
if ( c <= i)
i -= c;
mag = mag/16;
}
s.append(charForDigit[(int) i]);
| public static final void | appendDepth0To(java.lang.StringBuffer s, java.lang.Object o)Appends the default string representation of the object as given in
Object.toString() .
(The toString method for class Object
returns a string consisting of the name of the class of which the
object is an instance, the at-sign character `@ ', and
the unsigned hexadecimal representation of the hash code of the
object.)
Of course, this is quicker and more efficient than that method, and
does not create any extra extraneous objects.
if (o == null)
{
s.append(NULL);
return;
}
Class cls = o.getClass();
String nme = (String) clsname_cache.get(cls);
if (nme == null)
{
nme = cls.getName();
clsname_cache.put(cls,nme);
}
s.append(nme).append('@");
appendAsUnsignedHexadecimal(s,o.hashCode());
| private static void | appendFractDigits(java.lang.StringBuffer s, long i, int decimalOffset)
long mag = magnitude(i);
long c;
while ( i > 0 )
{
c = i/mag;
s.append(charForDigit[(int) c]);
decimalOffset--;
if (decimalOffset == 0)
s.append('.");
c *= mag;
if ( c <= i)
i -= c;
mag = mag/10;
}
if (i != 0)
s.append(charForDigit[(int) i]);
else if (decimalOffset > 0)
{
s.append(ZEROS[decimalOffset]);
decimalOffset = 1;
}
decimalOffset--;
if (decimalOffset == 0)
s.append(DOT_ZERO);
else if (decimalOffset == -1)
s.append('0");
| private static void | initializeMaps()Initializes the maps in the DisplayHelper with the InternalDisplayHelper's
known classes.
try
{
putInAppendMap(new BooleanAppender(),"java.lang.Boolean");
putInAppendMap(new ByteAppender(),"java.lang.Byte");
putInAppendMap(new CharacterAppender(),"java.lang.Character");
putInAppendMap(new DoubleAppender(),"java.lang.Double");
putInAppendMap(new FloatAppender(),"java.lang.Float");
putInAppendMap(new IntegerAppender(),"java.lang.Integer");
putInAppendMap(new LongAppender(),"java.lang.Long");
putInAppendMap(new ShortAppender(),"java.lang.Short");
putInAppendMap(new StringAppender(),"java.lang.String");
putInAppendMap(new VectorAppender(),"java.util.Vector");
putInAppendMap(new VectorAppender(),"java.util.Stack");
char[] c = new char[0];
putInAppendMap(new CharArrayAppender(),c.getClass());
putInAppendMap(new ObjectAppender(),"java.lang.Object");
}
catch(ClassNotFoundException e){}
| private static int | magnitude(double d)
return magnitude(d,Double.doubleToLongBits(d));
| private static int | magnitude(double d, long doubleToLongBits)
int magnitude =
(int) ((((doubleToLongBits & doubleExpMask) >> doubleExpShift) - doubleExpBias) * 0.301029995663981);
if (magnitude < -323)
magnitude = -323;
else if (magnitude > 308)
magnitude = 308;
if (d >= d_magnitudes[magnitude+323])
{
while(magnitude < 309 && d >= d_magnitudes[magnitude+323])
magnitude++;
magnitude--;
return magnitude;
}
else
{
while(magnitude > -324 && d < d_magnitudes[magnitude+323])
magnitude--;
return magnitude;
}
| private static int | magnitude(float d)
return magnitude(d,Float.floatToIntBits(d));
| private static int | magnitude(float d, int floatToIntBits)
int magnitude =
(int) ((((floatToIntBits & floatExpMask) >> floatExpShift) - floatExpBias) * 0.301029995663981);
if (magnitude < -44)
magnitude = -44;
else if (magnitude > 38)
magnitude = 38;
if (d >= f_magnitudes[magnitude+44])
{
while(magnitude < 39 && d >= f_magnitudes[magnitude+44])
magnitude++;
magnitude--;
return magnitude;
}
else
{
while(magnitude > -45 && d < f_magnitudes[magnitude+44])
magnitude--;
return magnitude;
}
| private static long | magnitude(long i)Assumes i is positive. Returns the magnitude of i in base 10.
if (i < 10L) return 1;
else if (i < 100L) return 10L;
else if (i < 1000L) return 100L;
else if (i < 10000L) return 1000L;
else if (i < 100000L) return 10000L;
else if (i < 1000000L) return 100000L;
else if (i < 10000000L) return 1000000L;
else if (i < 100000000L) return 10000000L;
else if (i < 1000000000L) return 100000000L;
else if (i < 10000000000L) return 1000000000L;
else if (i < 100000000000L) return 10000000000L;
else if (i < 1000000000000L) return 100000000000L;
else if (i < 10000000000000L) return 1000000000000L;
else if (i < 100000000000000L) return 10000000000000L;
else if (i < 1000000000000000L) return 100000000000000L;
else if (i < 10000000000000000L) return 1000000000000000L;
else if (i < 100000000000000000L) return 10000000000000000L;
else if (i < 1000000000000000000L) return 100000000000000000L;
else return 1000000000000000000L;
| private static long | magnitude16(long i)Assumes i is positive. Returns the magnitude of i in base 16.
if (i < 16L) return 1;
else if (i < 256L) return 16L;
else if (i < 4096L) return 256L;
else if (i < 65536L) return 4096L;
else if (i < 1048576L) return 65536L;
else if (i < 16777216L) return 1048576L;
else if (i < 268435456L) return 16777216L;
else if (i < 4294967296L) return 268435456L;
else if (i < 68719476736L) return 4294967296L;
else if (i < 1099511627776L) return 68719476736L;
else if (i < 17592186044416L) return 1099511627776L;
else if (i < 281474976710656L) return 17592186044416L;
else if (i < 4503599627370496L) return 281474976710656L;
else if (i < 72057594037927936L) return 4503599627370496L;
else if (i < 1152921504606846976L) return 72057594037927936L;
else return 1152921504606846976L;
| private static int | magnitude_i(int i)
if (i < 10) return 1;
else if (i < 100) return 10;
else if (i < 1000) return 100;
else if (i < 10000) return 1000;
else if (i < 100000) return 10000;
else if (i < 1000000) return 100000;
else if (i < 10000000) return 1000000;
else if (i < 100000000) return 10000000;
else if (i < 1000000000) return 100000000;
else return 1000000000;
| public static void | main(java.lang.String[] args)Test cases. Worth running as
java -verbosegc -ms4000000 jacks.basics.Appender
to see the effects of object creation vs. optimized conversions.
If run this way, note that a garbage collection is run immediately before and
after each test, so you see exactly which tests create how many objects. Garbage
collections run during a test are due to the test itself creating so many objects
that the vm has to reclaim space. Because each test starts with the default
empty string buffer, each test will have a large amount of memory to be garbage
collected from just a few objects - these are the char arrays inside the StringBuffers
being copied over as they expand. What is interesting to note is the difference
in objects and space reclaimed between the Appender test and the StringBuffer
test.
if (args.length > 0)
{
maintest(args);
maintest(args);
}
else
maintest(args);
| private static void | main_adj(int repeat, java.lang.String name, byte[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, char[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, double[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, float[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, int[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, long[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, java.lang.Object[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, short[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| private static void | main_adj(int repeat, java.lang.String name, boolean[] arr, java.lang.String list)
long time1, time2;
StringBuffer s;
AppenderHelper a = SINGLETON;
System.out.println("The " + name);
System.out.println(" " + list);
System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time1 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
a.append(s,arr[j]);
time1 = System.currentTimeMillis() - time1;
System.out.println(" The Appender took " + time1 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println("Starting test");
time2 = System.currentTimeMillis();
for (int i = repeat; i > 0; i--)
for (int j = arr.length-1; j >= 0; j--)
s.append(arr[j]);
time2 = System.currentTimeMillis() - time2;
System.out.println(" The StringBuffer took " + time2 + " milliseconds");
s = new StringBuffer();
Runtime.getRuntime().gc();
System.out.println(" For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
for (int j = 0; j < arr.length; j++)
s.append(arr[j]).append(", ");
System.out.println(" " + s);
s = new StringBuffer();
for (int j = 0; j < arr.length; j++)
a.append(s,arr[j]).append(s,", ");
System.out.println(" " + s);
System.out.println();
| public static void | maintest(java.lang.String[] args)
long time1, time2;
boolean[] bools = {true,false,true,false,true,true,false,true,false,false};
double[] ds = {Double.MAX_VALUE, -3.14e-200D, Double.NEGATIVE_INFINITY, 100,
567.89023D, 123e199D, -0.000456D, -1.234D, 1e55D, 99999};
float[] fs = {-3.14F, Float.POSITIVE_INFINITY, 99999, 100,
567.89023F, 123e33F, -0.000456F, -1.23456789e-2F, 1e-12F, Float.MIN_VALUE};
long[] ls = {2283911683699007717L, -8007630872066909262L, 4536503365853551745L,
548519563869L, 45L, Long.MAX_VALUE, 1L, -9999L, 7661314123L, 0L};
int[] is = {1147173962, 828789888, -337681747, 940436254, -20385232,
83, -1154302556, 1975989662, -515020324, Integer.MIN_VALUE};
char[] cs = {'a", '*", 12345, 9999, Character.MAX_VALUE};
short[] ss = {Short.MIN_VALUE, (short) 34567, (short) 23, (short) -5555, (short) 256};
byte[] bs = {Byte.MIN_VALUE, (byte) 99, (byte) 23, (byte) -100, (byte) -11};
Object[] os = {new Object(), new Object(), new Object()};
int repeat = 1000;
main_adj(repeat*100,"booleans",bools,
"true, false, true, false, true, true, false, true, false, false");
main_adj(repeat*5,"floats",fs,
"-3.14F, Float.POSITIVE_INFINITY, 567.89023F, 123e33F, -0.000456F, -1.23456789e-2F, 1e-12F, Float.MIN_VALUE");
main_adj(repeat*5,"doubles",ds,
"Double.MAX_VALUE, -3.14e-200D, Double.NEGATIVE_INFINITY, 567.89023D, 123e199D, -0.000456D, -1.234D, 1e55D");
main_adj(repeat*5,"longs",ls,
"2283911683699007717L, -8007630872066909262L, 4536503365853551745L, 548519563869L, 45L, Long.MAX_VALUE, 1L, -9999L, 7661314123L, 0L");
main_adj(repeat*50,"ints",is,
"1147173962, 828789888, -337681747, 940436254, -20385232, 83, -1154302556, 1975989662, -515020324, Integer.MIN_VALUE");
main_adj(repeat*500,"chars",cs,
"'a', '*', 12345, 9999, Character.MAX_VALUE");
main_adj(repeat*50,"shorts",ss,
"Short.MIN_VALUE, 34567, 23, -5555, 256");
main_adj(repeat*50,"bytes",bs,
"Byte.MIN_VALUE, 99, 23, -100, 245");
main_adj(repeat*20,"Objects",os,
"new Object(), new Object(), new Object()");
| public static void | putInAppendMap(AppendConverter h, java.lang.Class c)Classes needing to add append support for a particular class must add themselves
into the append map.
Basically, this means that when an object of class c is passed to the Appender
to be appended to the StringBuffer, the AppenderHelper looks up that class in the append
map. If there is an AppendConverter object registered for that class, then the task
of appending the original object (of class c) to the StringBuffer is delegated
to the registered AppendConverter object, by calling it with the method
AppendConverter.appendObj(AppenderHelper a, StringBuffer s, Object o, int depth)
append_map.put(c, h);
| public static void | putInAppendMap(AppendConverter h, java.lang.String classname)Convenience method so that classes can be registered by class name.
append_map.put(Class.forName(classname), h);
|
|