1   /*
2    * %W% %E%
3    *
4    * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5    * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package java.util;
9   
10  import java.io.BufferedWriter;
11  import java.io.Closeable;
12  import java.io.IOException;
13  import java.io.File;
14  import java.io.FileOutputStream;
15  import java.io.FileNotFoundException;
16  import java.io.Flushable;
17  import java.io.OutputStream;
18  import java.io.OutputStreamWriter;
19  import java.io.PrintStream;
20  import java.io.UnsupportedEncodingException;
21  import java.math.BigDecimal;
22  import java.math.BigInteger;
23  import java.math.MathContext;
24  import java.math.RoundingMode;
25  import java.nio.charset.Charset;
26  import java.text.DateFormatSymbols;
27  import java.text.DecimalFormat;
28  import java.text.DecimalFormatSymbols;
29  import java.text.NumberFormat;
30  import java.util.Calendar;
31  import java.util.Date;
32  import java.util.Locale;
33  import java.util.regex.Matcher;
34  import java.util.regex.Pattern;
35  
36  import sun.misc.FpUtils;
37  import sun.misc.DoubleConsts;
38  import sun.misc.FormattedFloatingDecimal;
39  
40  /**
41   * An interpreter for printf-style format strings.  This class provides support
42   * for layout justification and alignment, common formats for numeric, string,
43   * and date/time data, and locale-specific output.  Common Java types such as
44   * <tt>byte</tt>, {@link java.math.BigDecimal BigDecimal}, and {@link Calendar}
45   * are supported.  Limited formatting customization for arbitrary user types is
46   * provided through the {@link Formattable} interface.
47   *
48   * <p> Formatters are not necessarily safe for multithreaded access.  Thread
49   * safety is optional and is the responsibility of users of methods in this
50   * class.
51   *
52   * <p> Formatted printing for the Java language is heavily inspired by C's
53   * <tt>printf</tt>.  Although the format strings are similar to C, some
54   * customizations have been made to accommodate the Java language and exploit
55   * some of its features.  Also, Java formatting is more strict than C's; for
56   * example, if a conversion is incompatible with a flag, an exception will be
57   * thrown.  In C inapplicable flags are silently ignored.  The format strings
58   * are thus intended to be recognizable to C programmers but not necessarily
59   * completely compatible with those in C.
60   *
61   * <p> Examples of expected usage:
62   *
63   * <blockquote><pre>
64   *   StringBuilder sb = new StringBuilder();
65   *   // Send all output to the Appendable object sb
66   *   Formatter formatter = new Formatter(sb, Locale.US);
67   *
68   *   // Explicit argument indices may be used to re-order output.
69   *   formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
70   *   // -&gt; " d  c  b  a"
71   *
72   *   // Optional locale as the first argument can be used to get
73   *   // locale-specific formatting of numbers.  The precision and width can be
74   *   // given to round and align the value.
75   *   formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
76   *   // -&gt; "e =    +2,7183"
77   *
78   *   // The '(' numeric flag may be used to format negative numbers with
79   *   // parentheses rather than a minus sign.  Group separators are
80   *   // automatically inserted.
81   *   formatter.format("Amount gained or lost since last statement: $ %(,.2f",
82   *                    balanceDelta);
83   *   // -&gt; "Amount gained or lost since last statement: $ (6,217.58)"
84   * </pre></blockquote>
85   *
86   * <p> Convenience methods for common formatting requests exist as illustrated
87   * by the following invocations:
88   *
89   * <blockquote><pre>
90   *   // Writes a formatted string to System.out.
91   *   System.out.format("Local time: %tT", Calendar.getInstance());
92   *   // -&gt; "Local time: 13:34:18"
93   *
94   *   // Writes formatted output to System.err.
95   *   System.err.printf("Unable to open file '%1$s': %2$s",
96   *                     fileName, exception.getMessage());
97   *   // -&gt; "Unable to open file 'food': No such file or directory"
98   * </pre></blockquote>
99   *
100  * <p> Like C's <tt>sprintf(3)</tt>, Strings may be formatted using the static
101  * method {@link String#format(String,Object...) String.format}:
102  *
103  * <blockquote><pre>
104  *   // Format a string containing a date.
105  *   import java.util.Calendar;
106  *   import java.util.GregorianCalendar;
107  *   import static java.util.Calendar.*;
108  *
109  *   Calendar c = new GregorianCalendar(1995, MAY, 23);
110  *   String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
111  *   // -&gt; s == "Duke's Birthday: May 23, 1995"
112  * </pre></blockquote>
113  *
114  * <h3><a name="org">Organization</a></h3>
115  *
116  * <p> This specification is divided into two sections.  The first section, <a
117  * href="#summary">Summary</a>, covers the basic formatting concepts.  This
118  * section is intended for users who want to get started quickly and are
119  * familiar with formatted printing in other programming languages.  The second
120  * section, <a href="#detail">Details</a>, covers the specific implementation
121  * details.  It is intended for users who want more precise specification of
122  * formatting behavior.
123  *
124  * <h3><a name="summary">Summary</a></h3>
125  *
126  * <p> This section is intended to provide a brief overview of formatting
127  * concepts.  For precise behavioral details, refer to the <a
128  * href="#detail">Details</a> section.
129  *
130  * <h4><a name="syntax">Format String Syntax</a></h4>
131  *
132  * <p> Every method which produces formatted output requires a <i>format
133  * string</i> and an <i>argument list</i>.  The format string is a {@link
134  * String} which may contain fixed text and one or more embedded <i>format
135  * specifiers</i>.  Consider the following example:
136  *
137  * <blockquote><pre>
138  *   Calendar c = ...;
139  *   String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
140  * </pre></blockquote>
141  *
142  * This format string is the first argument to the <tt>format</tt> method.  It
143  * contains three format specifiers "<tt>%1$tm</tt>", "<tt>%1$te</tt>", and
144  * "<tt>%1$tY</tt>" which indicate how the arguments should be processed and
145  * where they should be inserted in the text.  The remaining portions of the
146  * format string are fixed text including <tt>"Dukes Birthday: "</tt> and any
147  * other spaces or punctuation.
148  *
149  * The argument list consists of all arguments passed to the method after the
150  * format string.  In the above example, the argument list is of size one and
151  * consists of the {@link java.util.Calendar Calendar} object <tt>c</tt>.
152  *
153  * <ul>
154  *
155  * <li> The format specifiers for general, character, and numeric types have
156  * the following syntax:
157  *
158  * <blockquote><pre>
159  *   %[argument_index$][flags][width][.precision]conversion
160  * </pre></blockquote>
161  *
162  * <p> The optional <i>argument_index</i> is a decimal integer indicating the
163  * position of the argument in the argument list.  The first argument is
164  * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
165  *
166  * <p> The optional <i>flags</i> is a set of characters that modify the output
167  * format.  The set of valid flags depends on the conversion.
168  *
169  * <p> The optional <i>width</i> is a non-negative decimal integer indicating
170  * the minimum number of characters to be written to the output.
171  *
172  * <p> The optional <i>precision</i> is a non-negative decimal integer usually
173  * used to restrict the number of characters.  The specific behavior depends on
174  * the conversion.
175  *
176  * <p> The required <i>conversion</i> is a character indicating how the
177  * argument should be formatted.  The set of valid conversions for a given
178  * argument depends on the argument's data type.
179  *
180  * <li> The format specifiers for types which are used to represents dates and
181  * times have the following syntax:
182  *
183  * <blockquote><pre>
184  *   %[argument_index$][flags][width]conversion
185  * </pre></blockquote>
186  *
187  * <p> The optional <i>argument_index</i>, <i>flags</i> and <i>width</i> are
188  * defined as above.
189  *
190  * <p> The required <i>conversion</i> is a two character sequence.  The first
191  * character is <tt>'t'</tt> or <tt>'T'</tt>.  The second character indicates
192  * the format to be used.  These characters are similar to but not completely
193  * identical to those defined by GNU <tt>date</tt> and POSIX
194  * <tt>strftime(3c)</tt>.
195  *
196  * <li> The format specifiers which do not correspond to arguments have the
197  * following syntax:
198  *
199  * <blockquote><pre>
200  *   %[flags][width]conversion
201  * </pre></blockquote>
202  *
203  * <p> The optional <i>flags</i> and <i>width</i> is defined as above.
204  *
205  * <p> The required <i>conversion</i> is a character indicating content to be
206  * inserted in the output.
207  *
208  * </ul>
209  *
210  * <h4> Conversions </h4>
211  *
212  * <p> Conversions are divided into the following categories:
213  *
214  * <ol>
215  *
216  * <li> <b>General</b> - may be applied to any argument
217  * type
218  *
219  * <li> <b>Character</b> - may be applied to basic types which represent
220  * Unicode characters: <tt>char</tt>, {@link Character}, <tt>byte</tt>, {@link
221  * Byte}, <tt>short</tt>, and {@link Short}. This conversion may also be
222  * applied to the types <tt>int</tt> and {@link Integer} when {@link
223  * Character#isValidCodePoint} returns <tt>true</tt>
224  *
225  * <li> <b>Numeric</b>
226  *
227  * <ol>
228  *
229  * <li> <b>Integral</b> - may be applied to Java integral types: <tt>byte</tt>,
230  * {@link Byte}, <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link
231  * Integer}, <tt>long</tt>, {@link Long}, and {@link java.math.BigInteger
232  * BigInteger}
233  *
234  * <li><b>Floating Point</b> - may be applied to Java floating-point types:
235  * <tt>float</tt>, {@link Float}, <tt>double</tt>, {@link Double}, and {@link
236  * java.math.BigDecimal BigDecimal}
237  *
238  * </ol>
239  *
240  * <li> <b>Date/Time</b> - may be applied to Java types which are capable of
241  * encoding a date or time: <tt>long</tt>, {@link Long}, {@link Calendar}, and
242  * {@link Date}.
243  *
244  * <li> <b>Percent</b> - produces a literal <tt>'%'</tt>
245  * (<tt>'&#92;u0025'</tt>)
246  *
247  * <li> <b>Line Separator</b> - produces the platform-specific line separator
248  *
249  * </ol>
250  *
251  * <p> The following table summarizes the supported conversions.  Conversions
252  * denoted by an upper-case character (i.e. <tt>'B'</tt>, <tt>'H'</tt>,
253  * <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>, <tt>'G'</tt>,
254  * <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the corresponding
255  * lower-case conversion characters except that the result is converted to
256  * upper case according to the rules of the prevailing {@link java.util.Locale
257  * Locale}.  The result is equivalent to the following invocation of {@link
258  * String#toUpperCase()}
259  *
260  * <pre>
261  *    out.toUpperCase() </pre>
262  *
263  * <table cellpadding=5 summary="genConv">
264  *
265  * <tr><th valign="bottom"> Conversion
266  *     <th valign="bottom"> Argument Category
267  *     <th valign="bottom"> Description
268  *
269  * <tr><td valign="top"> <tt>'b'</tt>, <tt>'B'</tt>
270  *     <td valign="top"> general
271  *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
272  *     "<tt>false</tt>".  If <i>arg</i> is a <tt>boolean</tt> or {@link
273  *     Boolean}, then the result is the string returned by {@link
274  *     String#valueOf(boolean) String.valueOf()}.  Otherwise, the result is
275  *     "true".
276  *
277  * <tr><td valign="top"> <tt>'h'</tt>, <tt>'H'</tt>
278  *     <td valign="top"> general
279  *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
280  *     "<tt>null</tt>".  Otherwise, the result is obtained by invoking
281  *     <tt>Integer.toHexString(arg.hashCode())</tt>.
282  *
283  * <tr><td valign="top"> <tt>'s'</tt>, <tt>'S'</tt>
284  *     <td valign="top"> general
285  *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
286  *     "<tt>null</tt>".  If <i>arg</i> implements {@link Formattable}, then
287  *     {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
288  *     result is obtained by invoking <tt>arg.toString()</tt>.
289  *
290  * <tr><td valign="top"><tt>'c'</tt>, <tt>'C'</tt>
291  *     <td valign="top"> character
292  *     <td> The result is a Unicode character
293  *
294  * <tr><td valign="top"><tt>'d'</tt>
295  *     <td valign="top"> integral
296  *     <td> The result is formatted as a decimal integer
297  *
298  * <tr><td valign="top"><tt>'o'</tt>
299  *     <td valign="top"> integral
300  *     <td> The result is formatted as an octal integer
301  *
302  * <tr><td valign="top"><tt>'x'</tt>, <tt>'X'</tt>
303  *     <td valign="top"> integral
304  *     <td> The result is formatted as a hexadecimal integer
305  *
306  * <tr><td valign="top"><tt>'e'</tt>, <tt>'E'</tt>
307  *     <td valign="top"> floating point
308  *     <td> The result is formatted as a decimal number in computerized
309  *     scientific notation
310  *
311  * <tr><td valign="top"><tt>'f'</tt>
312  *     <td valign="top"> floating point
313  *     <td> The result is formatted as a decimal number
314  *
315  * <tr><td valign="top"><tt>'g'</tt>, <tt>'G'</tt>
316  *     <td valign="top"> floating point
317  *     <td> The result is formatted using computerized scientific notation or
318  *     decimal format, depending on the precision and the value after rounding.
319  *
320  * <tr><td valign="top"><tt>'a'</tt>, <tt>'A'</tt>
321  *     <td valign="top"> floating point
322  *     <td> The result is formatted as a hexadecimal floating-point number with
323  *     a significand and an exponent
324  *
325  * <tr><td valign="top"><tt>'t'</tt>, <tt>'T'</tt>
326  *     <td valign="top"> date/time
327  *     <td> Prefix for date and time conversion characters.  See <a
328  *     href="#dt">Date/Time Conversions</a>.
329  *
330  * <tr><td valign="top"><tt>'%'</tt>
331  *     <td valign="top"> percent
332  *     <td> The result is a literal <tt>'%'</tt> (<tt>'&#92;u0025'</tt>)
333  *
334  * <tr><td valign="top"><tt>'n'</tt>
335  *     <td valign="top"> line separator
336  *     <td> The result is the platform-specific line separator
337  *
338  * </table>
339  *
340  * <p> Any characters not explicitly defined as conversions are illegal and are
341  * reserved for future extensions.
342  *
343  * <h4><a name="dt">Date/Time Conversions</a></h4>
344  *
345  * <p> The following date and time conversion suffix characters are defined for
346  * the <tt>'t'</tt> and <tt>'T'</tt> conversions.  The types are similar to but
347  * not completely identical to those defined by GNU <tt>date</tt> and POSIX
348  * <tt>strftime(3c)</tt>.  Additional conversion types are provided to access
349  * Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds within the
350  * second).
351  *
352  * <p> The following conversion characters are used for formatting times:
353  *
354  * <table cellpadding=5 summary="time">
355  *
356  * <tr><td valign="top"> <tt>'H'</tt>
357  *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
358  *     a leading zero as necessary i.e. <tt>00 - 23</tt>.
359  *
360  * <tr><td valign="top"><tt>'I'</tt>
361  *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
362  *     zero as necessary, i.e.  <tt>01 - 12</tt>.
363  *
364  * <tr><td valign="top"><tt>'k'</tt>
365  *     <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
366  *
367  * <tr><td valign="top"><tt>'l'</tt>
368  *     <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>.
369  *
370  * <tr><td valign="top"><tt>'M'</tt>
371  *     <td> Minute within the hour formatted as two digits with a leading zero
372  *     as necessary, i.e.  <tt>00 - 59</tt>.
373  *
374  * <tr><td valign="top"><tt>'S'</tt>
375  *     <td> Seconds within the minute, formatted as two digits with a leading
376  *     zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
377  *     value required to support leap seconds).
378  *
379  * <tr><td valign="top"><tt>'L'</tt>
380  *     <td> Millisecond within the second formatted as three digits with
381  *     leading zeros as necessary, i.e. <tt>000 - 999</tt>.
382  *
383  * <tr><td valign="top"><tt>'N'</tt>
384  *     <td> Nanosecond within the second, formatted as nine digits with leading
385  *     zeros as necessary, i.e. <tt>000000000 - 999999999</tt>.
386  *
387  * <tr><td valign="top"><tt>'p'</tt>
388  *     <td> Locale-specific {@linkplain
389  *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
390  *     in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>". Use of the conversion
391  *     prefix <tt>'T'</tt> forces this output to upper case.
392  *
393  * <tr><td valign="top"><tt>'z'</tt>
394  *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
395  *     style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
396  *
397  * <tr><td valign="top"><tt>'Z'</tt>
398  *     <td> A string representing the abbreviation for the time zone.  The
399  *     Formatter's locale will supersede the locale of the argument (if any).
400  *
401  * <tr><td valign="top"><tt>'s'</tt>
402  *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
403  *     <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
404  *     <tt>Long.MAX_VALUE/1000</tt>.
405  *
406  * <tr><td valign="top"><tt>'Q'</tt>
407  *     <td> Milliseconds since the beginning of the epoch starting at 1 January
408  *     1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
409  *     <tt>Long.MAX_VALUE</tt>.
410  *
411  * </table>
412  *
413  * <p> The following conversion characters are used for formatting dates:
414  *
415  * <table cellpadding=5 summary="date">
416  *
417  * <tr><td valign="top"><tt>'B'</tt>
418  *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
419  *     full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
420  *
421  * <tr><td valign="top"><tt>'b'</tt>
422  *     <td> Locale-specific {@linkplain
423  *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
424  *     e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
425  *
426  * <tr><td valign="top"><tt>'h'</tt>
427  *     <td> Same as <tt>'b'</tt>.
428  *
429  * <tr><td valign="top"><tt>'A'</tt>
430  *     <td> Locale-specific full name of the {@linkplain
431  *     java.text.DateFormatSymbols#getWeekdays day of the week},
432  *     e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
433  *
434  * <tr><td valign="top"><tt>'a'</tt>
435  *     <td> Locale-specific short name of the {@linkplain
436  *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
437  *     e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
438  *
439  * <tr><td valign="top"><tt>'C'</tt>
440  *     <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
441  *     with leading zero as necessary, i.e. <tt>00 - 99</tt>
442  *
443  * <tr><td valign="top"><tt>'Y'</tt>
444  *     <td> Year, formatted as at least four digits with leading zeros as
445  *     necessary, e.g. <tt>0092</tt> equals <tt>92</tt> CE for the Gregorian
446  *     calendar.
447  *
448  * <tr><td valign="top"><tt>'y'</tt>
449  *     <td> Last two digits of the year, formatted with leading zeros as
450  *     necessary, i.e. <tt>00 - 99</tt>.
451  *
452  * <tr><td valign="top"><tt>'j'</tt>
453  *     <td> Day of year, formatted as three digits with leading zeros as
454  *     necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
455  *
456  * <tr><td valign="top"><tt>'m'</tt>
457  *     <td> Month, formatted as two digits with leading zeros as necessary,
458  *     i.e. <tt>01 - 13</tt>.
459  *
460  * <tr><td valign="top"><tt>'d'</tt>
461  *     <td> Day of month, formatted as two digits with leading zeros as
462  *     necessary, i.e. <tt>01 - 31</tt>
463  *
464  * <tr><td valign="top"><tt>'e'</tt>
465  *     <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt>.
466  *
467  * </table>
468  *
469  * <p> The following conversion characters are used for formatting common
470  * date/time compositions.
471  *
472  * <table cellpadding=5 summary="composites">
473  *
474  * <tr><td valign="top"><tt>'R'</tt>
475  *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
476  *
477  * <tr><td valign="top"><tt>'T'</tt>
478  *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
479  *
480  * <tr><td valign="top"><tt>'r'</tt>
481  *     <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS %Tp"</tt>.
482  *     The location of the morning or afternoon marker (<tt>'%Tp'</tt>) may be
483  *     locale-dependent.
484  *
485  * <tr><td valign="top"><tt>'D'</tt>
486  *     <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
487  *
488  * <tr><td valign="top"><tt>'F'</tt>
489  *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
490  *     complete date formatted as <tt>"%tY-%tm-%td"</tt>.
491  *
492  * <tr><td valign="top"><tt>'c'</tt>
493  *     <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
494  *     e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
495  *
496  * </table>
497  *
498  * <p> Any characters not explicitly defined as date/time conversion suffixes
499  * are illegal and are reserved for future extensions.
500  *
501  * <h4> Flags </h4>
502  *
503  * <p> The following table summarizes the supported flags.  <i>y</i> means the
504  * flag is supported for the indicated argument types.
505  *
506  * <table cellpadding=5 summary="genConv">
507  *
508  * <tr><th valign="bottom"> Flag <th valign="bottom"> General
509  *     <th valign="bottom"> Character <th valign="bottom"> Integral
510  *     <th valign="bottom"> Floating Point
511  *     <th valign="bottom"> Date/Time
512  *     <th valign="bottom"> Description
513  *
514  * <tr><td> '-' <td align="center" valign="top"> y
515  *     <td align="center" valign="top"> y
516  *     <td align="center" valign="top"> y
517  *     <td align="center" valign="top"> y
518  *     <td align="center" valign="top"> y
519  *     <td> The result will be left-justified.
520  *
521  * <tr><td> '#' <td align="center" valign="top"> y<sup>1</sup>
522  *     <td align="center" valign="top"> -
523  *     <td align="center" valign="top"> y<sup>3</sup>
524  *     <td align="center" valign="top"> y
525  *     <td align="center" valign="top"> -
526  *     <td> The result should use a conversion-dependent alternate form
527  *
528  * <tr><td> '+' <td align="center" valign="top"> -
529  *     <td align="center" valign="top"> -
530  *     <td align="center" valign="top"> y<sup>4</sup>
531  *     <td align="center" valign="top"> y
532  *     <td align="center" valign="top"> -
533  *     <td> The result will always include a sign
534  *
535  * <tr><td> '&nbsp;&nbsp;' <td align="center" valign="top"> -
536  *     <td align="center" valign="top"> -
537  *     <td align="center" valign="top"> y<sup>4</sup>
538  *     <td align="center" valign="top"> y
539  *     <td align="center" valign="top"> -
540  *     <td> The result will include a leading space for positive values
541  *
542  * <tr><td> '0' <td align="center" valign="top"> -
543  *     <td align="center" valign="top"> -
544  *     <td align="center" valign="top"> y
545  *     <td align="center" valign="top"> y
546  *     <td align="center" valign="top"> -
547  *     <td> The result will be zero-padded
548  *
549  * <tr><td> ',' <td align="center" valign="top"> -
550  *     <td align="center" valign="top"> -
551  *     <td align="center" valign="top"> y<sup>2</sup>
552  *     <td align="center" valign="top"> y<sup>5</sup>
553  *     <td align="center" valign="top"> -
554  *     <td> The result will include locale-specific {@linkplain
555  *     java.text.DecimalFormatSymbols#getGroupingSeparator grouping separators}
556  *
557  * <tr><td> '(' <td align="center" valign="top"> -
558  *     <td align="center" valign="top"> -
559  *     <td align="center" valign="top"> y<sup>4</sup>
560  *     <td align="center" valign="top"> y<sup>5</sup>
561  *     <td align="center"> -
562  *     <td> The result will enclose negative numbers in parentheses
563  *
564  * </table>
565  *
566  * <p> <sup>1</sup> Depends on the definition of {@link Formattable}.
567  *
568  * <p> <sup>2</sup> For <tt>'d'</tt> conversion only.
569  *
570  * <p> <sup>3</sup> For <tt>'o'</tt>, <tt>'x'</tt>, and <tt>'X'</tt>
571  * conversions only.
572  *
573  * <p> <sup>4</sup> For <tt>'d'</tt>, <tt>'o'</tt>, <tt>'x'</tt>, and
574  * <tt>'X'</tt> conversions applied to {@link java.math.BigInteger BigInteger}
575  * or <tt>'d'</tt> applied to <tt>byte</tt>, {@link Byte}, <tt>short</tt>, {@link
576  * Short}, <tt>int</tt> and {@link Integer}, <tt>long</tt>, and {@link Long}.
577  *
578  * <p> <sup>5</sup> For <tt>'e'</tt>, <tt>'E'</tt>, <tt>'f'</tt>,
579  * <tt>'g'</tt>, and <tt>'G'</tt> conversions only.
580  *
581  * <p> Any characters not explicitly defined as flags are illegal and are
582  * reserved for future extensions.
583  *
584  * <h4> Width </h4>
585  *
586  * <p> The width is the minimum number of characters to be written to the
587  * output.  For the line separator conversion, width is not applicable; if it
588  * is provided, an exception will be thrown.
589  *
590  * <h4> Precision </h4>
591  *
592  * <p> For general argument types, the precision is the maximum number of
593  * characters to be written to the output.
594  *
595  * <p> For the floating-point conversions <tt>'e'</tt>, <tt>'E'</tt>, and
596  * <tt>'f'</tt> the precision is the number of digits after the decimal
597  * separator.  If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the
598  * precision is the total number of digits in the resulting magnitude after
599  * rounding.  If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the
600  * precision must not be specified.
601  *
602  * <p> For character, integral, and date/time argument types and the percent
603  * and line separator conversions, the precision is not applicable; if a
604  * precision is provided, an exception will be thrown.
605  *
606  * <h4> Argument Index </h4>
607  *
608  * <p> The argument index is a decimal integer indicating the position of the
609  * argument in the argument list.  The first argument is referenced by
610  * "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
611  *
612  * <p> Another way to reference arguments by position is to use the
613  * <tt>'&lt;'</tt> (<tt>'&#92;u003c'</tt>) flag, which causes the argument for
614  * the previous format specifier to be re-used.  For example, the following two
615  * statements would produce identical strings:
616  *
617  * <blockquote><pre>
618  *   Calendar c = ...;
619  *   String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
620  *
621  *   String s2 = String.format("Duke's Birthday: %1$tm %&lt;te,%&lt;tY", c);
622  * </pre></blockquote>
623  *
624  * <hr>
625  * <h3><a name="detail">Details</a></h3>
626  *
627  * <p> This section is intended to provide behavioral details for formatting,
628  * including conditions and exceptions, supported data types, localization, and
629  * interactions between flags, conversions, and data types.  For an overview of
630  * formatting concepts, refer to the <a href="#summary">Summary</a>
631  *
632  * <p> Any characters not explicitly defined as conversions, date/time
633  * conversion suffixes, or flags are illegal and are reserved for
634  * future extensions.  Use of such a character in a format string will
635  * cause an {@link UnknownFormatConversionException} or {@link
636  * UnknownFormatFlagsException} to be thrown.
637  *
638  * <p> If the format specifier contains a width or precision with an invalid
639  * value or which is otherwise unsupported, then a {@link
640  * IllegalFormatWidthException} or {@link IllegalFormatPrecisionException}
641  * respectively will be thrown.
642  *
643  * <p> If a format specifier contains a conversion character that is not
644  * applicable to the corresponding argument, then an {@link
645  * IllegalFormatConversionException} will be thrown.
646  *
647  * <p> All specified exceptions may be thrown by any of the <tt>format</tt>
648  * methods of <tt>Formatter</tt> as well as by any <tt>format</tt> convenience
649  * methods such as {@link String#format(String,Object...) String.format} and
650  * {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
651  *
652  * <p> Conversions denoted by an upper-case character (i.e. <tt>'B'</tt>,
653  * <tt>'H'</tt>, <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>,
654  * <tt>'G'</tt>, <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the
655  * corresponding lower-case conversion characters except that the result is
656  * converted to upper case according to the rules of the prevailing {@link
657  * java.util.Locale Locale}.  The result is equivalent to the following
658  * invocation of {@link String#toUpperCase()}
659  *
660  * <pre>
661  *    out.toUpperCase() </pre>
662  *
663  * <h4><a name="dgen">General</a></h4>
664  *
665  * <p> The following general conversions may be applied to any argument type:
666  *
667  * <table cellpadding=5 summary="dgConv">
668  *
669  * <tr><td valign="top"> <tt>'b'</tt>
670  *     <td valign="top"> <tt>'&#92;u0062'</tt>
671  *     <td> Produces either "<tt>true</tt>" or "<tt>false</tt>" as returned by
672  *     {@link Boolean#toString(boolean)}.
673  *
674  *     <p> If the argument is <tt>null</tt>, then the result is
675  *     "<tt>false</tt>".  If the argument is a <tt>boolean</tt> or {@link
676  *     Boolean}, then the result is the string returned by {@link
677  *     String#valueOf(boolean) String.valueOf()}.  Otherwise, the result is
678  *     "<tt>true</tt>".
679  *
680  *     <p> If the <tt>'#'</tt> flag is given, then a {@link
681  *     FormatFlagsConversionMismatchException} will be thrown.
682  *
683  * <tr><td valign="top"> <tt>'B'</tt>
684  *     <td valign="top"> <tt>'&#92;u0042'</tt>
685  *     <td> The upper-case variant of <tt>'b'</tt>.
686  *
687  * <tr><td valign="top"> <tt>'h'</tt>
688  *     <td valign="top"> <tt>'&#92;u0068'</tt>
689  *     <td> Produces a string representing the hash code value of the object.
690  *
691  *     <p> If the argument, <i>arg</i> is <tt>null</tt>, then the
692  *     result is "<tt>null</tt>".  Otherwise, the result is obtained
693  *     by invoking <tt>Integer.toHexString(arg.hashCode())</tt>.
694  *
695  *     <p> If the <tt>'#'</tt> flag is given, then a {@link
696  *     FormatFlagsConversionMismatchException} will be thrown.
697  *
698  * <tr><td valign="top"> <tt>'H'</tt>
699  *     <td valign="top"> <tt>'&#92;u0048'</tt>
700  *     <td> The upper-case variant of <tt>'h'</tt>.
701  *
702  * <tr><td valign="top"> <tt>'s'</tt>
703  *     <td valign="top"> <tt>'&#92;u0073'</tt>
704  *     <td> Produces a string.
705  *
706  *     <p> If the argument is <tt>null</tt>, then the result is
707  *     "<tt>null</tt>".  If the argument implements {@link Formattable}, then
708  *     its {@link Formattable#formatTo formatTo} method is invoked.
709  *     Otherwise, the result is obtained by invoking the argument's
710  *     <tt>toString()</tt> method.
711  *
712  *     <p> If the <tt>'#'</tt> flag is given and the argument is not a {@link
713  *     Formattable} , then a {@link FormatFlagsConversionMismatchException}
714  *     will be thrown.
715  *
716  * <tr><td valign="top"> <tt>'S'</tt>
717  *     <td valign="top"> <tt>'&#92;u0053'</tt>
718  *     <td> The upper-case variant of <tt>'s'</tt>.
719  *
720  * </table>
721  *
722  * <p> The following <a name="dFlags">flags</a> apply to general conversions:
723  *
724  * <table cellpadding=5 summary="dFlags">
725  *
726  * <tr><td valign="top"> <tt>'-'</tt>
727  *     <td valign="top"> <tt>'&#92;u002d'</tt>
728  *     <td> Left justifies the output.  Spaces (<tt>'&#92;u0020'</tt>) will be
729  *     added at the end of the converted value as required to fill the minimum
730  *     width of the field.  If the width is not provided, then a {@link
731  *     MissingFormatWidthException} will be thrown.  If this flag is not given
732  *     then the output will be right-justified.
733  *
734  * <tr><td valign="top"> <tt>'#'</tt>
735  *     <td valign="top"> <tt>'&#92;u0023'</tt>
736  *     <td> Requires the output use an alternate form.  The definition of the
737  *     form is specified by the conversion.
738  *
739  * </table>
740  *
741  * <p> The <a name="genWidth">width</a> is the minimum number of characters to
742  * be written to the
743  * output.  If the length of the converted value is less than the width then
744  * the output will be padded by <tt>'&nbsp;&nbsp;'</tt> (<tt>&#92;u0020'</tt>)
745  * until the total number of characters equals the width.  The padding is on
746  * the left by default.  If the <tt>'-'</tt> flag is given, then the padding
747  * will be on the right.  If the width is not specified then there is no
748  * minimum.
749  *
750  * <p> The precision is the maximum number of characters to be written to the
751  * output.  The precision is applied before the width, thus the output will be
752  * truncated to <tt>precision</tt> characters even if the width is greater than
753  * the precision.  If the precision is not specified then there is no explicit
754  * limit on the number of characters.
755  *
756  * <h4><a name="dchar">Character</a></h4>
757  *
758  * This conversion may be applied to <tt>char</tt> and {@link Character}.  It
759  * may also be applied to the types <tt>byte</tt>, {@link Byte},
760  * <tt>short</tt>, and {@link Short}, <tt>int</tt> and {@link Integer} when
761  * {@link Character#isValidCodePoint} returns <tt>true</tt>.  If it returns
762  * <tt>false</tt> then an {@link IllegalFormatCodePointException} will be
763  * thrown.
764  *
765  * <table cellpadding=5 summary="charConv">
766  *
767  * <tr><td valign="top"> <tt>'c'</tt>
768  *     <td valign="top"> <tt>'&#92;u0063'</tt>
769  *     <td> Formats the argument as a Unicode character as described in <a
770  *     href="../lang/Character.html#unicode">Unicode Character
771  *     Representation</a>.  This may be more than one 16-bit <tt>char</tt> in
772  *     the case where the argument represents a supplementary character.
773  *
774  *     <p> If the <tt>'#'</tt> flag is given, then a {@link
775  *     FormatFlagsConversionMismatchException} will be thrown.
776  *
777  * <tr><td valign="top"> <tt>'C'</tt>
778  *     <td valign="top"> <tt>'&#92;u0043'</tt>
779  *     <td> The upper-case variant of <tt>'c'</tt>.
780  *
781  * </table>
782  *
783  * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
784  * conversions</a> applies.  If the <tt>'#'</tt> flag is given, then a {@link
785  * FormatFlagsConversionMismatchException} will be thrown.
786  *
787  * <p> The width is defined as for <a href="#genWidth">General conversions</a>.
788  *
789  * <p> The precision is not applicable.  If the precision is specified then an
790  * {@link IllegalFormatPrecisionException} will be thrown.
791  *
792  * <h4><a name="dnum">Numeric</a></h4>
793  *
794  * <p> Numeric conversions are divided into the following categories:
795  *
796  * <ol>
797  *
798  * <li> <a href="#dnint"><b>Byte, Short, Integer, and Long</b></a>
799  *
800  * <li> <a href="#dnbint"><b>BigInteger</b></a>
801  *
802  * <li> <a href="#dndec"><b>Float and Double</b></a>
803  *
804  * <li> <a href="#dndec"><b>BigDecimal</b></a>
805  *
806  * </ol>
807  *
808  * <p> Numeric types will be formatted according to the following algorithm:
809  *
810  * <p><b><a name="l10n algorithm"> Number Localization Algorithm</a></b>
811  *
812  * <p> After digits are obtained for the integer part, fractional part, and
813  * exponent (as appropriate for the data type), the following transformation
814  * is applied:
815  *
816  * <ol>
817  *
818  * <li> Each digit character <i>d</i> in the string is replaced by a
819  * locale-specific digit computed relative to the current locale's
820  * {@linkplain java.text.DecimalFormatSymbols#getZeroDigit() zero digit}
821  * <i>z</i>; that is <i>d&nbsp;-&nbsp;</i> <tt>'0'</tt>
822  * <i>&nbsp;+&nbsp;z</i>.
823  *
824  * <li> If a decimal separator is present, a locale-specific {@linkplain
825  * java.text.DecimalFormatSymbols#getDecimalSeparator decimal separator} is
826  * substituted.
827  *
828  * <li> If the <tt>','</tt> (<tt>'&#92;u002c'</tt>)
829  * <a name="l10n group">flag</a> is given, then the locale-specific {@linkplain
830  * java.text.DecimalFormatSymbols#getGroupingSeparator grouping separator} is
831  * inserted by scanning the integer part of the string from least significant
832  * to most significant digits and inserting a separator at intervals defined by
833  * the locale's {@linkplain java.text.DecimalFormat#getGroupingSize() grouping
834  * size}.
835  *
836  * <li> If the <tt>'0'</tt> flag is given, then the locale-specific {@linkplain
837  * java.text.DecimalFormatSymbols#getZeroDigit() zero digits} are inserted
838  * after the sign character, if any, and before the first non-zero digit, until
839  * the length of the string is equal to the requested field width.
840  *
841  * <li> If the value is negative and the <tt>'('</tt> flag is given, then a
842  * <tt>'('</tt> (<tt>'&#92;u0028'</tt>) is prepended and a <tt>')'</tt>
843  * (<tt>'&#92;u0029'</tt>) is appended.
844  *
845  * <li> If the value is negative (or floating-point negative zero) and
846  * <tt>'('</tt> flag is not given, then a <tt>'-'</tt> (<tt>'&#92;u002d'</tt>)
847  * is prepended.
848  *
849  * <li> If the <tt>'+'</tt> flag is given and the value is positive or zero (or
850  * floating-point positive zero), then a <tt>'+'</tt> (<tt>'&#92;u002b'</tt>)
851  * will be prepended.
852  *
853  * </ol>
854  *
855  * <p> If the value is NaN or positive infinity the literal strings "NaN" or
856  * "Infinity" respectively, will be output.  If the value is negative infinity,
857  * then the output will be "(Infinity)" if the <tt>'('</tt> flag is given
858  * otherwise the output will be "-Infinity".  These values are not localized.
859  *
860  * <p><a name="dnint"><b> Byte, Short, Integer, and Long </b></a>
861  *
862  * <p> The following conversions may be applied to <tt>byte</tt>, {@link Byte},
863  * <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link Integer},
864  * <tt>long</tt>, and {@link Long}.
865  *
866  * <table cellpadding=5 summary="IntConv">
867  *
868  * <tr><td valign="top"> <tt>'d'</tt>
869  *     <td valign="top"> <tt>'&#92;u0054'</tt>
870  *     <td> Formats the argument as a decimal integer. The <a
871  *     href="#l10n algorithm">localization algorithm</a> is applied.
872  *
873  *     <p> If the <tt>'0'</tt> flag is given and the value is negative, then
874  *     the zero padding will occur after the sign.
875  *
876  *     <p> If the <tt>'#'</tt> flag is given then a {@link
877  *     FormatFlagsConversionMismatchException} will be thrown.
878  *
879  * <tr><td valign="top"> <tt>'o'</tt>
880  *     <td valign="top"> <tt>'&#92;u006f'</tt>
881  *     <td> Formats the argument as an integer in base eight.  No localization
882  *     is applied.
883  *
884  *     <p> If <i>x</i> is negative then the result will be an unsigned value
885  *     generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
886  *     number of bits in the type as returned by the static <tt>SIZE</tt> field
887  *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
888  *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
889  *     classes as appropriate.
890  *
891  *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
892  *     with the radix indicator <tt>'0'</tt>.
893  *
894  *     <p> If the <tt>'0'</tt> flag is given then the output will be padded
895  *     with leading zeros to the field width following any indication of sign.
896  *
897  *     <p> If <tt>'('</tt>, <tt>'+'</tt>, '&nbsp&nbsp;', or <tt>','</tt> flags
898  *     are given then a {@link FormatFlagsConversionMismatchException} will be
899  *     thrown.
900  *
901  * <tr><td valign="top"> <tt>'x'</tt>
902  *     <td valign="top"> <tt>'&#92;u0078'</tt>
903  *     <td> Formats the argument as an integer in base sixteen. No
904  *     localization is applied.
905  *
906  *     <p> If <i>x</i> is negative then the result will be an unsigned value
907  *     generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
908  *     number of bits in the type as returned by the static <tt>SIZE</tt> field
909  *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
910  *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
911  *     classes as appropriate.
912  *
913  *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
914  *     with the radix indicator <tt>"0x"</tt>.
915  *
916  *     <p> If the <tt>'0'</tt> flag is given then the output will be padded to
917  *     the field width with leading zeros after the radix indicator or sign (if
918  *     present).
919  *
920  *     <p> If <tt>'('</tt>, <tt>'&nbsp;&nbsp;'</tt>, <tt>'+'</tt>, or
921  *     <tt>','</tt> flags are given then a {@link
922  *     FormatFlagsConversionMismatchException} will be thrown.
923  *
924  * <tr><td valign="top"> <tt>'X'</tt>
925  *     <td valign="top"> <tt>'&#92;u0058'</tt>
926  *     <td> The upper-case variant of <tt>'x'</tt>.  The entire string
927  *     representing the number will be converted to {@linkplain
928  *     String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
929  *     all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
930  *     (<tt>'&#92;u0061'</tt> -  <tt>'&#92;u0066'</tt>).
931  *
932  * </table>
933  *
934  * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
935  * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
936  * contain the radix indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
937  * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
938  * and the value.
939  *
940  * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
941  * before the sign.
942  *
943  * <p> The following <a name="intFlags">flags</a> apply to numeric integral
944  * conversions:
945  *
946  * <table cellpadding=5 summary="intFlags">
947  *
948  * <tr><td valign="top"> <tt>'+'</tt>
949  *     <td valign="top"> <tt>'&#92;u002b'</tt>
950  *     <td> Requires the output to include a positive sign for all positive
951  *     numbers.  If this flag is not given then only negative values will
952  *     include a sign.
953  *
954  *     <p> If both the <tt>'+'</tt> and <tt>'&nbsp;&nbsp;'</tt> flags are given
955  *     then an {@link IllegalFormatFlagsException} will be thrown.
956  *
957  * <tr><td valign="top"> <tt>'&nbsp;&nbsp;'</tt>
958  *     <td valign="top"> <tt>'&#92;u0020'</tt>
959  *     <td> Requires the output to include a single extra space
960  *     (<tt>'&#92;u0020'</tt>) for non-negative values.
961  *
962  *     <p> If both the <tt>'+'</tt> and <tt>'&nbsp;&nbsp;'</tt> flags are given
963  *     then an {@link IllegalFormatFlagsException} will be thrown.
964  *
965  * <tr><td valign="top"> <tt>'0'</tt>
966  *     <td valign="top"> <tt>'&#92;u0030'</tt>
967  *     <td> Requires the output to be padded with leading {@linkplain
968  *     java.text.DecimalFormatSymbols#getZeroDigit zeros} to the minimum field
969  *     width following any sign or radix indicator except when converting NaN
970  *     or infinity.  If the width is not provided, then a {@link
971  *     MissingFormatWidthException} will be thrown.
972  *
973  *     <p> If both the <tt>'-'</tt> and <tt>'0'</tt> flags are given then an
974  *     {@link IllegalFormatFlagsException} will be thrown.
975  *
976  * <tr><td valign="top"> <tt>','</tt>
977  *     <td valign="top"> <tt>'&#92;u002c'</tt>
978  *     <td> Requires the output to include the locale-specific {@linkplain
979  *     java.text.DecimalFormatSymbols#getGroupingSeparator group separators} as
980  *     described in the <a href="#l10n group">"group" section</a> of the
981  *     localization algorithm.
982  *
983  * <tr><td valign="top"> <tt>'('</tt>
984  *     <td valign="top"> <tt>'&#92;u0028'</tt>
985  *     <td> Requires the output to prepend a <tt>'('</tt>
986  *     (<tt>'&#92;u0028'</tt>) and append a <tt>')'</tt>
987  *     (<tt>'&#92;u0029'</tt>) to negative values.
988  *
989  * </table>
990  *
991  * <p> If no <a name="intdFlags">flags</a> are given the default formatting is
992  * as follows:
993  *
994  * <ul>
995  *
996  * <li> The output is right-justified within the <tt>width</tt>
997  *
998  * <li> Negative numbers begin with a <tt>'-'</tt> (<tt>'&#92;u002d'</tt>)
999  *
1000 * <li> Positive numbers and zero do not include a sign or extra leading
1001 * space
1002 *
1003 * <li> No grouping separators are included
1004 *
1005 * </ul>
1006 *
1007 * <p> The <a name="intWidth">width</a> is the minimum number of characters to
1008 * be written to the output.  This includes any signs, digits, grouping
1009 * separators, radix indicator, and parentheses.  If the length of the
1010 * converted value is less than the width then the output will be padded by
1011 * spaces (<tt>'&#92;u0020'</tt>) until the total number of characters equals
1012 * width.  The padding is on the left by default.  If <tt>'-'</tt> flag is
1013 * given then the padding will be on the right.  If width is not specified then
1014 * there is no minimum.
1015 *
1016 * <p> The precision is not applicable.  If precision is specified then an
1017 * {@link IllegalFormatPrecisionException} will be thrown.
1018 *
1019 * <p><a name="dnbint"><b> BigInteger </b></a>
1020 *
1021 * <p> The following conversions may be applied to {@link
1022 * java.math.BigInteger}.
1023 *
1024 * <table cellpadding=5 summary="BIntConv">
1025 *
1026 * <tr><td valign="top"> <tt>'d'</tt>
1027 *     <td valign="top"> <tt>'&#92;u0054'</tt>
1028 *     <td> Requires the output to be formatted as a decimal integer. The <a
1029 *     href="#l10n algorithm">localization algorithm</a> is applied.
1030 *
1031 *     <p> If the <tt>'#'</tt> flag is given {@link
1032 *     FormatFlagsConversionMismatchException} will be thrown.
1033 *
1034 * <tr><td valign="top"> <tt>'o'</tt>
1035 *     <td valign="top"> <tt>'&#92;u006f'</tt>
1036 *     <td> Requires the output to be formatted as an integer in base eight.
1037 *     No localization is applied.
1038 *
1039 *     <p> If <i>x</i> is negative then the result will be a signed value
1040 *     beginning with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).  Signed output is
1041 *     allowed for this type because unlike the primitive types it is not
1042 *     possible to create an unsigned equivalent without assuming an explicit
1043 *     data-type size.
1044 *
1045 *     <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1046 *     then the result will begin with <tt>'+'</tt> (<tt>'&#92;u002b'</tt>).
1047 *
1048 *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
1049 *     with <tt>'0'</tt> prefix.
1050 *
1051 *     <p> If the <tt>'0'</tt> flag is given then the output will be padded
1052 *     with leading zeros to the field width following any indication of sign.
1053 *
1054 *     <p> If the <tt>','</tt> flag is given then a {@link
1055 *     FormatFlagsConversionMismatchException} will be thrown.
1056 *
1057 * <tr><td valign="top"> <tt>'x'</tt>
1058 *     <td valign="top"> <tt>'&#92;u0078'</tt>
1059 *     <td> Requires the output to be formatted as an integer in base
1060 *     sixteen.  No localization is applied.
1061 *
1062 *     <p> If <i>x</i> is negative then the result will be a signed value
1063 *     beginning with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).  Signed output is
1064 *     allowed for this type because unlike the primitive types it is not
1065 *     possible to create an unsigned equivalent without assuming an explicit
1066 *     data-type size.
1067 *
1068 *     <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1069 *     then the result will begin with <tt>'+'</tt> (<tt>'&#92;u002b'</tt>).
1070 *
1071 *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
1072 *     with the radix indicator <tt>"0x"</tt>.
1073 *
1074 *     <p> If the <tt>'0'</tt> flag is given then the output will be padded to
1075 *     the field width with leading zeros after the radix indicator or sign (if
1076 *     present).
1077 *
1078 *     <p> If the <tt>','</tt> flag is given then a {@link
1079 *     FormatFlagsConversionMismatchException} will be thrown.
1080 *
1081 * <tr><td valign="top"> <tt>'X'</tt>
1082 *     <td valign="top"> <tt>'&#92;u0058'</tt>
1083 *     <td> The upper-case variant of <tt>'x'</tt>.  The entire string
1084 *     representing the number will be converted to {@linkplain
1085 *     String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
1086 *     all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
1087 *     (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1088 *
1089 * </table>
1090 *
1091 * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
1092 * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
1093 * contain the base indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
1094 * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
1095 * and the value.
1096 *
1097 * <p> If the <tt>'0'</tt> flag is given and the value is negative, then the
1098 * zero padding will occur after the sign.
1099 *
1100 * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
1101 * before the sign.
1102 *
1103 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1104 * Long apply.  The <a href="#intdFlags">default behavior</a> when no flags are
1105 * given is the same as for Byte, Short, Integer, and Long.
1106 *
1107 * <p> The specification of <a href="#intWidth">width</a> is the same as
1108 * defined for Byte, Short, Integer, and Long.
1109 *
1110 * <p> The precision is not applicable.  If precision is specified then an
1111 * {@link IllegalFormatPrecisionException} will be thrown.
1112 *
1113 * <p><a name="dndec"><b> Float and Double</b></a>
1114 *
1115 * <p> The following conversions may be applied to <tt>float</tt>, {@link
1116 * Float}, <tt>double</tt> and {@link Double}.
1117 *
1118 * <table cellpadding=5 summary="floatConv">
1119 *
1120 * <tr><td valign="top"> <tt>'e'</tt>
1121 *     <td valign="top"> <tt>'&#92;u0065'</tt>
1122 *     <td> Requires the output to be formatted using <a
1123 *     name="scientific">computerized scientific notation</a>.  The <a
1124 *     href="#l10n algorithm">localization algorithm</a> is applied.
1125 *
1126 *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1127 *
1128 *     <p> If <i>m</i> is NaN or infinite, the literal strings "NaN" or
1129 *     "Infinity", respectively, will be output.  These values are not
1130 *     localized.
1131 *
1132 *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1133 *     will be <tt>"+00"</tt>.
1134 *
1135 *     <p> Otherwise, the result is a string that represents the sign and
1136 *     magnitude (absolute value) of the argument.  The formatting of the sign
1137 *     is described in the <a href="#l10n algorithm">localization
1138 *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1139 *     value.
1140 *
1141 *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1142 *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1143 *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1144 *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1145 *     integer part of <i>a</i>, as a single decimal digit, followed by the
1146 *     decimal separator followed by decimal digits representing the fractional
1147 *     part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1148 *     (<tt>'&#92;u0065'</tt>), followed by the sign of the exponent, followed
1149 *     by a representation of <i>n</i> as a decimal integer, as produced by the
1150 *     method {@link Long#toString(long, int)}, and zero-padded to include at
1151 *     least two digits.
1152 *
1153 *     <p> The number of digits in the result for the fractional part of
1154 *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1155 *     specified then the default value is <tt>6</tt>. If the precision is less
1156 *     than the number of digits which would appear after the decimal point in
1157 *     the string returned by {@link Float#toString(float)} or {@link
1158 *     Double#toString(double)} respectively, then the value will be rounded
1159 *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1160 *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1161 *     For a canonical representation of the value, use {@link
1162 *     Float#toString(float)} or {@link Double#toString(double)} as
1163 *     appropriate.
1164 *
1165 *     <p>If the <tt>','</tt> flag is given, then an {@link
1166 *     FormatFlagsConversionMismatchException} will be thrown.
1167 *
1168 * <tr><td valign="top"> <tt>'E'</tt>
1169 *     <td valign="top"> <tt>'&#92;u0045'</tt>
1170 *     <td> The upper-case variant of <tt>'e'</tt>.  The exponent symbol
1171 *     will be <tt>'E'</tt> (<tt>'&#92;u0045'</tt>).
1172 *
1173 * <tr><td valign="top"> <tt>'g'</tt>
1174 *     <td valign="top"> <tt>'&#92;u0067'</tt>
1175 *     <td> Requires the output to be formatted in general scientific notation
1176 *     as described below. The <a href="#l10n algorithm">localization
1177 *     algorithm</a> is applied.
1178 *
1179 *     <p> After rounding for the precision, the formatting of the resulting
1180 *     magnitude <i>m</i> depends on its value.
1181 *
1182 *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1183 *     than 10<sup>precision</sup> then it is represented in <i><a
1184 *     href="#decimal">decimal format</a></i>.
1185 *
1186 *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1187 *     10<sup>precision</sup>, then it is represented in <i><a
1188 *     href="#scientific">computerized scientific notation</a></i>.
1189 *
1190 *     <p> The total number of significant digits in <i>m</i> is equal to the
1191 *     precision.  If the precision is not specified, then the default value is
1192 *     <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1193 *     <tt>1</tt>.
1194 *
1195 *     <p> If the <tt>'#'</tt> flag is given then an {@link
1196 *     FormatFlagsConversionMismatchException} will be thrown.
1197 *
1198 * <tr><td valign="top"> <tt>'G'</tt>
1199 *     <td valign="top"> <tt>'&#92;u0047'</tt>
1200 *     <td> The upper-case variant of <tt>'g'</tt>.
1201 *
1202 * <tr><td valign="top"> <tt>'f'</tt>
1203 *     <td valign="top"> <tt>'&#92;u0066'</tt>
1204 *     <td> Requires the output to be formatted using <a name="decimal">decimal
1205 *     format</a>.  The <a href="#l10n algorithm">localization algorithm</a> is
1206 *     applied.
1207 *
1208 *     <p> The result is a string that represents the sign and magnitude
1209 *     (absolute value) of the argument.  The formatting of the sign is
1210 *     described in the <a href="#l10n algorithm">localization
1211 *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1212 *     value.
1213 *
1214 *     <p> If <i>m</i> NaN or infinite, the literal strings "NaN" or
1215 *     "Infinity", respectively, will be output.  These values are not
1216 *     localized.
1217 *
1218 *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1219 *     leading zeroes, followed by the decimal separator followed by one or
1220 *     more decimal digits representing the fractional part of <i>m</i>.
1221 *
1222 *     <p> The number of digits in the result for the fractional part of
1223 *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1224 *     specified then the default value is <tt>6</tt>. If the precision is less
1225 *     than the number of digits which would appear after the decimal point in
1226 *     the string returned by {@link Float#toString(float)} or {@link
1227 *     Double#toString(double)} respectively, then the value will be rounded
1228 *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1229 *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1230 *     For a canonical representation of the value,use {@link
1231 *     Float#toString(float)} or {@link Double#toString(double)} as
1232 *     appropriate.
1233 *
1234 * <tr><td valign="top"> <tt>'a'</tt>
1235 *     <td valign="top"> <tt>'&#92;u0061'</tt>
1236 *     <td> Requires the output to be formatted in hexadecimal exponential
1237 *     form.  No localization is applied.
1238 *
1239 *     <p> The result is a string that represents the sign and magnitude
1240 *     (absolute value) of the argument <i>x</i>.
1241 *
1242 *     <p> If <i>x</i> is negative or a negative-zero value then the result
1243 *     will begin with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).
1244 *
1245 *     <p> If <i>x</i> is positive or a positive-zero value and the
1246 *     <tt>'+'</tt> flag is given then the result will begin with <tt>'+'</tt>
1247 *     (<tt>'&#92;u002b'</tt>).
1248 *
1249 *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1250 *
1251 *     <ul>
1252 *
1253 *     <li> If the value is NaN or infinite, the literal strings "NaN" or
1254 *     "Infinity", respectively, will be output.
1255 *
1256 *     <li> If <i>m</i> is zero then it is represented by the string
1257 *     <tt>"0x0.0p0"</tt>.
1258 *
1259 *     <li> If <i>m</i> is a <tt>double</tt> value with a normalized
1260 *     representation then substrings are used to represent the significand and
1261 *     exponent fields.  The significand is represented by the characters
1262 *     <tt>"0x1."</tt> followed by the hexadecimal representation of the rest
1263 *     of the significand as a fraction.  The exponent is represented by
1264 *     <tt>'p'</tt> (<tt>'&#92;u0070'</tt>) followed by a decimal string of the
1265 *     unbiased exponent as if produced by invoking {@link
1266 *     Integer#toString(int) Integer.toString} on the exponent value.
1267 *
1268 *     <li> If <i>m</i> is a <tt>double</tt> value with a subnormal
1269 *     representation then the significand is represented by the characters
1270 *     <tt>'0x0.'</tt> followed by the hexadecimal representation of the rest
1271 *     of the significand as a fraction.  The exponent is represented by
1272 *     <tt>'p-1022'</tt>.  Note that there must be at least one nonzero digit
1273 *     in a subnormal significand.
1274 *
1275 *     </ul>
1276 *
1277 *     <p> If the <tt>'('</tt> or <tt>','</tt> flags are given, then a {@link
1278 *     FormatFlagsConversionMismatchException} will be thrown.
1279 *
1280 * <tr><td valign="top"> <tt>'A'</tt>
1281 *     <td valign="top"> <tt>'&#92;u0041'</tt>
1282 *     <td> The upper-case variant of <tt>'a'</tt>.  The entire string
1283 *     representing the number will be converted to upper case including the
1284 *     <tt>'x'</tt> (<tt>'&#92;u0078'</tt>) and <tt>'p'</tt>
1285 *     (<tt>'&#92;u0070'</tt> and all hexadecimal digits <tt>'a'</tt> -
1286 *     <tt>'f'</tt> (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1287 *
1288 * </table>
1289 *
1290 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1291 * Long apply.
1292 *
1293 * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1294 * always be present.
1295 *
1296 * <p> If no <a name="floatdFlags">flags</a> are given the default formatting
1297 * is as follows:
1298 *
1299 * <ul>
1300 *
1301 * <li> The output is right-justified within the <tt>width</tt>
1302 *
1303 * <li> Negative numbers begin with a <tt>'-'</tt>
1304 *
1305 * <li> Positive numbers and positive zero do not include a sign or extra
1306 * leading space
1307 *
1308 * <li> No grouping separators are included
1309 *
1310 * <li> The decimal separator will only appear if a digit follows it
1311 *
1312 * </ul>
1313 *
1314 * <p> The <a name="floatDWidth">width</a> is the minimum number of characters
1315 * to be written to the output.  This includes any signs, digits, grouping
1316 * separators, decimal separators, exponential symbol, radix indicator,
1317 * parentheses, and strings representing infinity and NaN as applicable.  If
1318 * the length of the converted value is less than the width then the output
1319 * will be padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1320 * characters equals width.  The padding is on the left by default.  If the
1321 * <tt>'-'</tt> flag is given then the padding will be on the right.  If width
1322 * is not specified then there is no minimum.
1323 *
1324 * <p> If the <a name="floatDPrec">conversion</a> is <tt>'e'</tt>,
1325 * <tt>'E'</tt> or <tt>'f'</tt>, then the precision is the number of digits
1326 * after the decimal separator.  If the precision is not specified, then it is
1327 * assumed to be <tt>6</tt>.
1328 *
1329 * <p> If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the precision is
1330 * the total number of significant digits in the resulting magnitude after
1331 * rounding.  If the precision is not specified, then the default value is
1332 * <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1333 * <tt>1</tt>.
1334 *
1335 * <p> If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the precision
1336 * is the number of hexadecimal digits after the decimal separator.  If the
1337 * precision is not provided, then all of the digits as returned by {@link
1338 * Double#toHexString(double)} will be output.
1339 *
1340 * <p><a name="dndec"><b> BigDecimal </b></a>
1341 *
1342 * <p> The following conversions may be applied {@link java.math.BigDecimal
1343 * BigDecimal}.
1344 *
1345 * <table cellpadding=5 summary="floatConv">
1346 *
1347 * <tr><td valign="top"> <tt>'e'</tt>
1348 *     <td valign="top"> <tt>'&#92;u0065'</tt>
1349 *     <td> Requires the output to be formatted using <a
1350 *     name="scientific">computerized scientific notation</a>.  The <a
1351 *     href="#l10n algorithm">localization algorithm</a> is applied.
1352 *
1353 *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1354 *
1355 *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1356 *     will be <tt>"+00"</tt>.
1357 *
1358 *     <p> Otherwise, the result is a string that represents the sign and
1359 *     magnitude (absolute value) of the argument.  The formatting of the sign
1360 *     is described in the <a href="#l10n algorithm">localization
1361 *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1362 *     value.
1363 *
1364 *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1365 *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1366 *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1367 *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1368 *     integer part of <i>a</i>, as a single decimal digit, followed by the
1369 *     decimal separator followed by decimal digits representing the fractional
1370 *     part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1371 *     (<tt>'&#92;u0065'</tt>), followed by the sign of the exponent, followed
1372 *     by a representation of <i>n</i> as a decimal integer, as produced by the
1373 *     method {@link Long#toString(long, int)}, and zero-padded to include at
1374 *     least two digits.
1375 *
1376 *     <p> The number of digits in the result for the fractional part of
1377 *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1378 *     specified then the default value is <tt>6</tt>.  If the precision is
1379 *     less than the number of digits which would appear after the decimal
1380 *     point in the string returned by {@link Float#toString(float)} or {@link
1381 *     Double#toString(double)} respectively, then the value will be rounded
1382 *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1383 *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1384 *     For a canonical representation of the value, use {@link
1385 *     BigDecimal#toString()}.
1386 *
1387 *     <p> If the <tt>','</tt> flag is given, then an {@link
1388 *     FormatFlagsConversionMismatchException} will be thrown.
1389 *
1390 * <tr><td valign="top"> <tt>'E'</tt>
1391 *     <td valign="top"> <tt>'&#92;u0045'</tt>
1392 *     <td> The upper-case variant of <tt>'e'</tt>.  The exponent symbol
1393 *     will be <tt>'E'</tt> (<tt>'&#92;u0045'</tt>).
1394 *
1395 * <tr><td valign="top"> <tt>'g'</tt>
1396 *     <td valign="top"> <tt>'&#92;u0067'</tt>
1397 *     <td> Requires the output to be formatted in general scientific notation
1398 *     as described below. The <a href="#l10n algorithm">localization
1399 *     algorithm</a> is applied.
1400 *
1401 *     <p> After rounding for the precision, the formatting of the resulting
1402 *     magnitude <i>m</i> depends on its value.
1403 *
1404 *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1405 *     than 10<sup>precision</sup> then it is represented in <i><a
1406 *     href="#decimal">decimal format</a></i>.
1407 *
1408 *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1409 *     10<sup>precision</sup>, then it is represented in <i><a
1410 *     href="#scientific">computerized scientific notation</a></i>.
1411 *
1412 *     <p> The total number of significant digits in <i>m</i> is equal to the
1413 *     precision.  If the precision is not specified, then the default value is
1414 *     <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1415 *     <tt>1</tt>.
1416 *
1417 *     <p> If the <tt>'#'</tt> flag is given then an {@link
1418 *     FormatFlagsConversionMismatchException} will be thrown.
1419 *
1420 * <tr><td valign="top"> <tt>'G'</tt>
1421 *     <td valign="top"> <tt>'&#92;u0047'</tt>
1422 *     <td> The upper-case variant of <tt>'g'</tt>.
1423 *
1424 * <tr><td valign="top"> <tt>'f'</tt>
1425 *     <td valign="top"> <tt>'&#92;u0066'</tt>
1426 *     <td> Requires the output to be formatted using <a name="decimal">decimal
1427 *     format</a>.  The <a href="#l10n algorithm">localization algorithm</a> is
1428 *     applied.
1429 *
1430 *     <p> The result is a string that represents the sign and magnitude
1431 *     (absolute value) of the argument.  The formatting of the sign is
1432 *     described in the <a href="#l10n algorithm">localization
1433 *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1434 *     value.
1435 *
1436 *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1437 *     leading zeroes, followed by the decimal separator followed by one or
1438 *     more decimal digits representing the fractional part of <i>m</i>.
1439 *
1440 *     <p> The number of digits in the result for the fractional part of
1441 *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1442 *     specified then the default value is <tt>6</tt>.  If the precision is
1443 *     less than the number of digits which would appear after the decimal
1444 *     point in the string returned by {@link Float#toString(float)} or {@link
1445 *     Double#toString(double)} respectively, then the value will be rounded
1446 *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1447 *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1448 *     For a canonical representation of the value, use {@link
1449 *     BigDecimal#toString()}.
1450 *
1451 * </table>
1452 *
1453 * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1454 * Long apply.
1455 *
1456 * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1457 * always be present.
1458 *
1459 * <p> The <a href="#floatdFlags">default behavior</a> when no flags are
1460 * given is the same as for Float and Double.
1461 *
1462 * <p> The specification of <a href="#floatDWidth">width</a> and <a
1463 * href="#floatDPrec">precision</a> is the same as defined for Float and
1464 * Double.
1465 *
1466 * <h4><a name="ddt">Date/Time</a></h4>
1467 *
1468 * <p> This conversion may be applied to <tt>long</tt>, {@link Long}, {@link
1469 * Calendar}, and {@link Date}.
1470 *
1471 * <table cellpadding=5 summary="DTConv">
1472 *
1473 * <tr><td valign="top"> <tt>'t'</tt>
1474 *     <td valign="top"> <tt>'&#92;u0074'</tt>
1475 *     <td> Prefix for date and time conversion characters.
1476 * <tr><td valign="top"> <tt>'T'</tt>
1477 *     <td valign="top"> <tt>'&#92;u0054'</tt>
1478 *     <td> The upper-case variant of <tt>'t'</tt>.
1479 *
1480 * </table>
1481 *
1482 * <p> The following date and time conversion character suffixes are defined
1483 * for the <tt>'t'</tt> and <tt>'T'</tt> conversions.  The types are similar to
1484 * but not completely identical to those defined by GNU <tt>date</tt> and
1485 * POSIX <tt>strftime(3c)</tt>.  Additional conversion types are provided to
1486 * access Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds
1487 * within the second).
1488 *
1489 * <p> The following conversion characters are used for formatting times:
1490 *
1491 * <table cellpadding=5 summary="time">
1492 *
1493 * <tr><td valign="top"> <tt>'H'</tt>
1494 *     <td valign="top"> <tt>'&#92;u0048'</tt>
1495 *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
1496 *     a leading zero as necessary i.e. <tt>00 - 23</tt>. <tt>00</tt>
1497 *     corresponds to midnight.
1498 *
1499 * <tr><td valign="top"><tt>'I'</tt>
1500 *     <td valign="top"> <tt>'&#92;u0049'</tt>
1501 *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
1502 *     zero as necessary, i.e.  <tt>01 - 12</tt>.  <tt>01</tt> corresponds to
1503 *     one o'clock (either morning or afternoon).
1504 *
1505 * <tr><td valign="top"><tt>'k'</tt>
1506 *     <td valign="top"> <tt>'&#92;u006b'</tt>
1507 *     <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
1508 *     <tt>0</tt> corresponds to midnight.
1509 *
1510 * <tr><td valign="top"><tt>'l'</tt>
1511 *     <td valign="top"> <tt>'&#92;u006c'</tt>
1512 *     <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>.  <tt>1</tt>
1513 *     corresponds to one o'clock (either morning or afternoon).
1514 *
1515 * <tr><td valign="top"><tt>'M'</tt>
1516 *     <td valign="top"> <tt>'&#92;u004d'</tt>
1517 *     <td> Minute within the hour formatted as two digits with a leading zero
1518 *     as necessary, i.e.  <tt>00 - 59</tt>.
1519 *
1520 * <tr><td valign="top"><tt>'S'</tt>
1521 *     <td valign="top"> <tt>'&#92;u0053'</tt>
1522 *     <td> Seconds within the minute, formatted as two digits with a leading
1523 *     zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
1524 *     value required to support leap seconds).
1525 *
1526 * <tr><td valign="top"><tt>'L'</tt>
1527 *     <td valign="top"> <tt>'&#92;u004c'</tt>
1528 *     <td> Millisecond within the second formatted as three digits with
1529 *     leading zeros as necessary, i.e. <tt>000 - 999</tt>.
1530 *
1531 * <tr><td valign="top"><tt>'N'</tt>
1532 *     <td valign="top"> <tt>'&#92;u004e'</tt>
1533 *     <td> Nanosecond within the second, formatted as nine digits with leading
1534 *     zeros as necessary, i.e. <tt>000000000 - 999999999</tt>.  The precision
1535 *     of this value is limited by the resolution of the underlying operating
1536 *     system or hardware.
1537 *
1538 * <tr><td valign="top"><tt>'p'</tt>
1539 *     <td valign="top"> <tt>'&#92;u0070'</tt>
1540 *     <td> Locale-specific {@linkplain
1541 *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
1542 *     in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>".  Use of the
1543 *     conversion prefix <tt>'T'</tt> forces this output to upper case.  (Note
1544 *     that <tt>'p'</tt> produces lower-case output.  This is different from
1545 *     GNU <tt>date</tt> and POSIX <tt>strftime(3c)</tt> which produce
1546 *     upper-case output.)
1547 *
1548 * <tr><td valign="top"><tt>'z'</tt>
1549 *     <td valign="top"> <tt>'&#92;u007a'</tt>
1550 *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
1551 *     style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
1552 *
1553 * <tr><td valign="top"><tt>'Z'</tt>
1554 *     <td valign="top"> <tt>'&#92;u005a'</tt>
1555 *     <td> A string representing the abbreviation for the time zone.
1556 *
1557 * <tr><td valign="top"><tt>'s'</tt>
1558 *     <td valign="top"> <tt>'&#92;u0073'</tt>
1559 *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
1560 *     <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
1561 *     <tt>Long.MAX_VALUE/1000</tt>.
1562 *
1563 * <tr><td valign="top"><tt>'Q'</tt>
1564 *     <td valign="top"> <tt>'&#92;u004f'</tt>
1565 *     <td> Milliseconds since the beginning of the epoch starting at 1 January
1566 *     1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
1567 *     <tt>Long.MAX_VALUE</tt>. The precision of this value is limited by
1568 *     the resolution of the underlying operating system or hardware.
1569 *
1570 * </table>
1571 *
1572 * <p> The following conversion characters are used for formatting dates:
1573 *
1574 * <table cellpadding=5 summary="date">
1575 *
1576 * <tr><td valign="top"><tt>'B'</tt>
1577 *     <td valign="top"> <tt>'&#92;u0042'</tt>
1578 *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
1579 *     full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
1580 *
1581 * <tr><td valign="top"><tt>'b'</tt>
1582 *     <td valign="top"> <tt>'&#92;u0062'</tt>
1583 *     <td> Locale-specific {@linkplain
1584 *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
1585 *     e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
1586 *
1587 * <tr><td valign="top"><tt>'h'</tt>
1588 *     <td valign="top"> <tt>'&#92;u0068'</tt>
1589 *     <td> Same as <tt>'b'</tt>.
1590 *
1591 * <tr><td valign="top"><tt>'A'</tt>
1592 *     <td valign="top"> <tt>'&#92;u0041'</tt>
1593 *     <td> Locale-specific full name of the {@linkplain
1594 *     java.text.DateFormatSymbols#getWeekdays day of the week},
1595 *     e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
1596 *
1597 * <tr><td valign="top"><tt>'a'</tt>
1598 *     <td valign="top"> <tt>'&#92;u0061'</tt>
1599 *     <td> Locale-specific short name of the {@linkplain
1600 *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
1601 *     e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
1602 *
1603 * <tr><td valign="top"><tt>'C'</tt>
1604 *     <td valign="top"> <tt>'&#92;u0043'</tt>
1605 *     <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
1606 *     with leading zero as necessary, i.e. <tt>00 - 99</tt>
1607 *
1608 * <tr><td valign="top"><tt>'Y'</tt>
1609 *     <td valign="top"> <tt>'&#92;u0059'</tt> <td> Year, formatted to at least
1610 *     four digits with leading zeros as necessary, e.g. <tt>0092</tt> equals
1611 *     <tt>92</tt> CE for the Gregorian calendar.
1612 *
1613 * <tr><td valign="top"><tt>'y'</tt>
1614 *     <td valign="top"> <tt>'&#92;u0079'</tt>
1615 *     <td> Last two digits of the year, formatted with leading zeros as
1616 *     necessary, i.e. <tt>00 - 99</tt>.
1617 *
1618 * <tr><td valign="top"><tt>'j'</tt>
1619 *     <td valign="top"> <tt>'&#92;u006a'</tt>
1620 *     <td> Day of year, formatted as three digits with leading zeros as
1621 *     necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
1622 *     <tt>001</tt> corresponds to the first day of the year.
1623 *
1624 * <tr><td valign="top"><tt>'m'</tt>
1625 *     <td valign="top"> <tt>'&#92;u006d'</tt>
1626 *     <td> Month, formatted as two digits with leading zeros as necessary,
1627 *     i.e. <tt>01 - 13</tt>, where "<tt>01</tt>" is the first month of the
1628 *     year and ("<tt>13</tt>" is a special value required to support lunar
1629 *     calendars).
1630 *
1631 * <tr><td valign="top"><tt>'d'</tt>
1632 *     <td valign="top"> <tt>'&#92;u0064'</tt>
1633 *     <td> Day of month, formatted as two digits with leading zeros as
1634 *     necessary, i.e. <tt>01 - 31</tt>, where "<tt>01</tt>" is the first day
1635 *     of the month.
1636 *
1637 * <tr><td valign="top"><tt>'e'</tt>
1638 *     <td valign="top"> <tt>'&#92;u0065'</tt>
1639 *     <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt> where
1640 *     "<tt>1</tt>" is the first day of the month.
1641 *
1642 * </table>
1643 *
1644 * <p> The following conversion characters are used for formatting common
1645 * date/time compositions.
1646 *
1647 * <table cellpadding=5 summary="composites">
1648 *
1649 * <tr><td valign="top"><tt>'R'</tt>
1650 *     <td valign="top"> <tt>'&#92;u0052'</tt>
1651 *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
1652 *
1653 * <tr><td valign="top"><tt>'T'</tt>
1654 *     <td valign="top"> <tt>'&#92;u0054'</tt>
1655 *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
1656 *
1657 * <tr><td valign="top"><tt>'r'</tt>
1658 *     <td valign="top"> <tt>'&#92;u0072'</tt>
1659 *     <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS
1660 *     %Tp"</tt>.  The location of the morning or afternoon marker
1661 *     (<tt>'%Tp'</tt>) may be locale-dependent.
1662 *
1663 * <tr><td valign="top"><tt>'D'</tt>
1664 *     <td valign="top"> <tt>'&#92;u0044'</tt>
1665 *     <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
1666 *
1667 * <tr><td valign="top"><tt>'F'</tt>
1668 *     <td valign="top"> <tt>'&#92;u0046'</tt>
1669 *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
1670 *     complete date formatted as <tt>"%tY-%tm-%td"</tt>.
1671 *
1672 * <tr><td valign="top"><tt>'c'</tt>
1673 *     <td valign="top"> <tt>'&#92;u0063'</tt>
1674 *     <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
1675 *     e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
1676 *
1677 * </table>
1678 *
1679 * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1680 * conversions</a> applies.  If the <tt>'#'</tt> flag is given, then a {@link
1681 * FormatFlagsConversionMismatchException} will be thrown.
1682 *
1683 * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1684 * be written to the output.  If the length of the converted value is less than
1685 * the <tt>width</tt> then the output will be padded by spaces
1686 * (<tt>'&#92;u0020'</tt>) until the total number of characters equals width.
1687 * The padding is on the left by default.  If the <tt>'-'</tt> flag is given
1688 * then the padding will be on the right.  If width is not specified then there
1689 * is no minimum.
1690 *
1691 * <p> The precision is not applicable.  If the precision is specified then an
1692 * {@link IllegalFormatPrecisionException} will be thrown.
1693 *
1694 * <h4><a name="dper">Percent</a></h4>
1695 *
1696 * <p> The conversion does not correspond to any argument.
1697 *
1698 * <table cellpadding=5 summary="DTConv">
1699 *
1700 * <tr><td valign="top"><tt>'%'</tt>
1701 *     <td> The result is a literal <tt>'%'</tt> (<tt>'&#92;u0025'</tt>)
1702 *
1703 * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1704 * be written to the output including the <tt>'%'</tt>.  If the length of the
1705 * converted value is less than the <tt>width</tt> then the output will be
1706 * padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1707 * characters equals width.  The padding is on the left.  If width is not
1708 * specified then just the <tt>'%'</tt> is output.
1709 *
1710 * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1711 * conversions</a> applies.  If any other flags are provided, then a
1712 * {@link FormatFlagsConversionMismatchException} will be thrown.
1713 *
1714 * <p> The precision is not applicable.  If the precision is specified an
1715 * {@link IllegalFormatPrecisionException} will be thrown.
1716 *
1717 * </table>
1718 *
1719 * <h4><a name="dls">Line Separator</a></h4>
1720 *
1721 * <p> The conversion does not correspond to any argument.
1722 *
1723 * <table cellpadding=5 summary="DTConv">
1724 *
1725 * <tr><td valign="top"><tt>'n'</tt>
1726 *     <td> the platform-specific line separator as returned by {@link
1727 *     System#getProperty System.getProperty("line.separator")}.
1728 *
1729 * </table>
1730 *
1731 * <p> Flags, width, and precision are not applicable.  If any are provided an
1732 * {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
1733 * and {@link IllegalFormatPrecisionException}, respectively will be thrown.
1734 *
1735 * <h4><a name="dpos">Argument Index</a></h4>
1736 *
1737 * <p> Format specifiers can reference arguments in three ways:
1738 *
1739 * <ul>
1740 *
1741 * <li> <i>Explicit indexing</i> is used when the format specifier contains an
1742 * argument index.  The argument index is a decimal integer indicating the
1743 * position of the argument in the argument list.  The first argument is
1744 * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.  An argument
1745 * may be referenced more than once.
1746 *
1747 * <p> For example:
1748 *
1749 * <blockquote><pre>
1750 *   formatter.format("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s",
1751 *                    "a", "b", "c", "d")
1752 *   // -&gt; "d c b a d c b a"
1753 * </pre></blockquote>
1754 *
1755 * <li> <i>Relative indexing</i> is used when the format specifier contains a
1756 * <tt>'&lt;'</tt> (<tt>'&#92;u003c'</tt>) flag which causes the argument for
1757 * the previous format specifier to be re-used.  If there is no previous
1758 * argument, then a {@link MissingFormatArgumentException} is thrown.
1759 *
1760 * <blockquote><pre>
1761 *    formatter.format("%s %s %&lt;s %&lt;s", "a", "b", "c", "d")
1762 *    // -&gt; "a b b b"
1763 *    // "c" and "d" are ignored because they are not referenced
1764 * </pre></blockquote>
1765 *
1766 * <li> <i>Ordinary indexing</i> is used when the format specifier contains
1767 * neither an argument index nor a <tt>'&lt;'</tt> flag.  Each format specifier
1768 * which uses ordinary indexing is assigned a sequential implicit index into
1769 * argument list which is independent of the indices used by explicit or
1770 * relative indexing.
1771 *
1772 * <blockquote><pre>
1773 *   formatter.format("%s %s %s %s", "a", "b", "c", "d")
1774 *   // -&gt; "a b c d"
1775 * </pre></blockquote>
1776 *
1777 * </ul>
1778 *
1779 * <p> It is possible to have a format string which uses all forms of indexing,
1780 * for example:
1781 *
1782 * <blockquote><pre>
1783 *   formatter.format("%2$s %s %&lt;s %s", "a", "b", "c", "d")
1784 *   // -&gt; "b a a b"
1785 *   // "c" and "d" are ignored because they are not referenced
1786 * </pre></blockquote>
1787 *
1788 * <p> The maximum number of arguments is limited by the maximum dimension of a
1789 * Java array as defined by the <a
1790 * href="http://java.sun.com/docs/books/vmspec/">Java Virtual Machine
1791 * Specification</a>.  If the argument index is does not correspond to an
1792 * available argument, then a {@link MissingFormatArgumentException} is thrown.
1793 *
1794 * <p> If there are more arguments than format specifiers, the extra arguments
1795 * are ignored.
1796 *
1797 * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
1798 * method or constructor in this class will cause a {@link
1799 * NullPointerException} to be thrown.
1800 *
1801 * @author  Iris Clark
1802 * @version     %I%, %G%
1803 * @since 1.5
1804 */
1805public final class Formatter implements Closeable, Flushable {
1806    private Appendable a;
1807    private Locale l;
1808
1809    private IOException lastException;
1810
1811    private char zero = '0';
1812    private static double scaleUp;
1813
1814    // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
1815    // + 3 (max # exp digits) + 4 (error) = 30
1816    private static final int MAX_FD_CHARS = 30;
1817
1818    // Initialize internal data.
1819    private void init(Appendable a, Locale l) {
1820    this.a = a;
1821    this.l = l;
1822    setZero();
1823    }
1824
1825    /**
1826     * Constructs a new formatter.
1827     *
1828     * <p> The destination of the formatted output is a {@link StringBuilder}
1829     * which may be retrieved by invoking {@link #out out()} and whose
1830     * current content may be converted into a string by invoking {@link
1831     * #toString toString()}.  The locale used is the {@linkplain
1832     * Locale#getDefault() default locale} for this instance of the Java
1833     * virtual machine.
1834     */
1835    public Formatter() {
1836    init(new StringBuilder(), Locale.getDefault());
1837    }
1838
1839    /**
1840     * Constructs a new formatter with the specified destination.
1841     *
1842     * <p> The locale used is the {@linkplain Locale#getDefault() default
1843     * locale} for this instance of the Java virtual machine.
1844     *
1845     * @param  a
1846     *         Destination for the formatted output.  If <tt>a</tt> is
1847     *         <tt>null</tt> then a {@link StringBuilder} will be created.
1848     */
1849    public Formatter(Appendable a) {
1850    if (a == null)
1851        a = new StringBuilder();
1852    init(a, Locale.getDefault());
1853    }
1854
1855    /**
1856     * Constructs a new formatter with the specified locale.
1857     *
1858     * <p> The destination of the formatted output is a {@link StringBuilder}
1859     * which may be retrieved by invoking {@link #out out()} and whose current
1860     * content may be converted into a string by invoking {@link #toString
1861     * toString()}.
1862     *
1863     * @param  l
1864     *         The {@linkplain java.util.Locale locale} to apply during
1865     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
1866     *         is applied.
1867     */
1868    public Formatter(Locale l) {
1869    init(new StringBuilder(), l);
1870    }
1871
1872    /**
1873     * Constructs a new formatter with the specified destination and locale.
1874     *
1875     * @param  a
1876     *         Destination for the formatted output.  If <tt>a</tt> is
1877     *         <tt>null</tt> then a {@link StringBuilder} will be created.
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(Appendable a, Locale l) {
1885    if (a == null)
1886        a = new StringBuilder();
1887    init(a, l);
1888    }
1889
1890    /**
1891     * Constructs a new formatter with the specified file name.
1892     *
1893     * <p> The charset used is the {@linkplain
1894     * java.nio.charset.Charset#defaultCharset() default charset} for this
1895     * instance of the Java virtual machine.
1896     *
1897     * <p> The locale used is the {@linkplain Locale#getDefault() default
1898     * locale} for this instance of the Java virtual machine.
1899     *
1900     * @param  fileName
1901     *         The name of the file to use as the destination of this
1902     *         formatter.  If the file exists then it will be truncated to
1903     *         zero size; otherwise, a new file will be created.  The output
1904     *         will be written to the file and is buffered.
1905     *
1906     * @throws  SecurityException
1907     *          If a security manager is present and {@link
1908     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1909     *          access to the file
1910     *
1911     * @throws  FileNotFoundException
1912     *          If the given file name does not denote an existing, writable
1913     *          regular file and a new regular file of that name cannot be
1914     *          created, or if some other error occurs while opening or
1915     *          creating the file
1916     */
1917    public Formatter(String fileName) throws FileNotFoundException {
1918    init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
1919         Locale.getDefault());
1920    }
1921
1922    /**
1923     * Constructs a new formatter with the specified file name and charset.
1924     *
1925     * <p> The locale used is the {@linkplain Locale#getDefault default
1926     * locale} for this instance of the Java virtual machine.
1927     *
1928     * @param  fileName
1929     *         The name of the file to use as the destination of this
1930     *         formatter.  If the file exists then it will be truncated to
1931     *         zero size; otherwise, a new file will be created.  The output
1932     *         will be written to the file and is buffered.
1933     *
1934     * @param  csn
1935     *         The name of a supported {@linkplain java.nio.charset.Charset
1936     *         charset}
1937     *
1938     * @throws  FileNotFoundException
1939     *          If the given file name does not denote an existing, writable
1940     *          regular file and a new regular file of that name cannot be
1941     *          created, or if some other error occurs while opening or
1942     *          creating the file
1943     *
1944     * @throws  SecurityException
1945     *          If a security manager is present and {@link
1946     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1947     *          access to the file
1948     *
1949     * @throws  UnsupportedEncodingException
1950     *          If the named charset is not supported
1951     */
1952    public Formatter(String fileName, String csn)
1953    throws FileNotFoundException, UnsupportedEncodingException
1954    {
1955    this(fileName, csn, Locale.getDefault());
1956    }
1957
1958    /**
1959     * Constructs a new formatter with the specified file name, charset, and
1960     * locale.
1961     *
1962     * @param  fileName
1963     *         The name of the file to use as the destination of this
1964     *         formatter.  If the file exists then it will be truncated to
1965     *         zero size; otherwise, a new file will be created.  The output
1966     *         will be written to the file and is buffered.
1967     *
1968     * @param  csn
1969     *         The name of a supported {@linkplain java.nio.charset.Charset
1970     *         charset}
1971     *
1972     * @param  l
1973     *         The {@linkplain java.util.Locale locale} to apply during
1974     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
1975     *         is applied.
1976     *
1977     * @throws  FileNotFoundException
1978     *          If the given file name does not denote an existing, writable
1979     *          regular file and a new regular file of that name cannot be
1980     *          created, or if some other error occurs while opening or
1981     *          creating the file
1982     *
1983     * @throws  SecurityException
1984     *          If a security manager is present and {@link
1985     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1986     *          access to the file
1987     *
1988     * @throws  UnsupportedEncodingException
1989     *          If the named charset is not supported
1990     */
1991    public Formatter(String fileName, String csn, Locale l)
1992    throws FileNotFoundException, UnsupportedEncodingException
1993    {
1994    init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
1995         l);
1996    }
1997
1998    /**
1999     * Constructs a new formatter with the specified file.
2000     *
2001     * <p> The charset used is the {@linkplain
2002     * java.nio.charset.Charset#defaultCharset() default charset} for this
2003     * instance of the Java virtual machine.
2004     *
2005     * <p> The locale used is the {@linkplain Locale#getDefault() default
2006     * locale} for this instance of the Java virtual machine.
2007     *
2008     * @param  file
2009     *         The file to use as the destination of this formatter.  If the
2010     *         file exists then it will be truncated to zero size; otherwise,
2011     *         a new file will be created.  The output will be written to the
2012     *         file and is buffered.
2013     *
2014     * @throws  SecurityException
2015     *          If a security manager is present and {@link
2016     *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2017     *          write access to the file
2018     *
2019     * @throws  FileNotFoundException
2020     *          If the given file object does not denote an existing, writable
2021     *          regular file and a new regular file of that name cannot be
2022     *          created, or if some other error occurs while opening or
2023     *          creating the file
2024     */
2025    public Formatter(File file) throws FileNotFoundException {
2026    init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
2027         Locale.getDefault());
2028    }
2029
2030    /**
2031     * Constructs a new formatter with the specified file and charset.
2032     *
2033     * <p> The locale used is the {@linkplain Locale#getDefault default
2034     * locale} for this instance of the Java virtual machine.
2035     *
2036     * @param  file
2037     *         The file to use as the destination of this formatter.  If the
2038     *         file exists then it will be truncated to zero size; otherwise,
2039     *         a new file will be created.  The output will be written to the
2040     *         file and is buffered.
2041     *
2042     * @param  csn
2043     *         The name of a supported {@linkplain java.nio.charset.Charset
2044     *         charset}
2045     *
2046     * @throws  FileNotFoundException
2047     *          If the given file object does not denote an existing, writable
2048     *          regular file and a new regular file of that name cannot be
2049     *          created, or if some other error occurs while opening or
2050     *          creating the file
2051     *
2052     * @throws  SecurityException
2053     *          If a security manager is present and {@link
2054     *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2055     *          write access to the file
2056     *
2057     * @throws  UnsupportedEncodingException
2058     *          If the named charset is not supported
2059     */
2060    public Formatter(File file, String csn)
2061    throws FileNotFoundException, UnsupportedEncodingException
2062    {
2063    this(file, csn, Locale.getDefault());
2064    }
2065
2066    /**
2067     * Constructs a new formatter with the specified file, charset, and
2068     * locale.
2069     *
2070     * @param  file
2071     *         The file to use as the destination of this formatter.  If the
2072     *         file exists then it will be truncated to zero size; otherwise,
2073     *         a new file will be created.  The output will be written to the
2074     *         file and is buffered.
2075     *
2076     * @param  csn
2077     *         The name of a supported {@linkplain java.nio.charset.Charset
2078     *         charset}
2079     *
2080     * @param  l
2081     *         The {@linkplain java.util.Locale locale} to apply during
2082     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2083     *         is applied.
2084     *
2085     * @throws  FileNotFoundException
2086     *          If the given file object does not denote an existing, writable
2087     *          regular file and a new regular file of that name cannot be
2088     *          created, or if some other error occurs while opening or
2089     *          creating the file
2090     *
2091     * @throws  SecurityException
2092     *          If a security manager is present and {@link
2093     *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2094     *          write access to the file
2095     *
2096     * @throws  UnsupportedEncodingException
2097     *          If the named charset is not supported
2098     */
2099    public Formatter(File file, String csn, Locale l)
2100    throws FileNotFoundException, UnsupportedEncodingException
2101    {
2102    init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
2103         l);
2104    }
2105
2106    /**
2107     * Constructs a new formatter with the specified print stream.
2108     *
2109     * <p> The locale used is the {@linkplain Locale#getDefault() default
2110     * locale} for this instance of the Java virtual machine.
2111     *
2112     * <p> Characters are written to the given {@link java.io.PrintStream
2113     * PrintStream} object and are therefore encoded using that object's
2114     * charset.
2115     *
2116     * @param  ps
2117     *         The stream to use as the destination of this formatter.
2118     */
2119    public Formatter(PrintStream ps) {
2120    if (ps == null)
2121        throw new NullPointerException();
2122    init((Appendable)ps, Locale.getDefault());
2123    }
2124
2125    /**
2126     * Constructs a new formatter with the specified output stream.
2127     *
2128     * <p> The charset used is the {@linkplain
2129     * java.nio.charset.Charset#defaultCharset() default charset} for this
2130     * instance of the Java virtual machine.
2131     *
2132     * <p> The locale used is the {@linkplain Locale#getDefault() default
2133     * locale} for this instance of the Java virtual machine.
2134     *
2135     * @param  os
2136     *         The output stream to use as the destination of this formatter.
2137     *         The output will be buffered.
2138     */
2139    public Formatter(OutputStream os) {
2140    init(new BufferedWriter(new OutputStreamWriter(os)),
2141         Locale.getDefault());
2142    }
2143
2144    /**
2145     * Constructs a new formatter with the specified output stream and
2146     * charset.
2147     *
2148     * <p> The locale used is the {@linkplain Locale#getDefault default
2149     * locale} for this instance of the Java virtual machine.
2150     *
2151     * @param  os
2152     *         The output stream to use as the destination of this formatter.
2153     *         The output will be buffered.
2154     *
2155     * @param  csn
2156     *         The name of a supported {@linkplain java.nio.charset.Charset
2157     *         charset}
2158     *
2159     * @throws  UnsupportedEncodingException
2160     *          If the named charset is not supported
2161     */
2162    public Formatter(OutputStream os, String csn)
2163    throws UnsupportedEncodingException
2164    {
2165    this(os, csn, Locale.getDefault());
2166    }
2167
2168    /**
2169     * Constructs a new formatter with the specified output stream, charset,
2170     * and locale.
2171     *
2172     * @param  os
2173     *         The output stream to use as the destination of this formatter.
2174     *         The output will be buffered.
2175     *
2176     * @param  csn
2177     *         The name of a supported {@linkplain java.nio.charset.Charset
2178     *         charset}
2179     *
2180     * @param  l
2181     *         The {@linkplain java.util.Locale locale} to apply during
2182     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2183     *         is applied.
2184     *
2185     * @throws  UnsupportedEncodingException
2186     *          If the named charset is not supported
2187     */
2188    public Formatter(OutputStream os, String csn, Locale l)
2189    throws UnsupportedEncodingException
2190    {
2191    init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
2192    }
2193
2194    private void setZero() {
2195    if ((l != null) && !l.equals(Locale.US)) {
2196        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
2197        zero = dfs.getZeroDigit();
2198    }
2199    }
2200
2201    /**
2202     * Returns the locale set by the construction of this formatter.
2203     *
2204     * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2205     * for this object which has a locale argument does not change this value.
2206     *
2207     * @return  <tt>null</tt> if no localization is applied, otherwise a
2208     *          locale
2209     *
2210     * @throws  FormatterClosedException
2211     *          If this formatter has been closed by invoking its {@link
2212     *          #close()} method
2213     */
2214    public Locale locale() {
2215    ensureOpen();
2216    return l;
2217    }
2218
2219    /**
2220     * Returns the destination for the output.
2221     *
2222     * @return  The destination for the output
2223     *
2224     * @throws  FormatterClosedException
2225     *          If this formatter has been closed by invoking its {@link
2226     *          #close()} method
2227     */
2228    public Appendable out() {
2229    ensureOpen();
2230    return a;
2231    }
2232
2233    /**
2234     * Returns the result of invoking <tt>toString()</tt> on the destination
2235     * for the output.  For example, the following code formats text into a
2236     * {@link StringBuilder} then retrieves the resultant string:
2237     *
2238     * <blockquote><pre>
2239     *   Formatter f = new Formatter();
2240     *   f.format("Last reboot at %tc", lastRebootDate);
2241     *   String s = f.toString();
2242     *   // -&gt; s == "Last reboot at Sat Jan 01 00:00:00 PST 2000"
2243     * </pre></blockquote>
2244     *
2245     * <p> An invocation of this method behaves in exactly the same way as the
2246     * invocation
2247     *
2248     * <pre>
2249     *     out().toString() </pre>
2250     *
2251     * <p> Depending on the specification of <tt>toString</tt> for the {@link
2252     * Appendable}, the returned string may or may not contain the characters
2253     * written to the destination.  For instance, buffers typically return
2254     * their contents in <tt>toString()</tt>, but streams cannot since the
2255     * data is discarded.
2256     *
2257     * @return  The result of invoking <tt>toString()</tt> on the destination
2258     *          for the output
2259     *
2260     * @throws  FormatterClosedException
2261     *          If this formatter has been closed by invoking its {@link
2262     *          #close()} method
2263     */
2264    public String toString() {
2265    ensureOpen();
2266    return a.toString();
2267    }
2268
2269    /**
2270     * Flushes this formatter.  If the destination implements the {@link
2271     * java.io.Flushable} interface, its <tt>flush</tt> method will be invoked.
2272     *
2273     * <p> Flushing a formatter writes any buffered output in the destination
2274     * to the underlying stream.
2275     *
2276     * @throws  FormatterClosedException
2277     *          If this formatter has been closed by invoking its {@link
2278     *          #close()} method
2279     */
2280    public void flush() {
2281    ensureOpen();
2282    if (a instanceof Flushable) {
2283        try {
2284                ((Flushable)a).flush();
2285            } catch (IOException ioe) {
2286                lastException = ioe;
2287            }
2288        }
2289    }
2290
2291    /**
2292     * Closes this formatter.  If the destination implements the {@link
2293     * java.io.Closeable} interface, its <tt>close</tt> method will be invoked.
2294     *
2295     * <p> Closing a formatter allows it to release resources it may be holding
2296     * (such as open files).  If the formatter is already closed, then invoking
2297     * this method has no effect.
2298     *
2299     * <p> Attempting to invoke any methods except {@link #ioException()} in
2300     * this formatter after it has been closed will result in a {@link
2301     * FormatterClosedException}.
2302     */
2303    public void close() {
2304    if (a == null)
2305        return;
2306    try {
2307        if (a instanceof Closeable)
2308                ((Closeable)a).close();
2309    } catch (IOException ioe) {
2310        lastException = ioe;
2311    } finally {
2312        a = null;
2313        }
2314    }
2315
2316    private void ensureOpen() {
2317    if (a == null)
2318        throw new FormatterClosedException();
2319    }
2320
2321    /**
2322     * Returns the <tt>IOException</tt> last thrown by this formatter's {@link
2323     * Appendable}.
2324     *
2325     * <p> If the destination's <tt>append()</tt> method never throws
2326     * <tt>IOException</tt>, then this method will always return <tt>null</tt>.
2327     *
2328     * @return  The last exception thrown by the Appendable or <tt>null</tt> if
2329     *          no such exception exists.
2330     */
2331    public IOException ioException() {
2332        return lastException;
2333    }
2334
2335    /**
2336     * Writes a formatted string to this object's destination using the
2337     * specified format string and arguments.  The locale used is the one
2338     * defined during the construction of this formatter.
2339     *
2340     * @param  format
2341     *         A format string as described in <a href="#syntax">Format string
2342     *         syntax</a>.
2343     *
2344     * @param  args
2345     *         Arguments referenced by the format specifiers in the format
2346     *         string.  If there are more arguments than format specifiers, the
2347     *         extra arguments are ignored.  The maximum number of arguments is
2348     *         limited by the maximum dimension of a Java array as defined by
2349     *         the <a href="http://java.sun.com/docs/books/vmspec/">Java
2350     *         Virtual Machine Specification</a>.
2351     *
2352     * @throws  IllegalFormatException
2353     *          If a format string contains an illegal syntax, a format
2354     *          specifier that is incompatible with the given arguments,
2355     *          insufficient arguments given the format string, or other
2356     *          illegal conditions.  For specification of all possible
2357     *          formatting errors, see the <a href="#detail">Details</a>
2358     *          section of the formatter class specification.
2359     *
2360     * @throws  FormatterClosedException
2361     *          If this formatter has been closed by invoking its {@link
2362     *          #close()} method
2363     *
2364     * @return  This formatter
2365     */
2366    public Formatter format(String format, Object ... args) {
2367    return format(l, format, args);
2368    }
2369
2370    /**
2371     * Writes a formatted string to this object's destination using the
2372     * specified locale, format string, and arguments.
2373     *
2374     * @param  l
2375     *         The {@linkplain java.util.Locale locale} to apply during
2376     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2377     *         is applied.  This does not change this object's locale that was
2378     *         set during construction.
2379     *
2380     * @param  format
2381     *         A format string as described in <a href="#syntax">Format string
2382     *         syntax</a>
2383     *
2384     * @param  args
2385     *         Arguments referenced by the format specifiers in the format
2386     *         string.  If there are more arguments than format specifiers, the
2387     *         extra arguments are ignored.  The maximum number of arguments is
2388     *         limited by the maximum dimension of a Java array as defined by
2389     *         the <a href="http://java.sun.com/docs/books/vmspec/">Java
2390     *         Virtual Machine Specification</a>
2391     *
2392     * @throws  IllegalFormatException
2393     *          If a format string contains an illegal syntax, a format
2394     *          specifier that is incompatible with the given arguments,
2395     *          insufficient arguments given the format string, or other
2396     *          illegal conditions.  For specification of all possible
2397     *          formatting errors, see the <a href="#detail">Details</a>
2398     *          section of the formatter class specification.
2399     *
2400     * @throws  FormatterClosedException
2401     *          If this formatter has been closed by invoking its {@link
2402     *          #close()} method
2403     *
2404     * @return  This formatter
2405     */
2406    public Formatter format(Locale l, String format, Object ... args) {
2407    ensureOpen();
2408
2409    // index of last argument referenced
2410    int last = -1;
2411    // last ordinary index
2412    int lasto = -1;
2413
2414    FormatString[] fsa = parse(format);
2415    for (int i = 0; i < fsa.length; i++) {
2416        FormatString fs = fsa[i];
2417        int index = fs.index();
2418        try {
2419        switch (index) {
2420        case -2:  // fixed string, "%n", or "%%"
2421            fs.print(null, l);
2422            break;
2423        case -1:  // relative index
2424            if (last < 0 || (args != null && last > args.length - 1))
2425            throw new MissingFormatArgumentException(fs.toString());
2426            fs.print((args == null ? null : args[last]), l);
2427            break;
2428        case 0:  // ordinary index
2429            lasto++;
2430            last = lasto;
2431            if (args != null && lasto > args.length - 1)
2432            throw new MissingFormatArgumentException(fs.toString());
2433            fs.print((args == null ? null : args[lasto]), l);
2434            break;
2435        default:  // explicit index
2436            last = index - 1;
2437            if (args != null && last > args.length - 1)
2438            throw new MissingFormatArgumentException(fs.toString());
2439            fs.print((args == null ? null : args[last]), l);
2440            break;
2441        }
2442        } catch (IOException x) {
2443        lastException = x;
2444        }
2445    }
2446    return this;
2447    }
2448
2449    // %[argument_index$][flags][width][.precision][t]conversion
2450    private static final String formatSpecifier
2451    = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
2452
2453    private static Pattern fsPattern = Pattern.compile(formatSpecifier);
2454
2455    // Look for format specifiers in the format string.
2456    private FormatString[] parse(String s) {
2457    ArrayList al = new ArrayList();
2458    Matcher m = fsPattern.matcher(s);
2459    int i = 0;
2460    while (i < s.length()) {
2461        if (m.find(i)) {
2462        // Anything between the start of the string and the beginning
2463        // of the format specifier is either fixed text or contains
2464        // an invalid format string.
2465        if (m.start() != i) {
2466            // Make sure we didn't miss any invalid format specifiers
2467            checkText(s.substring(i, m.start()));
2468            // Assume previous characters were fixed text
2469            al.add(new FixedString(s.substring(i, m.start())));
2470        }
2471
2472        // Expect 6 groups in regular expression
2473        String[] sa = new String[6];
2474        for (int j = 0; j < m.groupCount(); j++)
2475            {
2476            sa[j] = m.group(j + 1);
2477//          System.out.print(sa[j] + " ");
2478            }
2479//      System.out.println();
2480        al.add(new FormatSpecifier(this, sa));
2481        i = m.end();
2482        } else {
2483        // No more valid format specifiers.  Check for possible invalid
2484        // format specifiers.
2485        checkText(s.substring(i));
2486        // The rest of the string is fixed text
2487        al.add(new FixedString(s.substring(i)));
2488        break;
2489        }
2490    }
2491//      FormatString[] fs = new FormatString[al.size()];
2492//      for (int j = 0; j < al.size(); j++)
2493//          System.out.println(((FormatString) al.get(j)).toString());
2494    return (FormatString[]) al.toArray(new FormatString[0]);
2495    }
2496
2497    private void checkText(String s) {
2498    int idx;
2499    // If there are any '%' in the given string, we got a bad format
2500    // specifier.
2501    if ((idx = s.indexOf('%')) != -1) {
2502        char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
2503        throw new UnknownFormatConversionException(String.valueOf(c));
2504    }
2505    }
2506
2507    private interface FormatString {
2508    int index();
2509    void print(Object arg, Locale l) throws IOException;
2510    String toString();
2511    }
2512
2513    private class FixedString implements FormatString {
2514    private String s;
2515    FixedString(String s) { this.s = s; }
2516    public int index() { return -2; }
2517    public void print(Object arg, Locale l)
2518        throws IOException { a.append(s); }
2519    public String toString() { return s; }
2520    }
2521
2522    public enum BigDecimalLayoutForm { SCIENTIFIC, DECIMAL_FLOAT };
2523
2524    private class FormatSpecifier implements FormatString {
2525    private int index = -1;
2526    private Flags f = Flags.NONE;
2527    private int width;
2528    private int precision;
2529    private boolean dt = false;
2530    private char c;
2531
2532    private Formatter formatter;
2533
2534    // cache the line separator
2535    private String ls;
2536
2537    private int index(String s) {
2538        if (s != null) {
2539        try {
2540            index = Integer.parseInt(s.substring(0, s.length() - 1));
2541        } catch (NumberFormatException x) {
2542            assert(false);
2543        }
2544        } else {
2545        index = 0;
2546        }
2547        return index;
2548    }
2549
2550    public int index() {
2551        return index;
2552    }
2553
2554    private Flags flags(String s) {
2555        f = Flags.parse(s);
2556        if (f.contains(Flags.PREVIOUS))
2557        index = -1;
2558        return f;
2559    }
2560
2561    Flags flags() {
2562        return f;
2563    }
2564
2565    private int width(String s) {
2566        width = -1;
2567        if (s != null) {
2568        try {
2569            width  = Integer.parseInt(s);
2570            if (width < 0)
2571            throw new IllegalFormatWidthException(width);
2572        } catch (NumberFormatException x) {
2573            assert(false);
2574        }
2575        }
2576        return width;
2577    }
2578
2579    int width() {
2580        return width;
2581    }
2582
2583    private int precision(String s) {
2584        precision = -1;
2585        if (s != null) {
2586        try {
2587            // remove the '.'
2588            precision = Integer.parseInt(s.substring(1));
2589            if (precision < 0)
2590            throw new IllegalFormatPrecisionException(precision);
2591        } catch (NumberFormatException x) {
2592            assert(false);
2593        }
2594        }
2595        return precision;
2596    }
2597
2598    int precision() {
2599        return precision;
2600    }
2601
2602    private char conversion(String s) {
2603        c = s.charAt(0);
2604        if (!dt) {
2605        if (!Conversion.isValid(c))
2606            throw new UnknownFormatConversionException(String.valueOf(c));
2607        if (Character.isUpperCase(c))
2608            f.add(Flags.UPPERCASE);
2609        c = Character.toLowerCase(c);
2610        if (Conversion.isText(c))
2611            index = -2;
2612        }
2613        return c;
2614    }
2615
2616    private char conversion() {
2617        return c;
2618    }
2619
2620    FormatSpecifier(Formatter formatter, String[] sa) {
2621        this.formatter = formatter;
2622        int idx = 0;
2623
2624        index(sa[idx++]);
2625        flags(sa[idx++]);
2626        width(sa[idx++]);
2627        precision(sa[idx++]);
2628
2629        if (sa[idx] != null) {
2630        dt = true;
2631        if (sa[idx].equals("T"))
2632            f.add(Flags.UPPERCASE);
2633        }
2634        conversion(sa[++idx]);
2635
2636        if (dt)
2637        checkDateTime();
2638        else if (Conversion.isGeneral(c))
2639        checkGeneral();
2640        else if (Conversion.isCharacter(c))
2641        checkCharacter();
2642        else if (Conversion.isInteger(c))
2643        checkInteger();
2644        else if (Conversion.isFloat(c))
2645        checkFloat();
2646            else if (Conversion.isText(c))
2647        checkText();
2648        else
2649        throw new UnknownFormatConversionException(String.valueOf(c));
2650    }
2651
2652    public void print(Object arg, Locale l) throws IOException {
2653        if (dt) {
2654        printDateTime(arg, l);
2655        return;
2656        }
2657        switch(c) {
2658        case Conversion.DECIMAL_INTEGER:
2659        case Conversion.OCTAL_INTEGER:
2660        case Conversion.HEXADECIMAL_INTEGER:
2661        printInteger(arg, l);
2662        break;
2663        case Conversion.SCIENTIFIC:
2664        case Conversion.GENERAL:
2665        case Conversion.DECIMAL_FLOAT:
2666        case Conversion.HEXADECIMAL_FLOAT:
2667        printFloat(arg, l);
2668        break;
2669        case Conversion.CHARACTER:
2670        case Conversion.CHARACTER_UPPER:
2671        printCharacter(arg);
2672        break;
2673        case Conversion.BOOLEAN:
2674        printBoolean(arg);
2675        break;
2676        case Conversion.STRING:
2677        printString(arg, l);
2678        break;
2679        case Conversion.HASHCODE:
2680        printHashCode(arg);
2681        break;
2682        case Conversion.LINE_SEPARATOR:
2683        if (ls == null)
2684            ls = System.getProperty("line.separator");
2685        a.append(ls);
2686        break;
2687        case Conversion.PERCENT_SIGN:
2688        a.append('%');
2689        break;
2690        default:
2691        assert false;
2692        }
2693    }
2694
2695    private void printInteger(Object arg, Locale l) throws IOException {
2696        if (arg == null)
2697        print("null");
2698        else if (arg instanceof Byte)
2699        print(((Byte)arg).byteValue(), l);
2700        else if (arg instanceof Short)
2701        print(((Short)arg).shortValue(), l);
2702        else if (arg instanceof Integer)
2703        print(((Integer)arg).intValue(), l);
2704        else if (arg instanceof Long)
2705        print(((Long)arg).longValue(), l);
2706        else if (arg instanceof BigInteger)
2707        print(((BigInteger)arg), l);
2708        else
2709        failConversion(c, arg);
2710    }
2711
2712    private void printFloat(Object arg, Locale l) throws IOException {
2713        if (arg == null)
2714        print("null");
2715        else if (arg instanceof Float)
2716        print(((Float)arg).floatValue(), l);
2717        else if (arg instanceof Double)
2718        print(((Double)arg).doubleValue(), l);
2719        else if (arg instanceof BigDecimal)
2720        print(((BigDecimal)arg), l);
2721        else
2722        failConversion(c, arg);
2723    }
2724
2725    private void printDateTime(Object arg, Locale l) throws IOException {
2726        if (arg == null) {
2727        print("null");
2728        return;
2729        }
2730        Calendar cal = null;
2731
2732        // Instead of Calendar.setLenient(true), perhaps we should
2733        // wrap the IllegalArgumentException that might be thrown?
2734        if (arg instanceof Long) {
2735        // Note that the following method uses an instance of the
2736        // default time zone (TimeZone.getDefaultRef().
2737        cal = Calendar.getInstance(l);
2738        cal.setTimeInMillis((Long)arg);
2739        } else if (arg instanceof Date) {
2740        // Note that the following method uses an instance of the
2741        // default time zone (TimeZone.getDefaultRef().
2742        cal = Calendar.getInstance(l);
2743        cal.setTime((Date)arg);
2744        } else if (arg instanceof Calendar) {
2745        cal = (Calendar) ((Calendar)arg).clone();
2746        cal.setLenient(true);
2747        } else {
2748        failConversion(c, arg);
2749        }
2750        print(cal, c, l);
2751    }
2752
2753    private void printCharacter(Object arg) throws IOException {
2754        if (arg == null) {
2755        print("null");
2756        return;
2757        }
2758        String s = null;
2759        if (arg instanceof Character) {
2760        s = ((Character)arg).toString();
2761        } else if (arg instanceof Byte) {
2762        byte i = ((Byte)arg).byteValue();
2763        if (Character.isValidCodePoint(i))
2764            s = new String(Character.toChars(i));
2765        else
2766            throw new IllegalFormatCodePointException(i);
2767        } else if (arg instanceof Short) {
2768        short i = ((Short)arg).shortValue();
2769        if (Character.isValidCodePoint(i))
2770            s = new String(Character.toChars(i));
2771        else
2772            throw new IllegalFormatCodePointException(i);
2773        } else if (arg instanceof Integer) {
2774        int i = ((Integer)arg).intValue();
2775        if (Character.isValidCodePoint(i))
2776            s = new String(Character.toChars(i));
2777        else
2778            throw new IllegalFormatCodePointException(i);
2779        } else {
2780        failConversion(c, arg);
2781        }
2782        print(s);
2783    }
2784
2785    private void printString(Object arg, Locale l) throws IOException {
2786        if (arg == null) {
2787        print("null");
2788        } else if (arg instanceof Formattable) {
2789        Formatter fmt = formatter;
2790        if (formatter.locale() != l)
2791            fmt = new Formatter(formatter.out(), l);
2792        ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
2793        } else {
2794        print(arg.toString());
2795        }
2796    }
2797
2798    private void printBoolean(Object arg) throws IOException {
2799        String s;
2800        if (arg != null)
2801        s = ((arg instanceof Boolean)
2802             ? ((Boolean)arg).toString()
2803             : Boolean.toString(true));
2804        else
2805        s = Boolean.toString(false);
2806        print(s);
2807    }
2808
2809    private void printHashCode(Object arg) throws IOException {
2810        String s = (arg == null
2811            ? "null"
2812            : Integer.toHexString(arg.hashCode()));
2813        print(s);
2814    }
2815
2816    private void print(String s) throws IOException {
2817        if (precision != -1 && precision < s.length())
2818        s = s.substring(0, precision);
2819        if (f.contains(Flags.UPPERCASE))
2820        s = s.toUpperCase();
2821        a.append(justify(s));
2822    }
2823
2824    private String justify(String s) {
2825        if (width == -1)
2826        return s;
2827        StringBuilder sb = new StringBuilder();
2828        boolean pad = f.contains(Flags.LEFT_JUSTIFY);
2829        int sp = width - s.length();
2830        if (!pad)
2831        for (int i = 0; i < sp; i++) sb.append(' ');
2832        sb.append(s);
2833        if (pad)
2834        for (int i = 0; i < sp; i++) sb.append(' ');
2835        return sb.toString();
2836    }
2837
2838    public String toString() {
2839        StringBuilder sb = new StringBuilder('%');
2840        // Flags.UPPERCASE is set internally for legal conversions.
2841        Flags dupf = f.dup().remove(Flags.UPPERCASE);
2842        sb.append(dupf.toString());
2843        if (index > 0)
2844        sb.append(index).append('$');
2845        if (width != -1)
2846        sb.append(width);
2847        if (precision != -1)
2848        sb.append('.').append(precision);
2849        if (dt)
2850        sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't');
2851        sb.append(f.contains(Flags.UPPERCASE)
2852              ? Character.toUpperCase(c) : c);
2853        return sb.toString();
2854    }
2855
2856    private void checkGeneral() {
2857        if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE)
2858        && f.contains(Flags.ALTERNATE))
2859        failMismatch(Flags.ALTERNATE, c);
2860        // '-' requires a width
2861        if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2862        throw new MissingFormatWidthException(toString());
2863        checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE, Flags.ZERO_PAD,
2864              Flags.GROUP, Flags.PARENTHESES);
2865    }
2866
2867    private void checkDateTime() {
2868        if (precision != -1)
2869        throw new IllegalFormatPrecisionException(precision);
2870        if (!DateTime.isValid(c))
2871        throw new UnknownFormatConversionException("t" + c);
2872        checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE,
2873              Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
2874        // '-' requires a width
2875        if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2876        throw new MissingFormatWidthException(toString());
2877    }
2878
2879    private void checkCharacter() {
2880        if (precision != -1)
2881        throw new IllegalFormatPrecisionException(precision);
2882        checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE,
2883              Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
2884        // '-' requires a width
2885        if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2886        throw new MissingFormatWidthException(toString());
2887    }
2888
2889    private void checkInteger() {
2890        checkNumeric();
2891        if (precision != -1)
2892        throw new IllegalFormatPrecisionException(precision);
2893
2894        if (c == Conversion.DECIMAL_INTEGER)
2895        checkBadFlags(Flags.ALTERNATE);
2896        else if (c == Conversion.OCTAL_INTEGER)
2897        checkBadFlags(Flags.GROUP);
2898        else
2899        checkBadFlags(Flags.GROUP);
2900    }
2901
2902    private void checkBadFlags(Flags ... badFlags) {
2903        for (int i = 0; i < badFlags.length; i++)
2904        if (f.contains(badFlags[i]))
2905            failMismatch(badFlags[i], c);
2906    }
2907
2908    private void checkFloat() {
2909        checkNumeric();
2910        if (c == Conversion.DECIMAL_FLOAT) {
2911        } else if (c == Conversion.HEXADECIMAL_FLOAT) {
2912        checkBadFlags(Flags.PARENTHESES, Flags.GROUP);
2913        } else if (c == Conversion.SCIENTIFIC) {
2914        checkBadFlags(Flags.GROUP);
2915        } else if (c == Conversion.GENERAL) {
2916        checkBadFlags(Flags.ALTERNATE);
2917        }
2918    }
2919
2920    private void checkNumeric() {
2921        if (width != -1 && width < 0)
2922        throw new IllegalFormatWidthException(width);
2923
2924        if (precision != -1 && precision < 0)
2925        throw new IllegalFormatPrecisionException(precision);
2926
2927        // '-' and '0' require a width
2928        if (width == -1
2929        && (f.contains(Flags.LEFT_JUSTIFY) || f.contains(Flags.ZERO_PAD)))
2930        throw new MissingFormatWidthException(toString());
2931
2932        // bad combination
2933        if ((f.contains(Flags.PLUS) && f.contains(Flags.LEADING_SPACE))
2934        || (f.contains(Flags.LEFT_JUSTIFY) && f.contains(Flags.ZERO_PAD)))
2935        throw new IllegalFormatFlagsException(f.toString());
2936    }
2937
2938    private void checkText() {
2939        if (precision != -1)
2940        throw new IllegalFormatPrecisionException(precision);
2941        switch (c) {
2942        case Conversion.PERCENT_SIGN:
2943        if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf()
2944            && f.valueOf() != Flags.NONE.valueOf())
2945            throw new IllegalFormatFlagsException(f.toString());
2946        // '-' requires a width
2947        if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2948            throw new MissingFormatWidthException(toString());
2949        break;
2950        case Conversion.LINE_SEPARATOR:
2951        if (width != -1)
2952            throw new IllegalFormatWidthException(width);
2953        if (f.valueOf() != Flags.NONE.valueOf())
2954            throw new IllegalFormatFlagsException(f.toString());
2955        break;
2956        default:
2957        assert false;
2958        }
2959    }
2960
2961    private void print(byte value, Locale l) throws IOException {
2962        long v = value;
2963        if (value < 0
2964        && (c == Conversion.OCTAL_INTEGER
2965            || c == Conversion.HEXADECIMAL_INTEGER)) {
2966        v += (1L << 8);
2967        assert v >= 0 : v;
2968        }
2969        print(v, l);
2970    }
2971
2972    private void print(short value, Locale l) throws IOException {
2973        long v = value;
2974        if (value < 0
2975        && (c == Conversion.OCTAL_INTEGER
2976            || c == Conversion.HEXADECIMAL_INTEGER)) {
2977        v += (1L << 16);
2978        assert v >= 0 : v;
2979        }
2980        print(v, l);
2981    }
2982
2983    private void print(int value, Locale l) throws IOException {
2984        long v = value;
2985        if (value < 0
2986        && (c == Conversion.OCTAL_INTEGER
2987            || c == Conversion.HEXADECIMAL_INTEGER)) {
2988        v += (1L << 32);
2989        assert v >= 0 : v;
2990        }
2991        print(v, l);
2992    }
2993
2994    private void print(long value, Locale l) throws IOException {
2995
2996        StringBuilder sb = new StringBuilder();
2997
2998        if (c == Conversion.DECIMAL_INTEGER) {
2999        boolean neg = value < 0;
3000        char[] va;
3001        if (value < 0)
3002            va = Long.toString(value, 10).substring(1).toCharArray();
3003        else
3004            va = Long.toString(value, 10).toCharArray();
3005
3006        // leading sign indicator
3007        leadingSign(sb, neg);
3008
3009        // the value
3010        localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l);
3011
3012        // trailing sign indicator
3013        trailingSign(sb, neg);
3014        } else if (c == Conversion.OCTAL_INTEGER) {
3015        checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3016                  Flags.PLUS);
3017        String s = Long.toOctalString(value);
3018        int len = (f.contains(Flags.ALTERNATE)
3019               ? s.length() + 1
3020               : s.length());
3021
3022        // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3023        if (f.contains(Flags.ALTERNATE))
3024            sb.append('0');
3025        if (f.contains(Flags.ZERO_PAD))
3026            for (int i = 0; i < width - len; i++) sb.append('0');
3027        sb.append(s);
3028        } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3029        checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3030                  Flags.PLUS);
3031        String s = Long.toHexString(value);
3032        int len = (f.contains(Flags.ALTERNATE)
3033               ? s.length() + 2
3034               : s.length());
3035
3036        // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3037        if (f.contains(Flags.ALTERNATE))
3038            sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x");
3039        if (f.contains(Flags.ZERO_PAD))
3040            for (int i = 0; i < width - len; i++) sb.append('0');
3041        if (f.contains(Flags.UPPERCASE))
3042            s = s.toUpperCase();
3043        sb.append(s);
3044        }
3045
3046        // justify based on width
3047        a.append(justify(sb.toString()));
3048    }
3049
3050    // neg := val < 0
3051    private StringBuilder leadingSign(StringBuilder sb, boolean neg) {
3052        if (!neg) {
3053        if (f.contains(Flags.PLUS)) {
3054            sb.append('+');
3055        } else if (f.contains(Flags.LEADING_SPACE)) {
3056            sb.append(' ');
3057        }
3058        } else {
3059        if (f.contains(Flags.PARENTHESES))
3060            sb.append('(');
3061        else
3062            sb.append('-');
3063        }
3064        return sb;
3065    }
3066
3067    // neg := val < 0
3068    private StringBuilder trailingSign(StringBuilder sb, boolean neg) {
3069        if (neg && f.contains(Flags.PARENTHESES))
3070        sb.append(')');
3071        return sb;
3072    }
3073
3074    private void print(BigInteger value, Locale l) throws IOException {
3075        StringBuilder sb = new StringBuilder();
3076        boolean neg = value.signum() == -1;
3077        BigInteger v = value.abs();
3078
3079        // leading sign indicator
3080        leadingSign(sb, neg);
3081
3082        // the value
3083        if (c == Conversion.DECIMAL_INTEGER) {
3084        char[] va = v.toString().toCharArray();
3085        localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l);
3086        } else if (c == Conversion.OCTAL_INTEGER) {
3087        String s = v.toString(8);
3088
3089        int len = s.length() + sb.length();
3090        if (neg && f.contains(Flags.PARENTHESES))
3091            len++;
3092
3093        // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3094        if (f.contains(Flags.ALTERNATE)) {
3095            len++;
3096            sb.append('0');
3097        }
3098        if (f.contains(Flags.ZERO_PAD)) {
3099            for (int i = 0; i < width - len; i++)
3100            sb.append('0');
3101        }
3102        sb.append(s);
3103        } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3104        String s = v.toString(16);
3105
3106        int len = s.length() + sb.length();
3107        if (neg && f.contains(Flags.PARENTHESES))
3108            len++;
3109
3110        // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3111        if (f.contains(Flags.ALTERNATE)) {
3112            len += 2;
3113            sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x");
3114        }
3115        if (f.contains(Flags.ZERO_PAD))
3116            for (int i = 0; i < width - len; i++)
3117            sb.append('0');
3118        if (f.contains(Flags.UPPERCASE))
3119            s = s.toUpperCase();
3120        sb.append(s);
3121        }
3122
3123        // trailing sign indicator
3124        trailingSign(sb, (value.signum() == -1));
3125
3126        // justify based on width
3127        a.append(justify(sb.toString()));
3128    }
3129
3130    private void print(float value, Locale l) throws IOException {
3131        print((double) value, l);
3132    }
3133
3134    private void print(double value, Locale l) throws IOException {
3135        StringBuilder sb = new StringBuilder();
3136        boolean neg = Double.compare(value, 0.0) == -1;
3137
3138        if (!Double.isNaN(value)) {
3139        double v = Math.abs(value);
3140
3141        // leading sign indicator
3142        leadingSign(sb, neg);
3143
3144        // the value
3145        if (!Double.isInfinite(v))
3146            print(sb, v, l, f, c, precision, neg);
3147        else
3148            sb.append(f.contains(Flags.UPPERCASE)
3149                  ? "INFINITY" : "Infinity");
3150
3151        // trailing sign indicator
3152        trailingSign(sb, neg);
3153        } else {
3154        sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN");
3155        }
3156
3157        // justify based on width
3158        a.append(justify(sb.toString()));
3159    }
3160
3161    // !Double.isInfinite(value) && !Double.isNaN(value)
3162    private void print(StringBuilder sb, double value, Locale l,
3163               Flags f, char c, int precision, boolean neg)
3164        throws IOException
3165    {
3166        if (c == Conversion.SCIENTIFIC) {
3167        // Create a new FormattedFloatingDecimal with the desired
3168        // precision.
3169        int prec = (precision == -1 ? 6 : precision);
3170
3171        FormattedFloatingDecimal fd
3172            = new FormattedFloatingDecimal(value, prec,
3173                        FormattedFloatingDecimal.Form.SCIENTIFIC);
3174
3175        char[] v = new char[MAX_FD_CHARS];
3176        int len = fd.getChars(v);
3177
3178        char[] mant = addZeros(mantissa(v, len), prec);
3179
3180        // If the precision is zero and the '#' flag is set, add the
3181        // requested decimal point.
3182        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3183            mant = addDot(mant);
3184
3185        char[] exp = (value == 0.0)
3186            ? new char[] {'+','0','0'} : exponent(v, len);
3187
3188        int newW = width;
3189        if (width != -1)
3190            newW = adjustWidth(width - exp.length - 1, f, neg);
3191        localizedMagnitude(sb, mant, f, newW, null);
3192
3193        sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3194
3195        Flags flags = f.dup().remove(Flags.GROUP);
3196        char sign = exp[0];
3197        assert(sign == '+' || sign == '-');
3198        sb.append(sign);
3199
3200        char[] tmp = new char[exp.length - 1];
3201        System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3202        sb.append(localizedMagnitude(null, tmp, flags, -1, null));
3203        } else if (c == Conversion.DECIMAL_FLOAT) {
3204        // Create a new FormattedFloatingDecimal with the desired
3205        // precision.
3206        int prec = (precision == -1 ? 6 : precision);
3207
3208        FormattedFloatingDecimal fd
3209            = new FormattedFloatingDecimal(value, prec,
3210            FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
3211
3212        // MAX_FD_CHARS + 1 (round?)
3213        char[] v = new char[MAX_FD_CHARS + 1
3214                   + Math.abs(fd.getExponent())];
3215        int len = fd.getChars(v);
3216
3217        char[] mant = addZeros(mantissa(v, len), prec);
3218
3219        // If the precision is zero and the '#' flag is set, add the
3220        // requested decimal point.
3221        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3222            mant = addDot(mant);
3223
3224        int newW = width;
3225        if (width != -1)
3226            newW = adjustWidth(width, f, neg);
3227        localizedMagnitude(sb, mant, f, newW, l);
3228        } else if (c == Conversion.GENERAL) {
3229        int prec = precision;
3230        if (precision == -1)
3231            prec = 6;
3232        else if (precision == 0)
3233            prec = 1;
3234
3235        FormattedFloatingDecimal fd
3236            = new FormattedFloatingDecimal(value, prec,
3237            FormattedFloatingDecimal.Form.GENERAL);
3238
3239        // MAX_FD_CHARS + 1 (round?)
3240        char[] v = new char[MAX_FD_CHARS + 1
3241                   + Math.abs(fd.getExponent())];
3242        int len = fd.getChars(v);
3243
3244        char[] exp = exponent(v, len);
3245        if (exp != null) {
3246            prec -= 1;
3247        } else {
3248            prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1;
3249        }
3250
3251        char[] mant = addZeros(mantissa(v, len), prec);
3252        // If the precision is zero and the '#' flag is set, add the
3253        // requested decimal point.
3254        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3255            mant = addDot(mant);
3256
3257        int newW = width;
3258        if (width != -1) {
3259            if (exp != null)
3260            newW = adjustWidth(width - exp.length - 1, f, neg);
3261            else
3262            newW = adjustWidth(width, f, neg);
3263        }
3264        localizedMagnitude(sb, mant, f, newW, null);
3265
3266        if (exp != null) {
3267            sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3268
3269            Flags flags = f.dup().remove(Flags.GROUP);
3270            char sign = exp[0];
3271            assert(sign == '+' || sign == '-');
3272            sb.append(sign);
3273
3274            char[] tmp = new char[exp.length - 1];
3275            System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3276            sb.append(localizedMagnitude(null, tmp, flags, -1, null));
3277        }
3278        } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3279        int prec = precision;
3280        if (precision == -1)
3281            // assume that we want all of the digits
3282            prec = 0;
3283        else if (precision == 0)
3284            prec = 1;
3285
3286        String s = hexDouble(value, prec);
3287
3288        char[] va;
3289        boolean upper = f.contains(Flags.UPPERCASE);
3290        sb.append(upper ? "0X" : "0x");
3291
3292        if (f.contains(Flags.ZERO_PAD))
3293            for (int i = 0; i < width - s.length() - 2; i++)
3294            sb.append('0');
3295
3296        int idx = s.indexOf('p');
3297        va = s.substring(0, idx).toCharArray();
3298        if (upper) {
3299            String tmp = new String(va);
3300            // don't localize hex
3301            tmp = tmp.toUpperCase(Locale.US);
3302            va = tmp.toCharArray();
3303        }
3304        sb.append(prec != 0 ? addZeros(va, prec) : va);
3305        sb.append(upper ? 'P' : 'p');
3306        sb.append(s.substring(idx+1));
3307        }
3308    }
3309
3310    private char[] mantissa(char[] v, int len) {
3311        int i;
3312        for (i = 0; i < len; i++) {
3313        if (v[i] == 'e')
3314            break;
3315        }
3316        char[] tmp = new char[i];
3317        System.arraycopy(v, 0, tmp, 0, i);
3318        return tmp;
3319    }
3320
3321    private char[] exponent(char[] v, int len) {
3322        int i;
3323        for (i = len - 1; i >= 0; i--) {
3324        if (v[i] == 'e')
3325            break;
3326        }
3327        if (i == -1)
3328        return null;
3329        char[] tmp = new char[len - i - 1];
3330        System.arraycopy(v, i + 1, tmp, 0, len - i - 1);
3331        return tmp;
3332    }
3333
3334    // Add zeros to the requested precision.
3335    private char[] addZeros(char[] v, int prec) {
3336        // Look for the dot.  If we don't find one, the we'll need to add
3337        // it before we add the zeros.
3338        int i;
3339        for (i = 0; i < v.length; i++) {
3340        if (v[i] == '.')
3341            break;
3342        }
3343        boolean needDot = false;
3344        if (i == v.length) {
3345        needDot = true;
3346        }
3347
3348        // Determine existing precision.
3349        int outPrec = v.length - i - (needDot ? 0 : 1);
3350        assert (outPrec <= prec);
3351        if (outPrec == prec)
3352        return v;
3353
3354        // Create new array with existing contents.
3355        char[] tmp
3356        = new char[v.length + prec - outPrec + (needDot ? 1 : 0)];
3357        System.arraycopy(v, 0, tmp, 0, v.length);
3358
3359        // Add dot if previously determined to be necessary.
3360        int start = v.length;
3361        if (needDot) {
3362        tmp[v.length] = '.';
3363        start++;
3364        }
3365
3366        // Add zeros.
3367        for (int j = start; j < tmp.length; j++)
3368        tmp[j] = '0';
3369
3370        return tmp;
3371    }
3372
3373    // Method assumes that d > 0.
3374    private String hexDouble(double d, int prec) {
3375        // Let Double.toHexString handle simple cases
3376        if(!FpUtils.isFinite(d) || d == 0.0 || prec == 0 || prec >= 13)
3377        // remove "0x"
3378        return Double.toHexString(d).substring(2);
3379        else {
3380        assert(prec >= 1 && prec <= 12);
3381
3382        int exponent  = FpUtils.getExponent(d);
3383        boolean subnormal
3384            = (exponent == DoubleConsts.MIN_EXPONENT - 1);
3385
3386        // If this is subnormal input so normalize (could be faster to
3387        // do as integer operation).
3388        if (subnormal) {
3389            scaleUp = FpUtils.scalb(1.0, 54);
3390            d *= scaleUp;
3391            // Calculate the exponent.  This is not just exponent + 54
3392            // since the former is not the normalized exponent.
3393            exponent = FpUtils.getExponent(d);
3394            assert exponent >= DoubleConsts.MIN_EXPONENT &&
3395            exponent <= DoubleConsts.MAX_EXPONENT: exponent;
3396        }
3397
3398        int precision = 1 + prec*4;
3399        int shiftDistance
3400            =  DoubleConsts.SIGNIFICAND_WIDTH - precision;
3401        assert(shiftDistance >= 1 && shiftDistance < DoubleConsts.SIGNIFICAND_WIDTH);
3402
3403        long doppel = Double.doubleToLongBits(d);
3404        // Deterime the number of bits to keep.
3405        long newSignif
3406            = (doppel & (DoubleConsts.EXP_BIT_MASK
3407                 | DoubleConsts.SIGNIF_BIT_MASK))
3408                     >> shiftDistance;
3409        // Bits to round away.
3410        long roundingBits = doppel & ~(~0L << shiftDistance);
3411
3412        // To decide how to round, look at the low-order bit of the
3413        // working significand, the highest order discarded bit (the
3414        // round bit) and whether any of the lower order discarded bits
3415        // are nonzero (the sticky bit).
3416
3417        boolean leastZero = (newSignif & 0x1L) == 0L;
3418        boolean round
3419            = ((1L << (shiftDistance - 1) ) & roundingBits) != 0L;
3420        boolean sticky  = shiftDistance > 1 &&
3421            (~(1L<< (shiftDistance - 1)) & roundingBits) != 0;
3422        if((leastZero && round && sticky) || (!leastZero && round)) {
3423            newSignif++;
3424        }
3425
3426        long signBit = doppel & DoubleConsts.SIGN_BIT_MASK;
3427        newSignif = signBit | (newSignif << shiftDistance);
3428        double result = Double.longBitsToDouble(newSignif);
3429
3430        if (Double.isInfinite(result) ) {
3431            // Infinite result generated by rounding
3432            return "1.0p1024";
3433        } else {
3434            String res = Double.toHexString(result).substring(2);
3435            if (!subnormal)
3436            return res;
3437            else {
3438            // Create a normalized subnormal string.
3439            int idx = res.indexOf('p');
3440            if (idx == -1) {
3441                // No 'p' character in hex string.
3442                assert false;
3443                return null;
3444            } else {
3445                // Get exponent and append at the end.
3446                String exp = res.substring(idx + 1);
3447                int iexp = Integer.parseInt(exp) -54;
3448                return res.substring(0, idx) + "p"
3449                + Integer.toString(iexp);
3450            }
3451            }
3452        }
3453        }
3454    }
3455
3456    private void print(BigDecimal value, Locale l) throws IOException {
3457        if (c == Conversion.HEXADECIMAL_FLOAT)
3458        failConversion(c, value);
3459        StringBuilder sb = new StringBuilder();
3460        boolean neg = value.signum() == -1;
3461        BigDecimal v = value.abs();
3462        // leading sign indicator
3463        leadingSign(sb, neg);
3464
3465        // the value
3466        print(sb, v, l, f, c, precision, neg);
3467
3468        // trailing sign indicator
3469        trailingSign(sb, neg);
3470
3471        // justify based on width
3472        a.append(justify(sb.toString()));
3473    }
3474
3475    // value > 0
3476    private void print(StringBuilder sb, BigDecimal value, Locale l,
3477               Flags f, char c, int precision, boolean neg)
3478        throws IOException
3479    {
3480        if (c == Conversion.SCIENTIFIC) {
3481        // Create a new BigDecimal with the desired precision.
3482        int prec = (precision == -1 ? 6 : precision);
3483        int scale = value.scale();
3484        int origPrec = value.precision();
3485        int nzeros = 0;
3486        int compPrec;
3487
3488        if (prec > origPrec - 1) {
3489            compPrec = origPrec;
3490            nzeros = prec - (origPrec - 1);
3491        } else {
3492            compPrec = prec + 1;
3493        }
3494
3495        MathContext mc = new MathContext(compPrec);
3496        BigDecimal v
3497            = new BigDecimal(value.unscaledValue(), scale, mc);
3498
3499        BigDecimalLayout bdl
3500            = new BigDecimalLayout(v.unscaledValue(), v.scale(),
3501                       BigDecimalLayoutForm.SCIENTIFIC);
3502
3503        char[] mant = bdl.mantissa();
3504
3505        // Add a decimal point if necessary.  The mantissa may not
3506        // contain a decimal point if the scale is zero (the internal
3507        // representation has no fractional part) or the original
3508        // precision is one. Append a decimal point if '#' is set or if
3509        // we require zero padding to get to the requested precision.
3510        if ((origPrec == 1 || !bdl.hasDot())
3511            && (nzeros > 0 || (f.contains(Flags.ALTERNATE))))
3512            mant = addDot(mant);
3513
3514        // Add trailing zeros in the case precision is greater than
3515        // the number of available digits after the decimal separator.
3516        mant = trailingZeros(mant, nzeros);
3517
3518        char[] exp = bdl.exponent();
3519        int newW = width;
3520        if (width != -1)
3521            newW = adjustWidth(width - exp.length - 1, f, neg);
3522        localizedMagnitude(sb, mant, f, newW, null);
3523
3524        sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3525
3526        Flags flags = f.dup().remove(Flags.GROUP);
3527        char sign = exp[0];
3528        assert(sign == '+' || sign == '-');
3529        sb.append(exp[0]);
3530
3531        char[] tmp = new char[exp.length - 1];
3532        System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3533        sb.append(localizedMagnitude(null, tmp, flags, -1, null));
3534        } else if (c == Conversion.DECIMAL_FLOAT) {
3535        // Create a new BigDecimal with the desired precision.
3536        int prec = (precision == -1 ? 6 : precision);
3537        int scale = value.scale();
3538                if (scale > prec) {
3539                    // more "scale" digits than the requested "precision
3540                    int compPrec = value.precision();
3541                    if (compPrec <= scale) {
3542                        // case of 0.xxxxxx
3543                        value = value.setScale(prec, RoundingMode.HALF_UP);
3544                    } else {
3545                        compPrec -= (scale - prec);
3546                        value = new BigDecimal(value.unscaledValue(),
3547                                               scale,
3548                                               new MathContext(compPrec));
3549                    }
3550                }
3551                BigDecimalLayout bdl = new BigDecimalLayout(
3552                                           value.unscaledValue(),
3553                                           value.scale(),
3554                                           BigDecimalLayoutForm.DECIMAL_FLOAT);
3555        char mant[] = bdl.mantissa();
3556        int nzeros = (bdl.scale() < prec ? prec - bdl.scale() : 0);
3557
3558        // Add a decimal point if necessary.  The mantissa may not
3559        // contain a decimal point if the scale is zero (the internal
3560        // representation has no fractional part).  Append a decimal
3561        // point if '#' is set or we require zero padding to get to the
3562        // requested precision.
3563        if (bdl.scale() == 0 && (f.contains(Flags.ALTERNATE) || nzeros > 0))
3564            mant = addDot(bdl.mantissa());
3565
3566        // Add trailing zeros if the precision is greater than the
3567        // number of available digits after the decimal separator.
3568        mant = trailingZeros(mant, nzeros);
3569
3570        localizedMagnitude(sb, mant, f, adjustWidth(width, f, neg), l);
3571        } else if (c == Conversion.GENERAL) {
3572        int prec = precision;
3573        if (precision == -1)
3574            prec = 6;
3575        else if (precision == 0)
3576            prec = 1;
3577
3578        BigDecimal tenToTheNegFour = BigDecimal.valueOf(1, 4);
3579        BigDecimal tenToThePrec = BigDecimal.valueOf(1, -prec);
3580        if ((value.equals(BigDecimal.ZERO))
3581            || ((value.compareTo(tenToTheNegFour) != -1)
3582            && (value.compareTo(tenToThePrec) == -1))) {
3583
3584            int e = - value.scale()
3585            + (value.unscaledValue().toString().length() - 1);
3586
3587            // xxx.yyy
3588            //   g precision (# sig digits) = #x + #y
3589            //   f precision = #y
3590            //   exponent = #x - 1
3591            // => f precision = g precision - exponent - 1
3592            // 0.000zzz
3593            //   g precision (# sig digits) = #z
3594            //   f precision = #0 (after '.') + #z
3595            //   exponent = - #0 (after '.') - 1
3596            // => f precision = g precision - exponent - 1
3597            prec = prec - e - 1;
3598
3599            print(sb, value, l, f, Conversion.DECIMAL_FLOAT, prec,
3600              neg);
3601        } else {
3602            print(sb, value, l, f, Conversion.SCIENTIFIC, prec - 1, neg);
3603        }
3604        } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3605        // This conversion isn't supported.  The error should be
3606        // reported earlier.
3607        assert false;
3608        }
3609    }
3610
3611    private class BigDecimalLayout {
3612        private StringBuilder mant;
3613        private StringBuilder exp;
3614        private boolean dot = false;
3615        private int scale;
3616
3617        public BigDecimalLayout(BigInteger intVal, int scale, BigDecimalLayoutForm form) {
3618        layout(intVal, scale, form);
3619        }
3620
3621        public boolean hasDot() {
3622        return dot;
3623        }
3624
3625        public int scale() {
3626        return scale;
3627        }
3628
3629        // char[] with canonical string representation
3630        public char[] layoutChars() {
3631        StringBuilder sb = new StringBuilder(mant);
3632        if (exp != null) {
3633            sb.append('E');
3634            sb.append(exp);
3635        }
3636        return toCharArray(sb);
3637        }
3638
3639        public char[] mantissa() {
3640        return toCharArray(mant);
3641        }
3642
3643        // The exponent will be formatted as a sign ('+' or '-') followed
3644        // by the exponent zero-padded to include at least two digits.
3645        public char[] exponent() {
3646        return toCharArray(exp);
3647        }
3648
3649        private char[] toCharArray(StringBuilder sb) {
3650        if (sb == null)
3651            return null;
3652        char[] result = new char[sb.length()];
3653        sb.getChars(0, result.length, result, 0);
3654        return result;
3655        }
3656
3657        private void layout(BigInteger intVal, int scale, BigDecimalLayoutForm form) {
3658        char coeff[] = intVal.toString().toCharArray();
3659        this.scale = scale;
3660
3661        // Construct a buffer, with sufficient capacity for all cases.
3662        // If E-notation is needed, length will be: +1 if negative, +1
3663        // if '.' needed, +2 for "E+", + up to 10 for adjusted
3664        // exponent.  Otherwise it could have +1 if negative, plus
3665        // leading "0.00000"
3666        mant = new StringBuilder(coeff.length + 14);
3667
3668        if (scale == 0) {
3669            int len = coeff.length;
3670            if (len > 1) {
3671            mant.append(coeff[0]);
3672            if (form == BigDecimalLayoutForm.SCIENTIFIC) {
3673                mant.append('.');
3674                dot = true;
3675                mant.append(coeff, 1, len - 1);
3676                exp = new StringBuilder("+");
3677                if (len < 10)
3678                exp.append("0").append(len - 1);
3679                else
3680                exp.append(len - 1);
3681            } else {
3682                mant.append(coeff, 1, len - 1);
3683            }
3684            } else {
3685            mant.append(coeff);
3686            if (form == BigDecimalLayoutForm.SCIENTIFIC)
3687                exp = new StringBuilder("+00");
3688            }
3689            return;
3690        }
3691        long adjusted = -(long) scale + (coeff.length - 1);
3692        if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
3693            // count of padding zeros
3694            int pad = scale - coeff.length;
3695            if (pad >= 0) {
3696            // 0.xxx form
3697            mant.append("0.");
3698            dot = true;
3699            for (; pad > 0 ; pad--) mant.append('0');
3700            mant.append(coeff);
3701            } else {
3702            if (-pad < coeff.length) {
3703                // xx.xx form
3704                mant.append(coeff, 0, -pad);
3705                mant.append('.');
3706                dot = true;
3707                mant.append(coeff, -pad, scale);
3708            } else {
3709                // xx form
3710                mant.append(coeff, 0, coeff.length);
3711                for (int i = 0; i < -scale; i++) 
3712                mant.append('0');
3713                this.scale = 0;
3714            }
3715            }
3716        } else {
3717            // x.xxx form
3718            mant.append(coeff[0]);
3719            if (coeff.length > 1) {
3720            mant.append('.');
3721            dot = true;
3722            mant.append(coeff, 1, coeff.length-1);
3723            }
3724            exp = new StringBuilder();
3725            if (adjusted != 0) {
3726            long abs = Math.abs(adjusted);
3727            // require sign
3728            exp.append(adjusted < 0 ? '-' : '+');
3729            if (abs < 10)
3730                exp.append('0');
3731            exp.append(abs);
3732            } else {
3733            exp.append("+00");
3734            }
3735        }
3736        }
3737    }
3738
3739    private int adjustWidth(int width, Flags f, boolean neg) {
3740        int newW = width;
3741        if (newW != -1 && neg && f.contains(Flags.PARENTHESES))
3742        newW--;
3743        return newW;
3744    }
3745
3746    // Add a '.' to th mantissa if required
3747    private char[] addDot(char[] mant) {
3748        char[] tmp = mant;
3749        tmp = new char[mant.length + 1];
3750        System.arraycopy(mant, 0, tmp, 0, mant.length);
3751        tmp[tmp.length - 1] = '.';
3752        return tmp;
3753    }
3754
3755    // Add trailing zeros in the case precision is greater than the number
3756    // of available digits after the decimal separator.
3757    private char[] trailingZeros(char[] mant, int nzeros) {
3758        char[] tmp = mant;
3759        if (nzeros > 0) {
3760        tmp = new char[mant.length + nzeros];
3761        System.arraycopy(mant, 0, tmp, 0, mant.length);
3762        for (int i = mant.length; i < tmp.length; i++)
3763            tmp[i] = '0';
3764        }
3765        return tmp;
3766    }
3767
3768    private void print(Calendar t, char c, Locale l)  throws IOException
3769    {
3770        StringBuilder sb = new StringBuilder();
3771        print(sb, t, c, l);
3772
3773        // justify based on width
3774        String s = justify(sb.toString());
3775        if (f.contains(Flags.UPPERCASE))
3776        s = s.toUpperCase();
3777
3778        a.append(s);
3779    }
3780
3781    private Appendable print(StringBuilder sb, Calendar t, char c,
3782                 Locale l)
3783        throws IOException
3784    {
3785        assert(width == -1);
3786        if (sb == null)
3787        sb = new StringBuilder();
3788        switch (c) {
3789        case DateTime.HOUR_OF_DAY_0: // 'H' (00 - 23)
3790        case DateTime.HOUR_0:        // 'I' (01 - 12)
3791        case DateTime.HOUR_OF_DAY:   // 'k' (0 - 23) -- like H
3792        case DateTime.HOUR:        { // 'l' (1 - 12) -- like I
3793        int i = t.get(Calendar.HOUR_OF_DAY);
3794        if (c == DateTime.HOUR_0 || c == DateTime.HOUR)
3795            i = (i == 0 || i == 12 ? 12 : i % 12);
3796        Flags flags = (c == DateTime.HOUR_OF_DAY_0
3797                   || c == DateTime.HOUR_0
3798                   ? Flags.ZERO_PAD
3799                   : Flags.NONE);
3800        sb.append(localizedMagnitude(null, i, flags, 2, l));
3801        break;
3802        }
3803        case DateTime.MINUTE:      { // 'M' (00 - 59)
3804        int i = t.get(Calendar.MINUTE);
3805        Flags flags = Flags.ZERO_PAD;
3806        sb.append(localizedMagnitude(null, i, flags, 2, l));
3807        break;
3808        }
3809        case DateTime.NANOSECOND:  { // 'N' (000000000 - 999999999)
3810        int i = t.get(Calendar.MILLISECOND) * 1000000;
3811        Flags flags = Flags.ZERO_PAD;
3812        sb.append(localizedMagnitude(null, i, flags, 9, l));
3813        break;
3814        }
3815        case DateTime.MILLISECOND: { // 'L' (000 - 999)
3816        int i = t.get(Calendar.MILLISECOND);
3817        Flags flags = Flags.ZERO_PAD;
3818        sb.append(localizedMagnitude(null, i, flags, 3, l));
3819        break;
3820        }
3821        case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
3822        long i = t.getTimeInMillis();
3823        Flags flags = Flags.NONE;
3824        sb.append(localizedMagnitude(null, i, flags, width, l));
3825        break;
3826        }
3827        case DateTime.AM_PM:       { // 'p' (am or pm)
3828        // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
3829        String[] ampm = { "AM", "PM" };
3830        if (l != null && l != Locale.US) {
3831            DateFormatSymbols dfs = DateFormatSymbols.getInstance(l);
3832            ampm = dfs.getAmPmStrings();
3833        }
3834        String s = ampm[t.get(Calendar.AM_PM)];
3835        sb.append(s.toLowerCase(l != null ? l : Locale.US));
3836        break;
3837        }
3838        case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
3839        long i = t.getTimeInMillis() / 1000;
3840        Flags flags = Flags.NONE;
3841        sb.append(localizedMagnitude(null, i, flags, width, l));
3842        break;
3843        }
3844        case DateTime.SECOND:      { // 'S' (00 - 60 - leap second)
3845        int i = t.get(Calendar.SECOND);
3846        Flags flags = Flags.ZERO_PAD;
3847        sb.append(localizedMagnitude(null, i, flags, 2, l));
3848        break;
3849        }
3850        case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
3851        int i = t.get(Calendar.ZONE_OFFSET);
3852        boolean neg = i < 0;
3853        sb.append(neg ? '-' : '+');
3854        if (neg)
3855            i = -i;
3856        int min = i / 60000;
3857        // combine minute and hour into a single integer
3858        int offset = (min / 60) * 100 + (min % 60);
3859        Flags flags = Flags.ZERO_PAD;
3860
3861        sb.append(localizedMagnitude(null, offset, flags, 4, l));
3862        break;
3863        }
3864        case DateTime.ZONE:        { // 'Z' (symbol)
3865        TimeZone tz = t.getTimeZone();
3866        sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0),
3867                       TimeZone.SHORT,
3868                       l));
3869        break;
3870        }
3871
3872            // Date
3873        case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
3874        case DateTime.NAME_OF_DAY:          { // 'A'
3875        int i = t.get(Calendar.DAY_OF_WEEK);
3876        Locale lt = ((l == null) ? Locale.US : l);
3877        DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
3878        if (c == DateTime.NAME_OF_DAY)
3879            sb.append(dfs.getWeekdays()[i]);
3880        else
3881            sb.append(dfs.getShortWeekdays()[i]);
3882        break;
3883        }
3884        case DateTime.NAME_OF_MONTH_ABBREV:   // 'b'
3885        case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
3886        case DateTime.NAME_OF_MONTH:        { // 'B'
3887        int i = t.get(Calendar.MONTH);
3888        Locale lt = ((l == null) ? Locale.US : l);
3889        DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
3890        if (c == DateTime.NAME_OF_MONTH)
3891            sb.append(dfs.getMonths()[i]);
3892        else
3893            sb.append(dfs.getShortMonths()[i]);
3894        break;
3895        }
3896        case DateTime.CENTURY:                // 'C' (00 - 99)
3897        case DateTime.YEAR_2:                 // 'y' (00 - 99)
3898        case DateTime.YEAR_4:               { // 'Y' (0000 - 9999)
3899        int i = t.get(Calendar.YEAR);
3900        int size = 2;
3901        switch (c) {
3902        case DateTime.CENTURY:
3903            i /= 100;
3904            break;
3905        case DateTime.YEAR_2:
3906            i %= 100;
3907            break;
3908        case DateTime.YEAR_4:
3909            size = 4;
3910            break;
3911        }
3912        Flags flags = Flags.ZERO_PAD;
3913        sb.append(localizedMagnitude(null, i, flags, size, l));
3914        break;
3915        }
3916        case DateTime.DAY_OF_MONTH_0:         // 'd' (01 - 31)
3917        case DateTime.DAY_OF_MONTH:         { // 'e' (1 - 31) -- like d
3918        int i = t.get(Calendar.DATE);
3919        Flags flags = (c == DateTime.DAY_OF_MONTH_0
3920                   ? Flags.ZERO_PAD
3921                   : Flags.NONE);
3922        sb.append(localizedMagnitude(null, i, flags, 2, l));
3923        break;
3924        }
3925        case DateTime.DAY_OF_YEAR:          { // 'j' (001 - 366)
3926        int i = t.get(Calendar.DAY_OF_YEAR);
3927        Flags flags = Flags.ZERO_PAD;
3928        sb.append(localizedMagnitude(null, i, flags, 3, l));
3929        break;
3930        }
3931        case DateTime.MONTH:                { // 'm' (01 - 12)
3932        int i = t.get(Calendar.MONTH) + 1;
3933        Flags flags = Flags.ZERO_PAD;
3934        sb.append(localizedMagnitude(null, i, flags, 2, l));
3935        break;
3936        }
3937
3938            // Composites
3939        case DateTime.TIME:         // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
3940        case DateTime.TIME_24_HOUR:    { // 'R' (hh:mm same as %H:%M)
3941        char sep = ':';
3942        print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
3943        print(sb, t, DateTime.MINUTE, l);
3944        if (c == DateTime.TIME) {
3945            sb.append(sep);
3946            print(sb, t, DateTime.SECOND, l);
3947        }
3948        break;
3949        }
3950        case DateTime.TIME_12_HOUR:    { // 'r' (hh:mm:ss [AP]M)
3951        char sep = ':';
3952        print(sb, t, DateTime.HOUR_0, l).append(sep);
3953        print(sb, t, DateTime.MINUTE, l).append(sep);
3954        print(sb, t, DateTime.SECOND, l).append(' ');
3955        // this may be in wrong place for some locales
3956        StringBuilder tsb = new StringBuilder();
3957        print(tsb, t, DateTime.AM_PM, l);
3958        sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
3959        break;
3960        }
3961        case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
3962        char sep = ' ';
3963        print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep);
3964        print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep);
3965        print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
3966        print(sb, t, DateTime.TIME, l).append(sep);
3967        print(sb, t, DateTime.ZONE, l).append(sep);
3968        print(sb, t, DateTime.YEAR_4, l);
3969        break;
3970        }
3971        case DateTime.DATE:            { // 'D' (mm/dd/yy)
3972        char sep = '/';
3973        print(sb, t, DateTime.MONTH, l).append(sep);
3974        print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
3975        print(sb, t, DateTime.YEAR_2, l);
3976        break;
3977        }
3978        case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
3979        char sep = '-';
3980        print(sb, t, DateTime.YEAR_4, l).append(sep);
3981        print(sb, t, DateTime.MONTH, l).append(sep);
3982        print(sb, t, DateTime.DAY_OF_MONTH_0, l);
3983        break;
3984        }
3985        default:
3986        assert false;
3987        }
3988        return sb;
3989    }
3990
3991    // -- Methods to support throwing exceptions --
3992
3993    private void failMismatch(Flags f, char c) {
3994        String fs = f.toString();
3995        throw new FormatFlagsConversionMismatchException(fs, c);
3996    }
3997
3998    private void failConversion(char c, Object arg) {
3999        throw new IllegalFormatConversionException(c, arg.getClass());
4000    }
4001
4002    private char getZero(Locale l) {
4003        if ((l != null) &&  !l.equals(locale())) {
4004        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4005        return dfs.getZeroDigit();
4006        }
4007        return zero;
4008    }
4009
4010    private StringBuilder
4011        localizedMagnitude(StringBuilder sb, long value, Flags f,
4012                   int width, Locale l)
4013    {
4014        char[] va = Long.toString(value, 10).toCharArray();
4015        return localizedMagnitude(sb, va, f, width, l);
4016    }
4017
4018    private StringBuilder
4019        localizedMagnitude(StringBuilder sb, char[] value, Flags f,
4020                   int width, Locale l)
4021    {
4022        if (sb == null)
4023        sb = new StringBuilder();
4024        int begin = sb.length();
4025
4026        char zero = getZero(l);
4027
4028        // determine localized grouping separator and size
4029        char grpSep = '\0';
4030        int  grpSize = -1;
4031        char decSep = '\0';
4032
4033        int len = value.length;
4034        int dot = len;
4035        for (int j = 0; j < len; j++) {
4036        if (value[j] == '.') {
4037            dot = j;
4038            break;
4039        }
4040        }
4041
4042        if (dot < len) {
4043        if (l == null || l.equals(Locale.US)) {
4044            decSep  = '.';
4045        } else {
4046            DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4047            decSep  = dfs.getDecimalSeparator();
4048        }
4049        }
4050
4051        if (f.contains(Flags.GROUP)) {
4052        if (l == null || l.equals(Locale.US)) {
4053            grpSep = ',';
4054            grpSize = 3;
4055        } else {
4056            DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4057            grpSep = dfs.getGroupingSeparator();
4058            DecimalFormat df = (DecimalFormat) NumberFormat.getIntegerInstance(l);
4059            grpSize = df.getGroupingSize();
4060        }
4061        }
4062
4063        // localize the digits inserting group separators as necessary
4064        for (int j = 0; j < len; j++) {
4065        if (j == dot) {
4066            sb.append(decSep);
4067            // no more group separators after the decimal separator
4068            grpSep = '\0';
4069            continue;
4070        }
4071
4072        char c = value[j];
4073        sb.append((char) ((c - '0') + zero));
4074        if (grpSep != '\0' && j != dot - 1 && ((dot - j) % grpSize == 1))
4075            sb.append(grpSep);
4076        }
4077
4078        // apply zero padding
4079        len = sb.length();
4080        if (width != -1 && f.contains(Flags.ZERO_PAD))
4081        for (int k = 0; k < width - len; k++)
4082            sb.insert(begin, zero);
4083
4084        return sb;
4085    }
4086    }
4087
4088    private static class Flags {
4089    private int flags;
4090
4091    static final Flags NONE          = new Flags(0);      // ''
4092
4093    // duplicate declarations from Formattable.java
4094    static final Flags LEFT_JUSTIFY  = new Flags(1<<0);   // '-'
4095    static final Flags UPPERCASE     = new Flags(1<<1);   // '^'
4096    static final Flags ALTERNATE     = new Flags(1<<2);   // '#'
4097
4098    // numerics
4099        static final Flags PLUS          = new Flags(1<<3);   // '+'
4100        static final Flags LEADING_SPACE = new Flags(1<<4);   // ' '
4101        static final Flags ZERO_PAD      = new Flags(1<<5);   // '0'
4102        static final Flags GROUP         = new Flags(1<<6);   // ','
4103        static final Flags PARENTHESES   = new Flags(1<<7);   // '('
4104
4105    // indexing
4106    static final Flags PREVIOUS      = new Flags(1<<8);   // '<'
4107
4108    private Flags(int f) {
4109        flags = f;
4110    }
4111
4112    public int valueOf() {
4113        return flags;
4114    }
4115
4116    public boolean contains(Flags f) {
4117        return (flags & f.valueOf()) == f.valueOf();
4118    }
4119
4120    public Flags dup() {
4121        return new Flags(flags);
4122    }
4123
4124    private Flags add(Flags f) {
4125        flags |= f.valueOf();
4126        return this;
4127    }
4128
4129    public Flags remove(Flags f) {
4130        flags &= ~f.valueOf();
4131        return this;
4132    }
4133
4134    public static Flags parse(String s) {
4135        char[] ca = s.toCharArray();
4136        Flags f = new Flags(0);
4137        for (int i = 0; i < ca.length; i++) {
4138        Flags v = parse(ca[i]);
4139        if (f.contains(v))
4140            throw new DuplicateFormatFlagsException(v.toString());
4141        f.add(v);
4142        }
4143        return f;
4144    }
4145
4146    // parse those flags which may be provided by users
4147    private static Flags parse(char c) {
4148        switch (c) {
4149        case '-': return LEFT_JUSTIFY;
4150        case '#': return ALTERNATE;
4151        case '+': return PLUS;
4152        case ' ': return LEADING_SPACE;
4153        case '0': return ZERO_PAD;
4154        case ',': return GROUP;
4155        case '(': return PARENTHESES;
4156        case '<': return PREVIOUS;
4157        default:
4158        throw new UnknownFormatFlagsException(String.valueOf(c));
4159        }
4160    }
4161
4162    // Returns a string representation of the current <tt>Flags</tt>.
4163    public static String toString(Flags f) {
4164        return f.toString();
4165    }
4166
4167    public String toString() {
4168        StringBuilder sb = new StringBuilder();
4169        if (contains(LEFT_JUSTIFY))  sb.append('-');
4170        if (contains(UPPERCASE))     sb.append('^');
4171        if (contains(ALTERNATE))     sb.append('#');
4172        if (contains(PLUS))          sb.append('+');
4173        if (contains(LEADING_SPACE)) sb.append(' ');
4174        if (contains(ZERO_PAD))      sb.append('0');
4175        if (contains(GROUP))         sb.append(',');
4176        if (contains(PARENTHESES))   sb.append('(');
4177        if (contains(PREVIOUS))      sb.append('<');
4178        return sb.toString();
4179    }
4180    }
4181
4182    private static class Conversion {
4183        // Byte, Short, Integer, Long, BigInteger
4184        // (and associated primitives due to autoboxing)
4185    static final char DECIMAL_INTEGER     = 'd';
4186    static final char OCTAL_INTEGER       = 'o';
4187    static final char HEXADECIMAL_INTEGER = 'x';
4188    static final char HEXADECIMAL_INTEGER_UPPER = 'X';
4189
4190        // Float, Double, BigDecimal
4191        // (and associated primitives due to autoboxing)
4192    static final char SCIENTIFIC          = 'e';
4193    static final char SCIENTIFIC_UPPER    = 'E';
4194    static final char GENERAL             = 'g';
4195    static final char GENERAL_UPPER       = 'G';
4196    static final char DECIMAL_FLOAT       = 'f';
4197    static final char HEXADECIMAL_FLOAT   = 'a';
4198    static final char HEXADECIMAL_FLOAT_UPPER = 'A';
4199
4200        // Character, Byte, Short, Integer
4201        // (and associated primitives due to autoboxing)
4202    static final char CHARACTER           = 'c';
4203    static final char CHARACTER_UPPER     = 'C';
4204
4205        // java.util.Date, java.util.Calendar, long
4206    static final char DATE_TIME           = 't';
4207    static final char DATE_TIME_UPPER     = 'T';
4208
4209        // if (arg.TYPE != boolean) return boolean
4210        // if (arg != null) return true; else return false;
4211    static final char BOOLEAN             = 'b';
4212    static final char BOOLEAN_UPPER       = 'B';
4213        // if (arg instanceof Formattable) arg.formatTo()
4214        // else arg.toString();
4215    static final char STRING              = 's';
4216    static final char STRING_UPPER        = 'S';
4217        // arg.hashCode()
4218    static final char HASHCODE            = 'h';
4219    static final char HASHCODE_UPPER      = 'H';
4220
4221    static final char LINE_SEPARATOR      = 'n';
4222    static final char PERCENT_SIGN        = '%';
4223
4224    static boolean isValid(char c) {
4225        return (isGeneral(c) || isInteger(c) || isFloat(c) || isText(c)
4226            || c == 't' || isCharacter(c));
4227    }
4228
4229    // Returns true iff the Conversion is applicable to all objects.
4230    static boolean isGeneral(char c) {
4231        switch (c) {
4232        case BOOLEAN:
4233        case BOOLEAN_UPPER:
4234        case STRING:
4235        case STRING_UPPER:
4236        case HASHCODE:
4237        case HASHCODE_UPPER:
4238        return true;
4239        default:
4240        return false;
4241        }
4242    }
4243
4244    // Returns true iff the Conversion is applicable to character.
4245    static boolean isCharacter(char c) {
4246        switch (c) {
4247        case CHARACTER:
4248        case CHARACTER_UPPER:
4249        return true;
4250        default:
4251        return false;
4252        }
4253    }
4254
4255    // Returns true iff the Conversion is an integer type.
4256    static boolean isInteger(char c) {
4257        switch (c) {
4258        case DECIMAL_INTEGER:
4259        case OCTAL_INTEGER:
4260        case HEXADECIMAL_INTEGER:
4261        case HEXADECIMAL_INTEGER_UPPER:
4262        return true;
4263        default:
4264        return false;
4265        }
4266    }
4267
4268    // Returns true iff the Conversion is a floating-point type.
4269    static boolean isFloat(char c) {
4270        switch (c) {
4271        case SCIENTIFIC:
4272        case SCIENTIFIC_UPPER:
4273        case GENERAL:
4274        case GENERAL_UPPER:
4275        case DECIMAL_FLOAT:
4276        case HEXADECIMAL_FLOAT:
4277        case HEXADECIMAL_FLOAT_UPPER:
4278        return true;
4279        default:
4280        return false;
4281        }
4282    }
4283
4284    // Returns true iff the Conversion does not require an argument
4285    static boolean isText(char c) {
4286        switch (c) {
4287        case LINE_SEPARATOR:
4288        case PERCENT_SIGN:
4289        return true;
4290        default:
4291        return false;
4292        }
4293    }
4294    }
4295
4296    private static class DateTime {
4297        static final char HOUR_OF_DAY_0 = 'H'; // (00 - 23)
4298        static final char HOUR_0        = 'I'; // (01 - 12)
4299        static final char HOUR_OF_DAY   = 'k'; // (0 - 23) -- like H
4300        static final char HOUR          = 'l'; // (1 - 12) -- like I
4301        static final char MINUTE        = 'M'; // (00 - 59)
4302        static final char NANOSECOND    = 'N'; // (000000000 - 999999999)
4303        static final char MILLISECOND   = 'L'; // jdk, not in gnu (000 - 999)
4304        static final char MILLISECOND_SINCE_EPOCH = 'Q'; // (0 - 99...?)
4305        static final char AM_PM         = 'p'; // (am or pm)
4306        static final char SECONDS_SINCE_EPOCH = 's'; // (0 - 99...?)
4307        static final char SECOND        = 'S'; // (00 - 60 - leap second)
4308        static final char TIME          = 'T'; // (24 hour hh:mm:ss)
4309        static final char ZONE_NUMERIC  = 'z'; // (-1200 - +1200) - ls minus?
4310        static final char ZONE          = 'Z'; // (symbol)
4311
4312        // Date
4313        static final char NAME_OF_DAY_ABBREV    = 'a'; // 'a'
4314        static final char NAME_OF_DAY           = 'A'; // 'A'
4315        static final char NAME_OF_MONTH_ABBREV  = 'b'; // 'b'
4316        static final char NAME_OF_MONTH         = 'B'; // 'B'
4317        static final char CENTURY               = 'C'; // (00 - 99)
4318        static final char DAY_OF_MONTH_0        = 'd'; // (01 - 31)
4319        static final char DAY_OF_MONTH          = 'e'; // (1 - 31) -- like d
4320// *    static final char ISO_WEEK_OF_YEAR_2    = 'g'; // cross %y %V
4321// *    static final char ISO_WEEK_OF_YEAR_4    = 'G'; // cross %Y %V
4322        static final char NAME_OF_MONTH_ABBREV_X  = 'h'; // -- same b
4323        static final char DAY_OF_YEAR           = 'j'; // (001 - 366)
4324    static final char MONTH                 = 'm'; // (01 - 12)
4325// *    static final char DAY_OF_WEEK_1         = 'u'; // (1 - 7) Monday
4326// *    static final char WEEK_OF_YEAR_SUNDAY   = 'U'; // (0 - 53) Sunday+
4327// *    static final char WEEK_OF_YEAR_MONDAY_01 = 'V'; // (01 - 53) Monday+
4328// *    static final char DAY_OF_WEEK_0         = 'w'; // (0 - 6) Sunday
4329// *    static final char WEEK_OF_YEAR_MONDAY   = 'W'; // (00 - 53) Monday
4330        static final char YEAR_2                = 'y'; // (00 - 99)
4331        static final char YEAR_4                = 'Y'; // (0000 - 9999)
4332
4333    // Composites
4334        static final char TIME_12_HOUR  = 'r'; // (hh:mm:ss [AP]M)
4335        static final char TIME_24_HOUR  = 'R'; // (hh:mm same as %H:%M)
4336// *    static final char LOCALE_TIME   = 'X'; // (%H:%M:%S) - parse format?
4337        static final char DATE_TIME             = 'c';
4338                                            // (Sat Nov 04 12:02:33 EST 1999)
4339        static final char DATE                  = 'D'; // (mm/dd/yy)
4340        static final char ISO_STANDARD_DATE     = 'F'; // (%Y-%m-%d)
4341// *    static final char LOCALE_DATE           = 'x'; // (mm/dd/yy)
4342
4343    static boolean isValid(char c) {
4344        switch (c) {
4345        case HOUR_OF_DAY_0:
4346        case HOUR_0:
4347        case HOUR_OF_DAY:
4348        case HOUR:
4349        case MINUTE:
4350        case NANOSECOND:
4351        case MILLISECOND:
4352        case MILLISECOND_SINCE_EPOCH:
4353        case AM_PM:
4354        case SECONDS_SINCE_EPOCH:
4355        case SECOND:
4356        case TIME:
4357        case ZONE_NUMERIC:
4358        case ZONE:
4359
4360            // Date
4361        case NAME_OF_DAY_ABBREV:
4362        case NAME_OF_DAY:
4363        case NAME_OF_MONTH_ABBREV:
4364        case NAME_OF_MONTH:
4365        case CENTURY:
4366        case DAY_OF_MONTH_0:
4367        case DAY_OF_MONTH:
4368// *        case ISO_WEEK_OF_YEAR_2:
4369// *        case ISO_WEEK_OF_YEAR_4:
4370        case NAME_OF_MONTH_ABBREV_X:
4371        case DAY_OF_YEAR:
4372        case MONTH:
4373// *        case DAY_OF_WEEK_1:
4374// *        case WEEK_OF_YEAR_SUNDAY:
4375// *        case WEEK_OF_YEAR_MONDAY_01:
4376// *        case DAY_OF_WEEK_0:
4377// *        case WEEK_OF_YEAR_MONDAY:
4378        case YEAR_2:
4379        case YEAR_4:
4380
4381        // Composites
4382        case TIME_12_HOUR:
4383        case TIME_24_HOUR:
4384// *        case LOCALE_TIME:
4385        case DATE_TIME:
4386        case DATE:
4387        case ISO_STANDARD_DATE:
4388// *        case LOCALE_DATE:
4389        return true;
4390        default:
4391        return false;
4392        }
4393    }
4394    }
4395}
4396