// //(c) 2000 Sun Microsystems, Inc. //ALL RIGHTS RESERVED // //License Grant- // // //Permission to use, copy, modify, and distribute this Software and its //documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is //hereby granted. // //This Software is provided "AS IS". All express warranties, including any //implied warranty of merchantability, satisfactory quality, fitness for a //particular purpose, or non-infringement, are disclaimed, except to the extent //that such disclaimers are held to be legally invalid. // //You acknowledge that Software is not designed, licensed or intended for use in //the design, construction, operation or maintenance of any nuclear facility //("High Risk Activities"). Sun disclaims any express or implied warranty of //fitness for such uses. // //Please refer to the file http://www.sun.com/policies/trademarks/ for further //important trademark information and to //http://java.sun.com/nav/business/index.html for further important licensing //information for the Java Technology. // package com.ximple.util; //~--- JDK imports ------------------------------------------------------------ import java.text.DecimalFormatSymbols; import java.util.Enumeration; import java.util.Locale; import java.util.Vector; /** * PrintfFormat allows the formatting of an array of * objects embedded within a string. Primitive types * must be passed using wrapper types. The formatting * is controlled by a control string. *
* A control string is a Java string that contains a * control specification. The control specification * starts at the first percent sign (%) in the string, * provided that this percent sign *
* A control specification usually takes the form: *
% ['-+ #0]* [0..9]* { . [0..9]* }+ * { [hlL] }+ [idfgGoxXeEcs] ** There are variants of this basic form that are * discussed below. *
* The format is composed of zero or more directives * defined as follows: *
* The results are undefined if there are insufficient * arguments for the format. Usually an unchecked * exception will be thrown. If the format is * exhausted while arguments remain, the excess * arguments are evaluated but are otherwise ignored. * In format strings containing the % form of * conversion specifications, each argument in the * argument list is used exactly once.
*
* Conversions can be applied to the n
th
* argument after the format in the argument list,
* rather than to the next unused argument. In this
* case, the conversion characer % is replaced by the
* sequence %n
$, where n
is
* a decimal integer giving the position of the
* argument in the argument list.
* In format strings containing the %n
$
* form of conversion specifications, each argument
* in the argument list is used exactly once.
* The following table lists escape sequences and * associated actions on display devices capable of * the action. *
Sequence | *Name | *Description |
---|---|---|
\\ | backlash | None. * |
\a | alert | Attempts to alert * the user through audible or visible * notification. * |
\b | backspace | Moves the * printing position to one column before * the current position, unless the * current position is the start of a line. * |
\f | form-feed | Moves the * printing position to the initial * printing position of the next logical * page. * |
\n | newline | Moves the * printing position to the start of the * next line. * |
\r | carriage-return | Moves * the printing position to the start of * the current line. * |
\t | tab | Moves the printing * position to the next implementation- * defined horizontal tab position. * |
\v | vertical-tab | Moves the * printing position to the start of the * next implementation-defined vertical * tab position. * |
* Each conversion specification is introduced by * the percent sign character (%). After the character * %, the following appear in sequence:
** Zero or more flags (in any order), which modify the * meaning of the conversion specification.
** An optional minimum field width. If the converted * value has fewer characters than the field width, it * will be padded with spaces by default on the left; * t will be padded on the right, if the left- * adjustment flag (-), described below, is given to * the field width. The field width takes the form * of a decimal integer. If the conversion character * is s, the field width is the the minimum number of * characters to be printed.
** An optional precision that gives the minumum number * of digits to appear for the d, i, o, x or X * conversions (the field is padded with leading * zeros); the number of digits to appear after the * radix character for the e, E, and f conversions, * the maximum number of significant digits for the g * and G conversions; or the maximum number of * characters to be written from a string is s and S * conversions. The precision takes the form of an * optional decimal digit string, where a null digit * string is treated as 0. If a precision appears * with a c conversion character the precision is * ignored. *
** An optional h specifies that a following d, i, o, * x, or X conversion character applies to a type * short argument (the argument will be promoted * according to the integral promotions and its value * converted to type short before printing).
** An optional l (ell) specifies that a following * d, i, o, x, or X conversion character applies to a * type long argument.
** A field width or precision may be indicated by an * asterisk (*) instead of a digit string. In this * case, an integer argument supplised the field width * precision. The argument that is actually converted * is not fetched until the conversion letter is seen, * so the the arguments specifying field width or * precision must appear before the argument (if any) * to be converted. If the precision argument is * negative, it will be changed to zero. A negative * field width argument is taken as a - flag, followed * by a positive field width.
*
* In format strings containing the %n
$
* form of a conversion specification, a field width
* or precision may be indicated by the sequence
* *m
$, where m is a decimal integer
* giving the position in the argument list (after the
* format argument) of an integer argument containing
* the field width or precision.
* The format can contain either numbered argument
* specifications (that is, %n
$ and
* *m
$), or unnumbered argument
* specifications (that is % and *), but normally not
* both. The only exception to this is that %% can
* be mixed with the %n
$ form. The
* results of mixing numbered and unnumbered argument
* specifications in a format string are undefined.
* The flags and their meanings are:
** Each conversion character results in fetching zero * or more arguments. The results are undefined if * there are insufficient arguments for the format. * Usually, an unchecked exception will be thrown. * If the format is exhausted while arguments remain, * the excess arguments are ignored.
* ** The conversion characters and their meanings are: *
** If a conversion specification does not match one of * the above forms, an IllegalArgumentException is * thrown and the instance of PrintfFormat is not * created.
** If a floating point value is the internal * representation for infinity, the output is * [+]Infinity, where Infinity is either Infinity or * Inf, depending on the desired output string length. * Printing of the sign follows the rules described * above.
** If a floating point value is the internal * representation for "not-a-number," the output is * [+]NaN. Printing of the sign follows the rules * described above.
** In no case does a non-existent or small field width * cause truncation of a field; if the result of a * conversion is wider than the field width, the field * is simply expanded to contain the conversion result. *
** The behavior is like printf. One exception is that * the minimum number of exponent digits is 3 instead * of 2 for e and E formats when the optional L is used * before the e, E, g, or G conversion character. The * optional L does not imply conversion to a long long * double.
** The biggest divergence from the C printf * specification is in the use of 16 bit characters. * This allows the handling of characters beyond the * small ASCII character set and allows the utility to * interoperate correctly with the rest of the Java * runtime environment.
** Omissions from the C printf specification are * numerous. All the known omissions are present * because Java never uses bytes to represent * characters and does not have pointers:
** Most of this specification is quoted from the Unix * man page for the sprintf utility.
* * @author Allan Jacobs * @version 1 * Release 1: Initial release. * Release 2: Asterisk field widths and precisions * %n$ and *m$ * Bug fixes * g format fix (2 digits in e form corrupt) * rounding in f format implemented * round up when digit not printed is 5 * formatting of -0.0f * round up/down when last digits are 50000... */ public final class PrintfFormat { /** Vector of control strings and format literals. */ private Vector vFmt = new Vector(); /** Character position. Used by the constructor. */ private int cPos = 0; /** Character position. Used by the constructor. */ private DecimalFormatSymbols dfs = null; /** * Constructs an array of control specifications * possibly preceded, separated, or followed by * ordinary strings. Control strings begin with * unpaired percent signs. A pair of successive * percent signs designates a single percent sign in * the format. * @param fmtArg Control string. * @exception IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(String fmtArg) throws IllegalArgumentException { this(Locale.getDefault(), fmtArg); } /** * Constructs an array of control specifications * possibly preceded, separated, or followed by * ordinary strings. Control strings begin with * unpaired percent signs. A pair of successive * percent signs designates a single percent sign in * the format. * @param fmtArg Control string. * @exception IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(Locale locale, String fmtArg) throws IllegalArgumentException { dfs = new DecimalFormatSymbols(locale); int ePos = 0; ConversionSpecification sFmt = null; String unCS = this.nonControl(fmtArg, 0); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.addElement(sFmt); } while ((cPos != -1) && (cPos < fmtArg.length())) { for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) { char c = 0; c = fmtArg.charAt(ePos); if (c == 'i') { break; } if (c == 'd') { break; } if (c == 'f') { break; } if (c == 'g') { break; } if (c == 'G') { break; } if (c == 'o') { break; } if (c == 'x') { break; } if (c == 'X') { break; } if (c == 'e') { break; } if (c == 'E') { break; } if (c == 'c') { break; } if (c == 's') { break; } if (c == '%') { break; } } ePos = Math.min(ePos + 1, fmtArg.length()); sFmt = new ConversionSpecification(fmtArg.substring(cPos, ePos)); vFmt.addElement(sFmt); unCS = this.nonControl(fmtArg, ePos); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.addElement(sFmt); } } } /** * Return a substring starting at *start
and ending at either the end
* of the String s
, the next unpaired
* percent sign, or at the end of the String if the
* last character is a percent sign.
* @param s Control string.
* @param start Position in the string
* s
to begin looking for the start
* of a control string.
* @return the substring from the start position
* to the beginning of the control string.
*/
private String nonControl(String s, int start)
{
String ret = "";
cPos = s.indexOf("%", start);
if (cPos == -1)
{
cPos = s.length();
}
return s.substring(start, cPos);
}
/**
* Format an array of objects. Byte, Short,
* Integer, Long, Float, Double, and Character
* arguments are treated as wrappers for primitive
* types.
* @param o The array of objects to format.
* @return The formatted String.
*/
public String sprintf(Object[] o)
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
int i = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
if (cs.isPositionalSpecification())
{
i = cs.getArgumentPosition() - 1;
if (cs.isPositionalFieldWidth())
{
int ifw = cs.getArgumentPositionForFieldWidth() - 1;
cs.setFieldWidthWithArg(((Integer) o[ifw]).intValue());
}
if (cs.isPositionalPrecision())
{
int ipr = cs.getArgumentPositionForPrecision() - 1;
cs.setPrecisionWithArg(((Integer) o[ipr]).intValue());
}
} else
{
if (cs.isVariableFieldWidth())
{
cs.setFieldWidthWithArg(((Integer) o[i]).intValue());
i++;
}
if (cs.isVariablePrecision())
{
cs.setPrecisionWithArg(((Integer) o[i]).intValue());
i++;
}
}
if (o[i] instanceof Byte)
{
sb.append(cs.internalsprintf(((Byte) o[i]).byteValue()));
} else if (o[i] instanceof Short)
{
sb.append(cs.internalsprintf(((Short) o[i]).shortValue()));
} else if (o[i] instanceof Integer)
{
sb.append(cs.internalsprintf(((Integer) o[i]).intValue()));
} else if (o[i] instanceof Long)
{
sb.append(cs.internalsprintf(((Long) o[i]).longValue()));
} else if (o[i] instanceof Float)
{
sb.append(cs.internalsprintf(((Float) o[i]).floatValue()));
} else if (o[i] instanceof Double)
{
sb.append(cs.internalsprintf(((Double) o[i]).doubleValue()));
} else if (o[i] instanceof Character)
{
sb.append(cs.internalsprintf(((Character) o[i]).charValue()));
} else if (o[i] instanceof String)
{
sb.append(cs.internalsprintf((String) o[i]));
} else
{
sb.append(cs.internalsprintf(o[i]));
}
if (!cs.isPositionalSpecification())
{
i++;
}
}
}
return sb.toString();
}
/**
* Format nothing. Just use the control string.
* @return the formatted String.
*/
public String sprintf()
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
}
}
return sb.toString();
}
/**
* Format an int.
* @param x The int to format.
* @return The formatted String.
* @exception IllegalArgumentException if the
* conversion character is f, e, E, g, G, s,
* or S.
*/
public String sprintf(int x) throws IllegalArgumentException
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
sb.append(cs.internalsprintf(x));
}
}
return sb.toString();
}
/**
* Format an long.
* @param x The long to format.
* @return The formatted String.
* @exception IllegalArgumentException if the
* conversion character is f, e, E, g, G, s,
* or S.
*/
public String sprintf(long x) throws IllegalArgumentException
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
sb.append(cs.internalsprintf(x));
}
}
return sb.toString();
}
/**
* Format a double.
* @param x The double to format.
* @return The formatted String.
* @exception IllegalArgumentException if the
* conversion character is c, C, s, S,
* d, d, x, X, or o.
*/
public String sprintf(double x) throws IllegalArgumentException
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
sb.append(cs.internalsprintf(x));
}
}
return sb.toString();
}
/**
* Format a String.
* @param x The String to format.
* @return The formatted String.
* @exception IllegalArgumentException if the
* conversion character is neither s nor S.
*/
public String sprintf(String x) throws IllegalArgumentException
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
sb.append(cs.internalsprintf(x));
}
}
return sb.toString();
}
/**
* Format an Object. Convert wrapper types to
* their primitive equivalents and call the
* appropriate internal formatting method. Convert
* Strings using an internal formatting method for
* Strings. Otherwise use the default formatter
* (use toString).
* @param x the Object to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is inappropriate for
* formatting an unwrapped value.
*/
public String sprintf(Object x) throws IllegalArgumentException
{
Enumeration e = vFmt.elements();
ConversionSpecification cs = null;
char c = 0;
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements())
{
cs = (ConversionSpecification) e.nextElement();
c = cs.getConversionCharacter();
if (c == '\0')
{
sb.append(cs.getLiteral());
} else if (c == '%')
{
sb.append("%");
} else
{
if (x instanceof Byte)
{
sb.append(cs.internalsprintf(((Byte) x).byteValue()));
} else if (x instanceof Short)
{
sb.append(cs.internalsprintf(((Short) x).shortValue()));
} else if (x instanceof Integer)
{
sb.append(cs.internalsprintf(((Integer) x).intValue()));
} else if (x instanceof Long)
{
sb.append(cs.internalsprintf(((Long) x).longValue()));
} else if (x instanceof Float)
{
sb.append(cs.internalsprintf(((Float) x).floatValue()));
} else if (x instanceof Double)
{
sb.append(cs.internalsprintf(((Double) x).doubleValue()));
} else if (x instanceof Character)
{
sb.append(cs.internalsprintf(((Character) x).charValue()));
} else if (x instanceof String)
{
sb.append(cs.internalsprintf((String) x));
} else
{
sb.append(cs.internalsprintf(x));
}
}
}
return sb.toString();
}
/**
* * ConversionSpecification allows the formatting of * a single primitive or object embedded within a * string. The formatting is controlled by a * format string. Only one Java primitive or * object can be formatted at a time. *
* A format string is a Java string that contains * a control string. The control string starts at * the first percent sign (%) in the string, * provided that this percent sign *
* A control string takes the form: *
% ['-+ #0]* [0..9]* { . [0..9]* }+ * { [hlL] }+ [idfgGoxXeEcs] **
* The behavior is like printf. One (hopefully the
* only) exception is that the minimum number of
* exponent digits is 3 instead of 2 for e and E
* formats when the optional L is used before the
* e, E, g, or G conversion character. The
* optional L does not imply conversion to a long
* long double.
*/
private class ConversionSpecification
{
/** Default precision. */
private final static int defaultDigits = 6;
/**
* The integer portion of the result of a decimal
* conversion (i, d, u, f, g, or G) will be
* formatted with thousands' grouping characters.
* For other conversions the flag is ignored.
*/
private boolean thousands = false;
/**
* The result of the conversion will be
* left-justified within the field.
*/
private boolean leftJustify = false;
/**
* The result of a signed conversion will always
* begin with a sign (+ or -).
*/
private boolean leadingSign = false;
/**
* Flag indicating that left padding with spaces is
* specified.
*/
private boolean leadingSpace = false;
/**
* For an o conversion, increase the precision to
* force the first digit of the result to be a
* zero. For x (or X) conversions, a non-zero
* result will have 0x (or 0X) prepended to it.
* For e, E, f, g, or G conversions, the result
* will always contain a radix character, even if
* no digits follow the point. For g and G
* conversions, trailing zeros will not be removed
* from the result.
*/
private boolean alternateForm = false;
/**
* Flag indicating that left padding with zeroes is
* specified.
*/
private boolean leadingZeros = false;
/**
* Flag indicating that the field width is *.
*/
private boolean variableFieldWidth = false;
/**
* If the converted value has fewer bytes than the
* field width, it will be padded with spaces or
* zeroes.
*/
private int fieldWidth = 0;
/**
* Flag indicating whether or not the field width
* has been set.
*/
private boolean fieldWidthSet = false;
/**
* The minimum number of digits to appear for the
* d, i, o, u, x, or X conversions. The number of
* digits to appear after the radix character for
* the e, E, and f conversions. The maximum number
* of significant digits for the g and G
* conversions. The maximum number of bytes to be
* printed from a string in s and S conversions.
*/
private int precision = 0;
/**
* Flag indicating that the precision is *.
*/
private boolean variablePrecision = false;
/**
* Flag indicating whether or not the precision has
* been set.
*/
private boolean precisionSet = false;
/*
*/
private boolean positionalSpecification = false;
private int argumentPosition = 0;
private boolean positionalFieldWidth = false;
private int argumentPositionForFieldWidth = 0;
private boolean positionalPrecision = false;
private int argumentPositionForPrecision = 0;
/**
* Flag specifying that a following d, i, o, u, x,
* or X conversion character applies to a type
* short int.
*/
private boolean optionalh = false;
/**
* Flag specifying that a following d, i, o, u, x,
* or X conversion character applies to a type lont
* int argument.
*/
private boolean optionall = false;
/**
* Flag specifying that a following e, E, f, g, or
* G conversion character applies to a type double
* argument. This is a noop in Java.
*/
private boolean optionalL = false;
/** Control string type. */
private char conversionCharacter = '\0';
/**
* Position within the control string. Used by
* the constructor.
*/
private int pos = 0;
/** Literal or control format string. */
private String fmt;
/**
* Constructor. Used to prepare an instance
* to hold a literal, not a control string.
*/
ConversionSpecification()
{
}
/**
* Constructor for a conversion specification.
* The argument must begin with a % and end
* with the conversion character for the
* conversion specification.
* @param fmtArg String specifying the
* conversion specification.
* @exception IllegalArgumentException if the
* input string is null, zero length, or
* otherwise malformed.
*/
ConversionSpecification(String fmtArg) throws IllegalArgumentException
{
if (fmtArg == null)
{
throw new NullPointerException();
}
if (fmtArg.length() == 0)
{
throw new IllegalArgumentException("Control strings must have positive" + " lengths.");
}
if (fmtArg.charAt(0) == '%')
{
fmt = fmtArg;
pos = 1;
setArgPosition();
setFlagCharacters();
setFieldWidth();
setPrecision();
setOptionalHL();
if (setConversionCharacter())
{
if (pos == fmtArg.length())
{
if (leadingZeros && leftJustify)
{
leadingZeros = false;
}
if (precisionSet && leadingZeros)
{
if ((conversionCharacter == 'd') || (conversionCharacter == 'i') || (conversionCharacter == 'o')
|| (conversionCharacter == 'x'))
{
leadingZeros = false;
}
}
} else
{
throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg);
}
} else
{
throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg);
}
} else
{
throw new IllegalArgumentException("Control strings must begin with %.");
}
}
/**
* Set the String for this instance.
* @param s the String to store.
*/
void setLiteral(String s)
{
fmt = s;
}
/**
* Get the String for this instance. Translate
* any escape sequences.
*
* @return s the stored String.
*/
String getLiteral()
{
StringBuffer sb = new StringBuffer();
int i = 0;
while (i < fmt.length())
{
if (fmt.charAt(i) == '\\')
{
i++;
if (i < fmt.length())
{
char c = fmt.charAt(i);
switch (c)
{
case 'a' :
sb.append((char) 0x07);
break;
case 'b' :
sb.append('\b');
break;
case 'f' :
sb.append('\f');
break;
case 'n' :
sb.append(System.getProperty("line.separator"));
break;
case 'r' :
sb.append('\r');
break;
case 't' :
sb.append('\t');
break;
case 'v' :
sb.append((char) 0x0b);
break;
case '\\' :
sb.append('\\');
break;
}
i++;
} else
{
sb.append('\\');
}
} else
{
i++;
}
}
return fmt;
}
/**
* Get the conversion character that tells what
* type of control character this instance has.
*
* @return the conversion character.
*/
char getConversionCharacter()
{
return conversionCharacter;
}
/**
* Check whether the specifier has a variable
* field width that is going to be set by an
* argument.
* @return true
if the conversion
* uses an * field width; otherwise
* false
.
*/
boolean isVariableFieldWidth()
{
return variableFieldWidth;
}
/**
* Set the field width with an argument. A
* negative field width is taken as a - flag
* followed by a positive field width.
* @param fw the field width.
*/
void setFieldWidthWithArg(int fw)
{
if (fw < 0)
{
leftJustify = true;
}
fieldWidthSet = true;
fieldWidth = Math.abs(fw);
}
/**
* Check whether the specifier has a variable
* precision that is going to be set by an
* argument.
* @return true
if the conversion
* uses an * precision; otherwise
* false
.
*/
boolean isVariablePrecision()
{
return variablePrecision;
}
/**
* Set the precision with an argument. A
* negative precision will be changed to zero.
* @param pr the precision.
*/
void setPrecisionWithArg(int pr)
{
precisionSet = true;
precision = Math.max(pr, 0);
}
/**
* Format an int argument using this conversion
* specification.
* @param s the int to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is f, e, E, g, or G.
*/
String internalsprintf(int s) throws IllegalArgumentException
{
String s2 = "";
switch (conversionCharacter)
{
case 'd' :
case 'i' :
if (optionalh)
{
s2 = printDFormat((short) s);
} else if (optionall)
{
s2 = printDFormat((long) s);
} else
{
s2 = printDFormat(s);
}
break;
case 'x' :
case 'X' :
if (optionalh)
{
s2 = printXFormat((short) s);
} else if (optionall)
{
s2 = printXFormat((long) s);
} else
{
s2 = printXFormat(s);
}
break;
case 'o' :
if (optionalh)
{
s2 = printOFormat((short) s);
} else if (optionall)
{
s2 = printOFormat((long) s);
} else
{
s2 = printOFormat(s);
}
break;
case 'c' :
case 'C' :
s2 = printCFormat((char) s);
break;
default :
throw new IllegalArgumentException("Cannot format a int with a format using a " + conversionCharacter
+ " conversion character.");
}
return s2;
}
/**
* Format a long argument using this conversion
* specification.
* @param s the long to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is f, e, E, g, or G.
*/
String internalsprintf(long s) throws IllegalArgumentException
{
String s2 = "";
switch (conversionCharacter)
{
case 'd' :
case 'i' :
if (optionalh)
{
s2 = printDFormat((short) s);
} else if (optionall)
{
s2 = printDFormat(s);
} else
{
s2 = printDFormat((int) s);
}
break;
case 'x' :
case 'X' :
if (optionalh)
{
s2 = printXFormat((short) s);
} else if (optionall)
{
s2 = printXFormat(s);
} else
{
s2 = printXFormat((int) s);
}
break;
case 'o' :
if (optionalh)
{
s2 = printOFormat((short) s);
} else if (optionall)
{
s2 = printOFormat(s);
} else
{
s2 = printOFormat((int) s);
}
break;
case 'c' :
case 'C' :
s2 = printCFormat((char) s);
break;
default :
throw new IllegalArgumentException("Cannot format a long with a format using a " + conversionCharacter
+ " conversion character.");
}
return s2;
}
/**
* Format a double argument using this conversion
* specification.
* @param s the double to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is c, C, s, S, i, d,
* x, X, or o.
*/
String internalsprintf(double s) throws IllegalArgumentException
{
String s2 = "";
switch (conversionCharacter)
{
case 'f' :
s2 = printFFormat(s);
break;
case 'E' :
case 'e' :
s2 = printEFormat(s);
break;
case 'G' :
case 'g' :
s2 = printGFormat(s);
break;
default :
throw new IllegalArgumentException("Cannot " + "format a double with a format using a " + conversionCharacter
+ " conversion character.");
}
return s2;
}
/**
* Format a String argument using this conversion
* specification.
* @param s the String to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is neither s nor S.
*/
String internalsprintf(String s) throws IllegalArgumentException
{
String s2 = "";
if ((conversionCharacter == 's') || (conversionCharacter == 'S'))
{
s2 = printSFormat(s);
} else
{
throw new IllegalArgumentException("Cannot " + "format a String with a format using a " + conversionCharacter
+ " conversion character.");
}
return s2;
}
/**
* Format an Object argument using this conversion
* specification.
* @param s the Object to format.
* @return the formatted String.
* @exception IllegalArgumentException if the
* conversion character is neither s nor S.
*/
String internalsprintf(Object s)
{
String s2 = "";
if ((conversionCharacter == 's') || (conversionCharacter == 'S'))
{
s2 = printSFormat(s.toString());
} else
{
throw new IllegalArgumentException("Cannot format a String with a format using" + " a " + conversionCharacter
+ " conversion character.");
}
return s2;
}
/**
* For f format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both
* a '+' and a ' ' are specified, the blank flag
* is ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the number of digits
* to appear after the radix character. Padding is
* with trailing 0s.
*/
private char[] fFormatDigits(double x)
{
// int defaultDigits=6;
String sx, sxOut;
int i, j, k;
int n1In, n2In;
int expon = 0;
boolean minusSign = false;
if (x > 0.0)
{
sx = Double.toString(x);
} else if (x < 0.0)
{
sx = Double.toString(-x);
minusSign = true;
} else
{
sx = Double.toString(x);
if (sx.charAt(0) == '-')
{
minusSign = true;
sx = sx.substring(1);
}
}
int ePos = sx.indexOf('E');
int rPos = sx.indexOf('.');
if (rPos != -1)
{
n1In = rPos;
} else if (ePos != -1)
{
n1In = ePos;
} else
{
n1In = sx.length();
}
if (rPos != -1)
{
if (ePos != -1)
{
n2In = ePos - rPos - 1;
} else
{
n2In = sx.length() - rPos - 1;
}
} else
{
n2In = 0;
}
if (ePos != -1)
{
int ie = ePos + 1;
expon = 0;
if (sx.charAt(ie) == '-')
{
for (++ie; ie < sx.length(); ie++)
{
if (sx.charAt(ie) != '0')
{
break;
}
}
if (ie < sx.length())
{
expon = -Integer.parseInt(sx.substring(ie));
}
} else
{
if (sx.charAt(ie) == '+')
{
++ie;
}
for (; ie < sx.length(); ie++)
{
if (sx.charAt(ie) != '0')
{
break;
}
}
if (ie < sx.length())
{
expon = Integer.parseInt(sx.substring(ie));
}
}
}
int p;
if (precisionSet)
{
p = precision;
} else
{
p = defaultDigits - 1;
}
char[] ca1 = sx.toCharArray();
char[] ca2 = new char[n1In + n2In];
char[] ca3, ca4, ca5;
for (j = 0; j < n1In; j++)
{
ca2[j] = ca1[j];
}
i = j + 1;
for (k = 0; k < n2In; j++, i++, k++)
{
ca2[j] = ca1[i];
}
if (n1In + expon <= 0)
{
ca3 = new char[-expon + n2In];
for (j = 0, k = 0; k < (-n1In - expon); k++, j++)
{
ca3[j] = '0';
}
for (i = 0; i < (n1In + n2In); i++, j++)
{
ca3[j] = ca2[i];
}
} else
{
ca3 = ca2;
}
boolean carry = false;
if (p < -expon + n2In)
{
if (expon < 0)
{
i = p;
} else
{
i = p + n1In;
}
carry = checkForCarry(ca3, i);
if (carry)
{
carry = startSymbolicCarry(ca3, i - 1, 0);
}
}
if (n1In + expon <= 0)
{
ca4 = new char[2 + p];
if (!carry)
{
ca4[0] = '0';
} else
{
ca4[0] = '1';
}
if (alternateForm ||!precisionSet || (precision != 0))
{
ca4[1] = '.';
for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++)
{
ca4[j] = ca3[i];
}
for (; j < ca4.length; j++)
{
ca4[j] = '0';
}
}
} else
{
if (!carry)
{
if (alternateForm ||!precisionSet || (precision != 0))
{
ca4 = new char[n1In + expon + p + 1];
} else
{
ca4 = new char[n1In + expon];
}
j = 0;
} else
{
if (alternateForm ||!precisionSet || (precision != 0))
{
ca4 = new char[n1In + expon + p + 2];
} else
{
ca4 = new char[n1In + expon + 1];
}
ca4[0] = '1';
j = 1;
}
for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++)
{
ca4[j] = ca3[i];
}
for (; i < n1In + expon; i++, j++)
{
ca4[j] = '0';
}
if (alternateForm ||!precisionSet || (precision != 0))
{
ca4[j] = '.';
j++;
for (k = 0; (i < ca3.length) && (k < p); i++, j++, k++)
{
ca4[j] = ca3[i];
}
for (; j < ca4.length; j++)
{
ca4[j] = '0';
}
}
}
int nZeros = 0;
if (!leftJustify && leadingZeros)
{
int xThousands = 0;
if (thousands)
{
int xlead = 0;
if ((ca4[0] == '+') || (ca4[0] == '-') || (ca4[0] == ' '))
{
xlead = 1;
}
int xdp = xlead;
for (; xdp < ca4.length; xdp++)
{
if (ca4[xdp] == '.')
{
break;
}
}
xThousands = (xdp - xlead) / 3;
}
if (fieldWidthSet)
{
nZeros = fieldWidth - ca4.length;
}
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
{
nZeros--;
}
nZeros -= xThousands;
if (nZeros < 0)
{
nZeros = 0;
}
}
j = 0;
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
{
ca5 = new char[ca4.length + nZeros + 1];
j++;
} else
{
ca5 = new char[ca4.length + nZeros];
}
if (!minusSign)
{
if (leadingSign)
{
ca5[0] = '+';
}
if (leadingSpace)
{
ca5[0] = ' ';
}
} else
{
ca5[0] = '-';
}
for (i = 0; i < nZeros; i++, j++)
{
ca5[j] = '0';
}
for (i = 0; i < ca4.length; i++, j++)
{
ca5[j] = ca4[i];
}
int lead = 0;
if ((ca5[0] == '+') || (ca5[0] == '-') || (ca5[0] == ' '))
{
lead = 1;
}
int dp = lead;
for (; dp < ca5.length; dp++)
{
if (ca5[dp] == '.')
{
break;
}
}
int nThousands = (dp - lead) / 3;
// Localize the decimal point.
if (dp < ca5.length)
{
ca5[dp] = dfs.getDecimalSeparator();
}
char[] ca6 = ca5;
if (thousands && (nThousands > 0))
{
ca6 = new char[ca5.length + nThousands + lead];
ca6[0] = ca5[0];
for (i = lead, k = lead; i < dp; i++)
{
if ((i > 0) && (dp - i) % 3 == 0)
{
// ca6[k]=',';
ca6[k] = dfs.getGroupingSeparator();
ca6[k + 1] = ca5[i];
k += 2;
} else
{
ca6[k] = ca5[i];
k++;
}
}
for (; i < ca5.length; i++, k++)
{
ca6[k] = ca5[i];
}
}
return ca6;
}
/**
* An intermediate routine on the way to creating
* an f format String. The method decides whether
* the input double value is an infinity,
* not-a-number, or a finite double and formats
* each type of input appropriately.
* @param x the double value to be formatted.
* @return the converted double value.
*/
private String fFormatString(double x)
{
boolean noDigits = false;
char[] ca6, ca7;
if (Double.isInfinite(x))
{
if (x == Double.POSITIVE_INFINITY)
{
if (leadingSign)
{
ca6 = "+Inf".toCharArray();
} else if (leadingSpace)
{
ca6 = " Inf".toCharArray();
} else
{
ca6 = "Inf".toCharArray();
}
} else
{
ca6 = "-Inf".toCharArray();
}
noDigits = true;
} else if (Double.isNaN(x))
{
if (leadingSign)
{
ca6 = "+NaN".toCharArray();
} else if (leadingSpace)
{
ca6 = " NaN".toCharArray();
} else
{
ca6 = "NaN".toCharArray();
}
noDigits = true;
} else
{
ca6 = fFormatDigits(x);
}
ca7 = applyFloatPadding(ca6, false);
return new String(ca7);
}
/**
* For e format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both a
* '+' and a ' ' are specified, the blank flag is
* ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear after the radix character.
* Padding is with trailing 0s.
*
* The behavior is like printf. One (hopefully the
* only) exception is that the minimum number of
* exponent digits is 3 instead of 2 for e and E
* formats when the optional L is used before the
* e, E, g, or G conversion character. The optional
* L does not imply conversion to a long long
* double.
*/
private char[] eFormatDigits(double x, char eChar)
{
char[] ca1, ca2, ca3;
// int defaultDigits=6;
String sx, sxOut;
int i, j, k, p;
int n1In, n2In;
int expon = 0;
int ePos, rPos, eSize;
boolean minusSign = false;
if (x > 0.0)
{
sx = Double.toString(x);
} else if (x < 0.0)
{
sx = Double.toString(-x);
minusSign = true;
} else
{
sx = Double.toString(x);
if (sx.charAt(0) == '-')
{
minusSign = true;
sx = sx.substring(1);
}
}
ePos = sx.indexOf('E');
if (ePos == -1)
{
ePos = sx.indexOf('e');
}
rPos = sx.indexOf('.');
if (rPos != -1)
{
n1In = rPos;
} else if (ePos != -1)
{
n1In = ePos;
} else
{
n1In = sx.length();
}
if (rPos != -1)
{
if (ePos != -1)
{
n2In = ePos - rPos - 1;
} else
{
n2In = sx.length() - rPos - 1;
}
} else
{
n2In = 0;
}
if (ePos != -1)
{
int ie = ePos + 1;
expon = 0;
if (sx.charAt(ie) == '-')
{
for (++ie; ie < sx.length(); ie++)
{
if (sx.charAt(ie) != '0')
{
break;
}
}
if (ie < sx.length())
{
expon = -Integer.parseInt(sx.substring(ie));
}
} else
{
if (sx.charAt(ie) == '+')
{
++ie;
}
for (; ie < sx.length(); ie++)
{
if (sx.charAt(ie) != '0')
{
break;
}
}
if (ie < sx.length())
{
expon = Integer.parseInt(sx.substring(ie));
}
}
}
if (rPos != -1)
{
expon += rPos - 1;
}
if (precisionSet)
{
p = precision;
} else
{
p = defaultDigits - 1;
}
if ((rPos != -1) && (ePos != -1))
{
ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1, ePos)).toCharArray();
} else if (rPos != -1)
{
ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1)).toCharArray();
} else if (ePos != -1)
{
ca1 = sx.substring(0, ePos).toCharArray();
} else
{
ca1 = sx.toCharArray();
}
boolean carry = false;
int i0 = 0;
if (ca1[0] != '0')
{
i0 = 0;
} else
{
for (i0 = 0; i0 < ca1.length; i0++)
{
if (ca1[i0] != '0')
{
break;
}
}
}
if (i0 + p < ca1.length - 1)
{
carry = checkForCarry(ca1, i0 + p + 1);
if (carry)
{
carry = startSymbolicCarry(ca1, i0 + p, i0);
}
if (carry)
{
ca2 = new char[i0 + p + 1];
ca2[i0] = '1';
for (j = 0; j < i0; j++)
{
ca2[j] = '0';
}
for (i = i0, j = i0 + 1; j < p + 1; i++, j++)
{
ca2[j] = ca1[i];
}
expon++;
ca1 = ca2;
}
}
if ((Math.abs(expon) < 100) &&!optionalL)
{
eSize = 4;
} else
{
eSize = 5;
}
if (alternateForm ||!precisionSet || (precision != 0))
{
ca2 = new char[2 + p + eSize];
} else
{
ca2 = new char[1 + eSize];
}
if (ca1[0] != '0')
{
ca2[0] = ca1[0];
j = 1;
} else
{
for (j = 1; j < ((ePos == -1)
? ca1.length
: ePos); j++)
{
if (ca1[j] != '0')
{
break;
}
}
if (((ePos != -1) && (j < ePos)) || ((ePos == -1) && (j < ca1.length)))
{
ca2[0] = ca1[j];
expon -= j;
j++;
} else
{
ca2[0] = '0';
j = 2;
}
}
if (alternateForm ||!precisionSet || (precision != 0))
{
ca2[1] = '.';
i = 2;
} else
{
i = 1;
}
for (k = 0; (k < p) && (j < ca1.length); j++, i++, k++)
{
ca2[i] = ca1[j];
}
for (; i < ca2.length - eSize; i++)
{
ca2[i] = '0';
}
ca2[i++] = eChar;
if (expon < 0)
{
ca2[i++] = '-';
} else
{
ca2[i++] = '+';
}
expon = Math.abs(expon);
if (expon >= 100)
{
switch (expon / 100)
{
case 1 :
ca2[i] = '1';
break;
case 2 :
ca2[i] = '2';
break;
case 3 :
ca2[i] = '3';
break;
case 4 :
ca2[i] = '4';
break;
case 5 :
ca2[i] = '5';
break;
case 6 :
ca2[i] = '6';
break;
case 7 :
ca2[i] = '7';
break;
case 8 :
ca2[i] = '8';
break;
case 9 :
ca2[i] = '9';
break;
}
i++;
}
switch ((expon % 100) / 10)
{
case 0 :
ca2[i] = '0';
break;
case 1 :
ca2[i] = '1';
break;
case 2 :
ca2[i] = '2';
break;
case 3 :
ca2[i] = '3';
break;
case 4 :
ca2[i] = '4';
break;
case 5 :
ca2[i] = '5';
break;
case 6 :
ca2[i] = '6';
break;
case 7 :
ca2[i] = '7';
break;
case 8 :
ca2[i] = '8';
break;
case 9 :
ca2[i] = '9';
break;
}
i++;
switch (expon % 10)
{
case 0 :
ca2[i] = '0';
break;
case 1 :
ca2[i] = '1';
break;
case 2 :
ca2[i] = '2';
break;
case 3 :
ca2[i] = '3';
break;
case 4 :
ca2[i] = '4';
break;
case 5 :
ca2[i] = '5';
break;
case 6 :
ca2[i] = '6';
break;
case 7 :
ca2[i] = '7';
break;
case 8 :
ca2[i] = '8';
break;
case 9 :
ca2[i] = '9';
break;
}
int nZeros = 0;
if (!leftJustify && leadingZeros)
{
int xThousands = 0;
if (thousands)
{
int xlead = 0;
if ((ca2[0] == '+') || (ca2[0] == '-') || (ca2[0] == ' '))
{
xlead = 1;
}
int xdp = xlead;
for (; xdp < ca2.length; xdp++)
{
if (ca2[xdp] == '.')
{
break;
}
}
xThousands = (xdp - xlead) / 3;
}
if (fieldWidthSet)
{
nZeros = fieldWidth - ca2.length;
}
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
{
nZeros--;
}
nZeros -= xThousands;
if (nZeros < 0)
{
nZeros = 0;
}
}
j = 0;
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
{
ca3 = new char[ca2.length + nZeros + 1];
j++;
} else
{
ca3 = new char[ca2.length + nZeros];
}
if (!minusSign)
{
if (leadingSign)
{
ca3[0] = '+';
}
if (leadingSpace)
{
ca3[0] = ' ';
}
} else
{
ca3[0] = '-';
}
for (k = 0; k < nZeros; j++, k++)
{
ca3[j] = '0';
}
for (i = 0; (i < ca2.length) && (j < ca3.length); i++, j++)
{
ca3[j] = ca2[i];
}
int lead = 0;
if ((ca3[0] == '+') || (ca3[0] == '-') || (ca3[0] == ' '))
{
lead = 1;
}
int dp = lead;
for (; dp < ca3.length; dp++)
{
if (ca3[dp] == '.')
{
break;
}
}
int nThousands = dp / 3;
// Localize the decimal point.
if (dp < ca3.length)
{
ca3[dp] = dfs.getDecimalSeparator();
}
char[] ca4 = ca3;
if (thousands && (nThousands > 0))
{
ca4 = new char[ca3.length + nThousands + lead];
ca4[0] = ca3[0];
for (i = lead, k = lead; i < dp; i++)
{
if ((i > 0) && (dp - i) % 3 == 0)
{
// ca4[k]=',';
ca4[k] = dfs.getGroupingSeparator();
ca4[k + 1] = ca3[i];
k += 2;
} else
{
ca4[k] = ca3[i];
k++;
}
}
for (; i < ca3.length; i++, k++)
{
ca4[k] = ca3[i];
}
}
return ca4;
}
/**
* Check to see if the digits that are going to
* be truncated because of the precision should
* force a round in the preceding digits.
* @param ca1 the array of digits
* @param icarry the index of the first digit that
* is to be truncated from the print
* @return true
if the truncation forces
* a round that will change the print
*/
private boolean checkForCarry(char[] ca1, int icarry)
{
boolean carry = false;
if (icarry < ca1.length)
{
if ((ca1[icarry] == '6') || (ca1[icarry] == '7') || (ca1[icarry] == '8') || (ca1[icarry] == '9'))
{
carry = true;
} else if (ca1[icarry] == '5')
{
int ii = icarry + 1;
for (; ii < ca1.length; ii++)
{
if (ca1[ii] != '0')
{
break;
}
}
carry = ii < ca1.length;
if (!carry && (icarry > 0))
{
carry = ((ca1[icarry - 1] == '1') || (ca1[icarry - 1] == '3') || (ca1[icarry - 1] == '5')
|| (ca1[icarry - 1] == '7') || (ca1[icarry - 1] == '9'));
}
}
}
return carry;
}
/**
* Start the symbolic carry process. The process
* is not quite finished because the symbolic
* carry may change the length of the string and
* change the exponent (in e format).
* @param cLast index of the last digit changed
* by the round
* @param cFirst index of the first digit allowed
* to be changed by this phase of the round
* @return true
if the carry forces
* a round that will change the print still
* more
*/
private boolean startSymbolicCarry(char[] ca, int cLast, int cFirst)
{
boolean carry = true;
for (int i = cLast; carry && (i >= cFirst); i--)
{
carry = false;
switch (ca[i])
{
case '0' :
ca[i] = '1';
break;
case '1' :
ca[i] = '2';
break;
case '2' :
ca[i] = '3';
break;
case '3' :
ca[i] = '4';
break;
case '4' :
ca[i] = '5';
break;
case '5' :
ca[i] = '6';
break;
case '6' :
ca[i] = '7';
break;
case '7' :
ca[i] = '8';
break;
case '8' :
ca[i] = '9';
break;
case '9' :
ca[i] = '0';
carry = true;
break;
}
}
return carry;
}
/**
* An intermediate routine on the way to creating
* an e format String. The method decides whether
* the input double value is an infinity,
* not-a-number, or a finite double and formats
* each type of input appropriately.
* @param x the double value to be formatted.
* @param eChar an 'e' or 'E' to use in the
* converted double value.
* @return the converted double value.
*/
private String eFormatString(double x, char eChar)
{
boolean noDigits = false;
char[] ca4, ca5;
if (Double.isInfinite(x))
{
if (x == Double.POSITIVE_INFINITY)
{
if (leadingSign)
{
ca4 = "+Inf".toCharArray();
} else if (leadingSpace)
{
ca4 = " Inf".toCharArray();
} else
{
ca4 = "Inf".toCharArray();
}
} else
{
ca4 = "-Inf".toCharArray();
}
noDigits = true;
} else if (Double.isNaN(x))
{
if (leadingSign)
{
ca4 = "+NaN".toCharArray();
} else if (leadingSpace)
{
ca4 = " NaN".toCharArray();
} else
{
ca4 = "NaN".toCharArray();
}
noDigits = true;
} else
{
ca4 = eFormatDigits(x, eChar);
}
ca5 = applyFloatPadding(ca4, false);
return new String(ca5);
}
/**
* Apply zero or blank, left or right padding.
* @param ca4 array of characters before padding is
* finished
* @param noDigits NaN or signed Inf
* @return a padded array of characters
*/
private char[] applyFloatPadding(char[] ca4, boolean noDigits)
{
char[] ca5 = ca4;
if (fieldWidthSet)
{
int i, j, nBlanks;
if (leftJustify)
{
nBlanks = fieldWidth - ca4.length;
if (nBlanks > 0)
{
ca5 = new char[ca4.length + nBlanks];
for (i = 0; i < ca4.length; i++)
{
ca5[i] = ca4[i];
}
for (j = 0; j < nBlanks; j++, i++)
{
ca5[i] = ' ';
}
}
} else if (!leadingZeros || noDigits)
{
nBlanks = fieldWidth - ca4.length;
if (nBlanks > 0)
{
ca5 = new char[ca4.length + nBlanks];
for (i = 0; i < nBlanks; i++)
{
ca5[i] = ' ';
}
for (j = 0; j < ca4.length; i++, j++)
{
ca5[i] = ca4[j];
}
}
} else if (leadingZeros)
{
nBlanks = fieldWidth - ca4.length;
if (nBlanks > 0)
{
ca5 = new char[ca4.length + nBlanks];
i = 0;
j = 0;
if (ca4[0] == '-')
{
ca5[0] = '-';
i++;
j++;
}
for (int k = 0; k < nBlanks; i++, k++)
{
ca5[i] = '0';
}
for (; j < ca4.length; i++, j++)
{
ca5[i] = ca4[j];
}
}
}
}
return ca5;
}
/**
* Format method for the f conversion character.
* @param x the double to format.
* @return the formatted String.
*/
private String printFFormat(double x)
{
return fFormatString(x);
}
/**
* Format method for the e or E conversion
* character.
* @param x the double to format.
* @return the formatted String.
*/
private String printEFormat(double x)
{
if (conversionCharacter == 'e')
{
return eFormatString(x, 'e');
} else
{
return eFormatString(x, 'E');
}
}
/**
* Format method for the g conversion character.
*
* For g format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both a
* '+' and a ' ' are specified, the blank flag is
* ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear after the radix character.
* Padding is with trailing 0s.
* @param x the double to format.
* @return the formatted String.
*/
private String printGFormat(double x)
{
String sx, sy, sz, ret;
int savePrecision = precision;
int i;
char[] ca4, ca5;
boolean noDigits = false;
if (Double.isInfinite(x))
{
if (x == Double.POSITIVE_INFINITY)
{
if (leadingSign)
{
ca4 = "+Inf".toCharArray();
} else if (leadingSpace)
{
ca4 = " Inf".toCharArray();
} else
{
ca4 = "Inf".toCharArray();
}
} else
{
ca4 = "-Inf".toCharArray();
}
noDigits = true;
} else if (Double.isNaN(x))
{
if (leadingSign)
{
ca4 = "+NaN".toCharArray();
} else if (leadingSpace)
{
ca4 = " NaN".toCharArray();
} else
{
ca4 = "NaN".toCharArray();
}
noDigits = true;
} else
{
if (!precisionSet)
{
precision = defaultDigits;
}
if (precision == 0)
{
precision = 1;
}
int ePos = -1;
if (conversionCharacter == 'g')
{
sx = eFormatString(x, 'e').trim();
ePos = sx.indexOf('e');
} else
{
sx = eFormatString(x, 'E').trim();
ePos = sx.indexOf('E');
}
i = ePos + 1;
int expon = 0;
if (sx.charAt(i) == '-')
{
for (++i; i < sx.length(); i++)
{
if (sx.charAt(i) != '0')
{
break;
}
}
if (i < sx.length())
{
expon = -Integer.parseInt(sx.substring(i));
}
} else
{
if (sx.charAt(i) == '+')
{
++i;
}
for (; i < sx.length(); i++)
{
if (sx.charAt(i) != '0')
{
break;
}
}
if (i < sx.length())
{
expon = Integer.parseInt(sx.substring(i));
}
}
// Trim trailing zeros.
// If the radix character is not followed by
// a digit, trim it, too.
if (!alternateForm)
{
if ((expon >= -4) && (expon < precision))
{
sy = fFormatString(x).trim();
} else
{
sy = sx.substring(0, ePos);
}
i = sy.length() - 1;
for (; i >= 0; i--)
{
if (sy.charAt(i) != '0')
{
break;
}
}
if ((i >= 0) && (sy.charAt(i) == '.'))
{
i--;
}
if (i == -1)
{
sz = "0";
} else if (!Character.isDigit(sy.charAt(i)))
{
sz = sy.substring(0, i + 1) + "0";
} else
{
sz = sy.substring(0, i + 1);
}
if ((expon >= -4) && (expon < precision))
{
ret = sz;
} else
{
ret = sz + sx.substring(ePos);
}
} else
{
if ((expon >= -4) && (expon < precision))
{
ret = fFormatString(x).trim();
} else
{
ret = sx;
}
}
// leading space was trimmed off during
// construction
if (leadingSpace)
{
if (x >= 0)
{
ret = " " + ret;
}
}
ca4 = ret.toCharArray();
}
// Pad with blanks or zeros.
ca5 = applyFloatPadding(ca4, false);
precision = savePrecision;
return new String(ca5);
}
/**
* Format method for the d conversion specifer and
* short argument.
*
* For d format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. A '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both a
* '+' and a ' ' are specified, the blank flag is
* ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the short to format.
* @return the formatted String.
*/
private String printDFormat(short x)
{
return printDFormat(Short.toString(x));
}
/**
* Format method for the d conversion character and
* long argument.
*
* For d format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. A '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both a
* '+' and a ' ' are specified, the blank flag is
* ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the long to format.
* @return the formatted String.
*/
private String printDFormat(long x)
{
return printDFormat(Long.toString(x));
}
/**
* Format method for the d conversion character and
* int argument.
*
* For d format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. A '+' character means that the conversion
* will always begin with a sign (+ or -). The
* blank flag character means that a non-negative
* input will be preceded with a blank. If both a
* '+' and a ' ' are specified, the blank flag is
* ignored. The '0' flag character implies that
* padding to the field width will be done with
* zeros instead of blanks.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the int to format.
* @return the formatted String.
*/
private String printDFormat(int x)
{
return printDFormat(Integer.toString(x));
}
/**
* Utility method for formatting using the d
* conversion character.
* @param sx the String to format, the result of
* converting a short, int, or long to a
* String.
* @return the formatted String.
*/
private String printDFormat(String sx)
{
int nLeadingZeros = 0;
int nBlanks = 0,
n = 0;
int i = 0,
jFirst = 0;
boolean neg = sx.charAt(0) == '-';
if (sx.equals("0") && precisionSet && (precision == 0))
{
sx = "";
}
if (!neg)
{
if (precisionSet && (sx.length() < precision))
{
nLeadingZeros = precision - sx.length();
}
} else
{
if (precisionSet && (sx.length() - 1) < precision)
{
nLeadingZeros = precision - sx.length() + 1;
}
}
if (nLeadingZeros < 0)
{
nLeadingZeros = 0;
}
if (fieldWidthSet)
{
nBlanks = fieldWidth - nLeadingZeros - sx.length();
if (!neg && (leadingSign || leadingSpace))
{
nBlanks--;
}
}
if (nBlanks < 0)
{
nBlanks = 0;
}
if (leadingSign)
{
n++;
} else if (leadingSpace)
{
n++;
}
n += nBlanks;
n += nLeadingZeros;
n += sx.length();
char[] ca = new char[n];
if (leftJustify)
{
if (neg)
{
ca[i++] = '-';
} else if (leadingSign)
{
ca[i++] = '+';
} else if (leadingSpace)
{
ca[i++] = ' ';
}
char[] csx = sx.toCharArray();
jFirst = neg
? 1
: 0;
for (int j = 0; j < nLeadingZeros; i++, j++)
{
ca[i] = '0';
}
for (int j = jFirst; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
for (int j = 0; j < nBlanks; i++, j++)
{
ca[i] = ' ';
}
} else
{
if (!leadingZeros)
{
for (i = 0; i < nBlanks; i++)
{
ca[i] = ' ';
}
if (neg)
{
ca[i++] = '-';
} else if (leadingSign)
{
ca[i++] = '+';
} else if (leadingSpace)
{
ca[i++] = ' ';
}
} else
{
if (neg)
{
ca[i++] = '-';
} else if (leadingSign)
{
ca[i++] = '+';
} else if (leadingSpace)
{
ca[i++] = ' ';
}
for (int j = 0; j < nBlanks; j++, i++)
{
ca[i] = '0';
}
}
for (int j = 0; j < nLeadingZeros; j++, i++)
{
ca[i] = '0';
}
char[] csx = sx.toCharArray();
jFirst = neg
? 1
: 0;
for (int j = jFirst; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
}
return new String(ca);
}
/**
* Format method for the x conversion character and
* short argument.
*
* For x format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means to lead with
* '0x'.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the short to format.
* @return the formatted String.
*/
private String printXFormat(short x)
{
String sx = null;
if (x == Short.MIN_VALUE)
{
sx = "8000";
} else if (x < 0)
{
String t;
if (x == Short.MIN_VALUE)
{
t = "0";
} else
{
t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 16);
if ((t.charAt(0) == 'F') || (t.charAt(0) == 'f'))
{
t = t.substring(16, 32);
}
}
switch (t.length())
{
case 1 :
sx = "800" + t;
break;
case 2 :
sx = "80" + t;
break;
case 3 :
sx = "8" + t;
break;
case 4 :
switch (t.charAt(0))
{
case '1' :
sx = "9" + t.substring(1, 4);
break;
case '2' :
sx = "a" + t.substring(1, 4);
break;
case '3' :
sx = "b" + t.substring(1, 4);
break;
case '4' :
sx = "c" + t.substring(1, 4);
break;
case '5' :
sx = "d" + t.substring(1, 4);
break;
case '6' :
sx = "e" + t.substring(1, 4);
break;
case '7' :
sx = "f" + t.substring(1, 4);
break;
}
break;
}
} else
{
sx = Integer.toString((int) x, 16);
}
return printXFormat(sx);
}
/**
* Format method for the x conversion character and
* long argument.
*
* For x format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means to lead with
* '0x'.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the long to format.
* @return the formatted String.
*/
private String printXFormat(long x)
{
String sx = null;
if (x == Long.MIN_VALUE)
{
sx = "8000000000000000";
} else if (x < 0)
{
String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 16);
switch (t.length())
{
case 1 :
sx = "800000000000000" + t;
break;
case 2 :
sx = "80000000000000" + t;
break;
case 3 :
sx = "8000000000000" + t;
break;
case 4 :
sx = "800000000000" + t;
break;
case 5 :
sx = "80000000000" + t;
break;
case 6 :
sx = "8000000000" + t;
break;
case 7 :
sx = "800000000" + t;
break;
case 8 :
sx = "80000000" + t;
break;
case 9 :
sx = "8000000" + t;
break;
case 10 :
sx = "800000" + t;
break;
case 11 :
sx = "80000" + t;
break;
case 12 :
sx = "8000" + t;
break;
case 13 :
sx = "800" + t;
break;
case 14 :
sx = "80" + t;
break;
case 15 :
sx = "8" + t;
break;
case 16 :
switch (t.charAt(0))
{
case '1' :
sx = "9" + t.substring(1, 16);
break;
case '2' :
sx = "a" + t.substring(1, 16);
break;
case '3' :
sx = "b" + t.substring(1, 16);
break;
case '4' :
sx = "c" + t.substring(1, 16);
break;
case '5' :
sx = "d" + t.substring(1, 16);
break;
case '6' :
sx = "e" + t.substring(1, 16);
break;
case '7' :
sx = "f" + t.substring(1, 16);
break;
}
break;
}
} else
{
sx = Long.toString(x, 16);
}
return printXFormat(sx);
}
/**
* Format method for the x conversion character and
* int argument.
*
* For x format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means to lead with
* '0x'.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the int to format.
* @return the formatted String.
*/
private String printXFormat(int x)
{
String sx = null;
if (x == Integer.MIN_VALUE)
{
sx = "80000000";
} else if (x < 0)
{
String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 16);
switch (t.length())
{
case 1 :
sx = "8000000" + t;
break;
case 2 :
sx = "800000" + t;
break;
case 3 :
sx = "80000" + t;
break;
case 4 :
sx = "8000" + t;
break;
case 5 :
sx = "800" + t;
break;
case 6 :
sx = "80" + t;
break;
case 7 :
sx = "8" + t;
break;
case 8 :
switch (t.charAt(0))
{
case '1' :
sx = "9" + t.substring(1, 8);
break;
case '2' :
sx = "a" + t.substring(1, 8);
break;
case '3' :
sx = "b" + t.substring(1, 8);
break;
case '4' :
sx = "c" + t.substring(1, 8);
break;
case '5' :
sx = "d" + t.substring(1, 8);
break;
case '6' :
sx = "e" + t.substring(1, 8);
break;
case '7' :
sx = "f" + t.substring(1, 8);
break;
}
break;
}
} else
{
sx = Integer.toString(x, 16);
}
return printXFormat(sx);
}
/**
* Utility method for formatting using the x
* conversion character.
* @param sx the String to format, the result of
* converting a short, int, or long to a
* String.
* @return the formatted String.
*/
private String printXFormat(String sx)
{
int nLeadingZeros = 0;
int nBlanks = 0;
if (sx.equals("0") && precisionSet && (precision == 0))
{
sx = "";
}
if (precisionSet)
{
nLeadingZeros = precision - sx.length();
}
if (nLeadingZeros < 0)
{
nLeadingZeros = 0;
}
if (fieldWidthSet)
{
nBlanks = fieldWidth - nLeadingZeros - sx.length();
if (alternateForm)
{
nBlanks = nBlanks - 2;
}
}
if (nBlanks < 0)
{
nBlanks = 0;
}
int n = 0;
if (alternateForm)
{
n += 2;
}
n += nLeadingZeros;
n += sx.length();
n += nBlanks;
char[] ca = new char[n];
int i = 0;
if (leftJustify)
{
if (alternateForm)
{
ca[i++] = '0';
ca[i++] = 'x';
}
for (int j = 0; j < nLeadingZeros; j++, i++)
{
ca[i] = '0';
}
char[] csx = sx.toCharArray();
for (int j = 0; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
for (int j = 0; j < nBlanks; j++, i++)
{
ca[i] = ' ';
}
} else
{
if (!leadingZeros)
{
for (int j = 0; j < nBlanks; j++, i++)
{
ca[i] = ' ';
}
}
if (alternateForm)
{
ca[i++] = '0';
ca[i++] = 'x';
}
if (leadingZeros)
{
for (int j = 0; j < nBlanks; j++, i++)
{
ca[i] = '0';
}
}
for (int j = 0; j < nLeadingZeros; j++, i++)
{
ca[i] = '0';
}
char[] csx = sx.toCharArray();
for (int j = 0; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
}
String caReturn = new String(ca);
if (conversionCharacter == 'X')
{
caReturn = caReturn.toUpperCase();
}
return caReturn;
}
/**
* Format method for the o conversion character and
* short argument.
*
* For o format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means that the
* output begins with a leading 0 and the precision
* is increased by 1.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the short to format.
* @return the formatted String.
*/
private String printOFormat(short x)
{
String sx = null;
if (x == Short.MIN_VALUE)
{
sx = "100000";
} else if (x < 0)
{
String t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 8);
switch (t.length())
{
case 1 :
sx = "10000" + t;
break;
case 2 :
sx = "1000" + t;
break;
case 3 :
sx = "100" + t;
break;
case 4 :
sx = "10" + t;
break;
case 5 :
sx = "1" + t;
break;
}
} else
{
sx = Integer.toString((int) x, 8);
}
return printOFormat(sx);
}
/**
* Format method for the o conversion character and
* long argument.
*
* For o format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means that the
* output begins with a leading 0 and the precision
* is increased by 1.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the long to format.
* @return the formatted String.
*/
private String printOFormat(long x)
{
String sx = null;
if (x == Long.MIN_VALUE)
{
sx = "1000000000000000000000";
} else if (x < 0)
{
String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 8);
switch (t.length())
{
case 1 :
sx = "100000000000000000000" + t;
break;
case 2 :
sx = "10000000000000000000" + t;
break;
case 3 :
sx = "1000000000000000000" + t;
break;
case 4 :
sx = "100000000000000000" + t;
break;
case 5 :
sx = "10000000000000000" + t;
break;
case 6 :
sx = "1000000000000000" + t;
break;
case 7 :
sx = "100000000000000" + t;
break;
case 8 :
sx = "10000000000000" + t;
break;
case 9 :
sx = "1000000000000" + t;
break;
case 10 :
sx = "100000000000" + t;
break;
case 11 :
sx = "10000000000" + t;
break;
case 12 :
sx = "1000000000" + t;
break;
case 13 :
sx = "100000000" + t;
break;
case 14 :
sx = "10000000" + t;
break;
case 15 :
sx = "1000000" + t;
break;
case 16 :
sx = "100000" + t;
break;
case 17 :
sx = "10000" + t;
break;
case 18 :
sx = "1000" + t;
break;
case 19 :
sx = "100" + t;
break;
case 20 :
sx = "10" + t;
break;
case 21 :
sx = "1" + t;
break;
}
} else
{
sx = Long.toString(x, 8);
}
return printOFormat(sx);
}
/**
* Format method for the o conversion character and
* int argument.
*
* For o format, the flag character '-', means that
* the output should be left justified within the
* field. The default is to pad with blanks on the
* left. The '#' flag character means that the
* output begins with a leading 0 and the precision
* is increased by 1.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is to
* add no padding. Padding is with blanks by
* default.
*
* The precision, if set, is the minimum number of
* digits to appear. Padding is with leading 0s.
* @param x the int to format.
* @return the formatted String.
*/
private String printOFormat(int x)
{
String sx = null;
if (x == Integer.MIN_VALUE)
{
sx = "20000000000";
} else if (x < 0)
{
String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 8);
switch (t.length())
{
case 1 :
sx = "2000000000" + t;
break;
case 2 :
sx = "200000000" + t;
break;
case 3 :
sx = "20000000" + t;
break;
case 4 :
sx = "2000000" + t;
break;
case 5 :
sx = "200000" + t;
break;
case 6 :
sx = "20000" + t;
break;
case 7 :
sx = "2000" + t;
break;
case 8 :
sx = "200" + t;
break;
case 9 :
sx = "20" + t;
break;
case 10 :
sx = "2" + t;
break;
case 11 :
sx = "3" + t.substring(1);
break;
}
} else
{
sx = Integer.toString(x, 8);
}
return printOFormat(sx);
}
/**
* Utility method for formatting using the o
* conversion character.
* @param sx the String to format, the result of
* converting a short, int, or long to a
* String.
* @return the formatted String.
*/
private String printOFormat(String sx)
{
int nLeadingZeros = 0;
int nBlanks = 0;
if (sx.equals("0") && precisionSet && (precision == 0))
{
sx = "";
}
if (precisionSet)
{
nLeadingZeros = precision - sx.length();
}
if (alternateForm)
{
nLeadingZeros++;
}
if (nLeadingZeros < 0)
{
nLeadingZeros = 0;
}
if (fieldWidthSet)
{
nBlanks = fieldWidth - nLeadingZeros - sx.length();
}
if (nBlanks < 0)
{
nBlanks = 0;
}
int n = nLeadingZeros + sx.length() + nBlanks;
char[] ca = new char[n];
int i;
if (leftJustify)
{
for (i = 0; i < nLeadingZeros; i++)
{
ca[i] = '0';
}
char[] csx = sx.toCharArray();
for (int j = 0; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
for (int j = 0; j < nBlanks; j++, i++)
{
ca[i] = ' ';
}
} else
{
if (leadingZeros)
{
for (i = 0; i < nBlanks; i++)
{
ca[i] = '0';
}
} else
{
for (i = 0; i < nBlanks; i++)
{
ca[i] = ' ';
}
}
for (int j = 0; j < nLeadingZeros; j++, i++)
{
ca[i] = '0';
}
char[] csx = sx.toCharArray();
for (int j = 0; j < csx.length; j++, i++)
{
ca[i] = csx[j];
}
}
return new String(ca);
}
/**
* Format method for the c conversion character and
* char argument.
*
* The only flag character that affects c format is
* the '-', meaning that the output should be left
* justified within the field. The default is to
* pad with blanks on the left.
*
* The field width is treated as the minimum number
* of characters to be printed. Padding is with
* blanks by default. The default width is 1.
*
* The precision, if set, is ignored.
* @param x the char to format.
* @return the formatted String.
*/
private String printCFormat(char x)
{
int nPrint = 1;
int width = fieldWidth;
if (!fieldWidthSet)
{
width = nPrint;
}
char[] ca = new char[width];
int i = 0;
if (leftJustify)
{
ca[0] = x;
for (i = 1; i <= width - nPrint; i++)
{
ca[i] = ' ';
}
} else
{
for (i = 0; i < width - nPrint; i++)
{
ca[i] = ' ';
}
ca[i] = x;
}
return new String(ca);
}
/**
* Format method for the s conversion character and
* String argument.
*
* The only flag character that affects s format is
* the '-', meaning that the output should be left
* justified within the field. The default is to
* pad with blanks on the left.
*
* The field width is treated as the minimum number
* of characters to be printed. The default is the
* smaller of the number of characters in the the
* input and the precision. Padding is with blanks
* by default.
*
* The precision, if set, specifies the maximum
* number of characters to be printed from the
* string. A null digit string is treated
* as a 0. The default is not to set a maximum
* number of characters to be printed.
* @param x the String to format.
* @return the formatted String.
*/
private String printSFormat(String x)
{
int nPrint = x.length();
int width = fieldWidth;
if (precisionSet && (nPrint > precision))
{
nPrint = precision;
}
if (!fieldWidthSet)
{
width = nPrint;
}
int n = 0;
if (width > nPrint)
{
n += width - nPrint;
}
if (nPrint >= x.length())
{
n += x.length();
} else
{
n += nPrint;
}
char[] ca = new char[n];
int i = 0;
if (leftJustify)
{
if (nPrint >= x.length())
{
char[] csx = x.toCharArray();
for (i = 0; i < x.length(); i++)
{
ca[i] = csx[i];
}
} else
{
char[] csx = x.substring(0, nPrint).toCharArray();
for (i = 0; i < nPrint; i++)
{
ca[i] = csx[i];
}
}
for (int j = 0; j < width - nPrint; j++, i++)
{
ca[i] = ' ';
}
} else
{
for (i = 0; i < width - nPrint; i++)
{
ca[i] = ' ';
}
if (nPrint >= x.length())
{
char[] csx = x.toCharArray();
for (int j = 0; j < x.length(); i++, j++)
{
ca[i] = csx[j];
}
} else
{
char[] csx = x.substring(0, nPrint).toCharArray();
for (int j = 0; j < nPrint; i++, j++)
{
ca[i] = csx[j];
}
}
}
return new String(ca);
}
/**
* Check for a conversion character. If it is
* there, store it.
* @return true
if the conversion
* character is there, and
* false
otherwise.
*/
private boolean setConversionCharacter()
{
/* idfgGoxXeEcs */
boolean ret = false;
conversionCharacter = '\0';
if (pos < fmt.length())
{
char c = fmt.charAt(pos);
if ((c == 'i') || (c == 'd') || (c == 'f') || (c == 'g') || (c == 'G') || (c == 'o') || (c == 'x') || (c == 'X')
|| (c == 'e') || (c == 'E') || (c == 'c') || (c == 's') || (c == '%'))
{
conversionCharacter = c;
pos++;
ret = true;
}
}
return ret;
}
/**
* Check for an h, l, or L in a format. An L is
* used to control the minimum number of digits
* in an exponent when using floating point
* formats. An l or h is used to control
* conversion of the input to a long or short,
* respectively, before formatting. If any of
* these is present, store them.
*/
private void setOptionalHL()
{
optionalh = false;
optionall = false;
optionalL = false;
if (pos < fmt.length())
{
char c = fmt.charAt(pos);
if (c == 'h')
{
optionalh = true;
pos++;
} else if (c == 'l')
{
optionall = true;
pos++;
} else if (c == 'L')
{
optionalL = true;
pos++;
}
}
}
/**
* Set the precision.
*/
private void setPrecision()
{
int firstPos = pos;
precisionSet = false;
if ((pos < fmt.length()) && (fmt.charAt(pos) == '.'))
{
pos++;
if ((pos < fmt.length()) && (fmt.charAt(pos) == '*'))
{
pos++;
if (!setPrecisionArgPosition())
{
variablePrecision = true;
precisionSet = true;
}
return;
} else
{
while (pos < fmt.length())
{
char c = fmt.charAt(pos);
if (Character.isDigit(c))
{
pos++;
} else
{
break;
}
}
if (pos > firstPos + 1)
{
String sz = fmt.substring(firstPos + 1, pos);
precision = Integer.parseInt(sz);
precisionSet = true;
}
}
}
}
/**
* Set the field width.
*/
private void setFieldWidth()
{
int firstPos = pos;
fieldWidth = 0;
fieldWidthSet = false;
if ((pos < fmt.length()) && (fmt.charAt(pos) == '*'))
{
pos++;
if (!setFieldWidthArgPosition())
{
variableFieldWidth = true;
fieldWidthSet = true;
}
} else
{
while (pos < fmt.length())
{
char c = fmt.charAt(pos);
if (Character.isDigit(c))
{
pos++;
} else
{
break;
}
}
if ((firstPos < pos) && (firstPos < fmt.length()))
{
String sz = fmt.substring(firstPos, pos);
fieldWidth = Integer.parseInt(sz);
fieldWidthSet = true;
}
}
}
/**
* Store the digits n
in %n$ forms.
*/
private void setArgPosition()
{
int xPos;
for (xPos = pos; xPos < fmt.length(); xPos++)
{
if (!Character.isDigit(fmt.charAt(xPos)))
{
break;
}
}
if ((xPos > pos) && (xPos < fmt.length()))
{
if (fmt.charAt(xPos) == '$')
{
positionalSpecification = true;
argumentPosition = Integer.parseInt(fmt.substring(pos, xPos));
pos = xPos + 1;
}
}
}
/**
* Store the digits n
in *n$ forms.
*/
private boolean setFieldWidthArgPosition()
{
boolean ret = false;
int xPos;
for (xPos = pos; xPos < fmt.length(); xPos++)
{
if (!Character.isDigit(fmt.charAt(xPos)))
{
break;
}
}
if ((xPos > pos) && (xPos < fmt.length()))
{
if (fmt.charAt(xPos) == '$')
{
positionalFieldWidth = true;
argumentPositionForFieldWidth = Integer.parseInt(fmt.substring(pos, xPos));
pos = xPos + 1;
ret = true;
}
}
return ret;
}
/**
* Store the digits n
in *n$ forms.
*/
private boolean setPrecisionArgPosition()
{
boolean ret = false;
int xPos;
for (xPos = pos; xPos < fmt.length(); xPos++)
{
if (!Character.isDigit(fmt.charAt(xPos)))
{
break;
}
}
if ((xPos > pos) && (xPos < fmt.length()))
{
if (fmt.charAt(xPos) == '$')
{
positionalPrecision = true;
argumentPositionForPrecision = Integer.parseInt(fmt.substring(pos, xPos));
pos = xPos + 1;
ret = true;
}
}
return ret;
}
boolean isPositionalSpecification()
{
return positionalSpecification;
}
int getArgumentPosition()
{
return argumentPosition;
}
boolean isPositionalFieldWidth()
{
return positionalFieldWidth;
}
int getArgumentPositionForFieldWidth()
{
return argumentPositionForFieldWidth;
}
boolean isPositionalPrecision()
{
return positionalPrecision;
}
int getArgumentPositionForPrecision()
{
return argumentPositionForPrecision;
}
/**
* Set flag characters, one of '-+#0 or a space.
*/
private void setFlagCharacters()
{
/* '-+ #0 */
thousands = false;
leftJustify = false;
leadingSign = false;
leadingSpace = false;
alternateForm = false;
leadingZeros = false;
for (; pos < fmt.length(); pos++)
{
char c = fmt.charAt(pos);
if (c == '\'')
{
thousands = true;
} else if (c == '-')
{
leftJustify = true;
leadingZeros = false;
} else if (c == '+')
{
leadingSign = true;
leadingSpace = false;
} else if (c == ' ')
{
if (!leadingSign)
{
leadingSpace = true;
}
} else if (c == '#')
{
alternateForm = true;
} else if (c == '0')
{
if (!leftJustify)
{
leadingZeros = true;
}
} else
{
break;
}
}
}
}
}