]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 occurrence 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 | This pipe-delimited syntax is 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 occurrence. 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 straight 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 | "../../../doc/images/valid-html401.png" 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> |