All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.sun.PrintfFormat Maven / Gradle / Ivy

/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * PrintfFormat.java
 * ---------------
 */

package org.jpedal.sun;
//
// (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.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;

/**
 * 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. *
  3. is not at the end of the format string, and *
    precedes a sequence of characters that parses as * a valid control specification.
  4. *
*

*

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

    *
  • ordinary characters, which are simply copied to * the output stream;
  • *
  • escape sequences, which represent non-graphic * characters; and
  • *
  • conversion specifications, each of which * results in the fetching of 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 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:

*
    *
  • %c is the same as %C. *
  • %s is the same as %S. *
  • u, p, and n conversion characters. *
  • %ws format. *
  • h modifier applied to an n conversion character. *
  • l (ell) modifier applied to the c, n, or s * conversion characters. *
  • ll (ell ell) modifier to d, i, o, u, x, or X * conversion characters. *
  • ll (ell ell) modifier to an n conversion * character. *
  • c, C, d,i,o,u,x, and X conversion characters * apply to Byte, Character, Short, Integer, Long * types. *
  • f, e, E, g, and G conversion characters apply * to Float and Double types. *
  • s and S conversion characters apply to String * types. *
  • All other reference types can be formatted * using the s or S conversion characters only. *
*

* 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... */ @SuppressWarnings("ALL") 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. * @throws IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(final 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. * @throws IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(final Locale locale, final String fmtArg) throws IllegalArgumentException { dfs = new DecimalFormatSymbols(locale); int ePos; ConversionSpecification sFmt; String unCS = this.nonControl(fmtArg, 0); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.add(sFmt); } while (cPos != -1 && cPos < fmtArg.length()) { for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) { final char c; 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.add(sFmt); unCS = this.nonControl(fmtArg, ePos); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.add(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(final String s, final 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(final Object[] o) { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; int i = 0; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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()) { final int ifw = cs.getArgumentPositionForFieldWidth() - 1; cs.setFieldWidthWithArg((Integer) o[ifw]); } if (cs.isPositionalPrecision()) { final int ipr = cs.getArgumentPositionForPrecision() - 1; cs.setPrecisionWithArg((Integer) o[ipr]); } } else { if (cs.isVariableFieldWidth()) { cs.setFieldWidthWithArg((Integer) o[i]); i++; } if (cs.isVariablePrecision()) { cs.setPrecisionWithArg((Integer) o[i]); i++; } } if (o[i] instanceof Byte) { sb.append(cs.internalsprintf( ((Number) o[i]).byteValue())); } else if (o[i] instanceof Short) { sb.append(cs.internalsprintf( ((Number) o[i]).shortValue())); } else if (o[i] instanceof Integer) { sb.append(cs.internalsprintf( ((Number) o[i]).intValue())); } else if (o[i] instanceof Long) { sb.append(cs.internalsprintf( ((Number) o[i]).longValue())); } else if (o[i] instanceof Float) { sb.append(cs.internalsprintf( ((Number) o[i]).floatValue())); } else if (o[i] instanceof Double) { sb.append(cs.internalsprintf( ((Number) 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() { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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. * @throws IllegalArgumentException if the * conversion character is f, e, E, g, G, s, * or S. */ public String sprintf(final int x) throws IllegalArgumentException { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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. * @throws IllegalArgumentException if the * conversion character is f, e, E, g, G, s, * or S. */ public String sprintf(final long x) throws IllegalArgumentException { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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. * @throws IllegalArgumentException if the * conversion character is c, C, s, S, * d, d, x, X, or o. */ public String sprintf(final double x) throws IllegalArgumentException { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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. * @throws IllegalArgumentException if the * conversion character is neither s nor S. */ public String sprintf(final String x) throws IllegalArgumentException { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); 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. * @throws IllegalArgumentException if the * conversion character is inappropriate for * formatting an unwrapped value. */ public String sprintf(final Object x) throws IllegalArgumentException { final Iterator e = vFmt.iterator(); ConversionSpecification cs; char c; final StringBuilder sb = new StringBuilder(); while (e.hasNext()) { cs = e.next(); c = cs.getConversionCharacter(); if (c == '\0') { sb.append(cs.getLiteral()); } else if (c == '%') { sb.append('%'); } else { if (x instanceof Byte) { sb.append(cs.internalsprintf( ((Number) x).byteValue())); } else if (x instanceof Short) { sb.append(cs.internalsprintf( ((Number) x).shortValue())); } else if (x instanceof Integer) { sb.append(cs.internalsprintf( ((Number) x).intValue())); } else if (x instanceof Long) { sb.append(cs.internalsprintf( ((Number) x).longValue())); } else if (x instanceof Float) { sb.append(cs.internalsprintf( ((Number) x).floatValue())); } else if (x instanceof Double) { sb.append(cs.internalsprintf( ((Number) 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. * @throws IllegalArgumentException if the * input string is null, zero length, or * otherwise malformed. */ ConversionSpecification(final String fmtArg) throws IllegalArgumentException { if (fmtArg == null) { throw new NullPointerException(); } if (fmtArg.isEmpty()) { 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(final String s) { fmt = s; } /** * Get the String for this instance. Translate * any escape sequences. * * @return s the stored String. */ String getLiteral() { 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(final 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(final 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. * @throws IllegalArgumentException if the * conversion character is f, e, E, g, or G. */ String internalsprintf(final int s) throws IllegalArgumentException { final 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. * @throws IllegalArgumentException if the * conversion character is f, e, E, g, or G. */ String internalsprintf(final long s) throws IllegalArgumentException { final 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. * @throws IllegalArgumentException if the * conversion character is c, C, s, S, i, d, * x, X, or o. */ String internalsprintf(final double s) throws IllegalArgumentException { final 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. * @throws IllegalArgumentException if the * conversion character is neither s nor S. */ String internalsprintf(final String s) throws IllegalArgumentException { final 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. * @throws IllegalArgumentException if the * conversion character is neither s nor S. */ String internalsprintf(final Object s) { final 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(final double x) { // int defaultDigits=6; String sx; //sxOut; int i, j, k; final int n1In; final int 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); } } final int ePos = sx.indexOf('E'); final 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)); } } } final int p; if (precisionSet) { p = precision; } else { p = defaultDigits - 1; } final char[] ca1 = sx.toCharArray(); final char[] ca2 = new char[n1In + n2In]; final char[] ca3; final char[] ca4; final char[] 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; } } final 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(final double x) { //boolean noDigits=false; final char[] ca6; final char[] 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. */ @SuppressWarnings("OverlyLongMethod") private char[] eFormatDigits(final double x, final char eChar) { char[] ca1; char[] ca2; final char[] ca3; // int defaultDigits=6; String sx; //sxOut; int i; int j; int k; final int p; // int n1In,n2In; int expon = 0; int ePos; final int rPos; final int 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; int i0; 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; } } final 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(final char[] ca1, final 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( final char[] ca, final int cLast, final 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(final double x, final char eChar) { //boolean noDigits=false; final char[] ca4; final char[] 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( final char[] ca4, final boolean noDigits) { char[] ca5 = ca4; if (fieldWidthSet) { int i; int j; final int 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(final 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(final 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(final double x) { final String sx; final String sy; final String sz; StringBuffer ret; final int savePrecision = precision; int i; final char[] ca4; final char[] 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; } final int ePos; 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 = new StringBuffer(sz); } else { ret = new StringBuffer(sz); ret.append(sx.substring(ePos)); } } else { if (expon >= -4 && expon < precision) { ret = new StringBuffer(fFormatString(x).trim()); } else { ret = new StringBuffer(sx); } } // leading space was trimmed off during // construction if (leadingSpace) { if (x >= 0) { ret.append(' ').append(ret); } } ca4 = ret.toString().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(final 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(final 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(final 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; final int jFirst; final 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(); final char[] ca = new char[n]; if (leftJustify) { if (neg) { ca[i++] = '-'; } else if (leadingSign) { ca[i++] = '+'; } else if (leadingSpace) { ca[i++] = ' '; } final 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'; } final 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(final 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(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(final long x) { String sx = null; if (x == Long.MIN_VALUE) { sx = "8000000000000000"; } else if (x < 0) { final 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(final int x) { String sx = null; if (x == Integer.MIN_VALUE) { sx = "80000000"; } else if (x < 0) { final 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 -= 2; } } if (nBlanks < 0) { nBlanks = 0; } int n = 0; if (alternateForm) { n += 2; } n += nLeadingZeros; n += sx.length(); n += nBlanks; final 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'; } final 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'; } final 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(final short x) { String sx = null; if (x == Short.MIN_VALUE) { sx = "100000"; } else if (x < 0) { final 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(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(final long x) { String sx = null; if (x == Long.MIN_VALUE) { sx = "1000000000000000000000"; } else if (x < 0) { final 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(final int x) { String sx = null; if (x == Integer.MIN_VALUE) { sx = "20000000000"; } else if (x < 0) { final 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; } final int n = nLeadingZeros + sx.length() + nBlanks; final char[] ca = new char[n]; int i; if (leftJustify) { for (i = 0; i < nLeadingZeros; i++) { ca[i] = '0'; } final 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'; } final 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(final char x) { final int nPrint = 1; int width = fieldWidth; if (!fieldWidthSet) { width = nPrint; } final char[] ca = new char[width]; int i; 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(final 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; } final char[] ca = new char[n]; int i; if (leftJustify) { if (nPrint >= x.length()) { final char[] csx = x.toCharArray(); for (i = 0; i < x.length(); i++) { ca[i] = csx[i]; } } else { final 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()) { final char[] csx = x.toCharArray(); for (int j = 0; j < x.length(); i++, j++) { ca[i] = csx[j]; } } else { final 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()) { final 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()) { final 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() { final 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; } } else { while (pos < fmt.length()) { final char c = fmt.charAt(pos); if (Character.isDigit(c)) { pos++; } else { break; } } if (pos > firstPos + 1) { final String sz = fmt.substring(firstPos + 1, pos); precision = Integer.parseInt(sz); precisionSet = true; } } } } /** * Set the field width. */ private void setFieldWidth() { final 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()) { final char c = fmt.charAt(pos); if (Character.isDigit(c)) { pos++; } else { break; } } if (firstPos < pos && firstPos < fmt.length()) { final 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; OUTER: for (; pos < fmt.length(); pos++) { final char c = fmt.charAt(pos); switch (c) { case '\'': thousands = true; break; case '-': leftJustify = true; leadingZeros = false; break; case '+': leadingSign = true; leadingSpace = false; break; case ' ': if (!leadingSign) { leadingSpace = true; } break; case '#': alternateForm = true; break; case '0': if (!leftJustify) { leadingZeros = true; } break; default: break OUTER; } } } /** * 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; /** * The result of the conversion will be * left-justified within the field. */ private boolean leftJustify; /** * The result of a signed conversion will always * begin with a sign (+ or -). */ private boolean leadingSign; /** * Flag indicating that left padding with spaces is * specified. */ private boolean leadingSpace; /** * 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; /** * Flag indicating that left padding with zeroes is * specified. */ private boolean leadingZeros; /** * Flag indicating that the field width is *. */ private boolean variableFieldWidth; /** * If the converted value has fewer bytes than the * field width, it will be padded with spaces or * zeroes. */ private int fieldWidth; /** * Flag indicating whether or not the field width * has been set. */ private boolean fieldWidthSet; /** * 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; /** * Default precision. */ private static final int defaultDigits = 6; /** * Flag indicating that the precision is *. */ private boolean variablePrecision; /** * Flag indicating whether or not the precision has * been set. */ private boolean precisionSet; /* */ private boolean positionalSpecification; private int argumentPosition; private boolean positionalFieldWidth; private int argumentPositionForFieldWidth; private boolean positionalPrecision; private int argumentPositionForPrecision; /** * Flag specifying that a following d, i, o, u, x, * or X conversion character applies to a type * short int. */ private boolean optionalh; /** * Flag specifying that a following d, i, o, u, x, * or X conversion character applies to a type lont * int argument. */ private boolean optionall; /** * 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; /** * Control string type. */ private char conversionCharacter; /** * Position within the control string. Used by * the constructor. */ private int pos; /** * Literal or control format string. */ private String fmt; } /** * Vector of control strings and format literals. */ private final ArrayList vFmt = new ArrayList(); /** * Character position. Used by the constructor. */ private int cPos; /** * Character position. Used by the constructor. */ private final DecimalFormatSymbols dfs; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy