1 {fmt}
2 =====
3
4 .. image:: https://travis-ci.org/fmtlib/fmt.png?branch=master
5 :target: https://travis-ci.org/fmtlib/fmt
6
7 .. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v
8 :target: https://ci.appveyor.com/project/vitaut/fmt
9
10 .. image:: https://badges.gitter.im/Join%20Chat.svg
11 :alt: Join the chat at https://gitter.im/fmtlib/fmt
12 :target: https://gitter.im/fmtlib/fmt
13
14 **fmt** is an open-source formatting library for C++.
15 It can be used as a safe alternative to printf or as a fast
16 alternative to IOStreams.
17
18 `Documentation <http://fmtlib.net/latest/>`_
19
20 Features
21 --------
22
23 * Two APIs: faster concatenation-based `write API
24 <http://fmtlib.net/latest/api.html#write-api>`_ and slower,
25 but still very fast, replacement-based `format API
26 <http://fmtlib.net/latest/api.html#format-api>`_ with positional arguments
27 for localization.
28 * Write API similar to the one used by IOStreams but stateless allowing
29 faster implementation.
30 * Format API with `format string syntax
31 <http://fmtlib.net/latest/syntax.html>`_
32 similar to the one used by `str.format
33 <https://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python.
34 * Safe `printf implementation
35 <http://fmtlib.net/latest/api.html#printf-formatting-functions>`_
36 including the POSIX extension for positional arguments.
37 * Support for user-defined types.
38 * High speed: performance of the format API is close to that of
39 glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_
40 and better than the performance of IOStreams. See `Speed tests`_ and
41 `Fast integer to string conversion in C++
42 <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
43 * Small code size both in terms of source code (the core library consists of a single
44 header file and a single source file) and compiled code.
45 See `Compile time and code bloat`_.
46 * Reliability: the library has an extensive set of `unit tests
47 <https://github.com/fmtlib/fmt/tree/master/test>`_.
48 * Safety: the library is fully type safe, errors in format strings are
49 reported using exceptions, automatic memory management prevents buffer
50 overflow errors.
51 * Ease of use: small self-contained code base, no external dependencies,
52 permissive BSD `license
53 <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
54 * `Portability <http://fmtlib.net/latest/index.html#portability>`_ with consistent output
55 across platforms and support for older compilers.
56 * Clean warning-free codebase even on high warning levels
57 (-Wall -Wextra -pedantic).
58 * Support for wide strings.
59 * Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro.
60
61 See the `documentation <http://fmtlib.net/latest/>`_ for more details.
62
63 Examples
64 --------
65
66 This prints ``Hello, world!`` to stdout:
67
68 .. code:: c++
69
70 fmt::print("Hello, {}!", "world"); // uses Python-like format string syntax
71 fmt::printf("Hello, %s!", "world"); // uses printf format string syntax
72
73 Arguments can be accessed by position and arguments' indices can be repeated:
74
75 .. code:: c++
76
77 std::string s = fmt::format("{0}{1}{0}", "abra", "cad");
78 // s == "abracadabra"
79
80 fmt can be used as a safe portable replacement for ``itoa``:
81
82 .. code:: c++
83
84 fmt::MemoryWriter w;
85 w << 42; // replaces itoa(42, buffer, 10)
86 w << fmt::hex(42); // replaces itoa(42, buffer, 16)
87 // access the string using w.str() or w.c_str()
88
89 An object of any user-defined type for which there is an overloaded
90 :code:`std::ostream` insertion operator (``operator<<``) can be formatted:
91
92 .. code:: c++
93
94 #include "fmt/ostream.h"
95
96 class Date {
97 int year_, month_, day_;
98 public:
99 Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
100
101 friend std::ostream &operator<<(std::ostream &os, const Date &d) {
102 return os << d.year_ << '-' << d.month_ << '-' << d.day_;
103 }
104 };
105
106 std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
107 // s == "The date is 2012-12-9"
108
109 You can use the `FMT_VARIADIC
110 <http://fmtlib.net/latest/api.html#utilities>`_
111 macro to create your own functions similar to `format
112 <http://fmtlib.net/latest/api.html#format>`_ and
113 `print <http://fmtlib.net/latest/api.html#print>`_
114 which take arbitrary arguments:
115
116 .. code:: c++
117
118 // Prints formatted error message.
119 void report_error(const char *format, fmt::ArgList args) {
120 fmt::print("Error: ");
121 fmt::print(format, args);
122 }
123 FMT_VARIADIC(void, report_error, const char *)
124
125 report_error("file not found: {}", path);
126
127 Note that you only need to define one function that takes ``fmt::ArgList``
128 argument. ``FMT_VARIADIC`` automatically defines necessary wrappers that
129 accept variable number of arguments.
130
131 Projects using this library
132 ---------------------------
133
134 * `0 A.D. <http://play0ad.com/>`_: A free, open-source, cross-platform real-time strategy game
135
136 * `AMPL/MP <https://github.com/ampl/mp>`_:
137 An open-source library for mathematical programming
138
139 * `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle
140
141 * `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
142 Player vs Player Gaming Network with tweaks
143
144 * `KBEngine <http://kbengine.org/>`_: An open-source MMOG server engine
145
146 * `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
147
148 * `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
149
150 * `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
151
152 * `PenUltima Online (POL) <http://www.polserver.com/>`_:
153 An MMO server, compatible with most Ultima Online clients
154
155 * `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance, associative database
156
157 * `readpe <https://bitbucket.org/sys_dev/readpe>`_: Read Portable Executable
158
159 * `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster proxy
160
161 * `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_:
162 Small crossplatform 2D graphic engine
163
164 * `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
165 Business intelligence software
166
167 * `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store that can handle
168 1 million transactions per second on a single server
169
170 * `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ framework for
171 high-performance server applications on modern hardware
172
173 * `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
174
175 * `Stellar <https://www.stellar.org/>`_: Financial platform
176
177 * `Touch Surgery <https://www.touchsurgery.com/>`_: Surgery simulator
178
179 * `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source MMORPG framework
180
181 `More... <https://github.com/search?q=cppformat&type=Code>`_
182
183 If you are aware of other projects using this library, please let me know
184 by `email <mailto:victor.zverovich (a] gmail.com>`_ or by submitting an
185 `issue <https://github.com/fmtlib/fmt/issues>`_.
186
187 Motivation
188 ----------
189
190 So why yet another formatting library?
191
192 There are plenty of methods for doing this task, from standard ones like
193 the printf family of function and IOStreams to Boost Format library and
194 FastFormat. The reason for creating a new library is that every existing
195 solution that I found either had serious issues or didn't provide
196 all the features I needed.
197
198 Printf
199 ~~~~~~
200
201 The good thing about printf is that it is pretty fast and readily available
202 being a part of the C standard library. The main drawback is that it
203 doesn't support user-defined types. Printf also has safety issues although
204 they are mostly solved with `__attribute__ ((format (printf, ...))
205 <http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
206 There is a POSIX extension that adds positional arguments required for
207 `i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
208 to printf but it is not a part of C99 and may not be available on some
209 platforms.
210
211 IOStreams
212 ~~~~~~~~~
213
214 The main issue with IOStreams is best illustrated with an example:
215
216 .. code:: c++
217
218 std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
219
220 which is a lot of typing compared to printf:
221
222 .. code:: c++
223
224 printf("%.2f\n", 1.23456);
225
226 Matthew Wilson, the author of FastFormat, referred to this situation with
227 IOStreams as "chevron hell". IOStreams doesn't support positional arguments
228 by design.
229
230 The good part is that IOStreams supports user-defined types and is safe
231 although error reporting is awkward.
232
233 Boost Format library
234 ~~~~~~~~~~~~~~~~~~~~
235
236 This is a very powerful library which supports both printf-like format
237 strings and positional arguments. The main its drawback is performance.
238 According to various benchmarks it is much slower than other methods
239 considered here. Boost Format also has excessive build times and severe
240 code bloat issues (see `Benchmarks`_).
241
242 FastFormat
243 ~~~~~~~~~~
244
245 This is an interesting library which is fast, safe and has positional
246 arguments. However it has significant limitations, citing its author:
247
248 Three features that have no hope of being accommodated within the
249 current design are:
250
251 * Leading zeros (or any other non-space padding)
252 * Octal/hexadecimal encoding
253 * Runtime width/alignment specification
254
255 It is also quite big and has a heavy dependency, STLSoft, which might be
256 too restrictive for using it in some projects.
257
258 Loki SafeFormat
259 ~~~~~~~~~~~~~~~
260
261 SafeFormat is a formatting library which uses printf-like format strings
262 and is type safe. It doesn't support user-defined types or positional
263 arguments. It makes unconventional use of ``operator()`` for passing
264 format arguments.
265
266 Tinyformat
267 ~~~~~~~~~~
268
269 This library supports printf-like format strings and is very small and
270 fast. Unfortunately it doesn't support positional arguments and wrapping
271 it in C++98 is somewhat difficult. Also its performance and code compactness
272 are limited by IOStreams.
273
274 Boost Spirit.Karma
275 ~~~~~~~~~~~~~~~~~~
276
277 This is not really a formatting library but I decided to include it here
278 for completeness. As IOStreams it suffers from the problem of mixing
279 verbatim text with arguments. The library is pretty fast, but slower
280 on integer formatting than ``fmt::Writer`` on Karma's own benchmark,
281 see `Fast integer to string conversion in C++
282 <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
283
284 Benchmarks
285 ----------
286
287 Speed tests
288 ~~~~~~~~~~~
289
290 The following speed tests results were generated by building
291 ``tinyformat_test.cpp`` on Ubuntu GNU/Linux 14.04.1 with
292 ``g++-4.8.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three
293 runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or
294 equivalent is filled 2000000 times with output sent to ``/dev/null``; for
295 further details see the `source
296 <https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
297
298 ================= ============= ===========
299 Library Method Run Time, s
300 ================= ============= ===========
301 EGLIBC 2.19 printf 1.30
302 libstdc++ 4.8.2 std::ostream 1.85
303 fmt 1.0 fmt::print 1.42
304 tinyformat 2.0.1 tfm::printf 2.25
305 Boost Format 1.54 boost::format 9.94
306 ================= ============= ===========
307
308 As you can see ``boost::format`` is much slower than the alternative methods; this
309 is confirmed by `other tests <http://accu.org/index.php/journals/1539>`_.
310 Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat
311 cannot be faster than the IOStreams because it uses them internally.
312 Performance of fmt is close to that of printf, being `faster than printf on integer
313 formatting <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_,
314 but slower on floating-point formatting which dominates this benchmark.
315
316 Compile time and code bloat
317 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
318
319 The script `bloat-test.py
320 <https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
321 from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
322 tests compile time and code bloat for nontrivial projects.
323 It generates 100 translation units and uses ``printf()`` or its alternative
324 five times in each to simulate a medium sized project. The resulting
325 executable size and compile time (g++-4.8.1, Ubuntu GNU/Linux 13.10,
326 best of three) is shown in the following tables.
327
328 **Optimized build (-O3)**
329
330 ============ =============== ==================== ==================
331 Method Compile Time, s Executable size, KiB Stripped size, KiB
332 ============ =============== ==================== ==================
333 printf 2.6 41 30
334 IOStreams 19.4 92 70
335 fmt 46.8 46 34
336 tinyformat 64.6 418 386
337 Boost Format 222.8 990 923
338 ============ =============== ==================== ==================
339
340 As you can see, fmt has two times less overhead in terms of resulting
341 code size compared to IOStreams and comes pretty close to ``printf``.
342 Boost Format has by far the largest overheads.
343
344 **Non-optimized build**
345
346 ============ =============== ==================== ==================
347 Method Compile Time, s Executable size, KiB Stripped size, KiB
348 ============ =============== ==================== ==================
349 printf 2.1 41 30
350 IOStreams 19.7 86 62
351 fmt 47.9 108 86
352 tinyformat 27.7 234 190
353 Boost Format 122.6 884 763
354 ============ =============== ==================== ==================
355
356 ``libc``, ``libstdc++`` and ``libfmt`` are all linked as shared
357 libraries to compare formatting function overhead only. Boost Format
358 and tinyformat are header-only libraries so they don't provide any
359 linkage options.
360
361 Running the tests
362 ~~~~~~~~~~~~~~~~~
363
364 Please refer to `Building the library`__ for the instructions on how to build
365 the library and run the unit tests.
366
367 __ http://fmtlib.net/latest/usage.html#building-the-library
368
369 Benchmarks reside in a separate repository,
370 `format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
371 so to run the benchmarks you first need to clone this repository and
372 generate Makefiles with CMake::
373
374 $ git clone --recursive https://github.com/fmtlib/format-benchmark.git
375 $ cd format-benchmark
376 $ cmake .
377
378 Then you can run the speed test::
379
380 $ make speed-test
381
382 or the bloat test::
383
384 $ make bloat-test
385
386 License
387 -------
388
389 fmt is distributed under the BSD `license
390 <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
391
392 The `Format String Syntax
393 <http://fmtlib.net/latest/syntax.html>`_
394 section in the documentation is based on the one from Python `string module
395 documentation <https://docs.python.org/3/library/string.html#module-string>`_
396 adapted for the current library. For this reason the documentation is
397 distributed under the Python Software Foundation license available in
398 `doc/python-license.txt
399 <https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
400 It only applies if you distribute the documentation of fmt.
401
402 Acknowledgments
403 ---------------
404
405 The fmt library is maintained by Victor Zverovich (`vitaut <https://github.com/vitaut>`_)
406 and Jonathan Mller (`foonathan <https://github.com/foonathan>`_) with contributions from many
407 other people. See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and `Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. Let us know if your contribution
408 is not listed or mentioned incorrectly and we'll make it right.
409
410 The benchmark section of this readme file and the performance tests are taken
411 from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
412 written by Chris Foster. Boost Format library is acknowledged transitively
413 since it had some influence on tinyformat.
414 Some ideas used in the implementation are borrowed from `Loki
415 <http://loki-lib.sourceforge.net/>`_ SafeFormat and `Diagnostic API
416 <http://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`_ in
417 `Clang <http://clang.llvm.org/>`_.
418 Format string syntax and the documentation are based on Python's `str.format
419 <http://docs.python.org/2/library/stdtypes.html#str.format>`_.
420 Thanks `Doug Turnbull <https://github.com/softwaredoug>`_ for his valuable
421 comments and contribution to the design of the type-safe API and
422 `Gregory Czajkowski <https://github.com/gcflymoto>`_ for implementing binary
423 formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`_ for comprehensive
424 `comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`_
425 and useful comments regarding performance, `Boris Kaul <https://github.com/localvoid>`_ for
426 `C++ counting digits benchmark <https://github.com/localvoid/cxx-benchmark-count-digits>`_.
427 Thanks to `CarterLi <https://github.com/CarterLi>`_ for contributing various
428 improvements to the code.
429