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