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