0001: package com.technoetic.xplanner.format;
0002:
0003: //
0004: // (c) 2000 Sun Microsystems, Inc.
0005: // ALL RIGHTS RESERVED
0006: // URL: // http://java.sun.com/developer/technicalArticles/Programming/sprintf/PrintfFormat.java
0007: //
0008: // License Grant-
0009: //
0010: //
0011: // Permission to use, copy, modify, and distribute this Software and its
0012: // documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is
0013: // hereby granted.
0014: //
0015: // This Software is provided "AS IS". All express warranties, including any
0016: // implied warranty of merchantability, satisfactory quality, fitness for a
0017: // particular purpose, or non-infringement, are disclaimed, except to the extent
0018: // that such disclaimers are held to be legally invalid.
0019: //
0020: // You acknowledge that Software is not designed, licensed or intended for use in
0021: // the design, construction, operation or maintenance of any nuclear facility
0022: // ("High Risk Activities"). Sun disclaims any express or implied warranty of
0023: // fitness for such uses.
0024: //
0025: // Please refer to the file http://www.sun.com/policies/trademarks/ for further
0026: // important trademark information and to
0027: // http://java.sun.com/nav/business/index.html for further important licensing
0028: // information for the Java Technology.
0029: //
0030:
0031: import java.text.DecimalFormatSymbols;
0032: import java.util.Enumeration;
0033: import java.util.Locale;
0034: import java.util.Vector;
0035:
0036: /**
0037: * PrintfFormat allows the formatting of an array of
0038: * objects embedded within a string. Primitive types
0039: * must be passed using wrapper types. The formatting
0040: * is controlled by a control string.
0041: *<p>
0042: * A control string is a Java string that contains a
0043: * control specification. The control specification
0044: * starts at the first percent sign (%) in the string,
0045: * provided that this percent sign
0046: *<ol>
0047: *<li>is not escaped protected by a matching % or is
0048: * not an escape % character,
0049: *<li>is not at the end of the format string, and
0050: *<li>precedes a sequence of characters that parses as
0051: * a valid control specification.
0052: *</ol>
0053: *</p><p>
0054: * A control specification usually takes the form:
0055: *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
0056: * { [hlL] }+ [idfgGoxXeEcs]
0057: *</pre>
0058: * There are variants of this basic form that are
0059: * discussed below.</p>
0060: *<p>
0061: * The format is composed of zero or more directives
0062: * defined as follows:
0063: *<ul>
0064: *<li>ordinary characters, which are simply copied to
0065: * the output stream;
0066: *<li>escape sequences, which represent non-graphic
0067: * characters; and
0068: *<li>conversion specifications, each of which
0069: * results in the fetching of zero or more arguments.
0070: *</ul></p>
0071: *<p>
0072: * The results are undefined if there are insufficient
0073: * arguments for the format. Usually an unchecked
0074: * exception will be thrown. If the format is
0075: * exhausted while arguments remain, the excess
0076: * arguments are evaluated but are otherwise ignored.
0077: * In format strings containing the % form of
0078: * conversion specifications, each argument in the
0079: * argument list is used exactly once.</p>
0080: * <p>
0081: * Conversions can be applied to the <code>n</code>th
0082: * argument after the format in the argument list,
0083: * rather than to the next unused argument. In this
0084: * case, the conversion characer % is replaced by the
0085: * sequence %<code>n</code>$, where <code>n</code> is
0086: * a decimal integer giving the position of the
0087: * argument in the argument list.</p>
0088: * <p>
0089: * In format strings containing the %<code>n</code>$
0090: * form of conversion specifications, each argument
0091: * in the argument list is used exactly once.</p>
0092: *
0093: *<h4>Escape Sequences</h4>
0094: *<p>
0095: * The following table lists escape sequences and
0096: * associated actions on display devices capable of
0097: * the action.
0098: *<table>
0099: *<tr><th align=left>Sequence</th>
0100: * <th align=left>Name</th>
0101: * <th align=left>Description</th></tr>
0102: *<tr><td>\\</td><td>backlash</td><td>None.
0103: *</td></tr>
0104: *<tr><td>\a</td><td>alert</td><td>Attempts to alert
0105: * the user through audible or visible
0106: * notification.
0107: *</td></tr>
0108: *<tr><td>\b</td><td>backspace</td><td>Moves the
0109: * printing position to one column before
0110: * the current position, unless the
0111: * current position is the start of a line.
0112: *</td></tr>
0113: *<tr><td>\f</td><td>form-feed</td><td>Moves the
0114: * printing position to the initial
0115: * printing position of the next logical
0116: * page.
0117: *</td></tr>
0118: *<tr><td>\n</td><td>newline</td><td>Moves the
0119: * printing position to the start of the
0120: * next line.
0121: *</td></tr>
0122: *<tr><td>\r</td><td>carriage-return</td><td>Moves
0123: * the printing position to the start of
0124: * the current line.
0125: *</td></tr>
0126: *<tr><td>\t</td><td>tab</td><td>Moves the printing
0127: * position to the next implementation-
0128: * defined horizontal tab position.
0129: *</td></tr>
0130: *<tr><td>\v</td><td>vertical-tab</td><td>Moves the
0131: * printing position to the start of the
0132: * next implementation-defined vertical
0133: * tab position.
0134: *</td></tr>
0135: *</table></p>
0136: *<h4>Conversion Specifications</h4>
0137: *<p>
0138: * Each conversion specification is introduced by
0139: * the percent sign character (%). After the character
0140: * %, the following appear in sequence:</p>
0141: *<p>
0142: * Zero or more flags (in any order), which modify the
0143: * meaning of the conversion specification.</p>
0144: *<p>
0145: * An optional minimum field width. If the converted
0146: * value has fewer characters than the field width, it
0147: * will be padded with spaces by default on the left;
0148: * t will be padded on the right, if the left-
0149: * adjustment flag (-), described below, is given to
0150: * the field width. The field width takes the form
0151: * of a decimal integer. If the conversion character
0152: * is s, the field width is the the minimum number of
0153: * characters to be printed.</p>
0154: *<p>
0155: * An optional precision that gives the minumum number
0156: * of digits to appear for the d, i, o, x or X
0157: * conversions (the field is padded with leading
0158: * zeros); the number of digits to appear after the
0159: * radix character for the e, E, and f conversions,
0160: * the maximum number of significant digits for the g
0161: * and G conversions; or the maximum number of
0162: * characters to be written from a string is s and S
0163: * conversions. The precision takes the form of an
0164: * optional decimal digit string, where a null digit
0165: * string is treated as 0. If a precision appears
0166: * with a c conversion character the precision is
0167: * ignored.
0168: * </p>
0169: *<p>
0170: * An optional h specifies that a following d, i, o,
0171: * x, or X conversion character applies to a type
0172: * short argument (the argument will be promoted
0173: * according to the integral promotions and its value
0174: * converted to type short before printing).</p>
0175: *<p>
0176: * An optional l (ell) specifies that a following
0177: * d, i, o, x, or X conversion character applies to a
0178: * type long argument.</p>
0179: *<p>
0180: * A field width or precision may be indicated by an
0181: * asterisk (*) instead of a digit string. In this
0182: * case, an integer argument supplised the field width
0183: * precision. The argument that is actually converted
0184: * is not fetched until the conversion letter is seen,
0185: * so the the arguments specifying field width or
0186: * precision must appear before the argument (if any)
0187: * to be converted. If the precision argument is
0188: * negative, it will be changed to zero. A negative
0189: * field width argument is taken as a - flag, followed
0190: * by a positive field width.</p>
0191: * <p>
0192: * In format strings containing the %<code>n</code>$
0193: * form of a conversion specification, a field width
0194: * or precision may be indicated by the sequence
0195: * *<code>m</code>$, where m is a decimal integer
0196: * giving the position in the argument list (after the
0197: * format argument) of an integer argument containing
0198: * the field width or precision.</p>
0199: * <p>
0200: * The format can contain either numbered argument
0201: * specifications (that is, %<code>n</code>$ and
0202: * *<code>m</code>$), or unnumbered argument
0203: * specifications (that is % and *), but normally not
0204: * both. The only exception to this is that %% can
0205: * be mixed with the %<code>n</code>$ form. The
0206: * results of mixing numbered and unnumbered argument
0207: * specifications in a format string are undefined.</p>
0208: *
0209: *<h4>Flag Characters</h4>
0210: *<p>
0211: * The flags and their meanings are:</p>
0212: *<dl>
0213: * <dt>'<dd> integer portion of the result of a
0214: * decimal conversion (%i, %d, %f, %g, or %G) will
0215: * be formatted with thousands' grouping
0216: * characters. For other conversions the flag
0217: * is ignored. The non-monetary grouping
0218: * character is used.
0219: * <dt>-<dd> result of the conversion is left-justified
0220: * within the field. (It will be right-justified
0221: * if this flag is not specified).</td></tr>
0222: * <dt>+<dd> result of a signed conversion always
0223: * begins with a sign (+ or -). (It will begin
0224: * with a sign only when a negative value is
0225: * converted if this flag is not specified.)
0226: * <dt><space><dd> If the first character of a
0227: * signed conversion is not a sign, a space
0228: * character will be placed before the result.
0229: * This means that if the space character and +
0230: * flags both appear, the space flag will be
0231: * ignored.
0232: * <dt>#<dd> value is to be converted to an alternative
0233: * form. For c, d, i, and s conversions, the flag
0234: * has no effect. For o conversion, it increases
0235: * the precision to force the first digit of the
0236: * result to be a zero. For x or X conversion, a
0237: * non-zero result has 0x or 0X prefixed to it,
0238: * respectively. For e, E, f, g, and G
0239: * conversions, the result always contains a radix
0240: * character, even if no digits follow the radix
0241: * character (normally, a decimal point appears in
0242: * the result of these conversions only if a digit
0243: * follows it). For g and G conversions, trailing
0244: * zeros will not be removed from the result as
0245: * they normally are.
0246: * <dt>0<dd> d, i, o, x, X, e, E, f, g, and G
0247: * conversions, leading zeros (following any
0248: * indication of sign or base) are used to pad to
0249: * the field width; no space padding is
0250: * performed. If the 0 and - flags both appear,
0251: * the 0 flag is ignored. For d, i, o, x, and X
0252: * conversions, if a precision is specified, the
0253: * 0 flag will be ignored. For c conversions,
0254: * the flag is ignored.
0255: *</dl>
0256: *
0257: *<h4>Conversion Characters</h4>
0258: *<p>
0259: * Each conversion character results in fetching zero
0260: * or more arguments. The results are undefined if
0261: * there are insufficient arguments for the format.
0262: * Usually, an unchecked exception will be thrown.
0263: * If the format is exhausted while arguments remain,
0264: * the excess arguments are ignored.</p>
0265: *
0266: *<p>
0267: * The conversion characters and their meanings are:
0268: *</p>
0269: *<dl>
0270: * <dt>d,i<dd>The int argument is converted to a
0271: * signed decimal in the style [-]dddd. The
0272: * precision specifies the minimum number of
0273: * digits to appear; if the value being
0274: * converted can be represented in fewer
0275: * digits, it will be expanded with leading
0276: * zeros. The default precision is 1. The
0277: * result of converting 0 with an explicit
0278: * precision of 0 is no characters.
0279: * <dt>o<dd> The int argument is converted to unsigned
0280: * octal format in the style ddddd. The
0281: * precision specifies the minimum number of
0282: * digits to appear; if the value being
0283: * converted can be represented in fewer
0284: * digits, it will be expanded with leading
0285: * zeros. The default precision is 1. The
0286: * result of converting 0 with an explicit
0287: * precision of 0 is no characters.
0288: * <dt>x<dd> The int argument is converted to unsigned
0289: * hexadecimal format in the style dddd; the
0290: * letters abcdef are used. The precision
0291: * specifies the minimum numberof digits to
0292: * appear; if the value being converted can be
0293: * represented in fewer digits, it will be
0294: * expanded with leading zeros. The default
0295: * precision is 1. The result of converting 0
0296: * with an explicit precision of 0 is no
0297: * characters.
0298: * <dt>X<dd> Behaves the same as the x conversion
0299: * character except that letters ABCDEF are
0300: * used instead of abcdef.
0301: * <dt>f<dd> The floating point number argument is
0302: * written in decimal notation in the style
0303: * [-]ddd.ddd, where the number of digits after
0304: * the radix character (shown here as a decimal
0305: * point) is equal to the precision
0306: * specification. A Locale is used to determine
0307: * the radix character to use in this format.
0308: * If the precision is omitted from the
0309: * argument, six digits are written after the
0310: * radix character; if the precision is
0311: * explicitly 0 and the # flag is not specified,
0312: * no radix character appears. If a radix
0313: * character appears, at least 1 digit appears
0314: * before it. The value is rounded to the
0315: * appropriate number of digits.
0316: * <dt>e,E<dd>The floating point number argument is
0317: * written in the style [-]d.ddde{+-}dd
0318: * (the symbols {+-} indicate either a plus or
0319: * minus sign), where there is one digit before
0320: * the radix character (shown here as a decimal
0321: * point) and the number of digits after it is
0322: * equal to the precision. A Locale is used to
0323: * determine the radix character to use in this
0324: * format. When the precision is missing, six
0325: * digits are written after the radix character;
0326: * if the precision is 0 and the # flag is not
0327: * specified, no radix character appears. The
0328: * E conversion will produce a number with E
0329: * instead of e introducing the exponent. The
0330: * exponent always contains at least two digits.
0331: * However, if the value to be written requires
0332: * an exponent greater than two digits,
0333: * additional exponent digits are written as
0334: * necessary. The value is rounded to the
0335: * appropriate number of digits.
0336: * <dt>g,G<dd>The floating point number argument is
0337: * written in style f or e (or in sytle E in the
0338: * case of a G conversion character), with the
0339: * precision specifying the number of
0340: * significant digits. If the precision is
0341: * zero, it is taken as one. The style used
0342: * depends on the value converted: style e
0343: * (or E) will be used only if the exponent
0344: * resulting from the conversion is less than
0345: * -4 or greater than or equal to the precision.
0346: * Trailing zeros are removed from the result.
0347: * A radix character appears only if it is
0348: * followed by a digit.
0349: * <dt>c,C<dd>The integer argument is converted to a
0350: * char and the result is written.
0351: *
0352: * <dt>s,S<dd>The argument is taken to be a string and
0353: * bytes from the string are written until the
0354: * end of the string or the number of bytes
0355: * indicated by the precision specification of
0356: * the argument is reached. If the precision
0357: * is omitted from the argument, it is taken to
0358: * be infinite, so all characters up to the end
0359: * of the string are written.
0360: * <dt>%<dd>Write a % character; no argument is
0361: * converted.
0362: *</dl>
0363: *<p>
0364: * If a conversion specification does not match one of
0365: * the above forms, an IllegalArgumentException is
0366: * thrown and the instance of PrintfFormat is not
0367: * created.</p>
0368: *<p>
0369: * If a floating point value is the internal
0370: * representation for infinity, the output is
0371: * [+]Infinity, where Infinity is either Infinity or
0372: * Inf, depending on the desired output string length.
0373: * Printing of the sign follows the rules described
0374: * above.</p>
0375: *<p>
0376: * If a floating point value is the internal
0377: * representation for "not-a-number," the output is
0378: * [+]NaN. Printing of the sign follows the rules
0379: * described above.</p>
0380: *<p>
0381: * In no case does a non-existent or small field width
0382: * cause truncation of a field; if the result of a
0383: * conversion is wider than the field width, the field
0384: * is simply expanded to contain the conversion result.
0385: *</p>
0386: *<p>
0387: * The behavior is like printf. One exception is that
0388: * the minimum number of exponent digits is 3 instead
0389: * of 2 for e and E formats when the optional L is used
0390: * before the e, E, g, or G conversion character. The
0391: * optional L does not imply conversion to a long long
0392: * double. </p>
0393: * <p>
0394: * The biggest divergence from the C printf
0395: * specification is in the use of 16 bit characters.
0396: * This allows the handling of characters beyond the
0397: * small ASCII character set and allows the utility to
0398: * interoperate correctly with the rest of the Java
0399: * runtime environment.</p>
0400: *<p>
0401: * Omissions from the C printf specification are
0402: * numerous. All the known omissions are present
0403: * because Java never uses bytes to represent
0404: * characters and does not have pointers:</p>
0405: *<ul>
0406: * <li>%c is the same as %C.
0407: * <li>%s is the same as %S.
0408: * <li>u, p, and n conversion characters.
0409: * <li>%ws format.
0410: * <li>h modifier applied to an n conversion character.
0411: * <li>l (ell) modifier applied to the c, n, or s
0412: * conversion characters.
0413: * <li>ll (ell ell) modifier to d, i, o, u, x, or X
0414: * conversion characters.
0415: * <li>ll (ell ell) modifier to an n conversion
0416: * character.
0417: * <li>c, C, d,i,o,u,x, and X conversion characters
0418: * apply to Byte, Character, Short, Integer, Long
0419: * types.
0420: * <li>f, e, E, g, and G conversion characters apply
0421: * to Float and Double types.
0422: * <li>s and S conversion characters apply to String
0423: * types.
0424: * <li>All other reference types can be formatted
0425: * using the s or S conversion characters only.
0426: *</ul>
0427: * <p>
0428: * Most of this specification is quoted from the Unix
0429: * man page for the sprintf utility.</p>
0430: *
0431: * @author Allan Jacobs
0432: * @version 1
0433: * Release 1: Initial release.
0434: * Release 2: Asterisk field widths and precisions
0435: * %n$ and *m$
0436: * Bug fixes
0437: * g format fix (2 digits in e form corrupt)
0438: * rounding in f format implemented
0439: * round up when digit not printed is 5
0440: * formatting of -0.0f
0441: * round up/down when last digits are 50000...
0442: */
0443: public class PrintfFormat {
0444: /**
0445: * Constructs an array of control specifications
0446: * possibly preceded, separated, or followed by
0447: * ordinary strings. Control strings begin with
0448: * unpaired percent signs. A pair of successive
0449: * percent signs designates a single percent sign in
0450: * the format.
0451: * @param fmtArg Control string.
0452: * @exception java.lang.IllegalArgumentException if the control
0453: * string is null, zero length, or otherwise
0454: * malformed.
0455: */
0456: public PrintfFormat(String fmtArg) throws IllegalArgumentException {
0457: this (Locale.getDefault(), fmtArg);
0458: }
0459:
0460: /**
0461: * Constructs an array of control specifications
0462: * possibly preceded, separated, or followed by
0463: * ordinary strings. Control strings begin with
0464: * unpaired percent signs. A pair of successive
0465: * percent signs designates a single percent sign in
0466: * the format.
0467: * @param fmtArg Control string.
0468: * @exception java.lang.IllegalArgumentException if the control
0469: * string is null, zero length, or otherwise
0470: * malformed.
0471: */
0472: public PrintfFormat(Locale locale, String fmtArg)
0473: throws IllegalArgumentException {
0474: dfs = new DecimalFormatSymbols(locale);
0475: int ePos = 0;
0476: ConversionSpecification sFmt = null;
0477: String unCS = this .nonControl(fmtArg, 0);
0478: if (unCS != null) {
0479: sFmt = new ConversionSpecification();
0480: sFmt.setLiteral(unCS);
0481: vFmt.addElement(sFmt);
0482: }
0483: while (cPos != -1 && cPos < fmtArg.length()) {
0484: for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) {
0485: char c = 0;
0486: c = fmtArg.charAt(ePos);
0487: if (c == 'i')
0488: break;
0489: if (c == 'd')
0490: break;
0491: if (c == 'f')
0492: break;
0493: if (c == 'g')
0494: break;
0495: if (c == 'G')
0496: break;
0497: if (c == 'o')
0498: break;
0499: if (c == 'x')
0500: break;
0501: if (c == 'X')
0502: break;
0503: if (c == 'e')
0504: break;
0505: if (c == 'E')
0506: break;
0507: if (c == 'c')
0508: break;
0509: if (c == 's')
0510: break;
0511: if (c == '%')
0512: break;
0513: }
0514: ePos = Math.min(ePos + 1, fmtArg.length());
0515: sFmt = new ConversionSpecification(fmtArg.substring(cPos,
0516: ePos));
0517: vFmt.addElement(sFmt);
0518: unCS = this .nonControl(fmtArg, ePos);
0519: if (unCS != null) {
0520: sFmt = new ConversionSpecification();
0521: sFmt.setLiteral(unCS);
0522: vFmt.addElement(sFmt);
0523: }
0524: }
0525: }
0526:
0527: /**
0528: * Return a substring starting at
0529: * <code>start</code> and ending at either the end
0530: * of the String <code>s</code>, the next unpaired
0531: * percent sign, or at the end of the String if the
0532: * last character is a percent sign.
0533: * @param s Control string.
0534: * @param start Position in the string
0535: * <code>s</code> to begin looking for the start
0536: * of a control string.
0537: * @return the substring from the start position
0538: * to the beginning of the control string.
0539: */
0540: private String nonControl(String s, int start) {
0541: String ret = "";
0542: cPos = s.indexOf("%", start);
0543: if (cPos == -1)
0544: cPos = s.length();
0545: return s.substring(start, cPos);
0546: }
0547:
0548: /**
0549: * Format an array of objects. Byte, Short,
0550: * Integer, Long, Float, Double, and Character
0551: * arguments are treated as wrappers for primitive
0552: * types.
0553: * @param o The array of objects to format.
0554: * @return The formatted String.
0555: */
0556: public String sprintf(Object[] o) {
0557: Enumeration e = vFmt.elements();
0558: ConversionSpecification cs = null;
0559: char c = 0;
0560: int i = 0;
0561: StringBuffer sb = new StringBuffer();
0562: while (e.hasMoreElements()) {
0563: cs = (ConversionSpecification) e.nextElement();
0564: c = cs.getConversionCharacter();
0565: if (c == '\0')
0566: sb.append(cs.getLiteral());
0567: else if (c == '%')
0568: sb.append("%");
0569: else {
0570: if (cs.isPositionalSpecification()) {
0571: i = cs.getArgumentPosition() - 1;
0572: if (cs.isPositionalFieldWidth()) {
0573: int ifw = cs.getArgumentPositionForFieldWidth() - 1;
0574: cs.setFieldWidthWithArg(((Integer) o[ifw])
0575: .intValue());
0576: }
0577: if (cs.isPositionalPrecision()) {
0578: int ipr = cs.getArgumentPositionForPrecision() - 1;
0579: cs.setPrecisionWithArg(((Integer) o[ipr])
0580: .intValue());
0581: }
0582: } else {
0583: if (cs.isVariableFieldWidth()) {
0584: cs.setFieldWidthWithArg(((Integer) o[i])
0585: .intValue());
0586: i++;
0587: }
0588: if (cs.isVariablePrecision()) {
0589: cs.setPrecisionWithArg(((Integer) o[i])
0590: .intValue());
0591: i++;
0592: }
0593: }
0594: if (o[i] instanceof Byte)
0595: sb.append(cs.internalsprintf(((Byte) o[i])
0596: .byteValue()));
0597: else if (o[i] instanceof Short)
0598: sb.append(cs.internalsprintf(((Short) o[i])
0599: .shortValue()));
0600: else if (o[i] instanceof Integer)
0601: sb.append(cs.internalsprintf(((Integer) o[i])
0602: .intValue()));
0603: else if (o[i] instanceof Long)
0604: sb.append(cs.internalsprintf(((Long) o[i])
0605: .longValue()));
0606: else if (o[i] instanceof Float)
0607: sb.append(cs.internalsprintf(((Float) o[i])
0608: .floatValue()));
0609: else if (o[i] instanceof Double)
0610: sb.append(cs.internalsprintf(((Double) o[i])
0611: .doubleValue()));
0612: else if (o[i] instanceof Character)
0613: sb.append(cs.internalsprintf(((Character) o[i])
0614: .charValue()));
0615: else if (o[i] instanceof String)
0616: sb.append(cs.internalsprintf((String) o[i]));
0617: else
0618: sb.append(cs.internalsprintf(o[i]));
0619: if (!cs.isPositionalSpecification())
0620: i++;
0621: }
0622: }
0623: return sb.toString();
0624: }
0625:
0626: /**
0627: * Format nothing. Just use the control string.
0628: * @return the formatted String.
0629: */
0630: public String sprintf() {
0631: Enumeration e = vFmt.elements();
0632: ConversionSpecification cs = null;
0633: char c = 0;
0634: StringBuffer sb = new StringBuffer();
0635: while (e.hasMoreElements()) {
0636: cs = (ConversionSpecification) e.nextElement();
0637: c = cs.getConversionCharacter();
0638: if (c == '\0')
0639: sb.append(cs.getLiteral());
0640: else if (c == '%')
0641: sb.append("%");
0642: }
0643: return sb.toString();
0644: }
0645:
0646: /**
0647: * Format an int.
0648: * @param x The int to format.
0649: * @return The formatted String.
0650: * @exception java.lang.IllegalArgumentException if the
0651: * conversion character is f, e, E, g, G, s,
0652: * or S.
0653: */
0654: public String sprintf(int x) throws IllegalArgumentException {
0655: Enumeration e = vFmt.elements();
0656: ConversionSpecification cs = null;
0657: char c = 0;
0658: StringBuffer sb = new StringBuffer();
0659: while (e.hasMoreElements()) {
0660: cs = (ConversionSpecification) e.nextElement();
0661: c = cs.getConversionCharacter();
0662: if (c == '\0')
0663: sb.append(cs.getLiteral());
0664: else if (c == '%')
0665: sb.append("%");
0666: else
0667: sb.append(cs.internalsprintf(x));
0668: }
0669: return sb.toString();
0670: }
0671:
0672: /**
0673: * Format an long.
0674: * @param x The long to format.
0675: * @return The formatted String.
0676: * @exception java.lang.IllegalArgumentException if the
0677: * conversion character is f, e, E, g, G, s,
0678: * or S.
0679: */
0680: public String sprintf(long x) throws IllegalArgumentException {
0681: Enumeration e = vFmt.elements();
0682: ConversionSpecification cs = null;
0683: char c = 0;
0684: StringBuffer sb = new StringBuffer();
0685: while (e.hasMoreElements()) {
0686: cs = (ConversionSpecification) e.nextElement();
0687: c = cs.getConversionCharacter();
0688: if (c == '\0')
0689: sb.append(cs.getLiteral());
0690: else if (c == '%')
0691: sb.append("%");
0692: else
0693: sb.append(cs.internalsprintf(x));
0694: }
0695: return sb.toString();
0696: }
0697:
0698: /**
0699: * Format a double.
0700: * @param x The double to format.
0701: * @return The formatted String.
0702: * @exception java.lang.IllegalArgumentException if the
0703: * conversion character is c, C, s, S,
0704: * d, d, x, X, or o.
0705: */
0706: public String sprintf(double x) throws IllegalArgumentException {
0707: Enumeration e = vFmt.elements();
0708: ConversionSpecification cs = null;
0709: char c = 0;
0710: StringBuffer sb = new StringBuffer();
0711: while (e.hasMoreElements()) {
0712: cs = (ConversionSpecification) e.nextElement();
0713: c = cs.getConversionCharacter();
0714: if (c == '\0')
0715: sb.append(cs.getLiteral());
0716: else if (c == '%')
0717: sb.append("%");
0718: else
0719: sb.append(cs.internalsprintf(x));
0720: }
0721: return sb.toString();
0722: }
0723:
0724: /**
0725: * Format a String.
0726: * @param x The String to format.
0727: * @return The formatted String.
0728: * @exception java.lang.IllegalArgumentException if the
0729: * conversion character is neither s nor S.
0730: */
0731: public String sprintf(String x) throws IllegalArgumentException {
0732: Enumeration e = vFmt.elements();
0733: ConversionSpecification cs = null;
0734: char c = 0;
0735: StringBuffer sb = new StringBuffer();
0736: while (e.hasMoreElements()) {
0737: cs = (ConversionSpecification) e.nextElement();
0738: c = cs.getConversionCharacter();
0739: if (c == '\0')
0740: sb.append(cs.getLiteral());
0741: else if (c == '%')
0742: sb.append("%");
0743: else
0744: sb.append(cs.internalsprintf(x));
0745: }
0746: return sb.toString();
0747: }
0748:
0749: /**
0750: * Format an Object. Convert wrapper types to
0751: * their primitive equivalents and call the
0752: * appropriate internal formatting method. Convert
0753: * Strings using an internal formatting method for
0754: * Strings. Otherwise use the default formatter
0755: * (use toString).
0756: * @param x the Object to format.
0757: * @return the formatted String.
0758: * @exception java.lang.IllegalArgumentException if the
0759: * conversion character is inappropriate for
0760: * formatting an unwrapped value.
0761: */
0762: public String sprintf(Object x) throws IllegalArgumentException {
0763: Enumeration e = vFmt.elements();
0764: ConversionSpecification cs = null;
0765: char c = 0;
0766: StringBuffer sb = new StringBuffer();
0767: while (e.hasMoreElements()) {
0768: cs = (ConversionSpecification) e.nextElement();
0769: c = cs.getConversionCharacter();
0770: if (c == '\0')
0771: sb.append(cs.getLiteral());
0772: else if (c == '%')
0773: sb.append("%");
0774: else {
0775: if (x instanceof Byte)
0776: sb.append(cs
0777: .internalsprintf(((Byte) x).byteValue()));
0778: else if (x instanceof Short)
0779: sb.append(cs.internalsprintf(((Short) x)
0780: .shortValue()));
0781: else if (x instanceof Integer)
0782: sb.append(cs.internalsprintf(((Integer) x)
0783: .intValue()));
0784: else if (x instanceof Long)
0785: sb.append(cs
0786: .internalsprintf(((Long) x).longValue()));
0787: else if (x instanceof Float)
0788: sb.append(cs.internalsprintf(((Float) x)
0789: .floatValue()));
0790: else if (x instanceof Double)
0791: sb.append(cs.internalsprintf(((Double) x)
0792: .doubleValue()));
0793: else if (x instanceof Character)
0794: sb.append(cs.internalsprintf(((Character) x)
0795: .charValue()));
0796: else if (x instanceof String)
0797: sb.append(cs.internalsprintf((String) x));
0798: else
0799: sb.append(cs.internalsprintf(x));
0800: }
0801: }
0802: return sb.toString();
0803: }
0804:
0805: /**
0806: *<p>
0807: * ConversionSpecification allows the formatting of
0808: * a single primitive or object embedded within a
0809: * string. The formatting is controlled by a
0810: * format string. Only one Java primitive or
0811: * object can be formatted at a time.
0812: *<p>
0813: * A format string is a Java string that contains
0814: * a control string. The control string starts at
0815: * the first percent sign (%) in the string,
0816: * provided that this percent sign
0817: *<ol>
0818: *<li>is not escaped protected by a matching % or
0819: * is not an escape % character,
0820: *<li>is not at the end of the format string, and
0821: *<li>precedes a sequence of characters that parses
0822: * as a valid control string.
0823: *</ol>
0824: *<p>
0825: * A control string takes the form:
0826: *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
0827: * { [hlL] }+ [idfgGoxXeEcs]
0828: *</pre>
0829: *<p>
0830: * The behavior is like printf. One (hopefully the
0831: * only) exception is that the minimum number of
0832: * exponent digits is 3 instead of 2 for e and E
0833: * formats when the optional L is used before the
0834: * e, E, g, or G conversion character. The
0835: * optional L does not imply conversion to a long
0836: * long double.
0837: */
0838: private class ConversionSpecification {
0839: /**
0840: * Constructor. Used to prepare an instance
0841: * to hold a literal, not a control string.
0842: */
0843: ConversionSpecification() {
0844: }
0845:
0846: /**
0847: * Constructor for a conversion specification.
0848: * The argument must begin with a % and end
0849: * with the conversion character for the
0850: * conversion specification.
0851: * @param fmtArg String specifying the
0852: * conversion specification.
0853: * @exception java.lang.IllegalArgumentException if the
0854: * input string is null, zero length, or
0855: * otherwise malformed.
0856: */
0857: ConversionSpecification(String fmtArg)
0858: throws IllegalArgumentException {
0859: if (fmtArg == null)
0860: throw new NullPointerException();
0861: if (fmtArg.length() == 0)
0862: throw new IllegalArgumentException(
0863: "Control strings must have positive"
0864: + " lengths.");
0865: if (fmtArg.charAt(0) == '%') {
0866: fmt = fmtArg;
0867: pos = 1;
0868: setArgPosition();
0869: setFlagCharacters();
0870: setFieldWidth();
0871: setPrecision();
0872: setOptionalHL();
0873: if (setConversionCharacter()) {
0874: if (pos == fmtArg.length()) {
0875: if (leadingZeros && leftJustify)
0876: leadingZeros = false;
0877: if (precisionSet && leadingZeros) {
0878: if (conversionCharacter == 'd'
0879: || conversionCharacter == 'i'
0880: || conversionCharacter == 'o'
0881: || conversionCharacter == 'x') {
0882: leadingZeros = false;
0883: }
0884: }
0885: } else
0886: throw new IllegalArgumentException(
0887: "Malformed conversion specification="
0888: + fmtArg);
0889: } else
0890: throw new IllegalArgumentException(
0891: "Malformed conversion specification="
0892: + fmtArg);
0893: } else
0894: throw new IllegalArgumentException(
0895: "Control strings must begin with %.");
0896: }
0897:
0898: /**
0899: * Set the String for this instance.
0900: * @param s the String to store.
0901: */
0902: void setLiteral(String s) {
0903: fmt = s;
0904: }
0905:
0906: /**
0907: * Get the String for this instance. Translate
0908: * any escape sequences.
0909: *
0910: * @return s the stored String.
0911: */
0912: String getLiteral() {
0913: StringBuffer sb = new StringBuffer();
0914: int i = 0;
0915: while (i < fmt.length()) {
0916: if (fmt.charAt(i) == '\\') {
0917: i++;
0918: if (i < fmt.length()) {
0919: char c = fmt.charAt(i);
0920: switch (c) {
0921: case 'a':
0922: sb.append((char) 0x07);
0923: break;
0924: case 'b':
0925: sb.append('\b');
0926: break;
0927: case 'f':
0928: sb.append('\f');
0929: break;
0930: case 'n':
0931: sb.append(System
0932: .getProperty("line.separator"));
0933: break;
0934: case 'r':
0935: sb.append('\r');
0936: break;
0937: case 't':
0938: sb.append('\t');
0939: break;
0940: case 'v':
0941: sb.append((char) 0x0b);
0942: break;
0943: case '\\':
0944: sb.append('\\');
0945: break;
0946: }
0947: i++;
0948: } else
0949: sb.append('\\');
0950: } else
0951: i++;
0952: }
0953: return fmt;
0954: }
0955:
0956: /**
0957: * Get the conversion character that tells what
0958: * type of control character this instance has.
0959: *
0960: * @return the conversion character.
0961: */
0962: char getConversionCharacter() {
0963: return conversionCharacter;
0964: }
0965:
0966: /**
0967: * Check whether the specifier has a variable
0968: * field width that is going to be set by an
0969: * argument.
0970: * @return <code>true</code> if the conversion
0971: * uses an * field width; otherwise
0972: * <code>false</code>.
0973: */
0974: boolean isVariableFieldWidth() {
0975: return variableFieldWidth;
0976: }
0977:
0978: /**
0979: * Set the field width with an argument. A
0980: * negative field width is taken as a - flag
0981: * followed by a positive field width.
0982: * @param fw the field width.
0983: */
0984: void setFieldWidthWithArg(int fw) {
0985: if (fw < 0)
0986: leftJustify = true;
0987: fieldWidthSet = true;
0988: fieldWidth = Math.abs(fw);
0989: }
0990:
0991: /**
0992: * Check whether the specifier has a variable
0993: * precision that is going to be set by an
0994: * argument.
0995: * @return <code>true</code> if the conversion
0996: * uses an * precision; otherwise
0997: * <code>false</code>.
0998: */
0999: boolean isVariablePrecision() {
1000: return variablePrecision;
1001: }
1002:
1003: /**
1004: * Set the precision with an argument. A
1005: * negative precision will be changed to zero.
1006: * @param pr the precision.
1007: */
1008: void setPrecisionWithArg(int pr) {
1009: precisionSet = true;
1010: precision = Math.max(pr, 0);
1011: }
1012:
1013: /**
1014: * Format an int argument using this conversion
1015: * specification.
1016: * @param s the int to format.
1017: * @return the formatted String.
1018: * @exception java.lang.IllegalArgumentException if the
1019: * conversion character is f, e, E, g, or G.
1020: */
1021: String internalsprintf(int s) throws IllegalArgumentException {
1022: String s2 = "";
1023: switch (conversionCharacter) {
1024: case 'd':
1025: case 'i':
1026: if (optionalh)
1027: s2 = printDFormat((short) s);
1028: else if (optionall)
1029: s2 = printDFormat((long) s);
1030: else
1031: s2 = printDFormat(s);
1032: break;
1033: case 'x':
1034: case 'X':
1035: if (optionalh)
1036: s2 = printXFormat((short) s);
1037: else if (optionall)
1038: s2 = printXFormat((long) s);
1039: else
1040: s2 = printXFormat(s);
1041: break;
1042: case 'o':
1043: if (optionalh)
1044: s2 = printOFormat((short) s);
1045: else if (optionall)
1046: s2 = printOFormat((long) s);
1047: else
1048: s2 = printOFormat(s);
1049: break;
1050: case 'c':
1051: case 'C':
1052: s2 = printCFormat((char) s);
1053: break;
1054: default:
1055: throw new IllegalArgumentException(
1056: "Cannot format a int with a format using a "
1057: + conversionCharacter
1058: + " conversion character.");
1059: }
1060: return s2;
1061: }
1062:
1063: /**
1064: * Format a long argument using this conversion
1065: * specification.
1066: * @param s the long to format.
1067: * @return the formatted String.
1068: * @exception java.lang.IllegalArgumentException if the
1069: * conversion character is f, e, E, g, or G.
1070: */
1071: String internalsprintf(long s) throws IllegalArgumentException {
1072: String s2 = "";
1073: switch (conversionCharacter) {
1074: case 'd':
1075: case 'i':
1076: if (optionalh)
1077: s2 = printDFormat((short) s);
1078: else if (optionall)
1079: s2 = printDFormat(s);
1080: else
1081: s2 = printDFormat((int) s);
1082: break;
1083: case 'x':
1084: case 'X':
1085: if (optionalh)
1086: s2 = printXFormat((short) s);
1087: else if (optionall)
1088: s2 = printXFormat(s);
1089: else
1090: s2 = printXFormat((int) s);
1091: break;
1092: case 'o':
1093: if (optionalh)
1094: s2 = printOFormat((short) s);
1095: else if (optionall)
1096: s2 = printOFormat(s);
1097: else
1098: s2 = printOFormat((int) s);
1099: break;
1100: case 'c':
1101: case 'C':
1102: s2 = printCFormat((char) s);
1103: break;
1104: default:
1105: throw new IllegalArgumentException(
1106: "Cannot format a long with a format using a "
1107: + conversionCharacter
1108: + " conversion character.");
1109: }
1110: return s2;
1111: }
1112:
1113: /**
1114: * Format a double argument using this conversion
1115: * specification.
1116: * @param s the double to format.
1117: * @return the formatted String.
1118: * @exception java.lang.IllegalArgumentException if the
1119: * conversion character is c, C, s, S, i, d,
1120: * x, X, or o.
1121: */
1122: String internalsprintf(double s)
1123: throws IllegalArgumentException {
1124: String s2 = "";
1125: switch (conversionCharacter) {
1126: case 'f':
1127: s2 = printFFormat(s);
1128: break;
1129: case 'E':
1130: case 'e':
1131: s2 = printEFormat(s);
1132: break;
1133: case 'G':
1134: case 'g':
1135: s2 = printGFormat(s);
1136: break;
1137: default:
1138: throw new IllegalArgumentException("Cannot "
1139: + "format a double with a format using a "
1140: + conversionCharacter
1141: + " conversion character.");
1142: }
1143: return s2;
1144: }
1145:
1146: /**
1147: * Format a String argument using this conversion
1148: * specification.
1149: * @param s the String to format.
1150: * @return the formatted String.
1151: * @exception java.lang.IllegalArgumentException if the
1152: * conversion character is neither s nor S.
1153: */
1154: String internalsprintf(String s)
1155: throws IllegalArgumentException {
1156: String s2 = "";
1157: if (conversionCharacter == 's'
1158: || conversionCharacter == 'S')
1159: s2 = printSFormat(s);
1160: else
1161: throw new IllegalArgumentException("Cannot "
1162: + "format a String with a format using a "
1163: + conversionCharacter
1164: + " conversion character.");
1165: return s2;
1166: }
1167:
1168: /**
1169: * Format an Object argument using this conversion
1170: * specification.
1171: * @param s the Object to format.
1172: * @return the formatted String.
1173: * @exception java.lang.IllegalArgumentException if the
1174: * conversion character is neither s nor S.
1175: */
1176: String internalsprintf(Object s) {
1177: String s2 = "";
1178: if (conversionCharacter == 's'
1179: || conversionCharacter == 'S')
1180: s2 = printSFormat(s.toString());
1181: else
1182: throw new IllegalArgumentException(
1183: "Cannot format a String with a format using"
1184: + " a " + conversionCharacter
1185: + " conversion character.");
1186: return s2;
1187: }
1188:
1189: /**
1190: * For f format, the flag character '-', means that
1191: * the output should be left justified within the
1192: * field. The default is to pad with blanks on the
1193: * left. '+' character means that the conversion
1194: * will always begin with a sign (+ or -). The
1195: * blank flag character means that a non-negative
1196: * input will be preceded with a blank. If both
1197: * a '+' and a ' ' are specified, the blank flag
1198: * is ignored. The '0' flag character implies that
1199: * padding to the field width will be done with
1200: * zeros instead of blanks.
1201: *
1202: * The field width is treated as the minimum number
1203: * of characters to be printed. The default is to
1204: * add no padding. Padding is with blanks by
1205: * default.
1206: *
1207: * The precision, if set, is the number of digits
1208: * to appear after the radix character. Padding is
1209: * with trailing 0s.
1210: */
1211: private char[] fFormatDigits(double x) {
1212: // int defaultDigits=6;
1213: String sx, sxOut;
1214: int i, j, k;
1215: int n1In, n2In;
1216: int expon = 0;
1217: boolean minusSign = false;
1218: if (x > 0.0)
1219: sx = Double.toString(x);
1220: else if (x < 0.0) {
1221: sx = Double.toString(-x);
1222: minusSign = true;
1223: } else {
1224: sx = Double.toString(x);
1225: if (sx.charAt(0) == '-') {
1226: minusSign = true;
1227: sx = sx.substring(1);
1228: }
1229: }
1230: int ePos = sx.indexOf('E');
1231: int rPos = sx.indexOf('.');
1232: if (rPos != -1)
1233: n1In = rPos;
1234: else if (ePos != -1)
1235: n1In = ePos;
1236: else
1237: n1In = sx.length();
1238: if (rPos != -1) {
1239: if (ePos != -1)
1240: n2In = ePos - rPos - 1;
1241: else
1242: n2In = sx.length() - rPos - 1;
1243: } else
1244: n2In = 0;
1245: if (ePos != -1) {
1246: int ie = ePos + 1;
1247: expon = 0;
1248: if (sx.charAt(ie) == '-') {
1249: for (++ie; ie < sx.length(); ie++)
1250: if (sx.charAt(ie) != '0')
1251: break;
1252: if (ie < sx.length())
1253: expon = -Integer.parseInt(sx.substring(ie));
1254: } else {
1255: if (sx.charAt(ie) == '+')
1256: ++ie;
1257: for (; ie < sx.length(); ie++)
1258: if (sx.charAt(ie) != '0')
1259: break;
1260: if (ie < sx.length())
1261: expon = Integer.parseInt(sx.substring(ie));
1262: }
1263: }
1264: int p;
1265: if (precisionSet)
1266: p = precision;
1267: else
1268: p = defaultDigits - 1;
1269: char[] ca1 = sx.toCharArray();
1270: char[] ca2 = new char[n1In + n2In];
1271: char[] ca3, ca4, ca5;
1272: for (j = 0; j < n1In; j++)
1273: ca2[j] = ca1[j];
1274: i = j + 1;
1275: for (k = 0; k < n2In; j++, i++, k++)
1276: ca2[j] = ca1[i];
1277: if (n1In + expon <= 0) {
1278: ca3 = new char[-expon + n2In];
1279: for (j = 0, k = 0; k < (-n1In - expon); k++, j++)
1280: ca3[j] = '0';
1281: for (i = 0; i < (n1In + n2In); i++, j++)
1282: ca3[j] = ca2[i];
1283: } else
1284: ca3 = ca2;
1285: boolean carry = false;
1286: if (p < -expon + n2In) {
1287: if (expon < 0)
1288: i = p;
1289: else
1290: i = p + n1In;
1291: carry = checkForCarry(ca3, i);
1292: if (carry)
1293: carry = startSymbolicCarry(ca3, i - 1, 0);
1294: }
1295: if (n1In + expon <= 0) {
1296: ca4 = new char[2 + p];
1297: if (!carry)
1298: ca4[0] = '0';
1299: else
1300: ca4[0] = '1';
1301: if (alternateForm || !precisionSet || precision != 0) {
1302: ca4[1] = '.';
1303: for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++)
1304: ca4[j] = ca3[i];
1305: for (; j < ca4.length; j++)
1306: ca4[j] = '0';
1307: }
1308: } else {
1309: if (!carry) {
1310: if (alternateForm || !precisionSet
1311: || precision != 0)
1312: ca4 = new char[n1In + expon + p + 1];
1313: else
1314: ca4 = new char[n1In + expon];
1315: j = 0;
1316: } else {
1317: if (alternateForm || !precisionSet
1318: || precision != 0)
1319: ca4 = new char[n1In + expon + p + 2];
1320: else
1321: ca4 = new char[n1In + expon + 1];
1322: ca4[0] = '1';
1323: j = 1;
1324: }
1325: for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++)
1326: ca4[j] = ca3[i];
1327: for (; i < n1In + expon; i++, j++)
1328: ca4[j] = '0';
1329: if (alternateForm || !precisionSet || precision != 0) {
1330: ca4[j] = '.';
1331: j++;
1332: for (k = 0; i < ca3.length && k < p; i++, j++, k++)
1333: ca4[j] = ca3[i];
1334: for (; j < ca4.length; j++)
1335: ca4[j] = '0';
1336: }
1337: }
1338: int nZeros = 0;
1339: if (!leftJustify && leadingZeros) {
1340: int xThousands = 0;
1341: if (thousands) {
1342: int xlead = 0;
1343: if (ca4[0] == '+' || ca4[0] == '-' || ca4[0] == ' ')
1344: xlead = 1;
1345: int xdp = xlead;
1346: for (; xdp < ca4.length; xdp++)
1347: if (ca4[xdp] == '.')
1348: break;
1349: xThousands = (xdp - xlead) / 3;
1350: }
1351: if (fieldWidthSet)
1352: nZeros = fieldWidth - ca4.length;
1353: if ((!minusSign && (leadingSign || leadingSpace))
1354: || minusSign)
1355: nZeros--;
1356: nZeros -= xThousands;
1357: if (nZeros < 0)
1358: nZeros = 0;
1359: }
1360: j = 0;
1361: if ((!minusSign && (leadingSign || leadingSpace))
1362: || minusSign) {
1363: ca5 = new char[ca4.length + nZeros + 1];
1364: j++;
1365: } else
1366: ca5 = new char[ca4.length + nZeros];
1367: if (!minusSign) {
1368: if (leadingSign)
1369: ca5[0] = '+';
1370: if (leadingSpace)
1371: ca5[0] = ' ';
1372: } else
1373: ca5[0] = '-';
1374: for (i = 0; i < nZeros; i++, j++)
1375: ca5[j] = '0';
1376: for (i = 0; i < ca4.length; i++, j++)
1377: ca5[j] = ca4[i];
1378:
1379: int lead = 0;
1380: if (ca5[0] == '+' || ca5[0] == '-' || ca5[0] == ' ')
1381: lead = 1;
1382: int dp = lead;
1383: for (; dp < ca5.length; dp++)
1384: if (ca5[dp] == '.')
1385: break;
1386: int nThousands = (dp - lead) / 3;
1387: // Localize the decimal point.
1388: if (dp < ca5.length)
1389: ca5[dp] = dfs.getDecimalSeparator();
1390: char[] ca6 = ca5;
1391: if (thousands && nThousands > 0) {
1392: ca6 = new char[ca5.length + nThousands + lead];
1393: ca6[0] = ca5[0];
1394: for (i = lead, k = lead; i < dp; i++) {
1395: if (i > 0 && (dp - i) % 3 == 0) {
1396: // ca6[k]=',';
1397: ca6[k] = dfs.getGroupingSeparator();
1398: ca6[k + 1] = ca5[i];
1399: k += 2;
1400: } else {
1401: ca6[k] = ca5[i];
1402: k++;
1403: }
1404: }
1405: for (; i < ca5.length; i++, k++) {
1406: ca6[k] = ca5[i];
1407: }
1408: }
1409: return ca6;
1410: }
1411:
1412: /**
1413: * An intermediate routine on the way to creating
1414: * an f format String. The method decides whether
1415: * the input double value is an infinity,
1416: * not-a-number, or a finite double and formats
1417: * each type of input appropriately.
1418: * @param x the double value to be formatted.
1419: * @return the converted double value.
1420: */
1421: private String fFormatString(double x) {
1422: boolean noDigits = false;
1423: char[] ca6, ca7;
1424: if (Double.isInfinite(x)) {
1425: if (x == Double.POSITIVE_INFINITY) {
1426: if (leadingSign)
1427: ca6 = "+Inf".toCharArray();
1428: else if (leadingSpace)
1429: ca6 = " Inf".toCharArray();
1430: else
1431: ca6 = "Inf".toCharArray();
1432: } else
1433: ca6 = "-Inf".toCharArray();
1434: noDigits = true;
1435: } else if (Double.isNaN(x)) {
1436: if (leadingSign)
1437: ca6 = "+NaN".toCharArray();
1438: else if (leadingSpace)
1439: ca6 = " NaN".toCharArray();
1440: else
1441: ca6 = "NaN".toCharArray();
1442: noDigits = true;
1443: } else
1444: ca6 = fFormatDigits(x);
1445: ca7 = applyFloatPadding(ca6, false);
1446: return new String(ca7);
1447: }
1448:
1449: /**
1450: * For e format, the flag character '-', means that
1451: * the output should be left justified within the
1452: * field. The default is to pad with blanks on the
1453: * left. '+' character means that the conversion
1454: * will always begin with a sign (+ or -). The
1455: * blank flag character means that a non-negative
1456: * input will be preceded with a blank. If both a
1457: * '+' and a ' ' are specified, the blank flag is
1458: * ignored. The '0' flag character implies that
1459: * padding to the field width will be done with
1460: * zeros instead of blanks.
1461: *
1462: * The field width is treated as the minimum number
1463: * of characters to be printed. The default is to
1464: * add no padding. Padding is with blanks by
1465: * default.
1466: *
1467: * The precision, if set, is the minimum number of
1468: * digits to appear after the radix character.
1469: * Padding is with trailing 0s.
1470: *
1471: * The behavior is like printf. One (hopefully the
1472: * only) exception is that the minimum number of
1473: * exponent digits is 3 instead of 2 for e and E
1474: * formats when the optional L is used before the
1475: * e, E, g, or G conversion character. The optional
1476: * L does not imply conversion to a long long
1477: * double.
1478: */
1479: private char[] eFormatDigits(double x, char eChar) {
1480: char[] ca1, ca2, ca3;
1481: // int defaultDigits=6;
1482: String sx, sxOut;
1483: int i, j, k, p;
1484: int n1In, n2In;
1485: int expon = 0;
1486: int ePos, rPos, eSize;
1487: boolean minusSign = false;
1488: if (x > 0.0)
1489: sx = Double.toString(x);
1490: else if (x < 0.0) {
1491: sx = Double.toString(-x);
1492: minusSign = true;
1493: } else {
1494: sx = Double.toString(x);
1495: if (sx.charAt(0) == '-') {
1496: minusSign = true;
1497: sx = sx.substring(1);
1498: }
1499: }
1500: ePos = sx.indexOf('E');
1501: if (ePos == -1)
1502: ePos = sx.indexOf('e');
1503: rPos = sx.indexOf('.');
1504: if (rPos != -1)
1505: n1In = rPos;
1506: else if (ePos != -1)
1507: n1In = ePos;
1508: else
1509: n1In = sx.length();
1510: if (rPos != -1) {
1511: if (ePos != -1)
1512: n2In = ePos - rPos - 1;
1513: else
1514: n2In = sx.length() - rPos - 1;
1515: } else
1516: n2In = 0;
1517: if (ePos != -1) {
1518: int ie = ePos + 1;
1519: expon = 0;
1520: if (sx.charAt(ie) == '-') {
1521: for (++ie; ie < sx.length(); ie++)
1522: if (sx.charAt(ie) != '0')
1523: break;
1524: if (ie < sx.length())
1525: expon = -Integer.parseInt(sx.substring(ie));
1526: } else {
1527: if (sx.charAt(ie) == '+')
1528: ++ie;
1529: for (; ie < sx.length(); ie++)
1530: if (sx.charAt(ie) != '0')
1531: break;
1532: if (ie < sx.length())
1533: expon = Integer.parseInt(sx.substring(ie));
1534: }
1535: }
1536: if (rPos != -1)
1537: expon += rPos - 1;
1538: if (precisionSet)
1539: p = precision;
1540: else
1541: p = defaultDigits - 1;
1542: if (rPos != -1 && ePos != -1)
1543: ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1,
1544: ePos)).toCharArray();
1545: else if (rPos != -1)
1546: ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1))
1547: .toCharArray();
1548: else if (ePos != -1)
1549: ca1 = sx.substring(0, ePos).toCharArray();
1550: else
1551: ca1 = sx.toCharArray();
1552: boolean carry = false;
1553: int i0 = 0;
1554: if (ca1[0] != '0')
1555: i0 = 0;
1556: else
1557: for (i0 = 0; i0 < ca1.length; i0++)
1558: if (ca1[i0] != '0')
1559: break;
1560: if (i0 + p < ca1.length - 1) {
1561: carry = checkForCarry(ca1, i0 + p + 1);
1562: if (carry)
1563: carry = startSymbolicCarry(ca1, i0 + p, i0);
1564: if (carry) {
1565: ca2 = new char[i0 + p + 1];
1566: ca2[i0] = '1';
1567: for (j = 0; j < i0; j++)
1568: ca2[j] = '0';
1569: for (i = i0, j = i0 + 1; j < p + 1; i++, j++)
1570: ca2[j] = ca1[i];
1571: expon++;
1572: ca1 = ca2;
1573: }
1574: }
1575: if (Math.abs(expon) < 100 && !optionalL)
1576: eSize = 4;
1577: else
1578: eSize = 5;
1579: if (alternateForm || !precisionSet || precision != 0)
1580: ca2 = new char[2 + p + eSize];
1581: else
1582: ca2 = new char[1 + eSize];
1583: if (ca1[0] != '0') {
1584: ca2[0] = ca1[0];
1585: j = 1;
1586: } else {
1587: for (j = 1; j < (ePos == -1 ? ca1.length : ePos); j++)
1588: if (ca1[j] != '0')
1589: break;
1590: if ((ePos != -1 && j < ePos)
1591: || (ePos == -1 && j < ca1.length)) {
1592: ca2[0] = ca1[j];
1593: expon -= j;
1594: j++;
1595: } else {
1596: ca2[0] = '0';
1597: j = 2;
1598: }
1599: }
1600: if (alternateForm || !precisionSet || precision != 0) {
1601: ca2[1] = '.';
1602: i = 2;
1603: } else
1604: i = 1;
1605: for (k = 0; k < p && j < ca1.length; j++, i++, k++)
1606: ca2[i] = ca1[j];
1607: for (; i < ca2.length - eSize; i++)
1608: ca2[i] = '0';
1609: ca2[i++] = eChar;
1610: if (expon < 0)
1611: ca2[i++] = '-';
1612: else
1613: ca2[i++] = '+';
1614: expon = Math.abs(expon);
1615: if (expon >= 100) {
1616: switch (expon / 100) {
1617: case 1:
1618: ca2[i] = '1';
1619: break;
1620: case 2:
1621: ca2[i] = '2';
1622: break;
1623: case 3:
1624: ca2[i] = '3';
1625: break;
1626: case 4:
1627: ca2[i] = '4';
1628: break;
1629: case 5:
1630: ca2[i] = '5';
1631: break;
1632: case 6:
1633: ca2[i] = '6';
1634: break;
1635: case 7:
1636: ca2[i] = '7';
1637: break;
1638: case 8:
1639: ca2[i] = '8';
1640: break;
1641: case 9:
1642: ca2[i] = '9';
1643: break;
1644: }
1645: i++;
1646: }
1647: switch ((expon % 100) / 10) {
1648: case 0:
1649: ca2[i] = '0';
1650: break;
1651: case 1:
1652: ca2[i] = '1';
1653: break;
1654: case 2:
1655: ca2[i] = '2';
1656: break;
1657: case 3:
1658: ca2[i] = '3';
1659: break;
1660: case 4:
1661: ca2[i] = '4';
1662: break;
1663: case 5:
1664: ca2[i] = '5';
1665: break;
1666: case 6:
1667: ca2[i] = '6';
1668: break;
1669: case 7:
1670: ca2[i] = '7';
1671: break;
1672: case 8:
1673: ca2[i] = '8';
1674: break;
1675: case 9:
1676: ca2[i] = '9';
1677: break;
1678: }
1679: i++;
1680: switch (expon % 10) {
1681: case 0:
1682: ca2[i] = '0';
1683: break;
1684: case 1:
1685: ca2[i] = '1';
1686: break;
1687: case 2:
1688: ca2[i] = '2';
1689: break;
1690: case 3:
1691: ca2[i] = '3';
1692: break;
1693: case 4:
1694: ca2[i] = '4';
1695: break;
1696: case 5:
1697: ca2[i] = '5';
1698: break;
1699: case 6:
1700: ca2[i] = '6';
1701: break;
1702: case 7:
1703: ca2[i] = '7';
1704: break;
1705: case 8:
1706: ca2[i] = '8';
1707: break;
1708: case 9:
1709: ca2[i] = '9';
1710: break;
1711: }
1712: int nZeros = 0;
1713: if (!leftJustify && leadingZeros) {
1714: int xThousands = 0;
1715: if (thousands) {
1716: int xlead = 0;
1717: if (ca2[0] == '+' || ca2[0] == '-' || ca2[0] == ' ')
1718: xlead = 1;
1719: int xdp = xlead;
1720: for (; xdp < ca2.length; xdp++)
1721: if (ca2[xdp] == '.')
1722: break;
1723: xThousands = (xdp - xlead) / 3;
1724: }
1725: if (fieldWidthSet)
1726: nZeros = fieldWidth - ca2.length;
1727: if ((!minusSign && (leadingSign || leadingSpace))
1728: || minusSign)
1729: nZeros--;
1730: nZeros -= xThousands;
1731: if (nZeros < 0)
1732: nZeros = 0;
1733: }
1734: j = 0;
1735: if ((!minusSign && (leadingSign || leadingSpace))
1736: || minusSign) {
1737: ca3 = new char[ca2.length + nZeros + 1];
1738: j++;
1739: } else
1740: ca3 = new char[ca2.length + nZeros];
1741: if (!minusSign) {
1742: if (leadingSign)
1743: ca3[0] = '+';
1744: if (leadingSpace)
1745: ca3[0] = ' ';
1746: } else
1747: ca3[0] = '-';
1748: for (k = 0; k < nZeros; j++, k++)
1749: ca3[j] = '0';
1750: for (i = 0; i < ca2.length && j < ca3.length; i++, j++)
1751: ca3[j] = ca2[i];
1752:
1753: int lead = 0;
1754: if (ca3[0] == '+' || ca3[0] == '-' || ca3[0] == ' ')
1755: lead = 1;
1756: int dp = lead;
1757: for (; dp < ca3.length; dp++)
1758: if (ca3[dp] == '.')
1759: break;
1760: int nThousands = dp / 3;
1761: // Localize the decimal point.
1762: if (dp < ca3.length)
1763: ca3[dp] = dfs.getDecimalSeparator();
1764: char[] ca4 = ca3;
1765: if (thousands && nThousands > 0) {
1766: ca4 = new char[ca3.length + nThousands + lead];
1767: ca4[0] = ca3[0];
1768: for (i = lead, k = lead; i < dp; i++) {
1769: if (i > 0 && (dp - i) % 3 == 0) {
1770: // ca4[k]=',';
1771: ca4[k] = dfs.getGroupingSeparator();
1772: ca4[k + 1] = ca3[i];
1773: k += 2;
1774: } else {
1775: ca4[k] = ca3[i];
1776: k++;
1777: }
1778: }
1779: for (; i < ca3.length; i++, k++)
1780: ca4[k] = ca3[i];
1781: }
1782: return ca4;
1783: }
1784:
1785: /**
1786: * Check to see if the digits that are going to
1787: * be truncated because of the precision should
1788: * force a round in the preceding digits.
1789: * @param ca1 the array of digits
1790: * @param icarry the index of the first digit that
1791: * is to be truncated from the print
1792: * @return <code>true</code> if the truncation forces
1793: * a round that will change the print
1794: */
1795: private boolean checkForCarry(char[] ca1, int icarry) {
1796: boolean carry = false;
1797: if (icarry < ca1.length) {
1798: if (ca1[icarry] == '6' || ca1[icarry] == '7'
1799: || ca1[icarry] == '8' || ca1[icarry] == '9')
1800: carry = true;
1801: else if (ca1[icarry] == '5') {
1802: int ii = icarry + 1;
1803: for (; ii < ca1.length; ii++)
1804: if (ca1[ii] != '0')
1805: break;
1806: carry = ii < ca1.length;
1807: if (!carry && icarry > 0) {
1808: carry = (ca1[icarry - 1] == '1'
1809: || ca1[icarry - 1] == '3'
1810: || ca1[icarry - 1] == '5'
1811: || ca1[icarry - 1] == '7' || ca1[icarry - 1] == '9');
1812: }
1813: }
1814: }
1815: return carry;
1816: }
1817:
1818: /**
1819: * Start the symbolic carry process. The process
1820: * is not quite finished because the symbolic
1821: * carry may change the length of the string and
1822: * change the exponent (in e format).
1823: * @param cLast index of the last digit changed
1824: * by the round
1825: * @param cFirst index of the first digit allowed
1826: * to be changed by this phase of the round
1827: * @return <code>true</code> if the carry forces
1828: * a round that will change the print still
1829: * more
1830: */
1831: private boolean startSymbolicCarry(char[] ca, int cLast,
1832: int cFirst) {
1833: boolean carry = true;
1834: for (int i = cLast; carry && i >= cFirst; i--) {
1835: carry = false;
1836: switch (ca[i]) {
1837: case '0':
1838: ca[i] = '1';
1839: break;
1840: case '1':
1841: ca[i] = '2';
1842: break;
1843: case '2':
1844: ca[i] = '3';
1845: break;
1846: case '3':
1847: ca[i] = '4';
1848: break;
1849: case '4':
1850: ca[i] = '5';
1851: break;
1852: case '5':
1853: ca[i] = '6';
1854: break;
1855: case '6':
1856: ca[i] = '7';
1857: break;
1858: case '7':
1859: ca[i] = '8';
1860: break;
1861: case '8':
1862: ca[i] = '9';
1863: break;
1864: case '9':
1865: ca[i] = '0';
1866: carry = true;
1867: break;
1868: }
1869: }
1870: return carry;
1871: }
1872:
1873: /**
1874: * An intermediate routine on the way to creating
1875: * an e format String. The method decides whether
1876: * the input double value is an infinity,
1877: * not-a-number, or a finite double and formats
1878: * each type of input appropriately.
1879: * @param x the double value to be formatted.
1880: * @param eChar an 'e' or 'E' to use in the
1881: * converted double value.
1882: * @return the converted double value.
1883: */
1884: private String eFormatString(double x, char eChar) {
1885: boolean noDigits = false;
1886: char[] ca4, ca5;
1887: if (Double.isInfinite(x)) {
1888: if (x == Double.POSITIVE_INFINITY) {
1889: if (leadingSign)
1890: ca4 = "+Inf".toCharArray();
1891: else if (leadingSpace)
1892: ca4 = " Inf".toCharArray();
1893: else
1894: ca4 = "Inf".toCharArray();
1895: } else
1896: ca4 = "-Inf".toCharArray();
1897: noDigits = true;
1898: } else if (Double.isNaN(x)) {
1899: if (leadingSign)
1900: ca4 = "+NaN".toCharArray();
1901: else if (leadingSpace)
1902: ca4 = " NaN".toCharArray();
1903: else
1904: ca4 = "NaN".toCharArray();
1905: noDigits = true;
1906: } else
1907: ca4 = eFormatDigits(x, eChar);
1908: ca5 = applyFloatPadding(ca4, false);
1909: return new String(ca5);
1910: }
1911:
1912: /**
1913: * Apply zero or blank, left or right padding.
1914: * @param ca4 array of characters before padding is
1915: * finished
1916: * @param noDigits NaN or signed Inf
1917: * @return a padded array of characters
1918: */
1919: private char[] applyFloatPadding(char[] ca4, boolean noDigits) {
1920: char[] ca5 = ca4;
1921: if (fieldWidthSet) {
1922: int i, j, nBlanks;
1923: if (leftJustify) {
1924: nBlanks = fieldWidth - ca4.length;
1925: if (nBlanks > 0) {
1926: ca5 = new char[ca4.length + nBlanks];
1927: for (i = 0; i < ca4.length; i++)
1928: ca5[i] = ca4[i];
1929: for (j = 0; j < nBlanks; j++, i++)
1930: ca5[i] = ' ';
1931: }
1932: } else if (!leadingZeros || noDigits) {
1933: nBlanks = fieldWidth - ca4.length;
1934: if (nBlanks > 0) {
1935: ca5 = new char[ca4.length + nBlanks];
1936: for (i = 0; i < nBlanks; i++)
1937: ca5[i] = ' ';
1938: for (j = 0; j < ca4.length; i++, j++)
1939: ca5[i] = ca4[j];
1940: }
1941: } else if (leadingZeros) {
1942: nBlanks = fieldWidth - ca4.length;
1943: if (nBlanks > 0) {
1944: ca5 = new char[ca4.length + nBlanks];
1945: i = 0;
1946: j = 0;
1947: if (ca4[0] == '-') {
1948: ca5[0] = '-';
1949: i++;
1950: j++;
1951: }
1952: for (int k = 0; k < nBlanks; i++, k++)
1953: ca5[i] = '0';
1954: for (; j < ca4.length; i++, j++)
1955: ca5[i] = ca4[j];
1956: }
1957: }
1958: }
1959: return ca5;
1960: }
1961:
1962: /**
1963: * Format method for the f conversion character.
1964: * @param x the double to format.
1965: * @return the formatted String.
1966: */
1967: private String printFFormat(double x) {
1968: return fFormatString(x);
1969: }
1970:
1971: /**
1972: * Format method for the e or E conversion
1973: * character.
1974: * @param x the double to format.
1975: * @return the formatted String.
1976: */
1977: private String printEFormat(double x) {
1978: if (conversionCharacter == 'e')
1979: return eFormatString(x, 'e');
1980: else
1981: return eFormatString(x, 'E');
1982: }
1983:
1984: /**
1985: * Format method for the g conversion character.
1986: *
1987: * For g format, the flag character '-', means that
1988: * the output should be left justified within the
1989: * field. The default is to pad with blanks on the
1990: * left. '+' character means that the conversion
1991: * will always begin with a sign (+ or -). The
1992: * blank flag character means that a non-negative
1993: * input will be preceded with a blank. If both a
1994: * '+' and a ' ' are specified, the blank flag is
1995: * ignored. The '0' flag character implies that
1996: * padding to the field width will be done with
1997: * zeros instead of blanks.
1998: *
1999: * The field width is treated as the minimum number
2000: * of characters to be printed. The default is to
2001: * add no padding. Padding is with blanks by
2002: * default.
2003: *
2004: * The precision, if set, is the minimum number of
2005: * digits to appear after the radix character.
2006: * Padding is with trailing 0s.
2007: * @param x the double to format.
2008: * @return the formatted String.
2009: */
2010: private String printGFormat(double x) {
2011: String sx, sy, sz, ret;
2012: int savePrecision = precision;
2013: int i;
2014: char[] ca4, ca5;
2015: boolean noDigits = false;
2016: if (Double.isInfinite(x)) {
2017: if (x == Double.POSITIVE_INFINITY) {
2018: if (leadingSign)
2019: ca4 = "+Inf".toCharArray();
2020: else if (leadingSpace)
2021: ca4 = " Inf".toCharArray();
2022: else
2023: ca4 = "Inf".toCharArray();
2024: } else
2025: ca4 = "-Inf".toCharArray();
2026: noDigits = true;
2027: } else if (Double.isNaN(x)) {
2028: if (leadingSign)
2029: ca4 = "+NaN".toCharArray();
2030: else if (leadingSpace)
2031: ca4 = " NaN".toCharArray();
2032: else
2033: ca4 = "NaN".toCharArray();
2034: noDigits = true;
2035: } else {
2036: if (!precisionSet)
2037: precision = defaultDigits;
2038: if (precision == 0)
2039: precision = 1;
2040: int ePos = -1;
2041: if (conversionCharacter == 'g') {
2042: sx = eFormatString(x, 'e').trim();
2043: ePos = sx.indexOf('e');
2044: } else {
2045: sx = eFormatString(x, 'E').trim();
2046: ePos = sx.indexOf('E');
2047: }
2048: i = ePos + 1;
2049: int expon = 0;
2050: if (sx.charAt(i) == '-') {
2051: for (++i; i < sx.length(); i++)
2052: if (sx.charAt(i) != '0')
2053: break;
2054: if (i < sx.length())
2055: expon = -Integer.parseInt(sx.substring(i));
2056: } else {
2057: if (sx.charAt(i) == '+')
2058: ++i;
2059: for (; i < sx.length(); i++)
2060: if (sx.charAt(i) != '0')
2061: break;
2062: if (i < sx.length())
2063: expon = Integer.parseInt(sx.substring(i));
2064: }
2065: // Trim trailing zeros.
2066: // If the radix character is not followed by
2067: // a digit, trim it, too.
2068: if (!alternateForm) {
2069: if (expon >= -4 && expon < precision)
2070: sy = fFormatString(x).trim();
2071: else
2072: sy = sx.substring(0, ePos);
2073: i = sy.length() - 1;
2074: for (; i >= 0; i--)
2075: if (sy.charAt(i) != '0')
2076: break;
2077: if (i >= 0 && sy.charAt(i) == '.')
2078: i--;
2079: if (i == -1)
2080: sz = "0";
2081: else if (!Character.isDigit(sy.charAt(i)))
2082: sz = sy.substring(0, i + 1) + "0";
2083: else
2084: sz = sy.substring(0, i + 1);
2085: if (expon >= -4 && expon < precision)
2086: ret = sz;
2087: else
2088: ret = sz + sx.substring(ePos);
2089: } else {
2090: if (expon >= -4 && expon < precision)
2091: ret = fFormatString(x).trim();
2092: else
2093: ret = sx;
2094: }
2095: // leading space was trimmed off during
2096: // construction
2097: if (leadingSpace)
2098: if (x >= 0)
2099: ret = " " + ret;
2100: ca4 = ret.toCharArray();
2101: }
2102: // Pad with blanks or zeros.
2103: ca5 = applyFloatPadding(ca4, false);
2104: precision = savePrecision;
2105: return new String(ca5);
2106: }
2107:
2108: /**
2109: * Format method for the d conversion specifer and
2110: * short argument.
2111: *
2112: * For d format, the flag character '-', means that
2113: * the output should be left justified within the
2114: * field. The default is to pad with blanks on the
2115: * left. A '+' character means that the conversion
2116: * will always begin with a sign (+ or -). The
2117: * blank flag character means that a non-negative
2118: * input will be preceded with a blank. If both a
2119: * '+' and a ' ' are specified, the blank flag is
2120: * ignored. The '0' flag character implies that
2121: * padding to the field width will be done with
2122: * zeros instead of blanks.
2123: *
2124: * The field width is treated as the minimum number
2125: * of characters to be printed. The default is to
2126: * add no padding. Padding is with blanks by
2127: * default.
2128: *
2129: * The precision, if set, is the minimum number of
2130: * digits to appear. Padding is with leading 0s.
2131: * @param x the short to format.
2132: * @return the formatted String.
2133: */
2134: private String printDFormat(short x) {
2135: return printDFormat(Short.toString(x));
2136: }
2137:
2138: /**
2139: * Format method for the d conversion character and
2140: * long argument.
2141: *
2142: * For d format, the flag character '-', means that
2143: * the output should be left justified within the
2144: * field. The default is to pad with blanks on the
2145: * left. A '+' character means that the conversion
2146: * will always begin with a sign (+ or -). The
2147: * blank flag character means that a non-negative
2148: * input will be preceded with a blank. If both a
2149: * '+' and a ' ' are specified, the blank flag is
2150: * ignored. The '0' flag character implies that
2151: * padding to the field width will be done with
2152: * zeros instead of blanks.
2153: *
2154: * The field width is treated as the minimum number
2155: * of characters to be printed. The default is to
2156: * add no padding. Padding is with blanks by
2157: * default.
2158: *
2159: * The precision, if set, is the minimum number of
2160: * digits to appear. Padding is with leading 0s.
2161: * @param x the long to format.
2162: * @return the formatted String.
2163: */
2164: private String printDFormat(long x) {
2165: return printDFormat(Long.toString(x));
2166: }
2167:
2168: /**
2169: * Format method for the d conversion character and
2170: * int argument.
2171: *
2172: * For d format, the flag character '-', means that
2173: * the output should be left justified within the
2174: * field. The default is to pad with blanks on the
2175: * left. A '+' character means that the conversion
2176: * will always begin with a sign (+ or -). The
2177: * blank flag character means that a non-negative
2178: * input will be preceded with a blank. If both a
2179: * '+' and a ' ' are specified, the blank flag is
2180: * ignored. The '0' flag character implies that
2181: * padding to the field width will be done with
2182: * zeros instead of blanks.
2183: *
2184: * The field width is treated as the minimum number
2185: * of characters to be printed. The default is to
2186: * add no padding. Padding is with blanks by
2187: * default.
2188: *
2189: * The precision, if set, is the minimum number of
2190: * digits to appear. Padding is with leading 0s.
2191: * @param x the int to format.
2192: * @return the formatted String.
2193: */
2194: private String printDFormat(int x) {
2195: return printDFormat(Integer.toString(x));
2196: }
2197:
2198: /**
2199: * Utility method for formatting using the d
2200: * conversion character.
2201: * @param sx the String to format, the result of
2202: * converting a short, int, or long to a
2203: * String.
2204: * @return the formatted String.
2205: */
2206: private String printDFormat(String sx) {
2207: int nLeadingZeros = 0;
2208: int nBlanks = 0, n = 0;
2209: int i = 0, jFirst = 0;
2210: boolean neg = sx.charAt(0) == '-';
2211: if (sx.equals("0") && precisionSet && precision == 0)
2212: sx = "";
2213: if (!neg) {
2214: if (precisionSet && sx.length() < precision)
2215: nLeadingZeros = precision - sx.length();
2216: } else {
2217: if (precisionSet && (sx.length() - 1) < precision)
2218: nLeadingZeros = precision - sx.length() + 1;
2219: }
2220: if (nLeadingZeros < 0)
2221: nLeadingZeros = 0;
2222: if (fieldWidthSet) {
2223: nBlanks = fieldWidth - nLeadingZeros - sx.length();
2224: if (!neg && (leadingSign || leadingSpace))
2225: nBlanks--;
2226: }
2227: if (nBlanks < 0)
2228: nBlanks = 0;
2229: if (leadingSign)
2230: n++;
2231: else if (leadingSpace)
2232: n++;
2233: n += nBlanks;
2234: n += nLeadingZeros;
2235: n += sx.length();
2236: char[] ca = new char[n];
2237: if (leftJustify) {
2238: if (neg)
2239: ca[i++] = '-';
2240: else if (leadingSign)
2241: ca[i++] = '+';
2242: else if (leadingSpace)
2243: ca[i++] = ' ';
2244: char[] csx = sx.toCharArray();
2245: jFirst = neg ? 1 : 0;
2246: for (int j = 0; j < nLeadingZeros; i++, j++)
2247: ca[i] = '0';
2248: for (int j = jFirst; j < csx.length; j++, i++)
2249: ca[i] = csx[j];
2250: for (int j = 0; j < nBlanks; i++, j++)
2251: ca[i] = ' ';
2252: } else {
2253: if (!leadingZeros) {
2254: for (i = 0; i < nBlanks; i++)
2255: ca[i] = ' ';
2256: if (neg)
2257: ca[i++] = '-';
2258: else if (leadingSign)
2259: ca[i++] = '+';
2260: else if (leadingSpace)
2261: ca[i++] = ' ';
2262: } else {
2263: if (neg)
2264: ca[i++] = '-';
2265: else if (leadingSign)
2266: ca[i++] = '+';
2267: else if (leadingSpace)
2268: ca[i++] = ' ';
2269: for (int j = 0; j < nBlanks; j++, i++)
2270: ca[i] = '0';
2271: }
2272: for (int j = 0; j < nLeadingZeros; j++, i++)
2273: ca[i] = '0';
2274: char[] csx = sx.toCharArray();
2275: jFirst = neg ? 1 : 0;
2276: for (int j = jFirst; j < csx.length; j++, i++)
2277: ca[i] = csx[j];
2278: }
2279: return new String(ca);
2280: }
2281:
2282: /**
2283: * Format method for the x conversion character and
2284: * short argument.
2285: *
2286: * For x format, the flag character '-', means that
2287: * the output should be left justified within the
2288: * field. The default is to pad with blanks on the
2289: * left. The '#' flag character means to lead with
2290: * '0x'.
2291: *
2292: * The field width is treated as the minimum number
2293: * of characters to be printed. The default is to
2294: * add no padding. Padding is with blanks by
2295: * default.
2296: *
2297: * The precision, if set, is the minimum number of
2298: * digits to appear. Padding is with leading 0s.
2299: * @param x the short to format.
2300: * @return the formatted String.
2301: */
2302: private String printXFormat(short x) {
2303: String sx = null;
2304: if (x == Short.MIN_VALUE)
2305: sx = "8000";
2306: else if (x < 0) {
2307: String t;
2308: if (x == Short.MIN_VALUE)
2309: t = "0";
2310: else {
2311: t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE,
2312: 16);
2313: if (t.charAt(0) == 'F' || t.charAt(0) == 'f')
2314: t = t.substring(16, 32);
2315: }
2316: switch (t.length()) {
2317: case 1:
2318: sx = "800" + t;
2319: break;
2320: case 2:
2321: sx = "80" + t;
2322: break;
2323: case 3:
2324: sx = "8" + t;
2325: break;
2326: case 4:
2327: switch (t.charAt(0)) {
2328: case '1':
2329: sx = "9" + t.substring(1, 4);
2330: break;
2331: case '2':
2332: sx = "a" + t.substring(1, 4);
2333: break;
2334: case '3':
2335: sx = "b" + t.substring(1, 4);
2336: break;
2337: case '4':
2338: sx = "c" + t.substring(1, 4);
2339: break;
2340: case '5':
2341: sx = "d" + t.substring(1, 4);
2342: break;
2343: case '6':
2344: sx = "e" + t.substring(1, 4);
2345: break;
2346: case '7':
2347: sx = "f" + t.substring(1, 4);
2348: break;
2349: }
2350: break;
2351: }
2352: } else
2353: sx = Integer.toString((int) x, 16);
2354: return printXFormat(sx);
2355: }
2356:
2357: /**
2358: * Format method for the x conversion character and
2359: * long argument.
2360: *
2361: * For x format, the flag character '-', means that
2362: * the output should be left justified within the
2363: * field. The default is to pad with blanks on the
2364: * left. The '#' flag character means to lead with
2365: * '0x'.
2366: *
2367: * The field width is treated as the minimum number
2368: * of characters to be printed. The default is to
2369: * add no padding. Padding is with blanks by
2370: * default.
2371: *
2372: * The precision, if set, is the minimum number of
2373: * digits to appear. Padding is with leading 0s.
2374: * @param x the long to format.
2375: * @return the formatted String.
2376: */
2377: private String printXFormat(long x) {
2378: String sx = null;
2379: if (x == Long.MIN_VALUE)
2380: sx = "8000000000000000";
2381: else if (x < 0) {
2382: String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE,
2383: 16);
2384: switch (t.length()) {
2385: case 1:
2386: sx = "800000000000000" + t;
2387: break;
2388: case 2:
2389: sx = "80000000000000" + t;
2390: break;
2391: case 3:
2392: sx = "8000000000000" + t;
2393: break;
2394: case 4:
2395: sx = "800000000000" + t;
2396: break;
2397: case 5:
2398: sx = "80000000000" + t;
2399: break;
2400: case 6:
2401: sx = "8000000000" + t;
2402: break;
2403: case 7:
2404: sx = "800000000" + t;
2405: break;
2406: case 8:
2407: sx = "80000000" + t;
2408: break;
2409: case 9:
2410: sx = "8000000" + t;
2411: break;
2412: case 10:
2413: sx = "800000" + t;
2414: break;
2415: case 11:
2416: sx = "80000" + t;
2417: break;
2418: case 12:
2419: sx = "8000" + t;
2420: break;
2421: case 13:
2422: sx = "800" + t;
2423: break;
2424: case 14:
2425: sx = "80" + t;
2426: break;
2427: case 15:
2428: sx = "8" + t;
2429: break;
2430: case 16:
2431: switch (t.charAt(0)) {
2432: case '1':
2433: sx = "9" + t.substring(1, 16);
2434: break;
2435: case '2':
2436: sx = "a" + t.substring(1, 16);
2437: break;
2438: case '3':
2439: sx = "b" + t.substring(1, 16);
2440: break;
2441: case '4':
2442: sx = "c" + t.substring(1, 16);
2443: break;
2444: case '5':
2445: sx = "d" + t.substring(1, 16);
2446: break;
2447: case '6':
2448: sx = "e" + t.substring(1, 16);
2449: break;
2450: case '7':
2451: sx = "f" + t.substring(1, 16);
2452: break;
2453: }
2454: break;
2455: }
2456: } else
2457: sx = Long.toString(x, 16);
2458: return printXFormat(sx);
2459: }
2460:
2461: /**
2462: * Format method for the x conversion character and
2463: * int argument.
2464: *
2465: * For x format, the flag character '-', means that
2466: * the output should be left justified within the
2467: * field. The default is to pad with blanks on the
2468: * left. The '#' flag character means to lead with
2469: * '0x'.
2470: *
2471: * The field width is treated as the minimum number
2472: * of characters to be printed. The default is to
2473: * add no padding. Padding is with blanks by
2474: * default.
2475: *
2476: * The precision, if set, is the minimum number of
2477: * digits to appear. Padding is with leading 0s.
2478: * @param x the int to format.
2479: * @return the formatted String.
2480: */
2481: private String printXFormat(int x) {
2482: String sx = null;
2483: if (x == Integer.MIN_VALUE)
2484: sx = "80000000";
2485: else if (x < 0) {
2486: String t = Integer.toString((~(-x - 1))
2487: ^ Integer.MIN_VALUE, 16);
2488: switch (t.length()) {
2489: case 1:
2490: sx = "8000000" + t;
2491: break;
2492: case 2:
2493: sx = "800000" + t;
2494: break;
2495: case 3:
2496: sx = "80000" + t;
2497: break;
2498: case 4:
2499: sx = "8000" + t;
2500: break;
2501: case 5:
2502: sx = "800" + t;
2503: break;
2504: case 6:
2505: sx = "80" + t;
2506: break;
2507: case 7:
2508: sx = "8" + t;
2509: break;
2510: case 8:
2511: switch (t.charAt(0)) {
2512: case '1':
2513: sx = "9" + t.substring(1, 8);
2514: break;
2515: case '2':
2516: sx = "a" + t.substring(1, 8);
2517: break;
2518: case '3':
2519: sx = "b" + t.substring(1, 8);
2520: break;
2521: case '4':
2522: sx = "c" + t.substring(1, 8);
2523: break;
2524: case '5':
2525: sx = "d" + t.substring(1, 8);
2526: break;
2527: case '6':
2528: sx = "e" + t.substring(1, 8);
2529: break;
2530: case '7':
2531: sx = "f" + t.substring(1, 8);
2532: break;
2533: }
2534: break;
2535: }
2536: } else
2537: sx = Integer.toString(x, 16);
2538: return printXFormat(sx);
2539: }
2540:
2541: /**
2542: * Utility method for formatting using the x
2543: * conversion character.
2544: * @param sx the String to format, the result of
2545: * converting a short, int, or long to a
2546: * String.
2547: * @return the formatted String.
2548: */
2549: private String printXFormat(String sx) {
2550: int nLeadingZeros = 0;
2551: int nBlanks = 0;
2552: if (sx.equals("0") && precisionSet && precision == 0)
2553: sx = "";
2554: if (precisionSet)
2555: nLeadingZeros = precision - sx.length();
2556: if (nLeadingZeros < 0)
2557: nLeadingZeros = 0;
2558: if (fieldWidthSet) {
2559: nBlanks = fieldWidth - nLeadingZeros - sx.length();
2560: if (alternateForm)
2561: nBlanks = nBlanks - 2;
2562: }
2563: if (nBlanks < 0)
2564: nBlanks = 0;
2565: int n = 0;
2566: if (alternateForm)
2567: n += 2;
2568: n += nLeadingZeros;
2569: n += sx.length();
2570: n += nBlanks;
2571: char[] ca = new char[n];
2572: int i = 0;
2573: if (leftJustify) {
2574: if (alternateForm) {
2575: ca[i++] = '0';
2576: ca[i++] = 'x';
2577: }
2578: for (int j = 0; j < nLeadingZeros; j++, i++)
2579: ca[i] = '0';
2580: char[] csx = sx.toCharArray();
2581: for (int j = 0; j < csx.length; j++, i++)
2582: ca[i] = csx[j];
2583: for (int j = 0; j < nBlanks; j++, i++)
2584: ca[i] = ' ';
2585: } else {
2586: if (!leadingZeros)
2587: for (int j = 0; j < nBlanks; j++, i++)
2588: ca[i] = ' ';
2589: if (alternateForm) {
2590: ca[i++] = '0';
2591: ca[i++] = 'x';
2592: }
2593: if (leadingZeros)
2594: for (int j = 0; j < nBlanks; j++, i++)
2595: ca[i] = '0';
2596: for (int j = 0; j < nLeadingZeros; j++, i++)
2597: ca[i] = '0';
2598: char[] csx = sx.toCharArray();
2599: for (int j = 0; j < csx.length; j++, i++)
2600: ca[i] = csx[j];
2601: }
2602: String caReturn = new String(ca);
2603: if (conversionCharacter == 'X')
2604: caReturn = caReturn.toUpperCase();
2605: return caReturn;
2606: }
2607:
2608: /**
2609: * Format method for the o conversion character and
2610: * short argument.
2611: *
2612: * For o format, the flag character '-', means that
2613: * the output should be left justified within the
2614: * field. The default is to pad with blanks on the
2615: * left. The '#' flag character means that the
2616: * output begins with a leading 0 and the precision
2617: * is increased by 1.
2618: *
2619: * The field width is treated as the minimum number
2620: * of characters to be printed. The default is to
2621: * add no padding. Padding is with blanks by
2622: * default.
2623: *
2624: * The precision, if set, is the minimum number of
2625: * digits to appear. Padding is with leading 0s.
2626: * @param x the short to format.
2627: * @return the formatted String.
2628: */
2629: private String printOFormat(short x) {
2630: String sx = null;
2631: if (x == Short.MIN_VALUE)
2632: sx = "100000";
2633: else if (x < 0) {
2634: String t = Integer.toString((~(-x - 1))
2635: ^ Short.MIN_VALUE, 8);
2636: switch (t.length()) {
2637: case 1:
2638: sx = "10000" + t;
2639: break;
2640: case 2:
2641: sx = "1000" + t;
2642: break;
2643: case 3:
2644: sx = "100" + t;
2645: break;
2646: case 4:
2647: sx = "10" + t;
2648: break;
2649: case 5:
2650: sx = "1" + t;
2651: break;
2652: }
2653: } else
2654: sx = Integer.toString((int) x, 8);
2655: return printOFormat(sx);
2656: }
2657:
2658: /**
2659: * Format method for the o conversion character and
2660: * long argument.
2661: *
2662: * For o format, the flag character '-', means that
2663: * the output should be left justified within the
2664: * field. The default is to pad with blanks on the
2665: * left. The '#' flag character means that the
2666: * output begins with a leading 0 and the precision
2667: * is increased by 1.
2668: *
2669: * The field width is treated as the minimum number
2670: * of characters to be printed. The default is to
2671: * add no padding. Padding is with blanks by
2672: * default.
2673: *
2674: * The precision, if set, is the minimum number of
2675: * digits to appear. Padding is with leading 0s.
2676: * @param x the long to format.
2677: * @return the formatted String.
2678: */
2679: private String printOFormat(long x) {
2680: String sx = null;
2681: if (x == Long.MIN_VALUE)
2682: sx = "1000000000000000000000";
2683: else if (x < 0) {
2684: String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE,
2685: 8);
2686: switch (t.length()) {
2687: case 1:
2688: sx = "100000000000000000000" + t;
2689: break;
2690: case 2:
2691: sx = "10000000000000000000" + t;
2692: break;
2693: case 3:
2694: sx = "1000000000000000000" + t;
2695: break;
2696: case 4:
2697: sx = "100000000000000000" + t;
2698: break;
2699: case 5:
2700: sx = "10000000000000000" + t;
2701: break;
2702: case 6:
2703: sx = "1000000000000000" + t;
2704: break;
2705: case 7:
2706: sx = "100000000000000" + t;
2707: break;
2708: case 8:
2709: sx = "10000000000000" + t;
2710: break;
2711: case 9:
2712: sx = "1000000000000" + t;
2713: break;
2714: case 10:
2715: sx = "100000000000" + t;
2716: break;
2717: case 11:
2718: sx = "10000000000" + t;
2719: break;
2720: case 12:
2721: sx = "1000000000" + t;
2722: break;
2723: case 13:
2724: sx = "100000000" + t;
2725: break;
2726: case 14:
2727: sx = "10000000" + t;
2728: break;
2729: case 15:
2730: sx = "1000000" + t;
2731: break;
2732: case 16:
2733: sx = "100000" + t;
2734: break;
2735: case 17:
2736: sx = "10000" + t;
2737: break;
2738: case 18:
2739: sx = "1000" + t;
2740: break;
2741: case 19:
2742: sx = "100" + t;
2743: break;
2744: case 20:
2745: sx = "10" + t;
2746: break;
2747: case 21:
2748: sx = "1" + t;
2749: break;
2750: }
2751: } else
2752: sx = Long.toString(x, 8);
2753: return printOFormat(sx);
2754: }
2755:
2756: /**
2757: * Format method for the o conversion character and
2758: * int argument.
2759: *
2760: * For o format, the flag character '-', means that
2761: * the output should be left justified within the
2762: * field. The default is to pad with blanks on the
2763: * left. The '#' flag character means that the
2764: * output begins with a leading 0 and the precision
2765: * is increased by 1.
2766: *
2767: * The field width is treated as the minimum number
2768: * of characters to be printed. The default is to
2769: * add no padding. Padding is with blanks by
2770: * default.
2771: *
2772: * The precision, if set, is the minimum number of
2773: * digits to appear. Padding is with leading 0s.
2774: * @param x the int to format.
2775: * @return the formatted String.
2776: */
2777: private String printOFormat(int x) {
2778: String sx = null;
2779: if (x == Integer.MIN_VALUE)
2780: sx = "20000000000";
2781: else if (x < 0) {
2782: String t = Integer.toString((~(-x - 1))
2783: ^ Integer.MIN_VALUE, 8);
2784: switch (t.length()) {
2785: case 1:
2786: sx = "2000000000" + t;
2787: break;
2788: case 2:
2789: sx = "200000000" + t;
2790: break;
2791: case 3:
2792: sx = "20000000" + t;
2793: break;
2794: case 4:
2795: sx = "2000000" + t;
2796: break;
2797: case 5:
2798: sx = "200000" + t;
2799: break;
2800: case 6:
2801: sx = "20000" + t;
2802: break;
2803: case 7:
2804: sx = "2000" + t;
2805: break;
2806: case 8:
2807: sx = "200" + t;
2808: break;
2809: case 9:
2810: sx = "20" + t;
2811: break;
2812: case 10:
2813: sx = "2" + t;
2814: break;
2815: case 11:
2816: sx = "3" + t.substring(1);
2817: break;
2818: }
2819: } else
2820: sx = Integer.toString(x, 8);
2821: return printOFormat(sx);
2822: }
2823:
2824: /**
2825: * Utility method for formatting using the o
2826: * conversion character.
2827: * @param sx the String to format, the result of
2828: * converting a short, int, or long to a
2829: * String.
2830: * @return the formatted String.
2831: */
2832: private String printOFormat(String sx) {
2833: int nLeadingZeros = 0;
2834: int nBlanks = 0;
2835: if (sx.equals("0") && precisionSet && precision == 0)
2836: sx = "";
2837: if (precisionSet)
2838: nLeadingZeros = precision - sx.length();
2839: if (alternateForm)
2840: nLeadingZeros++;
2841: if (nLeadingZeros < 0)
2842: nLeadingZeros = 0;
2843: if (fieldWidthSet)
2844: nBlanks = fieldWidth - nLeadingZeros - sx.length();
2845: if (nBlanks < 0)
2846: nBlanks = 0;
2847: int n = nLeadingZeros + sx.length() + nBlanks;
2848: char[] ca = new char[n];
2849: int i;
2850: if (leftJustify) {
2851: for (i = 0; i < nLeadingZeros; i++)
2852: ca[i] = '0';
2853: char[] csx = sx.toCharArray();
2854: for (int j = 0; j < csx.length; j++, i++)
2855: ca[i] = csx[j];
2856: for (int j = 0; j < nBlanks; j++, i++)
2857: ca[i] = ' ';
2858: } else {
2859: if (leadingZeros)
2860: for (i = 0; i < nBlanks; i++)
2861: ca[i] = '0';
2862: else
2863: for (i = 0; i < nBlanks; i++)
2864: ca[i] = ' ';
2865: for (int j = 0; j < nLeadingZeros; j++, i++)
2866: ca[i] = '0';
2867: char[] csx = sx.toCharArray();
2868: for (int j = 0; j < csx.length; j++, i++)
2869: ca[i] = csx[j];
2870: }
2871: return new String(ca);
2872: }
2873:
2874: /**
2875: * Format method for the c conversion character and
2876: * char argument.
2877: *
2878: * The only flag character that affects c format is
2879: * the '-', meaning that the output should be left
2880: * justified within the field. The default is to
2881: * pad with blanks on the left.
2882: *
2883: * The field width is treated as the minimum number
2884: * of characters to be printed. Padding is with
2885: * blanks by default. The default width is 1.
2886: *
2887: * The precision, if set, is ignored.
2888: * @param x the char to format.
2889: * @return the formatted String.
2890: */
2891: private String printCFormat(char x) {
2892: int nPrint = 1;
2893: int width = fieldWidth;
2894: if (!fieldWidthSet)
2895: width = nPrint;
2896: char[] ca = new char[width];
2897: int i = 0;
2898: if (leftJustify) {
2899: ca[0] = x;
2900: for (i = 1; i <= width - nPrint; i++)
2901: ca[i] = ' ';
2902: } else {
2903: for (i = 0; i < width - nPrint; i++)
2904: ca[i] = ' ';
2905: ca[i] = x;
2906: }
2907: return new String(ca);
2908: }
2909:
2910: /**
2911: * Format method for the s conversion character and
2912: * String argument.
2913: *
2914: * The only flag character that affects s format is
2915: * the '-', meaning that the output should be left
2916: * justified within the field. The default is to
2917: * pad with blanks on the left.
2918: *
2919: * The field width is treated as the minimum number
2920: * of characters to be printed. The default is the
2921: * smaller of the number of characters in the the
2922: * input and the precision. Padding is with blanks
2923: * by default.
2924: *
2925: * The precision, if set, specifies the maximum
2926: * number of characters to be printed from the
2927: * string. A null digit string is treated
2928: * as a 0. The default is not to set a maximum
2929: * number of characters to be printed.
2930: * @param x the String to format.
2931: * @return the formatted String.
2932: */
2933: private String printSFormat(String x) {
2934: int nPrint = x.length();
2935: int width = fieldWidth;
2936: if (precisionSet && nPrint > precision)
2937: nPrint = precision;
2938: if (!fieldWidthSet)
2939: width = nPrint;
2940: int n = 0;
2941: if (width > nPrint)
2942: n += width - nPrint;
2943: if (nPrint >= x.length())
2944: n += x.length();
2945: else
2946: n += nPrint;
2947: char[] ca = new char[n];
2948: int i = 0;
2949: if (leftJustify) {
2950: if (nPrint >= x.length()) {
2951: char[] csx = x.toCharArray();
2952: for (i = 0; i < x.length(); i++)
2953: ca[i] = csx[i];
2954: } else {
2955: char[] csx = x.substring(0, nPrint).toCharArray();
2956: for (i = 0; i < nPrint; i++)
2957: ca[i] = csx[i];
2958: }
2959: for (int j = 0; j < width - nPrint; j++, i++)
2960: ca[i] = ' ';
2961: } else {
2962: for (i = 0; i < width - nPrint; i++)
2963: ca[i] = ' ';
2964: if (nPrint >= x.length()) {
2965: char[] csx = x.toCharArray();
2966: for (int j = 0; j < x.length(); i++, j++)
2967: ca[i] = csx[j];
2968: } else {
2969: char[] csx = x.substring(0, nPrint).toCharArray();
2970: for (int j = 0; j < nPrint; i++, j++)
2971: ca[i] = csx[j];
2972: }
2973: }
2974: return new String(ca);
2975: }
2976:
2977: /**
2978: * Check for a conversion character. If it is
2979: * there, store it.
2980: * @param x the String to format.
2981: * @return <code>true</code> if the conversion
2982: * character is there, and
2983: * <code>false</code> otherwise.
2984: */
2985: private boolean setConversionCharacter() {
2986: /* idfgGoxXeEcs */
2987: boolean ret = false;
2988: conversionCharacter = '\0';
2989: if (pos < fmt.length()) {
2990: char c = fmt.charAt(pos);
2991: if (c == 'i' || c == 'd' || c == 'f' || c == 'g'
2992: || c == 'G' || c == 'o' || c == 'x' || c == 'X'
2993: || c == 'e' || c == 'E' || c == 'c' || c == 's'
2994: || c == '%') {
2995: conversionCharacter = c;
2996: pos++;
2997: ret = true;
2998: }
2999: }
3000: return ret;
3001: }
3002:
3003: /**
3004: * Check for an h, l, or L in a format. An L is
3005: * used to control the minimum number of digits
3006: * in an exponent when using floating point
3007: * formats. An l or h is used to control
3008: * conversion of the input to a long or short,
3009: * respectively, before formatting. If any of
3010: * these is present, store them.
3011: */
3012: private void setOptionalHL() {
3013: optionalh = false;
3014: optionall = false;
3015: optionalL = false;
3016: if (pos < fmt.length()) {
3017: char c = fmt.charAt(pos);
3018: if (c == 'h') {
3019: optionalh = true;
3020: pos++;
3021: } else if (c == 'l') {
3022: optionall = true;
3023: pos++;
3024: } else if (c == 'L') {
3025: optionalL = true;
3026: pos++;
3027: }
3028: }
3029: }
3030:
3031: /**
3032: * Set the precision.
3033: */
3034: private void setPrecision() {
3035: int firstPos = pos;
3036: precisionSet = false;
3037: if (pos < fmt.length() && fmt.charAt(pos) == '.') {
3038: pos++;
3039: if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
3040: pos++;
3041: if (!setPrecisionArgPosition()) {
3042: variablePrecision = true;
3043: precisionSet = true;
3044: }
3045: return;
3046: } else {
3047: while (pos < fmt.length()) {
3048: char c = fmt.charAt(pos);
3049: if (Character.isDigit(c))
3050: pos++;
3051: else
3052: break;
3053: }
3054: if (pos > firstPos + 1) {
3055: String sz = fmt.substring(firstPos + 1, pos);
3056: precision = Integer.parseInt(sz);
3057: precisionSet = true;
3058: }
3059: }
3060: }
3061: }
3062:
3063: /**
3064: * Set the field width.
3065: */
3066: private void setFieldWidth() {
3067: int firstPos = pos;
3068: fieldWidth = 0;
3069: fieldWidthSet = false;
3070: if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
3071: pos++;
3072: if (!setFieldWidthArgPosition()) {
3073: variableFieldWidth = true;
3074: fieldWidthSet = true;
3075: }
3076: } else {
3077: while (pos < fmt.length()) {
3078: char c = fmt.charAt(pos);
3079: if (Character.isDigit(c))
3080: pos++;
3081: else
3082: break;
3083: }
3084: if (firstPos < pos && firstPos < fmt.length()) {
3085: String sz = fmt.substring(firstPos, pos);
3086: fieldWidth = Integer.parseInt(sz);
3087: fieldWidthSet = true;
3088: }
3089: }
3090: }
3091:
3092: /**
3093: * Store the digits <code>n</code> in %n$ forms.
3094: */
3095: private void setArgPosition() {
3096: int xPos;
3097: for (xPos = pos; xPos < fmt.length(); xPos++) {
3098: if (!Character.isDigit(fmt.charAt(xPos)))
3099: break;
3100: }
3101: if (xPos > pos && xPos < fmt.length()) {
3102: if (fmt.charAt(xPos) == '$') {
3103: positionalSpecification = true;
3104: argumentPosition = Integer.parseInt(fmt.substring(
3105: pos, xPos));
3106: pos = xPos + 1;
3107: }
3108: }
3109: }
3110:
3111: /**
3112: * Store the digits <code>n</code> in *n$ forms.
3113: */
3114: private boolean setFieldWidthArgPosition() {
3115: boolean ret = false;
3116: int xPos;
3117: for (xPos = pos; xPos < fmt.length(); xPos++) {
3118: if (!Character.isDigit(fmt.charAt(xPos)))
3119: break;
3120: }
3121: if (xPos > pos && xPos < fmt.length()) {
3122: if (fmt.charAt(xPos) == '$') {
3123: positionalFieldWidth = true;
3124: argumentPositionForFieldWidth = Integer
3125: .parseInt(fmt.substring(pos, xPos));
3126: pos = xPos + 1;
3127: ret = true;
3128: }
3129: }
3130: return ret;
3131: }
3132:
3133: /**
3134: * Store the digits <code>n</code> in *n$ forms.
3135: */
3136: private boolean setPrecisionArgPosition() {
3137: boolean ret = false;
3138: int xPos;
3139: for (xPos = pos; xPos < fmt.length(); xPos++) {
3140: if (!Character.isDigit(fmt.charAt(xPos)))
3141: break;
3142: }
3143: if (xPos > pos && xPos < fmt.length()) {
3144: if (fmt.charAt(xPos) == '$') {
3145: positionalPrecision = true;
3146: argumentPositionForPrecision = Integer.parseInt(fmt
3147: .substring(pos, xPos));
3148: pos = xPos + 1;
3149: ret = true;
3150: }
3151: }
3152: return ret;
3153: }
3154:
3155: boolean isPositionalSpecification() {
3156: return positionalSpecification;
3157: }
3158:
3159: int getArgumentPosition() {
3160: return argumentPosition;
3161: }
3162:
3163: boolean isPositionalFieldWidth() {
3164: return positionalFieldWidth;
3165: }
3166:
3167: int getArgumentPositionForFieldWidth() {
3168: return argumentPositionForFieldWidth;
3169: }
3170:
3171: boolean isPositionalPrecision() {
3172: return positionalPrecision;
3173: }
3174:
3175: int getArgumentPositionForPrecision() {
3176: return argumentPositionForPrecision;
3177: }
3178:
3179: /**
3180: * Set flag characters, one of '-+#0 or a space.
3181: */
3182: private void setFlagCharacters() {
3183: /* '-+ #0 */
3184: thousands = false;
3185: leftJustify = false;
3186: leadingSign = false;
3187: leadingSpace = false;
3188: alternateForm = false;
3189: leadingZeros = false;
3190: for (; pos < fmt.length(); pos++) {
3191: char c = fmt.charAt(pos);
3192: if (c == '\'')
3193: thousands = true;
3194: else if (c == '-') {
3195: leftJustify = true;
3196: leadingZeros = false;
3197: } else if (c == '+') {
3198: leadingSign = true;
3199: leadingSpace = false;
3200: } else if (c == ' ') {
3201: if (!leadingSign)
3202: leadingSpace = true;
3203: } else if (c == '#')
3204: alternateForm = true;
3205: else if (c == '0') {
3206: if (!leftJustify)
3207: leadingZeros = true;
3208: } else
3209: break;
3210: }
3211: }
3212:
3213: /**
3214: * The integer portion of the result of a decimal
3215: * conversion (i, d, u, f, g, or G) will be
3216: * formatted with thousands' grouping characters.
3217: * For other conversions the flag is ignored.
3218: */
3219: private boolean thousands = false;
3220: /**
3221: * The result of the conversion will be
3222: * left-justified within the field.
3223: */
3224: private boolean leftJustify = false;
3225: /**
3226: * The result of a signed conversion will always
3227: * begin with a sign (+ or -).
3228: */
3229: private boolean leadingSign = false;
3230: /**
3231: * Flag indicating that left padding with spaces is
3232: * specified.
3233: */
3234: private boolean leadingSpace = false;
3235: /**
3236: * For an o conversion, increase the precision to
3237: * force the first digit of the result to be a
3238: * zero. For x (or X) conversions, a non-zero
3239: * result will have 0x (or 0X) prepended to it.
3240: * For e, E, f, g, or G conversions, the result
3241: * will always contain a radix character, even if
3242: * no digits follow the point. For g and G
3243: * conversions, trailing zeros will not be removed
3244: * from the result.
3245: */
3246: private boolean alternateForm = false;
3247: /**
3248: * Flag indicating that left padding with zeroes is
3249: * specified.
3250: */
3251: private boolean leadingZeros = false;
3252: /**
3253: * Flag indicating that the field width is *.
3254: */
3255: private boolean variableFieldWidth = false;
3256: /**
3257: * If the converted value has fewer bytes than the
3258: * field width, it will be padded with spaces or
3259: * zeroes.
3260: */
3261: private int fieldWidth = 0;
3262: /**
3263: * Flag indicating whether or not the field width
3264: * has been set.
3265: */
3266: private boolean fieldWidthSet = false;
3267: /**
3268: * The minimum number of digits to appear for the
3269: * d, i, o, u, x, or X conversions. The number of
3270: * digits to appear after the radix character for
3271: * the e, E, and f conversions. The maximum number
3272: * of significant digits for the g and G
3273: * conversions. The maximum number of bytes to be
3274: * printed from a string in s and S conversions.
3275: */
3276: private int precision = 0;
3277: /** Default precision. */
3278: private final static int defaultDigits = 6;
3279: /**
3280: * Flag indicating that the precision is *.
3281: */
3282: private boolean variablePrecision = false;
3283: /**
3284: * Flag indicating whether or not the precision has
3285: * been set.
3286: */
3287: private boolean precisionSet = false;
3288: /*
3289: */
3290: private boolean positionalSpecification = false;
3291: private int argumentPosition = 0;
3292: private boolean positionalFieldWidth = false;
3293: private int argumentPositionForFieldWidth = 0;
3294: private boolean positionalPrecision = false;
3295: private int argumentPositionForPrecision = 0;
3296: /**
3297: * Flag specifying that a following d, i, o, u, x,
3298: * or X conversion character applies to a type
3299: * short int.
3300: */
3301: private boolean optionalh = false;
3302: /**
3303: * Flag specifying that a following d, i, o, u, x,
3304: * or X conversion character applies to a type lont
3305: * int argument.
3306: */
3307: private boolean optionall = false;
3308: /**
3309: * Flag specifying that a following e, E, f, g, or
3310: * G conversion character applies to a type double
3311: * argument. This is a noop in Java.
3312: */
3313: private boolean optionalL = false;
3314: /** Control string type. */
3315: private char conversionCharacter = '\0';
3316: /**
3317: * Position within the control string. Used by
3318: * the constructor.
3319: */
3320: private int pos = 0;
3321: /** Literal or control format string. */
3322: private String fmt;
3323: }
3324:
3325: /** Vector of control strings and format literals. */
3326: private Vector vFmt = new Vector();
3327: /** Character position. Used by the constructor. */
3328: private int cPos = 0;
3329: /** Character position. Used by the constructor. */
3330: private DecimalFormatSymbols dfs = null;
3331: }
|