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://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
11 :alt: fmt is continuously fuzzed at oss-fuzz
12 :target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
13 colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
14 Summary&q=proj%3Dfmt&can=1
15
16.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
17 :alt: Ask questions at StackOverflow with the tag fmt
18 :target: https://stackoverflow.com/questions/tagged/fmt
19
20**{fmt}** is an open-source formatting library providing a fast and safe
21alternative to C stdio and C++ iostreams.
22
23If you like this project, please consider donating to BYSOL,
24an initiative to help victims of political repressions in Belarus:
25https://www.facebook.com/donate/759400044849707/108388587646909/.
26
27`Documentation <https://fmt.dev>`__
28
29Q&A: ask questions on `StackOverflow with the tag fmt
30<https://stackoverflow.com/questions/tagged/fmt>`_.
31
32Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
33
34Features
35--------
36
37* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
38 for localization
39* Implementation of `C++20 std::format
40 <https://en.cppreference.com/w/cpp/utility/format>`__
41* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
42 `format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
43* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
44 round-trip guarantees
45* Safe `printf implementation
46 <https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
47 extension for positional arguments
48* Extensibility: `support for user-defined types
49 <https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
50* High performance: faster than common standard library implementations of
51 ``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
52 and `Converting a hundred million integers to strings per second
53 <http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
54* Small code size both in terms of source code with the minimum configuration
55 consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
56 and compiled code; see `Compile time and code bloat`_
57* Reliability: the library has an extensive set of `tests
58 <https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
59 <https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
60 Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_
61* Safety: the library is fully type safe, errors in format strings can be
62 reported at compile time, automatic memory management prevents buffer overflow
63 errors
64* Ease of use: small self-contained code base, no external dependencies,
65 permissive MIT `license
66 <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
67* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
68 consistent output across platforms and support for older compilers
69* Clean warning-free codebase even on high warning levels such as
70 ``-Wall -Wextra -pedantic``
71* Locale-independence by default
72* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
73
74See the `documentation <https://fmt.dev>`_ for more details.
75
76Examples
77--------
78
79**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
80
81.. code:: c++
82
83 #include <fmt/core.h>
84
85 int main() {
86 fmt::print("Hello, world!\n");
87 }
88
89**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
90
91.. code:: c++
92
93 std::string s = fmt::format("The answer is {}.", 42);
94 // s == "The answer is 42."
95
96**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
97
98.. code:: c++
99
100 std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
101 // s == "I'd rather be happy than right."
102
103**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
104
105.. code:: c++
106
107 #include <fmt/chrono.h>
108
109 int main() {
110 using namespace std::literals::chrono_literals;
111 fmt::print("Default format: {} {}\n", 42s, 100ms);
112 fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
113 }
114
115Output::
116
117 Default format: 42s 100ms
118 strftime-like format: 03:15:30
119
120**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
121
122.. code:: c++
123
124 #include <vector>
125 #include <fmt/ranges.h>
126
127 int main() {
128 std::vector<int> v = {1, 2, 3};
129 fmt::print("{}\n", v);
130 }
131
132Output::
133
134 {1, 2, 3}
135
136**Check a format string at compile time**
137
138.. code:: c++
139
140 std::string s = fmt::format(FMT_STRING("{:d}"), "don't panic");
141
142This gives a compile-time error because ``d`` is an invalid format specifier for
143a string.
144
145**Write a file from a single thread**
146
147.. code:: c++
148
149 #include <fmt/os.h>
150
151 int main() {
152 auto out = fmt::output_file("guide.txt");
153 out.print("Don't {}", "Panic");
154 }
155
156This can be `5 to 9 times faster than fprintf
157<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
158
159**Print with colors and text styles**
160
161.. code:: c++
162
163 #include <fmt/color.h>
164
165 int main() {
166 fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
167 "Hello, {}!\n", "world");
168 fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
169 fmt::emphasis::underline, "Hello, {}!\n", "мир");
170 fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
171 "Hello, {}!\n", "世界");
172 }
173
174Output on a modern terminal:
175
176.. image:: https://user-images.githubusercontent.com/
177 576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
178
179Benchmarks
180----------
181
182Speed tests
183~~~~~~~~~~~
184
185================= ============= ===========
186Library Method Run Time, s
187================= ============= ===========
188libc printf 1.04
189libc++ std::ostream 3.05
190{fmt} 6.1.1 fmt::print 0.75
191Boost Format 1.67 boost::format 7.24
192Folly Format folly::format 2.23
193================= ============= ===========
194
195{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
196
197The above results were generated by building ``tinyformat_test.cpp`` on macOS
19810.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
199best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
200or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
201further details refer to the `source
202<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
203
204{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
205floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
206and faster than `double-conversion <https://github.com/google/double-conversion>`_ and
207`ryu <https://github.com/ulfjack/ryu>`_:
208
209.. image:: https://user-images.githubusercontent.com/576385/
210 95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png
211 :target: https://fmt.dev/unknown_mac64_clang12.0.html
212
213Compile time and code bloat
214~~~~~~~~~~~~~~~~~~~~~~~~~~~
215
216The script `bloat-test.py
217<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
218from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
219tests compile time and code bloat for nontrivial projects.
220It generates 100 translation units and uses ``printf()`` or its alternative
221five times in each to simulate a medium sized project. The resulting
222executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
223macOS Sierra, best of three) is shown in the following tables.
224
225**Optimized build (-O3)**
226
227============= =============== ==================== ==================
228Method Compile Time, s Executable size, KiB Stripped size, KiB
229============= =============== ==================== ==================
230printf 2.6 29 26
231printf+string 16.4 29 26
232iostreams 31.1 59 55
233{fmt} 19.0 37 34
234Boost Format 91.9 226 203
235Folly Format 115.7 101 88
236============= =============== ==================== ==================
237
238As you can see, {fmt} has 60% less overhead in terms of resulting binary code
239size compared to iostreams and comes pretty close to ``printf``. Boost Format
240and Folly Format have the largest overheads.
241
242``printf+string`` is the same as ``printf`` but with extra ``<string>``
243include to measure the overhead of the latter.
244
245**Non-optimized build**
246
247============= =============== ==================== ==================
248Method Compile Time, s Executable size, KiB Stripped size, KiB
249============= =============== ==================== ==================
250printf 2.2 33 30
251printf+string 16.0 33 30
252iostreams 28.3 56 52
253{fmt} 18.2 59 50
254Boost Format 54.1 365 303
255Folly Format 79.9 445 430
256============= =============== ==================== ==================
257
258``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
259compare formatting function overhead only. Boost Format is a
260header-only library so it doesn't provide any linkage options.
261
262Running the tests
263~~~~~~~~~~~~~~~~~
264
265Please refer to `Building the library`__ for the instructions on how to build
266the library and run the unit tests.
267
268__ https://fmt.dev/latest/usage.html#building-the-library
269
270Benchmarks reside in a separate repository,
271`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
272so to run the benchmarks you first need to clone this repository and
273generate Makefiles with CMake::
274
275 $ git clone --recursive https://github.com/fmtlib/format-benchmark.git
276 $ cd format-benchmark
277 $ cmake .
278
279Then you can run the speed test::
280
281 $ make speed-test
282
283or the bloat test::
284
285 $ make bloat-test
286
287Projects using this library
288---------------------------
289
290* `0 A.D. <https://play0ad.com/>`_: a free, open-source, cross-platform
291 real-time strategy game
292
293* `AMPL/MP <https://github.com/ampl/mp>`_:
294 an open-source library for mathematical programming
295
296* `Aseprite <https://github.com/aseprite/aseprite>`_:
297 animated sprite editor & pixel art tool
298
299* `AvioBook <https://www.aviobook.aero/en>`_: a comprehensive aircraft
300 operations suite
301
302* `Blizzard Battle.net <https://battle.net/>`_: an online gaming platform
303
304* `Celestia <https://celestia.space/>`_: real-time 3D visualization of space
305
306* `Ceph <https://ceph.com/>`_: a scalable distributed storage system
307
308* `ccache <https://ccache.dev/>`_: a compiler cache
309
310* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database
311 management system
312
313* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater
314 vehicle
315
316* `Drake <https://drake.mit.edu/>`_: a planning, control, and analysis toolbox
317 for nonlinear dynamical systems (MIT)
318
319* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
320 (Lyft)
321
322* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
323
324* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
325
326* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
327 Player vs Player Gaming Network with tweaks
328
329* `KBEngine <https://github.com/kbengine/kbengine>`_: an open-source MMOG server
330 engine
331
332* `Keypirinha <https://keypirinha.com/>`_: a semantic launcher for Windows
333
334* `Kodi <https://kodi.tv/>`_ (formerly xbmc): home theater software
335
336* `Knuth <https://kth.cash/>`_: high-performance Bitcoin full-node
337
338* `Microsoft Verona <https://github.com/microsoft/verona>`_:
339 research programming language for concurrent ownership
340
341* `MongoDB <https://mongodb.com/>`_: distributed document database
342
343* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: a small tool to
344 generate randomized datasets
345
346* `OpenSpace <https://openspaceproject.com/>`_: an open-source
347 astrovisualization framework
348
349* `PenUltima Online (POL) <https://www.polserver.com/>`_:
350 an MMO server, compatible with most Ultima Online clients
351
352* `PyTorch <https://github.com/pytorch/pytorch>`_: an open-source machine
353 learning library
354
355* `quasardb <https://www.quasardb.net/>`_: a distributed, high-performance,
356 associative database
357
358* `Quill <https://github.com/odygrd/quill>`_: asynchronous low-latency logging library
359
360* `QKW <https://github.com/ravijanjam/qkw>`_: generalizing aliasing to simplify
361 navigation, and executing complex multi-line terminal command sequences
362
363* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: a Redis cluster
364 proxy
365
366* `redpanda <https://vectorized.io/redpanda>`_: a 10x faster Kafka® replacement
367 for mission critical systems written in C++
368
369* `rpclib <http://rpclib.net/>`_: a modern C++ msgpack-RPC server and client
370 library
371
372* `Salesforce Analytics Cloud
373 <https://www.salesforce.com/analytics-cloud/overview/>`_:
374 business intelligence software
375
376* `Scylla <https://www.scylladb.com/>`_: a Cassandra-compatible NoSQL data store
377 that can handle 1 million transactions per second on a single server
378
379* `Seastar <http://www.seastar-project.org/>`_: an advanced, open-source C++
380 framework for high-performance server applications on modern hardware
381
382* `spdlog <https://github.com/gabime/spdlog>`_: super fast C++ logging library
383
384* `Stellar <https://www.stellar.org/>`_: financial platform
385
386* `Touch Surgery <https://www.touchsurgery.com/>`_: surgery simulator
387
388* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: open-source
389 MMORPG framework
390
391* `Windows Terminal <https://github.com/microsoft/terminal>`_: the new Windows
392 terminal
393
394`More... <https://github.com/search?q=fmtlib&type=Code>`_
395
396If you are aware of other projects using this library, please let me know
397by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
398`issue <https://github.com/fmtlib/fmt/issues>`_.
399
400Motivation
401----------
402
403So why yet another formatting library?
404
405There are plenty of methods for doing this task, from standard ones like
406the printf family of function and iostreams to Boost Format and FastFormat
407libraries. The reason for creating a new library is that every existing
408solution that I found either had serious issues or didn't provide
409all the features I needed.
410
411printf
412~~~~~~
413
414The good thing about ``printf`` is that it is pretty fast and readily available
415being a part of the C standard library. The main drawback is that it
416doesn't support user-defined types. ``printf`` also has safety issues although
417they are somewhat mitigated with `__attribute__ ((format (printf, ...))
418<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
419There is a POSIX extension that adds positional arguments required for
420`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
421to ``printf`` but it is not a part of C99 and may not be available on some
422platforms.
423
424iostreams
425~~~~~~~~~
426
427The main issue with iostreams is best illustrated with an example:
428
429.. code:: c++
430
431 std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
432
433which is a lot of typing compared to printf:
434
435.. code:: c++
436
437 printf("%.2f\n", 1.23456);
438
439Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams
440don't support positional arguments by design.
441
442The good part is that iostreams support user-defined types and are safe although
443error handling is awkward.
444
445Boost Format
446~~~~~~~~~~~~
447
448This is a very powerful library which supports both ``printf``-like format
449strings and positional arguments. Its main drawback is performance. According to
450various, benchmarks it is much slower than other methods considered here. Boost
451Format also has excessive build times and severe code bloat issues (see
452`Benchmarks`_).
453
454FastFormat
455~~~~~~~~~~
456
457This is an interesting library which is fast, safe and has positional arguments.
458However, it has significant limitations, citing its author:
459
460 Three features that have no hope of being accommodated within the
461 current design are:
462
463 * Leading zeros (or any other non-space padding)
464 * Octal/hexadecimal encoding
465 * Runtime width/alignment specification
466
467It is also quite big and has a heavy dependency, STLSoft, which might be too
468restrictive for using it in some projects.
469
470Boost Spirit.Karma
471~~~~~~~~~~~~~~~~~~
472
473This is not really a formatting library but I decided to include it here for
474completeness. As iostreams, it suffers from the problem of mixing verbatim text
475with arguments. The library is pretty fast, but slower on integer formatting
476than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
477see `Converting a hundred million integers to strings per second
478<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
479
480License
481-------
482
483{fmt} is distributed under the MIT `license
484<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
485
486Documentation License
487---------------------
488
489The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
490section in the documentation is based on the one from Python `string module
491documentation <https://docs.python.org/3/library/string.html#module-string>`_.
492For this reason the documentation is distributed under the Python Software
493Foundation license available in `doc/python-license.txt
494<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
495It only applies if you distribute the documentation of {fmt}.
496
497Maintainers
498-----------
499
500The {fmt} library is maintained by Victor Zverovich (`vitaut
501<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
502<https://github.com/foonathan>`_) with contributions from many other people.
503See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
504`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
505Let us know if your contribution is not listed or mentioned incorrectly and
506we'll make it right.
507