Victor Zverovich | f1cd541 | 2016-04-24 10:46:21 -0700 | [diff] [blame] | 1 | {fmt} |
| 2 | ===== |
vitaut | ec27d5d | 2012-12-07 08:26:46 -0800 | [diff] [blame] | 3 | |
Victor Zverovich | 5a6a585 | 2016-04-27 08:05:40 -0700 | [diff] [blame] | 4 | .. image:: https://travis-ci.org/fmtlib/fmt.png?branch=master |
| 5 | :target: https://travis-ci.org/fmtlib/fmt |
Victor Zverovich | 817d98a | 2014-04-14 23:19:38 -0700 | [diff] [blame] | 6 | |
Victor Zverovich | f4b5aea | 2016-04-27 08:13:56 -0700 | [diff] [blame] | 7 | .. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v |
| 8 | :target: https://ci.appveyor.com/project/vitaut/fmt |
Victor Zverovich | d22d11b | 2019-05-10 09:54:42 -0700 | [diff] [blame] | 9 | |
Paul Dreik | 840a817 | 2019-09-19 06:47:11 +0200 | [diff] [blame] | 10 | .. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfmt.svg |
| 11 | :alt: fmt is continuously fuzzed att oss-fuzz |
Paul Dreik | 63a9f3f | 2019-11-23 08:33:51 +0100 | [diff] [blame] | 12 | :target: https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dlibfmt&can=1 |
Paul Dreik | 840a817 | 2019-09-19 06:47:11 +0200 | [diff] [blame] | 13 | |
Victor Zverovich | 4afb39b | 2019-11-26 08:33:16 -0800 | [diff] [blame] | 14 | .. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg |
| 15 | :alt: Ask questions at StackOverflow with the tag fmt |
| 16 | :target: http://stackoverflow.com/questions/tagged/fmt |
| 17 | |
Victor Zverovich | 8222221 | 2018-02-10 07:45:32 -0800 | [diff] [blame] | 18 | **{fmt}** is an open-source formatting library for C++. |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 19 | It can be used as a safe and fast alternative to (s)printf and iostreams. |
Victor Zverovich | 70a2317 | 2012-12-07 14:18:37 -0800 | [diff] [blame] | 20 | |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 21 | `Documentation <https://fmt.dev/latest/>`__ |
vitaut | eb50269 | 2015-05-22 06:50:46 -0700 | [diff] [blame] | 22 | |
Victor Zverovich | ccc318e | 2019-05-10 10:04:44 -0700 | [diff] [blame] | 23 | Q&A: ask questions on `StackOverflow with the tag fmt <http://stackoverflow.com/questions/tagged/fmt>`_. |
Victor Zverovich | 4c8efd6 | 2019-05-10 09:56:40 -0700 | [diff] [blame] | 24 | |
Victor Zverovich | 70a2317 | 2012-12-07 14:18:37 -0800 | [diff] [blame] | 25 | Features |
| 26 | -------- |
| 27 | |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 28 | * Replacement-based `format API <https://fmt.dev/dev/api.html>`_ with |
Victor Zverovich | 84e520b | 2018-03-21 06:16:13 -0700 | [diff] [blame] | 29 | positional arguments for localization. |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 30 | * `Format string syntax <https://fmt.dev/dev/syntax.html>`_ similar to the one |
Paul Dreik | d2c9276 | 2019-09-29 08:55:09 +0200 | [diff] [blame] | 31 | of `str.format <https://docs.python.org/3/library/stdtypes.html#str.format>`_ |
Victor Zverovich | 84e520b | 2018-03-21 06:16:13 -0700 | [diff] [blame] | 32 | in Python. |
Victor Zverovich | 86a7d85 | 2015-02-26 09:05:20 -0800 | [diff] [blame] | 33 | * Safe `printf implementation |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 34 | <https://fmt.dev/latest/api.html#printf-formatting>`_ including |
Victor Zverovich | e613b3c | 2017-11-10 07:24:16 -0800 | [diff] [blame] | 35 | the POSIX extension for positional arguments. |
Victor Zverovich | 4fb73d1 | 2019-07-21 15:28:48 +0200 | [diff] [blame] | 36 | * Implementation of `C++20 std::format <https://fmt.dev/Text%20Formatting.html>`__. |
Victor Zverovich | 58e53b4 | 2012-12-07 14:32:48 -0800 | [diff] [blame] | 37 | * Support for user-defined types. |
Victor Zverovich | f230170 | 2019-03-10 12:13:14 -0700 | [diff] [blame] | 38 | * High performance: faster than common standard library implementations of |
| 39 | `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_ and |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 40 | iostreams. See `Speed tests`_ and `Fast integer to string conversion in C++ |
Victor Zverovich | d1369d4 | 2014-02-13 09:53:01 -0800 | [diff] [blame] | 41 | <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_. |
Victor Zverovich | 0ea70de | 2018-03-21 09:25:28 -0700 | [diff] [blame] | 42 | * Small code size both in terms of source code (the minimum configuration |
| 43 | consists of just three header files, ``core.h``, ``format.h`` and |
| 44 | ``format-inl.h``) and compiled code. See `Compile time and code bloat`_. |
Victor Zverovich | 7c697bf | 2012-12-11 16:30:27 -0800 | [diff] [blame] | 45 | * Reliability: the library has an extensive set of `unit tests |
Victor Zverovich | 4b8f8fa | 2019-09-25 07:14:45 -0700 | [diff] [blame] | 46 | <https://github.com/fmtlib/fmt/tree/master/test>`_ and is continuously fuzzed. |
Victor Zverovich | e613b3c | 2017-11-10 07:24:16 -0800 | [diff] [blame] | 47 | * Safety: the library is fully type safe, errors in format strings can be |
| 48 | reported at compile time, automatic memory management prevents buffer overflow |
| 49 | errors. |
Victor Zverovich | 7c697bf | 2012-12-11 16:30:27 -0800 | [diff] [blame] | 50 | * Ease of use: small self-contained code base, no external dependencies, |
Victor Zverovich | 972ffd3 | 2019-09-06 13:13:30 -0700 | [diff] [blame] | 51 | permissive MIT `license |
Victor Zverovich | e817bb9 | 2016-04-27 08:23:03 -0700 | [diff] [blame] | 52 | <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_ |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 53 | * `Portability <https://fmt.dev/latest/index.html#portability>`_ with |
Victor Zverovich | e613b3c | 2017-11-10 07:24:16 -0800 | [diff] [blame] | 54 | consistent output across platforms and support for older compilers. |
Victor Zverovich | 2d48158 | 2013-09-03 09:06:49 -0700 | [diff] [blame] | 55 | * Clean warning-free codebase even on high warning levels |
Victor Zverovich | e613b3c | 2017-11-10 07:24:16 -0800 | [diff] [blame] | 56 | (``-Wall -Wextra -pedantic``). |
Victor Zverovich | bc6c1c1 | 2013-09-04 22:03:37 -0700 | [diff] [blame] | 57 | * Support for wide strings. |
Victor Zverovich | bc33d17 | 2015-02-19 08:40:40 -0800 | [diff] [blame] | 58 | * Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro. |
Victor Zverovich | 70a2317 | 2012-12-07 14:18:37 -0800 | [diff] [blame] | 59 | |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 60 | See the `documentation <https://fmt.dev/latest/>`_ for more details. |
Victor Zverovich | c7354b6 | 2013-01-21 10:11:59 -0800 | [diff] [blame] | 61 | |
Victor Zverovich | 58e53b4 | 2012-12-07 14:32:48 -0800 | [diff] [blame] | 62 | Examples |
| 63 | -------- |
Victor Zverovich | 70a2317 | 2012-12-07 14:18:37 -0800 | [diff] [blame] | 64 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 65 | Print ``Hello, world!`` to ``stdout``: |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 66 | |
| 67 | .. code:: c++ |
Victor Zverovich | 58e53b4 | 2012-12-07 14:32:48 -0800 | [diff] [blame] | 68 | |
Victor Zverovich | 9b392a6 | 2019-03-16 07:59:58 -0700 | [diff] [blame] | 69 | fmt::print("Hello, {}!", "world"); // Python-like format string syntax |
| 70 | fmt::printf("Hello, %s!", "world"); // printf format string syntax |
Victor Zverovich | c50f94a | 2012-12-07 13:20:50 -0800 | [diff] [blame] | 71 | |
Victor Zverovich | 0fa65cf | 2019-03-16 07:36:27 -0700 | [diff] [blame] | 72 | Format a string and use positional arguments: |
| 73 | |
| 74 | .. code:: c++ |
| 75 | |
| 76 | std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy"); |
Victor Zverovich | 9b392a6 | 2019-03-16 07:59:58 -0700 | [diff] [blame] | 77 | // s == "I'd rather be happy than right." |
Victor Zverovich | 0fa65cf | 2019-03-16 07:36:27 -0700 | [diff] [blame] | 78 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 79 | Check a format string at compile time: |
Victor Zverovich | dba1ccc | 2017-11-10 07:38:51 -0800 | [diff] [blame] | 80 | |
| 81 | .. code:: c++ |
| 82 | |
| 83 | // test.cc |
Victor Zverovich | 8fd7e30 | 2018-03-09 15:44:46 -0800 | [diff] [blame] | 84 | #include <fmt/format.h> |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 85 | std::string s = format(FMT_STRING("{2}"), 42); |
Victor Zverovich | dba1ccc | 2017-11-10 07:38:51 -0800 | [diff] [blame] | 86 | |
| 87 | .. code:: |
| 88 | |
Victor Zverovich | 434eb91 | 2018-07-04 18:07:17 -0700 | [diff] [blame] | 89 | $ c++ -Iinclude -std=c++14 test.cc |
Victor Zverovich | dba1ccc | 2017-11-10 07:38:51 -0800 | [diff] [blame] | 90 | ... |
Victor Zverovich | fbca830 | 2018-09-12 12:44:04 -0700 | [diff] [blame] | 91 | test.cc:4:17: note: in instantiation of function template specialization 'fmt::v5::format<S, int>' requested here |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 92 | std::string s = format(FMT_STRING("{2}"), 42); |
Victor Zverovich | 434eb91 | 2018-07-04 18:07:17 -0700 | [diff] [blame] | 93 | ^ |
| 94 | include/fmt/core.h:778:19: note: non-constexpr function 'on_error' cannot be used in a constant expression |
Victor Zverovich | 8fd7e30 | 2018-03-09 15:44:46 -0800 | [diff] [blame] | 95 | ErrorHandler::on_error(message); |
| 96 | ^ |
Victor Zverovich | 434eb91 | 2018-07-04 18:07:17 -0700 | [diff] [blame] | 97 | include/fmt/format.h:2226:16: note: in call to '&checker.context_->on_error(&"argument index out of range"[0])' |
Victor Zverovich | 8fd7e30 | 2018-03-09 15:44:46 -0800 | [diff] [blame] | 98 | context_.on_error("argument index out of range"); |
| 99 | ^ |
Victor Zverovich | dba1ccc | 2017-11-10 07:38:51 -0800 | [diff] [blame] | 100 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 101 | Use {fmt} as a safe portable replacement for ``itoa`` |
Victor Zverovich | df1ba52 | 2018-04-22 17:04:28 -0700 | [diff] [blame] | 102 | (`godbolt <https://godbolt.org/g/NXmpU4>`_): |
Victor Zverovich | 1a236c8 | 2013-09-06 15:12:46 -0700 | [diff] [blame] | 103 | |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 104 | .. code:: c++ |
Victor Zverovich | 1a236c8 | 2013-09-06 15:12:46 -0700 | [diff] [blame] | 105 | |
Victor Zverovich | df1ba52 | 2018-04-22 17:04:28 -0700 | [diff] [blame] | 106 | fmt::memory_buffer buf; |
| 107 | format_to(buf, "{}", 42); // replaces itoa(42, buffer, 10) |
| 108 | format_to(buf, "{:x}", 42); // replaces itoa(42, buffer, 16) |
Victor Zverovich | 9b392a6 | 2019-03-16 07:59:58 -0700 | [diff] [blame] | 109 | // access the string with to_string(buf) or buf.data() |
Victor Zverovich | 1a236c8 | 2013-09-06 15:12:46 -0700 | [diff] [blame] | 110 | |
Victor Zverovich | ec645ca | 2019-03-16 10:47:50 -0700 | [diff] [blame] | 111 | Format objects of user-defined types via a simple `extension API |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 112 | <https://fmt.dev/latest/api.html#formatting-user-defined-types>`_: |
Victor Zverovich | a8a536b | 2012-12-13 08:12:09 -0800 | [diff] [blame] | 113 | |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 114 | .. code:: c++ |
Victor Zverovich | 8e23730 | 2012-12-09 19:19:47 -0800 | [diff] [blame] | 115 | |
Victor Zverovich | a7e356c | 2018-09-14 07:52:30 -0700 | [diff] [blame] | 116 | #include "fmt/format.h" |
Victor Zverovich | c110c6e | 2016-07-16 08:44:27 -0700 | [diff] [blame] | 117 | |
Victor Zverovich | a7e356c | 2018-09-14 07:52:30 -0700 | [diff] [blame] | 118 | struct date { |
| 119 | int year, month, day; |
| 120 | }; |
Victor Zverovich | 8e23730 | 2012-12-09 19:19:47 -0800 | [diff] [blame] | 121 | |
Victor Zverovich | a7e356c | 2018-09-14 07:52:30 -0700 | [diff] [blame] | 122 | template <> |
| 123 | struct fmt::formatter<date> { |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 124 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } |
Victor Zverovich | a7e356c | 2018-09-14 07:52:30 -0700 | [diff] [blame] | 125 | |
| 126 | template <typename FormatContext> |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 127 | auto format(const date& d, FormatContext& ctx) { |
Victor Zverovich | 0c7f5c3 | 2018-12-02 08:22:51 -0800 | [diff] [blame] | 128 | return format_to(ctx.out(), "{}-{}-{}", d.year, d.month, d.day); |
Victor Zverovich | 8e23730 | 2012-12-09 19:19:47 -0800 | [diff] [blame] | 129 | } |
| 130 | }; |
| 131 | |
Victor Zverovich | a7e356c | 2018-09-14 07:52:30 -0700 | [diff] [blame] | 132 | std::string s = fmt::format("The date is {}", date{2012, 12, 9}); |
Victor Zverovich | 8e23730 | 2012-12-09 19:19:47 -0800 | [diff] [blame] | 133 | // s == "The date is 2012-12-9" |
| 134 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 135 | Create your own functions similar to `format |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 136 | <https://fmt.dev/latest/api.html#format>`_ and |
| 137 | `print <https://fmt.dev/latest/api.html#print>`_ |
Victor Zverovich | d180c25 | 2018-04-15 06:19:38 -0700 | [diff] [blame] | 138 | which take arbitrary arguments (`godbolt <https://godbolt.org/g/MHjHVf>`_): |
Victor Zverovich | a8a536b | 2012-12-13 08:12:09 -0800 | [diff] [blame] | 139 | |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 140 | .. code:: c++ |
Victor Zverovich | 87b5ebf | 2012-12-11 13:54:53 -0800 | [diff] [blame] | 141 | |
Victor Zverovich | f6d481f | 2014-06-29 14:22:53 -0700 | [diff] [blame] | 142 | // Prints formatted error message. |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 143 | void vreport_error(const char* format, fmt::format_args args) { |
Victor Zverovich | b827a97 | 2014-07-01 16:59:25 -0700 | [diff] [blame] | 144 | fmt::print("Error: "); |
Victor Zverovich | c69e308 | 2017-10-20 18:00:31 -0700 | [diff] [blame] | 145 | fmt::vprint(format, args); |
Victor Zverovich | 87b5ebf | 2012-12-11 13:54:53 -0800 | [diff] [blame] | 146 | } |
Victor Zverovich | c69e308 | 2017-10-20 18:00:31 -0700 | [diff] [blame] | 147 | template <typename... Args> |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 148 | void report_error(const char* format, const Args & ... args) { |
Victor Zverovich | 111fa58 | 2018-04-08 09:03:37 -0700 | [diff] [blame] | 149 | vreport_error(format, fmt::make_format_args(args...)); |
Victor Zverovich | c69e308 | 2017-10-20 18:00:31 -0700 | [diff] [blame] | 150 | } |
Victor Zverovich | 87b5ebf | 2012-12-11 13:54:53 -0800 | [diff] [blame] | 151 | |
Victor Zverovich | f6d481f | 2014-06-29 14:22:53 -0700 | [diff] [blame] | 152 | report_error("file not found: {}", path); |
Victor Zverovich | 9d59057 | 2014-06-29 11:51:27 -0700 | [diff] [blame] | 153 | |
Victor Zverovich | c69e308 | 2017-10-20 18:00:31 -0700 | [diff] [blame] | 154 | Note that ``vreport_error`` is not parameterized on argument types which can |
Victor Zverovich | 9b392a6 | 2019-03-16 07:59:58 -0700 | [diff] [blame] | 155 | improve compile times and reduce code size compared to a fully parameterized |
Victor Zverovich | b10ccb8 | 2018-12-05 06:42:33 -0800 | [diff] [blame] | 156 | version. |
Victor Zverovich | 87b5ebf | 2012-12-11 13:54:53 -0800 | [diff] [blame] | 157 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 158 | Benchmarks |
| 159 | ---------- |
| 160 | |
| 161 | Speed tests |
| 162 | ~~~~~~~~~~~ |
| 163 | |
| 164 | ================= ============= =========== |
| 165 | Library Method Run Time, s |
| 166 | ================= ============= =========== |
Victor Zverovich | f4fcc5f | 2019-11-20 09:31:11 -0800 | [diff] [blame] | 167 | libc printf 1.03 |
| 168 | libc++ std::ostream 2.98 |
| 169 | {fmt} 4de41a fmt::print 0.76 |
| 170 | Boost Format 1.67 boost::format 7.24 |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 171 | Folly Format folly::format 2.23 |
| 172 | ================= ============= =========== |
| 173 | |
Victor Zverovich | f4fcc5f | 2019-11-20 09:31:11 -0800 | [diff] [blame] | 174 | {fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``. |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 175 | |
| 176 | The above results were generated by building ``tinyformat_test.cpp`` on macOS |
| 177 | 10.14.3 with ``clang++ -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of |
| 178 | three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` |
| 179 | or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for |
| 180 | further details refer to the `source |
| 181 | <https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_. |
| 182 | |
Victor Zverovich | 0a66e4c | 2019-03-24 11:37:07 -0700 | [diff] [blame] | 183 | {fmt} is 10x faster than ``std::ostringstream`` and ``sprintf`` on floating-point |
| 184 | formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_) |
| 185 | and as fast as `double-conversion <https://github.com/google/double-conversion>`_: |
| 186 | |
Victor Zverovich | ef7369c | 2019-11-28 08:09:46 -0800 | [diff] [blame] | 187 | .. image:: https://user-images.githubusercontent.com/576385/69767160-cdaca400-112f-11ea-9fc5-347c9f83caad.png |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 188 | :target: https://fmt.dev/unknown_mac64_clang10.0.html |
Victor Zverovich | 0a66e4c | 2019-03-24 11:37:07 -0700 | [diff] [blame] | 189 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 190 | Compile time and code bloat |
| 191 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 192 | |
| 193 | The script `bloat-test.py |
| 194 | <https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_ |
| 195 | from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_ |
| 196 | tests compile time and code bloat for nontrivial projects. |
| 197 | It generates 100 translation units and uses ``printf()`` or its alternative |
| 198 | five times in each to simulate a medium sized project. The resulting |
| 199 | executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42), |
| 200 | macOS Sierra, best of three) is shown in the following tables. |
| 201 | |
| 202 | **Optimized build (-O3)** |
| 203 | |
| 204 | ============= =============== ==================== ================== |
| 205 | Method Compile Time, s Executable size, KiB Stripped size, KiB |
| 206 | ============= =============== ==================== ================== |
| 207 | printf 2.6 29 26 |
| 208 | printf+string 16.4 29 26 |
| 209 | iostreams 31.1 59 55 |
| 210 | {fmt} 19.0 37 34 |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 211 | Boost Format 91.9 226 203 |
| 212 | Folly Format 115.7 101 88 |
| 213 | ============= =============== ==================== ================== |
| 214 | |
| 215 | As you can see, {fmt} has 60% less overhead in terms of resulting binary code |
| 216 | size compared to iostreams and comes pretty close to ``printf``. Boost Format |
| 217 | and Folly Format have the largest overheads. |
| 218 | |
| 219 | ``printf+string`` is the same as ``printf`` but with extra ``<string>`` |
| 220 | include to measure the overhead of the latter. |
| 221 | |
| 222 | **Non-optimized build** |
| 223 | |
| 224 | ============= =============== ==================== ================== |
| 225 | Method Compile Time, s Executable size, KiB Stripped size, KiB |
| 226 | ============= =============== ==================== ================== |
| 227 | printf 2.2 33 30 |
| 228 | printf+string 16.0 33 30 |
| 229 | iostreams 28.3 56 52 |
| 230 | {fmt} 18.2 59 50 |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 231 | Boost Format 54.1 365 303 |
| 232 | Folly Format 79.9 445 430 |
| 233 | ============= =============== ==================== ================== |
| 234 | |
| 235 | ``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to |
Victor Zverovich | 6793ffc | 2019-11-20 09:33:59 -0800 | [diff] [blame] | 236 | compare formatting function overhead only. Boost Format is a |
| 237 | header-only library so it doesn't provide any linkage options. |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 238 | |
| 239 | Running the tests |
| 240 | ~~~~~~~~~~~~~~~~~ |
| 241 | |
| 242 | Please refer to `Building the library`__ for the instructions on how to build |
| 243 | the library and run the unit tests. |
| 244 | |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 245 | __ https://fmt.dev/latest/usage.html#building-the-library |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 246 | |
| 247 | Benchmarks reside in a separate repository, |
| 248 | `format-benchmarks <https://github.com/fmtlib/format-benchmark>`_, |
| 249 | so to run the benchmarks you first need to clone this repository and |
| 250 | generate Makefiles with CMake:: |
| 251 | |
| 252 | $ git clone --recursive https://github.com/fmtlib/format-benchmark.git |
| 253 | $ cd format-benchmark |
| 254 | $ cmake . |
| 255 | |
| 256 | Then you can run the speed test:: |
| 257 | |
| 258 | $ make speed-test |
| 259 | |
| 260 | or the bloat test:: |
| 261 | |
| 262 | $ make bloat-test |
| 263 | |
Victor Zverovich | affa794 | 2014-01-30 11:16:27 -0800 | [diff] [blame] | 264 | Projects using this library |
| 265 | --------------------------- |
| 266 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 267 | * `0 A.D. <http://play0ad.com/>`_: A free, open-source, cross-platform real-time |
| 268 | strategy game |
Victor Zverovich | 38a7406 | 2015-02-06 13:46:19 -0800 | [diff] [blame] | 269 | |
Victor Zverovich | 73ec650 | 2014-10-12 14:18:17 -0700 | [diff] [blame] | 270 | * `AMPL/MP <https://github.com/ampl/mp>`_: |
| 271 | An open-source library for mathematical programming |
Victor Zverovich | 34cf54c | 2018-02-24 09:37:17 +0000 | [diff] [blame] | 272 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 273 | * `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft |
| 274 | operations suite |
Victor Zverovich | 29352af | 2018-12-01 08:19:20 -0800 | [diff] [blame] | 275 | |
| 276 | * `Celestia <https://celestia.space/>`_: Real-time 3D visualization of space |
Victor Zverovich | affa794 | 2014-01-30 11:16:27 -0800 | [diff] [blame] | 277 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 278 | * `Ceph <https://ceph.com/>`_: A scalable distributed storage system |
| 279 | |
Victor Zverovich | 58a8f2f | 2019-09-06 06:26:09 -0700 | [diff] [blame] | 280 | * `ccache <https://ccache.dev/>`_: A compiler cache |
| 281 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 282 | * `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater |
| 283 | vehicle |
Victor Zverovich | 2bf59a9 | 2016-08-10 08:29:44 -0700 | [diff] [blame] | 284 | |
vitaut | 7e94fcb | 2015-12-03 08:09:53 -0800 | [diff] [blame] | 285 | * `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_: |
Victor Zverovich | 8dbfd72 | 2014-06-28 19:17:13 -0700 | [diff] [blame] | 286 | Player vs Player Gaming Network with tweaks |
| 287 | |
vitaut | 7e94fcb | 2015-12-03 08:09:53 -0800 | [diff] [blame] | 288 | * `KBEngine <http://kbengine.org/>`_: An open-source MMOG server engine |
Victor Zverovich | 2938a92 | 2014-09-13 08:44:49 -0700 | [diff] [blame] | 289 | |
Victor Zverovich | 5174b8c | 2016-03-10 10:52:21 -0800 | [diff] [blame] | 290 | * `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows |
Victor Zverovich | 090de29 | 2016-03-10 10:51:52 -0800 | [diff] [blame] | 291 | |
Victor Zverovich | a09f748 | 2018-01-27 17:47:41 -0800 | [diff] [blame] | 292 | * `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software |
| 293 | |
Victor Zverovich | 73ec650 | 2014-10-12 14:18:17 -0700 | [diff] [blame] | 294 | * `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game |
| 295 | |
Victor Zverovich | c57029c | 2018-02-01 16:44:27 -0800 | [diff] [blame] | 296 | * `Drake <http://drake.mit.edu/>`_: A planning, control, and analysis toolbox |
| 297 | for nonlinear dynamical systems (MIT) |
| 298 | |
| 299 | * `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus |
| 300 | (Lyft) |
| 301 | |
Victor Zverovich | a9f810c | 2018-02-02 19:17:19 -0800 | [diff] [blame] | 302 | * `FiveM <https://fivem.net/>`_: a modification framework for GTA V |
| 303 | |
Billy Donahue | 1763d0e | 2019-04-12 12:47:21 -0400 | [diff] [blame] | 304 | * `MongoDB <https://mongodb.com/>`_: Distributed document database |
| 305 | |
Victor Zverovich | c57029c | 2018-02-01 16:44:27 -0800 | [diff] [blame] | 306 | * `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to |
| 307 | generate randomized datasets |
Victor Zverovich | 6e82084 | 2016-03-01 14:28:52 -0800 | [diff] [blame] | 308 | |
Victor Zverovich | 1a7d0ba | 2018-02-02 19:10:25 -0800 | [diff] [blame] | 309 | * `OpenSpace <http://openspaceproject.com/>`_: An open-source astrovisualization |
| 310 | framework |
| 311 | |
Victor Zverovich | 81dc04d | 2015-02-07 08:31:17 -0800 | [diff] [blame] | 312 | * `PenUltima Online (POL) <http://www.polserver.com/>`_: |
| 313 | An MMO server, compatible with most Ultima Online clients |
| 314 | |
Victor Zverovich | 1a7d0ba | 2018-02-02 19:10:25 -0800 | [diff] [blame] | 315 | * `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance, |
| 316 | associative database |
Victor Zverovich | 001054c | 2015-04-27 07:02:15 -0700 | [diff] [blame] | 317 | |
Victor Zverovich | 820c03a | 2014-12-02 06:39:16 -0800 | [diff] [blame] | 318 | * `readpe <https://bitbucket.org/sys_dev/readpe>`_: Read Portable Executable |
| 319 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 320 | * `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster |
| 321 | proxy |
Victor Zverovich | 42d8f5b | 2015-09-16 21:33:51 -0700 | [diff] [blame] | 322 | |
Victor Zverovich | b10ccb8 | 2018-12-05 06:42:33 -0800 | [diff] [blame] | 323 | * `rpclib <http://rpclib.net/>`_: A modern C++ msgpack-RPC server and client |
| 324 | library |
| 325 | |
vitaut | 7e94fcb | 2015-12-03 08:09:53 -0800 | [diff] [blame] | 326 | * `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_: |
Victor Zverovich | 38a7406 | 2015-02-06 13:46:19 -0800 | [diff] [blame] | 327 | Small crossplatform 2D graphic engine |
| 328 | |
Victor Zverovich | a23fbbb | 2014-12-02 12:54:12 -0800 | [diff] [blame] | 329 | * `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_: |
| 330 | Business intelligence software |
| 331 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 332 | * `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store |
| 333 | that can handle 1 million transactions per second on a single server |
Victor Zverovich | 2bf59a9 | 2016-08-10 08:29:44 -0700 | [diff] [blame] | 334 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 335 | * `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ |
| 336 | framework for high-performance server applications on modern hardware |
Victor Zverovich | 2bf59a9 | 2016-08-10 08:29:44 -0700 | [diff] [blame] | 337 | |
Victor Zverovich | 6e3d7d9 | 2014-12-08 06:15:31 -0800 | [diff] [blame] | 338 | * `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library |
| 339 | |
Victor Zverovich | a12f496 | 2015-09-16 21:45:27 -0700 | [diff] [blame] | 340 | * `Stellar <https://www.stellar.org/>`_: Financial platform |
| 341 | |
vitaut | 32fbc08 | 2015-08-08 18:58:25 -0700 | [diff] [blame] | 342 | * `Touch Surgery <https://www.touchsurgery.com/>`_: Surgery simulator |
| 343 | |
Victor Zverovich | a084495 | 2018-11-28 17:28:27 -0800 | [diff] [blame] | 344 | * `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source |
| 345 | MMORPG framework |
Victor Zverovich | ef5972e | 2015-03-17 19:43:47 -0700 | [diff] [blame] | 346 | |
Victor Zverovich | 2ed412f | 2019-09-06 13:03:14 -0700 | [diff] [blame] | 347 | `More... <https://github.com/search?q=fmtlib&type=Code>`_ |
Victor Zverovich | d930f69 | 2015-02-06 14:03:44 -0800 | [diff] [blame] | 348 | |
Victor Zverovich | 9d59057 | 2014-06-29 11:51:27 -0700 | [diff] [blame] | 349 | If you are aware of other projects using this library, please let me know |
Victor Zverovich | 73ec650 | 2014-10-12 14:18:17 -0700 | [diff] [blame] | 350 | by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an |
Victor Zverovich | e817bb9 | 2016-04-27 08:23:03 -0700 | [diff] [blame] | 351 | `issue <https://github.com/fmtlib/fmt/issues>`_. |
Victor Zverovich | affa794 | 2014-01-30 11:16:27 -0800 | [diff] [blame] | 352 | |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 353 | Motivation |
| 354 | ---------- |
| 355 | |
| 356 | So why yet another formatting library? |
| 357 | |
| 358 | There are plenty of methods for doing this task, from standard ones like |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 359 | the printf family of function and iostreams to Boost Format and FastFormat |
Victor Zverovich | 5e5506f | 2019-03-12 06:08:18 -0700 | [diff] [blame] | 360 | libraries. The reason for creating a new library is that every existing |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 361 | solution that I found either had serious issues or didn't provide |
| 362 | all the features I needed. |
| 363 | |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 364 | printf |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 365 | ~~~~~~ |
| 366 | |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 367 | The good thing about ``printf`` is that it is pretty fast and readily available |
Victor Zverovich | e1ba41f | 2014-05-14 19:17:20 -0700 | [diff] [blame] | 368 | being a part of the C standard library. The main drawback is that it |
Victor Zverovich | ef39274 | 2019-03-16 06:47:18 -0700 | [diff] [blame] | 369 | doesn't support user-defined types. ``printf`` also has safety issues although |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 370 | they are somewhat mitigated with `__attribute__ ((format (printf, ...)) |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 371 | <http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC. |
Victor Zverovich | cb45829 | 2012-12-09 10:09:15 -0800 | [diff] [blame] | 372 | There is a POSIX extension that adds positional arguments required for |
vitaut | 7e94fcb | 2015-12-03 08:09:53 -0800 | [diff] [blame] | 373 | `i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_ |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 374 | to ``printf`` but it is not a part of C99 and may not be available on some |
Victor Zverovich | cb45829 | 2012-12-09 10:09:15 -0800 | [diff] [blame] | 375 | platforms. |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 376 | |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 377 | iostreams |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 378 | ~~~~~~~~~ |
| 379 | |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 380 | The main issue with iostreams is best illustrated with an example: |
Victor Zverovich | a8a536b | 2012-12-13 08:12:09 -0800 | [diff] [blame] | 381 | |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 382 | .. code:: c++ |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 383 | |
| 384 | std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; |
| 385 | |
Victor Zverovich | a8a536b | 2012-12-13 08:12:09 -0800 | [diff] [blame] | 386 | which is a lot of typing compared to printf: |
| 387 | |
Victor Zverovich | f02e410 | 2014-11-07 07:04:03 -0800 | [diff] [blame] | 388 | .. code:: c++ |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 389 | |
| 390 | printf("%.2f\n", 1.23456); |
| 391 | |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 392 | Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams |
| 393 | don't support positional arguments by design. |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 394 | |
Victor Zverovich | 1428b34 | 2019-03-16 06:30:50 -0700 | [diff] [blame] | 395 | The good part is that iostreams support user-defined types and are safe although |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 396 | error handling is awkward. |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 397 | |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 398 | Boost Format |
| 399 | ~~~~~~~~~~~~ |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 400 | |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 401 | This is a very powerful library which supports both ``printf``-like format |
| 402 | strings and positional arguments. Its main drawback is performance. According to |
| 403 | various benchmarks it is much slower than other methods considered here. Boost |
| 404 | Format also has excessive build times and severe code bloat issues (see |
| 405 | `Benchmarks`_). |
Victor Zverovich | 3e4d847 | 2012-12-07 15:33:27 -0800 | [diff] [blame] | 406 | |
| 407 | FastFormat |
| 408 | ~~~~~~~~~~ |
| 409 | |
| 410 | This is an interesting library which is fast, safe and has positional |
| 411 | arguments. However it has significant limitations, citing its author: |
| 412 | |
| 413 | Three features that have no hope of being accommodated within the |
| 414 | current design are: |
| 415 | |
| 416 | * Leading zeros (or any other non-space padding) |
| 417 | * Octal/hexadecimal encoding |
| 418 | * Runtime width/alignment specification |
| 419 | |
| 420 | It is also quite big and has a heavy dependency, STLSoft, which might be |
| 421 | too restrictive for using it in some projects. |
| 422 | |
Victor Zverovich | 3cea869 | 2012-12-24 21:31:05 -0800 | [diff] [blame] | 423 | Boost Spirit.Karma |
| 424 | ~~~~~~~~~~~~~~~~~~ |
| 425 | |
Victor Zverovich | a7f68dc | 2019-03-16 06:46:19 -0700 | [diff] [blame] | 426 | This is not really a formatting library but I decided to include it here for |
| 427 | completeness. As iostreams, it suffers from the problem of mixing verbatim text |
| 428 | with arguments. The library is pretty fast, but slower on integer formatting |
| 429 | than ``fmt::format_int`` on Karma's own benchmark, |
Victor Zverovich | d1369d4 | 2014-02-13 09:53:01 -0800 | [diff] [blame] | 430 | see `Fast integer to string conversion in C++ |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 431 | <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_. |
Victor Zverovich | 3cea869 | 2012-12-24 21:31:05 -0800 | [diff] [blame] | 432 | |
Victor Zverovich | 8bbb0b4 | 2018-08-15 06:34:34 -0700 | [diff] [blame] | 433 | FAQ |
| 434 | --- |
| 435 | |
| 436 | Q: how can I capture formatting arguments and format them later? |
| 437 | |
| 438 | A: use ``std::tuple``: |
| 439 | |
| 440 | .. code:: c++ |
| 441 | |
| 442 | template <typename... Args> |
| 443 | auto capture(const Args&... args) { |
| 444 | return std::make_tuple(args...); |
| 445 | } |
| 446 | |
| 447 | auto print_message = [](const auto&... args) { |
| 448 | fmt::print(args...); |
| 449 | }; |
| 450 | |
| 451 | // Capture and store arguments: |
| 452 | auto args = capture("{} {}", 42, "foo"); |
| 453 | // Do formatting: |
| 454 | std::apply(print_message, args); |
| 455 | |
Victor Zverovich | faccb4c | 2012-12-12 07:44:41 -0800 | [diff] [blame] | 456 | License |
| 457 | ------- |
| 458 | |
Victor Zverovich | 972ffd3 | 2019-09-06 13:13:30 -0700 | [diff] [blame] | 459 | {fmt} is distributed under the MIT `license |
Victor Zverovich | e817bb9 | 2016-04-27 08:23:03 -0700 | [diff] [blame] | 460 | <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_. |
Victor Zverovich | e7c7b12 | 2013-01-14 06:43:31 -0800 | [diff] [blame] | 461 | |
Victor Zverovich | 3541e3a | 2013-01-14 06:47:10 -0800 | [diff] [blame] | 462 | The `Format String Syntax |
Victor Zverovich | 91bb3aa | 2019-05-17 15:42:00 -0700 | [diff] [blame] | 463 | <https://fmt.dev/latest/syntax.html>`_ |
Victor Zverovich | e7c7b12 | 2013-01-14 06:43:31 -0800 | [diff] [blame] | 464 | section in the documentation is based on the one from Python `string module |
vitaut | 7e94fcb | 2015-12-03 08:09:53 -0800 | [diff] [blame] | 465 | documentation <https://docs.python.org/3/library/string.html#module-string>`_ |
Victor Zverovich | e7c7b12 | 2013-01-14 06:43:31 -0800 | [diff] [blame] | 466 | adapted for the current library. For this reason the documentation is |
| 467 | distributed under the Python Software Foundation license available in |
vitaut | 1c72e70 | 2015-05-07 06:47:22 -0700 | [diff] [blame] | 468 | `doc/python-license.txt |
Victor Zverovich | f9ee5f4 | 2016-04-27 08:28:24 -0700 | [diff] [blame] | 469 | <https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_. |
Victor Zverovich | 4cddbfa | 2016-04-25 06:36:26 -0700 | [diff] [blame] | 470 | It only applies if you distribute the documentation of fmt. |
Victor Zverovich | e7c7b12 | 2013-01-14 06:43:31 -0800 | [diff] [blame] | 471 | |
Victor Zverovich | c50f94a | 2012-12-07 13:20:50 -0800 | [diff] [blame] | 472 | Acknowledgments |
| 473 | --------------- |
| 474 | |
Victor Zverovich | fdd0149 | 2019-03-16 07:27:53 -0700 | [diff] [blame] | 475 | The {fmt} library is maintained by Victor Zverovich (`vitaut |
Victor Zverovich | 38b603a | 2018-01-20 17:12:43 -0800 | [diff] [blame] | 476 | <https://github.com/vitaut>`_) and Jonathan MΓΌller (`foonathan |
| 477 | <https://github.com/foonathan>`_) with contributions from many other people. |
| 478 | See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and |
| 479 | `Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. |
| 480 | Let us know if your contribution is not listed or mentioned incorrectly and |
| 481 | we'll make it right. |
| 482 | |
Victor Zverovich | c50f94a | 2012-12-07 13:20:50 -0800 | [diff] [blame] | 483 | The benchmark section of this readme file and the performance tests are taken |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 484 | from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library |
Victor Zverovich | cb45829 | 2012-12-09 10:09:15 -0800 | [diff] [blame] | 485 | written by Chris Foster. Boost Format library is acknowledged transitively |
| 486 | since it had some influence on tinyformat. |
| 487 | Some ideas used in the implementation are borrowed from `Loki |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 488 | <http://loki-lib.sourceforge.net/>`_ SafeFormat and `Diagnostic API |
| 489 | <http://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`_ in |
| 490 | `Clang <http://clang.llvm.org/>`_. |
Victor Zverovich | e7c7b12 | 2013-01-14 06:43:31 -0800 | [diff] [blame] | 491 | Format string syntax and the documentation are based on Python's `str.format |
Jack Andersen | 0571013 | 2019-09-30 16:43:04 -1000 | [diff] [blame] | 492 | <https://docs.python.org/3/library/stdtypes.html#str.format>`_. |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 493 | Thanks `Doug Turnbull <https://github.com/softwaredoug>`_ for his valuable |
Victor Zverovich | 4c30447 | 2013-11-14 08:57:19 -0800 | [diff] [blame] | 494 | comments and contribution to the design of the type-safe API and |
Victor Zverovich | 9cbb25e | 2014-11-05 07:36:55 -0800 | [diff] [blame] | 495 | `Gregory Czajkowski <https://github.com/gcflymoto>`_ for implementing binary |
| 496 | formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`_ for comprehensive |
| 497 | `comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`_ |
| 498 | and useful comments regarding performance, `Boris Kaul <https://github.com/localvoid>`_ for |
| 499 | `C++ counting digits benchmark <https://github.com/localvoid/cxx-benchmark-count-digits>`_. |
Victor Zverovich | eb6baf0 | 2015-03-15 06:39:03 -0700 | [diff] [blame] | 500 | Thanks to `CarterLi <https://github.com/CarterLi>`_ for contributing various |
Victor Zverovich | 6e82084 | 2016-03-01 14:28:52 -0800 | [diff] [blame] | 501 | improvements to the code. |