History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/Formatter.java (1 of 18352 files). Show all

Unified · Split

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