git-svn-id: http://talendforge.org/svn/tos/trunk@73207 f6f1c999-d317-4740-80b0-e6d1abc6f99e
2978 lines
116 KiB
Java
2978 lines
116 KiB
Java
//
|
|
// (c) 2000 Sun Microsystems, Inc.
|
|
// ALL RIGHTS RESERVED
|
|
//
|
|
// License Grant-
|
|
//
|
|
//
|
|
// Permission to use, copy, modify, and distribute this Software and its
|
|
// documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is
|
|
// hereby granted.
|
|
//
|
|
// This Software is provided "AS IS". All express warranties, including any
|
|
// implied warranty of merchantability, satisfactory quality, fitness for a
|
|
// particular purpose, or non-infringement, are disclaimed, except to the extent
|
|
// that such disclaimers are held to be legally invalid.
|
|
//
|
|
// You acknowledge that Software is not designed, licensed or intended for use in
|
|
// the design, construction, operation or maintenance of any nuclear facility
|
|
// ("High Risk Activities"). Sun disclaims any express or implied warranty of
|
|
// fitness for such uses.
|
|
//
|
|
// Please refer to the file http://www.sun.com/policies/trademarks/ for further
|
|
// important trademark information and to
|
|
// http://java.sun.com/nav/business/index.html for further important licensing
|
|
// information for the Java Technology.
|
|
//
|
|
package routines.system;
|
|
|
|
import java.text.DecimalFormatSymbols;
|
|
import java.util.Enumeration;
|
|
import java.util.Locale;
|
|
import java.util.Vector;
|
|
|
|
/**
|
|
* PrintfFormat allows the formatting of an array of objects embedded within a string. Primitive types must be passed
|
|
* using wrapper types. The formatting is controlled by a control string.
|
|
* <p>
|
|
* 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
|
|
* <ol>
|
|
* <li>is not escaped protected by a matching % or is not an escape % character,
|
|
* <li>is not at the end of the format string, and
|
|
* <li>precedes a sequence of characters that parses as a valid control specification.
|
|
* </ol>
|
|
* </p>
|
|
* <p>
|
|
* A control specification usually takes the form:
|
|
*
|
|
* <pre>
|
|
* % ['-+ #0]* [0..9]* { . [0..9]* }+
|
|
* { [hlL] }+ [idfgGoxXeEcs]
|
|
* </pre>
|
|
*
|
|
* There are variants of this basic form that are discussed below.
|
|
* </p>
|
|
* <p>
|
|
* The format is composed of zero or more directives defined as follows:
|
|
* <ul>
|
|
* <li>ordinary characters, which are simply copied to the output stream;
|
|
* <li>escape sequences, which represent non-graphic characters; and
|
|
* <li>conversion specifications, each of which results in the fetching of zero or more arguments.
|
|
* </ul>
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* Conversions can be applied to the <code>n</code>th argument after the format in the argument list, rather than to
|
|
* the next unused argument. In this case, the conversion characer % is replaced by the sequence %<code>n</code>$,
|
|
* where <code>n</code> is a decimal integer giving the position of the argument in the argument list.
|
|
* </p>
|
|
* <p>
|
|
* In format strings containing the %<code>n</code>$ form of conversion specifications, each argument in the
|
|
* argument list is used exactly once.
|
|
* </p>
|
|
*
|
|
* <h4>Escape Sequences</h4>
|
|
* <p>
|
|
* The following table lists escape sequences and associated actions on display devices capable of the action. <table>
|
|
* <tr>
|
|
* <th align=left>Sequence</th>
|
|
* <th align=left>Name</th>
|
|
* <th align=left>Description</th>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\\</td>
|
|
* <td>backlash</td>
|
|
* <td>None. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\a</td>
|
|
* <td>alert</td>
|
|
* <td>Attempts to alert the user through audible or visible notification. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\b</td>
|
|
* <td>backspace</td>
|
|
* <td>Moves the printing position to one column before the current position, unless the current position is the start
|
|
* of a line. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\f</td>
|
|
* <td>form-feed</td>
|
|
* <td>Moves the printing position to the initial printing position of the next logical page. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\n</td>
|
|
* <td>newline</td>
|
|
* <td>Moves the printing position to the start of the next line. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\r</td>
|
|
* <td>carriage-return</td>
|
|
* <td>Moves the printing position to the start of the current line. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\t</td>
|
|
* <td>tab</td>
|
|
* <td>Moves the printing position to the next implementation- defined horizontal tab position. </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>\v</td>
|
|
* <td>vertical-tab</td>
|
|
* <td>Moves the printing position to the start of the next implementation-defined vertical tab position. </td>
|
|
* </tr>
|
|
* </table>
|
|
* </p>
|
|
* <h4>Conversion Specifications</h4>
|
|
* <p>
|
|
* Each conversion specification is introduced by the percent sign character (%). After the character %, the following
|
|
* appear in sequence:
|
|
* </p>
|
|
* <p>
|
|
* Zero or more flags (in any order), which modify the meaning of the conversion specification.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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).
|
|
* </p>
|
|
* <p>
|
|
* An optional l (ell) specifies that a following d, i, o, x, or X conversion character applies to a type long argument.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* In format strings containing the %<code>n</code>$ form of a conversion specification, a field width or precision
|
|
* may be indicated by the sequence *<code>m</code>$, 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.
|
|
* </p>
|
|
* <p>
|
|
* The format can contain either numbered argument specifications (that is, %<code>n</code>$ and *<code>m</code>$),
|
|
* or unnumbered argument specifications (that is % and *), but normally not both. The only exception to this is that %%
|
|
* can be mixed with the %<code>n</code>$ form. The results of mixing numbered and unnumbered argument
|
|
* specifications in a format string are undefined.
|
|
* </p>
|
|
*
|
|
* <h4>Flag Characters</h4>
|
|
* <p>
|
|
* The flags and their meanings are:
|
|
* </p>
|
|
* <dl>
|
|
* <dt>'
|
|
* <dd> 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.
|
|
* <dt>-
|
|
* <dd> result of the conversion is left-justified within the field. (It will be right-justified if this flag is not
|
|
* specified).</td>
|
|
* </tr>
|
|
* <dt>+
|
|
* <dd> 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.)
|
|
* <dt><space>
|
|
* <dd> 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.
|
|
* <dt>#
|
|
* <dd> 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.
|
|
* <dt>0
|
|
* <dd> 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.
|
|
* </dl>
|
|
*
|
|
* <h4>Conversion Characters</h4>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
*
|
|
* <p>
|
|
* The conversion characters and their meanings are:
|
|
* </p>
|
|
* <dl>
|
|
* <dt>d,i
|
|
* <dd>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.
|
|
* <dt>o
|
|
* <dd> 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.
|
|
* <dt>x
|
|
* <dd> 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.
|
|
* <dt>X
|
|
* <dd> Behaves the same as the x conversion character except that letters ABCDEF are used instead of abcdef.
|
|
* <dt>f
|
|
* <dd> 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.
|
|
* <dt>e,E
|
|
* <dd>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.
|
|
* <dt>g,G
|
|
* <dd>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.
|
|
* <dt>c,C
|
|
* <dd>The integer argument is converted to a char and the result is written.
|
|
*
|
|
* <dt>s,S
|
|
* <dd>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.
|
|
* <dt>%
|
|
* <dd>Write a % character; no argument is converted.
|
|
* </dl>
|
|
* <p>
|
|
* If a conversion specification does not match one of the above forms, an IllegalArgumentException is thrown and the
|
|
* instance of PrintfFormat is not created.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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.
|
|
* </p>
|
|
* <p>
|
|
* 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:
|
|
* </p>
|
|
* <ul>
|
|
* <li>%c is the same as %C.
|
|
* <li>%s is the same as %S.
|
|
* <li>u, p, and n conversion characters.
|
|
* <li>%ws format.
|
|
* <li>h modifier applied to an n conversion character.
|
|
* <li>l (ell) modifier applied to the c, n, or s conversion characters.
|
|
* <li>ll (ell ell) modifier to d, i, o, u, x, or X conversion characters.
|
|
* <li>ll (ell ell) modifier to an n conversion character.
|
|
* <li>c, C, d,i,o,u,x, and X conversion characters apply to Byte, Character, Short, Integer, Long types.
|
|
* <li>f, e, E, g, and G conversion characters apply to Float and Double types.
|
|
* <li>s and S conversion characters apply to String types.
|
|
* <li>All other reference types can be formatted using the s or S conversion characters only.
|
|
* </ul>
|
|
* <p>
|
|
* Most of this specification is quoted from the Unix man page for the sprintf utility.
|
|
* </p>
|
|
*
|
|
* @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 && cPos < fmtArg.length()) {
|
|
for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) {
|
|
char c = 0;
|
|
c = fmtArg.charAt(ePos);
|
|
if (c == 'i')
|
|
break;
|
|
if (c == 'd')
|
|
break;
|
|
if (c == 'f')
|
|
break;
|
|
if (c == 'g')
|
|
break;
|
|
if (c == 'G')
|
|
break;
|
|
if (c == 'o')
|
|
break;
|
|
if (c == 'x')
|
|
break;
|
|
if (c == 'X')
|
|
break;
|
|
if (c == 'e')
|
|
break;
|
|
if (c == 'E')
|
|
break;
|
|
if (c == 'c')
|
|
break;
|
|
if (c == 's')
|
|
break;
|
|
if (c == '%')
|
|
break;
|
|
}
|
|
ePos = Math.min(ePos + 1, fmtArg.length());
|
|
sFmt = new ConversionSpecification(fmtArg.substring(cPos, ePos));
|
|
vFmt.addElement(sFmt);
|
|
unCS = this.nonControl(fmtArg, ePos);
|
|
if (unCS != null) {
|
|
sFmt = new ConversionSpecification();
|
|
sFmt.setLiteral(unCS);
|
|
vFmt.addElement(sFmt);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a substring starting at <code>start</code> and ending at either the end of the String <code>s</code>,
|
|
* 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 <code>s</code> 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 = ""; //$NON-NLS-1$
|
|
cPos = s.indexOf("%", start); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
}
|
|
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("%"); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
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("%"); //$NON-NLS-1$
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* 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.
|
|
* <p>
|
|
* 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
|
|
* <ol>
|
|
* <li>is not escaped protected by a matching % or is not an escape % character,
|
|
* <li>is not at the end of the format string, and
|
|
* <li>precedes a sequence of characters that parses as a valid control string.
|
|
* </ol>
|
|
* <p>
|
|
* A control string takes the form:
|
|
*
|
|
* <pre>
|
|
* % ['-+ #0]* [0..9]* { . [0..9]* }+
|
|
* { [hlL] }+ [idfgGoxXeEcs]
|
|
* </pre>
|
|
*
|
|
* <p>
|
|
* 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."); //$NON-NLS-1$ //$NON-NLS-2$
|
|
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); //$NON-NLS-1$
|
|
} else
|
|
throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg); //$NON-NLS-1$
|
|
} else
|
|
throw new IllegalArgumentException("Control strings must begin with %."); //$NON-NLS-1$
|
|
}
|
|
|
|
/**
|
|
* Set the String for this instance.
|
|
*
|
|
* @param s the String to store.
|
|
*/
|
|
void setLiteral(String s) {
|
|
fmt = s;
|
|
}
|
|
|
|
/**
|
|
* Get the String for this instance. Translate any escape sequences.
|
|
*
|
|
* @return s the stored String.
|
|
*/
|
|
String getLiteral() {
|
|
StringBuffer sb = new StringBuffer();
|
|
int i = 0;
|
|
while (i < fmt.length()) {
|
|
if (fmt.charAt(i) == '\\') {
|
|
i++;
|
|
if (i < fmt.length()) {
|
|
char c = fmt.charAt(i);
|
|
switch (c) {
|
|
case 'a':
|
|
sb.append((char) 0x07);
|
|
break;
|
|
case 'b':
|
|
sb.append('\b');
|
|
break;
|
|
case 'f':
|
|
sb.append('\f');
|
|
break;
|
|
case 'n':
|
|
sb.append(System.getProperty("line.separator")); //$NON-NLS-1$
|
|
break;
|
|
case 'r':
|
|
sb.append('\r');
|
|
break;
|
|
case 't':
|
|
sb.append('\t');
|
|
break;
|
|
case 'v':
|
|
sb.append((char) 0x0b);
|
|
break;
|
|
case '\\':
|
|
sb.append('\\');
|
|
break;
|
|
}
|
|
i++;
|
|
} else
|
|
sb.append('\\');
|
|
} else
|
|
i++;
|
|
}
|
|
return fmt;
|
|
}
|
|
|
|
/**
|
|
* Get the conversion character that tells what type of control character this instance has.
|
|
*
|
|
* @return the conversion character.
|
|
*/
|
|
char getConversionCharacter() {
|
|
return conversionCharacter;
|
|
}
|
|
|
|
/**
|
|
* Check whether the specifier has a variable field width that is going to be set by an argument.
|
|
*
|
|
* @return <code>true</code> if the conversion uses an * field width; otherwise <code>false</code>.
|
|
*/
|
|
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 <code>true</code> if the conversion uses an * precision; otherwise <code>false</code>.
|
|
*/
|
|
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 = ""; //$NON-NLS-1$
|
|
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 //$NON-NLS-1$
|
|
+ " conversion character."); //$NON-NLS-1$
|
|
}
|
|
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 = ""; //$NON-NLS-1$
|
|
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 //$NON-NLS-1$
|
|
+ " conversion character."); //$NON-NLS-1$
|
|
}
|
|
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 = ""; //$NON-NLS-1$
|
|
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 " //$NON-NLS-1$ //$NON-NLS-2$
|
|
+ conversionCharacter + " conversion character."); //$NON-NLS-1$
|
|
}
|
|
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 = ""; //$NON-NLS-1$
|
|
if (conversionCharacter == 's' || conversionCharacter == 'S')
|
|
s2 = printSFormat(s);
|
|
else
|
|
throw new IllegalArgumentException("Cannot " + "format a String with a format using a " //$NON-NLS-1$ //$NON-NLS-2$
|
|
+ conversionCharacter + " conversion character."); //$NON-NLS-1$
|
|
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 = ""; //$NON-NLS-1$
|
|
if (conversionCharacter == 's' || conversionCharacter == 'S')
|
|
s2 = printSFormat(s.toString());
|
|
else
|
|
throw new IllegalArgumentException("Cannot format a String with a format using" + " a " //$NON-NLS-1$ //$NON-NLS-2$
|
|
+ conversionCharacter + " conversion character."); //$NON-NLS-1$
|
|
return s2;
|
|
}
|
|
|
|
/**
|
|
* For f format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. '+' character means that the conversion will always begin with a
|
|
* sign (+ or -). The blank flag character means that a non-negative input will be preceded with a blank. If
|
|
* both a '+' and a ' ' are specified, the blank flag is ignored. The '0' flag character implies that padding to
|
|
* the field width will be done with zeros instead of blanks.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the number of digits to appear after the radix character. Padding is with trailing
|
|
* 0s.
|
|
*/
|
|
private char[] fFormatDigits(double x) {
|
|
// int defaultDigits=6;
|
|
String sx, sxOut;
|
|
int i, j, k;
|
|
int n1In, n2In;
|
|
int expon = 0;
|
|
boolean minusSign = false;
|
|
if (x > 0.0)
|
|
sx = Double.toString(x);
|
|
else if (x < 0.0) {
|
|
sx = Double.toString(-x);
|
|
minusSign = true;
|
|
} else {
|
|
sx = Double.toString(x);
|
|
if (sx.charAt(0) == '-') {
|
|
minusSign = true;
|
|
sx = sx.substring(1);
|
|
}
|
|
}
|
|
int ePos = sx.indexOf('E');
|
|
int rPos = sx.indexOf('.');
|
|
if (rPos != -1)
|
|
n1In = rPos;
|
|
else if (ePos != -1)
|
|
n1In = ePos;
|
|
else
|
|
n1In = sx.length();
|
|
if (rPos != -1) {
|
|
if (ePos != -1)
|
|
n2In = ePos - rPos - 1;
|
|
else
|
|
n2In = sx.length() - rPos - 1;
|
|
} else
|
|
n2In = 0;
|
|
if (ePos != -1) {
|
|
int ie = ePos + 1;
|
|
expon = 0;
|
|
if (sx.charAt(ie) == '-') {
|
|
for (++ie; ie < sx.length(); ie++)
|
|
if (sx.charAt(ie) != '0')
|
|
break;
|
|
if (ie < sx.length())
|
|
expon = -Integer.parseInt(sx.substring(ie));
|
|
} else {
|
|
if (sx.charAt(ie) == '+')
|
|
++ie;
|
|
for (; ie < sx.length(); ie++)
|
|
if (sx.charAt(ie) != '0')
|
|
break;
|
|
if (ie < sx.length())
|
|
expon = Integer.parseInt(sx.substring(ie));
|
|
}
|
|
}
|
|
int p;
|
|
if (precisionSet)
|
|
p = precision;
|
|
else
|
|
p = defaultDigits - 1;
|
|
char[] ca1 = sx.toCharArray();
|
|
char[] ca2 = new char[n1In + n2In];
|
|
char[] ca3, ca4, ca5;
|
|
for (j = 0; j < n1In; j++)
|
|
ca2[j] = ca1[j];
|
|
i = j + 1;
|
|
for (k = 0; k < n2In; j++, i++, k++)
|
|
ca2[j] = ca1[i];
|
|
if (n1In + expon <= 0) {
|
|
ca3 = new char[-expon + n2In];
|
|
for (j = 0, k = 0; k < (-n1In - expon); k++, j++)
|
|
ca3[j] = '0';
|
|
for (i = 0; i < (n1In + n2In); i++, j++)
|
|
ca3[j] = ca2[i];
|
|
} else
|
|
ca3 = ca2;
|
|
boolean carry = false;
|
|
if (p < -expon + n2In) {
|
|
if (expon < 0)
|
|
i = p;
|
|
else
|
|
i = p + n1In;
|
|
carry = checkForCarry(ca3, i);
|
|
if (carry)
|
|
carry = startSymbolicCarry(ca3, i - 1, 0);
|
|
}
|
|
if (n1In + expon <= 0) {
|
|
ca4 = new char[2 + p];
|
|
if (!carry)
|
|
ca4[0] = '0';
|
|
else
|
|
ca4[0] = '1';
|
|
if (alternateForm || !precisionSet || precision != 0) {
|
|
ca4[1] = '.';
|
|
for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++)
|
|
ca4[j] = ca3[i];
|
|
for (; j < ca4.length; j++)
|
|
ca4[j] = '0';
|
|
}
|
|
} else {
|
|
if (!carry) {
|
|
if (alternateForm || !precisionSet || precision != 0)
|
|
ca4 = new char[n1In + expon + p + 1];
|
|
else
|
|
ca4 = new char[n1In + expon];
|
|
j = 0;
|
|
} else {
|
|
if (alternateForm || !precisionSet || precision != 0)
|
|
ca4 = new char[n1In + expon + p + 2];
|
|
else
|
|
ca4 = new char[n1In + expon + 1];
|
|
ca4[0] = '1';
|
|
j = 1;
|
|
}
|
|
for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++)
|
|
ca4[j] = ca3[i];
|
|
for (; i < n1In + expon; i++, j++)
|
|
ca4[j] = '0';
|
|
if (alternateForm || !precisionSet || precision != 0) {
|
|
ca4[j] = '.';
|
|
j++;
|
|
for (k = 0; i < ca3.length && k < p; i++, j++, k++)
|
|
ca4[j] = ca3[i];
|
|
for (; j < ca4.length; j++)
|
|
ca4[j] = '0';
|
|
}
|
|
}
|
|
int nZeros = 0;
|
|
if (!leftJustify && leadingZeros) {
|
|
int xThousands = 0;
|
|
if (thousands) {
|
|
int xlead = 0;
|
|
if (ca4[0] == '+' || ca4[0] == '-' || ca4[0] == ' ')
|
|
xlead = 1;
|
|
int xdp = xlead;
|
|
for (; xdp < ca4.length; xdp++)
|
|
if (ca4[xdp] == '.')
|
|
break;
|
|
xThousands = (xdp - xlead) / 3;
|
|
}
|
|
if (fieldWidthSet)
|
|
nZeros = fieldWidth - ca4.length;
|
|
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
|
|
nZeros--;
|
|
nZeros -= xThousands;
|
|
if (nZeros < 0)
|
|
nZeros = 0;
|
|
}
|
|
j = 0;
|
|
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
|
|
ca5 = new char[ca4.length + nZeros + 1];
|
|
j++;
|
|
} else
|
|
ca5 = new char[ca4.length + nZeros];
|
|
if (!minusSign) {
|
|
if (leadingSign)
|
|
ca5[0] = '+';
|
|
if (leadingSpace)
|
|
ca5[0] = ' ';
|
|
} else
|
|
ca5[0] = '-';
|
|
for (i = 0; i < nZeros; i++, j++)
|
|
ca5[j] = '0';
|
|
for (i = 0; i < ca4.length; i++, j++)
|
|
ca5[j] = ca4[i];
|
|
|
|
int lead = 0;
|
|
if (ca5[0] == '+' || ca5[0] == '-' || ca5[0] == ' ')
|
|
lead = 1;
|
|
int dp = lead;
|
|
for (; dp < ca5.length; dp++)
|
|
if (ca5[dp] == '.')
|
|
break;
|
|
int nThousands = (dp - lead) / 3;
|
|
// Localize the decimal point.
|
|
if (dp < ca5.length)
|
|
ca5[dp] = dfs.getDecimalSeparator();
|
|
char[] ca6 = ca5;
|
|
if (thousands && nThousands > 0) {
|
|
ca6 = new char[ca5.length + nThousands + lead];
|
|
ca6[0] = ca5[0];
|
|
for (i = lead, k = lead; i < dp; i++) {
|
|
if (i > 0 && (dp - i) % 3 == 0) {
|
|
// ca6[k]=',';
|
|
ca6[k] = dfs.getGroupingSeparator();
|
|
ca6[k + 1] = ca5[i];
|
|
k += 2;
|
|
} else {
|
|
ca6[k] = ca5[i];
|
|
k++;
|
|
}
|
|
}
|
|
for (; i < ca5.length; i++, k++) {
|
|
ca6[k] = ca5[i];
|
|
}
|
|
}
|
|
return ca6;
|
|
}
|
|
|
|
/**
|
|
* An intermediate routine on the way to creating an f format String. The method decides whether the input
|
|
* double value is an infinity, not-a-number, or a finite double and formats each type of input appropriately.
|
|
*
|
|
* @param x the double value to be formatted.
|
|
* @return the converted double value.
|
|
*/
|
|
private String fFormatString(double x) {
|
|
boolean noDigits = false;
|
|
char[] ca6, ca7;
|
|
if (Double.isInfinite(x)) {
|
|
if (x == Double.POSITIVE_INFINITY) {
|
|
if (leadingSign)
|
|
ca6 = "+Inf".toCharArray(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca6 = " Inf".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca6 = "Inf".toCharArray(); //$NON-NLS-1$
|
|
} else
|
|
ca6 = "-Inf".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else if (Double.isNaN(x)) {
|
|
if (leadingSign)
|
|
ca6 = "+NaN".toCharArray(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca6 = " NaN".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca6 = "NaN".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else
|
|
ca6 = fFormatDigits(x);
|
|
ca7 = applyFloatPadding(ca6, false);
|
|
return new String(ca7);
|
|
}
|
|
|
|
/**
|
|
* For e format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. '+' character means that the conversion will always begin with a
|
|
* sign (+ or -). The blank flag character means that a non-negative input will be preceded with a blank. If
|
|
* both a '+' and a ' ' are specified, the blank flag is ignored. The '0' flag character implies that padding to
|
|
* the field width will be done with zeros instead of blanks.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear after the radix character. Padding is with
|
|
* trailing 0s.
|
|
*
|
|
* The behavior is like printf. One (hopefully the only) exception is that the minimum number of exponent digits
|
|
* is 3 instead of 2 for e and E formats when the optional L is used before the e, E, g, or G conversion
|
|
* character. The optional L does not imply conversion to a long long double.
|
|
*/
|
|
private char[] eFormatDigits(double x, char eChar) {
|
|
char[] ca1, ca2, ca3;
|
|
// int defaultDigits=6;
|
|
String sx, sxOut;
|
|
int i, j, k, p;
|
|
int n1In, n2In;
|
|
int expon = 0;
|
|
int ePos, rPos, eSize;
|
|
boolean minusSign = false;
|
|
if (x > 0.0)
|
|
sx = Double.toString(x);
|
|
else if (x < 0.0) {
|
|
sx = Double.toString(-x);
|
|
minusSign = true;
|
|
} else {
|
|
sx = Double.toString(x);
|
|
if (sx.charAt(0) == '-') {
|
|
minusSign = true;
|
|
sx = sx.substring(1);
|
|
}
|
|
}
|
|
ePos = sx.indexOf('E');
|
|
if (ePos == -1)
|
|
ePos = sx.indexOf('e');
|
|
rPos = sx.indexOf('.');
|
|
if (rPos != -1)
|
|
n1In = rPos;
|
|
else if (ePos != -1)
|
|
n1In = ePos;
|
|
else
|
|
n1In = sx.length();
|
|
if (rPos != -1) {
|
|
if (ePos != -1)
|
|
n2In = ePos - rPos - 1;
|
|
else
|
|
n2In = sx.length() - rPos - 1;
|
|
} else
|
|
n2In = 0;
|
|
if (ePos != -1) {
|
|
int ie = ePos + 1;
|
|
expon = 0;
|
|
if (sx.charAt(ie) == '-') {
|
|
for (++ie; ie < sx.length(); ie++)
|
|
if (sx.charAt(ie) != '0')
|
|
break;
|
|
if (ie < sx.length())
|
|
expon = -Integer.parseInt(sx.substring(ie));
|
|
} else {
|
|
if (sx.charAt(ie) == '+')
|
|
++ie;
|
|
for (; ie < sx.length(); ie++)
|
|
if (sx.charAt(ie) != '0')
|
|
break;
|
|
if (ie < sx.length())
|
|
expon = Integer.parseInt(sx.substring(ie));
|
|
}
|
|
}
|
|
if (rPos != -1)
|
|
expon += rPos - 1;
|
|
if (precisionSet)
|
|
p = precision;
|
|
else
|
|
p = defaultDigits - 1;
|
|
if (rPos != -1 && ePos != -1)
|
|
ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1, ePos)).toCharArray();
|
|
else if (rPos != -1)
|
|
ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1)).toCharArray();
|
|
else if (ePos != -1)
|
|
ca1 = sx.substring(0, ePos).toCharArray();
|
|
else
|
|
ca1 = sx.toCharArray();
|
|
boolean carry = false;
|
|
int i0 = 0;
|
|
if (ca1[0] != '0')
|
|
i0 = 0;
|
|
else
|
|
for (i0 = 0; i0 < ca1.length; i0++)
|
|
if (ca1[i0] != '0')
|
|
break;
|
|
if (i0 + p < ca1.length - 1) {
|
|
carry = checkForCarry(ca1, i0 + p + 1);
|
|
if (carry)
|
|
carry = startSymbolicCarry(ca1, i0 + p, i0);
|
|
if (carry) {
|
|
ca2 = new char[i0 + p + 1];
|
|
ca2[i0] = '1';
|
|
for (j = 0; j < i0; j++)
|
|
ca2[j] = '0';
|
|
for (i = i0, j = i0 + 1; j < p + 1; i++, j++)
|
|
ca2[j] = ca1[i];
|
|
expon++;
|
|
ca1 = ca2;
|
|
}
|
|
}
|
|
if (Math.abs(expon) < 100 && !optionalL)
|
|
eSize = 4;
|
|
else
|
|
eSize = 5;
|
|
if (alternateForm || !precisionSet || precision != 0)
|
|
ca2 = new char[2 + p + eSize];
|
|
else
|
|
ca2 = new char[1 + eSize];
|
|
if (ca1[0] != '0') {
|
|
ca2[0] = ca1[0];
|
|
j = 1;
|
|
} else {
|
|
for (j = 1; j < (ePos == -1 ? ca1.length : ePos); j++)
|
|
if (ca1[j] != '0')
|
|
break;
|
|
if ((ePos != -1 && j < ePos) || (ePos == -1 && j < ca1.length)) {
|
|
ca2[0] = ca1[j];
|
|
expon -= j;
|
|
j++;
|
|
} else {
|
|
ca2[0] = '0';
|
|
j = 2;
|
|
}
|
|
}
|
|
if (alternateForm || !precisionSet || precision != 0) {
|
|
ca2[1] = '.';
|
|
i = 2;
|
|
} else
|
|
i = 1;
|
|
for (k = 0; k < p && j < ca1.length; j++, i++, k++)
|
|
ca2[i] = ca1[j];
|
|
for (; i < ca2.length - eSize; i++)
|
|
ca2[i] = '0';
|
|
ca2[i++] = eChar;
|
|
if (expon < 0)
|
|
ca2[i++] = '-';
|
|
else
|
|
ca2[i++] = '+';
|
|
expon = Math.abs(expon);
|
|
if (expon >= 100) {
|
|
switch (expon / 100) {
|
|
case 1:
|
|
ca2[i] = '1';
|
|
break;
|
|
case 2:
|
|
ca2[i] = '2';
|
|
break;
|
|
case 3:
|
|
ca2[i] = '3';
|
|
break;
|
|
case 4:
|
|
ca2[i] = '4';
|
|
break;
|
|
case 5:
|
|
ca2[i] = '5';
|
|
break;
|
|
case 6:
|
|
ca2[i] = '6';
|
|
break;
|
|
case 7:
|
|
ca2[i] = '7';
|
|
break;
|
|
case 8:
|
|
ca2[i] = '8';
|
|
break;
|
|
case 9:
|
|
ca2[i] = '9';
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
switch ((expon % 100) / 10) {
|
|
case 0:
|
|
ca2[i] = '0';
|
|
break;
|
|
case 1:
|
|
ca2[i] = '1';
|
|
break;
|
|
case 2:
|
|
ca2[i] = '2';
|
|
break;
|
|
case 3:
|
|
ca2[i] = '3';
|
|
break;
|
|
case 4:
|
|
ca2[i] = '4';
|
|
break;
|
|
case 5:
|
|
ca2[i] = '5';
|
|
break;
|
|
case 6:
|
|
ca2[i] = '6';
|
|
break;
|
|
case 7:
|
|
ca2[i] = '7';
|
|
break;
|
|
case 8:
|
|
ca2[i] = '8';
|
|
break;
|
|
case 9:
|
|
ca2[i] = '9';
|
|
break;
|
|
}
|
|
i++;
|
|
switch (expon % 10) {
|
|
case 0:
|
|
ca2[i] = '0';
|
|
break;
|
|
case 1:
|
|
ca2[i] = '1';
|
|
break;
|
|
case 2:
|
|
ca2[i] = '2';
|
|
break;
|
|
case 3:
|
|
ca2[i] = '3';
|
|
break;
|
|
case 4:
|
|
ca2[i] = '4';
|
|
break;
|
|
case 5:
|
|
ca2[i] = '5';
|
|
break;
|
|
case 6:
|
|
ca2[i] = '6';
|
|
break;
|
|
case 7:
|
|
ca2[i] = '7';
|
|
break;
|
|
case 8:
|
|
ca2[i] = '8';
|
|
break;
|
|
case 9:
|
|
ca2[i] = '9';
|
|
break;
|
|
}
|
|
int nZeros = 0;
|
|
if (!leftJustify && leadingZeros) {
|
|
int xThousands = 0;
|
|
if (thousands) {
|
|
int xlead = 0;
|
|
if (ca2[0] == '+' || ca2[0] == '-' || ca2[0] == ' ')
|
|
xlead = 1;
|
|
int xdp = xlead;
|
|
for (; xdp < ca2.length; xdp++)
|
|
if (ca2[xdp] == '.')
|
|
break;
|
|
xThousands = (xdp - xlead) / 3;
|
|
}
|
|
if (fieldWidthSet)
|
|
nZeros = fieldWidth - ca2.length;
|
|
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
|
|
nZeros--;
|
|
nZeros -= xThousands;
|
|
if (nZeros < 0)
|
|
nZeros = 0;
|
|
}
|
|
j = 0;
|
|
if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
|
|
ca3 = new char[ca2.length + nZeros + 1];
|
|
j++;
|
|
} else
|
|
ca3 = new char[ca2.length + nZeros];
|
|
if (!minusSign) {
|
|
if (leadingSign)
|
|
ca3[0] = '+';
|
|
if (leadingSpace)
|
|
ca3[0] = ' ';
|
|
} else
|
|
ca3[0] = '-';
|
|
for (k = 0; k < nZeros; j++, k++)
|
|
ca3[j] = '0';
|
|
for (i = 0; i < ca2.length && j < ca3.length; i++, j++)
|
|
ca3[j] = ca2[i];
|
|
|
|
int lead = 0;
|
|
if (ca3[0] == '+' || ca3[0] == '-' || ca3[0] == ' ')
|
|
lead = 1;
|
|
int dp = lead;
|
|
for (; dp < ca3.length; dp++)
|
|
if (ca3[dp] == '.')
|
|
break;
|
|
int nThousands = dp / 3;
|
|
// Localize the decimal point.
|
|
if (dp < ca3.length)
|
|
ca3[dp] = dfs.getDecimalSeparator();
|
|
char[] ca4 = ca3;
|
|
if (thousands && nThousands > 0) {
|
|
ca4 = new char[ca3.length + nThousands + lead];
|
|
ca4[0] = ca3[0];
|
|
for (i = lead, k = lead; i < dp; i++) {
|
|
if (i > 0 && (dp - i) % 3 == 0) {
|
|
// ca4[k]=',';
|
|
ca4[k] = dfs.getGroupingSeparator();
|
|
ca4[k + 1] = ca3[i];
|
|
k += 2;
|
|
} else {
|
|
ca4[k] = ca3[i];
|
|
k++;
|
|
}
|
|
}
|
|
for (; i < ca3.length; i++, k++)
|
|
ca4[k] = ca3[i];
|
|
}
|
|
return ca4;
|
|
}
|
|
|
|
/**
|
|
* Check to see if the digits that are going to be truncated because of the precision should force a round in
|
|
* the preceding digits.
|
|
*
|
|
* @param ca1 the array of digits
|
|
* @param icarry the index of the first digit that is to be truncated from the print
|
|
* @return <code>true</code> if the truncation forces a round that will change the print
|
|
*/
|
|
private boolean checkForCarry(char[] ca1, int icarry) {
|
|
boolean carry = false;
|
|
if (icarry < ca1.length) {
|
|
if (ca1[icarry] == '6' || ca1[icarry] == '7' || ca1[icarry] == '8' || ca1[icarry] == '9')
|
|
carry = true;
|
|
else if (ca1[icarry] == '5') {
|
|
int ii = icarry + 1;
|
|
for (; ii < ca1.length; ii++)
|
|
if (ca1[ii] != '0')
|
|
break;
|
|
carry = ii < ca1.length;
|
|
if (!carry && icarry > 0) {
|
|
carry = (ca1[icarry - 1] == '1' || ca1[icarry - 1] == '3' || ca1[icarry - 1] == '5'
|
|
|| ca1[icarry - 1] == '7' || ca1[icarry - 1] == '9');
|
|
}
|
|
}
|
|
}
|
|
return carry;
|
|
}
|
|
|
|
/**
|
|
* Start the symbolic carry process. The process is not quite finished because the symbolic carry may change the
|
|
* length of the string and change the exponent (in e format).
|
|
*
|
|
* @param cLast index of the last digit changed by the round
|
|
* @param cFirst index of the first digit allowed to be changed by this phase of the round
|
|
* @return <code>true</code> 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(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca4 = " Inf".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca4 = "Inf".toCharArray(); //$NON-NLS-1$
|
|
} else
|
|
ca4 = "-Inf".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else if (Double.isNaN(x)) {
|
|
if (leadingSign)
|
|
ca4 = "+NaN".toCharArray(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca4 = " NaN".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca4 = "NaN".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else
|
|
ca4 = eFormatDigits(x, eChar);
|
|
ca5 = applyFloatPadding(ca4, false);
|
|
return new String(ca5);
|
|
}
|
|
|
|
/**
|
|
* Apply zero or blank, left or right padding.
|
|
*
|
|
* @param ca4 array of characters before padding is finished
|
|
* @param noDigits NaN or signed Inf
|
|
* @return a padded array of characters
|
|
*/
|
|
private char[] applyFloatPadding(char[] ca4, boolean noDigits) {
|
|
char[] ca5 = ca4;
|
|
if (fieldWidthSet) {
|
|
int i, j, nBlanks;
|
|
if (leftJustify) {
|
|
nBlanks = fieldWidth - ca4.length;
|
|
if (nBlanks > 0) {
|
|
ca5 = new char[ca4.length + nBlanks];
|
|
for (i = 0; i < ca4.length; i++)
|
|
ca5[i] = ca4[i];
|
|
for (j = 0; j < nBlanks; j++, i++)
|
|
ca5[i] = ' ';
|
|
}
|
|
} else if (!leadingZeros || noDigits) {
|
|
nBlanks = fieldWidth - ca4.length;
|
|
if (nBlanks > 0) {
|
|
ca5 = new char[ca4.length + nBlanks];
|
|
for (i = 0; i < nBlanks; i++)
|
|
ca5[i] = ' ';
|
|
for (j = 0; j < ca4.length; i++, j++)
|
|
ca5[i] = ca4[j];
|
|
}
|
|
} else if (leadingZeros) {
|
|
nBlanks = fieldWidth - ca4.length;
|
|
if (nBlanks > 0) {
|
|
ca5 = new char[ca4.length + nBlanks];
|
|
i = 0;
|
|
j = 0;
|
|
if (ca4[0] == '-') {
|
|
ca5[0] = '-';
|
|
i++;
|
|
j++;
|
|
}
|
|
for (int k = 0; k < nBlanks; i++, k++)
|
|
ca5[i] = '0';
|
|
for (; j < ca4.length; i++, j++)
|
|
ca5[i] = ca4[j];
|
|
}
|
|
}
|
|
}
|
|
return ca5;
|
|
}
|
|
|
|
/**
|
|
* Format method for the f conversion character.
|
|
*
|
|
* @param x the double to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printFFormat(double x) {
|
|
return fFormatString(x);
|
|
}
|
|
|
|
/**
|
|
* Format method for the e or E conversion character.
|
|
*
|
|
* @param x the double to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printEFormat(double x) {
|
|
if (conversionCharacter == 'e')
|
|
return eFormatString(x, 'e');
|
|
else
|
|
return eFormatString(x, 'E');
|
|
}
|
|
|
|
/**
|
|
* Format method for the g conversion character.
|
|
*
|
|
* For g format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. '+' character means that the conversion will always begin with a
|
|
* sign (+ or -). The blank flag character means that a non-negative input will be preceded with a blank. If
|
|
* both a '+' and a ' ' are specified, the blank flag is ignored. The '0' flag character implies that padding to
|
|
* the field width will be done with zeros instead of blanks.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear after the radix character. Padding is with
|
|
* trailing 0s.
|
|
*
|
|
* @param x the double to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printGFormat(double x) {
|
|
String sx, sy, sz, ret;
|
|
int savePrecision = precision;
|
|
int i;
|
|
char[] ca4, ca5;
|
|
boolean noDigits = false;
|
|
if (Double.isInfinite(x)) {
|
|
if (x == Double.POSITIVE_INFINITY) {
|
|
if (leadingSign)
|
|
ca4 = "+Inf".toCharArray(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca4 = " Inf".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca4 = "Inf".toCharArray(); //$NON-NLS-1$
|
|
} else
|
|
ca4 = "-Inf".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else if (Double.isNaN(x)) {
|
|
if (leadingSign)
|
|
ca4 = "+NaN".toCharArray(); //$NON-NLS-1$
|
|
else if (leadingSpace)
|
|
ca4 = " NaN".toCharArray(); //$NON-NLS-1$
|
|
else
|
|
ca4 = "NaN".toCharArray(); //$NON-NLS-1$
|
|
noDigits = true;
|
|
} else {
|
|
if (!precisionSet)
|
|
precision = defaultDigits;
|
|
if (precision == 0)
|
|
precision = 1;
|
|
int ePos = -1;
|
|
if (conversionCharacter == 'g') {
|
|
sx = eFormatString(x, 'e').trim();
|
|
ePos = sx.indexOf('e');
|
|
} else {
|
|
sx = eFormatString(x, 'E').trim();
|
|
ePos = sx.indexOf('E');
|
|
}
|
|
i = ePos + 1;
|
|
int expon = 0;
|
|
if (sx.charAt(i) == '-') {
|
|
for (++i; i < sx.length(); i++)
|
|
if (sx.charAt(i) != '0')
|
|
break;
|
|
if (i < sx.length())
|
|
expon = -Integer.parseInt(sx.substring(i));
|
|
} else {
|
|
if (sx.charAt(i) == '+')
|
|
++i;
|
|
for (; i < sx.length(); i++)
|
|
if (sx.charAt(i) != '0')
|
|
break;
|
|
if (i < sx.length())
|
|
expon = Integer.parseInt(sx.substring(i));
|
|
}
|
|
// Trim trailing zeros.
|
|
// If the radix character is not followed by
|
|
// a digit, trim it, too.
|
|
if (!alternateForm) {
|
|
if (expon >= -4 && expon < precision)
|
|
sy = fFormatString(x).trim();
|
|
else
|
|
sy = sx.substring(0, ePos);
|
|
i = sy.length() - 1;
|
|
for (; i >= 0; i--)
|
|
if (sy.charAt(i) != '0')
|
|
break;
|
|
if (i >= 0 && sy.charAt(i) == '.')
|
|
i--;
|
|
if (i == -1)
|
|
sz = "0"; //$NON-NLS-1$
|
|
else if (!Character.isDigit(sy.charAt(i)))
|
|
sz = sy.substring(0, i + 1) + "0"; //$NON-NLS-1$
|
|
else
|
|
sz = sy.substring(0, i + 1);
|
|
if (expon >= -4 && expon < precision)
|
|
ret = sz;
|
|
else
|
|
ret = sz + sx.substring(ePos);
|
|
} else {
|
|
if (expon >= -4 && expon < precision)
|
|
ret = fFormatString(x).trim();
|
|
else
|
|
ret = sx;
|
|
}
|
|
// leading space was trimmed off during
|
|
// construction
|
|
if (leadingSpace)
|
|
if (x >= 0)
|
|
ret = " " + ret; //$NON-NLS-1$
|
|
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) //$NON-NLS-1$
|
|
sx = ""; //$NON-NLS-1$
|
|
if (!neg) {
|
|
if (precisionSet && sx.length() < precision)
|
|
nLeadingZeros = precision - sx.length();
|
|
} else {
|
|
if (precisionSet && (sx.length() - 1) < precision)
|
|
nLeadingZeros = precision - sx.length() + 1;
|
|
}
|
|
if (nLeadingZeros < 0)
|
|
nLeadingZeros = 0;
|
|
if (fieldWidthSet) {
|
|
nBlanks = fieldWidth - nLeadingZeros - sx.length();
|
|
if (!neg && (leadingSign || leadingSpace))
|
|
nBlanks--;
|
|
}
|
|
if (nBlanks < 0)
|
|
nBlanks = 0;
|
|
if (leadingSign)
|
|
n++;
|
|
else if (leadingSpace)
|
|
n++;
|
|
n += nBlanks;
|
|
n += nLeadingZeros;
|
|
n += sx.length();
|
|
char[] ca = new char[n];
|
|
if (leftJustify) {
|
|
if (neg)
|
|
ca[i++] = '-';
|
|
else if (leadingSign)
|
|
ca[i++] = '+';
|
|
else if (leadingSpace)
|
|
ca[i++] = ' ';
|
|
char[] csx = sx.toCharArray();
|
|
jFirst = neg ? 1 : 0;
|
|
for (int j = 0; j < nLeadingZeros; i++, j++)
|
|
ca[i] = '0';
|
|
for (int j = jFirst; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
for (int j = 0; j < nBlanks; i++, j++)
|
|
ca[i] = ' ';
|
|
} else {
|
|
if (!leadingZeros) {
|
|
for (i = 0; i < nBlanks; i++)
|
|
ca[i] = ' ';
|
|
if (neg)
|
|
ca[i++] = '-';
|
|
else if (leadingSign)
|
|
ca[i++] = '+';
|
|
else if (leadingSpace)
|
|
ca[i++] = ' ';
|
|
} else {
|
|
if (neg)
|
|
ca[i++] = '-';
|
|
else if (leadingSign)
|
|
ca[i++] = '+';
|
|
else if (leadingSpace)
|
|
ca[i++] = ' ';
|
|
for (int j = 0; j < nBlanks; j++, i++)
|
|
ca[i] = '0';
|
|
}
|
|
for (int j = 0; j < nLeadingZeros; j++, i++)
|
|
ca[i] = '0';
|
|
char[] csx = sx.toCharArray();
|
|
jFirst = neg ? 1 : 0;
|
|
for (int j = jFirst; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
}
|
|
return new String(ca);
|
|
}
|
|
|
|
/**
|
|
* Format method for the x conversion character and short argument.
|
|
*
|
|
* For x format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means to lead with '0x'.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the short to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printXFormat(short x) {
|
|
String sx = null;
|
|
if (x == Short.MIN_VALUE)
|
|
sx = "8000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t;
|
|
if (x == Short.MIN_VALUE)
|
|
t = "0"; //$NON-NLS-1$
|
|
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; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "80" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "8" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
switch (t.charAt(0)) {
|
|
case '1':
|
|
sx = "9" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '2':
|
|
sx = "a" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '3':
|
|
sx = "b" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '4':
|
|
sx = "c" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '5':
|
|
sx = "d" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '6':
|
|
sx = "e" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
case '7':
|
|
sx = "f" + t.substring(1, 4); //$NON-NLS-1$
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
} else
|
|
sx = Integer.toString((int) x, 16);
|
|
return printXFormat(sx);
|
|
}
|
|
|
|
/**
|
|
* Format method for the x conversion character and long argument.
|
|
*
|
|
* For x format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means to lead with '0x'.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the long to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printXFormat(long x) {
|
|
String sx = null;
|
|
if (x == Long.MIN_VALUE)
|
|
sx = "8000000000000000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 16);
|
|
switch (t.length()) {
|
|
case 1:
|
|
sx = "800000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "80000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "8000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
sx = "800000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 5:
|
|
sx = "80000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 6:
|
|
sx = "8000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 7:
|
|
sx = "800000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 8:
|
|
sx = "80000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 9:
|
|
sx = "8000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 10:
|
|
sx = "800000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 11:
|
|
sx = "80000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 12:
|
|
sx = "8000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 13:
|
|
sx = "800" + t; //$NON-NLS-1$
|
|
break;
|
|
case 14:
|
|
sx = "80" + t; //$NON-NLS-1$
|
|
break;
|
|
case 15:
|
|
sx = "8" + t; //$NON-NLS-1$
|
|
break;
|
|
case 16:
|
|
switch (t.charAt(0)) {
|
|
case '1':
|
|
sx = "9" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '2':
|
|
sx = "a" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '3':
|
|
sx = "b" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '4':
|
|
sx = "c" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '5':
|
|
sx = "d" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '6':
|
|
sx = "e" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
case '7':
|
|
sx = "f" + t.substring(1, 16); //$NON-NLS-1$
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
} else
|
|
sx = Long.toString(x, 16);
|
|
return printXFormat(sx);
|
|
}
|
|
|
|
/**
|
|
* Format method for the x conversion character and int argument.
|
|
*
|
|
* For x format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means to lead with '0x'.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the int to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printXFormat(int x) {
|
|
String sx = null;
|
|
if (x == Integer.MIN_VALUE)
|
|
sx = "80000000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 16);
|
|
switch (t.length()) {
|
|
case 1:
|
|
sx = "8000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "800000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "80000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
sx = "8000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 5:
|
|
sx = "800" + t; //$NON-NLS-1$
|
|
break;
|
|
case 6:
|
|
sx = "80" + t; //$NON-NLS-1$
|
|
break;
|
|
case 7:
|
|
sx = "8" + t; //$NON-NLS-1$
|
|
break;
|
|
case 8:
|
|
switch (t.charAt(0)) {
|
|
case '1':
|
|
sx = "9" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '2':
|
|
sx = "a" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '3':
|
|
sx = "b" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '4':
|
|
sx = "c" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '5':
|
|
sx = "d" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '6':
|
|
sx = "e" + t.substring(1, 8); //$NON-NLS-1$
|
|
break;
|
|
case '7':
|
|
sx = "f" + t.substring(1, 8); //$NON-NLS-1$
|
|
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) //$NON-NLS-1$
|
|
sx = ""; //$NON-NLS-1$
|
|
if (precisionSet)
|
|
nLeadingZeros = precision - sx.length();
|
|
if (nLeadingZeros < 0)
|
|
nLeadingZeros = 0;
|
|
if (fieldWidthSet) {
|
|
nBlanks = fieldWidth - nLeadingZeros - sx.length();
|
|
if (alternateForm)
|
|
nBlanks = nBlanks - 2;
|
|
}
|
|
if (nBlanks < 0)
|
|
nBlanks = 0;
|
|
int n = 0;
|
|
if (alternateForm)
|
|
n += 2;
|
|
n += nLeadingZeros;
|
|
n += sx.length();
|
|
n += nBlanks;
|
|
char[] ca = new char[n];
|
|
int i = 0;
|
|
if (leftJustify) {
|
|
if (alternateForm) {
|
|
ca[i++] = '0';
|
|
ca[i++] = 'x';
|
|
}
|
|
for (int j = 0; j < nLeadingZeros; j++, i++)
|
|
ca[i] = '0';
|
|
char[] csx = sx.toCharArray();
|
|
for (int j = 0; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
for (int j = 0; j < nBlanks; j++, i++)
|
|
ca[i] = ' ';
|
|
} else {
|
|
if (!leadingZeros)
|
|
for (int j = 0; j < nBlanks; j++, i++)
|
|
ca[i] = ' ';
|
|
if (alternateForm) {
|
|
ca[i++] = '0';
|
|
ca[i++] = 'x';
|
|
}
|
|
if (leadingZeros)
|
|
for (int j = 0; j < nBlanks; j++, i++)
|
|
ca[i] = '0';
|
|
for (int j = 0; j < nLeadingZeros; j++, i++)
|
|
ca[i] = '0';
|
|
char[] csx = sx.toCharArray();
|
|
for (int j = 0; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
}
|
|
String caReturn = new String(ca);
|
|
if (conversionCharacter == 'X')
|
|
caReturn = caReturn.toUpperCase();
|
|
return caReturn;
|
|
}
|
|
|
|
/**
|
|
* Format method for the o conversion character and short argument.
|
|
*
|
|
* For o format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means that the output begins with a leading
|
|
* 0 and the precision is increased by 1.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the short to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printOFormat(short x) {
|
|
String sx = null;
|
|
if (x == Short.MIN_VALUE)
|
|
sx = "100000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 8);
|
|
switch (t.length()) {
|
|
case 1:
|
|
sx = "10000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "1000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "100" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
sx = "10" + t; //$NON-NLS-1$
|
|
break;
|
|
case 5:
|
|
sx = "1" + t; //$NON-NLS-1$
|
|
break;
|
|
}
|
|
} else
|
|
sx = Integer.toString((int) x, 8);
|
|
return printOFormat(sx);
|
|
}
|
|
|
|
/**
|
|
* Format method for the o conversion character and long argument.
|
|
*
|
|
* For o format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means that the output begins with a leading
|
|
* 0 and the precision is increased by 1.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the long to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printOFormat(long x) {
|
|
String sx = null;
|
|
if (x == Long.MIN_VALUE)
|
|
sx = "1000000000000000000000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 8);
|
|
switch (t.length()) {
|
|
case 1:
|
|
sx = "100000000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "10000000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "1000000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
sx = "100000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 5:
|
|
sx = "10000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 6:
|
|
sx = "1000000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 7:
|
|
sx = "100000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 8:
|
|
sx = "10000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 9:
|
|
sx = "1000000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 10:
|
|
sx = "100000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 11:
|
|
sx = "10000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 12:
|
|
sx = "1000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 13:
|
|
sx = "100000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 14:
|
|
sx = "10000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 15:
|
|
sx = "1000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 16:
|
|
sx = "100000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 17:
|
|
sx = "10000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 18:
|
|
sx = "1000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 19:
|
|
sx = "100" + t; //$NON-NLS-1$
|
|
break;
|
|
case 20:
|
|
sx = "10" + t; //$NON-NLS-1$
|
|
break;
|
|
case 21:
|
|
sx = "1" + t; //$NON-NLS-1$
|
|
break;
|
|
}
|
|
} else
|
|
sx = Long.toString(x, 8);
|
|
return printOFormat(sx);
|
|
}
|
|
|
|
/**
|
|
* Format method for the o conversion character and int argument.
|
|
*
|
|
* For o format, the flag character '-', means that the output should be left justified within the field. The
|
|
* default is to pad with blanks on the left. The '#' flag character means that the output begins with a leading
|
|
* 0 and the precision is increased by 1.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is to add no
|
|
* padding. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, is the minimum number of digits to appear. Padding is with leading 0s.
|
|
*
|
|
* @param x the int to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printOFormat(int x) {
|
|
String sx = null;
|
|
if (x == Integer.MIN_VALUE)
|
|
sx = "20000000000"; //$NON-NLS-1$
|
|
else if (x < 0) {
|
|
String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 8);
|
|
switch (t.length()) {
|
|
case 1:
|
|
sx = "2000000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 2:
|
|
sx = "200000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 3:
|
|
sx = "20000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 4:
|
|
sx = "2000000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 5:
|
|
sx = "200000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 6:
|
|
sx = "20000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 7:
|
|
sx = "2000" + t; //$NON-NLS-1$
|
|
break;
|
|
case 8:
|
|
sx = "200" + t; //$NON-NLS-1$
|
|
break;
|
|
case 9:
|
|
sx = "20" + t; //$NON-NLS-1$
|
|
break;
|
|
case 10:
|
|
sx = "2" + t; //$NON-NLS-1$
|
|
break;
|
|
case 11:
|
|
sx = "3" + t.substring(1); //$NON-NLS-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) //$NON-NLS-1$
|
|
sx = ""; //$NON-NLS-1$
|
|
if (precisionSet)
|
|
nLeadingZeros = precision - sx.length();
|
|
if (alternateForm)
|
|
nLeadingZeros++;
|
|
if (nLeadingZeros < 0)
|
|
nLeadingZeros = 0;
|
|
if (fieldWidthSet)
|
|
nBlanks = fieldWidth - nLeadingZeros - sx.length();
|
|
if (nBlanks < 0)
|
|
nBlanks = 0;
|
|
int n = nLeadingZeros + sx.length() + nBlanks;
|
|
char[] ca = new char[n];
|
|
int i;
|
|
if (leftJustify) {
|
|
for (i = 0; i < nLeadingZeros; i++)
|
|
ca[i] = '0';
|
|
char[] csx = sx.toCharArray();
|
|
for (int j = 0; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
for (int j = 0; j < nBlanks; j++, i++)
|
|
ca[i] = ' ';
|
|
} else {
|
|
if (leadingZeros)
|
|
for (i = 0; i < nBlanks; i++)
|
|
ca[i] = '0';
|
|
else
|
|
for (i = 0; i < nBlanks; i++)
|
|
ca[i] = ' ';
|
|
for (int j = 0; j < nLeadingZeros; j++, i++)
|
|
ca[i] = '0';
|
|
char[] csx = sx.toCharArray();
|
|
for (int j = 0; j < csx.length; j++, i++)
|
|
ca[i] = csx[j];
|
|
}
|
|
return new String(ca);
|
|
}
|
|
|
|
/**
|
|
* Format method for the c conversion character and char argument.
|
|
*
|
|
* The only flag character that affects c format is the '-', meaning that the output should be left justified
|
|
* within the field. The default is to pad with blanks on the left.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. Padding is with blanks by
|
|
* default. The default width is 1.
|
|
*
|
|
* The precision, if set, is ignored.
|
|
*
|
|
* @param x the char to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printCFormat(char x) {
|
|
int nPrint = 1;
|
|
int width = fieldWidth;
|
|
if (!fieldWidthSet)
|
|
width = nPrint;
|
|
char[] ca = new char[width];
|
|
int i = 0;
|
|
if (leftJustify) {
|
|
ca[0] = x;
|
|
for (i = 1; i <= width - nPrint; i++)
|
|
ca[i] = ' ';
|
|
} else {
|
|
for (i = 0; i < width - nPrint; i++)
|
|
ca[i] = ' ';
|
|
ca[i] = x;
|
|
}
|
|
return new String(ca);
|
|
}
|
|
|
|
/**
|
|
* Format method for the s conversion character and String argument.
|
|
*
|
|
* The only flag character that affects s format is the '-', meaning that the output should be left justified
|
|
* within the field. The default is to pad with blanks on the left.
|
|
*
|
|
* The field width is treated as the minimum number of characters to be printed. The default is the smaller of
|
|
* the number of characters in the the input and the precision. Padding is with blanks by default.
|
|
*
|
|
* The precision, if set, specifies the maximum number of characters to be printed from the string. A null digit
|
|
* string is treated as a 0. The default is not to set a maximum number of characters to be printed.
|
|
*
|
|
* @param x the String to format.
|
|
* @return the formatted String.
|
|
*/
|
|
private String printSFormat(String x) {
|
|
int nPrint = x.length();
|
|
int width = fieldWidth;
|
|
if (precisionSet && nPrint > precision)
|
|
nPrint = precision;
|
|
if (!fieldWidthSet)
|
|
width = nPrint;
|
|
int n = 0;
|
|
if (width > nPrint)
|
|
n += width - nPrint;
|
|
if (nPrint >= x.length())
|
|
n += x.length();
|
|
else
|
|
n += nPrint;
|
|
char[] ca = new char[n];
|
|
int i = 0;
|
|
if (leftJustify) {
|
|
if (nPrint >= x.length()) {
|
|
char[] csx = x.toCharArray();
|
|
for (i = 0; i < x.length(); i++)
|
|
ca[i] = csx[i];
|
|
} else {
|
|
char[] csx = x.substring(0, nPrint).toCharArray();
|
|
for (i = 0; i < nPrint; i++)
|
|
ca[i] = csx[i];
|
|
}
|
|
for (int j = 0; j < width - nPrint; j++, i++)
|
|
ca[i] = ' ';
|
|
} else {
|
|
for (i = 0; i < width - nPrint; i++)
|
|
ca[i] = ' ';
|
|
if (nPrint >= x.length()) {
|
|
char[] csx = x.toCharArray();
|
|
for (int j = 0; j < x.length(); i++, j++)
|
|
ca[i] = csx[j];
|
|
} else {
|
|
char[] csx = x.substring(0, nPrint).toCharArray();
|
|
for (int j = 0; j < nPrint; i++, j++)
|
|
ca[i] = csx[j];
|
|
}
|
|
}
|
|
return new String(ca);
|
|
}
|
|
|
|
/**
|
|
* Check for a conversion character. If it is there, store it.
|
|
*
|
|
* @param x the String to format.
|
|
* @return <code>true</code> if the conversion character is there, and <code>false</code> otherwise.
|
|
*/
|
|
private boolean setConversionCharacter() {
|
|
/* idfgGoxXeEcs */
|
|
boolean ret = false;
|
|
conversionCharacter = '\0';
|
|
if (pos < fmt.length()) {
|
|
char c = fmt.charAt(pos);
|
|
if (c == 'i' || c == 'd' || c == 'f' || c == 'g' || c == 'G' || c == 'o' || c == 'x' || c == 'X'
|
|
|| c == 'e' || c == 'E' || c == 'c' || c == 's' || c == '%') {
|
|
conversionCharacter = c;
|
|
pos++;
|
|
ret = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Check for an h, l, or L in a format. An L is used to control the minimum number of digits in an exponent when
|
|
* using floating point formats. An l or h is used to control conversion of the input to a long or short,
|
|
* respectively, before formatting. If any of these is present, store them.
|
|
*/
|
|
private void setOptionalHL() {
|
|
optionalh = false;
|
|
optionall = false;
|
|
optionalL = false;
|
|
if (pos < fmt.length()) {
|
|
char c = fmt.charAt(pos);
|
|
if (c == 'h') {
|
|
optionalh = true;
|
|
pos++;
|
|
} else if (c == 'l') {
|
|
optionall = true;
|
|
pos++;
|
|
} else if (c == 'L') {
|
|
optionalL = true;
|
|
pos++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the precision.
|
|
*/
|
|
private void setPrecision() {
|
|
int firstPos = pos;
|
|
precisionSet = false;
|
|
if (pos < fmt.length() && fmt.charAt(pos) == '.') {
|
|
pos++;
|
|
if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
|
|
pos++;
|
|
if (!setPrecisionArgPosition()) {
|
|
variablePrecision = true;
|
|
precisionSet = true;
|
|
}
|
|
return;
|
|
} else {
|
|
while (pos < fmt.length()) {
|
|
char c = fmt.charAt(pos);
|
|
if (Character.isDigit(c))
|
|
pos++;
|
|
else
|
|
break;
|
|
}
|
|
if (pos > firstPos + 1) {
|
|
String sz = fmt.substring(firstPos + 1, pos);
|
|
precision = Integer.parseInt(sz);
|
|
precisionSet = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the field width.
|
|
*/
|
|
private void setFieldWidth() {
|
|
int firstPos = pos;
|
|
fieldWidth = 0;
|
|
fieldWidthSet = false;
|
|
if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
|
|
pos++;
|
|
if (!setFieldWidthArgPosition()) {
|
|
variableFieldWidth = true;
|
|
fieldWidthSet = true;
|
|
}
|
|
} else {
|
|
while (pos < fmt.length()) {
|
|
char c = fmt.charAt(pos);
|
|
if (Character.isDigit(c))
|
|
pos++;
|
|
else
|
|
break;
|
|
}
|
|
if (firstPos < pos && firstPos < fmt.length()) {
|
|
String sz = fmt.substring(firstPos, pos);
|
|
fieldWidth = Integer.parseInt(sz);
|
|
fieldWidthSet = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store the digits <code>n</code> 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 <code>n</code> 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 <code>n</code> in *n$ forms.
|
|
*/
|
|
private boolean setPrecisionArgPosition() {
|
|
boolean ret = false;
|
|
int xPos;
|
|
for (xPos = pos; xPos < fmt.length(); xPos++) {
|
|
if (!Character.isDigit(fmt.charAt(xPos)))
|
|
break;
|
|
}
|
|
if (xPos > pos && xPos < fmt.length()) {
|
|
if (fmt.charAt(xPos) == '$') {
|
|
positionalPrecision = true;
|
|
argumentPositionForPrecision = Integer.parseInt(fmt.substring(pos, xPos));
|
|
pos = xPos + 1;
|
|
ret = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
boolean isPositionalSpecification() {
|
|
return positionalSpecification;
|
|
}
|
|
|
|
int getArgumentPosition() {
|
|
return argumentPosition;
|
|
}
|
|
|
|
boolean isPositionalFieldWidth() {
|
|
return positionalFieldWidth;
|
|
}
|
|
|
|
int getArgumentPositionForFieldWidth() {
|
|
return argumentPositionForFieldWidth;
|
|
}
|
|
|
|
boolean isPositionalPrecision() {
|
|
return positionalPrecision;
|
|
}
|
|
|
|
int getArgumentPositionForPrecision() {
|
|
return argumentPositionForPrecision;
|
|
}
|
|
|
|
/**
|
|
* Set flag characters, one of '-+#0 or a space.
|
|
*/
|
|
private void setFlagCharacters() {
|
|
/* '-+ #0 */
|
|
thousands = false;
|
|
leftJustify = false;
|
|
leadingSign = false;
|
|
leadingSpace = false;
|
|
alternateForm = false;
|
|
leadingZeros = false;
|
|
for (; pos < fmt.length(); pos++) {
|
|
char c = fmt.charAt(pos);
|
|
if (c == '\'')
|
|
thousands = true;
|
|
else if (c == '-') {
|
|
leftJustify = true;
|
|
leadingZeros = false;
|
|
} else if (c == '+') {
|
|
leadingSign = true;
|
|
leadingSpace = false;
|
|
} else if (c == ' ') {
|
|
if (!leadingSign)
|
|
leadingSpace = true;
|
|
} else if (c == '#')
|
|
alternateForm = true;
|
|
else if (c == '0') {
|
|
if (!leftJustify)
|
|
leadingZeros = true;
|
|
} else
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The integer portion of the result of a decimal conversion (i, d, u, f, g, or G) will be formatted with
|
|
* thousands' grouping characters. For other conversions the flag is ignored.
|
|
*/
|
|
private boolean thousands = false;
|
|
|
|
/**
|
|
* The result of the conversion will be left-justified within the field.
|
|
*/
|
|
private boolean leftJustify = false;
|
|
|
|
/**
|
|
* The result of a signed conversion will always begin with a sign (+ or -).
|
|
*/
|
|
private boolean leadingSign = false;
|
|
|
|
/**
|
|
* Flag indicating that left padding with spaces is specified.
|
|
*/
|
|
private boolean leadingSpace = false;
|
|
|
|
/**
|
|
* For an o conversion, increase the precision to force the first digit of the result to be a zero. For x (or X)
|
|
* conversions, a non-zero result will have 0x (or 0X) prepended to it. For e, E, f, g, or G conversions, the
|
|
* result will always contain a radix character, even if no digits follow the point. For g and G conversions,
|
|
* trailing zeros will not be removed from the result.
|
|
*/
|
|
private boolean alternateForm = false;
|
|
|
|
/**
|
|
* Flag indicating that left padding with zeroes is specified.
|
|
*/
|
|
private boolean leadingZeros = false;
|
|
|
|
/**
|
|
* Flag indicating that the field width is *.
|
|
*/
|
|
private boolean variableFieldWidth = false;
|
|
|
|
/**
|
|
* If the converted value has fewer bytes than the field width, it will be padded with spaces or zeroes.
|
|
*/
|
|
private int fieldWidth = 0;
|
|
|
|
/**
|
|
* Flag indicating whether or not the field width has been set.
|
|
*/
|
|
private boolean fieldWidthSet = false;
|
|
|
|
/**
|
|
* The minimum number of digits to appear for the d, i, o, u, x, or X conversions. The number of digits to
|
|
* appear after the radix character for the e, E, and f conversions. The maximum number of significant digits
|
|
* for the g and G conversions. The maximum number of bytes to be printed from a string in s and S conversions.
|
|
*/
|
|
private int precision = 0;
|
|
|
|
/** Default precision. */
|
|
private final static int defaultDigits = 6;
|
|
|
|
/**
|
|
* Flag indicating that the precision is *.
|
|
*/
|
|
private boolean variablePrecision = false;
|
|
|
|
/**
|
|
* Flag indicating whether or not the precision has been set.
|
|
*/
|
|
private boolean precisionSet = false;
|
|
|
|
/*
|
|
*/
|
|
private boolean positionalSpecification = false;
|
|
|
|
private int argumentPosition = 0;
|
|
|
|
private boolean positionalFieldWidth = false;
|
|
|
|
private int argumentPositionForFieldWidth = 0;
|
|
|
|
private boolean positionalPrecision = false;
|
|
|
|
private int argumentPositionForPrecision = 0;
|
|
|
|
/**
|
|
* Flag specifying that a following d, i, o, u, x, or X conversion character applies to a type short int.
|
|
*/
|
|
private boolean optionalh = false;
|
|
|
|
/**
|
|
* Flag specifying that a following d, i, o, u, x, or X conversion character applies to a type lont int
|
|
* argument.
|
|
*/
|
|
private boolean optionall = false;
|
|
|
|
/**
|
|
* Flag specifying that a following e, E, f, g, or G conversion character applies to a type double argument.
|
|
* This is a noop in Java.
|
|
*/
|
|
private boolean optionalL = false;
|
|
|
|
/** Control string type. */
|
|
private char conversionCharacter = '\0';
|
|
|
|
/**
|
|
* Position within the control string. Used by the constructor.
|
|
*/
|
|
private int pos = 0;
|
|
|
|
/** Literal or control format string. */
|
|
private String fmt;
|
|
}
|
|
|
|
/** Vector of control strings and format literals. */
|
|
private Vector vFmt = new Vector();
|
|
|
|
/** Character position. Used by the constructor. */
|
|
private int cPos = 0;
|
|
|
|
/** Character position. Used by the constructor. */
|
|
private DecimalFormatSymbols dfs = null;
|
|
}
|