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