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