View Javadoc

1   package com.sharkysoft.printf;
2   
3   import java.io.IOException;
4   import java.io.Writer;
5   
6   /***
7    * Main Printf For Java interface.
8    *
9    * <p><b>Details:</b> <code>Printf</code> is the primary interface to Printf For
10   * Java.  This singleton class includes methods for outputing 
11   * printf-<wbr>formatted text and data to the console, file streams, and 
12   * buffers.</p>
13   * 
14   * <p>The formatting template for a printf request must be given as a 
15   * <code>String</code> or a {@link PrintfTemplate}.  The data to format in a 
16   * printf request must be given as an <code>Object</code> array or a 
17   * {@link PrintfData}.</p>
18   * 
19   * <p>For more information on both of these data structures, see the 
20   * <a href="doc-files/specification.htm">Printf for Java Specification 
21   * 2.0</a>.</p>
22   * 
23   * <p>Any of the formating methods in this class may throw the following 
24   * exceptions:</p>
25   * 
26   * <ul>
27   *   <li>{@link PrintfTemplateException} - If the format template is invalid.  Or,
28   *     if the format template includes a variable width or precision, and the
29   *     value supplied is negative.</li>
30   *   <li>{@link ClassCastException} - If a converstion type requires a certain
31   *     type of data, but the wrong data type is offered.</li>
32   *   <li>{@link NullPointerException} - If the data vector is <code>null</code>,
33   *     but the format template calls for data.  Or, if a conversion type 
34   *     requires non-<wbr><code>null</code> data, but the data being converted is 
35   *     <code>null</code>.</li>
36   * </ul>
37   * 
38   * <p><b>Quick tip for C programmers:</b> Programmers familiar with 
39   * <code>printf</code> in C may find the following idiom translations 
40   * useful.</p>
41   * 
42   * <table border=1>
43   *   <tr>
44   *     <th>C idiom</th>
45   *     <th>Printf for Java idiom</th>
46   *   </tr>
47   *   <tr>
48   *     <td><code>printf(fmt, arg1, arg2, ...)</code></td>
49   *     <td><code>Printf.out(fmt, new Object[] {arg1, arg2, ...})</code></td>
50   *   </tr>
51   *   <tr>
52   *     <td><code>sprintf(buff, fmt, arg1, arg2, ...)</code></td>
53   *     <td><code>buff = Printf.format(fmt, new Object[] {arg1, arg2, ...})</code></td>
54   *   </tr>
55   *   <tr>
56   *     <td><code>fprintf(out, fmt, arg1, arg2, ...)</code></td>
57   *     <td><code>Printf.write(out, fmt, new Object[] {arg1, arg2, ...})</code></td>
58   *   </tr>
59   * </table>
60   * 
61   * @author Sharky 
62   */
63  public final class Printf
64  {
65  	
66    /***
67     * Reserved.
68     */
69    private Printf()
70    {
71    }
72    
73    //////////////
74    //          //
75    //  format  //
76    //          //
77    //////////////
78    
79    /***
80     * Formats data to string.
81     * 
82     * <p><b>Details:</b> <code>format</code> converts the given data into a 
83     * string using the provided template.  Elements in the data vector may be 
84     * overwritten if the character counting format specifier is used.  The 
85     * template is pre-<wbr>compiled for efficiency.</p>
86     * 
87     * @param ipTemplate the template
88     * @param ioapData the data
89     * @return the formatted string
90     * 
91     * @see #format(String, Object[])
92     * @see #format(String, PrintfData)
93     */
94    public static String format(final PrintfTemplate ipTemplate, final Object[] ioapData)
95    {
96      final PrintfState vpState = new PrintfState();
97      vpState.mpOutput = new StringBuffer();
98      vpState.mapArgs = ioapData;
99      vpState.mnArgIndex = 0;
100     // Iterate through characters and fmt specifiers:
101     for (int vnI = 0; vnI < ipTemplate.mapComponents.length; ++vnI)
102       ipTemplate.mapComponents[vnI].format(vpState);
103     return vpState.mpOutput.toString();
104   }
105   
106   /***
107    * Formats data to string.
108    * 
109    * <p><b>Details:</b> <code>format</code> converts the given data into a 
110    * string using the provided template.  Elements in the data vector may be 
111    * overwritten if the character counting format specifier is used.</p>
112    * 
113    * @param isTemplate the template
114    * @param ioapData the data
115    * @return the formatted text
116    * 
117    * @see #format(PrintfTemplate, Object[])
118    * @see #format(String, PrintfData)
119    */
120   public static String format(final String isTemplate, final Object[] ioapData)
121   {
122     return format(new PrintfTemplate(isTemplate), ioapData);
123   }
124   
125   /***
126    * Formats data to string.
127    * 
128    * <p><b>Details:</b> <code>format</code> converts the given data into a 
129    * string using the provided template.  The data is given in a growable vector 
130    * for convenience.</p>
131    * 
132    * @param isTemplate the template
133    * @param ipData the data
134    * @return the formatted string
135    * 
136    * @see #format(PrintfTemplate, Object[])
137    * @see #format(String, Object[])
138    */
139   public static String format(final String isTemplate, final PrintfData ipData)
140   {
141     return format(new PrintfTemplate(isTemplate), ipData.done());
142   }
143   
144 	/***
145 	 * Formats template to stdout.
146 	 * 
147 	 * <p><b>Details:</b> <code>format</code> converts the given template to a 
148 	 * string.  Only format strings which do not require a data vector can be used 
149 	 * with this method.</p>
150 	 * 
151    * @param isTemplate the template
152    * @return the formatted string
153 	 * 
154    * @see #format(PrintfTemplate, Object[])
155    * @see #format(String, Object[])
156    * @see #format(String, PrintfData)
157 	 */
158 	public static String format(final String isTemplate)
159 	{
160 		return format(isTemplate, (Object[]) null);
161 	}
162   
163   ///////////
164   //       //
165   //  out  //
166   //       //
167   ///////////
168   
169 	/***
170 	 * Formats data to stdout.
171 	 * 
172 	 * <p><b>Details:</b> <code>format</code> converts the given data into a 
173 	 * string using the provided template and then outputs it to 
174 	 * <code>System.out</code>, which is usually the console.  The number of 
175 	 * characters output is returned.  Elements in the data vector may be 
176    * overwritten if the character counting format specifier is used.  The 
177    * template is pre-<wbr>compiled for efficiency.</p>
178 	 * 
179 	 * @param ipTemplate the template
180 	 * @param ioapData the data
181 	 * @return the number of characters output
182 	 * 
183    * @see #out(String, Object[])
184    * @see #out(String, PrintfData)
185 	 * @see #out(String)
186 	 */
187   public static int out(final PrintfTemplate ipTemplate, final Object[] ioapData)
188   {
189     final String vsOut = format(ipTemplate, ioapData);
190     System.out.print(vsOut);
191     return vsOut.length();
192   }
193   
194 	/***
195 	 * Formats data to stdout.
196 	 * 
197 	 * <p><b>Details:</b> <code>format</code> converts the given data into a 
198 	 * string using the provided template and then outputs it to 
199 	 * <code>System.out</code>, which is usually the console.  The number of 
200 	 * characters output is returned.  Elements in the data vector may be 
201 	 * overwritten if the character counting format specifier is used.</p>
202 	 * 
203 	 * @param isTemplate the template
204 	 * @param ioapData the data
205 	 * @return the number of characters output
206 	 * 
207    * @see #out(PrintfTemplate, Object[])
208    * @see #out(String, PrintfData)
209 	 * @see #out(String)
210 	 */
211   public static int out(final String isTemplate, final Object[] ioapData)
212   {
213     return out(new PrintfTemplate(isTemplate), ioapData);
214   }
215   
216 	/***
217 	 * Formats data to stdout.
218 	 * 
219 	 * <p><b>Details:</b> <code>format</code> converts the given data into a 
220 	 * string using the provided template and then outputs it to 
221 	 * <code>System.out</code>, which is usually the console.  The number of 
222 	 * characters output is returned.  The data is given in a growable vector for 
223 	 * convenience.</p>
224 	 * 
225 	 * @param isTemplate the template
226 	 * @param ipData the data
227 	 * @return the number of characters output
228 	 * 
229    * @see #out(PrintfTemplate, Object[])
230    * @see #out(String, Object[])
231 	 * @see #out(String)
232 	 */
233   public static int out(final String isTemplate, final PrintfData ipData)
234   {
235     return out(isTemplate, ipData.done());
236   }
237   
238 	/***
239 	 * Formats template to stdout.
240 	 * 
241 	 * <p><b>Details:</b> <code>format</code> converts the given template to a 
242 	 * string and then outputs it to <code>System.out</code>, which is usually the 
243 	 * console.  The number of characters output is returned.  Only format strings 
244 	 * which do not require a data vector can be used with this method.</p>
245 	 * 
246 	 * @param isTemplate the template
247 	 * @return the number of characters output
248 	 * 
249    * @see #out(PrintfTemplate, Object[])
250    * @see #out(String, Object[])
251 	 * @see #out(String, PrintfData)
252 	 */
253   public static int out(final String isTemplate)
254   {
255   	return out(isTemplate, (Object[]) null);
256   }
257   
258 	/////////////
259 	//         //
260   //  write  //
261   //         //
262   /////////////
263   
264 	/***
265 	 * Formats data to stream.
266 	 * 
267 	 * <p><b>Details:</b> <code>write</code> converts the given data into a string 
268 	 * using the provided template and then writes it to the given stream.  The 
269 	 * number of characters output is returned.  Elements in the data vector may 
270 	 * be overwritten if the character counting format specifier is used.  The 
271 	 * template is pre-<wbr>compiled for efficiency.</p>
272 	 * 
273 	 * @param ipWriter the stream
274 	 * @param ipTemplate the template
275 	 * @param ioapData the data
276 	 * @return the number of characters output
277 	 * @throws IOException if writing to the stream causes an IOException
278    * 
279    * @see #write(Writer, String, Object[])
280    * @see #write(Writer, String, PrintfData)
281    * @see #write(Writer, String)
282 	 */
283 	public static int write
284 	( final Writer ipWriter, 
285 	  final PrintfTemplate ipTemplate, 
286 	  final Object[] ioapData
287 	) throws IOException
288 	{
289 		final String vsOut = format(ipTemplate, ioapData);
290 		ipWriter.write(vsOut);
291 		return vsOut.length();
292 	}
293   
294 	/***
295 	 * Formats data to stream.
296 	 * 
297 	 * <p><b>Details:</b> <code>write</code> converts the given data into a string 
298 	 * using the provided template and then outputs it to the given stream.  The 
299 	 * number of characters output is returned.  Elements in the data vector may 
300 	 * be overwritten if the character counting format specifier is used.</p>
301 	 * 
302 	 * @param ipWriter the stream
303 	 * @param isTemplate the template
304 	 * @param ioapData the data
305 	 * @return the number of characters output
306 	 * @throws IOException if writing to the stream causes an IOException
307    * 
308    * @see #write(Writer, PrintfTemplate, Object[])
309    * @see #write(Writer, String, PrintfData)
310    * @see #write(Writer, String)
311 	 */
312 	public static int write
313 	( final Writer ipWriter, 
314 	  final String isTemplate, 
315 	  final Object[] ioapData
316 	) throws IOException
317 	{
318 		return write(ipWriter, new PrintfTemplate(isTemplate), ioapData);
319 	}
320   
321 	/***
322 	 * Formats data to stream.
323 	 * 
324 	 * <p><b>Details:</b> <code>write</code> converts the given data into a string 
325 	 * using the provided template and then outputs it to the given stream.  The 
326 	 * number of characters output is returned.  The data is given in a growable 
327 	 * vector for convenience.</p>
328 	 * 
329 	 * @param ipWriter the stream
330 	 * @param isTemplate the template
331 	 * @param ipData the data
332 	 * @return the number of characters output
333 	 * @throws IOException if writing to the stream causes an IOException
334    * 
335    * @see #write(Writer, PrintfTemplate, Object[])
336    * @see #write(Writer, String, Object[])
337    * @see #write(Writer, String)
338 	 */
339 	public static int write
340 	( final Writer ipWriter, 
341 	  final String isTemplate, 
342 	  final PrintfData ipData
343 	) throws IOException
344 	{
345 		return write(ipWriter, isTemplate, ipData.done());
346 	}
347   
348 	/***
349 	 * Formats template to stream.
350 	 * 
351 	 * <p><b>Details:</b> <code>write</code> converts the given template into a 
352 	 * string and then outputs it to the given stream.  The number of characters 
353 	 * output is returned.  Only format strings which do not require a data vector 
354 	 * can be used with this method.</p>
355 	 * 
356 	 * @param ipWriter the stream
357 	 * @param isTemplate the template
358 	 * @return the number of characters output
359 	 * @throws IOException if writing to the stream causes an IOException
360 	 * 
361    * @see #write(Writer, PrintfTemplate, Object[])
362    * @see #write(Writer, String, Object[])
363    * @see #write(Writer, String, PrintfData)
364 	 */
365 	public static int write(final Writer ipWriter, final String isTemplate) throws IOException
366 	{
367 		return write(ipWriter, isTemplate, (Object[]) null);
368 	}
369   
370 }
371