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++. 15It can be used as a safe alternative to printf or as a fast 16alternative to IOStreams. 17 18`Documentation <http://fmtlib.net/latest/>`_ 19 20Features 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 61See the `documentation <http://fmtlib.net/latest/>`_ for more details. 62 63Examples 64-------- 65 66This 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 73Arguments 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 80fmt 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 89An 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 109You can use the `FMT_VARIADIC 110<http://fmtlib.net/latest/api.html#utilities>`_ 111macro 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>`_ 114which 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 127Note that you only need to define one function that takes ``fmt::ArgList`` 128argument. ``FMT_VARIADIC`` automatically defines necessary wrappers that 129accept variable number of arguments. 130 131Projects 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* `Drake <http://drake.mit.edu/>`_: A planning, control, and analysis toolbox for nonlinear dynamical systems (MIT) 142 143* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus (Lyft) 144 145* `FiveM <https://fivem.net/>`_: a modification framework for GTA V 146 147* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_: 148 Player vs Player Gaming Network with tweaks 149 150* `KBEngine <http://kbengine.org/>`_: An open-source MMOG server engine 151 152* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows 153 154* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software 155 156* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game 157 158* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets 159 160* `OpenSpace <http://openspaceproject.com/>`_: An open-source astrovisualization framework 161 162* `PenUltima Online (POL) <http://www.polserver.com/>`_: 163 An MMO server, compatible with most Ultima Online clients 164 165* `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance, associative database 166 167* `readpe <https://bitbucket.org/sys_dev/readpe>`_: Read Portable Executable 168 169* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster proxy 170 171* `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_: 172 Small crossplatform 2D graphic engine 173 174* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_: 175 Business intelligence software 176 177* `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store that can handle 178 1 million transactions per second on a single server 179 180* `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ framework for 181 high-performance server applications on modern hardware 182 183* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library 184 185* `Stellar <https://www.stellar.org/>`_: Financial platform 186 187* `Touch Surgery <https://www.touchsurgery.com/>`_: Surgery simulator 188 189* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source MMORPG framework 190 191`More... <https://github.com/search?q=cppformat&type=Code>`_ 192 193If you are aware of other projects using this library, please let me know 194by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an 195`issue <https://github.com/fmtlib/fmt/issues>`_. 196 197Motivation 198---------- 199 200So why yet another formatting library? 201 202There are plenty of methods for doing this task, from standard ones like 203the printf family of function and IOStreams to Boost Format library and 204FastFormat. The reason for creating a new library is that every existing 205solution that I found either had serious issues or didn't provide 206all the features I needed. 207 208Printf 209~~~~~~ 210 211The good thing about printf is that it is pretty fast and readily available 212being a part of the C standard library. The main drawback is that it 213doesn't support user-defined types. Printf also has safety issues although 214they are mostly solved with `__attribute__ ((format (printf, ...)) 215<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC. 216There is a POSIX extension that adds positional arguments required for 217`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_ 218to printf but it is not a part of C99 and may not be available on some 219platforms. 220 221IOStreams 222~~~~~~~~~ 223 224The main issue with IOStreams is best illustrated with an example: 225 226.. code:: c++ 227 228 std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; 229 230which is a lot of typing compared to printf: 231 232.. code:: c++ 233 234 printf("%.2f\n", 1.23456); 235 236Matthew Wilson, the author of FastFormat, referred to this situation with 237IOStreams as "chevron hell". IOStreams doesn't support positional arguments 238by design. 239 240The good part is that IOStreams supports user-defined types and is safe 241although error reporting is awkward. 242 243Boost Format library 244~~~~~~~~~~~~~~~~~~~~ 245 246This is a very powerful library which supports both printf-like format 247strings and positional arguments. The main its drawback is performance. 248According to various benchmarks it is much slower than other methods 249considered here. Boost Format also has excessive build times and severe 250code bloat issues (see `Benchmarks`_). 251 252FastFormat 253~~~~~~~~~~ 254 255This is an interesting library which is fast, safe and has positional 256arguments. However it has significant limitations, citing its author: 257 258 Three features that have no hope of being accommodated within the 259 current design are: 260 261 * Leading zeros (or any other non-space padding) 262 * Octal/hexadecimal encoding 263 * Runtime width/alignment specification 264 265It is also quite big and has a heavy dependency, STLSoft, which might be 266too restrictive for using it in some projects. 267 268Loki SafeFormat 269~~~~~~~~~~~~~~~ 270 271SafeFormat is a formatting library which uses printf-like format strings 272and is type safe. It doesn't support user-defined types or positional 273arguments. It makes unconventional use of ``operator()`` for passing 274format arguments. 275 276Tinyformat 277~~~~~~~~~~ 278 279This library supports printf-like format strings and is very small and 280fast. Unfortunately it doesn't support positional arguments and wrapping 281it in C++98 is somewhat difficult. Also its performance and code compactness 282are limited by IOStreams. 283 284Boost Spirit.Karma 285~~~~~~~~~~~~~~~~~~ 286 287This is not really a formatting library but I decided to include it here 288for completeness. As IOStreams it suffers from the problem of mixing 289verbatim text with arguments. The library is pretty fast, but slower 290on integer formatting than ``fmt::Writer`` on Karma's own benchmark, 291see `Fast integer to string conversion in C++ 292<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_. 293 294Benchmarks 295---------- 296 297Speed tests 298~~~~~~~~~~~ 299 300The following speed tests results were generated by building 301``tinyformat_test.cpp`` on Ubuntu GNU/Linux 14.04.1 with 302``g++-4.8.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three 303runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or 304equivalent is filled 2000000 times with output sent to ``/dev/null``; for 305further details see the `source 306<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_. 307 308================= ============= =========== 309Library Method Run Time, s 310================= ============= =========== 311EGLIBC 2.19 printf 1.30 312libstdc++ 4.8.2 std::ostream 1.85 313fmt 1.0 fmt::print 1.42 314tinyformat 2.0.1 tfm::printf 2.25 315Boost Format 1.54 boost::format 9.94 316================= ============= =========== 317 318As you can see ``boost::format`` is much slower than the alternative methods; this 319is confirmed by `other tests <http://accu.org/index.php/journals/1539>`_. 320Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat 321cannot be faster than the IOStreams because it uses them internally. 322Performance of fmt is close to that of printf, being `faster than printf on integer 323formatting <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_, 324but slower on floating-point formatting which dominates this benchmark. 325 326Compile time and code bloat 327~~~~~~~~~~~~~~~~~~~~~~~~~~~ 328 329The script `bloat-test.py 330<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_ 331from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_ 332tests compile time and code bloat for nontrivial projects. 333It generates 100 translation units and uses ``printf()`` or its alternative 334five times in each to simulate a medium sized project. The resulting 335executable size and compile time (g++-4.8.1, Ubuntu GNU/Linux 13.10, 336best of three) is shown in the following tables. 337 338**Optimized build (-O3)** 339 340============ =============== ==================== ================== 341Method Compile Time, s Executable size, KiB Stripped size, KiB 342============ =============== ==================== ================== 343printf 2.6 41 30 344IOStreams 19.4 92 70 345fmt 46.8 46 34 346tinyformat 64.6 418 386 347Boost Format 222.8 990 923 348============ =============== ==================== ================== 349 350As you can see, fmt has two times less overhead in terms of resulting 351code size compared to IOStreams and comes pretty close to ``printf``. 352Boost Format has by far the largest overheads. 353 354**Non-optimized build** 355 356============ =============== ==================== ================== 357Method Compile Time, s Executable size, KiB Stripped size, KiB 358============ =============== ==================== ================== 359printf 2.1 41 30 360IOStreams 19.7 86 62 361fmt 47.9 108 86 362tinyformat 27.7 234 190 363Boost Format 122.6 884 763 364============ =============== ==================== ================== 365 366``libc``, ``libstdc++`` and ``libfmt`` are all linked as shared 367libraries to compare formatting function overhead only. Boost Format 368and tinyformat are header-only libraries so they don't provide any 369linkage options. 370 371Running the tests 372~~~~~~~~~~~~~~~~~ 373 374Please refer to `Building the library`__ for the instructions on how to build 375the library and run the unit tests. 376 377__ http://fmtlib.net/latest/usage.html#building-the-library 378 379Benchmarks reside in a separate repository, 380`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_, 381so to run the benchmarks you first need to clone this repository and 382generate Makefiles with CMake:: 383 384 $ git clone --recursive https://github.com/fmtlib/format-benchmark.git 385 $ cd format-benchmark 386 $ cmake . 387 388Then you can run the speed test:: 389 390 $ make speed-test 391 392or the bloat test:: 393 394 $ make bloat-test 395 396License 397------- 398 399fmt is distributed under the BSD `license 400<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_. 401 402The `Format String Syntax 403<http://fmtlib.net/latest/syntax.html>`_ 404section in the documentation is based on the one from Python `string module 405documentation <https://docs.python.org/3/library/string.html#module-string>`_ 406adapted for the current library. For this reason the documentation is 407distributed under the Python Software Foundation license available in 408`doc/python-license.txt 409<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_. 410It only applies if you distribute the documentation of fmt. 411 412Acknowledgments 413--------------- 414 415The fmt library is maintained by Victor Zverovich (`vitaut <https://github.com/vitaut>`_) 416and Jonathan Müller (`foonathan <https://github.com/foonathan>`_) with contributions from many 417other 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 418is not listed or mentioned incorrectly and we'll make it right. 419 420The benchmark section of this readme file and the performance tests are taken 421from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library 422written by Chris Foster. Boost Format library is acknowledged transitively 423since it had some influence on tinyformat. 424Some ideas used in the implementation are borrowed from `Loki 425<http://loki-lib.sourceforge.net/>`_ SafeFormat and `Diagnostic API 426<http://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`_ in 427`Clang <http://clang.llvm.org/>`_. 428Format string syntax and the documentation are based on Python's `str.format 429<http://docs.python.org/2/library/stdtypes.html#str.format>`_. 430Thanks `Doug Turnbull <https://github.com/softwaredoug>`_ for his valuable 431comments and contribution to the design of the type-safe API and 432`Gregory Czajkowski <https://github.com/gcflymoto>`_ for implementing binary 433formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`_ for comprehensive 434`comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`_ 435and useful comments regarding performance, `Boris Kaul <https://github.com/localvoid>`_ for 436`C++ counting digits benchmark <https://github.com/localvoid/cxx-benchmark-count-digits>`_. 437Thanks to `CarterLi <https://github.com/CarterLi>`_ for contributing various 438improvements to the code. 439