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