From 41cd6c47b23975098cd155517790e018670785e7 Mon Sep 17 00:00:00 2001 From: Kenneth Russel Date: Mon, 15 Jun 2009 23:12:27 +0000 Subject: Copied JOGL_2_SANDBOX r350 on to trunk; JOGL_2_SANDBOX branch is now closed git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@352 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4 --- src/demos/nurbs/surfaceapp/PrintfFormat.java | 3090 ++++++++++++++++++++++++++ 1 file changed, 3090 insertions(+) create mode 100755 src/demos/nurbs/surfaceapp/PrintfFormat.java (limited to 'src/demos/nurbs/surfaceapp/PrintfFormat.java') diff --git a/src/demos/nurbs/surfaceapp/PrintfFormat.java b/src/demos/nurbs/surfaceapp/PrintfFormat.java new file mode 100755 index 0000000..153460a --- /dev/null +++ b/src/demos/nurbs/surfaceapp/PrintfFormat.java @@ -0,0 +1,3090 @@ +package demos.nurbs.surfaceapp; +// +// (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. +// + + +import java.util.Enumeration; +import java.util.Vector; +import java.util.Locale; +import java.text.DecimalFormatSymbols; + +/** + * 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 + *

    + *
  1. is not escaped protected by a matching % or is + * not an escape % character, + *
  2. is not at the end of the format string, and + *
  3. precedes a sequence of characters that parses as + * a valid control specification. + *
+ *

+ * 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 nth + * 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.

+ * + *

Escape Sequences

+ *

+ * The following table lists escape sequences and + * associated actions on display devices capable of + * the action. + * + * + * + * + * + * + * + * + * + * + * + * + *
SequenceNameDescription
\\backlashNone. + *
\aalertAttempts to alert + * the user through audible or visible + * notification. + *
\bbackspaceMoves the + * printing position to one column before + * the current position, unless the + * current position is the start of a line. + *
\fform-feedMoves the + * printing position to the initial + * printing position of the next logical + * page. + *
\nnewlineMoves the + * printing position to the start of the + * next line. + *
\rcarriage-returnMoves + * the printing position to the start of + * the current line. + *
\ttabMoves the printing + * position to the next implementation- + * defined horizontal tab position. + *
\vvertical-tabMoves the + * printing position to the start of the + * next implementation-defined vertical + * tab position. + *

+ *

Conversion Specifications

+ *

+ * 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.

+ * + *

Flag Characters

+ *

+ * The flags and their meanings are:

+ *
+ *
'
integer portion of the result of a + * decimal conversion (%i, %d, %f, %g, or %G) will + * be formatted with thousands' grouping + * characters. For other conversions the flag + * is ignored. The non-monetary grouping + * character is used. + *
-
result of the conversion is left-justified + * within the field. (It will be right-justified + * if this flag is not specified). + *
+
result of a signed conversion always + * begins with a sign (+ or -). (It will begin + * with a sign only when a negative value is + * converted if this flag is not specified.) + *
<space>
If the first character of a + * signed conversion is not a sign, a space + * character will be placed before the result. + * This means that if the space character and + + * flags both appear, the space flag will be + * ignored. + *
#
value is to be converted to an alternative + * form. For c, d, i, and s conversions, the flag + * has no effect. For o conversion, it increases + * the precision to force the first digit of the + * result to be a zero. For x or X conversion, a + * non-zero result has 0x or 0X prefixed to it, + * respectively. For e, E, f, g, and G + * conversions, the result always contains a radix + * character, even if no digits follow the radix + * character (normally, a decimal point appears in + * the result of these conversions only if a digit + * follows it). For g and G conversions, trailing + * zeros will not be removed from the result as + * they normally are. + *
0
d, i, o, x, X, e, E, f, g, and G + * conversions, leading zeros (following any + * indication of sign or base) are used to pad to + * the field width; no space padding is + * performed. If the 0 and - flags both appear, + * the 0 flag is ignored. For d, i, o, x, and X + * conversions, if a precision is specified, the + * 0 flag will be ignored. For c conversions, + * the flag is ignored. + *
+ * + *

Conversion Characters

+ *

+ * 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: + *

+ *
+ *
d,i
The int argument is converted to a + * signed decimal in the style [-]dddd. The + * precision specifies the minimum number of + * digits to appear; if the value being + * converted can be represented in fewer + * digits, it will be expanded with leading + * zeros. The default precision is 1. The + * result of converting 0 with an explicit + * precision of 0 is no characters. + *
o
The int argument is converted to unsigned + * octal format in the style ddddd. The + * precision specifies the minimum number of + * digits to appear; if the value being + * converted can be represented in fewer + * digits, it will be expanded with leading + * zeros. The default precision is 1. The + * result of converting 0 with an explicit + * precision of 0 is no characters. + *
x
The int argument is converted to unsigned + * hexadecimal format in the style dddd; the + * letters abcdef are used. The precision + * specifies the minimum numberof digits to + * appear; if the value being converted can be + * represented in fewer digits, it will be + * expanded with leading zeros. The default + * precision is 1. The result of converting 0 + * with an explicit precision of 0 is no + * characters. + *
X
Behaves the same as the x conversion + * character except that letters ABCDEF are + * used instead of abcdef. + *
f
The floating point number argument is + * written in decimal notation in the style + * [-]ddd.ddd, where the number of digits after + * the radix character (shown here as a decimal + * point) is equal to the precision + * specification. A Locale is used to determine + * the radix character to use in this format. + * If the precision is omitted from the + * argument, six digits are written after the + * radix character; if the precision is + * explicitly 0 and the # flag is not specified, + * no radix character appears. If a radix + * character appears, at least 1 digit appears + * before it. The value is rounded to the + * appropriate number of digits. + *
e,E
The floating point number argument is + * written in the style [-]d.ddde{+-}dd + * (the symbols {+-} indicate either a plus or + * minus sign), where there is one digit before + * the radix character (shown here as a decimal + * point) and the number of digits after it is + * equal to the precision. A Locale is used to + * determine the radix character to use in this + * format. When the precision is missing, six + * digits are written after the radix character; + * if the precision is 0 and the # flag is not + * specified, no radix character appears. The + * E conversion will produce a number with E + * instead of e introducing the exponent. The + * exponent always contains at least two digits. + * However, if the value to be written requires + * an exponent greater than two digits, + * additional exponent digits are written as + * necessary. The value is rounded to the + * appropriate number of digits. + *
g,G
The floating point number argument is + * written in style f or e (or in sytle E in the + * case of a G conversion character), with the + * precision specifying the number of + * significant digits. If the precision is + * zero, it is taken as one. The style used + * depends on the value converted: style e + * (or E) will be used only if the exponent + * resulting from the conversion is less than + * -4 or greater than or equal to the precision. + * Trailing zeros are removed from the result. + * A radix character appears only if it is + * followed by a digit. + *
c,C
The integer argument is converted to a + * char and the result is written. + * + *
s,S
The argument is taken to be a string and + * bytes from the string are written until the + * end of the string or the number of bytes + * indicated by the precision specification of + * the argument is reached. If the precision + * is omitted from the argument, it is taken to + * be infinite, so all characters up to the end + * of the string are written. + *
%
Write a % character; no argument is + * converted. + *
+ *

+ * 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 class PrintfFormat { + /** + * 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 && cPosstart 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 + *

    + *
  1. is not escaped protected by a matching % or + * is not an escape % character, + *
  2. is not at the end of the format string, and + *
  3. precedes a sequence of characters that parses + * as a valid control string. + *
+ *

+ * 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 { + /** + * 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 (itrue 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; ie0) { + ca6 = new char[ca5.length+nThousands+lead]; + ca6[0]=ca5[0]; + for (i=lead,k=lead; i0 && (dp-i)%3==0) { + // ca6[k]=','; + ca6[k]=dfs.getGroupingSeparator(); + ca6[k+1]=ca5[i]; + k+=2; + } + else { + ca6[k]=ca5[i]; k++; + } + } + for (; i0.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=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 (; xdp0) { + ca4 = new char[ca3.length+nThousands+lead]; + ca4[0]=ca3[0]; + for (i=lead,k=lead; i0 && (dp-i)%3==0) { + // ca4[k]=','; + ca4[k]=dfs.getGroupingSeparator(); + ca4[k+1]=ca3[i]; + k+=2; + } + else { + ca4[k]=ca3[i]; k++; + } + } + for (; itrue if the truncation forces + * a round that will change the print + */ + private boolean checkForCarry(char[] ca1,int icarry) { + boolean carry=false; + if (icarry0) { + 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 0) { + ca5 = new char[ca4.length+nBlanks]; + for (i=0; i 0) { + ca5 = new char[ca4.length+nBlanks]; + i=0; j=0; + if (ca4[0]=='-') { ca5[0]='-'; i++; j++; } + for (int k=0; k=-4 && expon=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=-4 && expon=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) + 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()) { + char[] csx = x.toCharArray(); + for (int j=0; jtrue 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 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 (firstPosn in %n$ forms. + */ + private void setArgPosition() { + int xPos; + for (xPos=pos; xPospos && xPosn in *n$ forms. + */ + private boolean setFieldWidthArgPosition() { + boolean ret=false; + int xPos; + for (xPos=pos; xPospos && xPosn in *n$ forms. + */ + private boolean setPrecisionArgPosition() { + boolean ret=false; + int xPos; + for (xPos=pos; xPospos && xPos