1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
---|
2 | |
---|
3 | <HTML><HEAD><TITLE>The Boost Format library</TITLE> |
---|
4 | <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
---|
5 | </HEAD> |
---|
6 | <BODY bgColor=white text=black> |
---|
7 | |
---|
8 | <H1><IMG align=middle alt="boost.png (6897 bytes)" height=86 |
---|
9 | src="../../../boost.png" width=277>The Boost Format library</H1> |
---|
10 | <P>The <CODE> |
---|
11 | <A href="../../../boost/format.hpp"><boost/format.hpp></A></CODE> |
---|
12 | format class provides printf-like formatting, in a type-safe manner which allows output of |
---|
13 | user-defined types. |
---|
14 | <br> |
---|
15 | </P> |
---|
16 | <ul> |
---|
17 | <li><a href="#synopsis">Synopsis</a> </li> |
---|
18 | <li><a href="#how_it_works">How it works</a> </li> |
---|
19 | <li><a href="#examples">Examples</a> </li> |
---|
20 | <li><a href="#syntax">Syntax</a> |
---|
21 | <ul> |
---|
22 | <li><a href="#printf_directives">printf format-specification syntax</a> </li> |
---|
23 | <li><a href="#printf_differences">Incompatibilities with printf</a> </li> |
---|
24 | </ul> |
---|
25 | </li> |
---|
26 | <li><a href="#manipulators">Manipulators and the internal stream state</a> </li> |
---|
27 | <li><a href="#user-defined">User-defined types</a> </li> |
---|
28 | <li><a href="#alternatives">Alternatives</a></li> |
---|
29 | <li><a href="#exceptions">Exceptions</a></li> |
---|
30 | <li><a href="#performance">Performance</a></li> |
---|
31 | <li><a href="#extract">Class Interface Extract</a></li> |
---|
32 | <li><a href="#rationale">Rationale</a> </li> |
---|
33 | </ul> |
---|
34 | <a name="synopsis"></a> |
---|
35 | <hr> |
---|
36 | <H2>Synopsis</H2> |
---|
37 | <P>A format object is constructed from a format-string, and is then given arguments through |
---|
38 | repeated calls to <i>operator%</i>. |
---|
39 | <br> |
---|
40 | Each of those arguments are then converted to strings, who are in turn combined into one string, |
---|
41 | according to the format-string. |
---|
42 | </P> |
---|
43 | <BLOCKQUOTE><PRE> |
---|
44 | cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50; |
---|
45 | // prints "writing toto, x=40.230 : 50-th try" |
---|
46 | </PRE></BLOCKQUOTE> |
---|
47 | |
---|
48 | <a name="how_it_works"></a> |
---|
49 | <hr> |
---|
50 | <H2>How it works</H2> |
---|
51 | <ol> |
---|
52 | <li>When you call <i>format(s)</i>, where s is the format-string, it constructs an object, |
---|
53 | which parses the format string and look for all directives in it and prepares internal structures |
---|
54 | for the next step.</li> |
---|
55 | <li> |
---|
56 | Then, either immediately, |
---|
57 | as in <BLOCKQUOTE><PRE>cout << format("%2% %1%") % 36 % 77 )</PRE></BLOCKQUOTE> |
---|
58 | or later on, as in |
---|
59 | <BLOCKQUOTE><PRE>format fmter("%2% %1%"); |
---|
60 | fmter % 36; fmter % 77;</PRE></BLOCKQUOTE> |
---|
61 | you <i>feed</i> variables into the formatter. |
---|
62 | <br>those variables are dumped into an internal stream, |
---|
63 | which state is set according to the given formatting options in the format-string |
---|
64 | -if there are any-, |
---|
65 | and the format object stores the string results for the last step. |
---|
66 | </li> |
---|
67 | <li>Once all arguments have been fed you can dump the format object to a stream, |
---|
68 | or get its string value by using the |
---|
69 | <i>str()</i> member function, or the free function <i>str(const format& )</i> in namespace <i>boost</i>. The result string stays accessible in the format object until another argument is passed, |
---|
70 | at which time it is reinitialised. |
---|
71 | |
---|
72 | <BLOCKQUOTE><PRE> |
---|
73 | |
---|
74 | // fmter was previously created and fed arguments, it can print the result : |
---|
75 | cout << fmter ; |
---|
76 | |
---|
77 | // You can take the string result : |
---|
78 | string s = fmter.str(); |
---|
79 | |
---|
80 | // possibly several times : |
---|
81 | s = fmter.str( ); |
---|
82 | |
---|
83 | // You can also do all steps at once : |
---|
84 | cout << boost::format("%2% %1%") % 36 % 77; |
---|
85 | |
---|
86 | // using the str free function : |
---|
87 | string s2 = str( format("%2% %1%") % 36 % 77 ); |
---|
88 | |
---|
89 | </PRE></BLOCKQUOTE> |
---|
90 | </li> |
---|
91 | <li> |
---|
92 | Optionnally, after step 3, you can re-use a format object and restart at step2 : |
---|
93 | <i>fmter % 18 % 39; </i> |
---|
94 | <br> to format new variables with the same format-string, saving the expensive processing |
---|
95 | involved at step 1. |
---|
96 | </li> |
---|
97 | </ol> |
---|
98 | All in all, the format class translates a format-string (with eventually printf-like directives) |
---|
99 | into operations on an internal stream, and finally returns the result of the formatting, |
---|
100 | as a string, or directly into an output stream. |
---|
101 | |
---|
102 | <a name="examples"></a> |
---|
103 | <hr> |
---|
104 | <H2>Examples</H2> |
---|
105 | |
---|
106 | <BLOCKQUOTE><PRE> |
---|
107 | using namespace std; |
---|
108 | using boost::format; |
---|
109 | using boost::io::group; |
---|
110 | </PRE></BLOCKQUOTE> |
---|
111 | <ul> |
---|
112 | <li> Simple output, with reordering : |
---|
113 | <BLOCKQUOTE><PRE> |
---|
114 | |
---|
115 | cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style. |
---|
116 | |
---|
117 | </PRE></BLOCKQUOTE> |
---|
118 | It prints : "11 22 333 22 11 \n" |
---|
119 | </li> |
---|
120 | |
---|
121 | <li> More precise formatting, with Posix-printf positional directives : |
---|
122 | <BLOCKQUOTE><PRE> |
---|
123 | |
---|
124 | cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; // Posix-Printf style |
---|
125 | |
---|
126 | </PRE></BLOCKQUOTE> |
---|
127 | It prints : "(x,y) = ( -23, +35) \n" |
---|
128 | </li> |
---|
129 | |
---|
130 | <li> classical printf directive, no reordering : |
---|
131 | <BLOCKQUOTE><PRE> |
---|
132 | |
---|
133 | cout << format("writing %s, x=%s : %d-th step \n") % "toto" % 40.23 % 50; |
---|
134 | |
---|
135 | </PRE></BLOCKQUOTE> |
---|
136 | It prints : "writing toto, x=40.23 : 50-th step \n" |
---|
137 | </li> |
---|
138 | |
---|
139 | <li> Several ways to express the same thing : |
---|
140 | <BLOCKQUOTE><PRE> |
---|
141 | |
---|
142 | cout << format("(x,y) = (%+5d,%+5d) \n") % -23 % 35; |
---|
143 | cout << format("(x,y) = (%|+5|,%|+5|) \n") % -23 % 35; |
---|
144 | |
---|
145 | cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; |
---|
146 | cout << format("(x,y) = (%|1$+5|,%|2$+5|) \n") % -23 % 35; |
---|
147 | |
---|
148 | </PRE></BLOCKQUOTE> |
---|
149 | all those print : "(x,y) = ( -23, +35) \n" |
---|
150 | |
---|
151 | </li> |
---|
152 | |
---|
153 | <li> Using manipulators to modify the format-string : |
---|
154 | <BLOCKQUOTE><PRE> |
---|
155 | |
---|
156 | format fmter("_%1$+5d_ %1$d \n"); |
---|
157 | |
---|
158 | format fmter2("_%1%_ %1% \n"); |
---|
159 | fmter2.modify_item(1, group(showpos, setw(5)) ); |
---|
160 | |
---|
161 | cout << fmter % 101 ; |
---|
162 | cout << fmter2 % 101 ; |
---|
163 | |
---|
164 | </PRE></BLOCKQUOTE> |
---|
165 | Both print the same : "_ +101_ 101 \n" |
---|
166 | </li> |
---|
167 | |
---|
168 | <li> Using manipulators with arguments : |
---|
169 | <BLOCKQUOTE><PRE> |
---|
170 | |
---|
171 | cout << format("_%1%_ %1% \n") % group(showpos, setw(5), 101); |
---|
172 | |
---|
173 | </PRE></BLOCKQUOTE> |
---|
174 | The manipulators are applied at each occurence of %1%, and thus it prints : "_ +101_ +101 \n" |
---|
175 | </li> |
---|
176 | |
---|
177 | <li> New formatting feature : 'absolute tabulations', useful inside loops, |
---|
178 | to insure a field is printed at the same position from one line to the next, |
---|
179 | even if the widthes of the previous arguments can vary a lot. |
---|
180 | |
---|
181 | <BLOCKQUOTE><PRE> |
---|
182 | |
---|
183 | for(unsigned int i=0; i < names.size(); ++i) |
---|
184 | cout << format("%1%, %2%, %|40t|%3%\n") % names[i] % surname[i] % tel[i]; |
---|
185 | |
---|
186 | </PRE></BLOCKQUOTE> |
---|
187 | |
---|
188 | For some std::vector <i>names</i>, <i>surnames</i>, and <i>tel</i> (see sample_new_features.cpp) it prints : |
---|
189 | <BLOCKQUOTE><PRE> |
---|
190 | Marc-François Michel, Durand, +33 (0) 123 456 789 |
---|
191 | Jean, de Lattre de Tassigny, +33 (0) 987 654 321 |
---|
192 | </PRE></BLOCKQUOTE> |
---|
193 | |
---|
194 | |
---|
195 | </li> |
---|
196 | |
---|
197 | </ul> |
---|
198 | |
---|
199 | <hr> |
---|
200 | <H2>Sample Files</H2> |
---|
201 | <P>The program <A href="../example/sample_formats.cpp">sample_formats.cpp</A> |
---|
202 | demonstrates simple uses of <B>format</B>. |
---|
203 | <br> |
---|
204 | <P><A href="../example/sample_new_features.cpp">sample_new_features.cpp</A> |
---|
205 | illustrates the few formatting features that were added to printf's syntax such as |
---|
206 | simple positional directives, centered alignment, and 'tabulations'. |
---|
207 | <br> |
---|
208 | <P><A href="../example/sample_advanced.cpp">sample_advanced.cpp</A> |
---|
209 | demonstrates uses of advanced features, like reusing, and modifying, format objects, etc.. |
---|
210 | <br> |
---|
211 | <P>And <A href="../example/sample_userType.cpp">sample_userType.cpp</A> |
---|
212 | shows the behaviour of the <b>format</b> library on user-defined types. |
---|
213 | </P> |
---|
214 | |
---|
215 | |
---|
216 | <a name="syntax"></a> |
---|
217 | <hr> |
---|
218 | <H2>Syntax</H2> |
---|
219 | <P> |
---|
220 | <b>boost::format( </b> format-string <b> ) %</b> arg1 <b>%</b> arg2 <b>%</b> ... <b>%</b> argN |
---|
221 | |
---|
222 | </P> |
---|
223 | |
---|
224 | <P> |
---|
225 | The <i>format-string</i> contains text in which special directives will be replaced by |
---|
226 | strings resulting from the formatting of the given arguments. |
---|
227 | <br>The legacy syntax in the C and C++ worlds is the one used by printf, and thus format can use |
---|
228 | directly printf format-strings, and produce the same result (in almost all cases. see |
---|
229 | <a href="#printf_differences">Incompatibilities with printf</a> for details) |
---|
230 | <br> |
---|
231 | This core syntax was extended, to allow new features, but also to adapt to the C++ streams context. |
---|
232 | Thus, format accepts several forms of directives in format-strings : |
---|
233 | <UL> |
---|
234 | <li> Legacy printf format strings : <B>%</B><i>spec</i><b></b> where <i>spec</i> is a |
---|
235 | <a href="#printf_directives">printf format specification</a> |
---|
236 | <br><i>spec</i> passes formatting options, like width, alignment, numerical base used for |
---|
237 | formatting numbers, |
---|
238 | as well as other specific flags. |
---|
239 | But the classical <i>type-specification</i> flag of printf has a weaker meaning |
---|
240 | in format. It merely sets the appropriate flags on the internal stream, |
---|
241 | and/or formatting parameters, |
---|
242 | but does not require the corresponding argument to be of a specific type. |
---|
243 | <br> |
---|
244 | e.g. : the specification <i>2$x</i>, |
---|
245 | meaning "print argument number 2, which is an integral number, in hexa" for printf, |
---|
246 | merely means "print argument 2 with stream basefield flags set to <i>hex</i>" for format. |
---|
247 | </li> |
---|
248 | <li><B>%|</B><i>spec</i><b>|</b> where <i>spec</i> is a printf format specification. |
---|
249 | <br> |
---|
250 | The brackets are introduced, to improve the readability of the format-string, |
---|
251 | but primarily, to make the <i>type-conversion character</i> optional |
---|
252 | in <i>spec</i>. This information is not necessary with C++ variables, |
---|
253 | but with direct printf syntax, it is necessary to always give a type-conversion character, |
---|
254 | merely because this character is crucial to determine the end of a format-specification. |
---|
255 | <br> |
---|
256 | e.g. : "%|-5|" will format the next variable with width set to 5, and left-alignment |
---|
257 | just like the following printf directives : "%-5g", "%-5f", "%-5s" .. |
---|
258 | </li> |
---|
259 | <li> <b>%</b><i>N</i><b>%</b> <br>This simple positional notation |
---|
260 | requests the formatting of the <i>N</i>-th argument - wihout any formatting option. |
---|
261 | <br> |
---|
262 | (It's merely a shortcut to Printf's positional directives (like "%<i>N</i>$s"), |
---|
263 | but a major benefit is that it's much more readable, and |
---|
264 | does not use a "type-conversion" character) |
---|
265 | </li> |
---|
266 | </UL> |
---|
267 | On top of the standard printf format specifications, new features were implemented, like centered alignment. See <a href="#new_directives">new format specification</a> for details. |
---|
268 | |
---|
269 | <a name="printf_directives"></a> |
---|
270 | <h3>printf format specifications</h3> |
---|
271 | <p> |
---|
272 | The printf format specifications supported by Boost.format follows the Unix98 |
---|
273 | <a href="http://www.opengroup.org/onlinepubs/7908799/xsh/fprintf.html">Open-group printf</a> |
---|
274 | precise syntax, rather than the standard C printf, which does not support positional arguments. |
---|
275 | (Common flags have the same meaning in both, so it should not be a headache for anybody) |
---|
276 | <br> |
---|
277 | <i> Note that it is an error to use positional format specifications</i> |
---|
278 | (e.g. <i>%3$+d</i>) |
---|
279 | <i> mixed with non-positional ones</i> (e.g. <i>%+d</i>) <i>in the same format string.</i> |
---|
280 | <br> |
---|
281 | In the Open-group specification, referring to the same argument several times (e.g. <i>"%1$d %1$d"</i>) has undefined behaviour. Boost.format's behaviour in such cases is to allow each argument to be reffered to any number of times. The only constraint is |
---|
282 | that it expects exactly <i>P</i> arguments, <i>P</i> being the maximum argument number used in the |
---|
283 | format string. (e.g., for "%1$d %10$d", <i>P</i> == 10 ). |
---|
284 | <br>Supplying more, or less, than <i>P</i> arguments raises an exception. |
---|
285 | (unless it was set otherwise, see <a href="#exceptions">exceptions</a>) |
---|
286 | </p> |
---|
287 | <p> |
---|
288 | <br> |
---|
289 | <br> |
---|
290 | A specification <i>spec</i> has the form : |
---|
291 | [ <i>N</i><b>$</b> ] [ <i>flags</i> ] [ <i>width</i> ] |
---|
292 | [ <b>.</b> <i>precision</i> ] <i>type-char</i> |
---|
293 | <br> |
---|
294 | <br> |
---|
295 | Fields insided square brackets are optional. |
---|
296 | Each of those fields are explained one by one in the following list : |
---|
297 | </p> |
---|
298 | |
---|
299 | <ul> |
---|
300 | <li> |
---|
301 | <i>N</i> <b>$</b> (optional field) specifies that the format specification applies to the <i>N</i>-th argument. (it is called a <i>positional format specification</i>) |
---|
302 | <br>If this is not present, arguments are taken one by one. (and it is then an error to later supply an argument number) |
---|
303 | <li> |
---|
304 | <i>flags</i> is a sequences of any of those : |
---|
305 | <blockquote> |
---|
306 | <table border="1" cellpadding="5"> |
---|
307 | <tr> <td><b>Flag</b></td> <td><b>Meaning</b></td> <td><b>effect on internal stream</b></td> |
---|
308 | </tr> |
---|
309 | |
---|
310 | <tr> <td><b>'-'</b></td> <td>left alignment</td> |
---|
311 | <td>N/A (applied later on the string)</td> |
---|
312 | </tr> |
---|
313 | <tr> |
---|
314 | <td><b>'='</b></td> <td>centered alignment</td> |
---|
315 | <td>N/A (applied later on the string) |
---|
316 | <br><i>- note : added feature, not in printf -</i> |
---|
317 | </td> |
---|
318 | </tr> |
---|
319 | <tr> |
---|
320 | <td><b>'_'</b></td> <td>internal alignment</td> |
---|
321 | <td>sets internal alignment |
---|
322 | <br><i>- note : added feature, not in printf -</i> |
---|
323 | </td> |
---|
324 | </tr> |
---|
325 | |
---|
326 | <tr> <td><b>'+'</b></td> <td>show sign even for positive numbers</td> |
---|
327 | <td>sets <i>showpos</i></td> |
---|
328 | </tr> |
---|
329 | <tr> |
---|
330 | <td><b>'#'</b></td> |
---|
331 | <td>show numerical base, and decimal point</td> |
---|
332 | <td>sets <i>showbase</i> and <i>showpoint</i></td> |
---|
333 | </tr> |
---|
334 | <tr> |
---|
335 | <td><b>'0'</b></td> |
---|
336 | <td>pad with 0's (inserted after sign or base indicator)</td> |
---|
337 | <td>if not left-aligned, calls <i>setfill('0')</i> and sets <i>internal</i> |
---|
338 | <br> Extra actions are taken after stream conversion to handle |
---|
339 | <a href="#user-defined">user-defined output</a>. </td> |
---|
340 | </tr> |
---|
341 | <tr> |
---|
342 | <td><b>' '</b></td> |
---|
343 | <td>if the string does not begin with <i>+</i> or <i>-</i>, |
---|
344 | insert a <i>space</i> before the converted string</td> |
---|
345 | <td>N/A (applied later on the string) |
---|
346 | <br>Different to printf's behaviour : it is not affected by internal alignment</td> |
---|
347 | </tr> |
---|
348 | |
---|
349 | </table> |
---|
350 | </blockquote> |
---|
351 | </li> |
---|
352 | |
---|
353 | <li> |
---|
354 | <i>width</i> specifies a minimal width for the string resulting form the conversion. |
---|
355 | If necessary, the string will be padded with alignment and fill characters either set on the stream via manipulators, or specified by the format-string (e.g. flags '0', '-', ..) |
---|
356 | <br> |
---|
357 | Note that width is not just set on the conversion stream. |
---|
358 | To support output of <a href="#user-defined">user-defined types</a> |
---|
359 | (that might call <i>operator<<</i> many times on several members), |
---|
360 | the width is handled after stream conversion of the whole argument object, |
---|
361 | in the format class code. |
---|
362 | <li> |
---|
363 | <i>precision</i> (preceded by a point), sets the stream's <i>precision</i> |
---|
364 | <ul> |
---|
365 | <li>When outputting a floatting type number, it sets the maximum number of digits |
---|
366 | <ul><li>after decimal point when in fixed or scientific mode</li> |
---|
367 | <li>in total when in default mode ('<i>general mode</i>', like <i>%g</i>) </li> |
---|
368 | </ul> |
---|
369 | <li>When used with type-char <b>s</b> or <b>S</b> it takes another meaning : |
---|
370 | the conversion string is truncated to the <i>precision</i> first chars. |
---|
371 | (Note that the eventual padding to <i>width</i> is done after truncation.) |
---|
372 | </li> |
---|
373 | </ul> |
---|
374 | </li> |
---|
375 | <li> |
---|
376 | <i>type-char</i>. it does <b>not</b> impose the concerned argument to be of a restricted set |
---|
377 | of types, but merely sets the flags that are associated with this type specification. |
---|
378 | |
---|
379 | <blockquote> |
---|
380 | <table border="1" cellpadding="5"> |
---|
381 | <tr> |
---|
382 | <td><b>Type-Char</b></td> |
---|
383 | <td><b>Meaning</b></td> |
---|
384 | <td><b>effect on stream</b></td> |
---|
385 | </tr> |
---|
386 | <tr> |
---|
387 | <td><b>p or x</b></td> |
---|
388 | <td>hexadecimal output</td> |
---|
389 | <td>sets <i>hex</i></td> |
---|
390 | </tr> |
---|
391 | <tr> |
---|
392 | <td><b>o</b></td> |
---|
393 | <td>octal output</td> |
---|
394 | <td>sets <i>oct</i></td> |
---|
395 | </tr> |
---|
396 | <tr> |
---|
397 | <td><b>e</b></td> |
---|
398 | <td>scientific float format</td> |
---|
399 | <td>sets floatfield bits to <i>scientific</i></td> |
---|
400 | </tr> |
---|
401 | <tr> |
---|
402 | <td><b>f</b></td> |
---|
403 | <td>fixed float format</td> |
---|
404 | <td>sets floatfield bits to <i>fixed</i></td> |
---|
405 | </tr> |
---|
406 | <tr> |
---|
407 | <td><b>g</b></td> |
---|
408 | <td>general -default- float format</td> |
---|
409 | <td><b>unset</b> all floatfield bits</td> |
---|
410 | </tr> |
---|
411 | <tr> |
---|
412 | <td><b>X, E</b> or <b>G</b></td> |
---|
413 | <td>same effect as their lowercase counterparts, |
---|
414 | but using uppercase letters for number outputs. (exponents, hex digits, ..)</td> |
---|
415 | <td>same effects as <i>'x'</i>, <i>'e'</i>, or <i>'g'</i>, |
---|
416 | <b>plus</b> <i>uppercase</i></td> |
---|
417 | </tr> |
---|
418 | |
---|
419 | <tr> |
---|
420 | <td><b>d, i</b> or <b>u</b></td> |
---|
421 | <td><b>decimal</b> type output</td> |
---|
422 | <td>sets basefield bits to <i>dec</i></td> |
---|
423 | </tr> |
---|
424 | <tr> |
---|
425 | <td><b>s</b> or <b>S</b></td> |
---|
426 | <td>string output</td> |
---|
427 | <td><i>precision</i> specification is unset, |
---|
428 | and its value goes to an internal field for later 'truncation'. |
---|
429 | (see <i>precision</i> explanation above) </td> |
---|
430 | </tr> |
---|
431 | <tr> |
---|
432 | <td><b>c</b> or <b>C</b></td> |
---|
433 | <td>1-character output</td> |
---|
434 | <td>only the first character of the conversion string is used.</td> |
---|
435 | </tr> |
---|
436 | <tr> |
---|
437 | <td><b>%</b></td> |
---|
438 | <td>print the character <i>%</i></td> |
---|
439 | <td>N/A</td> |
---|
440 | </tr> |
---|
441 | </table> |
---|
442 | </blockquote> |
---|
443 | <p>Note that the 'n' type specification is ignored (and so is the corresponding argument), |
---|
444 | because it does not fit in this context. |
---|
445 | <br> |
---|
446 | Also, printf 'l', 'L', or 'h' modifiers (to indicate wide, long or short types) are supported |
---|
447 | (and simply have no effect on the internal stream). |
---|
448 | </p> |
---|
449 | |
---|
450 | </li> |
---|
451 | </ul> |
---|
452 | |
---|
453 | <a name="new_directives"></a> |
---|
454 | <h3>new format-specifications</h3> |
---|
455 | <ul> |
---|
456 | <li> as stated in the flags table, centered and internal alignment flags (' <i>=</i> ', |
---|
457 | and ' <i>_</i> ') were added. |
---|
458 | </li> |
---|
459 | <li> <i><b>%{</b>n</i><b>t}</b> , where <i>n</i> is a positive number, |
---|
460 | inserts an <i>absolute tabulation</i>. |
---|
461 | It means that format will, if needed, fill the string with characters, until |
---|
462 | the length of the string created so far reaches <i>n</i> characters. |
---|
463 | (see <a href="#examples">examples</a> ) |
---|
464 | </li> |
---|
465 | <li> <b>%{</b><i>n</i><B>T</B><i>X</i><b>}</b> inserts a tabulation in the same way, |
---|
466 | but using <i>X</i> as fill character instead of the current 'fill' char of the stream |
---|
467 | (which is <i>space</i> for a stream in default state) |
---|
468 | </li> |
---|
469 | </ul> |
---|
470 | |
---|
471 | <a name="printf_differences"></a> |
---|
472 | <h2>Differences of behaviour vs printf</h2> |
---|
473 | Suppose you have variables <i>x1, x2</i> (built_in types, supported by C's printf), |
---|
474 | <br> and a format string <i>s</i> intended for use with a printf function this way : |
---|
475 | <BLOCKQUOTE><PRE> |
---|
476 | printf(s, x1, x2); |
---|
477 | </PRE></BLOCKQUOTE> |
---|
478 | <br> |
---|
479 | In almost all cases, the result will be the same as with this command : |
---|
480 | <BLOCKQUOTE><PRE> |
---|
481 | cout << format(s) % x1 % x2; |
---|
482 | </PRE></BLOCKQUOTE> |
---|
483 | |
---|
484 | <p> |
---|
485 | But because some printf format specifications don't translate well into stream formatting options, |
---|
486 | there are a few notable imperfections in the way Boost.format emulates printf.<br> |
---|
487 | In any case, the <i>format</i> class should quietly ignore the unsupported options, so |
---|
488 | that printf format-strings are always accepted by format and produce almost the same |
---|
489 | output as printf. |
---|
490 | </p> |
---|
491 | <br>Here is the full list of such differences : |
---|
492 | <ul> |
---|
493 | <li> <b>'0'</b> and <b>' '</b> options : |
---|
494 | printf ignores these options for non numeric conversions, but format applies them to all |
---|
495 | types of variables. |
---|
496 | (so it is possible to use those options on user-defined types, e.g. a Rational class, etc..) |
---|
497 | </li> |
---|
498 | <li> <b>precision</b> for integral types arguments has a special meaning for printf : |
---|
499 | <br> <i> printf( "(%5.3d)" , 7 ) ;</i> prints « ( 007) » |
---|
500 | <br> While format, like streams, ignores the precision parameter for integral types conversions. |
---|
501 | </li> |
---|
502 | <li> the <b>'</b> printf option |
---|
503 | (<i>format with thousands grouping characters)</i>) |
---|
504 | has no effect in format. |
---|
505 | </li> |
---|
506 | <li> Width or precision set to asterisk (<i>*</i>) are used by printf to read this field from |
---|
507 | an argument. e.g. |
---|
508 | <i>printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);</i> |
---|
509 | <br>This class does not support this mechanism for now. so such precision or width fields are quietly |
---|
510 | ignored by the parsing. |
---|
511 | </ul> |
---|
512 | |
---|
513 | Also, note that the special <b>'n'</b> type-specification |
---|
514 | (used to tell printf to save in a variable the number of characters output by the formatting) |
---|
515 | has no effect in format. |
---|
516 | <br> Thus format strings containing this type-specification should produce the same converted |
---|
517 | string by printf or format. |
---|
518 | It will not cause differences in the formatted strings between printf and format. |
---|
519 | <br>To get the number of characters in the formatted string using Boost.Format, |
---|
520 | you can use the <i>size()</i> member function : |
---|
521 | <BLOCKQUOTE><PRE> |
---|
522 | format formatter("%+5d"); |
---|
523 | cout << formatter % x; |
---|
524 | unsigned int n = formatter.size(); |
---|
525 | </PRE></BLOCKQUOTE> |
---|
526 | |
---|
527 | <a name="user-defined"></a> |
---|
528 | <hr> |
---|
529 | <h2>User-defined types output</h2> |
---|
530 | <p> |
---|
531 | All flags which are translated into modification to the stream state |
---|
532 | act recursively within user-defined types. |
---|
533 | ( the flags remain active, and so does the desired format option, for each of |
---|
534 | the '<<' operations that might be called by the user-defined class) |
---|
535 | </p> |
---|
536 | e.g., with a Rational class, we would have something like : |
---|
537 | <BLOCKQUOTE><PRE> |
---|
538 | Rational ratio(16,9); |
---|
539 | cerr << format("%#x \n") % ratio; // -> "0x10/0x9 \n" |
---|
540 | </PRE></BLOCKQUOTE> |
---|
541 | |
---|
542 | <p> |
---|
543 | It's a different story for other formatting options. For example, setting width applies |
---|
544 | to the final output produced by the object, not to each of its internal outputs, and |
---|
545 | that's fortunate : |
---|
546 | </p> |
---|
547 | <BLOCKQUOTE><PRE> |
---|
548 | cerr << format("%-8d") % ratio; // -> "16/9 " and not "16 /9 " |
---|
549 | cerr << format("%=8d") % ratio; // -> " 16/9 " and not " 16 / 9 " |
---|
550 | </PRE></BLOCKQUOTE> |
---|
551 | <p> |
---|
552 | <br>But so does the 0 and ' ' options (contrarily to '+' which is directly translated to the stream |
---|
553 | state by <i>showpos</i>. But no such flags exist for the zero and space printf options) |
---|
554 | <br>and that is less natural : |
---|
555 | </p> |
---|
556 | <BLOCKQUOTE><PRE> |
---|
557 | cerr << format("%+08d \n") % ratio; // -> "+00016/9" |
---|
558 | cerr << format("% 08d \n") % ratio; // -> "000 16/9" |
---|
559 | </PRE></BLOCKQUOTE> |
---|
560 | It is possible to obtain a better behaviour by carefully designing the Rational's <i>operator<<</i> |
---|
561 | to handle the stream's width, alignment and <i>showpos</i> paramaters by itself. This is demonstrated in |
---|
562 | <A href="../example/sample_userType.cpp">sample_userType.cpp</A>. |
---|
563 | |
---|
564 | <p></p> |
---|
565 | |
---|
566 | <a name="manipulators"></a> |
---|
567 | <hr> |
---|
568 | <h3>Manipulators, and internal stream state</h3> |
---|
569 | <P> |
---|
570 | The internal stream state of <B>format</B> is saved before |
---|
571 | and restored after output of an argument; therefore, the modifiers are not sticky and affect only |
---|
572 | the argument they are applied to. |
---|
573 | <br> The default state for streams, as stated by the standard, is : |
---|
574 | precision 6, width 0, right alignment, and decimal flag set. |
---|
575 | </P> |
---|
576 | <P> |
---|
577 | The state of the internal <B>format</B> stream can be changed by manipulators passed along |
---|
578 | with the argument; via the <i>group</i> function, like that : |
---|
579 | </p> |
---|
580 | <BLOCKQUOTE><PRE> |
---|
581 | cout << format("%1% %2% %1%\n") % group(hex, showbase, 40) % 50; // prints "0x28 50 0x28\n" |
---|
582 | </PRE></BLOCKQUOTE> |
---|
583 | <p> |
---|
584 | <br>When passing N items inside a 'group' Boost.format needs to process manipulators |
---|
585 | diferently from regular argument, and thus using group is subject to the following constraints : |
---|
586 | <ol> |
---|
587 | <li>the object to be printed must be passed as the last item in the group</li> |
---|
588 | <li>the first N-1 items are treated as manipulators, and if they do produce output, it is discarded |
---|
589 | </li> |
---|
590 | </ol> |
---|
591 | |
---|
592 | |
---|
593 | |
---|
594 | <p> |
---|
595 | Such manipulators are passed to the streams right before the following argument, |
---|
596 | at every occurence. |
---|
597 | Note that formatting options specified within the format string are overridden |
---|
598 | by stream state modifiers passed this way. For instance in the following code, |
---|
599 | the <i>hex</i> manipulator has priority over the <i>d</i> type-specification in |
---|
600 | the format-string which would set decimal output : |
---|
601 | </P> |
---|
602 | <BLOCKQUOTE><PRE> |
---|
603 | cout << format("%1$d %2% %1%\n") % group(hex, showbase, 40) % 50; |
---|
604 | // prints "0x28 50 0x28\n" |
---|
605 | </PRE></BLOCKQUOTE> |
---|
606 | |
---|
607 | |
---|
608 | <a name="alternatives"></a> |
---|
609 | <H2>Alternatives</H2> |
---|
610 | <ul> |
---|
611 | <li> |
---|
612 | <B>printf</B> is the classical alternative, that is not type safe and not extendable to user-defined types. |
---|
613 | <li> |
---|
614 | ofrstream.cc |
---|
615 | by Karl Nelson's design was a big source of inspiration to this format class. |
---|
616 | </li> |
---|
617 | <li>James Kanze's library |
---|
618 | has a format class (in <i>srcode/Extended/format</i> ) which looks |
---|
619 | very well polished. Its design has in common with this class the use of internal stream |
---|
620 | for the actual conversions, as well as using operators to pass arguments. |
---|
621 | (but his class, as ofrstream, uses <i>operator<< </i> rather <i>than operator%</i> ) |
---|
622 | </li> |
---|
623 | <li><a href="http://groups.yahoo.com/group/boost/files/format3/">Karl Nelson's library</a> |
---|
624 | was intented as demonstration of alternative solutions |
---|
625 | in discussions on Boost's list for the design of Boost.format. |
---|
626 | </li> |
---|
627 | </ul> |
---|
628 | |
---|
629 | |
---|
630 | <a name="exceptions"></a> |
---|
631 | <hr> |
---|
632 | <H2>Exceptions</H2> |
---|
633 | <p> |
---|
634 | Boost.format enforces a number of rules on the usage of format objects. The format-string must obeys |
---|
635 | the syntax described above, the user must supply exactly the right number of arguments before outputting to the final destination, and if using modify_item or bind_arg, items and arguments index |
---|
636 | must not be out of range. |
---|
637 | <br> |
---|
638 | When format detects that one of these rules is not satisfied, it raises a corresponding exception, |
---|
639 | so that the mistakes don't go unnoticed and unhandled. |
---|
640 | <br> |
---|
641 | But the user can change this behaviour to fit his needs, |
---|
642 | and select which types of errors may raise exceptions using the following functions : |
---|
643 | </p> |
---|
644 | <BLOCKQUOTE><PRE> |
---|
645 | |
---|
646 | unsigned char exceptions(unsigned char newexcept); // query and set |
---|
647 | unsigned char exceptions() const; // just query |
---|
648 | |
---|
649 | </PRE></BLOCKQUOTE> |
---|
650 | |
---|
651 | <p> |
---|
652 | The user can compute the argument <i>newexcept</i> by combining the following atoms using binary arithmetic : |
---|
653 | |
---|
654 | <ul> |
---|
655 | <li> <b>boost::io::bad_format_string_bit</b> selects errors due to ill-formed format-strings. |
---|
656 | </li> |
---|
657 | |
---|
658 | <li> <b>boost::io::too_few_args_bit</b> selects errors due to asking for the srting result before all arguments are passed. |
---|
659 | </li> |
---|
660 | |
---|
661 | <li> <b>boost::io::too_many_args_bit</b> selects errors due to passing too many arguments. |
---|
662 | </li> |
---|
663 | |
---|
664 | <li> <b>boost::io::out_of_range_bit</b> select errors due to out of range index supplied by the user when calling |
---|
665 | <i>modify_item</i> or other functions taking an item index (or an argument index) |
---|
666 | </li> |
---|
667 | |
---|
668 | <li> <b>boost::io::all_error_bits</b> selects all errors |
---|
669 | </li> |
---|
670 | |
---|
671 | <li> <b>boost::io::no_error_bits</b> selects no error. |
---|
672 | </li> |
---|
673 | |
---|
674 | </ul> |
---|
675 | <p> |
---|
676 | For instance, if you don't want Boost.format to detect bad number of arguments, you can define |
---|
677 | a specific wrapper function for building format objects with the right exceptions settings : |
---|
678 | </p> |
---|
679 | <BLOCKQUOTE><PRE> |
---|
680 | |
---|
681 | boost::format my_fmt(const std::string & f_string) { |
---|
682 | using namespace boost::io; |
---|
683 | format fmter(f_string); |
---|
684 | fmter.exceptions( all_error_bits ^ ( too_many_args_bit | too_few_args_bit ) ); |
---|
685 | return fmter; |
---|
686 | } |
---|
687 | |
---|
688 | </PRE></BLOCKQUOTE> |
---|
689 | |
---|
690 | It is then allowed to give more arguments than needed (they are simply ignored) : |
---|
691 | |
---|
692 | <BLOCKQUOTE><PRE> |
---|
693 | |
---|
694 | cout << my_fmt(" %1% %2% \n") % 1 % 2 % 3 % 4 % 5; |
---|
695 | |
---|
696 | </PRE></BLOCKQUOTE> |
---|
697 | |
---|
698 | And if we ask for the result before all arguments are supplied, the corresponding part of the |
---|
699 | result is simply empty |
---|
700 | |
---|
701 | <BLOCKQUOTE><PRE> |
---|
702 | |
---|
703 | cout << my_fmt(" _%2%_ _%1%_ \n") % 1 ; |
---|
704 | // prints " __ _1_ \n" |
---|
705 | |
---|
706 | </PRE></BLOCKQUOTE> |
---|
707 | |
---|
708 | <a name="performance"></a> |
---|
709 | <hr> |
---|
710 | <H2>A Note about performance</H2> |
---|
711 | <p> |
---|
712 | The performance of boost::format for formatting a few builtin type arguments with reordering can be compared |
---|
713 | to that of Posix-printf, and of the equivalent stream manual operations to give a measure |
---|
714 | of the overhead incurred. |
---|
715 | The result may greatly depend on the compiler, standard library implementation, and the precise |
---|
716 | choice of format-string and arguments. |
---|
717 | </p> |
---|
718 | <p> |
---|
719 | Since common stream implementations eventually call functions of the printf family for the actual |
---|
720 | formatting of numbers, in general printf will be noticeably faster than the direct stream operations |
---|
721 | And due to to the reordering overhead (allocations to store the pieces of string, |
---|
722 | stream initialisation at each item formatting, ..) the |
---|
723 | direct stream operations would be faster than boost::format, |
---|
724 | (one cas expect a ratio ranging from 2 to 5 or more) |
---|
725 | </p> |
---|
726 | <p> |
---|
727 | When iterated formattings are a performance bottleneck, performance can be slightly increased by parsing |
---|
728 | the format string into a format object, and copying it at each formatting, in the following way. |
---|
729 | </p> |
---|
730 | <BLOCKQUOTE><PRE> |
---|
731 | const boost::format fmter(fstring); |
---|
732 | dest << boost::format(fmter) % arg1 % arg2 % arg3 ; |
---|
733 | </PRE></BLOCKQUOTE> |
---|
734 | <p> |
---|
735 | As an example of performance results, the author measured the time of execution of iterated formattings |
---|
736 | with 4 different methods |
---|
737 | </p> |
---|
738 | <ol> |
---|
739 | <li> posix printf </li> |
---|
740 | <li> manual stream output (to a dummy <i>nullStream</i> stream sending the bytes into oblivion)</li> |
---|
741 | <li> boost::format copied from a const object as shown above</li> |
---|
742 | <li> the straigt boost::format usage </li> |
---|
743 | </ol> |
---|
744 | <p> |
---|
745 | the test was compiled with g++-3.3.3 and the following timings were measured (in seconds, and ratios) : |
---|
746 | </p> |
---|
747 | <BLOCKQUOTE><PRE> |
---|
748 | string fstring="%3$0#6x %1$20.10E %2$g %3$0+5d \n"; |
---|
749 | double arg1=45.23; |
---|
750 | double arg2=12.34; |
---|
751 | int arg3=23; |
---|
752 | |
---|
753 | - release mode : |
---|
754 | printf : 2.13 |
---|
755 | nullStream : 3.43, = 1.61033 * printf |
---|
756 | boost::format copied : 6.77, = 3.1784 * printf , = 1.97376 * nullStream |
---|
757 | boost::format straight :10.67, = 5.00939 * printf , = 3.11079 * nullStream |
---|
758 | |
---|
759 | - debug mode : |
---|
760 | printf : 2.12 |
---|
761 | nullStream : 3.69, = 1.74057 * printf |
---|
762 | boost::format copied :10.02, = 4.72642 * printf , = 2.71545 * nullStream |
---|
763 | boost::format straight :17.03, = 8.03302 * printf , = 4.61518 * nullStream |
---|
764 | </PRE></BLOCKQUOTE> |
---|
765 | |
---|
766 | |
---|
767 | <a name="extract"></a> |
---|
768 | <hr> |
---|
769 | <H2>Class Interface Extract</H2> |
---|
770 | |
---|
771 | <BLOCKQUOTE><PRE>namespace boost { |
---|
772 | |
---|
773 | template<class charT, class Traits=std::char_traits<charT> > |
---|
774 | class basic_format |
---|
775 | { |
---|
776 | public: |
---|
777 | typedef std::basic_string<charT, Traits> string_t; |
---|
778 | typedef typename string_t::size_type size_type; |
---|
779 | basic_format(const charT* str); |
---|
780 | basic_format(const charT* str, const std::locale & loc); |
---|
781 | basic_format(const string_t& s); |
---|
782 | basic_format(const string_t& s, const std::locale & loc); |
---|
783 | basic_format& operator= (const basic_format& x); |
---|
784 | |
---|
785 | void clear(); // reset buffers |
---|
786 | basic_format& parse(const string_t&); // clears and parse a new format string |
---|
787 | |
---|
788 | string_t str() const; |
---|
789 | size_type size() const; |
---|
790 | |
---|
791 | // pass arguments through those operators : |
---|
792 | template<class T> basic_format& operator%(T& x); |
---|
793 | template<class T> basic_format& operator%(const T& x); |
---|
794 | |
---|
795 | // dump buffers to ostream : |
---|
796 | friend std::basic_ostream<charT, Traits>& |
---|
797 | operator<< <> ( std::basic_ostream<charT, Traits>& , basic_format& ); |
---|
798 | |
---|
799 | // Choosing which errors will throw exceptions : |
---|
800 | unsigned char exceptions() const; |
---|
801 | unsigned char exceptions(unsigned char newexcept); |
---|
802 | |
---|
803 | // ............ this is just an extract ....... |
---|
804 | }; // basic_format |
---|
805 | |
---|
806 | typedef basic_format<char > format; |
---|
807 | typedef basic_format<wchar_t > wformat; |
---|
808 | |
---|
809 | |
---|
810 | // free function for ease of use : |
---|
811 | template<class charT, class Traits> |
---|
812 | std::basic_string<charT,Traits> str(const basic_format<charT,Traits>& f) { |
---|
813 | return f.str(); |
---|
814 | } |
---|
815 | |
---|
816 | |
---|
817 | } // namespace boost |
---|
818 | </PRE></BLOCKQUOTE> |
---|
819 | <P> |
---|
820 | </P> |
---|
821 | <hr> |
---|
822 | |
---|
823 | <a name="rationale"></a> |
---|
824 | <H2>Rationale</H2> |
---|
825 | <p>This class's goal is to bring a better, C++, type-safe and type-extendable <i>printf</i> |
---|
826 | equivalent to be used with streams. |
---|
827 | </p> |
---|
828 | Precisely, <b>format</b> was designed to provide the following features : |
---|
829 | <ul> |
---|
830 | <li> support positional arguments (required for internationalisation) |
---|
831 | <li> accept an unlimited number of arguments. |
---|
832 | <li> make formatting commands visually natural. |
---|
833 | <li> support the use of manipulators to modify the display of an argument. |
---|
834 | in addition to the format-string syntax. |
---|
835 | <li> accept any types of variables, by relying on streams for the actual conversion |
---|
836 | to string. This specifically concerns user-defined types, for which the formatting |
---|
837 | options effects should be intuitively natural. |
---|
838 | <li> provide printf-compatibility, as much as it makes sense in a type-safe and type-extendable |
---|
839 | context. |
---|
840 | </li> |
---|
841 | </ul> |
---|
842 | <p> In the process of the design, many issues were faced, and some choices were made, that |
---|
843 | might not be intuitively right. But in each case they were taken for |
---|
844 | <a href="choices.html">some reasons</a>. |
---|
845 | </p> |
---|
846 | <hr> |
---|
847 | <H2>Credits</H2> |
---|
848 | <P>The author of Boost format is Samuel Krempp. He used ideas from |
---|
849 | Rüdiger Loos' format.hpp and Karl Nelson's formatting classes. |
---|
850 | <HR> |
---|
851 | |
---|
852 | <P>Revised 26 January, 2003</P> |
---|
853 | <p> |
---|
854 | <a href="http://validator.w3.org/check/referer"><img border="0" |
---|
855 | src="http://www.w3.org/Icons/valid-html40" |
---|
856 | alt="Valid HTML 4.0!" height="31" width="88"></a> |
---|
857 | </p> |
---|
858 | <P>© Samuel Krempp 2002</p> |
---|
859 | <p> Use, modification, and distribution are subject to the Boost Software |
---|
860 | License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> |
---|
861 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> |
---|
862 | www.boost.org/LICENSE_1_0.txt</a>)</p> |
---|
863 | |
---|
864 | <P></P> |
---|
865 | <P> </P></BODY></HTML> |
---|