0001 /*
0002 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.util;
0027
0028 import java.io.BufferedWriter;
0029 import java.io.Closeable;
0030 import java.io.IOException;
0031 import java.io.File;
0032 import java.io.FileOutputStream;
0033 import java.io.FileNotFoundException;
0034 import java.io.Flushable;
0035 import java.io.OutputStream;
0036 import java.io.OutputStreamWriter;
0037 import java.io.PrintStream;
0038 import java.io.UnsupportedEncodingException;
0039 import java.math.BigDecimal;
0040 import java.math.BigInteger;
0041 import java.math.MathContext;
0042 import java.nio.charset.Charset;
0043 import java.text.DateFormatSymbols;
0044 import java.text.DecimalFormat;
0045 import java.text.DecimalFormatSymbols;
0046 import java.text.NumberFormat;
0047 import java.util.Calendar;
0048 import java.util.Date;
0049 import java.util.Locale;
0050 import java.util.regex.Matcher;
0051 import java.util.regex.Pattern;
0052
0053 import sun.misc.FpUtils;
0054 import sun.misc.DoubleConsts;
0055 import sun.misc.FormattedFloatingDecimal;
0056
0057 /**
0058 * An interpreter for printf-style format strings. This class provides support
0059 * for layout justification and alignment, common formats for numeric, string,
0060 * and date/time data, and locale-specific output. Common Java types such as
0061 * <tt>byte</tt>, {@link java.math.BigDecimal BigDecimal}, and {@link Calendar}
0062 * are supported. Limited formatting customization for arbitrary user types is
0063 * provided through the {@link Formattable} interface.
0064 *
0065 * <p> Formatters are not necessarily safe for multithreaded access. Thread
0066 * safety is optional and is the responsibility of users of methods in this
0067 * class.
0068 *
0069 * <p> Formatted printing for the Java language is heavily inspired by C's
0070 * <tt>printf</tt>. Although the format strings are similar to C, some
0071 * customizations have been made to accommodate the Java language and exploit
0072 * some of its features. Also, Java formatting is more strict than C's; for
0073 * example, if a conversion is incompatible with a flag, an exception will be
0074 * thrown. In C inapplicable flags are silently ignored. The format strings
0075 * are thus intended to be recognizable to C programmers but not necessarily
0076 * completely compatible with those in C.
0077 *
0078 * <p> Examples of expected usage:
0079 *
0080 * <blockquote><pre>
0081 * StringBuilder sb = new StringBuilder();
0082 * // Send all output to the Appendable object sb
0083 * Formatter formatter = new Formatter(sb, Locale.US);
0084 *
0085 * // Explicit argument indices may be used to re-order output.
0086 * formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
0087 * // -> " d c b a"
0088 *
0089 * // Optional locale as the first argument can be used to get
0090 * // locale-specific formatting of numbers. The precision and width can be
0091 * // given to round and align the value.
0092 * formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
0093 * // -> "e = +2,7183"
0094 *
0095 * // The '(' numeric flag may be used to format negative numbers with
0096 * // parentheses rather than a minus sign. Group separators are
0097 * // automatically inserted.
0098 * formatter.format("Amount gained or lost since last statement: $ %(,.2f",
0099 * balanceDelta);
0100 * // -> "Amount gained or lost since last statement: $ (6,217.58)"
0101 * </pre></blockquote>
0102 *
0103 * <p> Convenience methods for common formatting requests exist as illustrated
0104 * by the following invocations:
0105 *
0106 * <blockquote><pre>
0107 * // Writes a formatted string to System.out.
0108 * System.out.format("Local time: %tT", Calendar.getInstance());
0109 * // -> "Local time: 13:34:18"
0110 *
0111 * // Writes formatted output to System.err.
0112 * System.err.printf("Unable to open file '%1$s': %2$s",
0113 * fileName, exception.getMessage());
0114 * // -> "Unable to open file 'food': No such file or directory"
0115 * </pre></blockquote>
0116 *
0117 * <p> Like C's <tt>sprintf(3)</tt>, Strings may be formatted using the static
0118 * method {@link String#format(String,Object...) String.format}:
0119 *
0120 * <blockquote><pre>
0121 * // Format a string containing a date.
0122 * import java.util.Calendar;
0123 * import java.util.GregorianCalendar;
0124 * import static java.util.Calendar.*;
0125 *
0126 * Calendar c = new GregorianCalendar(1995, MAY, 23);
0127 * String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0128 * // -> s == "Duke's Birthday: May 23, 1995"
0129 * </pre></blockquote>
0130 *
0131 * <h3><a name="org">Organization</a></h3>
0132 *
0133 * <p> This specification is divided into two sections. The first section, <a
0134 * href="#summary">Summary</a>, covers the basic formatting concepts. This
0135 * section is intended for users who want to get started quickly and are
0136 * familiar with formatted printing in other programming languages. The second
0137 * section, <a href="#detail">Details</a>, covers the specific implementation
0138 * details. It is intended for users who want more precise specification of
0139 * formatting behavior.
0140 *
0141 * <h3><a name="summary">Summary</a></h3>
0142 *
0143 * <p> This section is intended to provide a brief overview of formatting
0144 * concepts. For precise behavioral details, refer to the <a
0145 * href="#detail">Details</a> section.
0146 *
0147 * <h4><a name="syntax">Format String Syntax</a></h4>
0148 *
0149 * <p> Every method which produces formatted output requires a <i>format
0150 * string</i> and an <i>argument list</i>. The format string is a {@link
0151 * String} which may contain fixed text and one or more embedded <i>format
0152 * specifiers</i>. Consider the following example:
0153 *
0154 * <blockquote><pre>
0155 * Calendar c = ...;
0156 * String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0157 * </pre></blockquote>
0158 *
0159 * This format string is the first argument to the <tt>format</tt> method. It
0160 * contains three format specifiers "<tt>%1$tm</tt>", "<tt>%1$te</tt>", and
0161 * "<tt>%1$tY</tt>" which indicate how the arguments should be processed and
0162 * where they should be inserted in the text. The remaining portions of the
0163 * format string are fixed text including <tt>"Dukes Birthday: "</tt> and any
0164 * other spaces or punctuation.
0165 *
0166 * The argument list consists of all arguments passed to the method after the
0167 * format string. In the above example, the argument list is of size one and
0168 * consists of the {@link java.util.Calendar Calendar} object <tt>c</tt>.
0169 *
0170 * <ul>
0171 *
0172 * <li> The format specifiers for general, character, and numeric types have
0173 * the following syntax:
0174 *
0175 * <blockquote><pre>
0176 * %[argument_index$][flags][width][.precision]conversion
0177 * </pre></blockquote>
0178 *
0179 * <p> The optional <i>argument_index</i> is a decimal integer indicating the
0180 * position of the argument in the argument list. The first argument is
0181 * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
0182 *
0183 * <p> The optional <i>flags</i> is a set of characters that modify the output
0184 * format. The set of valid flags depends on the conversion.
0185 *
0186 * <p> The optional <i>width</i> is a non-negative decimal integer indicating
0187 * the minimum number of characters to be written to the output.
0188 *
0189 * <p> The optional <i>precision</i> is a non-negative decimal integer usually
0190 * used to restrict the number of characters. The specific behavior depends on
0191 * the conversion.
0192 *
0193 * <p> The required <i>conversion</i> is a character indicating how the
0194 * argument should be formatted. The set of valid conversions for a given
0195 * argument depends on the argument's data type.
0196 *
0197 * <li> The format specifiers for types which are used to represents dates and
0198 * times have the following syntax:
0199 *
0200 * <blockquote><pre>
0201 * %[argument_index$][flags][width]conversion
0202 * </pre></blockquote>
0203 *
0204 * <p> The optional <i>argument_index</i>, <i>flags</i> and <i>width</i> are
0205 * defined as above.
0206 *
0207 * <p> The required <i>conversion</i> is a two character sequence. The first
0208 * character is <tt>'t'</tt> or <tt>'T'</tt>. The second character indicates
0209 * the format to be used. These characters are similar to but not completely
0210 * identical to those defined by GNU <tt>date</tt> and POSIX
0211 * <tt>strftime(3c)</tt>.
0212 *
0213 * <li> The format specifiers which do not correspond to arguments have the
0214 * following syntax:
0215 *
0216 * <blockquote><pre>
0217 * %[flags][width]conversion
0218 * </pre></blockquote>
0219 *
0220 * <p> The optional <i>flags</i> and <i>width</i> is defined as above.
0221 *
0222 * <p> The required <i>conversion</i> is a character indicating content to be
0223 * inserted in the output.
0224 *
0225 * </ul>
0226 *
0227 * <h4> Conversions </h4>
0228 *
0229 * <p> Conversions are divided into the following categories:
0230 *
0231 * <ol>
0232 *
0233 * <li> <b>General</b> - may be applied to any argument
0234 * type
0235 *
0236 * <li> <b>Character</b> - may be applied to basic types which represent
0237 * Unicode characters: <tt>char</tt>, {@link Character}, <tt>byte</tt>, {@link
0238 * Byte}, <tt>short</tt>, and {@link Short}. This conversion may also be
0239 * applied to the types <tt>int</tt> and {@link Integer} when {@link
0240 * Character#isValidCodePoint} returns <tt>true</tt>
0241 *
0242 * <li> <b>Numeric</b>
0243 *
0244 * <ol>
0245 *
0246 * <li> <b>Integral</b> - may be applied to Java integral types: <tt>byte</tt>,
0247 * {@link Byte}, <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link
0248 * Integer}, <tt>long</tt>, {@link Long}, and {@link java.math.BigInteger
0249 * BigInteger}
0250 *
0251 * <li><b>Floating Point</b> - may be applied to Java floating-point types:
0252 * <tt>float</tt>, {@link Float}, <tt>double</tt>, {@link Double}, and {@link
0253 * java.math.BigDecimal BigDecimal}
0254 *
0255 * </ol>
0256 *
0257 * <li> <b>Date/Time</b> - may be applied to Java types which are capable of
0258 * encoding a date or time: <tt>long</tt>, {@link Long}, {@link Calendar}, and
0259 * {@link Date}.
0260 *
0261 * <li> <b>Percent</b> - produces a literal <tt>'%'</tt>
0262 * (<tt>'\u0025'</tt>)
0263 *
0264 * <li> <b>Line Separator</b> - produces the platform-specific line separator
0265 *
0266 * </ol>
0267 *
0268 * <p> The following table summarizes the supported conversions. Conversions
0269 * denoted by an upper-case character (i.e. <tt>'B'</tt>, <tt>'H'</tt>,
0270 * <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>, <tt>'G'</tt>,
0271 * <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the corresponding
0272 * lower-case conversion characters except that the result is converted to
0273 * upper case according to the rules of the prevailing {@link java.util.Locale
0274 * Locale}. The result is equivalent to the following invocation of {@link
0275 * String#toUpperCase()}
0276 *
0277 * <pre>
0278 * out.toUpperCase() </pre>
0279 *
0280 * <table cellpadding=5 summary="genConv">
0281 *
0282 * <tr><th valign="bottom"> Conversion
0283 * <th valign="bottom"> Argument Category
0284 * <th valign="bottom"> Description
0285 *
0286 * <tr><td valign="top"> <tt>'b'</tt>, <tt>'B'</tt>
0287 * <td valign="top"> general
0288 * <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0289 * "<tt>false</tt>". If <i>arg</i> is a <tt>boolean</tt> or {@link
0290 * Boolean}, then the result is the string returned by {@link
0291 * String#valueOf(boolean) String.valueOf(arg)}. Otherwise, the result is
0292 * "true".
0293 *
0294 * <tr><td valign="top"> <tt>'h'</tt>, <tt>'H'</tt>
0295 * <td valign="top"> general
0296 * <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0297 * "<tt>null</tt>". Otherwise, the result is obtained by invoking
0298 * <tt>Integer.toHexString(arg.hashCode())</tt>.
0299 *
0300 * <tr><td valign="top"> <tt>'s'</tt>, <tt>'S'</tt>
0301 * <td valign="top"> general
0302 * <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0303 * "<tt>null</tt>". If <i>arg</i> implements {@link Formattable}, then
0304 * {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
0305 * result is obtained by invoking <tt>arg.toString()</tt>.
0306 *
0307 * <tr><td valign="top"><tt>'c'</tt>, <tt>'C'</tt>
0308 * <td valign="top"> character
0309 * <td> The result is a Unicode character
0310 *
0311 * <tr><td valign="top"><tt>'d'</tt>
0312 * <td valign="top"> integral
0313 * <td> The result is formatted as a decimal integer
0314 *
0315 * <tr><td valign="top"><tt>'o'</tt>
0316 * <td valign="top"> integral
0317 * <td> The result is formatted as an octal integer
0318 *
0319 * <tr><td valign="top"><tt>'x'</tt>, <tt>'X'</tt>
0320 * <td valign="top"> integral
0321 * <td> The result is formatted as a hexadecimal integer
0322 *
0323 * <tr><td valign="top"><tt>'e'</tt>, <tt>'E'</tt>
0324 * <td valign="top"> floating point
0325 * <td> The result is formatted as a decimal number in computerized
0326 * scientific notation
0327 *
0328 * <tr><td valign="top"><tt>'f'</tt>
0329 * <td valign="top"> floating point
0330 * <td> The result is formatted as a decimal number
0331 *
0332 * <tr><td valign="top"><tt>'g'</tt>, <tt>'G'</tt>
0333 * <td valign="top"> floating point
0334 * <td> The result is formatted using computerized scientific notation or
0335 * decimal format, depending on the precision and the value after rounding.
0336 *
0337 * <tr><td valign="top"><tt>'a'</tt>, <tt>'A'</tt>
0338 * <td valign="top"> floating point
0339 * <td> The result is formatted as a hexadecimal floating-point number with
0340 * a significand and an exponent
0341 *
0342 * <tr><td valign="top"><tt>'t'</tt>, <tt>'T'</tt>
0343 * <td valign="top"> date/time
0344 * <td> Prefix for date and time conversion characters. See <a
0345 * href="#dt">Date/Time Conversions</a>.
0346 *
0347 * <tr><td valign="top"><tt>'%'</tt>
0348 * <td valign="top"> percent
0349 * <td> The result is a literal <tt>'%'</tt> (<tt>'\u0025'</tt>)
0350 *
0351 * <tr><td valign="top"><tt>'n'</tt>
0352 * <td valign="top"> line separator
0353 * <td> The result is the platform-specific line separator
0354 *
0355 * </table>
0356 *
0357 * <p> Any characters not explicitly defined as conversions are illegal and are
0358 * reserved for future extensions.
0359 *
0360 * <h4><a name="dt">Date/Time Conversions</a></h4>
0361 *
0362 * <p> The following date and time conversion suffix characters are defined for
0363 * the <tt>'t'</tt> and <tt>'T'</tt> conversions. The types are similar to but
0364 * not completely identical to those defined by GNU <tt>date</tt> and POSIX
0365 * <tt>strftime(3c)</tt>. Additional conversion types are provided to access
0366 * Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds within the
0367 * second).
0368 *
0369 * <p> The following conversion characters are used for formatting times:
0370 *
0371 * <table cellpadding=5 summary="time">
0372 *
0373 * <tr><td valign="top"> <tt>'H'</tt>
0374 * <td> Hour of the day for the 24-hour clock, formatted as two digits with
0375 * a leading zero as necessary i.e. <tt>00 - 23</tt>.
0376 *
0377 * <tr><td valign="top"><tt>'I'</tt>
0378 * <td> Hour for the 12-hour clock, formatted as two digits with a leading
0379 * zero as necessary, i.e. <tt>01 - 12</tt>.
0380 *
0381 * <tr><td valign="top"><tt>'k'</tt>
0382 * <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
0383 *
0384 * <tr><td valign="top"><tt>'l'</tt>
0385 * <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>.
0386 *
0387 * <tr><td valign="top"><tt>'M'</tt>
0388 * <td> Minute within the hour formatted as two digits with a leading zero
0389 * as necessary, i.e. <tt>00 - 59</tt>.
0390 *
0391 * <tr><td valign="top"><tt>'S'</tt>
0392 * <td> Seconds within the minute, formatted as two digits with a leading
0393 * zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
0394 * value required to support leap seconds).
0395 *
0396 * <tr><td valign="top"><tt>'L'</tt>
0397 * <td> Millisecond within the second formatted as three digits with
0398 * leading zeros as necessary, i.e. <tt>000 - 999</tt>.
0399 *
0400 * <tr><td valign="top"><tt>'N'</tt>
0401 * <td> Nanosecond within the second, formatted as nine digits with leading
0402 * zeros as necessary, i.e. <tt>000000000 - 999999999</tt>.
0403 *
0404 * <tr><td valign="top"><tt>'p'</tt>
0405 * <td> Locale-specific {@linkplain
0406 * java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
0407 * in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>". Use of the conversion
0408 * prefix <tt>'T'</tt> forces this output to upper case.
0409 *
0410 * <tr><td valign="top"><tt>'z'</tt>
0411 * <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>
0412 * style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
0413 *
0414 * <tr><td valign="top"><tt>'Z'</tt>
0415 * <td> A string representing the abbreviation for the time zone. The
0416 * Formatter's locale will supersede the locale of the argument (if any).
0417 *
0418 * <tr><td valign="top"><tt>'s'</tt>
0419 * <td> Seconds since the beginning of the epoch starting at 1 January 1970
0420 * <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
0421 * <tt>Long.MAX_VALUE/1000</tt>.
0422 *
0423 * <tr><td valign="top"><tt>'Q'</tt>
0424 * <td> Milliseconds since the beginning of the epoch starting at 1 January
0425 * 1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
0426 * <tt>Long.MAX_VALUE</tt>.
0427 *
0428 * </table>
0429 *
0430 * <p> The following conversion characters are used for formatting dates:
0431 *
0432 * <table cellpadding=5 summary="date">
0433 *
0434 * <tr><td valign="top"><tt>'B'</tt>
0435 * <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
0436 * full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
0437 *
0438 * <tr><td valign="top"><tt>'b'</tt>
0439 * <td> Locale-specific {@linkplain
0440 * java.text.DateFormatSymbols#getShortMonths abbreviated month name},
0441 * e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
0442 *
0443 * <tr><td valign="top"><tt>'h'</tt>
0444 * <td> Same as <tt>'b'</tt>.
0445 *
0446 * <tr><td valign="top"><tt>'A'</tt>
0447 * <td> Locale-specific full name of the {@linkplain
0448 * java.text.DateFormatSymbols#getWeekdays day of the week},
0449 * e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
0450 *
0451 * <tr><td valign="top"><tt>'a'</tt>
0452 * <td> Locale-specific short name of the {@linkplain
0453 * java.text.DateFormatSymbols#getShortWeekdays day of the week},
0454 * e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
0455 *
0456 * <tr><td valign="top"><tt>'C'</tt>
0457 * <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
0458 * with leading zero as necessary, i.e. <tt>00 - 99</tt>
0459 *
0460 * <tr><td valign="top"><tt>'Y'</tt>
0461 * <td> Year, formatted as at least four digits with leading zeros as
0462 * necessary, e.g. <tt>0092</tt> equals <tt>92</tt> CE for the Gregorian
0463 * calendar.
0464 *
0465 * <tr><td valign="top"><tt>'y'</tt>
0466 * <td> Last two digits of the year, formatted with leading zeros as
0467 * necessary, i.e. <tt>00 - 99</tt>.
0468 *
0469 * <tr><td valign="top"><tt>'j'</tt>
0470 * <td> Day of year, formatted as three digits with leading zeros as
0471 * necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
0472 *
0473 * <tr><td valign="top"><tt>'m'</tt>
0474 * <td> Month, formatted as two digits with leading zeros as necessary,
0475 * i.e. <tt>01 - 13</tt>.
0476 *
0477 * <tr><td valign="top"><tt>'d'</tt>
0478 * <td> Day of month, formatted as two digits with leading zeros as
0479 * necessary, i.e. <tt>01 - 31</tt>
0480 *
0481 * <tr><td valign="top"><tt>'e'</tt>
0482 * <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt>.
0483 *
0484 * </table>
0485 *
0486 * <p> The following conversion characters are used for formatting common
0487 * date/time compositions.
0488 *
0489 * <table cellpadding=5 summary="composites">
0490 *
0491 * <tr><td valign="top"><tt>'R'</tt>
0492 * <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
0493 *
0494 * <tr><td valign="top"><tt>'T'</tt>
0495 * <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
0496 *
0497 * <tr><td valign="top"><tt>'r'</tt>
0498 * <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS %Tp"</tt>.
0499 * The location of the morning or afternoon marker (<tt>'%Tp'</tt>) may be
0500 * locale-dependent.
0501 *
0502 * <tr><td valign="top"><tt>'D'</tt>
0503 * <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
0504 *
0505 * <tr><td valign="top"><tt>'F'</tt>
0506 * <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a>
0507 * complete date formatted as <tt>"%tY-%tm-%td"</tt>.
0508 *
0509 * <tr><td valign="top"><tt>'c'</tt>
0510 * <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
0511 * e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
0512 *
0513 * </table>
0514 *
0515 * <p> Any characters not explicitly defined as date/time conversion suffixes
0516 * are illegal and are reserved for future extensions.
0517 *
0518 * <h4> Flags </h4>
0519 *
0520 * <p> The following table summarizes the supported flags. <i>y</i> means the
0521 * flag is supported for the indicated argument types.
0522 *
0523 * <table cellpadding=5 summary="genConv">
0524 *
0525 * <tr><th valign="bottom"> Flag <th valign="bottom"> General
0526 * <th valign="bottom"> Character <th valign="bottom"> Integral
0527 * <th valign="bottom"> Floating Point
0528 * <th valign="bottom"> Date/Time
0529 * <th valign="bottom"> Description
0530 *
0531 * <tr><td> '-' <td align="center" valign="top"> y
0532 * <td align="center" valign="top"> y
0533 * <td align="center" valign="top"> y
0534 * <td align="center" valign="top"> y
0535 * <td align="center" valign="top"> y
0536 * <td> The result will be left-justified.
0537 *
0538 * <tr><td> '#' <td align="center" valign="top"> y<sup>1</sup>
0539 * <td align="center" valign="top"> -
0540 * <td align="center" valign="top"> y<sup>3</sup>
0541 * <td align="center" valign="top"> y
0542 * <td align="center" valign="top"> -
0543 * <td> The result should use a conversion-dependent alternate form
0544 *
0545 * <tr><td> '+' <td align="center" valign="top"> -
0546 * <td align="center" valign="top"> -
0547 * <td align="center" valign="top"> y<sup>4</sup>
0548 * <td align="center" valign="top"> y
0549 * <td align="center" valign="top"> -
0550 * <td> The result will always include a sign
0551 *
0552 * <tr><td> ' ' <td align="center" valign="top"> -
0553 * <td align="center" valign="top"> -
0554 * <td align="center" valign="top"> y<sup>4</sup>
0555 * <td align="center" valign="top"> y
0556 * <td align="center" valign="top"> -
0557 * <td> The result will include a leading space for positive values
0558 *
0559 * <tr><td> '0' <td align="center" valign="top"> -
0560 * <td align="center" valign="top"> -
0561 * <td align="center" valign="top"> y
0562 * <td align="center" valign="top"> y
0563 * <td align="center" valign="top"> -
0564 * <td> The result will be zero-padded
0565 *
0566 * <tr><td> ',' <td align="center" valign="top"> -
0567 * <td align="center" valign="top"> -
0568 * <td align="center" valign="top"> y<sup>2</sup>
0569 * <td align="center" valign="top"> y<sup>5</sup>
0570 * <td align="center" valign="top"> -
0571 * <td> The result will include locale-specific {@linkplain
0572 * java.text.DecimalFormatSymbols#getGroupingSeparator grouping separators}
0573 *
0574 * <tr><td> '(' <td align="center" valign="top"> -
0575 * <td align="center" valign="top"> -
0576 * <td align="center" valign="top"> y<sup>4</sup>
0577 * <td align="center" valign="top"> y<sup>5</sup>
0578 * <td align="center"> -
0579 * <td> The result will enclose negative numbers in parentheses
0580 *
0581 * </table>
0582 *
0583 * <p> <sup>1</sup> Depends on the definition of {@link Formattable}.
0584 *
0585 * <p> <sup>2</sup> For <tt>'d'</tt> conversion only.
0586 *
0587 * <p> <sup>3</sup> For <tt>'o'</tt>, <tt>'x'</tt>, and <tt>'X'</tt>
0588 * conversions only.
0589 *
0590 * <p> <sup>4</sup> For <tt>'d'</tt>, <tt>'o'</tt>, <tt>'x'</tt>, and
0591 * <tt>'X'</tt> conversions applied to {@link java.math.BigInteger BigInteger}
0592 * or <tt>'d'</tt> applied to <tt>byte</tt>, {@link Byte}, <tt>short</tt>, {@link
0593 * Short}, <tt>int</tt> and {@link Integer}, <tt>long</tt>, and {@link Long}.
0594 *
0595 * <p> <sup>5</sup> For <tt>'e'</tt>, <tt>'E'</tt>, <tt>'f'</tt>,
0596 * <tt>'g'</tt>, and <tt>'G'</tt> conversions only.
0597 *
0598 * <p> Any characters not explicitly defined as flags are illegal and are
0599 * reserved for future extensions.
0600 *
0601 * <h4> Width </h4>
0602 *
0603 * <p> The width is the minimum number of characters to be written to the
0604 * output. For the line separator conversion, width is not applicable; if it
0605 * is provided, an exception will be thrown.
0606 *
0607 * <h4> Precision </h4>
0608 *
0609 * <p> For general argument types, the precision is the maximum number of
0610 * characters to be written to the output.
0611 *
0612 * <p> For the floating-point conversions <tt>'e'</tt>, <tt>'E'</tt>, and
0613 * <tt>'f'</tt> the precision is the number of digits after the decimal
0614 * separator. If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the
0615 * precision is the total number of digits in the resulting magnitude after
0616 * rounding. If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the
0617 * precision must not be specified.
0618 *
0619 * <p> For character, integral, and date/time argument types and the percent
0620 * and line separator conversions, the precision is not applicable; if a
0621 * precision is provided, an exception will be thrown.
0622 *
0623 * <h4> Argument Index </h4>
0624 *
0625 * <p> The argument index is a decimal integer indicating the position of the
0626 * argument in the argument list. The first argument is referenced by
0627 * "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
0628 *
0629 * <p> Another way to reference arguments by position is to use the
0630 * <tt>'<'</tt> (<tt>'\u003c'</tt>) flag, which causes the argument for
0631 * the previous format specifier to be re-used. For example, the following two
0632 * statements would produce identical strings:
0633 *
0634 * <blockquote><pre>
0635 * Calendar c = ...;
0636 * String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0637 *
0638 * String s2 = String.format("Duke's Birthday: %1$tm %<te,%<tY", c);
0639 * </pre></blockquote>
0640 *
0641 * <hr>
0642 * <h3><a name="detail">Details</a></h3>
0643 *
0644 * <p> This section is intended to provide behavioral details for formatting,
0645 * including conditions and exceptions, supported data types, localization, and
0646 * interactions between flags, conversions, and data types. For an overview of
0647 * formatting concepts, refer to the <a href="#summary">Summary</a>
0648 *
0649 * <p> Any characters not explicitly defined as conversions, date/time
0650 * conversion suffixes, or flags are illegal and are reserved for
0651 * future extensions. Use of such a character in a format string will
0652 * cause an {@link UnknownFormatConversionException} or {@link
0653 * UnknownFormatFlagsException} to be thrown.
0654 *
0655 * <p> If the format specifier contains a width or precision with an invalid
0656 * value or which is otherwise unsupported, then a {@link
0657 * IllegalFormatWidthException} or {@link IllegalFormatPrecisionException}
0658 * respectively will be thrown.
0659 *
0660 * <p> If a format specifier contains a conversion character that is not
0661 * applicable to the corresponding argument, then an {@link
0662 * IllegalFormatConversionException} will be thrown.
0663 *
0664 * <p> All specified exceptions may be thrown by any of the <tt>format</tt>
0665 * methods of <tt>Formatter</tt> as well as by any <tt>format</tt> convenience
0666 * methods such as {@link String#format(String,Object...) String.format} and
0667 * {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
0668 *
0669 * <p> Conversions denoted by an upper-case character (i.e. <tt>'B'</tt>,
0670 * <tt>'H'</tt>, <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>,
0671 * <tt>'G'</tt>, <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the
0672 * corresponding lower-case conversion characters except that the result is
0673 * converted to upper case according to the rules of the prevailing {@link
0674 * java.util.Locale Locale}. The result is equivalent to the following
0675 * invocation of {@link String#toUpperCase()}
0676 *
0677 * <pre>
0678 * out.toUpperCase() </pre>
0679 *
0680 * <h4><a name="dgen">General</a></h4>
0681 *
0682 * <p> The following general conversions may be applied to any argument type:
0683 *
0684 * <table cellpadding=5 summary="dgConv">
0685 *
0686 * <tr><td valign="top"> <tt>'b'</tt>
0687 * <td valign="top"> <tt>'\u0062'</tt>
0688 * <td> Produces either "<tt>true</tt>" or "<tt>false</tt>" as returned by
0689 * {@link Boolean#toString(boolean)}.
0690 *
0691 * <p> If the argument is <tt>null</tt>, then the result is
0692 * "<tt>false</tt>". If the argument is a <tt>boolean</tt> or {@link
0693 * Boolean}, then the result is the string returned by {@link
0694 * String#valueOf(boolean) String.valueOf()}. Otherwise, the result is
0695 * "<tt>true</tt>".
0696 *
0697 * <p> If the <tt>'#'</tt> flag is given, then a {@link
0698 * FormatFlagsConversionMismatchException} will be thrown.
0699 *
0700 * <tr><td valign="top"> <tt>'B'</tt>
0701 * <td valign="top"> <tt>'\u0042'</tt>
0702 * <td> The upper-case variant of <tt>'b'</tt>.
0703 *
0704 * <tr><td valign="top"> <tt>'h'</tt>
0705 * <td valign="top"> <tt>'\u0068'</tt>
0706 * <td> Produces a string representing the hash code value of the object.
0707 *
0708 * <p> If the argument, <i>arg</i> is <tt>null</tt>, then the
0709 * result is "<tt>null</tt>". Otherwise, the result is obtained
0710 * by invoking <tt>Integer.toHexString(arg.hashCode())</tt>.
0711 *
0712 * <p> If the <tt>'#'</tt> flag is given, then a {@link
0713 * FormatFlagsConversionMismatchException} will be thrown.
0714 *
0715 * <tr><td valign="top"> <tt>'H'</tt>
0716 * <td valign="top"> <tt>'\u0048'</tt>
0717 * <td> The upper-case variant of <tt>'h'</tt>.
0718 *
0719 * <tr><td valign="top"> <tt>'s'</tt>
0720 * <td valign="top"> <tt>'\u0073'</tt>
0721 * <td> Produces a string.
0722 *
0723 * <p> If the argument is <tt>null</tt>, then the result is
0724 * "<tt>null</tt>". If the argument implements {@link Formattable}, then
0725 * its {@link Formattable#formatTo formatTo} method is invoked.
0726 * Otherwise, the result is obtained by invoking the argument's
0727 * <tt>toString()</tt> method.
0728 *
0729 * <p> If the <tt>'#'</tt> flag is given and the argument is not a {@link
0730 * Formattable} , then a {@link FormatFlagsConversionMismatchException}
0731 * will be thrown.
0732 *
0733 * <tr><td valign="top"> <tt>'S'</tt>
0734 * <td valign="top"> <tt>'\u0053'</tt>
0735 * <td> The upper-case variant of <tt>'s'</tt>.
0736 *
0737 * </table>
0738 *
0739 * <p> The following <a name="dFlags">flags</a> apply to general conversions:
0740 *
0741 * <table cellpadding=5 summary="dFlags">
0742 *
0743 * <tr><td valign="top"> <tt>'-'</tt>
0744 * <td valign="top"> <tt>'\u002d'</tt>
0745 * <td> Left justifies the output. Spaces (<tt>'\u0020'</tt>) will be
0746 * added at the end of the converted value as required to fill the minimum
0747 * width of the field. If the width is not provided, then a {@link
0748 * MissingFormatWidthException} will be thrown. If this flag is not given
0749 * then the output will be right-justified.
0750 *
0751 * <tr><td valign="top"> <tt>'#'</tt>
0752 * <td valign="top"> <tt>'\u0023'</tt>
0753 * <td> Requires the output use an alternate form. The definition of the
0754 * form is specified by the conversion.
0755 *
0756 * </table>
0757 *
0758 * <p> The <a name="genWidth">width</a> is the minimum number of characters to
0759 * be written to the
0760 * output. If the length of the converted value is less than the width then
0761 * the output will be padded by <tt>' '</tt> (<tt>\u0020'</tt>)
0762 * until the total number of characters equals the width. The padding is on
0763 * the left by default. If the <tt>'-'</tt> flag is given, then the padding
0764 * will be on the right. If the width is not specified then there is no
0765 * minimum.
0766 *
0767 * <p> The precision is the maximum number of characters to be written to the
0768 * output. The precision is applied before the width, thus the output will be
0769 * truncated to <tt>precision</tt> characters even if the width is greater than
0770 * the precision. If the precision is not specified then there is no explicit
0771 * limit on the number of characters.
0772 *
0773 * <h4><a name="dchar">Character</a></h4>
0774 *
0775 * This conversion may be applied to <tt>char</tt> and {@link Character}. It
0776 * may also be applied to the types <tt>byte</tt>, {@link Byte},
0777 * <tt>short</tt>, and {@link Short}, <tt>int</tt> and {@link Integer} when
0778 * {@link Character#isValidCodePoint} returns <tt>true</tt>. If it returns
0779 * <tt>false</tt> then an {@link IllegalFormatCodePointException} will be
0780 * thrown.
0781 *
0782 * <table cellpadding=5 summary="charConv">
0783 *
0784 * <tr><td valign="top"> <tt>'c'</tt>
0785 * <td valign="top"> <tt>'\u0063'</tt>
0786 * <td> Formats the argument as a Unicode character as described in <a
0787 * href="../lang/Character.html#unicode">Unicode Character
0788 * Representation</a>. This may be more than one 16-bit <tt>char</tt> in
0789 * the case where the argument represents a supplementary character.
0790 *
0791 * <p> If the <tt>'#'</tt> flag is given, then a {@link
0792 * FormatFlagsConversionMismatchException} will be thrown.
0793 *
0794 * <tr><td valign="top"> <tt>'C'</tt>
0795 * <td valign="top"> <tt>'\u0043'</tt>
0796 * <td> The upper-case variant of <tt>'c'</tt>.
0797 *
0798 * </table>
0799 *
0800 * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
0801 * conversions</a> applies. If the <tt>'#'</tt> flag is given, then a {@link
0802 * FormatFlagsConversionMismatchException} will be thrown.
0803 *
0804 * <p> The width is defined as for <a href="#genWidth">General conversions</a>.
0805 *
0806 * <p> The precision is not applicable. If the precision is specified then an
0807 * {@link IllegalFormatPrecisionException} will be thrown.
0808 *
0809 * <h4><a name="dnum">Numeric</a></h4>
0810 *
0811 * <p> Numeric conversions are divided into the following categories:
0812 *
0813 * <ol>
0814 *
0815 * <li> <a href="#dnint"><b>Byte, Short, Integer, and Long</b></a>
0816 *
0817 * <li> <a href="#dnbint"><b>BigInteger</b></a>
0818 *
0819 * <li> <a href="#dndec"><b>Float and Double</b></a>
0820 *
0821 * <li> <a href="#dndec"><b>BigDecimal</b></a>
0822 *
0823 * </ol>
0824 *
0825 * <p> Numeric types will be formatted according to the following algorithm:
0826 *
0827 * <p><b><a name="l10n algorithm"> Number Localization Algorithm</a></b>
0828 *
0829 * <p> After digits are obtained for the integer part, fractional part, and
0830 * exponent (as appropriate for the data type), the following transformation
0831 * is applied:
0832 *
0833 * <ol>
0834 *
0835 * <li> Each digit character <i>d</i> in the string is replaced by a
0836 * locale-specific digit computed relative to the current locale's
0837 * {@linkplain java.text.DecimalFormatSymbols#getZeroDigit() zero digit}
0838 * <i>z</i>; that is <i>d - </i> <tt>'0'</tt>
0839 * <i> + z</i>.
0840 *
0841 * <li> If a decimal separator is present, a locale-specific {@linkplain
0842 * java.text.DecimalFormatSymbols#getDecimalSeparator decimal separator} is
0843 * substituted.
0844 *
0845 * <li> If the <tt>','</tt> (<tt>'\u002c'</tt>)
0846 * <a name="l10n group">flag</a> is given, then the locale-specific {@linkplain
0847 * java.text.DecimalFormatSymbols#getGroupingSeparator grouping separator} is
0848 * inserted by scanning the integer part of the string from least significant
0849 * to most significant digits and inserting a separator at intervals defined by
0850 * the locale's {@linkplain java.text.DecimalFormat#getGroupingSize() grouping
0851 * size}.
0852 *
0853 * <li> If the <tt>'0'</tt> flag is given, then the locale-specific {@linkplain
0854 * java.text.DecimalFormatSymbols#getZeroDigit() zero digits} are inserted
0855 * after the sign character, if any, and before the first non-zero digit, until
0856 * the length of the string is equal to the requested field width.
0857 *
0858 * <li> If the value is negative and the <tt>'('</tt> flag is given, then a
0859 * <tt>'('</tt> (<tt>'\u0028'</tt>) is prepended and a <tt>')'</tt>
0860 * (<tt>'\u0029'</tt>) is appended.
0861 *
0862 * <li> If the value is negative (or floating-point negative zero) and
0863 * <tt>'('</tt> flag is not given, then a <tt>'-'</tt> (<tt>'\u002d'</tt>)
0864 * is prepended.
0865 *
0866 * <li> If the <tt>'+'</tt> flag is given and the value is positive or zero (or
0867 * floating-point positive zero), then a <tt>'+'</tt> (<tt>'\u002b'</tt>)
0868 * will be prepended.
0869 *
0870 * </ol>
0871 *
0872 * <p> If the value is NaN or positive infinity the literal strings "NaN" or
0873 * "Infinity" respectively, will be output. If the value is negative infinity,
0874 * then the output will be "(Infinity)" if the <tt>'('</tt> flag is given
0875 * otherwise the output will be "-Infinity". These values are not localized.
0876 *
0877 * <p><a name="dnint"><b> Byte, Short, Integer, and Long </b></a>
0878 *
0879 * <p> The following conversions may be applied to <tt>byte</tt>, {@link Byte},
0880 * <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link Integer},
0881 * <tt>long</tt>, and {@link Long}.
0882 *
0883 * <table cellpadding=5 summary="IntConv">
0884 *
0885 * <tr><td valign="top"> <tt>'d'</tt>
0886 * <td valign="top"> <tt>'\u0054'</tt>
0887 * <td> Formats the argument as a decimal integer. The <a
0888 * href="#l10n algorithm">localization algorithm</a> is applied.
0889 *
0890 * <p> If the <tt>'0'</tt> flag is given and the value is negative, then
0891 * the zero padding will occur after the sign.
0892 *
0893 * <p> If the <tt>'#'</tt> flag is given then a {@link
0894 * FormatFlagsConversionMismatchException} will be thrown.
0895 *
0896 * <tr><td valign="top"> <tt>'o'</tt>
0897 * <td valign="top"> <tt>'\u006f'</tt>
0898 * <td> Formats the argument as an integer in base eight. No localization
0899 * is applied.
0900 *
0901 * <p> If <i>x</i> is negative then the result will be an unsigned value
0902 * generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
0903 * number of bits in the type as returned by the static <tt>SIZE</tt> field
0904 * in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
0905 * {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
0906 * classes as appropriate.
0907 *
0908 * <p> If the <tt>'#'</tt> flag is given then the output will always begin
0909 * with the radix indicator <tt>'0'</tt>.
0910 *
0911 * <p> If the <tt>'0'</tt> flag is given then the output will be padded
0912 * with leading zeros to the field width following any indication of sign.
0913 *
0914 * <p> If <tt>'('</tt>, <tt>'+'</tt>, '  ', or <tt>','</tt> flags
0915 * are given then a {@link FormatFlagsConversionMismatchException} will be
0916 * thrown.
0917 *
0918 * <tr><td valign="top"> <tt>'x'</tt>
0919 * <td valign="top"> <tt>'\u0078'</tt>
0920 * <td> Formats the argument as an integer in base sixteen. No
0921 * localization is applied.
0922 *
0923 * <p> If <i>x</i> is negative then the result will be an unsigned value
0924 * generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
0925 * number of bits in the type as returned by the static <tt>SIZE</tt> field
0926 * in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
0927 * {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
0928 * classes as appropriate.
0929 *
0930 * <p> If the <tt>'#'</tt> flag is given then the output will always begin
0931 * with the radix indicator <tt>"0x"</tt>.
0932 *
0933 * <p> If the <tt>'0'</tt> flag is given then the output will be padded to
0934 * the field width with leading zeros after the radix indicator or sign (if
0935 * present).
0936 *
0937 * <p> If <tt>'('</tt>, <tt>' '</tt>, <tt>'+'</tt>, or
0938 * <tt>','</tt> flags are given then a {@link
0939 * FormatFlagsConversionMismatchException} will be thrown.
0940 *
0941 * <tr><td valign="top"> <tt>'X'</tt>
0942 * <td valign="top"> <tt>'\u0058'</tt>
0943 * <td> The upper-case variant of <tt>'x'</tt>. The entire string
0944 * representing the number will be converted to {@linkplain
0945 * String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
0946 * all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
0947 * (<tt>'\u0061'</tt> - <tt>'\u0066'</tt>).
0948 *
0949 * </table>
0950 *
0951 * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
0952 * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
0953 * contain the radix indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
0954 * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
0955 * and the value.
0956 *
0957 * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
0958 * before the sign.
0959 *
0960 * <p> The following <a name="intFlags">flags</a> apply to numeric integral
0961 * conversions:
0962 *
0963 * <table cellpadding=5 summary="intFlags">
0964 *
0965 * <tr><td valign="top"> <tt>'+'</tt>
0966 * <td valign="top"> <tt>'\u002b'</tt>
0967 * <td> Requires the output to include a positive sign for all positive
0968 * numbers. If this flag is not given then only negative values will
0969 * include a sign.
0970 *
0971 * <p> If both the <tt>'+'</tt> and <tt>' '</tt> flags are given
0972 * then an {@link IllegalFormatFlagsException} will be thrown.
0973 *
0974 * <tr><td valign="top"> <tt>' '</tt>
0975 * <td valign="top"> <tt>'\u0020'</tt>
0976 * <td> Requires the output to include a single extra space
0977 * (<tt>'\u0020'</tt>) for non-negative values.
0978 *
0979 * <p> If both the <tt>'+'</tt> and <tt>' '</tt> flags are given
0980 * then an {@link IllegalFormatFlagsException} will be thrown.
0981 *
0982 * <tr><td valign="top"> <tt>'0'</tt>
0983 * <td valign="top"> <tt>'\u0030'</tt>
0984 * <td> Requires the output to be padded with leading {@linkplain
0985 * java.text.DecimalFormatSymbols#getZeroDigit zeros} to the minimum field
0986 * width following any sign or radix indicator except when converting NaN
0987 * or infinity. If the width is not provided, then a {@link
0988 * MissingFormatWidthException} will be thrown.
0989 *
0990 * <p> If both the <tt>'-'</tt> and <tt>'0'</tt> flags are given then an
0991 * {@link IllegalFormatFlagsException} will be thrown.
0992 *
0993 * <tr><td valign="top"> <tt>','</tt>
0994 * <td valign="top"> <tt>'\u002c'</tt>
0995 * <td> Requires the output to include the locale-specific {@linkplain
0996 * java.text.DecimalFormatSymbols#getGroupingSeparator group separators} as
0997 * described in the <a href="#l10n group">"group" section</a> of the
0998 * localization algorithm.
0999 *
1000 * <tr><td valign="top"> <tt>'('</tt>
1001 * <td valign="top"> <tt>'\u0028'</tt>
1002 * <td> Requires the output to prepend a <tt>'('</tt>
1003 * (<tt>'\u0028'</tt>) and append a <tt>')'</tt>
1004 * (<tt>'\u0029'</tt>) to negative values.
1005 *
1006 * </table>
1007 *
1008 * <p> If no <a name="intdFlags">flags</a> are given the default formatting is
1009 * as follows:
1010 *
1011 * <ul>
1012 *
1013 * <li> The output is right-justified within the <tt>width</tt>
1014 *
1015 * <li> Negative numbers begin with a <tt>'-'</tt> (<tt>'\u002d'</tt>)
1016 *
1017 * <li> Positive numbers and zero do not include a sign or extra leading
1018 * space
1019 *
1020 * <li> No grouping separators are included
1021 *
1022 * </ul>
1023 *
1024 * <p> The <a name="intWidth">width</a> is the minimum number of characters to
1025 * be written to the output. This includes any signs, digits, grouping
1026 * separators, radix indicator, and parentheses. If the length of the
1027 * converted value is less than the width then the output will be padded by
1028 * spaces (<tt>'\u0020'</tt>) until the total number of characters equals
1029 * width. The padding is on the left by default. If <tt>'-'</tt> flag is
1030 * given then the padding will be on the right. If width is not specified then
1031 * there is no minimum.
1032 *
1033 * <p> The precision is not applicable. If precision is specified then an
1034 * {@link IllegalFormatPrecisionException} will be thrown.
1035 *
1036 * <p><a name="dnbint"><b> BigInteger </b></a>
1037 *
1038 * <p> The following conversions may be applied to {@link
1039 * java.math.BigInteger}.
1040 *
1041 * <table cellpadding=5 summary="BIntConv">
1042 *
1043 * <tr><td valign="top"> <tt>'d'</tt>
1044 * <td valign="top"> <tt>'\u0054'</tt>
1045 * <td> Requires the output to be formatted as a decimal integer. The <a
1046 * href="#l10n algorithm">localization algorithm</a> is applied.
1047 *
1048 * <p> If the <tt>'#'</tt> flag is given {@link
1049 * FormatFlagsConversionMismatchException} will be thrown.
1050 *
1051 * <tr><td valign="top"> <tt>'o'</tt>
1052 * <td valign="top"> <tt>'\u006f'</tt>
1053 * <td> Requires the output to be formatted as an integer in base eight.
1054 * No localization is applied.
1055 *
1056 * <p> If <i>x</i> is negative then the result will be a signed value
1057 * beginning with <tt>'-'</tt> (<tt>'\u002d'</tt>). Signed output is
1058 * allowed for this type because unlike the primitive types it is not
1059 * possible to create an unsigned equivalent without assuming an explicit
1060 * data-type size.
1061 *
1062 * <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1063 * then the result will begin with <tt>'+'</tt> (<tt>'\u002b'</tt>).
1064 *
1065 * <p> If the <tt>'#'</tt> flag is given then the output will always begin
1066 * with <tt>'0'</tt> prefix.
1067 *
1068 * <p> If the <tt>'0'</tt> flag is given then the output will be padded
1069 * with leading zeros to the field width following any indication of sign.
1070 *
1071 * <p> If the <tt>','</tt> flag is given then a {@link
1072 * FormatFlagsConversionMismatchException} will be thrown.
1073 *
1074 * <tr><td valign="top"> <tt>'x'</tt>
1075 * <td valign="top"> <tt>'\u0078'</tt>
1076 * <td> Requires the output to be formatted as an integer in base
1077 * sixteen. No localization is applied.
1078 *
1079 * <p> If <i>x</i> is negative then the result will be a signed value
1080 * beginning with <tt>'-'</tt> (<tt>'\u002d'</tt>). Signed output is
1081 * allowed for this type because unlike the primitive types it is not
1082 * possible to create an unsigned equivalent without assuming an explicit
1083 * data-type size.
1084 *
1085 * <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1086 * then the result will begin with <tt>'+'</tt> (<tt>'\u002b'</tt>).
1087 *
1088 * <p> If the <tt>'#'</tt> flag is given then the output will always begin
1089 * with the radix indicator <tt>"0x"</tt>.
1090 *
1091 * <p> If the <tt>'0'</tt> flag is given then the output will be padded to
1092 * the field width with leading zeros after the radix indicator or sign (if
1093 * present).
1094 *
1095 * <p> If the <tt>','</tt> flag is given then a {@link
1096 * FormatFlagsConversionMismatchException} will be thrown.
1097 *
1098 * <tr><td valign="top"> <tt>'X'</tt>
1099 * <td valign="top"> <tt>'\u0058'</tt>
1100 * <td> The upper-case variant of <tt>'x'</tt>. The entire string
1101 * representing the number will be converted to {@linkplain
1102 * String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
1103 * all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
1104 * (<tt>'\u0061'</tt> - <tt>'\u0066'</tt>).
1105 *
1106 * </table>
1107 *
1108 * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
1109 * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
1110 * contain the base indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
1111 * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
1112 * and the value.
1113 *
1114 * <p> If the <tt>'0'</tt> flag is given and the value is negative, then the
1115 * zero padding will occur after the sign.
1116 *
1117 * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
1118 * before the sign.
1119 *
1120 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1121 * Long apply. The <a href="#intdFlags">default behavior</a> when no flags are
1122 * given is the same as for Byte, Short, Integer, and Long.
1123 *
1124 * <p> The specification of <a href="#intWidth">width</a> is the same as
1125 * defined for Byte, Short, Integer, and Long.
1126 *
1127 * <p> The precision is not applicable. If precision is specified then an
1128 * {@link IllegalFormatPrecisionException} will be thrown.
1129 *
1130 * <p><a name="dndec"><b> Float and Double</b></a>
1131 *
1132 * <p> The following conversions may be applied to <tt>float</tt>, {@link
1133 * Float}, <tt>double</tt> and {@link Double}.
1134 *
1135 * <table cellpadding=5 summary="floatConv">
1136 *
1137 * <tr><td valign="top"> <tt>'e'</tt>
1138 * <td valign="top"> <tt>'\u0065'</tt>
1139 * <td> Requires the output to be formatted using <a
1140 * name="scientific">computerized scientific notation</a>. The <a
1141 * href="#l10n algorithm">localization algorithm</a> is applied.
1142 *
1143 * <p> The formatting of the magnitude <i>m</i> depends upon its value.
1144 *
1145 * <p> If <i>m</i> is NaN or infinite, the literal strings "NaN" or
1146 * "Infinity", respectively, will be output. These values are not
1147 * localized.
1148 *
1149 * <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1150 * will be <tt>"+00"</tt>.
1151 *
1152 * <p> Otherwise, the result is a string that represents the sign and
1153 * magnitude (absolute value) of the argument. The formatting of the sign
1154 * is described in the <a href="#l10n algorithm">localization
1155 * algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1156 * value.
1157 *
1158 * <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1159 * <= <i>m</i> < 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1160 * mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1161 * that 1 <= <i>a</i> < 10. The magnitude is then represented as the
1162 * integer part of <i>a</i>, as a single decimal digit, followed by the
1163 * decimal separator followed by decimal digits representing the fractional
1164 * part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1165 * (<tt>'\u0065'</tt>), followed by the sign of the exponent, followed
1166 * by a representation of <i>n</i> as a decimal integer, as produced by the
1167 * method {@link Long#toString(long, int)}, and zero-padded to include at
1168 * least two digits.
1169 *
1170 * <p> The number of digits in the result for the fractional part of
1171 * <i>m</i> or <i>a</i> is equal to the precision. If the precision is not
1172 * specified then the default value is <tt>6</tt>. If the precision is less
1173 * than the number of digits which would appear after the decimal point in
1174 * the string returned by {@link Float#toString(float)} or {@link
1175 * Double#toString(double)} respectively, then the value will be rounded
1176 * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1177 * algorithm}. Otherwise, zeros may be appended to reach the precision.
1178 * For a canonical representation of the value, use {@link
1179 * Float#toString(float)} or {@link Double#toString(double)} as
1180 * appropriate.
1181 *
1182 * <p>If the <tt>','</tt> flag is given, then an {@link
1183 * FormatFlagsConversionMismatchException} will be thrown.
1184 *
1185 * <tr><td valign="top"> <tt>'E'</tt>
1186 * <td valign="top"> <tt>'\u0045'</tt>
1187 * <td> The upper-case variant of <tt>'e'</tt>. The exponent symbol
1188 * will be <tt>'E'</tt> (<tt>'\u0045'</tt>).
1189 *
1190 * <tr><td valign="top"> <tt>'g'</tt>
1191 * <td valign="top"> <tt>'\u0067'</tt>
1192 * <td> Requires the output to be formatted in general scientific notation
1193 * as described below. The <a href="#l10n algorithm">localization
1194 * algorithm</a> is applied.
1195 *
1196 * <p> After rounding for the precision, the formatting of the resulting
1197 * magnitude <i>m</i> depends on its value.
1198 *
1199 * <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1200 * than 10<sup>precision</sup> then it is represented in <i><a
1201 * href="#decimal">decimal format</a></i>.
1202 *
1203 * <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1204 * 10<sup>precision</sup>, then it is represented in <i><a
1205 * href="#scientific">computerized scientific notation</a></i>.
1206 *
1207 * <p> The total number of significant digits in <i>m</i> is equal to the
1208 * precision. If the precision is not specified, then the default value is
1209 * <tt>6</tt>. If the precision is <tt>0</tt>, then it is taken to be
1210 * <tt>1</tt>.
1211 *
1212 * <p> If the <tt>'#'</tt> flag is given then an {@link
1213 * FormatFlagsConversionMismatchException} will be thrown.
1214 *
1215 * <tr><td valign="top"> <tt>'G'</tt>
1216 * <td valign="top"> <tt>'\u0047'</tt>
1217 * <td> The upper-case variant of <tt>'g'</tt>.
1218 *
1219 * <tr><td valign="top"> <tt>'f'</tt>
1220 * <td valign="top"> <tt>'\u0066'</tt>
1221 * <td> Requires the output to be formatted using <a name="decimal">decimal
1222 * format</a>. The <a href="#l10n algorithm">localization algorithm</a> is
1223 * applied.
1224 *
1225 * <p> The result is a string that represents the sign and magnitude
1226 * (absolute value) of the argument. The formatting of the sign is
1227 * described in the <a href="#l10n algorithm">localization
1228 * algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1229 * value.
1230 *
1231 * <p> If <i>m</i> NaN or infinite, the literal strings "NaN" or
1232 * "Infinity", respectively, will be output. These values are not
1233 * localized.
1234 *
1235 * <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1236 * leading zeroes, followed by the decimal separator followed by one or
1237 * more decimal digits representing the fractional part of <i>m</i>.
1238 *
1239 * <p> The number of digits in the result for the fractional part of
1240 * <i>m</i> or <i>a</i> is equal to the precision. If the precision is not
1241 * specified then the default value is <tt>6</tt>. If the precision is less
1242 * than the number of digits which would appear after the decimal point in
1243 * the string returned by {@link Float#toString(float)} or {@link
1244 * Double#toString(double)} respectively, then the value will be rounded
1245 * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1246 * algorithm}. Otherwise, zeros may be appended to reach the precision.
1247 * For a canonical representation of the value,use {@link
1248 * Float#toString(float)} or {@link Double#toString(double)} as
1249 * appropriate.
1250 *
1251 * <tr><td valign="top"> <tt>'a'</tt>
1252 * <td valign="top"> <tt>'\u0061'</tt>
1253 * <td> Requires the output to be formatted in hexadecimal exponential
1254 * form. No localization is applied.
1255 *
1256 * <p> The result is a string that represents the sign and magnitude
1257 * (absolute value) of the argument <i>x</i>.
1258 *
1259 * <p> If <i>x</i> is negative or a negative-zero value then the result
1260 * will begin with <tt>'-'</tt> (<tt>'\u002d'</tt>).
1261 *
1262 * <p> If <i>x</i> is positive or a positive-zero value and the
1263 * <tt>'+'</tt> flag is given then the result will begin with <tt>'+'</tt>
1264 * (<tt>'\u002b'</tt>).
1265 *
1266 * <p> The formatting of the magnitude <i>m</i> depends upon its value.
1267 *
1268 * <ul>
1269 *
1270 * <li> If the value is NaN or infinite, the literal strings "NaN" or
1271 * "Infinity", respectively, will be output.
1272 *
1273 * <li> If <i>m</i> is zero then it is represented by the string
1274 * <tt>"0x0.0p0"</tt>.
1275 *
1276 * <li> If <i>m</i> is a <tt>double</tt> value with a normalized
1277 * representation then substrings are used to represent the significand and
1278 * exponent fields. The significand is represented by the characters
1279 * <tt>"0x1."</tt> followed by the hexadecimal representation of the rest
1280 * of the significand as a fraction. The exponent is represented by
1281 * <tt>'p'</tt> (<tt>'\u0070'</tt>) followed by a decimal string of the
1282 * unbiased exponent as if produced by invoking {@link
1283 * Integer#toString(int) Integer.toString} on the exponent value.
1284 *
1285 * <li> If <i>m</i> is a <tt>double</tt> value with a subnormal
1286 * representation then the significand is represented by the characters
1287 * <tt>'0x0.'</tt> followed by the hexadecimal representation of the rest
1288 * of the significand as a fraction. The exponent is represented by
1289 * <tt>'p-1022'</tt>. Note that there must be at least one nonzero digit
1290 * in a subnormal significand.
1291 *
1292 * </ul>
1293 *
1294 * <p> If the <tt>'('</tt> or <tt>','</tt> flags are given, then a {@link
1295 * FormatFlagsConversionMismatchException} will be thrown.
1296 *
1297 * <tr><td valign="top"> <tt>'A'</tt>
1298 * <td valign="top"> <tt>'\u0041'</tt>
1299 * <td> The upper-case variant of <tt>'a'</tt>. The entire string
1300 * representing the number will be converted to upper case including the
1301 * <tt>'x'</tt> (<tt>'\u0078'</tt>) and <tt>'p'</tt>
1302 * (<tt>'\u0070'</tt> and all hexadecimal digits <tt>'a'</tt> -
1303 * <tt>'f'</tt> (<tt>'\u0061'</tt> - <tt>'\u0066'</tt>).
1304 *
1305 * </table>
1306 *
1307 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1308 * Long apply.
1309 *
1310 * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1311 * always be present.
1312 *
1313 * <p> If no <a name="floatdFlags">flags</a> are given the default formatting
1314 * is as follows:
1315 *
1316 * <ul>
1317 *
1318 * <li> The output is right-justified within the <tt>width</tt>
1319 *
1320 * <li> Negative numbers begin with a <tt>'-'</tt>
1321 *
1322 * <li> Positive numbers and positive zero do not include a sign or extra
1323 * leading space
1324 *
1325 * <li> No grouping separators are included
1326 *
1327 * <li> The decimal separator will only appear if a digit follows it
1328 *
1329 * </ul>
1330 *
1331 * <p> The <a name="floatDWidth">width</a> is the minimum number of characters
1332 * to be written to the output. This includes any signs, digits, grouping
1333 * separators, decimal separators, exponential symbol, radix indicator,
1334 * parentheses, and strings representing infinity and NaN as applicable. If
1335 * the length of the converted value is less than the width then the output
1336 * will be padded by spaces (<tt>'\u0020'</tt>) until the total number of
1337 * characters equals width. The padding is on the left by default. If the
1338 * <tt>'-'</tt> flag is given then the padding will be on the right. If width
1339 * is not specified then there is no minimum.
1340 *
1341 * <p> If the <a name="floatDPrec">conversion</a> is <tt>'e'</tt>,
1342 * <tt>'E'</tt> or <tt>'f'</tt>, then the precision is the number of digits
1343 * after the decimal separator. If the precision is not specified, then it is
1344 * assumed to be <tt>6</tt>.
1345 *
1346 * <p> If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the precision is
1347 * the total number of significant digits in the resulting magnitude after
1348 * rounding. If the precision is not specified, then the default value is
1349 * <tt>6</tt>. If the precision is <tt>0</tt>, then it is taken to be
1350 * <tt>1</tt>.
1351 *
1352 * <p> If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the precision
1353 * is the number of hexadecimal digits after the decimal separator. If the
1354 * precision is not provided, then all of the digits as returned by {@link
1355 * Double#toHexString(double)} will be output.
1356 *
1357 * <p><a name="dndec"><b> BigDecimal </b></a>
1358 *
1359 * <p> The following conversions may be applied {@link java.math.BigDecimal
1360 * BigDecimal}.
1361 *
1362 * <table cellpadding=5 summary="floatConv">
1363 *
1364 * <tr><td valign="top"> <tt>'e'</tt>
1365 * <td valign="top"> <tt>'\u0065'</tt>
1366 * <td> Requires the output to be formatted using <a
1367 * name="scientific">computerized scientific notation</a>. The <a
1368 * href="#l10n algorithm">localization algorithm</a> is applied.
1369 *
1370 * <p> The formatting of the magnitude <i>m</i> depends upon its value.
1371 *
1372 * <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1373 * will be <tt>"+00"</tt>.
1374 *
1375 * <p> Otherwise, the result is a string that represents the sign and
1376 * magnitude (absolute value) of the argument. The formatting of the sign
1377 * is described in the <a href="#l10n algorithm">localization
1378 * algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1379 * value.
1380 *
1381 * <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1382 * <= <i>m</i> < 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1383 * mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1384 * that 1 <= <i>a</i> < 10. The magnitude is then represented as the
1385 * integer part of <i>a</i>, as a single decimal digit, followed by the
1386 * decimal separator followed by decimal digits representing the fractional
1387 * part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1388 * (<tt>'\u0065'</tt>), followed by the sign of the exponent, followed
1389 * by a representation of <i>n</i> as a decimal integer, as produced by the
1390 * method {@link Long#toString(long, int)}, and zero-padded to include at
1391 * least two digits.
1392 *
1393 * <p> The number of digits in the result for the fractional part of
1394 * <i>m</i> or <i>a</i> is equal to the precision. If the precision is not
1395 * specified then the default value is <tt>6</tt>. If the precision is
1396 * less than the number of digits which would appear after the decimal
1397 * point in the string returned by {@link Float#toString(float)} or {@link
1398 * Double#toString(double)} respectively, then the value will be rounded
1399 * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1400 * algorithm}. Otherwise, zeros may be appended to reach the precision.
1401 * For a canonical representation of the value, use {@link
1402 * BigDecimal#toString()}.
1403 *
1404 * <p> If the <tt>','</tt> flag is given, then an {@link
1405 * FormatFlagsConversionMismatchException} will be thrown.
1406 *
1407 * <tr><td valign="top"> <tt>'E'</tt>
1408 * <td valign="top"> <tt>'\u0045'</tt>
1409 * <td> The upper-case variant of <tt>'e'</tt>. The exponent symbol
1410 * will be <tt>'E'</tt> (<tt>'\u0045'</tt>).
1411 *
1412 * <tr><td valign="top"> <tt>'g'</tt>
1413 * <td valign="top"> <tt>'\u0067'</tt>
1414 * <td> Requires the output to be formatted in general scientific notation
1415 * as described below. The <a href="#l10n algorithm">localization
1416 * algorithm</a> is applied.
1417 *
1418 * <p> After rounding for the precision, the formatting of the resulting
1419 * magnitude <i>m</i> depends on its value.
1420 *
1421 * <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1422 * than 10<sup>precision</sup> then it is represented in <i><a
1423 * href="#decimal">decimal format</a></i>.
1424 *
1425 * <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1426 * 10<sup>precision</sup>, then it is represented in <i><a
1427 * href="#scientific">computerized scientific notation</a></i>.
1428 *
1429 * <p> The total number of significant digits in <i>m</i> is equal to the
1430 * precision. If the precision is not specified, then the default value is
1431 * <tt>6</tt>. If the precision is <tt>0</tt>, then it is taken to be
1432 * <tt>1</tt>.
1433 *
1434 * <p> If the <tt>'#'</tt> flag is given then an {@link
1435 * FormatFlagsConversionMismatchException} will be thrown.
1436 *
1437 * <tr><td valign="top"> <tt>'G'</tt>
1438 * <td valign="top"> <tt>'\u0047'</tt>
1439 * <td> The upper-case variant of <tt>'g'</tt>.
1440 *
1441 * <tr><td valign="top"> <tt>'f'</tt>
1442 * <td valign="top"> <tt>'\u0066'</tt>
1443 * <td> Requires the output to be formatted using <a name="decimal">decimal
1444 * format</a>. The <a href="#l10n algorithm">localization algorithm</a> is
1445 * applied.
1446 *
1447 * <p> The result is a string that represents the sign and magnitude
1448 * (absolute value) of the argument. The formatting of the sign is
1449 * described in the <a href="#l10n algorithm">localization
1450 * algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1451 * value.
1452 *
1453 * <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1454 * leading zeroes, followed by the decimal separator followed by one or
1455 * more decimal digits representing the fractional part of <i>m</i>.
1456 *
1457 * <p> The number of digits in the result for the fractional part of
1458 * <i>m</i> or <i>a</i> is equal to the precision. If the precision is not
1459 * specified then the default value is <tt>6</tt>. If the precision is
1460 * less than the number of digits which would appear after the decimal
1461 * point in the string returned by {@link Float#toString(float)} or {@link
1462 * Double#toString(double)} respectively, then the value will be rounded
1463 * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1464 * algorithm}. Otherwise, zeros may be appended to reach the precision.
1465 * For a canonical representation of the value, use {@link
1466 * BigDecimal#toString()}.
1467 *
1468 * </table>
1469 *
1470 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1471 * Long apply.
1472 *
1473 * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1474 * always be present.
1475 *
1476 * <p> The <a href="#floatdFlags">default behavior</a> when no flags are
1477 * given is the same as for Float and Double.
1478 *
1479 * <p> The specification of <a href="#floatDWidth">width</a> and <a
1480 * href="#floatDPrec">precision</a> is the same as defined for Float and
1481 * Double.
1482 *
1483 * <h4><a name="ddt">Date/Time</a></h4>
1484 *
1485 * <p> This conversion may be applied to <tt>long</tt>, {@link Long}, {@link
1486 * Calendar}, and {@link Date}.
1487 *
1488 * <table cellpadding=5 summary="DTConv">
1489 *
1490 * <tr><td valign="top"> <tt>'t'</tt>
1491 * <td valign="top"> <tt>'\u0074'</tt>
1492 * <td> Prefix for date and time conversion characters.
1493 * <tr><td valign="top"> <tt>'T'</tt>
1494 * <td valign="top"> <tt>'\u0054'</tt>
1495 * <td> The upper-case variant of <tt>'t'</tt>.
1496 *
1497 * </table>
1498 *
1499 * <p> The following date and time conversion character suffixes are defined
1500 * for the <tt>'t'</tt> and <tt>'T'</tt> conversions. The types are similar to
1501 * but not completely identical to those defined by GNU <tt>date</tt> and
1502 * POSIX <tt>strftime(3c)</tt>. Additional conversion types are provided to
1503 * access Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds
1504 * within the second).
1505 *
1506 * <p> The following conversion characters are used for formatting times:
1507 *
1508 * <table cellpadding=5 summary="time">
1509 *
1510 * <tr><td valign="top"> <tt>'H'</tt>
1511 * <td valign="top"> <tt>'\u0048'</tt>
1512 * <td> Hour of the day for the 24-hour clock, formatted as two digits with
1513 * a leading zero as necessary i.e. <tt>00 - 23</tt>. <tt>00</tt>
1514 * corresponds to midnight.
1515 *
1516 * <tr><td valign="top"><tt>'I'</tt>
1517 * <td valign="top"> <tt>'\u0049'</tt>
1518 * <td> Hour for the 12-hour clock, formatted as two digits with a leading
1519 * zero as necessary, i.e. <tt>01 - 12</tt>. <tt>01</tt> corresponds to
1520 * one o'clock (either morning or afternoon).
1521 *
1522 * <tr><td valign="top"><tt>'k'</tt>
1523 * <td valign="top"> <tt>'\u006b'</tt>
1524 * <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
1525 * <tt>0</tt> corresponds to midnight.
1526 *
1527 * <tr><td valign="top"><tt>'l'</tt>
1528 * <td valign="top"> <tt>'\u006c'</tt>
1529 * <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>. <tt>1</tt>
1530 * corresponds to one o'clock (either morning or afternoon).
1531 *
1532 * <tr><td valign="top"><tt>'M'</tt>
1533 * <td valign="top"> <tt>'\u004d'</tt>
1534 * <td> Minute within the hour formatted as two digits with a leading zero
1535 * as necessary, i.e. <tt>00 - 59</tt>.
1536 *
1537 * <tr><td valign="top"><tt>'S'</tt>
1538 * <td valign="top"> <tt>'\u0053'</tt>
1539 * <td> Seconds within the minute, formatted as two digits with a leading
1540 * zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
1541 * value required to support leap seconds).
1542 *
1543 * <tr><td valign="top"><tt>'L'</tt>
1544 * <td valign="top"> <tt>'\u004c'</tt>
1545 * <td> Millisecond within the second formatted as three digits with
1546 * leading zeros as necessary, i.e. <tt>000 - 999</tt>.
1547 *
1548 * <tr><td valign="top"><tt>'N'</tt>
1549 * <td valign="top"> <tt>'\u004e'</tt>
1550 * <td> Nanosecond within the second, formatted as nine digits with leading
1551 * zeros as necessary, i.e. <tt>000000000 - 999999999</tt>. The precision
1552 * of this value is limited by the resolution of the underlying operating
1553 * system or hardware.
1554 *
1555 * <tr><td valign="top"><tt>'p'</tt>
1556 * <td valign="top"> <tt>'\u0070'</tt>
1557 * <td> Locale-specific {@linkplain
1558 * java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
1559 * in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>". Use of the
1560 * conversion prefix <tt>'T'</tt> forces this output to upper case. (Note
1561 * that <tt>'p'</tt> produces lower-case output. This is different from
1562 * GNU <tt>date</tt> and POSIX <tt>strftime(3c)</tt> which produce
1563 * upper-case output.)
1564 *
1565 * <tr><td valign="top"><tt>'z'</tt>
1566 * <td valign="top"> <tt>'\u007a'</tt>
1567 * <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>
1568 * style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
1569 *
1570 * <tr><td valign="top"><tt>'Z'</tt>
1571 * <td valign="top"> <tt>'\u005a'</tt>
1572 * <td> A string representing the abbreviation for the time zone.
1573 *
1574 * <tr><td valign="top"><tt>'s'</tt>
1575 * <td valign="top"> <tt>'\u0073'</tt>
1576 * <td> Seconds since the beginning of the epoch starting at 1 January 1970
1577 * <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
1578 * <tt>Long.MAX_VALUE/1000</tt>.
1579 *
1580 * <tr><td valign="top"><tt>'Q'</tt>
1581 * <td valign="top"> <tt>'\u004f'</tt>
1582 * <td> Milliseconds since the beginning of the epoch starting at 1 January
1583 * 1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
1584 * <tt>Long.MAX_VALUE</tt>. The precision of this value is limited by
1585 * the resolution of the underlying operating system or hardware.
1586 *
1587 * </table>
1588 *
1589 * <p> The following conversion characters are used for formatting dates:
1590 *
1591 * <table cellpadding=5 summary="date">
1592 *
1593 * <tr><td valign="top"><tt>'B'</tt>
1594 * <td valign="top"> <tt>'\u0042'</tt>
1595 * <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
1596 * full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
1597 *
1598 * <tr><td valign="top"><tt>'b'</tt>
1599 * <td valign="top"> <tt>'\u0062'</tt>
1600 * <td> Locale-specific {@linkplain
1601 * java.text.DateFormatSymbols#getShortMonths abbreviated month name},
1602 * e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
1603 *
1604 * <tr><td valign="top"><tt>'h'</tt>
1605 * <td valign="top"> <tt>'\u0068'</tt>
1606 * <td> Same as <tt>'b'</tt>.
1607 *
1608 * <tr><td valign="top"><tt>'A'</tt>
1609 * <td valign="top"> <tt>'\u0041'</tt>
1610 * <td> Locale-specific full name of the {@linkplain
1611 * java.text.DateFormatSymbols#getWeekdays day of the week},
1612 * e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
1613 *
1614 * <tr><td valign="top"><tt>'a'</tt>
1615 * <td valign="top"> <tt>'\u0061'</tt>
1616 * <td> Locale-specific short name of the {@linkplain
1617 * java.text.DateFormatSymbols#getShortWeekdays day of the week},
1618 * e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
1619 *
1620 * <tr><td valign="top"><tt>'C'</tt>
1621 * <td valign="top"> <tt>'\u0043'</tt>
1622 * <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
1623 * with leading zero as necessary, i.e. <tt>00 - 99</tt>
1624 *
1625 * <tr><td valign="top"><tt>'Y'</tt>
1626 * <td valign="top"> <tt>'\u0059'</tt> <td> Year, formatted to at least
1627 * four digits with leading zeros as necessary, e.g. <tt>0092</tt> equals
1628 * <tt>92</tt> CE for the Gregorian calendar.
1629 *
1630 * <tr><td valign="top"><tt>'y'</tt>
1631 * <td valign="top"> <tt>'\u0079'</tt>
1632 * <td> Last two digits of the year, formatted with leading zeros as
1633 * necessary, i.e. <tt>00 - 99</tt>.
1634 *
1635 * <tr><td valign="top"><tt>'j'</tt>
1636 * <td valign="top"> <tt>'\u006a'</tt>
1637 * <td> Day of year, formatted as three digits with leading zeros as
1638 * necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
1639 * <tt>001</tt> corresponds to the first day of the year.
1640 *
1641 * <tr><td valign="top"><tt>'m'</tt>
1642 * <td valign="top"> <tt>'\u006d'</tt>
1643 * <td> Month, formatted as two digits with leading zeros as necessary,
1644 * i.e. <tt>01 - 13</tt>, where "<tt>01</tt>" is the first month of the
1645 * year and ("<tt>13</tt>" is a special value required to support lunar
1646 * calendars).
1647 *
1648 * <tr><td valign="top"><tt>'d'</tt>
1649 * <td valign="top"> <tt>'\u0064'</tt>
1650 * <td> Day of month, formatted as two digits with leading zeros as
1651 * necessary, i.e. <tt>01 - 31</tt>, where "<tt>01</tt>" is the first day
1652 * of the month.
1653 *
1654 * <tr><td valign="top"><tt>'e'</tt>
1655 * <td valign="top"> <tt>'\u0065'</tt>
1656 * <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt> where
1657 * "<tt>1</tt>" is the first day of the month.
1658 *
1659 * </table>
1660 *
1661 * <p> The following conversion characters are used for formatting common
1662 * date/time compositions.
1663 *
1664 * <table cellpadding=5 summary="composites">
1665 *
1666 * <tr><td valign="top"><tt>'R'</tt>
1667 * <td valign="top"> <tt>'\u0052'</tt>
1668 * <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
1669 *
1670 * <tr><td valign="top"><tt>'T'</tt>
1671 * <td valign="top"> <tt>'\u0054'</tt>
1672 * <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
1673 *
1674 * <tr><td valign="top"><tt>'r'</tt>
1675 * <td valign="top"> <tt>'\u0072'</tt>
1676 * <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS
1677 * %Tp"</tt>. The location of the morning or afternoon marker
1678 * (<tt>'%Tp'</tt>) may be locale-dependent.
1679 *
1680 * <tr><td valign="top"><tt>'D'</tt>
1681 * <td valign="top"> <tt>'\u0044'</tt>
1682 * <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
1683 *
1684 * <tr><td valign="top"><tt>'F'</tt>
1685 * <td valign="top"> <tt>'\u0046'</tt>
1686 * <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a>
1687 * complete date formatted as <tt>"%tY-%tm-%td"</tt>.
1688 *
1689 * <tr><td valign="top"><tt>'c'</tt>
1690 * <td valign="top"> <tt>'\u0063'</tt>
1691 * <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
1692 * e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
1693 *
1694 * </table>
1695 *
1696 * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1697 * conversions</a> applies. If the <tt>'#'</tt> flag is given, then a {@link
1698 * FormatFlagsConversionMismatchException} will be thrown.
1699 *
1700 * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1701 * be written to the output. If the length of the converted value is less than
1702 * the <tt>width</tt> then the output will be padded by spaces
1703 * (<tt>'\u0020'</tt>) until the total number of characters equals width.
1704 * The padding is on the left by default. If the <tt>'-'</tt> flag is given
1705 * then the padding will be on the right. If width is not specified then there
1706 * is no minimum.
1707 *
1708 * <p> The precision is not applicable. If the precision is specified then an
1709 * {@link IllegalFormatPrecisionException} will be thrown.
1710 *
1711 * <h4><a name="dper">Percent</a></h4>
1712 *
1713 * <p> The conversion does not correspond to any argument.
1714 *
1715 * <table cellpadding=5 summary="DTConv">
1716 *
1717 * <tr><td valign="top"><tt>'%'</tt>
1718 * <td> The result is a literal <tt>'%'</tt> (<tt>'\u0025'</tt>)
1719 *
1720 * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1721 * be written to the output including the <tt>'%'</tt>. If the length of the
1722 * converted value is less than the <tt>width</tt> then the output will be
1723 * padded by spaces (<tt>'\u0020'</tt>) until the total number of
1724 * characters equals width. The padding is on the left. If width is not
1725 * specified then just the <tt>'%'</tt> is output.
1726 *
1727 * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1728 * conversions</a> applies. If any other flags are provided, then a
1729 * {@link FormatFlagsConversionMismatchException} will be thrown.
1730 *
1731 * <p> The precision is not applicable. If the precision is specified an
1732 * {@link IllegalFormatPrecisionException} will be thrown.
1733 *
1734 * </table>
1735 *
1736 * <h4><a name="dls">Line Separator</a></h4>
1737 *
1738 * <p> The conversion does not correspond to any argument.
1739 *
1740 * <table cellpadding=5 summary="DTConv">
1741 *
1742 * <tr><td valign="top"><tt>'n'</tt>
1743 * <td> the platform-specific line separator as returned by {@link
1744 * System#getProperty System.getProperty("line.separator")}.
1745 *
1746 * </table>
1747 *
1748 * <p> Flags, width, and precision are not applicable. If any are provided an
1749 * {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
1750 * and {@link IllegalFormatPrecisionException}, respectively will be thrown.
1751 *
1752 * <h4><a name="dpos">Argument Index</a></h4>
1753 *
1754 * <p> Format specifiers can reference arguments in three ways:
1755 *
1756 * <ul>
1757 *
1758 * <li> <i>Explicit indexing</i> is used when the format specifier contains an
1759 * argument index. The argument index is a decimal integer indicating the
1760 * position of the argument in the argument list. The first argument is
1761 * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc. An argument
1762 * may be referenced more than once.
1763 *
1764 * <p> For example:
1765 *
1766 * <blockquote><pre>
1767 * formatter.format("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s",
1768 * "a", "b", "c", "d")
1769 * // -> "d c b a d c b a"
1770 * </pre></blockquote>
1771 *
1772 * <li> <i>Relative indexing</i> is used when the format specifier contains a
1773 * <tt>'<'</tt> (<tt>'\u003c'</tt>) flag which causes the argument for
1774 * the previous format specifier to be re-used. If there is no previous
1775 * argument, then a {@link MissingFormatArgumentException} is thrown.
1776 *
1777 * <blockquote><pre>
1778 * formatter.format("%s %s %<s %<s", "a", "b", "c", "d")
1779 * // -> "a b b b"
1780 * // "c" and "d" are ignored because they are not referenced
1781 * </pre></blockquote>
1782 *
1783 * <li> <i>Ordinary indexing</i> is used when the format specifier contains
1784 * neither an argument index nor a <tt>'<'</tt> flag. Each format specifier
1785 * which uses ordinary indexing is assigned a sequential implicit index into
1786 * argument list which is independent of the indices used by explicit or
1787 * relative indexing.
1788 *
1789 * <blockquote><pre>
1790 * formatter.format("%s %s %s %s", "a", "b", "c", "d")
1791 * // -> "a b c d"
1792 * </pre></blockquote>
1793 *
1794 * </ul>
1795 *
1796 * <p> It is possible to have a format string which uses all forms of indexing,
1797 * for example:
1798 *
1799 * <blockquote><pre>
1800 * formatter.format("%2$s %s %<s %s", "a", "b", "c", "d")
1801 * // -> "b a a b"
1802 * // "c" and "d" are ignored because they are not referenced
1803 * </pre></blockquote>
1804 *
1805 * <p> The maximum number of arguments is limited by the maximum dimension of a
1806 * Java array as defined by the <a
1807 * href="http://java.sun.com/docs/books/vmspec/">Java Virtual Machine
1808 * Specification</a>. If the argument index is does not correspond to an
1809 * available argument, then a {@link MissingFormatArgumentException} is thrown.
1810 *
1811 * <p> If there are more arguments than format specifiers, the extra arguments
1812 * are ignored.
1813 *
1814 * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
1815 * method or constructor in this class will cause a {@link
1816 * NullPointerException} to be thrown.
1817 *
1818 * @author Iris Clark
1819 * @since 1.5
1820 */
1821 public final class Formatter implements Closeable, Flushable {
1822 private Appendable a;
1823 private Locale l;
1824
1825 private IOException lastException;
1826
1827 private char zero = '0';
1828 private static double scaleUp;
1829
1830 // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
1831 // + 3 (max # exp digits) + 4 (error) = 30
1832 private static final int MAX_FD_CHARS = 30;
1833
1834 // Initialize internal data.
1835 private void init(Appendable a, Locale l) {
1836 this .a = a;
1837 this .l = l;
1838 setZero();
1839 }
1840
1841 /**
1842 * Constructs a new formatter.
1843 *
1844 * <p> The destination of the formatted output is a {@link StringBuilder}
1845 * which may be retrieved by invoking {@link #out out()} and whose
1846 * current content may be converted into a string by invoking {@link
1847 * #toString toString()}. The locale used is the {@linkplain
1848 * Locale#getDefault() default locale} for this instance of the Java
1849 * virtual machine.
1850 */
1851 public Formatter() {
1852 init(new StringBuilder(), Locale.getDefault());
1853 }
1854
1855 /**
1856 * Constructs a new formatter with the specified destination.
1857 *
1858 * <p> The locale used is the {@linkplain Locale#getDefault() default
1859 * locale} for this instance of the Java virtual machine.
1860 *
1861 * @param a
1862 * Destination for the formatted output. If <tt>a</tt> is
1863 * <tt>null</tt> then a {@link StringBuilder} will be created.
1864 */
1865 public Formatter(Appendable a) {
1866 if (a == null)
1867 a = new StringBuilder();
1868 init(a, Locale.getDefault());
1869 }
1870
1871 /**
1872 * Constructs a new formatter with the specified locale.
1873 *
1874 * <p> The destination of the formatted output is a {@link StringBuilder}
1875 * which may be retrieved by invoking {@link #out out()} and whose current
1876 * content may be converted into a string by invoking {@link #toString
1877 * toString()}.
1878 *
1879 * @param l
1880 * The {@linkplain java.util.Locale locale} to apply during
1881 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
1882 * is applied.
1883 */
1884 public Formatter(Locale l) {
1885 init(new StringBuilder(), l);
1886 }
1887
1888 /**
1889 * Constructs a new formatter with the specified destination and locale.
1890 *
1891 * @param a
1892 * Destination for the formatted output. If <tt>a</tt> is
1893 * <tt>null</tt> then a {@link StringBuilder} will be created.
1894 *
1895 * @param l
1896 * The {@linkplain java.util.Locale locale} to apply during
1897 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
1898 * is applied.
1899 */
1900 public Formatter(Appendable a, Locale l) {
1901 if (a == null)
1902 a = new StringBuilder();
1903 init(a, l);
1904 }
1905
1906 /**
1907 * Constructs a new formatter with the specified file name.
1908 *
1909 * <p> The charset used is the {@linkplain
1910 * java.nio.charset.Charset#defaultCharset() default charset} for this
1911 * instance of the Java virtual machine.
1912 *
1913 * <p> The locale used is the {@linkplain Locale#getDefault() default
1914 * locale} for this instance of the Java virtual machine.
1915 *
1916 * @param fileName
1917 * The name of the file to use as the destination of this
1918 * formatter. If the file exists then it will be truncated to
1919 * zero size; otherwise, a new file will be created. The output
1920 * will be written to the file and is buffered.
1921 *
1922 * @throws SecurityException
1923 * If a security manager is present and {@link
1924 * SecurityManager#checkWrite checkWrite(fileName)} denies write
1925 * access to the file
1926 *
1927 * @throws FileNotFoundException
1928 * If the given file name does not denote an existing, writable
1929 * regular file and a new regular file of that name cannot be
1930 * created, or if some other error occurs while opening or
1931 * creating the file
1932 */
1933 public Formatter(String fileName) throws FileNotFoundException {
1934 init(new BufferedWriter(new OutputStreamWriter(
1935 new FileOutputStream(fileName))), Locale.getDefault());
1936 }
1937
1938 /**
1939 * Constructs a new formatter with the specified file name and charset.
1940 *
1941 * <p> The locale used is the {@linkplain Locale#getDefault default
1942 * locale} for this instance of the Java virtual machine.
1943 *
1944 * @param fileName
1945 * The name of the file to use as the destination of this
1946 * formatter. If the file exists then it will be truncated to
1947 * zero size; otherwise, a new file will be created. The output
1948 * will be written to the file and is buffered.
1949 *
1950 * @param csn
1951 * The name of a supported {@linkplain java.nio.charset.Charset
1952 * charset}
1953 *
1954 * @throws FileNotFoundException
1955 * If the given file name does not denote an existing, writable
1956 * regular file and a new regular file of that name cannot be
1957 * created, or if some other error occurs while opening or
1958 * creating the file
1959 *
1960 * @throws SecurityException
1961 * If a security manager is present and {@link
1962 * SecurityManager#checkWrite checkWrite(fileName)} denies write
1963 * access to the file
1964 *
1965 * @throws UnsupportedEncodingException
1966 * If the named charset is not supported
1967 */
1968 public Formatter(String fileName, String csn)
1969 throws FileNotFoundException, UnsupportedEncodingException {
1970 this (fileName, csn, Locale.getDefault());
1971 }
1972
1973 /**
1974 * Constructs a new formatter with the specified file name, charset, and
1975 * locale.
1976 *
1977 * @param fileName
1978 * The name of the file to use as the destination of this
1979 * formatter. If the file exists then it will be truncated to
1980 * zero size; otherwise, a new file will be created. The output
1981 * will be written to the file and is buffered.
1982 *
1983 * @param csn
1984 * The name of a supported {@linkplain java.nio.charset.Charset
1985 * charset}
1986 *
1987 * @param l
1988 * The {@linkplain java.util.Locale locale} to apply during
1989 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
1990 * is applied.
1991 *
1992 * @throws FileNotFoundException
1993 * If the given file name does not denote an existing, writable
1994 * regular file and a new regular file of that name cannot be
1995 * created, or if some other error occurs while opening or
1996 * creating the file
1997 *
1998 * @throws SecurityException
1999 * If a security manager is present and {@link
2000 * SecurityManager#checkWrite checkWrite(fileName)} denies write
2001 * access to the file
2002 *
2003 * @throws UnsupportedEncodingException
2004 * If the named charset is not supported
2005 */
2006 public Formatter(String fileName, String csn, Locale l)
2007 throws FileNotFoundException, UnsupportedEncodingException {
2008 init(new BufferedWriter(new OutputStreamWriter(
2009 new FileOutputStream(fileName), csn)), l);
2010 }
2011
2012 /**
2013 * Constructs a new formatter with the specified file.
2014 *
2015 * <p> The charset used is the {@linkplain
2016 * java.nio.charset.Charset#defaultCharset() default charset} for this
2017 * instance of the Java virtual machine.
2018 *
2019 * <p> The locale used is the {@linkplain Locale#getDefault() default
2020 * locale} for this instance of the Java virtual machine.
2021 *
2022 * @param file
2023 * The file to use as the destination of this formatter. If the
2024 * file exists then it will be truncated to zero size; otherwise,
2025 * a new file will be created. The output will be written to the
2026 * file and is buffered.
2027 *
2028 * @throws SecurityException
2029 * If a security manager is present and {@link
2030 * SecurityManager#checkWrite checkWrite(file.getPath())} denies
2031 * write access to the file
2032 *
2033 * @throws FileNotFoundException
2034 * If the given file object does not denote an existing, writable
2035 * regular file and a new regular file of that name cannot be
2036 * created, or if some other error occurs while opening or
2037 * creating the file
2038 */
2039 public Formatter(File file) throws FileNotFoundException {
2040 init(new BufferedWriter(new OutputStreamWriter(
2041 new FileOutputStream(file))), Locale.getDefault());
2042 }
2043
2044 /**
2045 * Constructs a new formatter with the specified file and charset.
2046 *
2047 * <p> The locale used is the {@linkplain Locale#getDefault default
2048 * locale} for this instance of the Java virtual machine.
2049 *
2050 * @param file
2051 * The file to use as the destination of this formatter. If the
2052 * file exists then it will be truncated to zero size; otherwise,
2053 * a new file will be created. The output will be written to the
2054 * file and is buffered.
2055 *
2056 * @param csn
2057 * The name of a supported {@linkplain java.nio.charset.Charset
2058 * charset}
2059 *
2060 * @throws FileNotFoundException
2061 * If the given file object does not denote an existing, writable
2062 * regular file and a new regular file of that name cannot be
2063 * created, or if some other error occurs while opening or
2064 * creating the file
2065 *
2066 * @throws SecurityException
2067 * If a security manager is present and {@link
2068 * SecurityManager#checkWrite checkWrite(file.getPath())} denies
2069 * write access to the file
2070 *
2071 * @throws UnsupportedEncodingException
2072 * If the named charset is not supported
2073 */
2074 public Formatter(File file, String csn)
2075 throws FileNotFoundException, UnsupportedEncodingException {
2076 this (file, csn, Locale.getDefault());
2077 }
2078
2079 /**
2080 * Constructs a new formatter with the specified file, charset, and
2081 * locale.
2082 *
2083 * @param file
2084 * The file to use as the destination of this formatter. If the
2085 * file exists then it will be truncated to zero size; otherwise,
2086 * a new file will be created. The output will be written to the
2087 * file and is buffered.
2088 *
2089 * @param csn
2090 * The name of a supported {@linkplain java.nio.charset.Charset
2091 * charset}
2092 *
2093 * @param l
2094 * The {@linkplain java.util.Locale locale} to apply during
2095 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
2096 * is applied.
2097 *
2098 * @throws FileNotFoundException
2099 * If the given file object does not denote an existing, writable
2100 * regular file and a new regular file of that name cannot be
2101 * created, or if some other error occurs while opening or
2102 * creating the file
2103 *
2104 * @throws SecurityException
2105 * If a security manager is present and {@link
2106 * SecurityManager#checkWrite checkWrite(file.getPath())} denies
2107 * write access to the file
2108 *
2109 * @throws UnsupportedEncodingException
2110 * If the named charset is not supported
2111 */
2112 public Formatter(File file, String csn, Locale l)
2113 throws FileNotFoundException, UnsupportedEncodingException {
2114 init(new BufferedWriter(new OutputStreamWriter(
2115 new FileOutputStream(file), csn)), l);
2116 }
2117
2118 /**
2119 * Constructs a new formatter with the specified print stream.
2120 *
2121 * <p> The locale used is the {@linkplain Locale#getDefault() default
2122 * locale} for this instance of the Java virtual machine.
2123 *
2124 * <p> Characters are written to the given {@link java.io.PrintStream
2125 * PrintStream} object and are therefore encoded using that object's
2126 * charset.
2127 *
2128 * @param ps
2129 * The stream to use as the destination of this formatter.
2130 */
2131 public Formatter(PrintStream ps) {
2132 if (ps == null)
2133 throw new NullPointerException();
2134 init((Appendable) ps, Locale.getDefault());
2135 }
2136
2137 /**
2138 * Constructs a new formatter with the specified output stream.
2139 *
2140 * <p> The charset used is the {@linkplain
2141 * java.nio.charset.Charset#defaultCharset() default charset} for this
2142 * instance of the Java virtual machine.
2143 *
2144 * <p> The locale used is the {@linkplain Locale#getDefault() default
2145 * locale} for this instance of the Java virtual machine.
2146 *
2147 * @param os
2148 * The output stream to use as the destination of this formatter.
2149 * The output will be buffered.
2150 */
2151 public Formatter(OutputStream os) {
2152 init(new BufferedWriter(new OutputStreamWriter(os)), Locale
2153 .getDefault());
2154 }
2155
2156 /**
2157 * Constructs a new formatter with the specified output stream and
2158 * charset.
2159 *
2160 * <p> The locale used is the {@linkplain Locale#getDefault default
2161 * locale} for this instance of the Java virtual machine.
2162 *
2163 * @param os
2164 * The output stream to use as the destination of this formatter.
2165 * The output will be buffered.
2166 *
2167 * @param csn
2168 * The name of a supported {@linkplain java.nio.charset.Charset
2169 * charset}
2170 *
2171 * @throws UnsupportedEncodingException
2172 * If the named charset is not supported
2173 */
2174 public Formatter(OutputStream os, String csn)
2175 throws UnsupportedEncodingException {
2176 this (os, csn, Locale.getDefault());
2177 }
2178
2179 /**
2180 * Constructs a new formatter with the specified output stream, charset,
2181 * and locale.
2182 *
2183 * @param os
2184 * The output stream to use as the destination of this formatter.
2185 * The output will be buffered.
2186 *
2187 * @param csn
2188 * The name of a supported {@linkplain java.nio.charset.Charset
2189 * charset}
2190 *
2191 * @param l
2192 * The {@linkplain java.util.Locale locale} to apply during
2193 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
2194 * is applied.
2195 *
2196 * @throws UnsupportedEncodingException
2197 * If the named charset is not supported
2198 */
2199 public Formatter(OutputStream os, String csn, Locale l)
2200 throws UnsupportedEncodingException {
2201 init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
2202 }
2203
2204 private void setZero() {
2205 if ((l != null) && !l.equals(Locale.US)) {
2206 DecimalFormatSymbols dfs = DecimalFormatSymbols
2207 .getInstance(l);
2208 zero = dfs.getZeroDigit();
2209 }
2210 }
2211
2212 /**
2213 * Returns the locale set by the construction of this formatter.
2214 *
2215 * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2216 * for this object which has a locale argument does not change this value.
2217 *
2218 * @return <tt>null</tt> if no localization is applied, otherwise a
2219 * locale
2220 *
2221 * @throws FormatterClosedException
2222 * If this formatter has been closed by invoking its {@link
2223 * #close()} method
2224 */
2225 public Locale locale() {
2226 ensureOpen();
2227 return l;
2228 }
2229
2230 /**
2231 * Returns the destination for the output.
2232 *
2233 * @return The destination for the output
2234 *
2235 * @throws FormatterClosedException
2236 * If this formatter has been closed by invoking its {@link
2237 * #close()} method
2238 */
2239 public Appendable out() {
2240 ensureOpen();
2241 return a;
2242 }
2243
2244 /**
2245 * Returns the result of invoking <tt>toString()</tt> on the destination
2246 * for the output. For example, the following code formats text into a
2247 * {@link StringBuilder} then retrieves the resultant string:
2248 *
2249 * <blockquote><pre>
2250 * Formatter f = new Formatter();
2251 * f.format("Last reboot at %tc", lastRebootDate);
2252 * String s = f.toString();
2253 * // -> s == "Last reboot at Sat Jan 01 00:00:00 PST 2000"
2254 * </pre></blockquote>
2255 *
2256 * <p> An invocation of this method behaves in exactly the same way as the
2257 * invocation
2258 *
2259 * <pre>
2260 * out().toString() </pre>
2261 *
2262 * <p> Depending on the specification of <tt>toString</tt> for the {@link
2263 * Appendable}, the returned string may or may not contain the characters
2264 * written to the destination. For instance, buffers typically return
2265 * their contents in <tt>toString()</tt>, but streams cannot since the
2266 * data is discarded.
2267 *
2268 * @return The result of invoking <tt>toString()</tt> on the destination
2269 * for the output
2270 *
2271 * @throws FormatterClosedException
2272 * If this formatter has been closed by invoking its {@link
2273 * #close()} method
2274 */
2275 public String toString() {
2276 ensureOpen();
2277 return a.toString();
2278 }
2279
2280 /**
2281 * Flushes this formatter. If the destination implements the {@link
2282 * java.io.Flushable} interface, its <tt>flush</tt> method will be invoked.
2283 *
2284 * <p> Flushing a formatter writes any buffered output in the destination
2285 * to the underlying stream.
2286 *
2287 * @throws FormatterClosedException
2288 * If this formatter has been closed by invoking its {@link
2289 * #close()} method
2290 */
2291 public void flush() {
2292 ensureOpen();
2293 if (a instanceof Flushable) {
2294 try {
2295 ((Flushable) a).flush();
2296 } catch (IOException ioe) {
2297 lastException = ioe;
2298 }
2299 }
2300 }
2301
2302 /**
2303 * Closes this formatter. If the destination implements the {@link
2304 * java.io.Closeable} interface, its <tt>close</tt> method will be invoked.
2305 *
2306 * <p> Closing a formatter allows it to release resources it may be holding
2307 * (such as open files). If the formatter is already closed, then invoking
2308 * this method has no effect.
2309 *
2310 * <p> Attempting to invoke any methods except {@link #ioException()} in
2311 * this formatter after it has been closed will result in a {@link
2312 * FormatterClosedException}.
2313 */
2314 public void close() {
2315 if (a == null)
2316 return;
2317 try {
2318 if (a instanceof Closeable)
2319 ((Closeable) a).close();
2320 } catch (IOException ioe) {
2321 lastException = ioe;
2322 } finally {
2323 a = null;
2324 }
2325 }
2326
2327 private void ensureOpen() {
2328 if (a == null)
2329 throw new FormatterClosedException();
2330 }
2331
2332 /**
2333 * Returns the <tt>IOException</tt> last thrown by this formatter's {@link
2334 * Appendable}.
2335 *
2336 * <p> If the destination's <tt>append()</tt> method never throws
2337 * <tt>IOException</tt>, then this method will always return <tt>null</tt>.
2338 *
2339 * @return The last exception thrown by the Appendable or <tt>null</tt> if
2340 * no such exception exists.
2341 */
2342 public IOException ioException() {
2343 return lastException;
2344 }
2345
2346 /**
2347 * Writes a formatted string to this object's destination using the
2348 * specified format string and arguments. The locale used is the one
2349 * defined during the construction of this formatter.
2350 *
2351 * @param format
2352 * A format string as described in <a href="#syntax">Format string
2353 * syntax</a>.
2354 *
2355 * @param args
2356 * Arguments referenced by the format specifiers in the format
2357 * string. If there are more arguments than format specifiers, the
2358 * extra arguments are ignored. The maximum number of arguments is
2359 * limited by the maximum dimension of a Java array as defined by
2360 * the <a href="http://java.sun.com/docs/books/vmspec/">Java
2361 * Virtual Machine Specification</a>.
2362 *
2363 * @throws IllegalFormatException
2364 * If a format string contains an illegal syntax, a format
2365 * specifier that is incompatible with the given arguments,
2366 * insufficient arguments given the format string, or other
2367 * illegal conditions. For specification of all possible
2368 * formatting errors, see the <a href="#detail">Details</a>
2369 * section of the formatter class specification.
2370 *
2371 * @throws FormatterClosedException
2372 * If this formatter has been closed by invoking its {@link
2373 * #close()} method
2374 *
2375 * @return This formatter
2376 */
2377 public Formatter format(String format, Object... args) {
2378 return format(l, format, args);
2379 }
2380
2381 /**
2382 * Writes a formatted string to this object's destination using the
2383 * specified locale, format string, and arguments.
2384 *
2385 * @param l
2386 * The {@linkplain java.util.Locale locale} to apply during
2387 * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
2388 * is applied. This does not change this object's locale that was
2389 * set during construction.
2390 *
2391 * @param format
2392 * A format string as described in <a href="#syntax">Format string
2393 * syntax</a>
2394 *
2395 * @param args
2396 * Arguments referenced by the format specifiers in the format
2397 * string. If there are more arguments than format specifiers, the
2398 * extra arguments are ignored. The maximum number of arguments is
2399 * limited by the maximum dimension of a Java array as defined by
2400 * the <a href="http://java.sun.com/docs/books/vmspec/">Java
2401 * Virtual Machine Specification</a>
2402 *
2403 * @throws IllegalFormatException
2404 * If a format string contains an illegal syntax, a format
2405 * specifier that is incompatible with the given arguments,
2406 * insufficient arguments given the format string, or other
2407 * illegal conditions. For specification of all possible
2408 * formatting errors, see the <a href="#detail">Details</a>
2409 * section of the formatter class specification.
2410 *
2411 * @throws FormatterClosedException
2412 * If this formatter has been closed by invoking its {@link
2413 * #close()} method
2414 *
2415 * @return This formatter
2416 */
2417 public Formatter format(Locale l, String format, Object... args) {
2418 ensureOpen();
2419
2420 // index of last argument referenced
2421 int last = -1;
2422 // last ordinary index
2423 int lasto = -1;
2424
2425 FormatString[] fsa = parse(format);
2426 for (int i = 0; i < fsa.length; i++) {
2427 FormatString fs = fsa[i];
2428 int index = fs.index();
2429 try {
2430 switch (index) {
2431 case -2: // fixed string, "%n", or "%%"
2432 fs.print(null, l);
2433 break;
2434 case -1: // relative index
2435 if (last < 0
2436 || (args != null && last > args.length - 1))
2437 throw new MissingFormatArgumentException(fs
2438 .toString());
2439 fs.print((args == null ? null : args[last]), l);
2440 break;
2441 case 0: // ordinary index
2442 lasto++;
2443 last = lasto;
2444 if (args != null && lasto > args.length - 1)
2445 throw new MissingFormatArgumentException(fs
2446 .toString());
2447 fs.print((args == null ? null : args[lasto]), l);
2448 break;
2449 default: // explicit index
2450 last = index - 1;
2451 if (args != null && last > args.length - 1)
2452 throw new MissingFormatArgumentException(fs
2453 .toString());
2454 fs.print((args == null ? null : args[last]), l);
2455 break;
2456 }
2457 } catch (IOException x) {
2458 lastException = x;
2459 }
2460 }
2461 return this ;
2462 }
2463
2464 // %[argument_index$][flags][width][.precision][t]conversion
2465 private static final String formatSpecifier = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
2466
2467 private static Pattern fsPattern = Pattern.compile(formatSpecifier);
2468
2469 // Look for format specifiers in the format string.
2470 private FormatString[] parse(String s) {
2471 ArrayList al = new ArrayList();
2472 Matcher m = fsPattern.matcher(s);
2473 int i = 0;
2474 while (i < s.length()) {
2475 if (m.find(i)) {
2476 // Anything between the start of the string and the beginning
2477 // of the format specifier is either fixed text or contains
2478 // an invalid format string.
2479 if (m.start() != i) {
2480 // Make sure we didn't miss any invalid format specifiers
2481 checkText(s.substring(i, m.start()));
2482 // Assume previous characters were fixed text
2483 al.add(new FixedString(s.substring(i, m.start())));
2484 }
2485
2486 // Expect 6 groups in regular expression
2487 String[] sa = new String[6];
2488 for (int j = 0; j < m.groupCount(); j++) {
2489 sa[j] = m.group(j + 1);
2490 // System.out.print(sa[j] + " ");
2491 }
2492 // System.out.println();
2493 al.add(new FormatSpecifier(this , sa));
2494 i = m.end();
2495 } else {
2496 // No more valid format specifiers. Check for possible invalid
2497 // format specifiers.
2498 checkText(s.substring(i));
2499 // The rest of the string is fixed text
2500 al.add(new FixedString(s.substring(i)));
2501 break;
2502 }
2503 }
2504 // FormatString[] fs = new FormatString[al.size()];
2505 // for (int j = 0; j < al.size(); j++)
2506 // System.out.println(((FormatString) al.get(j)).toString());
2507 return (FormatString[]) al.toArray(new FormatString[0]);
2508 }
2509
2510 private void checkText(String s) {
2511 int idx;
2512 // If there are any '%' in the given string, we got a bad format
2513 // specifier.
2514 if ((idx = s.indexOf('%')) != -1) {
2515 char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
2516 throw new UnknownFormatConversionException(String
2517 .valueOf(c));
2518 }
2519 }
2520
2521 private interface FormatString {
2522 int index();
2523
2524 void print(Object arg, Locale l) throws IOException;
2525
2526 String toString();
2527 }
2528
2529 private class FixedString implements FormatString {
2530 private String s;
2531
2532 FixedString(String s) {
2533 this .s = s;
2534 }
2535
2536 public int index() {
2537 return -2;
2538 }
2539
2540 public void print(Object arg, Locale l) throws IOException {
2541 a.append(s);
2542 }
2543
2544 public String toString() {
2545 return s;
2546 }
2547 }
2548
2549 public enum BigDecimalLayoutForm {
2550 SCIENTIFIC, DECIMAL_FLOAT
2551 };
2552
2553 private class FormatSpecifier implements FormatString {
2554 private int index = -1;
2555 private Flags f = Flags.NONE;
2556 private int width;
2557 private int precision;
2558 private boolean dt = false;
2559 private char c;
2560
2561 private Formatter formatter;
2562
2563 // cache the line separator
2564 private String ls;
2565
2566 private int index(String s) {
2567 if (s != null) {
2568 try {
2569 index = Integer.parseInt(s.substring(0,
2570 s.length() - 1));
2571 } catch (NumberFormatException x) {
2572 assert (false);
2573 }
2574 } else {
2575 index = 0;
2576 }
2577 return index;
2578 }
2579
2580 public int index() {
2581 return index;
2582 }
2583
2584 private Flags flags(String s) {
2585 f = Flags.parse(s);
2586 if (f.contains(Flags.PREVIOUS))
2587 index = -1;
2588 return f;
2589 }
2590
2591 Flags flags() {
2592 return f;
2593 }
2594
2595 private int width(String s) {
2596 width = -1;
2597 if (s != null) {
2598 try {
2599 width = Integer.parseInt(s);
2600 if (width < 0)
2601 throw new IllegalFormatWidthException(width);
2602 } catch (NumberFormatException x) {
2603 assert (false);
2604 }
2605 }
2606 return width;
2607 }
2608
2609 int width() {
2610 return width;
2611 }
2612
2613 private int precision(String s) {
2614 precision = -1;
2615 if (s != null) {
2616 try {
2617 // remove the '.'
2618 precision = Integer.parseInt(s.substring(1));
2619 if (precision < 0)
2620 throw new IllegalFormatPrecisionException(
2621 precision);
2622 } catch (NumberFormatException x) {
2623 assert (false);
2624 }
2625 }
2626 return precision;
2627 }
2628
2629 int precision() {
2630 return precision;
2631 }
2632
2633 private char conversion(String s) {
2634 c = s.charAt(0);
2635 if (!dt) {
2636 if (!Conversion.isValid(c))
2637 throw new UnknownFormatConversionException(String
2638 .valueOf(c));
2639 if (Character.isUpperCase(c))
2640 f.add(Flags.UPPERCASE);
2641 c = Character.toLowerCase(c);
2642 if (Conversion.isText(c))
2643 index = -2;
2644 }
2645 return c;
2646 }
2647
2648 private char conversion() {
2649 return c;
2650 }
2651
2652 FormatSpecifier(Formatter formatter, String[] sa) {
2653 this .formatter = formatter;
2654 int idx = 0;
2655
2656 index(sa[idx++]);
2657 flags(sa[idx++]);
2658 width(sa[idx++]);
2659 precision(sa[idx++]);
2660
2661 if (sa[idx] != null) {
2662 dt = true;
2663 if (sa[idx].equals("T"))
2664 f.add(Flags.UPPERCASE);
2665 }
2666 conversion(sa[++idx]);
2667
2668 if (dt)
2669 checkDateTime();
2670 else if (Conversion.isGeneral(c))
2671 checkGeneral();
2672 else if (Conversion.isCharacter(c))
2673 checkCharacter();
2674 else if (Conversion.isInteger(c))
2675 checkInteger();
2676 else if (Conversion.isFloat(c))
2677 checkFloat();
2678 else if (Conversion.isText(c))
2679 checkText();
2680 else
2681 throw new UnknownFormatConversionException(String
2682 .valueOf(c));
2683 }
2684
2685 public void print(Object arg, Locale l) throws IOException {
2686 if (dt) {
2687 printDateTime(arg, l);
2688 return;
2689 }
2690 switch (c) {
2691 case Conversion.DECIMAL_INTEGER:
2692 case Conversion.OCTAL_INTEGER:
2693 case Conversion.HEXADECIMAL_INTEGER:
2694 printInteger(arg, l);
2695 break;
2696 case Conversion.SCIENTIFIC:
2697 case Conversion.GENERAL:
2698 case Conversion.DECIMAL_FLOAT:
2699 case Conversion.HEXADECIMAL_FLOAT:
2700 printFloat(arg, l);
2701 break;
2702 case Conversion.CHARACTER:
2703 case Conversion.CHARACTER_UPPER:
2704 printCharacter(arg);
2705 break;
2706 case Conversion.BOOLEAN:
2707 printBoolean(arg);
2708 break;
2709 case Conversion.STRING:
2710 printString(arg, l);
2711 break;
2712 case Conversion.HASHCODE:
2713 printHashCode(arg);
2714 break;
2715 case Conversion.LINE_SEPARATOR:
2716 if (ls == null)
2717 ls = System.getProperty("line.separator");
2718 a.append(ls);
2719 break;
2720 case Conversion.PERCENT_SIGN:
2721 a.append('%');
2722 break;
2723 default:
2724 assert false;
2725 }
2726 }
2727
2728 private void printInteger(Object arg, Locale l)
2729 throws IOException {
2730 if (arg == null)
2731 print("null");
2732 else if (arg instanceof Byte)
2733 print(((Byte) arg).byteValue(), l);
2734 else if (arg instanceof Short)
2735 print(((Short) arg).shortValue(), l);
2736 else if (arg instanceof Integer)
2737 print(((Integer) arg).intValue(), l);
2738 else if (arg instanceof Long)
2739 print(((Long) arg).longValue(), l);
2740 else if (arg instanceof BigInteger)
2741 print(((BigInteger) arg), l);
2742 else
2743 failConversion(c, arg);
2744 }
2745
2746 private void printFloat(Object arg, Locale l)
2747 throws IOException {
2748 if (arg == null)
2749 print("null");
2750 else if (arg instanceof Float)
2751 print(((Float) arg).floatValue(), l);
2752 else if (arg instanceof Double)
2753 print(((Double) arg).doubleValue(), l);
2754 else if (arg instanceof BigDecimal)
2755 print(((BigDecimal) arg), l);
2756 else
2757 failConversion(c, arg);
2758 }
2759
2760 private void printDateTime(Object arg, Locale l)
2761 throws IOException {
2762 if (arg == null) {
2763 print("null");
2764 return;
2765 }
2766 Calendar cal = null;
2767
2768 // Instead of Calendar.setLenient(true), perhaps we should
2769 // wrap the IllegalArgumentException that might be thrown?
2770 if (arg instanceof Long) {
2771 // Note that the following method uses an instance of the
2772 // default time zone (TimeZone.getDefaultRef().
2773 cal = Calendar.getInstance(l == null ? Locale.US : l);
2774 cal.setTimeInMillis((Long) arg);
2775 } else if (arg instanceof Date) {
2776 // Note that the following method uses an instance of the
2777 // default time zone (TimeZone.getDefaultRef().
2778 cal = Calendar.getInstance(l == null ? Locale.US : l);
2779 cal.setTime((Date) arg);
2780 } else if (arg instanceof Calendar) {
2781 cal = (Calendar) ((Calendar) arg).clone();
2782 cal.setLenient(true);
2783 } else {
2784 failConversion(c, arg);
2785 }
2786 // Use the provided locale so that invocations of
2787 // localizedMagnitude() use optimizations for null.
2788 print(cal, c, l);
2789 }
2790
2791 private void printCharacter(Object arg) throws IOException {
2792 if (arg == null) {
2793 print("null");
2794 return;
2795 }
2796 String s = null;
2797 if (arg instanceof Character) {
2798 s = ((Character) arg).toString();
2799 } else if (arg instanceof Byte) {
2800 byte i = ((Byte) arg).byteValue();
2801 if (Character.isValidCodePoint(i))
2802 s = new String(Character.toChars(i));
2803 else
2804 throw new IllegalFormatCodePointException(i);
2805 } else if (arg instanceof Short) {
2806 short i = ((Short) arg).shortValue();
2807 if (Character.isValidCodePoint(i))
2808 s = new String(Character.toChars(i));
2809 else
2810 throw new IllegalFormatCodePointException(i);
2811 } else if (arg instanceof Integer) {
2812 int i = ((Integer) arg).intValue();
2813 if (Character.isValidCodePoint(i))
2814 s = new String(Character.toChars(i));
2815 else
2816 throw new IllegalFormatCodePointException(i);
2817 } else {
2818 failConversion(c, arg);
2819 }
2820 print(s);
2821 }
2822
2823 private void printString(Object arg, Locale l)
2824 throws IOException {
2825 if (arg == null) {
2826 print("null");
2827 } else if (arg instanceof Formattable) {
2828 Formatter fmt = formatter;
2829 if (formatter.locale() != l)
2830 fmt = new Formatter(formatter.out(), l);
2831 ((Formattable) arg).formatTo(fmt, f.valueOf(), width,
2832 precision);
2833 } else {
2834 print(arg.toString());
2835 }
2836 }
2837
2838 private void printBoolean(Object arg) throws IOException {
2839 String s;
2840 if (arg != null)
2841 s = ((arg instanceof Boolean) ? ((Boolean) arg)
2842 .toString() : Boolean.toString(true));
2843 else
2844 s = Boolean.toString(false);
2845 print(s);
2846 }
2847
2848 private void printHashCode(Object arg) throws IOException {
2849 String s = (arg == null ? "null" : Integer.toHexString(arg
2850 .hashCode()));
2851 print(s);
2852 }
2853
2854 private void print(String s) throws IOException {
2855 if (precision != -1 && precision < s.length())
2856 s = s.substring(0, precision);
2857 if (f.contains(Flags.UPPERCASE))
2858 s = s.toUpperCase();
2859 a.append(justify(s));
2860 }
2861
2862 private String justify(String s) {
2863 if (width == -1)
2864 return s;
2865 StringBuilder sb = new StringBuilder();
2866 boolean pad = f.contains(Flags.LEFT_JUSTIFY);
2867 int sp = width - s.length();
2868 if (!pad)
2869 for (int i = 0; i < sp; i++)
2870 sb.append(' ');
2871 sb.append(s);
2872 if (pad)
2873 for (int i = 0; i < sp; i++)
2874 sb.append(' ');
2875 return sb.toString();
2876 }
2877
2878 public String toString() {
2879 StringBuilder sb = new StringBuilder('%');
2880 // Flags.UPPERCASE is set internally for legal conversions.
2881 Flags dupf = f.dup().remove(Flags.UPPERCASE);
2882 sb.append(dupf.toString());
2883 if (index > 0)
2884 sb.append(index).append('$');
2885 if (width != -1)
2886 sb.append(width);
2887 if (precision != -1)
2888 sb.append('.').append(precision);
2889 if (dt)
2890 sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't');
2891 sb.append(f.contains(Flags.UPPERCASE) ? Character
2892 .toUpperCase(c) : c);
2893 return sb.toString();
2894 }
2895
2896 private void checkGeneral() {
2897 if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE)
2898 && f.contains(Flags.ALTERNATE))
2899 failMismatch(Flags.ALTERNATE, c);
2900 // '-' requires a width
2901 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2902 throw new MissingFormatWidthException(toString());
2903 checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE,
2904 Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
2905 }
2906
2907 private void checkDateTime() {
2908 if (precision != -1)
2909 throw new IllegalFormatPrecisionException(precision);
2910 if (!DateTime.isValid(c))
2911 throw new UnknownFormatConversionException("t" + c);
2912 checkBadFlags(Flags.ALTERNATE, Flags.PLUS,
2913 Flags.LEADING_SPACE, Flags.ZERO_PAD, Flags.GROUP,
2914 Flags.PARENTHESES);
2915 // '-' requires a width
2916 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2917 throw new MissingFormatWidthException(toString());
2918 }
2919
2920 private void checkCharacter() {
2921 if (precision != -1)
2922 throw new IllegalFormatPrecisionException(precision);
2923 checkBadFlags(Flags.ALTERNATE, Flags.PLUS,
2924 Flags.LEADING_SPACE, Flags.ZERO_PAD, Flags.GROUP,
2925 Flags.PARENTHESES);
2926 // '-' requires a width
2927 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2928 throw new MissingFormatWidthException(toString());
2929 }
2930
2931 private void checkInteger() {
2932 checkNumeric();
2933 if (precision != -1)
2934 throw new IllegalFormatPrecisionException(precision);
2935
2936 if (c == Conversion.DECIMAL_INTEGER)
2937 checkBadFlags(Flags.ALTERNATE);
2938 else if (c == Conversion.OCTAL_INTEGER)
2939 checkBadFlags(Flags.GROUP);
2940 else
2941 checkBadFlags(Flags.GROUP);
2942 }
2943
2944 private void checkBadFlags(Flags... badFlags) {
2945 for (int i = 0; i < badFlags.length; i++)
2946 if (f.contains(badFlags[i]))
2947 failMismatch(badFlags[i], c);
2948 }
2949
2950 private void checkFloat() {
2951 checkNumeric();
2952 if (c == Conversion.DECIMAL_FLOAT) {
2953 } else if (c == Conversion.HEXADECIMAL_FLOAT) {
2954 checkBadFlags(Flags.PARENTHESES, Flags.GROUP);
2955 } else if (c == Conversion.SCIENTIFIC) {
2956 checkBadFlags(Flags.GROUP);
2957 } else if (c == Conversion.GENERAL) {
2958 checkBadFlags(Flags.ALTERNATE);
2959 }
2960 }
2961
2962 private void checkNumeric() {
2963 if (width != -1 && width < 0)
2964 throw new IllegalFormatWidthException(width);
2965
2966 if (precision != -1 && precision < 0)
2967 throw new IllegalFormatPrecisionException(precision);
2968
2969 // '-' and '0' require a width
2970 if (width == -1
2971 && (f.contains(Flags.LEFT_JUSTIFY) || f
2972 .contains(Flags.ZERO_PAD)))
2973 throw new MissingFormatWidthException(toString());
2974
2975 // bad combination
2976 if ((f.contains(Flags.PLUS) && f
2977 .contains(Flags.LEADING_SPACE))
2978 || (f.contains(Flags.LEFT_JUSTIFY) && f
2979 .contains(Flags.ZERO_PAD)))
2980 throw new IllegalFormatFlagsException(f.toString());
2981 }
2982
2983 private void checkText() {
2984 if (precision != -1)
2985 throw new IllegalFormatPrecisionException(precision);
2986 switch (c) {
2987 case Conversion.PERCENT_SIGN:
2988 if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf()
2989 && f.valueOf() != Flags.NONE.valueOf())
2990 throw new IllegalFormatFlagsException(f.toString());
2991 // '-' requires a width
2992 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2993 throw new MissingFormatWidthException(toString());
2994 break;
2995 case Conversion.LINE_SEPARATOR:
2996 if (width != -1)
2997 throw new IllegalFormatWidthException(width);
2998 if (f.valueOf() != Flags.NONE.valueOf())
2999 throw new IllegalFormatFlagsException(f.toString());
3000 break;
3001 default:
3002 assert false;
3003 }
3004 }
3005
3006 private void print(byte value, Locale l) throws IOException {
3007 long v = value;
3008 if (value < 0
3009 && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3010 v += (1L << 8);
3011 assert v >= 0 : v;
3012 }
3013 print(v, l);
3014 }
3015
3016 private void print(short value, Locale l) throws IOException {
3017 long v = value;
3018 if (value < 0
3019 && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3020 v += (1L << 16);
3021 assert v >= 0 : v;
3022 }
3023 print(v, l);
3024 }
3025
3026 private void print(int value, Locale l) throws IOException {
3027 long v = value;
3028 if (value < 0
3029 && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3030 v += (1L << 32);
3031 assert v >= 0 : v;
3032 }
3033 print(v, l);
3034 }
3035
3036 private void print(long value, Locale l) throws IOException {
3037
3038 StringBuilder sb = new StringBuilder();
3039
3040 if (c == Conversion.DECIMAL_INTEGER) {
3041 boolean neg = value < 0;
3042 char[] va;
3043 if (value < 0)
3044 va = Long.toString(value, 10).substring(1)
3045 .toCharArray();
3046 else
3047 va = Long.toString(value, 10).toCharArray();
3048
3049 // leading sign indicator
3050 leadingSign(sb, neg);
3051
3052 // the value
3053 localizedMagnitude(sb, va, f,
3054 adjustWidth(width, f, neg), l);
3055
3056 // trailing sign indicator
3057 trailingSign(sb, neg);
3058 } else if (c == Conversion.OCTAL_INTEGER) {
3059 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3060 Flags.PLUS);
3061 String s = Long.toOctalString(value);
3062 int len = (f.contains(Flags.ALTERNATE) ? s.length() + 1
3063 : s.length());
3064
3065 // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3066 if (f.contains(Flags.ALTERNATE))
3067 sb.append('0');
3068 if (f.contains(Flags.ZERO_PAD))
3069 for (int i = 0; i < width - len; i++)
3070 sb.append('0');
3071 sb.append(s);
3072 } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3073 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3074 Flags.PLUS);
3075 String s = Long.toHexString(value);
3076 int len = (f.contains(Flags.ALTERNATE) ? s.length() + 2
3077 : s.length());
3078
3079 // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3080 if (f.contains(Flags.ALTERNATE))
3081 sb
3082 .append(f.contains(Flags.UPPERCASE) ? "0X"
3083 : "0x");
3084 if (f.contains(Flags.ZERO_PAD))
3085 for (int i = 0; i < width - len; i++)
3086 sb.append('0');
3087 if (f.contains(Flags.UPPERCASE))
3088 s = s.toUpperCase();
3089 sb.append(s);
3090 }
3091
3092 // justify based on width
3093 a.append(justify(sb.toString()));
3094 }
3095
3096 // neg := val < 0
3097 private StringBuilder leadingSign(StringBuilder sb, boolean neg) {
3098 if (!neg) {
3099 if (f.contains(Flags.PLUS)) {
3100 sb.append('+');
3101 } else if (f.contains(Flags.LEADING_SPACE)) {
3102 sb.append(' ');
3103 }
3104 } else {
3105 if (f.contains(Flags.PARENTHESES))
3106 sb.append('(');
3107 else
3108 sb.append('-');
3109 }
3110 return sb;
3111 }
3112
3113 // neg := val < 0
3114 private StringBuilder trailingSign(StringBuilder sb, boolean neg) {
3115 if (neg && f.contains(Flags.PARENTHESES))
3116 sb.append(')');
3117 return sb;
3118 }
3119
3120 private void print(BigInteger value, Locale l)
3121 throws IOException {
3122 StringBuilder sb = new StringBuilder();
3123 boolean neg = value.signum() == -1;
3124 BigInteger v = value.abs();
3125
3126 // leading sign indicator
3127 leadingSign(sb, neg);
3128
3129 // the value
3130 if (c == Conversion.DECIMAL_INTEGER) {
3131 char[] va = v.toString().toCharArray();
3132 localizedMagnitude(sb, va, f,
3133 adjustWidth(width, f, neg), l);
3134 } else if (c == Conversion.OCTAL_INTEGER) {
3135 String s = v.toString(8);
3136
3137 int len = s.length() + sb.length();
3138 if (neg && f.contains(Flags.PARENTHESES))
3139 len++;
3140
3141 // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3142 if (f.contains(Flags.ALTERNATE)) {
3143 len++;
3144 sb.append('0');
3145 }
3146 if (f.contains(Flags.ZERO_PAD)) {
3147 for (int i = 0; i < width - len; i++)
3148 sb.append('0');
3149 }
3150 sb.append(s);
3151 } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3152 String s = v.toString(16);
3153
3154 int len = s.length() + sb.length();
3155 if (neg && f.contains(Flags.PARENTHESES))
3156 len++;
3157
3158 // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3159 if (f.contains(Flags.ALTERNATE)) {
3160 len += 2;
3161 sb
3162 .append(f.contains(Flags.UPPERCASE) ? "0X"
3163 : "0x");
3164 }
3165 if (f.contains(Flags.ZERO_PAD))
3166 for (int i = 0; i < width - len; i++)
3167 sb.append('0');
3168 if (f.contains(Flags.UPPERCASE))
3169 s = s.toUpperCase();
3170 sb.append(s);
3171 }
3172
3173 // trailing sign indicator
3174 trailingSign(sb, (value.signum() == -1));
3175
3176 // justify based on width
3177 a.append(justify(sb.toString()));
3178 }
3179
3180 private void print(float value, Locale l) throws IOException {
3181 print((double) value, l);
3182 }
3183
3184 private void print(double value, Locale l) throws IOException {
3185 StringBuilder sb = new StringBuilder();
3186 boolean neg = Double.compare(value, 0.0) == -1;
3187
3188 if (!Double.isNaN(value)) {
3189 double v = Math.abs(value);
3190
3191 // leading sign indicator
3192 leadingSign(sb, neg);
3193
3194 // the value
3195 if (!Double.isInfinite(v))
3196 print(sb, v, l, f, c, precision, neg);
3197 else
3198 sb.append(f.contains(Flags.UPPERCASE) ? "INFINITY"
3199 : "Infinity");
3200
3201 // trailing sign indicator
3202 trailingSign(sb, neg);
3203 } else {
3204 sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN");
3205 }
3206
3207 // justify based on width
3208 a.append(justify(sb.toString()));
3209 }
3210
3211 // !Double.isInfinite(value) && !Double.isNaN(value)
3212 private void print(StringBuilder sb, double value, Locale l,
3213 Flags f, char c, int precision, boolean neg)
3214 throws IOException {
3215 if (c == Conversion.SCIENTIFIC) {
3216 // Create a new FormattedFloatingDecimal with the desired
3217 // precision.
3218 int prec = (precision == -1 ? 6 : precision);
3219
3220 FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3221 value, prec,
3222 FormattedFloatingDecimal.Form.SCIENTIFIC);
3223
3224 char[] v = new char[MAX_FD_CHARS];
3225 int len = fd.getChars(v);
3226
3227 char[] mant = addZeros(mantissa(v, len), prec);
3228
3229 // If the precision is zero and the '#' flag is set, add the
3230 // requested decimal point.
3231 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3232 mant = addDot(mant);
3233
3234 char[] exp = (value == 0.0) ? new char[] { '+', '0',
3235 '0' } : exponent(v, len);
3236
3237 int newW = width;
3238 if (width != -1)
3239 newW = adjustWidth(width - exp.length - 1, f, neg);
3240 localizedMagnitude(sb, mant, f, newW, l);
3241
3242 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3243
3244 Flags flags = f.dup().remove(Flags.GROUP);
3245 char sign = exp[0];
3246 assert (sign == '+' || sign == '-');
3247 sb.append(sign);
3248
3249 char[] tmp = new char[exp.length - 1];
3250 System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3251 sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3252 } else if (c == Conversion.DECIMAL_FLOAT) {
3253 // Create a new FormattedFloatingDecimal with the desired
3254 // precision.
3255 int prec = (precision == -1 ? 6 : precision);
3256
3257 FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3258 value, prec,
3259 FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
3260
3261 // MAX_FD_CHARS + 1 (round?)
3262 char[] v = new char[MAX_FD_CHARS + 1
3263 + Math.abs(fd.getExponent())];
3264 int len = fd.getChars(v);
3265
3266 char[] mant = addZeros(mantissa(v, len), prec);
3267
3268 // If the precision is zero and the '#' flag is set, add the
3269 // requested decimal point.
3270 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3271 mant = addDot(mant);
3272
3273 int newW = width;
3274 if (width != -1)
3275 newW = adjustWidth(width, f, neg);
3276 localizedMagnitude(sb, mant, f, newW, l);
3277 } else if (c == Conversion.GENERAL) {
3278 int prec = precision;
3279 if (precision == -1)
3280 prec = 6;
3281 else if (precision == 0)
3282 prec = 1;
3283
3284 FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3285 value, prec,
3286 FormattedFloatingDecimal.Form.GENERAL);
3287
3288 // MAX_FD_CHARS + 1 (round?)
3289 char[] v = new char[MAX_FD_CHARS + 1
3290 + Math.abs(fd.getExponent())];
3291 int len = fd.getChars(v);
3292
3293 char[] exp = exponent(v, len);
3294 if (exp != null) {
3295 prec -= 1;
3296 } else {
3297 prec = prec
3298 - (value == 0 ? 0 : fd.getExponentRounded())
3299 - 1;
3300 }
3301
3302 char[] mant = addZeros(mantissa(v, len), prec);
3303 // If the precision is zero and the '#' flag is set, add the
3304 // requested decimal point.
3305 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3306 mant = addDot(mant);
3307
3308 int newW = width;
3309 if (width != -1) {
3310 if (exp != null)
3311 newW = adjustWidth(width - exp.length - 1, f,
3312 neg);
3313 else
3314 newW = adjustWidth(width, f, neg);
3315 }
3316 localizedMagnitude(sb, mant, f, newW, l);
3317
3318 if (exp != null) {
3319 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3320
3321 Flags flags = f.dup().remove(Flags.GROUP);
3322 char sign = exp[0];
3323 assert (sign == '+' || sign == '-');
3324 sb.append(sign);
3325
3326 char[] tmp = new char[exp.length - 1];
3327 System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3328 sb.append(localizedMagnitude(null, tmp, flags, -1,
3329 l));
3330 }
3331 } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3332 int prec = precision;
3333 if (precision == -1)
3334 // assume that we want all of the digits
3335 prec = 0;
3336 else if (precision == 0)
3337 prec = 1;
3338
3339 String s = hexDouble(value, prec);
3340
3341 char[] va;
3342 boolean upper = f.contains(Flags.UPPERCASE);
3343 sb.append(upper ? "0X" : "0x");
3344
3345 if (f.contains(Flags.ZERO_PAD))
3346 for (int i = 0; i < width - s.length() - 2; i++)
3347 sb.append('0');
3348
3349 int idx = s.indexOf('p');
3350 va = s.substring(0, idx).toCharArray();
3351 if (upper) {
3352 String tmp = new String(va);
3353 // don't localize hex
3354 tmp = tmp.toUpperCase(Locale.US);
3355 va = tmp.toCharArray();
3356 }
3357 sb.append(prec != 0 ? addZeros(va, prec) : va);
3358 sb.append(upper ? 'P' : 'p');
3359 sb.append(s.substring(idx + 1));
3360 }
3361 }
3362
3363 private char[] mantissa(char[] v, int len) {
3364 int i;
3365 for (i = 0; i < len; i++) {
3366 if (v[i] == 'e')
3367 break;
3368 }
3369 char[] tmp = new char[i];
3370 System.arraycopy(v, 0, tmp, 0, i);
3371 return tmp;
3372 }
3373
3374 private char[] exponent(char[] v, int len) {
3375 int i;
3376 for (i = len - 1; i >= 0; i--) {
3377 if (v[i] == 'e')
3378 break;
3379 }
3380 if (i == -1)
3381 return null;
3382 char[] tmp = new char[len - i - 1];
3383 System.arraycopy(v, i + 1, tmp, 0, len - i - 1);
3384 return tmp;
3385 }
3386
3387 // Add zeros to the requested precision.
3388 private char[] addZeros(char[] v, int prec) {
3389 // Look for the dot. If we don't find one, the we'll need to add
3390 // it before we add the zeros.
3391 int i;
3392 for (i = 0; i < v.length; i++) {
3393 if (v[i] == '.')
3394 break;
3395 }
3396 boolean needDot = false;
3397 if (i == v.length) {
3398 needDot = true;
3399 }
3400
3401 // Determine existing precision.
3402 int outPrec = v.length - i - (needDot ? 0 : 1);
3403 assert (outPrec <= prec);
3404 if (outPrec == prec)
3405 return v;
3406
3407 // Create new array with existing contents.
3408 char[] tmp = new char[v.length + prec - outPrec
3409 + (needDot ? 1 : 0)];
3410 System.arraycopy(v, 0, tmp, 0, v.length);
3411
3412 // Add dot if previously determined to be necessary.
3413 int start = v.length;
3414 if (needDot) {
3415 tmp[v.length] = '.';
3416 start++;
3417 }
3418
3419 // Add zeros.
3420 for (int j = start; j < tmp.length; j++)
3421 tmp[j] = '0';
3422
3423 return tmp;
3424 }
3425
3426 // Method assumes that d > 0.
3427 private String hexDouble(double d, int prec) {
3428 // Let Double.toHexString handle simple cases
3429 if (!FpUtils.isFinite(d) || d == 0.0 || prec == 0
3430 || prec >= 13)
3431 // remove "0x"
3432 return Double.toHexString(d).substring(2);
3433 else {
3434 assert (prec >= 1 && prec <= 12);
3435
3436 int exponent = FpUtils.getExponent(d);
3437 boolean subnormal = (exponent == DoubleConsts.MIN_EXPONENT - 1);
3438
3439 // If this is subnormal input so normalize (could be faster to
3440 // do as integer operation).
3441 if (subnormal) {
3442 scaleUp = FpUtils.scalb(1.0, 54);
3443 d *= scaleUp;
3444 // Calculate the exponent. This is not just exponent + 54
3445 // since the former is not the normalized exponent.
3446 exponent = FpUtils.getExponent(d);
3447 assert exponent >= DoubleConsts.MIN_EXPONENT
3448 && exponent <= DoubleConsts.MAX_EXPONENT : exponent;
3449 }
3450
3451 int precision = 1 + prec * 4;
3452 int shiftDistance = DoubleConsts.SIGNIFICAND_WIDTH
3453 - precision;
3454 assert (shiftDistance >= 1 && shiftDistance < DoubleConsts.SIGNIFICAND_WIDTH);
3455
3456 long doppel = Double.doubleToLongBits(d);
3457 // Deterime the number of bits to keep.
3458 long newSignif = (doppel & (DoubleConsts.EXP_BIT_MASK | DoubleConsts.SIGNIF_BIT_MASK)) >> shiftDistance;
3459 // Bits to round away.
3460 long roundingBits = doppel & ~(~0L << shiftDistance);
3461
3462 // To decide how to round, look at the low-order bit of the
3463 // working significand, the highest order discarded bit (the
3464 // round bit) and whether any of the lower order discarded bits
3465 // are nonzero (the sticky bit).
3466
3467 boolean leastZero = (newSignif & 0x1L) == 0L;
3468 boolean round = ((1L << (shiftDistance - 1)) & roundingBits) != 0L;
3469 boolean sticky = shiftDistance > 1
3470 && (~(1L << (shiftDistance - 1)) & roundingBits) != 0;
3471 if ((leastZero && round && sticky)
3472 || (!leastZero && round)) {
3473 newSignif++;
3474 }
3475
3476 long signBit = doppel & DoubleConsts.SIGN_BIT_MASK;
3477 newSignif = signBit | (newSignif << shiftDistance);
3478 double result = Double.longBitsToDouble(newSignif);
3479
3480 if (Double.isInfinite(result)) {
3481 // Infinite result generated by rounding
3482 return "1.0p1024";
3483 } else {
3484 String res = Double.toHexString(result)
3485 .substring(2);
3486 if (!subnormal)
3487 return res;
3488 else {
3489 // Create a normalized subnormal string.
3490 int idx = res.indexOf('p');
3491 if (idx == -1) {
3492 // No 'p' character in hex string.
3493 assert false;
3494 return null;
3495 } else {
3496 // Get exponent and append at the end.
3497 String exp = res.substring(idx + 1);
3498 int iexp = Integer.parseInt(exp) - 54;
3499 return res.substring(0, idx) + "p"
3500 + Integer.toString(iexp);
3501 }
3502 }
3503 }
3504 }
3505 }
3506
3507 private void print(BigDecimal value, Locale l)
3508 throws IOException {
3509 if (c == Conversion.HEXADECIMAL_FLOAT)
3510 failConversion(c, value);
3511 StringBuilder sb = new StringBuilder();
3512 boolean neg = value.signum() == -1;
3513 BigDecimal v = value.abs();
3514 // leading sign indicator
3515 leadingSign(sb, neg);
3516
3517 // the value
3518 print(sb, v, l, f, c, precision, neg);
3519
3520 // trailing sign indicator
3521 trailingSign(sb, neg);
3522
3523 // justify based on width
3524 a.append(justify(sb.toString()));
3525 }
3526
3527 // value > 0
3528 private void print(StringBuilder sb, BigDecimal value,
3529 Locale l, Flags f, char c, int precision, boolean neg)
3530 throws IOException {
3531 if (c == Conversion.SCIENTIFIC) {
3532 // Create a new BigDecimal with the desired precision.
3533 int prec = (precision == -1 ? 6 : precision);
3534 int scale = value.scale();
3535 int origPrec = value.precision();
3536 int nzeros = 0;
3537 int compPrec;
3538
3539 if (prec > origPrec - 1) {
3540 compPrec = origPrec;
3541 nzeros = prec - (origPrec - 1);
3542 } else {
3543 compPrec = prec + 1;
3544 }
3545
3546 MathContext mc = new MathContext(compPrec);
3547 BigDecimal v = new BigDecimal(value.unscaledValue(),
3548 scale, mc);
3549
3550 BigDecimalLayout bdl = new BigDecimalLayout(v
3551 .unscaledValue(), v.scale(),
3552 BigDecimalLayoutForm.SCIENTIFIC);
3553
3554 char[] mant = bdl.mantissa();
3555
3556 // Add a decimal point if necessary. The mantissa may not
3557 // contain a decimal point if the scale is zero (the internal
3558 // representation has no fractional part) or the original
3559 // precision is one. Append a decimal point if '#' is set or if
3560 // we require zero padding to get to the requested precision.
3561 if ((origPrec == 1 || !bdl.hasDot())
3562 && (nzeros > 0 || (f.contains(Flags.ALTERNATE))))
3563 mant = addDot(mant);
3564
3565 // Add trailing zeros in the case precision is greater than
3566 // the number of available digits after the decimal separator.
3567 mant = trailingZeros(mant, nzeros);
3568
3569 char[] exp = bdl.exponent();
3570 int newW = width;
3571 if (width != -1)
3572 newW = adjustWidth(width - exp.length - 1, f, neg);
3573 localizedMagnitude(sb, mant, f, newW, l);
3574
3575 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3576
3577 Flags flags = f.dup().remove(Flags.GROUP);
3578 char sign = exp[0];
3579 assert (sign == '+' || sign == '-');
3580 sb.append(exp[0]);
3581
3582 char[] tmp = new char[exp.length - 1];
3583 System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3584 sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3585 } else if (c == Conversion.DECIMAL_FLOAT) {
3586 // Create a new BigDecimal with the desired precision.
3587 int prec = (precision == -1 ? 6 : precision);
3588 int scale = value.scale();
3589 int compPrec = value.precision();
3590 if (scale > prec)
3591 compPrec -= (scale - prec);
3592 MathContext mc = new MathContext(compPrec);
3593 BigDecimal v = new BigDecimal(value.unscaledValue(),
3594 scale, mc);
3595
3596 BigDecimalLayout bdl = new BigDecimalLayout(v
3597 .unscaledValue(), v.scale(),
3598 BigDecimalLayoutForm.DECIMAL_FLOAT);
3599
3600 char mant[] = bdl.mantissa();
3601 int nzeros = (bdl.scale() < prec ? prec - bdl.scale()
3602 : 0);
3603
3604 // Add a decimal point if necessary. The mantissa may not
3605 // contain a decimal point if the scale is zero (the internal
3606 // representation has no fractional part). Append a decimal
3607 // point if '#' is set or we require zero padding to get to the
3608 // requested precision.
3609 if (bdl.scale() == 0
3610 && (f.contains(Flags.ALTERNATE) || nzeros > 0))
3611 mant = addDot(bdl.mantissa());
3612
3613 // Add trailing zeros if the precision is greater than the
3614 // number of available digits after the decimal separator.
3615 mant = trailingZeros(mant, nzeros);
3616
3617 localizedMagnitude(sb, mant, f, adjustWidth(width, f,
3618 neg), l);
3619 } else if (c == Conversion.GENERAL) {
3620 int prec = precision;
3621 if (precision == -1)
3622 prec = 6;
3623 else if (precision == 0)
3624 prec = 1;
3625
3626 BigDecimal tenToTheNegFour = BigDecimal.valueOf(1, 4);
3627 BigDecimal tenToThePrec = BigDecimal.valueOf(1, -prec);
3628 if ((value.equals(BigDecimal.ZERO))
3629 || ((value.compareTo(tenToTheNegFour) != -1) && (value
3630 .compareTo(tenToThePrec) == -1))) {
3631
3632 int e = -value.scale()
3633 + (value.unscaledValue().toString()
3634 .length() - 1);
3635
3636 // xxx.yyy
3637 // g precision (# sig digits) = #x + #y
3638 // f precision = #y
3639 // exponent = #x - 1
3640 // => f precision = g precision - exponent - 1
3641 // 0.000zzz
3642 // g precision (# sig digits) = #z
3643 // f precision = #0 (after '.') + #z
3644 // exponent = - #0 (after '.') - 1
3645 // => f precision = g precision - exponent - 1
3646 prec = prec - e - 1;
3647
3648 print(sb, value, l, f, Conversion.DECIMAL_FLOAT,
3649 prec, neg);
3650 } else {
3651 print(sb, value, l, f, Conversion.SCIENTIFIC,
3652 prec - 1, neg);
3653 }
3654 } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3655 // This conversion isn't supported. The error should be
3656 // reported earlier.
3657 assert false;
3658 }
3659 }
3660
3661 private class BigDecimalLayout {
3662 private StringBuilder mant;
3663 private StringBuilder exp;
3664 private boolean dot = false;
3665 private int scale;
3666
3667 public BigDecimalLayout(BigInteger intVal, int scale,
3668 BigDecimalLayoutForm form) {
3669 layout(intVal, scale, form);
3670 }
3671
3672 public boolean hasDot() {
3673 return dot;
3674 }
3675
3676 public int scale() {
3677 return scale;
3678 }
3679
3680 // char[] with canonical string representation
3681 public char[] layoutChars() {
3682 StringBuilder sb = new StringBuilder(mant);
3683 if (exp != null) {
3684 sb.append('E');
3685 sb.append(exp);
3686 }
3687 return toCharArray(sb);
3688 }
3689
3690 public char[] mantissa() {
3691 return toCharArray(mant);
3692 }
3693
3694 // The exponent will be formatted as a sign ('+' or '-') followed
3695 // by the exponent zero-padded to include at least two digits.
3696 public char[] exponent() {
3697 return toCharArray(exp);
3698 }
3699
3700 private char[] toCharArray(StringBuilder sb) {
3701 if (sb == null)
3702 return null;
3703 char[] result = new char[sb.length()];
3704 sb.getChars(0, result.length, result, 0);
3705 return result;
3706 }
3707
3708 private void layout(BigInteger intVal, int scale,
3709 BigDecimalLayoutForm form) {
3710 char coeff[] = intVal.toString().toCharArray();
3711 this .scale = scale;
3712
3713 // Construct a buffer, with sufficient capacity for all cases.
3714 // If E-notation is needed, length will be: +1 if negative, +1
3715 // if '.' needed, +2 for "E+", + up to 10 for adjusted
3716 // exponent. Otherwise it could have +1 if negative, plus
3717 // leading "0.00000"
3718 mant = new StringBuilder(coeff.length + 14);
3719
3720 if (scale == 0) {
3721 int len = coeff.length;
3722 if (len > 1) {
3723 mant.append(coeff[0]);
3724 if (form == BigDecimalLayoutForm.SCIENTIFIC) {
3725 mant.append('.');
3726 dot = true;
3727 mant.append(coeff, 1, len - 1);
3728 exp = new StringBuilder("+");
3729 if (len < 10)
3730 exp.append("0").append(len - 1);
3731 else
3732 exp.append(len - 1);
3733 } else {
3734 mant.append(coeff, 1, len - 1);
3735 }
3736 } else {
3737 mant.append(coeff);
3738 if (form == BigDecimalLayoutForm.SCIENTIFIC)
3739 exp = new StringBuilder("+00");
3740 }
3741 return;
3742 }
3743 long adjusted = -(long) scale + (coeff.length - 1);
3744 if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
3745 // count of padding zeros
3746 int pad = scale - coeff.length;
3747 if (pad >= 0) {
3748 // 0.xxx form
3749 mant.append("0.");
3750 dot = true;
3751 for (; pad > 0; pad--)
3752 mant.append('0');
3753 mant.append(coeff);
3754 } else {
3755 if (-pad < coeff.length) {
3756 // xx.xx form
3757 mant.append(coeff, 0, -pad);
3758 mant.append('.');
3759 dot = true;
3760 mant.append(coeff, -pad, scale);
3761 } else {
3762 // xx form
3763 mant.append(coeff, 0, coeff.length);
3764 for (int i = 0; i < -scale; i++)
3765 mant.append('0');
3766 this .scale = 0;
3767 }
3768 }
3769 } else {
3770 // x.xxx form
3771 mant.append(coeff[0]);
3772 if (coeff.length > 1) {
3773 mant.append('.');
3774 dot = true;
3775 mant.append(coeff, 1, coeff.length - 1);
3776 }
3777 exp = new StringBuilder();
3778 if (adjusted != 0) {
3779 long abs = Math.abs(adjusted);
3780 // require sign
3781 exp.append(adjusted < 0 ? '-' : '+');
3782 if (abs < 10)
3783 exp.append('0');
3784 exp.append(abs);
3785 } else {
3786 exp.append("+00");
3787 }
3788 }
3789 }
3790 }
3791
3792 private int adjustWidth(int width, Flags f, boolean neg) {
3793 int newW = width;
3794 if (newW != -1 && neg && f.contains(Flags.PARENTHESES))
3795 newW--;
3796 return newW;
3797 }
3798
3799 // Add a '.' to th mantissa if required
3800 private char[] addDot(char[] mant) {
3801 char[] tmp = mant;
3802 tmp = new char[mant.length + 1];
3803 System.arraycopy(mant, 0, tmp, 0, mant.length);
3804 tmp[tmp.length - 1] = '.';
3805 return tmp;
3806 }
3807
3808 // Add trailing zeros in the case precision is greater than the number
3809 // of available digits after the decimal separator.
3810 private char[] trailingZeros(char[] mant, int nzeros) {
3811 char[] tmp = mant;
3812 if (nzeros > 0) {
3813 tmp = new char[mant.length + nzeros];
3814 System.arraycopy(mant, 0, tmp, 0, mant.length);
3815 for (int i = mant.length; i < tmp.length; i++)
3816 tmp[i] = '0';
3817 }
3818 return tmp;
3819 }
3820
3821 private void print(Calendar t, char c, Locale l)
3822 throws IOException {
3823 StringBuilder sb = new StringBuilder();
3824 print(sb, t, c, l);
3825
3826 // justify based on width
3827 String s = justify(sb.toString());
3828 if (f.contains(Flags.UPPERCASE))
3829 s = s.toUpperCase();
3830
3831 a.append(s);
3832 }
3833
3834 private Appendable print(StringBuilder sb, Calendar t, char c,
3835 Locale l) throws IOException {
3836 assert (width == -1);
3837 if (sb == null)
3838 sb = new StringBuilder();
3839 switch (c) {
3840 case DateTime.HOUR_OF_DAY_0: // 'H' (00 - 23)
3841 case DateTime.HOUR_0: // 'I' (01 - 12)
3842 case DateTime.HOUR_OF_DAY: // 'k' (0 - 23) -- like H
3843 case DateTime.HOUR: { // 'l' (1 - 12) -- like I
3844 int i = t.get(Calendar.HOUR_OF_DAY);
3845 if (c == DateTime.HOUR_0 || c == DateTime.HOUR)
3846 i = (i == 0 || i == 12 ? 12 : i % 12);
3847 Flags flags = (c == DateTime.HOUR_OF_DAY_0
3848 || c == DateTime.HOUR_0 ? Flags.ZERO_PAD
3849 : Flags.NONE);
3850 sb.append(localizedMagnitude(null, i, flags, 2, l));
3851 break;
3852 }
3853 case DateTime.MINUTE: { // 'M' (00 - 59)
3854 int i = t.get(Calendar.MINUTE);
3855 Flags flags = Flags.ZERO_PAD;
3856 sb.append(localizedMagnitude(null, i, flags, 2, l));
3857 break;
3858 }
3859 case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999)
3860 int i = t.get(Calendar.MILLISECOND) * 1000000;
3861 Flags flags = Flags.ZERO_PAD;
3862 sb.append(localizedMagnitude(null, i, flags, 9, l));
3863 break;
3864 }
3865 case DateTime.MILLISECOND: { // 'L' (000 - 999)
3866 int i = t.get(Calendar.MILLISECOND);
3867 Flags flags = Flags.ZERO_PAD;
3868 sb.append(localizedMagnitude(null, i, flags, 3, l));
3869 break;
3870 }
3871 case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
3872 long i = t.getTimeInMillis();
3873 Flags flags = Flags.NONE;
3874 sb.append(localizedMagnitude(null, i, flags, width, l));
3875 break;
3876 }
3877 case DateTime.AM_PM: { // 'p' (am or pm)
3878 // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
3879 String[] ampm = { "AM", "PM" };
3880 if (l != null && l != Locale.US) {
3881 DateFormatSymbols dfs = DateFormatSymbols
3882 .getInstance(l);
3883 ampm = dfs.getAmPmStrings();
3884 }
3885 String s = ampm[t.get(Calendar.AM_PM)];
3886 sb.append(s.toLowerCase(l != null ? l : Locale.US));
3887 break;
3888 }
3889 case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
3890 long i = t.getTimeInMillis() / 1000;
3891 Flags flags = Flags.NONE;
3892 sb.append(localizedMagnitude(null, i, flags, width, l));
3893 break;
3894 }
3895 case DateTime.SECOND: { // 'S' (00 - 60 - leap second)
3896 int i = t.get(Calendar.SECOND);
3897 Flags flags = Flags.ZERO_PAD;
3898 sb.append(localizedMagnitude(null, i, flags, 2, l));
3899 break;
3900 }
3901 case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
3902 int i = t.get(Calendar.ZONE_OFFSET);
3903 boolean neg = i < 0;
3904 sb.append(neg ? '-' : '+');
3905 if (neg)
3906 i = -i;
3907 int min = i / 60000;
3908 // combine minute and hour into a single integer
3909 int offset = (min / 60) * 100 + (min % 60);
3910 Flags flags = Flags.ZERO_PAD;
3911
3912 sb
3913 .append(localizedMagnitude(null, offset, flags,
3914 4, l));
3915 break;
3916 }
3917 case DateTime.ZONE: { // 'Z' (symbol)
3918 TimeZone tz = t.getTimeZone();
3919 sb.append(tz.getDisplayName(
3920 (t.get(Calendar.DST_OFFSET) != 0),
3921 TimeZone.SHORT, (l == null) ? Locale.US : l));
3922 break;
3923 }
3924
3925 // Date
3926 case DateTime.NAME_OF_DAY_ABBREV: // 'a'
3927 case DateTime.NAME_OF_DAY: { // 'A'
3928 int i = t.get(Calendar.DAY_OF_WEEK);
3929 Locale lt = ((l == null) ? Locale.US : l);
3930 DateFormatSymbols dfs = DateFormatSymbols
3931 .getInstance(lt);
3932 if (c == DateTime.NAME_OF_DAY)
3933 sb.append(dfs.getWeekdays()[i]);
3934 else
3935 sb.append(dfs.getShortWeekdays()[i]);
3936 break;
3937 }
3938 case DateTime.NAME_OF_MONTH_ABBREV: // 'b'
3939 case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
3940 case DateTime.NAME_OF_MONTH: { // 'B'
3941 int i = t.get(Calendar.MONTH);
3942 Locale lt = ((l == null) ? Locale.US : l);
3943 DateFormatSymbols dfs = DateFormatSymbols
3944 .getInstance(lt);
3945 if (c == DateTime.NAME_OF_MONTH)
3946 sb.append(dfs.getMonths()[i]);
3947 else
3948 sb.append(dfs.getShortMonths()[i]);
3949 break;
3950 }
3951 case DateTime.CENTURY: // 'C' (00 - 99)
3952 case DateTime.YEAR_2: // 'y' (00 - 99)
3953 case DateTime.YEAR_4: { // 'Y' (0000 - 9999)
3954 int i = t.get(Calendar.YEAR);
3955 int size = 2;
3956 switch (c) {
3957 case DateTime.CENTURY:
3958 i /= 100;
3959 break;
3960 case DateTime.YEAR_2:
3961 i %= 100;
3962 break;
3963 case DateTime.YEAR_4:
3964 size = 4;
3965 break;
3966 }
3967 Flags flags = Flags.ZERO_PAD;
3968 sb.append(localizedMagnitude(null, i, flags, size, l));
3969 break;
3970 }
3971 case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31)
3972 case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d
3973 int i = t.get(Calendar.DATE);
3974 Flags flags = (c == DateTime.DAY_OF_MONTH_0 ? Flags.ZERO_PAD
3975 : Flags.NONE);
3976 sb.append(localizedMagnitude(null, i, flags, 2, l));
3977 break;
3978 }
3979 case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366)
3980 int i = t.get(Calendar.DAY_OF_YEAR);
3981 Flags flags = Flags.ZERO_PAD;
3982 sb.append(localizedMagnitude(null, i, flags, 3, l));
3983 break;
3984 }
3985 case DateTime.MONTH: { // 'm' (01 - 12)
3986 int i = t.get(Calendar.MONTH) + 1;
3987 Flags flags = Flags.ZERO_PAD;
3988 sb.append(localizedMagnitude(null, i, flags, 2, l));
3989 break;
3990 }
3991
3992 // Composites
3993 case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
3994 case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M)
3995 char sep = ':';
3996 print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
3997 print(sb, t, DateTime.MINUTE, l);
3998 if (c == DateTime.TIME) {
3999 sb.append(sep);
4000 print(sb, t, DateTime.SECOND, l);
4001 }
4002 break;
4003 }
4004 case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M)
4005 char sep = ':';
4006 print(sb, t, DateTime.HOUR_0, l).append(sep);
4007 print(sb, t, DateTime.MINUTE, l).append(sep);
4008 print(sb, t, DateTime.SECOND, l).append(' ');
4009 // this may be in wrong place for some locales
4010 StringBuilder tsb = new StringBuilder();
4011 print(tsb, t, DateTime.AM_PM, l);
4012 sb.append(tsb.toString().toUpperCase(
4013 l != null ? l : Locale.US));
4014 break;
4015 }
4016 case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999)
4017 char sep = ' ';
4018 print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l)
4019 .append(sep);
4020 print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(
4021 sep);
4022 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4023 print(sb, t, DateTime.TIME, l).append(sep);
4024 print(sb, t, DateTime.ZONE, l).append(sep);
4025 print(sb, t, DateTime.YEAR_4, l);
4026 break;
4027 }
4028 case DateTime.DATE: { // 'D' (mm/dd/yy)
4029 char sep = '/';
4030 print(sb, t, DateTime.MONTH, l).append(sep);
4031 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4032 print(sb, t, DateTime.YEAR_2, l);
4033 break;
4034 }
4035 case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
4036 char sep = '-';
4037 print(sb, t, DateTime.YEAR_4, l).append(sep);
4038 print(sb, t, DateTime.MONTH, l).append(sep);
4039 print(sb, t, DateTime.DAY_OF_MONTH_0, l);
4040 break;
4041 }
4042 default:
4043 assert false;
4044 }
4045 return sb;
4046 }
4047
4048 // -- Methods to support throwing exceptions --
4049
4050 private void failMismatch(Flags f, char c) {
4051 String fs = f.toString();
4052 throw new FormatFlagsConversionMismatchException(fs, c);
4053 }
4054
4055 private void failConversion(char c, Object arg) {
4056 throw new IllegalFormatConversionException(c, arg
4057 .getClass());
4058 }
4059
4060 private char getZero(Locale l) {
4061 if ((l != null) && !l.equals(locale())) {
4062 DecimalFormatSymbols dfs = DecimalFormatSymbols
4063 .getInstance(l);
4064 return dfs.getZeroDigit();
4065 }
4066 return zero;
4067 }
4068
4069 private StringBuilder localizedMagnitude(StringBuilder sb,
4070 long value, Flags f, int width, Locale l) {
4071 char[] va = Long.toString(value, 10).toCharArray();
4072 return localizedMagnitude(sb, va, f, width, l);
4073 }
4074
4075 private StringBuilder localizedMagnitude(StringBuilder sb,
4076 char[] value, Flags f, int width, Locale l) {
4077 if (sb == null)
4078 sb = new StringBuilder();
4079 int begin = sb.length();
4080
4081 char zero = getZero(l);
4082
4083 // determine localized grouping separator and size
4084 char grpSep = '\0';
4085 int grpSize = -1;
4086 char decSep = '\0';
4087
4088 int len = value.length;
4089 int dot = len;
4090 for (int j = 0; j < len; j++) {
4091 if (value[j] == '.') {
4092 dot = j;
4093 break;
4094 }
4095 }
4096
4097 if (dot < len) {
4098 if (l == null || l.equals(Locale.US)) {
4099 decSep = '.';
4100 } else {
4101 DecimalFormatSymbols dfs = DecimalFormatSymbols
4102 .getInstance(l);
4103 decSep = dfs.getDecimalSeparator();
4104 }
4105 }
4106
4107 if (f.contains(Flags.GROUP)) {
4108 if (l == null || l.equals(Locale.US)) {
4109 grpSep = ',';
4110 grpSize = 3;
4111 } else {
4112 DecimalFormatSymbols dfs = DecimalFormatSymbols
4113 .getInstance(l);
4114 grpSep = dfs.getGroupingSeparator();
4115 DecimalFormat df = (DecimalFormat) NumberFormat
4116 .getIntegerInstance(l);
4117 grpSize = df.getGroupingSize();
4118 }
4119 }
4120
4121 // localize the digits inserting group separators as necessary
4122 for (int j = 0; j < len; j++) {
4123 if (j == dot) {
4124 sb.append(decSep);
4125 // no more group separators after the decimal separator
4126 grpSep = '\0';
4127 continue;
4128 }
4129
4130 char c = value[j];
4131 sb.append((char) ((c - '0') + zero));
4132 if (grpSep != '\0' && j != dot - 1
4133 && ((dot - j) % grpSize == 1))
4134 sb.append(grpSep);
4135 }
4136
4137 // apply zero padding
4138 len = sb.length();
4139 if (width != -1 && f.contains(Flags.ZERO_PAD))
4140 for (int k = 0; k < width - len; k++)
4141 sb.insert(begin, zero);
4142
4143 return sb;
4144 }
4145 }
4146
4147 private static class Flags {
4148 private int flags;
4149
4150 static final Flags NONE = new Flags(0); // ''
4151
4152 // duplicate declarations from Formattable.java
4153 static final Flags LEFT_JUSTIFY = new Flags(1 << 0); // '-'
4154 static final Flags UPPERCASE = new Flags(1 << 1); // '^'
4155 static final Flags ALTERNATE = new Flags(1 << 2); // '#'
4156
4157 // numerics
4158 static final Flags PLUS = new Flags(1 << 3); // '+'
4159 static final Flags LEADING_SPACE = new Flags(1 << 4); // ' '
4160 static final Flags ZERO_PAD = new Flags(1 << 5); // '0'
4161 static final Flags GROUP = new Flags(1 << 6); // ','
4162 static final Flags PARENTHESES = new Flags(1 << 7); // '('
4163
4164 // indexing
4165 static final Flags PREVIOUS = new Flags(1 << 8); // '<'
4166
4167 private Flags(int f) {
4168 flags = f;
4169 }
4170
4171 public int valueOf() {
4172 return flags;
4173 }
4174
4175 public boolean contains(Flags f) {
4176 return (flags & f.valueOf()) == f.valueOf();
4177 }
4178
4179 public Flags dup() {
4180 return new Flags(flags);
4181 }
4182
4183 private Flags add(Flags f) {
4184 flags |= f.valueOf();
4185 return this ;
4186 }
4187
4188 public Flags remove(Flags f) {
4189 flags &= ~f.valueOf();
4190 return this ;
4191 }
4192
4193 public static Flags parse(String s) {
4194 char[] ca = s.toCharArray();
4195 Flags f = new Flags(0);
4196 for (int i = 0; i < ca.length; i++) {
4197 Flags v = parse(ca[i]);
4198 if (f.contains(v))
4199 throw new DuplicateFormatFlagsException(v
4200 .toString());
4201 f.add(v);
4202 }
4203 return f;
4204 }
4205
4206 // parse those flags which may be provided by users
4207 private static Flags parse(char c) {
4208 switch (c) {
4209 case '-':
4210 return LEFT_JUSTIFY;
4211 case '#':
4212 return ALTERNATE;
4213 case '+':
4214 return PLUS;
4215 case ' ':
4216 return LEADING_SPACE;
4217 case '0':
4218 return ZERO_PAD;
4219 case ',':
4220 return GROUP;
4221 case '(':
4222 return PARENTHESES;
4223 case '<':
4224 return PREVIOUS;
4225 default:
4226 throw new UnknownFormatFlagsException(String.valueOf(c));
4227 }
4228 }
4229
4230 // Returns a string representation of the current <tt>Flags</tt>.
4231 public static String toString(Flags f) {
4232 return f.toString();
4233 }
4234
4235 public String toString() {
4236 StringBuilder sb = new StringBuilder();
4237 if (contains(LEFT_JUSTIFY))
4238 sb.append('-');
4239 if (contains(UPPERCASE))
4240 sb.append('^');
4241 if (contains(ALTERNATE))
4242 sb.append('#');
4243 if (contains(PLUS))
4244 sb.append('+');
4245 if (contains(LEADING_SPACE))
4246 sb.append(' ');
4247 if (contains(ZERO_PAD))
4248 sb.append('0');
4249 if (contains(GROUP))
4250 sb.append(',');
4251 if (contains(PARENTHESES))
4252 sb.append('(');
4253 if (contains(PREVIOUS))
4254 sb.append('<');
4255 return sb.toString();
4256 }
4257 }
4258
4259 private static class Conversion {
4260 // Byte, Short, Integer, Long, BigInteger
4261 // (and associated primitives due to autoboxing)
4262 static final char DECIMAL_INTEGER = 'd';
4263 static final char OCTAL_INTEGER = 'o';
4264 static final char HEXADECIMAL_INTEGER = 'x';
4265 static final char HEXADECIMAL_INTEGER_UPPER = 'X';
4266
4267 // Float, Double, BigDecimal
4268 // (and associated primitives due to autoboxing)
4269 static final char SCIENTIFIC = 'e';
4270 static final char SCIENTIFIC_UPPER = 'E';
4271 static final char GENERAL = 'g';
4272 static final char GENERAL_UPPER = 'G';
4273 static final char DECIMAL_FLOAT = 'f';
4274 static final char HEXADECIMAL_FLOAT = 'a';
4275 static final char HEXADECIMAL_FLOAT_UPPER = 'A';
4276
4277 // Character, Byte, Short, Integer
4278 // (and associated primitives due to autoboxing)
4279 static final char CHARACTER = 'c';
4280 static final char CHARACTER_UPPER = 'C';
4281
4282 // java.util.Date, java.util.Calendar, long
4283 static final char DATE_TIME = 't';
4284 static final char DATE_TIME_UPPER = 'T';
4285
4286 // if (arg.TYPE != boolean) return boolean
4287 // if (arg != null) return true; else return false;
4288 static final char BOOLEAN = 'b';
4289 static final char BOOLEAN_UPPER = 'B';
4290 // if (arg instanceof Formattable) arg.formatTo()
4291 // else arg.toString();
4292 static final char STRING = 's';
4293 static final char STRING_UPPER = 'S';
4294 // arg.hashCode()
4295 static final char HASHCODE = 'h';
4296 static final char HASHCODE_UPPER = 'H';
4297
4298 static final char LINE_SEPARATOR = 'n';
4299 static final char PERCENT_SIGN = '%';
4300
4301 static boolean isValid(char c) {
4302 return (isGeneral(c) || isInteger(c) || isFloat(c)
4303 || isText(c) || c == 't' || isCharacter(c));
4304 }
4305
4306 // Returns true iff the Conversion is applicable to all objects.
4307 static boolean isGeneral(char c) {
4308 switch (c) {
4309 case BOOLEAN:
4310 case BOOLEAN_UPPER:
4311 case STRING:
4312 case STRING_UPPER:
4313 case HASHCODE:
4314 case HASHCODE_UPPER:
4315 return true;
4316 default:
4317 return false;
4318 }
4319 }
4320
4321 // Returns true iff the Conversion is applicable to character.
4322 static boolean isCharacter(char c) {
4323 switch (c) {
4324 case CHARACTER:
4325 case CHARACTER_UPPER:
4326 return true;
4327 default:
4328 return false;
4329 }
4330 }
4331
4332 // Returns true iff the Conversion is an integer type.
4333 static boolean isInteger(char c) {
4334 switch (c) {
4335 case DECIMAL_INTEGER:
4336 case OCTAL_INTEGER:
4337 case HEXADECIMAL_INTEGER:
4338 case HEXADECIMAL_INTEGER_UPPER:
4339 return true;
4340 default:
4341 return false;
4342 }
4343 }
4344
4345 // Returns true iff the Conversion is a floating-point type.
4346 static boolean isFloat(char c) {
4347 switch (c) {
4348 case SCIENTIFIC:
4349 case SCIENTIFIC_UPPER:
4350 case GENERAL:
4351 case GENERAL_UPPER:
4352 case DECIMAL_FLOAT:
4353 case HEXADECIMAL_FLOAT:
4354 case HEXADECIMAL_FLOAT_UPPER:
4355 return true;
4356 default:
4357 return false;
4358 }
4359 }
4360
4361 // Returns true iff the Conversion does not require an argument
4362 static boolean isText(char c) {
4363 switch (c) {
4364 case LINE_SEPARATOR:
4365 case PERCENT_SIGN:
4366 return true;
4367 default:
4368 return false;
4369 }
4370 }
4371 }
4372
4373 private static class DateTime {
4374 static final char HOUR_OF_DAY_0 = 'H'; // (00 - 23)
4375 static final char HOUR_0 = 'I'; // (01 - 12)
4376 static final char HOUR_OF_DAY = 'k'; // (0 - 23) -- like H
4377 static final char HOUR = 'l'; // (1 - 12) -- like I
4378 static final char MINUTE = 'M'; // (00 - 59)
4379 static final char NANOSECOND = 'N'; // (000000000 - 999999999)
4380 static final char MILLISECOND = 'L'; // jdk, not in gnu (000 - 999)
4381 static final char MILLISECOND_SINCE_EPOCH = 'Q'; // (0 - 99...?)
4382 static final char AM_PM = 'p'; // (am or pm)
4383 static final char SECONDS_SINCE_EPOCH = 's'; // (0 - 99...?)
4384 static final char SECOND = 'S'; // (00 - 60 - leap second)
4385 static final char TIME = 'T'; // (24 hour hh:mm:ss)
4386 static final char ZONE_NUMERIC = 'z'; // (-1200 - +1200) - ls minus?
4387 static final char ZONE = 'Z'; // (symbol)
4388
4389 // Date
4390 static final char NAME_OF_DAY_ABBREV = 'a'; // 'a'
4391 static final char NAME_OF_DAY = 'A'; // 'A'
4392 static final char NAME_OF_MONTH_ABBREV = 'b'; // 'b'
4393 static final char NAME_OF_MONTH = 'B'; // 'B'
4394 static final char CENTURY = 'C'; // (00 - 99)
4395 static final char DAY_OF_MONTH_0 = 'd'; // (01 - 31)
4396 static final char DAY_OF_MONTH = 'e'; // (1 - 31) -- like d
4397 // * static final char ISO_WEEK_OF_YEAR_2 = 'g'; // cross %y %V
4398 // * static final char ISO_WEEK_OF_YEAR_4 = 'G'; // cross %Y %V
4399 static final char NAME_OF_MONTH_ABBREV_X = 'h'; // -- same b
4400 static final char DAY_OF_YEAR = 'j'; // (001 - 366)
4401 static final char MONTH = 'm'; // (01 - 12)
4402 // * static final char DAY_OF_WEEK_1 = 'u'; // (1 - 7) Monday
4403 // * static final char WEEK_OF_YEAR_SUNDAY = 'U'; // (0 - 53) Sunday+
4404 // * static final char WEEK_OF_YEAR_MONDAY_01 = 'V'; // (01 - 53) Monday+
4405 // * static final char DAY_OF_WEEK_0 = 'w'; // (0 - 6) Sunday
4406 // * static final char WEEK_OF_YEAR_MONDAY = 'W'; // (00 - 53) Monday
4407 static final char YEAR_2 = 'y'; // (00 - 99)
4408 static final char YEAR_4 = 'Y'; // (0000 - 9999)
4409
4410 // Composites
4411 static final char TIME_12_HOUR = 'r'; // (hh:mm:ss [AP]M)
4412 static final char TIME_24_HOUR = 'R'; // (hh:mm same as %H:%M)
4413 // * static final char LOCALE_TIME = 'X'; // (%H:%M:%S) - parse format?
4414 static final char DATE_TIME = 'c';
4415 // (Sat Nov 04 12:02:33 EST 1999)
4416 static final char DATE = 'D'; // (mm/dd/yy)
4417 static final char ISO_STANDARD_DATE = 'F'; // (%Y-%m-%d)
4418 // * static final char LOCALE_DATE = 'x'; // (mm/dd/yy)
4419
4420 static boolean isValid(char c) {
4421 switch (c) {
4422 case HOUR_OF_DAY_0:
4423 case HOUR_0:
4424 case HOUR_OF_DAY:
4425 case HOUR:
4426 case MINUTE:
4427 case NANOSECOND:
4428 case MILLISECOND:
4429 case MILLISECOND_SINCE_EPOCH:
4430 case AM_PM:
4431 case SECONDS_SINCE_EPOCH:
4432 case SECOND:
4433 case TIME:
4434 case ZONE_NUMERIC:
4435 case ZONE:
4436
4437 // Date
4438 case NAME_OF_DAY_ABBREV:
4439 case NAME_OF_DAY:
4440 case NAME_OF_MONTH_ABBREV:
4441 case NAME_OF_MONTH:
4442 case CENTURY:
4443 case DAY_OF_MONTH_0:
4444 case DAY_OF_MONTH:
4445 // * case ISO_WEEK_OF_YEAR_2:
4446 // * case ISO_WEEK_OF_YEAR_4:
4447 case NAME_OF_MONTH_ABBREV_X:
4448 case DAY_OF_YEAR:
4449 case MONTH:
4450 // * case DAY_OF_WEEK_1:
4451 // * case WEEK_OF_YEAR_SUNDAY:
4452 // * case WEEK_OF_YEAR_MONDAY_01:
4453 // * case DAY_OF_WEEK_0:
4454 // * case WEEK_OF_YEAR_MONDAY:
4455 case YEAR_2:
4456 case YEAR_4:
4457
4458 // Composites
4459 case TIME_12_HOUR:
4460 case TIME_24_HOUR:
4461 // * case LOCALE_TIME:
4462 case DATE_TIME:
4463 case DATE:
4464 case ISO_STANDARD_DATE:
4465 // * case LOCALE_DATE:
4466 return true;
4467 default:
4468 return false;
4469 }
4470 }
4471 }
4472 }
|