1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership.
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License.  You may obtain a copy of the License at
72c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
92c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.util;
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.BufferedWriter;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Closeable;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.File;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FileNotFoundException;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FileOutputStream;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Flushable;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.OutputStream;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.OutputStreamWriter;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintStream;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.UnsupportedEncodingException;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigDecimal;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger;
313819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.math.MathContext;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.charset.Charset;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AccessController;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivilegedAction;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.text.DateFormatSymbols;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.text.DecimalFormat;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.text.DecimalFormatSymbols;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.text.NumberFormat;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40bb3b16f46964155b9ceead25db1c0e3841ce61a7Dan Egnor// BEGIN android-added
41bb3b16f46964155b9ceead25db1c0e3841ce61a7Dan Egnorimport org.apache.harmony.luni.util.LocaleCache;
42bb3b16f46964155b9ceead25db1c0e3841ce61a7Dan Egnor// END android-added
43bb3b16f46964155b9ceead25db1c0e3841ce61a7Dan Egnor
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
45612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Formats arguments according to a format string (like {@code printf} in C).
46612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
47612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * It's relatively rare to use a {@code Formatter} directly. A variety of classes offer convenience
48612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * methods for accessing formatter functionality.
490c7c39cce1c6f052cd2afa4fc1ad99de70b37dd6Elliott Hughes * Of these, {@link String#format} is generally the most useful.
500c7c39cce1c6f052cd2afa4fc1ad99de70b37dd6Elliott Hughes * {@link java.io.PrintStream} and {@link java.io.PrintWriter} both offer
510c7c39cce1c6f052cd2afa4fc1ad99de70b37dd6Elliott Hughes * {@code format} and {@code printf} methods.
52612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
53612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Format strings</i> consist of plain text interspersed with format specifiers, such
54612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * as {@code "name: %s weight: %03dkg\n"}. Being a Java string, the usual Java string literal
55612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * backslash escapes are of course available.
56612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
57612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Format specifiers</i> (such as {@code "%s"} or {@code "%03d"} in the example) start with a
58612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code %} and describe how to format their corresponding argument. It includes an optional
59612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * argument index, optional flags, an optional width, an optional precision, and a mandatory
60612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * conversion type.
61612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * In the example, {@code "%s"} has no flags, no width, and no precision, while
62612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code "%03d"} has the flag {@code 0}, the width 3, and no precision.
63612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
64612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Not all combinations of argument index, flags, width, precision, and conversion type
65612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * are valid.
66612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
67612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Argument index</i>. Normally, each format specifier consumes the next argument to
68612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code format}.
69612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * For convenient localization, it's possible to reorder arguments so that they appear in a
70612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * different order in the output than the order in which they were supplied.
71612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * For example, {@code "%4$s"} formats the fourth argument ({@code 4$}) as a string ({@code s}).
72612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * It's also possible to reuse an argument with {@code <}. For example,
73612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code format("%o %<d %<x", 64)} results in {@code "100 64 40"}.
74612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
75612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Flags</i>. The available flags are:
76612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
78612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> <TD COLSPAN=4> <B>Flags</B> </TD> </tr>
79612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
80612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code ,}</td>
81612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Use grouping separators for large numbers. (Decimal only.)</td>
82612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%,d", 1024);}</td>
83612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 1,234}</td>
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
86612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code +}</td>
87612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Always show sign. (Decimal only.)</td>
88612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td>
89612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>+5,   +5</pre></td>
903819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
92612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code  }</td>
93612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">A space indicates that non-negative numbers
94612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * should have a leading space. (Decimal only.)</td>
95612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td>
96612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>x 4    4</pre></td>
973819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
99612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code (}</td>
100612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Put parentheses around negative numbers. (Decimal only.)</td>
101612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td>
102612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>12, (12),   (12)</pre></td>
1033819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
105612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code -}</td>
106612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Left-justify. (Requires width.)</td>
107612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%-6dx", 5);}<br/>{@code format("%-3C, %3C", 'd', 0x65);}</td>
108612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>5      x</pre><br/><pre>D  ,   E</pre></td>
1093819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
110612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
111612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code 0}</td>
112612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Pad the number with leading zeros. (Requires width.)</td>
113612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td>
114612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 0000004, 5555}</td>
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
117612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code #}</td>
118612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Alternate form. (Octal and hex only.) </td>
119612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%o %#o", 010, 010);}<br/>{@code format("%x %#x", 0x12, 0x12);}</td>
120612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 10 010}<br/>{@code 12 0x12}</td>
1213819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
122612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </table>
123612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
124612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Width</i>. The width is a decimal integer specifying the minimum number of characters to be
125612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * used to represent the argument. If the result would otherwise be shorter than the width, padding
126612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * will be added (the exact details of which depend on the flags). Note that you can't use width to
127612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * truncate a field, only to make it wider: see precision for control over the maximum width.
128612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
129612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Precision</i>. The precision is a {@code .} followed by a decimal integer, giving the minimum
130612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * number of digits for {@code d}, {@code o}, {@code x}, or {@code X}; the minimum number of digits
131612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * after the decimal point for {@code a}, {@code A}, {@code e}, {@code E}, {@code f}, or {@code F};
132612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * the maximum number of significant digits for {@code g} or {@code G}; or the maximum number of
133612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * characters for {@code s} or {@code S}.
134612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
135612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <i>Conversion type</i>. One or two characters describing how to interpret the argument. Most
136612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * conversions are a single character, but date/time conversions all start with {@code t} and
137612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * have a single extra character describing the desired output.
138612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
139612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Many conversion types have a corresponding uppercase variant that converts its result to
140612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * uppercase using the rules of the relevant locale (either the default or the locale set for
141612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * this formatter).
142612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
143612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * This table shows the available single-character (non-date/time) conversion types:
144612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <TD COLSPAN=4>
147612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>String conversions</B>
148612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
149612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * All types are acceptable arguments. Values of type {@link Formattable} have their
150612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code formatTo} method invoked; all other types use {@code toString}.
151612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
154612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code s}</td>
155612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">String.</td>
156612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%s %s", "hello", "Hello");}</td>
157612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code hello Hello}</td>
1583819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
160612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code S}</td>
161612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Uppercase string.</td>
162612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%S %S", "hello", "Hello");}</td>
163612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code HELLO HELLO}</td>
1643819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <TD COLSPAN=4>
167612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>Character conversions</B>
168612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
169612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Byte, Character, Short, and Integer (and primitives that box to those types) are all acceptable
170612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * as character arguments. Any other type is an error.
171612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
174612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code c}</td>
175612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Character.</td>
176612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%c %c", 'd', 'E');}</td>
177612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code d E}</td>
1783819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
180612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code C}</td>
181612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Uppercase character.</td>
182612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%C %C", 'd', 'E');}</td>
183612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code D E}</td>
1843819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
185612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
186612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <TD COLSPAN=4>
187612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>Integer conversions</B>
188612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
189612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Byte, Short, Integer, Long, and BigInteger (and primitives that box to those types) are all
190612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * acceptable as integer arguments. Any other type is an error.
191612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
1923819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
194612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code d}</td>
195612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Decimal.</td>
196612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%d", 26);}</td>
197612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 26}</td>
1983819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
200612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code o}</td>
201612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Octal.</td>
202612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%o", 032);}</td>
203612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 32}</td>
2043819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
206612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code x}, {@code X}</td>
207612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Hexadecimal.</td>
208612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%x %X", 0x1a, 0x1a);}</td>
209612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 1a 1A}</td>
2103819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
212612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <TD COLSPAN=4><B>Floating-point conversions</B>
213612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
214612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Float, Double, and BigDecimal (and primitives that box to those types) are all acceptable as
215612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * floating-point arguments. Any other type is an error.
216612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
2193819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * <td width="5%">{@code f}</td>
220612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Decimal floating point.</td>
221612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>
222612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%f", 123.456f);
223612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%.1f", 123.456f);
224612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%1.5f", 123.456f);
225612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%10f", 123.456f);
226612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%6.0f", 123.456f);</td>
227612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%" valign="top"><pre>
228612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes123.456001
229612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes123.5
230612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes123.45600
231612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes123.456001
232612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes&nbsp;&nbsp;&nbsp;123</pre></td>
2333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
235612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code e}, {@code E}</td>
236612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Engineering/exponential floating point.</td>
237612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"><pre>
238612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%e", 123.456f);
239612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%.1e", 123.456f);
240612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%1.5E", 123.456f);
241612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%10E", 123.456f);
242612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughesformat("%6.0E", 123.456f);</td>
243612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%" valign="top"><pre>
244612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes1.234560e+02
245612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes1.2e+02
246612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes1.23456E+02
247612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes1.234560E+02
248612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes&nbsp;1E+02</pre></td>
2493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
251612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%" valign="top">{@code g}, {@code G}</td>
252612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%" valign="top">Decimal or engineering, depending on the magnitude of the value.</td>
253612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%" valign="top">{@code format("%g %g", 0.123, 0.0000123);}</td>
254612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%" valign="top">{@code 0.123000 1.23000e-05}</td>
2553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
257612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code a}, {@code A}</td>
258612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Hexadecimal floating point.</td>
259612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%a", 123.456f);}</td>
260612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 0x1.edd2f2p6}</td>
2613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <TD COLSPAN=4>
264612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>Boolean conversion</B>
265612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
266612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Accepts Boolean values. {@code null} is considered false, and instances of all other
267612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * types are considered true.
268612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
271612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code b}, {@code B}</td>
272612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Boolean.</td>
273612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%b %b", true, false);}<br>{@code format("%B %B", true, false);}<br>{@code format("%b", null);}<br>{@code format("%b", "hello");}</td>
274612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code true false}<br>{@code TRUE FALSE}<br>{@code false}<br>{@code true}</td>
2753819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <TD COLSPAN=4>
278612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>Hash code conversion</B>
279612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
280612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Invokes {@code hashCode} on its argument, which may be of any type.
281612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
284612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code h}, {@code H}</td>
285612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Hexadecimal hash code.</td>
286612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%h", this);}<br>{@code format("%H", this);}<br>{@code format("%h", null);}</td>
287612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 190d11}<br>{@code 190D11}<br>{@code null}</td>
2883819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <TD COLSPAN=4>
291612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <B>Zero-argument conversions</B></TD>
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
294612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code %}</td>
295612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">A literal % character.</td>
296612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%d%%", 50);}</td>
297612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 50%}</td>
2983819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
300612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code n}</td>
301612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Newline. (The value of the system property {@code "line.separator"}.)</td>
302612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("first%nsecond");}</td>
303612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code first\nsecond}</td>
304612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
305612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </table>
306612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
307612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * It's also possible to format dates and times with {@code Formatter}, though you should seriously
30845071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * consider using {@link java.text.SimpleDateFormat} via the factory methods in
30945071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * {@link java.text.DateFormat} instead.
310612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * The facilities offered by {@code Formatter} are low-level and place the burden of localization
31145071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * on the developer. Using {@link java.text.DateFormat#getDateInstance},
31245071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * {@link java.text.DateFormat#getTimeInstance}, and
31345071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * {@link java.text.DateFormat#getDateTimeInstance} is preferable for dates and times that will be
314612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * presented to a human. Those methods will select the best format strings for the user's locale.
315612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
316612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * The best non-localized form is <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a>,
317612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * which you can get with {@code "%tF"} (2010-01-22), {@code "%tF %tR"} (2010-01-22 13:39),
318612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code "%tF %tT"} (2010-01-22 13:39:15), or {@code "%tF %tT%z"} (2010-01-22 13:39:15-0800).
319612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
320612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * As with the other conversions, date/time conversion has an uppercase format. Replacing
321612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * {@code %t} with {@code %T} will uppercase the field according to the rules of the formatter's
322612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * locale.
323612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
324612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * This table shows the date/time conversions:
325612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
326612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
327612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <TD COLSPAN=4><B>Date/time conversions</B>
328612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <br>
329612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Calendar, Date, and Long (representing milliseconds past the epoch) are all acceptable
330612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * as date/time arguments. Any other type is an error. The epoch is 1970-01-01 00:00:00 UTC.
331612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </TD>
3323819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
334612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code ta}</td>
335612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Localized weekday name (abbreviated).</td>
336612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%ta", cal, cal);}</td>
337612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code Tue}</td>
338612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
339612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
340612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tA}</td>
341612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Localized weekday name (full).</td>
342612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tA", cal, cal);}</td>
343612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code Tuesday}</td>
344612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
345612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
346612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tb}</td>
347612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Localized month name (abbreviated).</td>
348612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tb", cal);}</td>
349612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code Apr}</td>
350612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
351612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
352612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tB}</td>
353612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Localized month name (full).</td>
354612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tB", cal);}</td>
355612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code April}</td>
356612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
357612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
358612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tc}</td>
35945071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * <td width="25%">Locale-preferred date and time representation. (See {@link java.text.DateFormat} for more variations.)</td>
360612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tc", cal);}</td>
361612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code Tue Apr 01 16:19:17 CEST 2008}</td>
362612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
363612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
364612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tC}</td>
365612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit century.</td>
366612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tC", cal);}</td>
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <td width="30%">{@code 20}</td>
3683819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
370612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code td}</td>
371612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit day of month (01-31).</td>
372612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%td", cal);}</td>
373612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 01}</td>
374612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
375612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
376612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tD}</td>
377612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Ambiguous US date format (MM/DD/YY). Do not use.</td>
378612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tD", cal);}</td>
379612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 04/01/08}</td>
380612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
381612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
382612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code te}</td>
383612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Day of month (1-31).</td>
384612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%te", cal);}</td>
385612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 1}</td>
3863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
388612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tF}</td>
389612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Full date in ISO 8601 format (YYYY-MM-DD).</td>
3903819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * <td width="30%">{@code format("%tF", cal);}</td>
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <td width="30%">{@code 2008-04-01}</td>
3923819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
394612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code th}</td>
395612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Synonym for {@code %tb}.</td>
396612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"></td>
397612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%"></td>
3983819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
400612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tH}</td>
401612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">24-hour hour of day (00-23).</td>
402612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tH", cal);}</td>
403612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 16}</td>
404612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
405612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
406612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tI}</td>
407612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">12-hour hour of day (01-12).</td>
408612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tH", cal);}</td>
409612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 04}</td>
410612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
411612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
412612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tj}</td>
413612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">3-digit day of year (001-366).</td>
414612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tj", cal);}</td>
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <td width="30%">{@code 092}</td>
4163819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
418612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tk}</td>
419612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">24-hour hour of day (0-23).</td>
420612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tH", cal);}</td>
421612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 16}</td>
422612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
423612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
424612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tl}</td>
425612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">12-hour hour of day (1-12).</td>
426612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tH", cal);}</td>
427612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 4}</td>
428612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
429612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
430612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tL}</td>
431612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Milliseconds.</td>
432612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tL", cal);}</td>
433612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 359}</td>
434612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * </tr>
435612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
436612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tm}</td>
437612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit month of year (01-12).</td>
438612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tm", cal);}</td>
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <td width="30%">{@code 04}</td>
4403819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
442612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tM}</td>
443612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit minute.</td>
444612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tM", cal);}</td>
445612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 08}</td>
4463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
448612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tN}</td>
449612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Nanoseconds.</td>
450612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tN", cal);}</td>
451612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 359000000}</td>
4523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
454612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tp}</td>
455612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">a.m. or p.m.</td>
4563819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td>
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <td width="30%">{@code pm PM}</td>
4583819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
460612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tQ}</td>
461612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Milliseconds since the epoch.</td>
462612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tQ", cal);}</td>
463612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 1207059412656}</td>
4643819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
466612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tr}</td>
467612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Full 12-hour time ({@code %tI:%tM:%tS %Tp}).</td>
468612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tr", cal);}</td>
469612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 04:15:32 PM}</td>
4703819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
472612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tR}</td>
473612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Short 24-hour time ({@code %tH:%tM}).</td>
474612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tR", cal);}</td>
475612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 16:15}</td>
4763819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
478612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code ts}</td>
479612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Seconds since the epoch.</td>
480612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%ts", cal);}</td>
481612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 1207059412}</td>
4823819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
484612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tS}</td>
485612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit seconds (00-60).</td>
486612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tS", cal);}</td>
487612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 17}</td>
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
490612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tT}</td>
491612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Full 24-hour time ({@code %tH:%tM:%tS}).</td>
492612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tT", cal);}</td>
493612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 16:15:32}</td>
4943819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
496612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code ty}</td>
497612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">2-digit year (00-99).</td>
498612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%ty", cal);}</td>
499612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 08}</td>
5003819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
502612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tY}</td>
503612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">4-digit year.</td>
504612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tY", cal);}</td>
505612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code 2008}</td>
5063819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
507612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <tr>
508612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tz}</td>
509612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Time zone GMT offset.</td>
510612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tz", cal);}</td>
511612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code +0100}</td>
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </tr>
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <tr>
514612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="5%">{@code tZ}</td>
515612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="25%">Localized time zone abbreviation.</td>
516612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code format("%tZ", cal);}</td>
517612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <td width="30%">{@code CEST}</td>
5183819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </tr>
5193819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * </table>
520612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * <p>
521612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * Formatter is not thread-safe.
5223819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson *
5233819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * @since 1.5
52445071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * @see java.text.DateFormat
525612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes * @see Formattable
52645071dd09330c9399735b13c81f8d75e4c6bfa0dElliott Hughes * @see java.text.SimpleDateFormat
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class Formatter implements Closeable, Flushable {
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The enumeration giving the available styles for formatting very large
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * decimal numbers.
5333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     */
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public enum BigDecimalLayoutForm {
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Use scientific style for BigDecimals.
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        SCIENTIFIC,
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Use normal decimal/float style for BigDecimals.
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DECIMAL_FLOAT
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Appendable out;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Locale locale;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean closed = false;
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private IOException lastIOException;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter}.
5553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The output is written to a {@code StringBuilder} which can be acquired by invoking
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #out()} and whose content can be obtained by calling
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code toString()}.
5593819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter() {
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new StringBuilder(), Locale.getDefault());
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
5673819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} whose output will be written to the
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * specified {@code Appendable}.
5693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The locale for the {@code Formatter} is the default {@code Locale}.
5713819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param a
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then a {@code StringBuilder} will be used.
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(Appendable a) {
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(a, Locale.getDefault());
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} with the specified {@code Locale}.
5823819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The output is written to a {@code StringBuilder} which can be acquired by invoking
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #out()} and whose content can be obtained by calling
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code toString()}.
5863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then no localization will be used.
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(Locale l) {
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new StringBuilder(), l);
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
5963819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the specified {@code Locale}
5973819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * and whose output will be written to the
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * specified {@code Appendable}.
5993819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param a
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then a {@code StringBuilder} will be used.
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then no localization will be used.
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(Appendable a, Locale l) {
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (null == a) {
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out = new StringBuilder();
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out = a;
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = l;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} whose output is written to the specified file.
6183819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The charset of the {@code Formatter} is the default charset.
6203819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
6223819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param fileName
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the filename of the file that is used as the output
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            destination for the {@code Formatter}. The file will be truncated to
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            zero size if the file exists, or else a new file will be
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            created. The output of the {@code Formatter} is buffered.
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the filename does not denote a normal and writable file,
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             or if a new file cannot be created, or if any error arises when
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             opening or creating the file.
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the file in {@code checkWrite(file.getPath())}.
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(String fileName) throws FileNotFoundException {
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new File(fileName));
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} whose output is written to the specified file.
6433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
6453819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param fileName
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the filename of the file that is used as the output
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            destination for the {@code Formatter}. The file will be truncated to
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            zero size if the file exists, or else a new file will be
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            created. The output of the {@code Formatter} is buffered.
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the filename does not denote a normal and writable file,
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             or if a new file cannot be created, or if any error arises when
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             opening or creating the file.
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the file in {@code checkWrite(file.getPath())}.
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(String fileName, String csn) throws FileNotFoundException,
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            UnsupportedEncodingException {
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new File(fileName), csn);
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
6693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and whose output is written to the specified file.
6713819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param fileName
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the filename of the file that is used as the output
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            destination for the {@code Formatter}. The file will be truncated to
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            zero size if the file exists, or else a new file will be
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            created. The output of the {@code Formatter} is buffered.
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then no localization will be used.
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the filename does not denote a normal and writable file,
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             or if a new file cannot be created, or if any error arises when
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             opening or creating the file.
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the file in {@code checkWrite(file.getPath())}.
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(String fileName, String csn, Locale l)
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws FileNotFoundException, UnsupportedEncodingException {
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new File(fileName), csn, l);
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} whose output is written to the specified {@code File}.
7003819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The charset of the {@code Formatter} is the default charset.
7023819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
7043819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code File} that is used as the output destination for the
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            exists, or else a new {@code File} will be created. The output of the
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter} is buffered.
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code File} is not a normal and writable {@code File}, or if a
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             new {@code File} cannot be created, or if any error rises when opening or
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             creating the {@code File}.
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(File file) throws FileNotFoundException {
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(new FileOutputStream(file));
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
7233819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the given charset,
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and whose output is written to the specified {@code File}.
7253819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
7273819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code File} that is used as the output destination for the
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            exists, or else a new {@code File} will be created. The output of the
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter} is buffered.
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code File} is not a normal and writable {@code File}, or if a
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             new {@code File} cannot be created, or if any error rises when opening or
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             creating the {@code File}.
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(File file, String csn) throws FileNotFoundException,
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            UnsupportedEncodingException {
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(file, csn, Locale.getDefault());
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
7513819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and whose output is written to the specified {@code File}.
7533819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code File} that is used as the output destination for the
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            exists, or else a new {@code File} will be created. The output of the
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code Formatter} is buffered.
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then no localization will be used.
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FileNotFoundException
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code File} is not a normal and writable {@code File}, or if a
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             new {@code File} cannot be created, or if any error rises when opening or
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             creating the {@code File}.
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SecurityException
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if there is a {@code SecurityManager} in place which denies permission
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(File file, String csn, Locale l)
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws FileNotFoundException, UnsupportedEncodingException {
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FileOutputStream fout = null;
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fout = new FileOutputStream(file);
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            OutputStreamWriter writer = new OutputStreamWriter(fout, csn);
7803819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            // BEGIN android-changed
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out = new BufferedWriter(writer, 8192);
7823819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            // END android-changed
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException e) {
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            closeOutputStream(fout);
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw e;
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (UnsupportedEncodingException e) {
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            closeOutputStream(fout);
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw e;
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = l;
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} whose output is written to the specified {@code OutputStream}.
7963819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The charset of the {@code Formatter} is the default charset.
7983819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
8003819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param os
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the stream to be used as the destination of the {@code Formatter}.
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(OutputStream os) {
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        OutputStreamWriter writer = new OutputStreamWriter(os, Charset
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .defaultCharset());
8073819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        // BEGIN android-changed
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out = new BufferedWriter(writer, 8192);
8093819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        // END android-changed
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = Locale.getDefault();
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
8143819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the given charset,
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and whose output is written to the specified {@code OutputStream}.
8163819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
8183819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param os
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the stream to be used as the destination of the {@code Formatter}.
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(OutputStream os, String csn)
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws UnsupportedEncodingException {
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(os, csn, Locale.getDefault());
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
8333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and whose output is written to the specified {@code OutputStream}.
8353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param os
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the stream to be used as the destination of the {@code Formatter}.
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param csn
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the charset for the {@code Formatter}.
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            then no localization will be used.
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedEncodingException
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the charset with the specified name is not supported.
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(OutputStream os, String csn, Locale l)
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws UnsupportedEncodingException {
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        OutputStreamWriter writer = new OutputStreamWriter(os, csn);
8503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        // BEGIN android-changed
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out = new BufferedWriter(writer, 8192);
8523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        // END android-changed
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = l;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a {@code Formatter} whose output is written to the specified {@code PrintStream}.
8593819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The charset of the {@code Formatter} is the default charset.
8613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
8633819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ps
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code PrintStream} used as destination of the {@code Formatter}. If
8663819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *            {@code ps} is {@code null}, then a {@code NullPointerException} will
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            be raised.
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter(PrintStream ps) {
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (null == ps) {
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException();
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out = ps;
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = Locale.getDefault();
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void checkClosed() {
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (closed) {
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new FormatterClosedException();
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the {@code Locale} of the {@code Formatter}.
8853819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the {@code Locale} for the {@code Formatter} or {@code null} for no {@code Locale}.
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Locale locale() {
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkClosed();
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return locale;
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the output destination of the {@code Formatter}.
8973819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the output destination of the {@code Formatter}.
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Appendable out() {
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkClosed();
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return out;
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the content by calling the {@code toString()} method of the output
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * destination.
9103819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the content by calling the {@code toString()} method of the output
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         destination.
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkClosed();
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return out.toString();
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Flushes the {@code Formatter}. If the output destination is {@link Flushable},
9243819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * then the method {@code flush()} will be called on that destination.
9253819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void flush() {
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkClosed();
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (out instanceof Flushable) {
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ((Flushable) out).flush();
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (IOException e) {
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                lastIOException = e;
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Closes the {@code Formatter}. If the output destination is {@link Closeable},
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then the method {@code close()} will be called on that destination.
9433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the {@code Formatter} has been closed, then calling the this method will have no
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * effect.
9463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Any method but the {@link #ioException()} that is called after the
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code Formatter} has been closed will raise a {@code FormatterClosedException}.
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void close() {
9512c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        if (!closed) {
9522c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            closed = true;
9532c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            try {
9542c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (out instanceof Closeable) {
9552c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    ((Closeable) out).close();
9562c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                }
9572c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } catch (IOException e) {
9582c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                lastIOException = e;
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the last {@code IOException} thrown by the {@code Formatter}'s output
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * destination. If the {@code append()} method of the destination does not throw
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code IOException}s, the {@code ioException()} method will always return {@code null}.
9673819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the last {@code IOException} thrown by the {@code Formatter}'s output
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         destination.
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public IOException ioException() {
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return lastIOException;
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes a formatted string to the output destination of the {@code Formatter}.
9773819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param format
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            a format string.
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param args
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the arguments list used in the {@code format()} method. If there are
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            more arguments than those specified by the format string, then
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the additional arguments are ignored.
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return this {@code Formatter}.
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalFormatException
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the format string is illegal or incompatible with the
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             arguments, or if fewer arguments are sent than those required by
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             the format string, or any other illegal situation.
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter format(String format, Object... args) {
993636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        // BEGIN android-changed
994636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        doFormat(format, args);
995636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        return this;
996636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        // END android-changed
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9993819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson    // BEGIN android-added
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Cached transformer. Improves performance when format() is called multiple
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * times.
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Transformer transformer;
10053819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson    // END android-added
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes a formatted string to the output destination of the {@code Formatter}.
10093819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param l
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale} used in the method. If {@code locale} is
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code null}, then no localization will be applied. This
10132c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes     *            parameter does not change this Formatter's default {@code Locale}
10142c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes     *            as specified during construction, and only applies for the
10152c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes     *            duration of this call.
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param format
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            a format string.
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param args
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the arguments list used in the {@code format()} method. If there are
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            more arguments than those specified by the format string, then
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the additional arguments are ignored.
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return this {@code Formatter}.
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalFormatException
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the format string is illegal or incompatible with the
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             arguments, or if fewer arguments are sent than those required by
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             the format string, or any other illegal situation.
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws FormatterClosedException
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the {@code Formatter} has been closed.
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Formatter format(Locale l, String format, Object... args) {
10312c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // BEGIN android-changed
10322c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        Locale originalLocale = locale;
10332c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        try {
10342c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            this.locale = l;
10352c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            doFormat(format, args);
10362c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        } finally {
10372c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            this.locale = originalLocale;
10382c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        }
10392c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        return this;
10402c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // END android-changed
10412c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    }
10422c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
10432c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    // BEGIN android-changed
10442c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    private void doFormat(String format, Object... args) {
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkClosed();
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Reuse the previous transformer if the locale matches.
1048636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        if (transformer == null || !transformer.locale.equals(locale)) {
10492c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            transformer = new Transformer(this, locale);
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1052e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        FormatSpecifierParser fsp = new FormatSpecifierParser(format);
10532c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int currentObjectIndex = 0;
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object lastArgument = null;
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean hasLastArgumentSet = false;
10572c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
1058e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        int length = format.length();
10592c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        int i = 0;
10602c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        while (i < length) {
10612c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // Find the maximal plain-text sequence...
10622c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int plainTextStart = i;
1063e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            int nextPercent = format.indexOf('%', i);
1064e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            int plainTextEnd = (nextPercent == -1) ? length : nextPercent;
10652c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // ...and output it.
10662c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (plainTextEnd > plainTextStart) {
10672c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                outputCharSequence(format, plainTextStart, plainTextEnd);
10682c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            }
1069e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            i = plainTextEnd;
10702c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // Do we have a format specifier?
10712c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (i < length) {
1072e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes                FormatToken token = fsp.parseFormatToken(i + 1);
1073f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Object argument = null;
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (token.requireArgument()) {
10762c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    int index = token.getArgIndex() == FormatToken.UNSET ? currentObjectIndex++ : token.getArgIndex();
10772c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    argument = getArgument(args, index, fsp, lastArgument, hasLastArgumentSet);
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastArgument = argument;
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hasLastArgumentSet = true;
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
10812c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
10822c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                CharSequence substitution = transformer.transform(token, argument);
1083636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                // The substitution is null if we called Formattable.formatTo.
10842c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (substitution != null) {
10852c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    outputCharSequence(substitution, 0, substitution.length());
10862c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                }
10872c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                i = fsp.i;
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
10912c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    // END android-changed
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1093f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes    // BEGIN android-added
1094f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes    // Fixes http://code.google.com/p/android/issues/detail?id=1767.
10952c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    private void outputCharSequence(CharSequence cs, int start, int end) {
10962c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        try {
10972c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            out.append(cs, start, end);
10982c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        } catch (IOException e) {
10992c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            lastIOException = e;
1100f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        }
1101f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes    }
1102f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes    // END android-added
1103f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes
11042c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    private Object getArgument(Object[] args, int index, FormatSpecifierParser fsp,
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object lastArgument, boolean hasLastArgumentSet) {
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (index == FormatToken.LAST_ARGUMENT_INDEX && !hasLastArgumentSet) {
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new MissingFormatArgumentException("<"); //$NON-NLS-1$
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (null == args) {
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (index >= args.length) {
11152c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            throw new MissingFormatArgumentException(fsp.getFormatSpecifierText());
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (index == FormatToken.LAST_ARGUMENT_INDEX) {
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return lastArgument;
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return args[index];
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static void closeOutputStream(OutputStream os) {
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (null == os) {
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            os.close();
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IOException e) {
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // silently
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
113835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes     * Complete details of a single format specifier parsed from a format string.
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class FormatToken {
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        static final int LAST_ARGUMENT_INDEX = -2;
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        static final int UNSET = -1;
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        static final int FLAGS_UNSET = 0;
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        static final int DEFAULT_PRECISION = 6;
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        static final int FLAG_ZERO = 1 << 4;
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int argIndex = UNSET;
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        // These have package access for performance. They used to be represented by an int bitmask
115435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        // and accessed via methods, but Android's JIT doesn't yet do a good job of such code.
115535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        // Direct field access, on the other hand, is fast.
115635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagAdd;
115735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagComma;
115835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagMinus;
115935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagParenthesis;
116035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagSharp;
116135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagSpace;
116235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean flagZero;
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        private char conversionType = (char) UNSET;
116535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        private char dateSuffix;
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int precision = UNSET;
116835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        private int width = UNSET;
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11702c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private StringBuilder strFlags;
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1172d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes        // Tests whether there were no flags, no width, and no precision specified.
1173d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes        boolean isDefault() {
117435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            // TODO: call hasDefaultFlags when the JIT can inline it.
117535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            return !flagAdd && !flagComma && !flagMinus && !flagParenthesis && !flagSharp &&
117635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    !flagSpace && !flagZero && width == UNSET && precision == UNSET;
117735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        }
117835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
117935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean hasDefaultFlags() {
118035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            return !flagAdd && !flagComma && !flagMinus && !flagParenthesis && !flagSharp &&
118135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    !flagSpace && !flagZero;
1182d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes        }
1183d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean isPrecisionSet() {
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return precision != UNSET;
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean isWidthSet() {
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return width != UNSET;
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1192636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        boolean hasArg() {
1193636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            return argIndex != UNSET;
1194636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes        }
1195636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int getArgIndex() {
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return argIndex;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void setArgIndex(int index) {
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            argIndex = index;
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int getWidth() {
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return width;
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void setWidth(int width) {
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.width = width;
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int getPrecision() {
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return precision;
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void setPrecision(int precise) {
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.precision = precise;
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String getStrFlags() {
12212c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return (strFlags != null) ? strFlags.toString() : "";
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Sets qualified char as one of the flags. If the char is qualified,
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * sets it as a flag and returns true. Or else returns false.
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
122835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        boolean setFlag(int ch) {
122935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            boolean dupe = false;
123035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            switch (ch) {
123135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case '+':
123235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagAdd;
123335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagAdd = true;
123435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
123535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case ',':
123635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagComma;
123735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagComma = true;
123835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
123935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case '-':
124035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagMinus;
124135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagMinus = true;
124235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
124335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case '(':
124435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagParenthesis;
124535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagParenthesis = true;
124635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
124735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case '#':
124835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagSharp;
124935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagSharp = true;
125035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
125135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case ' ':
125235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagSpace;
125335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagSpace = true;
125435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
125535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            case '0':
125635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                dupe = flagZero;
125735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                flagZero = true;
125835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                break;
125935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            default:
126035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                return false;
126135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            }
126235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (dupe) {
126335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new DuplicateFormatFlagsException(String.valueOf(ch));
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
12652c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (strFlags == null) {
126635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                strFlags = new StringBuilder(7); // There are seven possible flags.
12672c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            }
1268a3bd410b30ae944d5033537357a0c01a56461e4dElliott Hughes            strFlags.append((char) ch);
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char getConversionType() {
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return conversionType;
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void setConversionType(char c) {
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            conversionType = c;
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char getDateSuffix() {
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return dateSuffix;
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void setDateSuffix(char c) {
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dateSuffix = c;
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean requireArgument() {
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return conversionType != '%' && conversionType != 'n';
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
129135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
129235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        void checkMissingWidth() {
129335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (flagMinus && width == UNSET) {
129435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new MissingFormatWidthException("-" + conversionType);
129535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            }
129635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        }
129735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
129835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        void ensureOnlyMinus() {
129935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (flagAdd || flagComma || flagParenthesis || flagSharp || flagSpace || flagZero) {
130035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new FormatFlagsConversionMismatchException(getStrFlags(), conversionType);
130135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            }
130235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        }
130335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
130435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        void ensureNoPrecision() {
130535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (isPrecisionSet()) {
130635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new IllegalFormatPrecisionException(precision);
130735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            }
130835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        }
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Transforms the argument to the formatted string according to the format
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * information contained in the format token.
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class Transformer {
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private Formatter formatter;
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private FormatToken formatToken;
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private Object arg;
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private Locale locale;
1320771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        private DecimalFormatSymbols decimalFormatSymbols;
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private static String lineSeparator;
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13230dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor        // BEGIN android-changed
1324771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        // This object is mutated during use, so can't be cached safely.
13250dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor        // private NumberFormat numberFormat;
13260dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor        // END android-changed
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private DateTimeUtil dateTimeUtil;
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Transformer(Formatter formatter, Locale locale) {
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.formatter = formatter;
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.locale = (null == locale ? Locale.US : locale);
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private NumberFormat getNumberFormat() {
13360dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor            // BEGIN android-changed
13370dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor            return LocaleCache.getNumberFormat(locale);
13380dfef7bc223f18a1372b4c44c822b9cdc5d5f741Dan Egnor            // END android-changed
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        // BEGIN android-changed
1342771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        DecimalFormatSymbols getDecimalFormatSymbols() {
1343771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (decimalFormatSymbols == null) {
1344771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                decimalFormatSymbols = new DecimalFormatSymbols(locale);
1345771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            }
1346771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            return decimalFormatSymbols;
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1348771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        // END android-changed
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the formatted string according to the format token and the
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * argument.
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1354f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        CharSequence transform(FormatToken token, Object argument) {
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.formatToken = token;
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.arg = argument;
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1358d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            // There are only two format specifiers that matter: "%d" and "%s".
1359d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            // Nothing else is common in the wild. We fast-path these two to
1360dddc36885260b49e4bbde0f39d281f222f2fe77fElliott Hughes            // avoid the heavyweight machinery needed to cope with flags, width,
1361dddc36885260b49e4bbde0f39d281f222f2fe77fElliott Hughes            // and precision.
1362d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            if (token.isDefault()) {
1363d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                switch (token.getConversionType()) {
1364d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                case 's':
1365e2036b3a340e0d687d9bbdb500658ef4585545e2Elliott Hughes                    if (arg == null) {
1366e2036b3a340e0d687d9bbdb500658ef4585545e2Elliott Hughes                        return "null";
1367e2036b3a340e0d687d9bbdb500658ef4585545e2Elliott Hughes                    } else if (!(arg instanceof Formattable)) {
1368d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                        return arg.toString();
1369d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                    }
1370d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                    break;
1371d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                case 'd':
1372d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                    if (arg instanceof Integer || arg instanceof Long || arg instanceof Short || arg instanceof Byte) {
1373d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                        // TODO: when we fix the rest of formatter to correctly use locale-specific
1374d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                        // digits when getDecimalFormatSymbols().getZeroDigit() != '0', we'll need
1375d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                        // to add a special case here too.
1376d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                        return arg.toString();
1377d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                    }
1378d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                }
1379d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            }
1380d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes
1381f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes            CharSequence result;
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (token.getConversionType()) {
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'B':
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'b': {
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromBoolean();
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'H':
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'h': {
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromHashCode();
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'S':
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 's': {
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromString();
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'C':
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'c': {
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromCharacter();
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'd':
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'o':
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'x':
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'X': {
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (null == arg || arg instanceof BigInteger) {
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result = transformFromBigInteger();
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result = transformFromInteger();
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'e':
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'E':
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'g':
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'G':
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'f':
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'a':
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'A': {
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromFloat();
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case '%': {
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromPercent();
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'n': {
14293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                    result = transformFromLineSeparator();
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 't':
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'T': {
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result = transformFromDateTime();
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default: {
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new UnknownFormatConversionException(String
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            .valueOf(token.getConversionType()));
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (Character.isUpperCase(token.getConversionType())) {
1444d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                if (result != null) {
14458cdf9790e869778b0ed3da7f149cb7c132a0f142Elliott Hughes                    result = result.toString().toUpperCase(locale);
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return result;
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        private IllegalFormatConversionException badArgumentType() {
145235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            throw new IllegalFormatConversionException(formatToken.getConversionType(),
145335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    arg.getClass());
145435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes        }
145535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms the Boolean argument to a formatted string.
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1459f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromBoolean() {
146035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.checkMissingWidth();
146135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureOnlyMinus();
14622c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            CharSequence result;
14632c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (arg instanceof Boolean) {
14642c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = arg.toString();
14652c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } else if (arg == null) {
14662c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = "false"; //$NON-NLS-1$
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
14682c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = "true"; //$NON-NLS-1$
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
14702c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding(result, 0);
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1474612ae259a58d460574d21a13a0409c0f6f6f635fElliott Hughes         * Transforms the hash code of the argument to a formatted string.
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1476f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromHashCode() {
147735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.checkMissingWidth();
147835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureOnlyMinus();
14792c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            CharSequence result;
14802c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (arg == null) {
14812c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = "null"; //$NON-NLS-1$
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
14832c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = Integer.toHexString(arg.hashCode());
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
14852c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding(result, 0);
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms the String to a formatted string.
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1491f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromString() {
149235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.checkMissingWidth();
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arg instanceof Formattable) {
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // only minus and sharp flag is valid
149535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagAdd || formatToken.flagComma || formatToken.flagParenthesis || formatToken.flagSpace || formatToken.flagZero) {
1496636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
149835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                int flag = 0;
149935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagMinus) {
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    flag |= FormattableFlags.LEFT_JUSTIFY;
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
150235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagSharp) {
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    flag |= FormattableFlags.ALTERNATE;
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (Character.isUpperCase(formatToken.getConversionType())) {
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    flag |= FormattableFlags.UPPERCASE;
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
150835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                ((Formattable) arg).formatTo(formatter, flag, formatToken.getWidth(),
150935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        formatToken.getPrecision());
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // all actions have been taken out in the
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Formattable.formatTo, thus there is nothing to do, just
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // returns null, which tells the Parser to add nothing to the
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // output.
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return null;
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
151635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            // only '-' is valid for flags if the argument is not an instance of Formattable
151735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureOnlyMinus();
15182c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            CharSequence result = arg != null ? arg.toString() : "null";
15192c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding(result, 0);
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms the Character to a formatted string.
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1525f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromCharacter() {
152635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.checkMissingWidth();
152735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureOnlyMinus();
152835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15302c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (arg == null) {
153135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                return padding("null", 0);
153235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            }
153335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (arg instanceof Character) {
153435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                return padding(String.valueOf(arg), 0);
153535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            } else if (arg instanceof Byte || arg instanceof Short || arg instanceof Integer) {
153635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                int codePoint = ((Number) arg).intValue();
153735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (!Character.isValidCodePoint(codePoint)) {
153835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new IllegalFormatCodePointException(codePoint);
153935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                }
154035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                CharSequence result = (codePoint < Character.MIN_SUPPLEMENTARY_CODE_POINT)
154135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        ? String.valueOf((char) codePoint)
154235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        : String.valueOf(Character.toChars(codePoint));
154335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                return padding(result, 0);
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
154535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw badArgumentType();
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms percent to a formatted string. Only '-' is legal flag.
1551636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes         * Precision and arguments are illegal.
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1553f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromPercent() {
155435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.checkMissingWidth();
155535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureOnlyMinus();
155635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
1557636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            if (formatToken.hasArg()) {
1558636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1559636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            }
15602c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding("%", 0);
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1564636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes         * Transforms line separator to a formatted string. Any flag, width,
1565636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes         * precision or argument is illegal.
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1567f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromLineSeparator() {
156835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (formatToken.isWidthSet()) {
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatWidthException(formatToken.getWidth());
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (!formatToken.hasDefaultFlags() || formatToken.hasArg()) {
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1578636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            if (lineSeparator == null) {
1579636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                lineSeparator = AccessController.doPrivileged(new PrivilegedAction<String>() {
1580636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    public String run() {
1581636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                        return System.getProperty("line.separator"); //$NON-NLS-1$
1582636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    }
1583636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                });
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return lineSeparator;
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Pads characters to the formatted string.
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
15912c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private CharSequence padding(CharSequence source, int startIndex) {
15922c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            boolean sourceIsStringBuilder = (source instanceof StringBuilder);
15932c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int start = startIndex;
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int width = formatToken.getWidth();
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int precision = formatToken.getPrecision();
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int length = source.length();
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (precision >= 0) {
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                length = Math.min(length, precision);
16012c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (sourceIsStringBuilder) {
16022c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    ((StringBuilder) source).setLength(length);
16032c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                } else {
16042c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    source = source.subSequence(0, length);
16052c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                }
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (width > 0) {
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                width = Math.max(source.length(), width);
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (length >= width) {
1611f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes                return source;
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16142c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            char paddingChar = '\u0020'; // space as padding char.
161535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagZero) {
16162c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (formatToken.getConversionType() == 'd') {
16172c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    paddingChar = getDecimalFormatSymbols().getZeroDigit();
16182c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                } else {
16192c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    paddingChar = '0';
16202c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                }
16212c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } else {
16222c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                // if padding char is space, always pad from the start.
16232c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                start = 0;
16242c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            }
16252c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            char[] paddingChars = new char[width - length];
16262c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            Arrays.fill(paddingChars, paddingChar);
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            boolean paddingRight = formatToken.flagMinus;
16292c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            StringBuilder result = toStringBuilder(source);
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (paddingRight) {
16312c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result.append(paddingChars);
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
16332c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result.insert(start, paddingChars);
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
16352c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return result;
16362c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        }
16372c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
16382c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private StringBuilder toStringBuilder(CharSequence cs) {
16392c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return cs instanceof StringBuilder ? (StringBuilder) cs : new StringBuilder(cs);
16402c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        }
16412c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
16422c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private StringBuilder wrapParentheses(StringBuilder result) {
16432c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            result.setCharAt(0, '('); // Replace the '-'.
164435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagZero) {
16452c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                formatToken.setWidth(formatToken.getWidth() - 1);
16462c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = (StringBuilder) padding(result, 1);
16472c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result.append(')');
16482c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } else {
16492c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result.append(')');
16502c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                result = (StringBuilder) padding(result, 0);
16512c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            }
16522c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return result;
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms the Integer to a formatted string.
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1658f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromInteger() {
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int startIndex = 0;
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder result = new StringBuilder();
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char currentConversionType = formatToken.getConversionType();
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus || formatToken.flagZero) {
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!formatToken.isWidthSet()) {
166535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new MissingFormatWidthException(formatToken.getStrFlags());
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
166835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            // Combination of '+' and ' ' is illegal.
166935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagAdd && formatToken.flagSpace) {
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
167235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
167335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            long value;
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arg instanceof Long) {
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value = ((Long) arg).longValue();
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (arg instanceof Integer) {
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value = ((Integer) arg).longValue();
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (arg instanceof Short) {
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value = ((Short) arg).longValue();
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (arg instanceof Byte) {
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value = ((Byte) arg).longValue();
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
168335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw badArgumentType();
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ('d' != currentConversionType) {
168635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagAdd || formatToken.flagSpace || formatToken.flagComma ||
168735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        formatToken.flagParenthesis) {
168835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
168935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                            formatToken.getConversionType());
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp) {
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ('d' == currentConversionType) {
169535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
169635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                            formatToken.getConversionType());
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if ('o' == currentConversionType) {
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.append("0"); //$NON-NLS-1$
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 1;
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.append("0x"); //$NON-NLS-1$
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 2;
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus && formatToken.flagZero) {
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ('d' == currentConversionType) {
171135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagComma) {
17122c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    NumberFormat numberFormat = getNumberFormat();
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    numberFormat.setGroupingUsed(true);
17142c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    result.append(numberFormat.format(arg));
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
17162c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    result.append(value);
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
171835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes
171935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (value < 0) {
172035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    if (formatToken.flagParenthesis) {
172135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        return wrapParentheses(result);
172235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    } else if (formatToken.flagZero) {
172335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        startIndex++;
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
172535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                } else {
172635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    if (formatToken.flagAdd) {
172735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        result.insert(0, '+');
172835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        startIndex += 1;
172935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    } else if (formatToken.flagSpace) {
173035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        result.insert(0, ' ');
173135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        startIndex += 1;
173235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    }
173335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                }
173435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            } else {
173535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                // Undo sign-extension, since we'll be using Long.to(Octal|Hex)String.
173635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (arg instanceof Byte) {
173735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    value &= 0xffL;
173835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                } else if (arg instanceof Short) {
173935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    value &= 0xffffL;
174035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                } else if (arg instanceof Integer) {
174135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    value &= 0xffffffffL;
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ('o' == currentConversionType) {
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.append(Long.toOctalString(value));
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.append(Long.toHexString(value));
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return padding(result, startIndex);
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1753f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromSpecialNumber() {
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!(arg instanceof Number) || arg instanceof BigDecimal) {
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return null;
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Number number = (Number) arg;
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            double d = number.doubleValue();
17602c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            String source = null;
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (Double.isNaN(d)) {
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                source = "NaN"; //$NON-NLS-1$
1763636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            } else if (d == Double.POSITIVE_INFINITY) {
176435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagAdd) {
1765636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    source = "+Infinity"; //$NON-NLS-1$
176635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                } else if (formatToken.flagSpace) {
1767636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    source = " Infinity"; //$NON-NLS-1$
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
1769636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    source = "Infinity"; //$NON-NLS-1$
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1771636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            } else if (d == Double.NEGATIVE_INFINITY) {
177235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagParenthesis) {
1773636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    source = "(Infinity)"; //$NON-NLS-1$
1774636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                } else {
1775636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                    source = "-Infinity"; //$NON-NLS-1$
1776636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes                }
1777636bc6174d81cc4017d1659e94e8b33a5e51914aElliott Hughes            } else {
17782c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return null;
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
17802c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
17812c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            formatToken.setPrecision(FormatToken.UNSET);
178219c5378901c2facf48f02eedb77eaf24fc225986Elliott Hughes            formatToken.flagZero = false;
17832c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding(source, 0);
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1786f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromNull() {
178719c5378901c2facf48f02eedb77eaf24fc225986Elliott Hughes            formatToken.flagZero = false;
17882c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding("null", 0); //$NON-NLS-1$
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms a BigInteger to a formatted string.
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1794f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromBigInteger() {
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int startIndex = 0;
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean isNegative = false;
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder result = new StringBuilder();
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            BigInteger bigInt = (BigInteger) arg;
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char currentConversionType = formatToken.getConversionType();
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
180135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus || formatToken.flagZero) {
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!formatToken.isWidthSet()) {
180335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new MissingFormatWidthException(formatToken.getStrFlags());
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Combination of '+' & ' ' is illegal.
180835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagAdd && formatToken.flagSpace) {
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Combination of '-' & '0' is illegal.
181335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagZero && formatToken.flagMinus) {
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if ('d' != currentConversionType && formatToken.flagComma) {
182035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
182135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        currentConversionType);
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp && 'd' == currentConversionType) {
182535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
182635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        currentConversionType);
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (bigInt == null) {
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return transformFromNull();
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isNegative = (bigInt.compareTo(BigInteger.ZERO) < 0);
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ('d' == currentConversionType) {
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                NumberFormat numberFormat = getNumberFormat();
183735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                numberFormat.setGroupingUsed(formatToken.flagComma);
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.append(numberFormat.format(bigInt));
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if ('o' == currentConversionType) {
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // convert BigInteger to a string presentation using radix 8
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.append(bigInt.toString(8));
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // convert BigInteger to a string presentation using radix 16
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.append(bigInt.toString(16));
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
184635138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp) {
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startIndex = isNegative ? 1 : 0;
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ('o' == currentConversionType) {
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(startIndex, "0"); //$NON-NLS-1$
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 1;
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if ('x' == currentConversionType
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        || 'X' == currentConversionType) {
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(startIndex, "0x"); //$NON-NLS-1$
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 2;
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!isNegative) {
185935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagAdd) {
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(0, '+');
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 1;
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
186335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagSpace) {
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(0, ' ');
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex += 1;
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* pad paddingChar to the output */
187035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (isNegative && formatToken.flagParenthesis) {
18712c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return wrapParentheses(result);
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
187335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (isNegative && formatToken.flagZero) {
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startIndex++;
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return padding(result, startIndex);
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms a Float,Double or BigDecimal to a formatted string.
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1882f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromFloat() {
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder result = new StringBuilder();
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int startIndex = 0;
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char currentConversionType = formatToken.getConversionType();
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus || formatToken.flagZero) {
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!formatToken.isWidthSet()) {
188935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new MissingFormatWidthException(formatToken.getStrFlags());
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
189335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagAdd && formatToken.flagSpace) {
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
189735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus && formatToken.flagZero) {
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatFlagsException(formatToken.getStrFlags());
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1901771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (currentConversionType == 'e' || currentConversionType == 'E') {
190235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagComma) {
190335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
190435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                            currentConversionType);
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1906771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            } else if (currentConversionType == 'g' || currentConversionType == 'G') {
190735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagSharp) {
190835138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
190935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                            currentConversionType);
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1911771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            } else if (currentConversionType == 'a' || currentConversionType == 'A') {
191235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagComma || formatToken.flagParenthesis) {
191335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
191435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                            currentConversionType);
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (null == arg) {
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return transformFromNull();
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!(arg instanceof Float || arg instanceof Double || arg instanceof BigDecimal)) {
192335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw badArgumentType();
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1926f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes            CharSequence specialNumberResult = transformFromSpecialNumber();
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (null != specialNumberResult) {
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return specialNumberResult;
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1931771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (currentConversionType != 'a' && currentConversionType != 'A' &&
1932c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes                    !formatToken.isPrecisionSet()) {
1933c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes                formatToken.setPrecision(FormatToken.DEFAULT_PRECISION);
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1935c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // output result
1937771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            DecimalFormatSymbols decimalFormatSymbols = getDecimalFormatSymbols();
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            FloatUtil floatUtil = new FloatUtil(result, formatToken,
1939771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    (DecimalFormat) getNumberFormat(), decimalFormatSymbols, arg);
1940771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            floatUtil.transform(currentConversionType);
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            formatToken.setPrecision(FormatToken.UNSET);
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1944771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (decimalFormatSymbols.getMinusSign() == result.charAt(0)) {
194535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagParenthesis) {
19462c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    return wrapParentheses(result);
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
194935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagSpace) {
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(0, ' ');
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex++;
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
195335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                if (formatToken.flagAdd) {
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.insert(0, floatUtil.getAddSign());
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startIndex++;
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char firstChar = result.charAt(0);
196035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagZero
1961771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    && (firstChar == floatUtil.getAddSign() || firstChar == decimalFormatSymbols.getMinusSign())) {
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startIndex = 1;
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1965771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (currentConversionType == 'a' || currentConversionType == 'A') {
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startIndex += 2;
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return padding(result, startIndex);
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Transforms a Date to a formatted string.
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1974f69a407c29a01b5e4a228b52fd08505cb7dc1b09Elliott Hughes        private CharSequence transformFromDateTime() {
197535138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            formatToken.ensureNoPrecision();
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197735138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            char currentConversionType = formatToken.getConversionType();
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197935138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp) {
198035138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                throw new FormatFlagsConversionMismatchException(formatToken.getStrFlags(),
198135138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                        currentConversionType);
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198435138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagMinus && formatToken.getWidth() == FormatToken.UNSET) {
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new MissingFormatWidthException("-" //$NON-NLS-1$
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + currentConversionType);
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (null == arg) {
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return transformFromNull();
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Calendar calendar;
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arg instanceof Calendar) {
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                calendar = (Calendar) arg;
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Date date = null;
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (arg instanceof Long) {
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    date = new Date(((Long) arg).longValue());
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (arg instanceof Date) {
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    date = (Date) arg;
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
200335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes                    throw badArgumentType();
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                calendar = Calendar.getInstance(locale);
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                calendar.setTime(date);
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (null == dateTimeUtil) {
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dateTimeUtil = new DateTimeUtil(locale);
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder result = new StringBuilder();
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // output result
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dateTimeUtil.transform(formatToken, calendar, result);
20152c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return padding(result, 0);
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class FloatUtil {
2020c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes        private final StringBuilder result;
2021c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes        private final DecimalFormat decimalFormat;
2022771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        private final DecimalFormatSymbols decimalFormatSymbols;
2023c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes        private final FormatToken formatToken;
2024c047c11da7d284940bcac9a28c42145628d49fedElliott Hughes        private final Object argument;
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2026771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        FloatUtil(StringBuilder result, FormatToken formatToken, DecimalFormat decimalFormat,
2027771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                DecimalFormatSymbols decimalFormatSymbols, Object argument) {
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.result = result;
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.formatToken = formatToken;
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.decimalFormat = decimalFormat;
2031771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            this.decimalFormatSymbols = decimalFormatSymbols;
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.argument = argument;
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2035771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes        void transform(char conversionType) {
2036771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            switch (conversionType) {
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'e':
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'E': {
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_e();
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'f': {
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_f();
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'g':
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'G': {
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_g();
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'a':
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'A': {
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_a();
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default: {
2057771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    throw new UnknownFormatConversionException(String.valueOf(conversionType));
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char getAddSign() {
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return '+';
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void transform_e() {
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder pattern = new StringBuilder();
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pattern.append('0');
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (formatToken.getPrecision() > 0) {
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pattern.append('.');
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char[] zeros = new char[formatToken.getPrecision()];
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Arrays.fill(zeros, '0');
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pattern.append(zeros);
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pattern.append('E');
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pattern.append("+00"); //$NON-NLS-1$
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decimalFormat.applyPattern(pattern.toString());
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String formattedString = decimalFormat.format(argument);
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(formattedString.replace('E', 'e'));
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20812c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // if the flag is sharp and decimal separator is always given
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // out.
208335138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp && formatToken.getPrecision() == 0) {
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int indexOfE = result.indexOf("e"); //$NON-NLS-1$
2085771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                result.insert(indexOfE, decimalFormatSymbols.getDecimalSeparator());
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void transform_g() {
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int precision = formatToken.getPrecision();
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            precision = (0 == precision ? 1 : precision);
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            formatToken.setPrecision(precision);
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (0.0 == ((Number) argument).doubleValue()) {
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                precision--;
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                formatToken.setPrecision(precision);
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                transform_f();
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean requireScientificRepresentation = true;
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            double d = ((Number) argument).doubleValue();
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            d = Math.abs(d);
21043819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            if (Double.isInfinite(d)) {
21053819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                precision = formatToken.getPrecision();
21063819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                precision--;
21073819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                formatToken.setPrecision(precision);
21083819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                transform_e();
21093819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                return;
21103819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            }
21113819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            BigDecimal b = new BigDecimal(d, new MathContext(precision));
21123819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            d = b.doubleValue();
21133819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            long l = b.longValue();
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21153819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            if (d >= 1 && d < Math.pow(10, precision)) {
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (l < Math.pow(10, precision)) {
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    requireScientificRepresentation = false;
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    precision -= String.valueOf(l).length();
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    precision = precision < 0 ? 0 : precision;
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    l = Math.round(d * Math.pow(10, precision + 1));
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (String.valueOf(l).length() <= formatToken
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            .getPrecision()) {
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        precision++;
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    formatToken.setPrecision(precision);
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
21293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                l = b.movePointRight(4).longValue();
21303819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                if (d >= Math.pow(10, -4) && d < 1) {
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    requireScientificRepresentation = false;
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    precision += 4 - String.valueOf(l).length();
21333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                    l = b.movePointRight(precision + 1).longValue();
2134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (String.valueOf(l).length() <= formatToken
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            .getPrecision()) {
2136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        precision++;
2137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
21383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                    l = b.movePointRight(precision).longValue();
21393819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                    if (l >= Math.pow(10, precision - 4)) {
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        formatToken.setPrecision(precision);
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (requireScientificRepresentation) {
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                precision = formatToken.getPrecision();
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                precision--;
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                formatToken.setPrecision(precision);
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                transform_e();
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                transform_f();
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void transform_f() {
2155771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            // TODO: store a default DecimalFormat we can clone?
2156771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            String pattern = "0.000000";
2157771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            if (formatToken.flagComma || formatToken.getPrecision() != 6) {
2158771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                StringBuilder patternBuilder = new StringBuilder();
2159771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                if (formatToken.flagComma) {
2160771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    patternBuilder.append(',');
2161771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    int groupingSize = decimalFormat.getGroupingSize();
2162771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    if (groupingSize > 1) {
2163771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                        char[] sharps = new char[groupingSize - 1];
2164771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                        Arrays.fill(sharps, '#');
2165771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                        patternBuilder.append(sharps);
2166771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    }
2167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2168771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                patternBuilder.append(0);
2169771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                if (formatToken.getPrecision() > 0) {
2170771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    patternBuilder.append('.');
2171771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    char[] zeros = new char[formatToken.getPrecision()];
2172771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    Arrays.fill(zeros, '0');
2173771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                    patternBuilder.append(zeros);
2174771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                }
2175771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                pattern = patternBuilder.toString();
2176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2177771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            // TODO: if DecimalFormat.toPattern was cheap, we could make this cheap (preferably *in* DecimalFormat).
2178771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes            decimalFormat.applyPattern(pattern);
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(decimalFormat.format(argument));
21802c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // if the flag is sharp and decimal separator is always given
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // out.
218235138e0566bc395af2f30a3a4354033adb1d0682Elliott Hughes            if (formatToken.flagSharp && formatToken.getPrecision() == 0) {
2183771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                result.append(decimalFormatSymbols.getDecimalSeparator());
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void transform_a() {
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (argument instanceof Float) {
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Float F = (Float) argument;
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.append(Float.toHexString(F.floatValue()));
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (argument instanceof Double) {
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Double D = (Double) argument;
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.append(Double.toHexString(D.doubleValue()));
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // BigInteger is not supported.
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalFormatConversionException(
2198771f3129d213c4725c5a78c6a4ae86ea1b015968Elliott Hughes                        formatToken.getConversionType(), argument.getClass());
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!formatToken.isPrecisionSet()) {
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int precision = formatToken.getPrecision();
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            precision = (0 == precision ? 1 : precision);
22072c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int indexOfFirstFractionalDigit = result.indexOf(".") + 1; //$NON-NLS-1$
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int indexOfP = result.indexOf("p"); //$NON-NLS-1$
22092c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int fractionalLength = indexOfP - indexOfFirstFractionalDigit;
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fractionalLength == precision) {
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fractionalLength < precision) {
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char zeros[] = new char[precision - fractionalLength];
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Arrays.fill(zeros, '0');
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.insert(indexOfP, zeros);
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
22212c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            result.delete(indexOfFirstFractionalDigit + precision, indexOfP);
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class DateTimeUtil {
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private Calendar calendar;
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private Locale locale;
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private StringBuilder result;
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private DateFormatSymbols dateFormatSymbols;
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DateTimeUtil(Locale locale) {
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.locale = locale;
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void transform(FormatToken formatToken, Calendar aCalendar,
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                StringBuilder aResult) {
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.result = aResult;
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.calendar = aCalendar;
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char suffix = formatToken.getDateSuffix();
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (suffix) {
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'H': {
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_H();
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'I': {
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_I();
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'M': {
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_M();
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'S': {
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_S();
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'L': {
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_L();
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'N': {
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_N();
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'k': {
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_k();
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'l': {
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_l();
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'p': {
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_p(true);
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 's': {
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_s();
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'z': {
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_z();
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'Z': {
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_Z();
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'Q': {
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_Q();
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'B': {
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_B();
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'b':
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'h': {
2303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_b();
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'A': {
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_A();
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'a': {
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_a();
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'C': {
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_C();
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'Y': {
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_Y();
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'y': {
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_y();
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'j': {
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_j();
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'm': {
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_m();
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'd': {
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_d();
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'e': {
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_e();
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'R': {
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_R();
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'T': {
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_T();
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'r': {
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_r();
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'D': {
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_D();
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'F': {
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_F();
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case 'c': {
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    transform_c();
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default: {
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new UnknownFormatConversionException(String
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            .valueOf(formatToken.getConversionType())
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            + formatToken.getDateSuffix());
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_e() {
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int day = calendar.get(Calendar.DAY_OF_MONTH);
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(day);
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_d() {
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int day = calendar.get(Calendar.DAY_OF_MONTH);
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(day, 2));
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_m() {
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int month = calendar.get(Calendar.MONTH);
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // The returned month starts from zero, which needs to be
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // incremented by 1.
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            month++;
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(month, 2));
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_j() {
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int day = calendar.get(Calendar.DAY_OF_YEAR);
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(day, 3));
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_y() {
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int year = calendar.get(Calendar.YEAR);
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            year %= 100;
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(year, 2));
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_Y() {
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int year = calendar.get(Calendar.YEAR);
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(year, 4));
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_C() {
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int year = calendar.get(Calendar.YEAR);
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            year /= 100;
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(year, 2));
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_a() {
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int day = calendar.get(Calendar.DAY_OF_WEEK);
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(getDateFormatSymbols().getShortWeekdays()[day]);
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_A() {
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int day = calendar.get(Calendar.DAY_OF_WEEK);
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(getDateFormatSymbols().getWeekdays()[day]);
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_b() {
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int month = calendar.get(Calendar.MONTH);
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(getDateFormatSymbols().getShortMonths()[month]);
2428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_B() {
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int month = calendar.get(Calendar.MONTH);
2432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(getDateFormatSymbols().getMonths()[month]);
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_Q() {
2436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long milliSeconds = calendar.getTimeInMillis();
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(milliSeconds);
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_s() {
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long milliSeconds = calendar.getTimeInMillis();
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            milliSeconds /= 1000;
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(milliSeconds);
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_Z() {
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TimeZone timeZone = calendar.getTimeZone();
24483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            result.append(timeZone
24493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                    .getDisplayName(
24503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                            timeZone.inDaylightTime(calendar.getTime()),
24513819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                            TimeZone.SHORT, locale));
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_z() {
245594a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            long offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
245694a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            char sign = '+';
245794a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            if (offset < 0) {
245894a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes                sign = '-';
245994a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes                offset = -offset;
246094a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            }
246194a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            result.append(sign);
246294a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            result.append(paddingZeros(offset / 3600000, 2));
246394a6dc1d671e6fb619b739a2f1640f416552a881Elliott Hughes            result.append(paddingZeros((offset % 3600000) / 60000, 2));
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_p(boolean isLowerCase) {
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int i = calendar.get(Calendar.AM_PM);
2468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String s = getDateFormatSymbols().getAmPmStrings()[i];
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (isLowerCase) {
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                s = s.toLowerCase(locale);
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(s);
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_N() {
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long nanosecond = calendar.get(Calendar.MILLISECOND) * 1000000L;
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(nanosecond, 9));
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_L() {
2481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int millisecond = calendar.get(Calendar.MILLISECOND);
2482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(millisecond, 3));
2483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_S() {
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int second = calendar.get(Calendar.SECOND);
2487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(second, 2));
2488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_M() {
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int minute = calendar.get(Calendar.MINUTE);
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(minute, 2));
2493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_l() {
2496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hour = calendar.get(Calendar.HOUR);
2497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (0 == hour) {
2498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hour = 12;
2499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(hour);
2501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_k() {
2504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hour = calendar.get(Calendar.HOUR_OF_DAY);
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(hour);
2506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_I() {
2509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hour = calendar.get(Calendar.HOUR);
2510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (0 == hour) {
2511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hour = 12;
2512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(hour, 2));
2514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_H() {
2517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hour = calendar.get(Calendar.HOUR_OF_DAY);
2518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(paddingZeros(hour, 2));
2519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_R() {
2522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_H();
2523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(':');
2524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_M();
2525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_T() {
2528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_H();
2529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(':');
2530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_M();
2531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(':');
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_S();
2533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_r() {
2536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_I();
2537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(':');
2538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_M();
2539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(':');
2540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_S();
2541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_p(false);
2543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_D() {
2546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_m();
2547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append('/');
2548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_d();
2549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append('/');
2550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_y();
2551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_F() {
2554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_Y();
2555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append('-');
2556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_m();
2557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append('-');
2558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_d();
2559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void transform_c() {
2562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_a();
2563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_b();
2565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_d();
2567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_T();
2569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_Z();
2571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(' ');
2572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            transform_Y();
2573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25752c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // TODO: this doesn't need a temporary StringBuilder!
2576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private static String paddingZeros(long number, int length) {
2577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = length;
2578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StringBuilder result = new StringBuilder();
2579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.append(number);
2580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int startIndex = 0;
2581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (number < 0) {
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                len++;
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startIndex = 1;
2584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            len -= result.length();
2586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (len > 0) {
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char[] zeros = new char[len];
2588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Arrays.fill(zeros, '0');
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.insert(startIndex, zeros);
2590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return result.toString();
2592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private DateFormatSymbols getDateFormatSymbols() {
2595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (null == dateFormatSymbols) {
2596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dateFormatSymbols = new DateFormatSymbols(locale);
2597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return dateFormatSymbols;
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26022c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes    private static class FormatSpecifierParser {
2603e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        private String format;
2604e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        private int length;
2605e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes
26062c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private int startIndex;
26072c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private int i;
2608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26092c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        /**
2610e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes         * Constructs a new parser for the given format string.
2611e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes         */
2612e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        FormatSpecifierParser(String format) {
2613e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            this.format = format;
2614e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            this.length = format.length();
2615e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        }
2616e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes
2617e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        /**
2618e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes         * Returns a FormatToken representing the format specifier starting at 'offset'.
26192c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes         * @param offset the first character after the '%'
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2621e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes        FormatToken parseFormatToken(int offset) {
26222c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            this.startIndex = offset;
26232c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            this.i = offset;
26242c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return parseArgumentIndexAndFlags(new FormatToken());
2625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26272c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        /**
26282c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes         * Returns a string corresponding to the last format specifier that was parsed.
26292c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes         * Used to construct error messages.
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
26312c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        String getFormatSpecifierText() {
2632e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            return format.substring(startIndex, i);
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26352c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private int peek() {
2636e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            return (i < length) ? format.charAt(i) : -1;
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26392c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private char advance() {
2640e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            if (i >= length) {
26412c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                throw new UnknownFormatConversionException(getFormatSpecifierText());
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2643e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            return format.charAt(i++);
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26462c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private FormatToken parseArgumentIndexAndFlags(FormatToken token) {
26472c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // Parse the argument index, if there is one.
26482c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int position = i;
26492c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int ch = peek();
26502c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (Character.isDigit(ch)) {
26512c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                int number = nextInt();
26522c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (peek() == '$') {
26532c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    // The number was an argument index.
26542c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    advance(); // Swallow the '$'.
26552c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    if (number == FormatToken.UNSET) {
26562c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                        throw new MissingFormatArgumentException(getFormatSpecifierText());
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
26582c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    // k$ stands for the argument whose index is k-1 except that
26592c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    // 0$ and 1$ both stand for the first element.
26602c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    token.setArgIndex(Math.max(0, number - 1));
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
26622c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    if (ch == '0') {
26632c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                        // The digit zero is a format flag, so reparse it as such.
26642c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                        i = position;
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
26662c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                        // The number was a width. This means there are no flags to parse.
26672c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                        return parseWidth(token, number);
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
26702c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } else if (ch == '<') {
2671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                token.setArgIndex(FormatToken.LAST_ARGUMENT_INDEX);
26722c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                advance();
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26752c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // Parse the flags.
26762c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            while (token.setFlag(peek())) {
26772c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                advance();
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26802c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            // What comes next?
26812c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            ch = peek();
26822c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (Character.isDigit(ch)) {
26832c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parseWidth(token, nextInt());
26842c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            } else if (ch == '.') {
26852c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parsePrecision(token);
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
26872c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parseConversionType(token);
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26912c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // We pass the width in because in some cases we've already parsed it.
26922c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // (Because of the ambiguity between argument indexes and widths.)
26932c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private FormatToken parseWidth(FormatToken token, int width) {
26942c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            token.setWidth(width);
26952c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int ch = peek();
26962c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (ch == '.') {
26972c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parsePrecision(token);
2698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
26992c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parseConversionType(token);
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27032c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private FormatToken parsePrecision(FormatToken token) {
27042c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            advance(); // Swallow the '.'.
27052c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            int ch = peek();
27062c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            if (Character.isDigit(ch)) {
27072c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                token.setPrecision(nextInt());
27082c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                return parseConversionType(token);
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
27102c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                // The precision is required but not given by the format string.
27112c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                throw new UnknownFormatConversionException(getFormatSpecifierText());
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27152c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private FormatToken parseConversionType(FormatToken token) {
2716d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            char conversionType = advance(); // A conversion type is mandatory.
2717d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            token.setConversionType(conversionType);
2718d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes            if (conversionType == 't' || conversionType == 'T') {
2719d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                char dateSuffix = advance(); // A date suffix is mandatory for 't' or 'T'.
2720d028bd15d5c5dfe2b4cbc66e7c4d6d4c716795deElliott Hughes                token.setDateSuffix(dateSuffix);
27212c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            }
27222c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return token;
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27252c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // Parses an integer (of arbitrary length, but typically just one digit).
27262c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private int nextInt() {
27272c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            long value = 0;
2728e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes            while (i < length && Character.isDigit(format.charAt(i))) {
2729e25b3c255c19693b9aa5bb16e90e007766246595Elliott Hughes                value = 10 * value + (format.charAt(i++) - '0');
27302c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                if (value > Integer.MAX_VALUE) {
27312c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                    return failNextInt();
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
27342c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return (int) value;
27352c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        }
27362c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes
27372c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        // Swallow remaining digits to resync our attempted parse, but return failure.
27382c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes        private int failNextInt() {
27392c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            while (Character.isDigit(peek())) {
27402c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes                advance();
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
27422c5e73632c4bb75004fd3858b2bba30857e82598Elliott Hughes            return FormatToken.UNSET;
2743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2746