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