commit aa53608: [Project] Add fmt library for simple string ops

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Mar 12 18:00:09 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-03-12 11:57:42 +0000
URL: https://github.com/rspamd/rspamd/commit/aa53608938ac4e25d9cdef4a222463dc338b0c85

[Project] Add fmt library for simple string ops

---
 CMakeLists.txt                                |    3 +-
 contrib/DEPENDENCY_INFO.md                    |    1 +
 contrib/fmt/CMakeLists.txt                    |  316 ++
 contrib/{kann/LICENSE.txt => fmt/LICENSE.rst} |   21 +-
 contrib/fmt/README.rst                        |  506 ++++
 contrib/fmt/include/fmt/chrono.h              | 1118 +++++++
 contrib/fmt/include/fmt/color.h               |  603 ++++
 contrib/fmt/include/fmt/compile.h             |  701 +++++
 contrib/fmt/include/fmt/core.h                | 2122 +++++++++++++
 contrib/fmt/include/fmt/format-inl.h          | 2801 +++++++++++++++++
 contrib/fmt/include/fmt/format.h              | 3960 +++++++++++++++++++++++++
 contrib/fmt/include/fmt/locale.h              |   64 +
 contrib/fmt/include/fmt/os.h                  |  480 +++
 contrib/fmt/include/fmt/ostream.h             |  177 ++
 contrib/fmt/include/fmt/posix.h               |    2 +
 contrib/fmt/include/fmt/printf.h              |  751 +++++
 contrib/fmt/include/fmt/ranges.h              |  396 +++
 contrib/fmt/src/format.cc                     |   99 +
 contrib/fmt/src/os.cc                         |  322 ++
 src/CMakeLists.txt                            |    1 +
 20 files changed, 14434 insertions(+), 10 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b4538dd3..71796b294 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,6 +117,7 @@ INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/"
 		"${CMAKE_SOURCE_DIR}/contrib/lc-btrie"
 		"${CMAKE_SOURCE_DIR}/contrib/lua-lpeg"
 		"${CMAKE_SOURCE_DIR}/contrib/frozen/include"
+		"${CMAKE_SOURCE_DIR}/contrib/fmt/include"
 		"${CMAKE_BINARY_DIR}/src" #Stored in the binary dir
 		"${CMAKE_BINARY_DIR}/src/libcryptobox")
 
@@ -650,7 +651,7 @@ ADD_SUBDIRECTORY(contrib/libev)
 ADD_SUBDIRECTORY(contrib/kann)
 ADD_SUBDIRECTORY(contrib/fastutf8)
 ADD_SUBDIRECTORY(contrib/google-ced)
-
+ADD_SUBDIRECTORY(contrib/fmt)
 
 IF (NOT WITH_LUAJIT)
 	ADD_SUBDIRECTORY(contrib/lua-bit)
diff --git a/contrib/DEPENDENCY_INFO.md b/contrib/DEPENDENCY_INFO.md
index 502d7e161..12e00df26 100644
--- a/contrib/DEPENDENCY_INFO.md
+++ b/contrib/DEPENDENCY_INFO.md
@@ -31,3 +31,4 @@
 | expected      | v1.0    | Public Domain / CC0 | NO      |                    |
 | robin-hood    | 3.9.1   | MIT                 | NO      |                    |
 | frozen        | 1.0.1   | Apache 2            | NO      |                    |
+| fmt           | 7.1.3   | MIT                 | NO      |                    |
diff --git a/contrib/fmt/CMakeLists.txt b/contrib/fmt/CMakeLists.txt
new file mode 100644
index 000000000..b05a024a7
--- /dev/null
+++ b/contrib/fmt/CMakeLists.txt
@@ -0,0 +1,316 @@
+cmake_minimum_required(VERSION 3.1...3.18)
+
+# Fallback for using newer policies on CMake <3.12.
+if(${CMAKE_VERSION} VERSION_LESS 3.12)
+  cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+endif()
+
+# Determine if fmt is built as a subproject (using add_subdirectory)
+# or if it is the master project.
+set(MASTER_PROJECT OFF)
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+  set(MASTER_PROJECT ON)
+  message(STATUS "CMake version: ${CMAKE_VERSION}")
+endif ()
+
+# Joins arguments and places the results in ${result_var}.
+function(join result_var)
+  set(result )
+  foreach (arg ${ARGN})
+    set(result "${result}${arg}")
+  endforeach ()
+  set(${result_var} "${result}" PARENT_SCOPE)
+endfunction()
+
+include(CMakeParseArguments)
+
+# Sets a cache variable with a docstring joined from multiple arguments:
+#   set(<variable> <value>... CACHE <type> <docstring>...)
+# This allows splitting a long docstring for readability.
+function(set_verbose)
+  # cmake_parse_arguments is broken in CMake 3.4 (cannot parse CACHE) so use
+  # list instead.
+  list(GET ARGN 0 var)
+  list(REMOVE_AT ARGN 0)
+  list(GET ARGN 0 val)
+  list(REMOVE_AT ARGN 0)
+  list(REMOVE_AT ARGN 0)
+  list(GET ARGN 0 type)
+  list(REMOVE_AT ARGN 0)
+  join(doc ${ARGN})
+  set(${var} ${val} CACHE ${type} ${doc})
+endfunction()
+
+# Set the default CMAKE_BUILD_TYPE to Release.
+# This should be done before the project command since the latter can set
+# CMAKE_BUILD_TYPE itself (it does so for nmake).
+if (MASTER_PROJECT AND NOT CMAKE_BUILD_TYPE)
+  set_verbose(CMAKE_BUILD_TYPE Release CACHE STRING
+              "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
+              "CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
+endif ()
+
+project(FMT CXX)
+include(GNUInstallDirs)
+set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING
+            "Installation directory for include files, a relative path that "
+            "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.")
+
+option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
+option(FMT_WERROR "Halt the compilation with an error on compiler warnings."
+       OFF)
+
+# Options that control generation of various targets.
+option(FMT_DOC "Generate the doc target." ${MASTER_PROJECT})
+option(FMT_INSTALL "Generate the install target." ${MASTER_PROJECT})
+option(FMT_TEST "Generate the test target." ${MASTER_PROJECT})
+option(FMT_FUZZ "Generate the fuzz target." OFF)
+option(FMT_CUDA_TEST "Generate the cuda-test target." OFF)
+option(FMT_OS "Include core requiring OS (Windows/Posix) " ON)
+
+# Get version from core.h
+file(READ include/fmt/core.h core_h)
+if (NOT core_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
+  message(FATAL_ERROR "Cannot get FMT_VERSION from core.h.")
+endif ()
+# Use math to skip leading zeros if any.
+math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
+math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
+math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
+join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
+                 ${CPACK_PACKAGE_VERSION_PATCH})
+message(STATUS "Version: ${FMT_VERSION}")
+
+message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+
+if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+endif ()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic
+      -Wold-style-cast -Wundef
+      -Wredundant-decls -Wwrite-strings -Wpointer-arith
+      -Wcast-qual -Wformat=2 -Wmissing-include-dirs
+      -Wcast-align
+      -Wctor-dtor-privacy -Wdisabled-optimization
+      -Winvalid-pch -Woverloaded-virtual
+      -Wconversion -Wswitch-enum -Wundef
+      -Wno-ctor-dtor-privacy -Wno-format-nonliteral)
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
+      set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept
+         -Wno-dangling-else -Wno-unused-local-typedefs)
+  endif ()
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
+      set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion
+          -Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast
+          -Wvector-operation-performance -Wsized-deallocation)
+  endif ()
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
+      set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
+          -Wnull-dereference -Wduplicated-cond)
+  endif ()
+  set(WERROR_FLAG -Werror)
+endif ()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wconversion -Wundef
+      -Wdeprecated -Wweak-vtables)
+  set(WERROR_FLAG -Werror)
+endif ()
+
+if (MSVC)
+  set(PEDANTIC_COMPILE_FLAGS /W3)
+  set(WERROR_FLAG /WX)
+endif ()
+
+set(strtod_l_headers stdlib.h)
+if (APPLE)
+  set(strtod_l_headers ${strtod_l_headers} xlocale.h)
+endif ()
+
+include(CheckSymbolExists)
+if (WIN32)
+  check_symbol_exists(_strtod_l "${strtod_l_headers}" HAVE_STRTOD_L)
+else ()
+  check_symbol_exists(strtod_l "${strtod_l_headers}" HAVE_STRTOD_L)
+endif ()
+
+function(add_headers VAR)
+  set(headers ${${VAR}})
+  foreach (header ${ARGN})
+    set(headers ${headers} include/fmt/${header})
+  endforeach()
+  set(${VAR} ${headers} PARENT_SCOPE)
+endfunction()
+
+# Define the fmt library, its includes and the needed defines.
+add_headers(FMT_HEADERS chrono.h color.h compile.h core.h format.h format-inl.h
+                        locale.h os.h ostream.h posix.h printf.h ranges.h)
+if (FMT_OS)
+  set(FMT_SOURCES src/format.cc src/os.cc)
+else()
+  set(FMT_SOURCES src/format.cc)
+endif ()
+
+add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst)
+add_library(fmt::fmt ALIAS fmt)
+
+if (HAVE_STRTOD_L)
+  target_compile_definitions(fmt PUBLIC FMT_LOCALE)
+endif ()
+
+if (FMT_WERROR)
+  target_compile_options(fmt PRIVATE ${WERROR_FLAG})
+endif ()
+if (FMT_PEDANTIC)
+  target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
+endif ()
+
+target_compile_features(fmt INTERFACE ${FMT_REQUIRED_FEATURES})
+
+target_include_directories(fmt PUBLIC
+  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+  $<INSTALL_INTERFACE:${FMT_INC_DIR}>)
+
+set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.")
+
+set_target_properties(fmt PROPERTIES
+  VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}
+  DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}")
+
+# Set FMT_LIB_NAME for pkg-config fmt.pc. We cannot use the OUTPUT_NAME target
+# property because it's not set by default.
+set(FMT_LIB_NAME fmt)
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+  set(FMT_LIB_NAME ${FMT_LIB_NAME}${FMT_DEBUG_POSTFIX})
+endif ()
+
+if (BUILD_SHARED_LIBS)
+  if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND
+      NOT EMSCRIPTEN)
+    # Fix rpmlint warning:
+    # unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
+    target_link_libraries(fmt -Wl,--as-needed)
+  endif ()
+  target_compile_definitions(fmt PRIVATE FMT_EXPORT INTERFACE FMT_SHARED)
+endif ()
+if (FMT_SAFE_DURATION_CAST)
+  target_compile_definitions(fmt PUBLIC FMT_SAFE_DURATION_CAST)
+endif()
+
+add_library(fmt-header-only INTERFACE)
+add_library(fmt::fmt-header-only ALIAS fmt-header-only)
+
+target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
+target_compile_features(fmt-header-only INTERFACE ${FMT_REQUIRED_FEATURES})
+
+target_include_directories(fmt-header-only INTERFACE
+  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+  $<INSTALL_INTERFACE:${FMT_INC_DIR}>)
+
+# Install targets.
+if (FMT_INSTALL)
+  include(CMakePackageConfigHelpers)
+  set_verbose(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING
+              "Installation directory for cmake files, a relative path that "
+              "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute "
+              "path.")
+  set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
+  set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
+  set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc)
+  set(targets_export_name fmt-targets)
+
+  set_verbose(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
+              "Installation directory for libraries, a relative path that "
+              "will be joined to ${CMAKE_INSTALL_PREFIX} or an absolute path.")
+
+  set_verbose(FMT_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH
+              "Installation directory for pkgconfig (.pc) files, a relative "
+              "path that will be joined with ${CMAKE_INSTALL_PREFIX} or an "
+              "absolute path.")
+
+  # Generate the version, config and target files into the build directory.
+  write_basic_package_version_file(
+    ${version_config}
+    VERSION ${FMT_VERSION}
+    COMPATIBILITY AnyNewerVersion)
+
+  join_paths(libdir_for_pc_file "\${exec_prefix}" "${FMT_LIB_DIR}")
+  join_paths(includedir_for_pc_file "\${prefix}" "${FMT_INC_DIR}")
+
+  configure_file(
+    "${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in"
+    "${pkgconfig}"
+    @ONLY)
+  configure_package_config_file(
+    ${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
+    ${project_config}
+    INSTALL_DESTINATION ${FMT_CMAKE_DIR})
+
+  set(INSTALL_TARGETS fmt fmt-header-only)
+  # Use a namespace because CMake provides better diagnostics for namespaced
+  # imported targets.
+  export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt::
+         FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
+
+  # Install version, config and target files.
+  install(
+    FILES ${project_config} ${version_config}
+    DESTINATION ${FMT_CMAKE_DIR})
+  install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
+          NAMESPACE fmt::)
+
+  # Install the library and headers.
+  install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
+          LIBRARY DESTINATION ${FMT_LIB_DIR}
+          ARCHIVE DESTINATION ${FMT_LIB_DIR}
+          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+  install(FILES $<TARGET_PDB_FILE:${INSTALL_TARGETS}>
+          DESTINATION ${FMT_LIB_DIR} OPTIONAL)
+  install(FILES ${FMT_HEADERS} DESTINATION "${FMT_INC_DIR}/fmt")
+  install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
+endif ()
+
+if (FMT_DOC)
+  add_subdirectory(doc)
+endif ()
+
+if (FMT_TEST)
+  enable_testing()
+  add_subdirectory(test)
+endif ()
+
+# Control fuzzing independent of the unit tests.
+if (FMT_FUZZ)
+  add_subdirectory(test/fuzzing)
+
+  # The FMT_FUZZ macro is used to prevent resource exhaustion in fuzzing
+  # mode and make fuzzing practically possible. It is similar to
+  # FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION but uses a different name to
+  # avoid interfering with fuzzing of projects that use {fmt}.
+  # See also https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode.
+  target_compile_definitions(fmt PUBLIC FMT_FUZZ)
+endif ()
+
+set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore)
+if (MASTER_PROJECT AND EXISTS ${gitignore})
+  # Get the list of ignored files from .gitignore.
+  file (STRINGS ${gitignore} lines)
+  list(REMOVE_ITEM lines /doc/html)
+  foreach (line ${lines})
+    string(REPLACE "." "[.]" line "${line}")
+    string(REPLACE "*" ".*" line "${line}")
+    set(ignored_files ${ignored_files} "${line}$" "${line}/")
+  endforeach ()
+  set(ignored_files ${ignored_files}
+    /.git /breathe /format-benchmark sphinx/ .buildinfo .doctrees)
+
+  set(CPACK_SOURCE_GENERATOR ZIP)
+  set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
+  set(CPACK_SOURCE_PACKAGE_FILE_NAME fmt-${FMT_VERSION})
+  set(CPACK_PACKAGE_NAME fmt)
+  set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.rst)
+  include(CPack)
+endif ()
diff --git a/contrib/kann/LICENSE.txt b/contrib/fmt/LICENSE.rst
similarity index 57%
copy from contrib/kann/LICENSE.txt
copy to contrib/fmt/LICENSE.rst
index 8b2cf1141..f0ec3db4d 100644
--- a/contrib/kann/LICENSE.txt
+++ b/contrib/fmt/LICENSE.rst
@@ -1,7 +1,4 @@
-The MIT License
-
-Copyright (c) 2018-2019 Dana-Farber Cancer Institute
-              2016-2018 Broad Institute
+Copyright (c) 2012 - present, Victor Zverovich
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -17,8 +14,14 @@ included in all copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--- Optional exception to the license ---
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into a machine-executable object form of such
+source code, you may redistribute such embedded portions in such object form
+without including the above copyright and permission notices.
diff --git a/contrib/fmt/README.rst b/contrib/fmt/README.rst
new file mode 100644
index 000000000..acddc70ef
--- /dev/null
+++ b/contrib/fmt/README.rst
@@ -0,0 +1,506 @@
+{fmt}
+=====
+
+.. image:: https://travis-ci.org/fmtlib/fmt.png?branch=master
+   :target: https://travis-ci.org/fmtlib/fmt
+
+.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v
+   :target: https://ci.appveyor.com/project/vitaut/fmt
+
+.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
+   :alt: fmt is continuously fuzzed at oss-fuzz
+   :target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
+            colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
+            Summary&q=proj%3Dfmt&can=1
+
+.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
+   :alt: Ask questions at StackOverflow with the tag fmt
+   :target: https://stackoverflow.com/questions/tagged/fmt
+
+**{fmt}** is an open-source formatting library providing a fast and safe
+alternative to C stdio and C++ iostreams.
+
+If you like this project, please consider donating to BYSOL,
+an initiative to help victims of political repressions in Belarus:
+https://www.facebook.com/donate/759400044849707/108388587646909/.
+
+`Documentation <https://fmt.dev>`__
+
+Q&A: ask questions on `StackOverflow with the tag fmt
+<https://stackoverflow.com/questions/tagged/fmt>`_.
+
+Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
+
+Features
+--------
+
+* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
+  for localization
+* Implementation of `C++20 std::format
+  <https://en.cppreference.com/w/cpp/utility/format>`__
+* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
+  `format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
+* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
+  round-trip guarantees
+* Safe `printf implementation
+  <https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
+  extension for positional arguments
+* Extensibility: `support for user-defined types
+  <https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
+* High performance: faster than common standard library implementations of
+  ``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
+  and `Converting a hundred million integers to strings per second
+  <http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
+* Small code size both in terms of source code with the minimum configuration
+  consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
+  and compiled code; see `Compile time and code bloat`_
+* Reliability: the library has an extensive set of `tests
+  <https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
+  <https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
+  Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_
+* Safety: the library is fully type safe, errors in format strings can be
+  reported at compile time, automatic memory management prevents buffer overflow
+  errors
+* Ease of use: small self-contained code base, no external dependencies,
+  permissive MIT `license
+  <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
+* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
+  consistent output across platforms and support for older compilers
+* Clean warning-free codebase even on high warning levels such as
+  ``-Wall -Wextra -pedantic``
+* Locale-independence by default
+* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
+
+See the `documentation <https://fmt.dev>`_ for more details.
+
+Examples
+--------
+
+**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
+
+.. code:: c++
+
+    #include <fmt/core.h>
+    
+    int main() {
+      fmt::print("Hello, world!\n");
+    }
+
+**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
+
+.. code:: c++
+
+    std::string s = fmt::format("The answer is {}.", 42);
+    // s == "The answer is 42."
+
+**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
+
+.. code:: c++
+
+    std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
+    // s == "I'd rather be happy than right."
+
+**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
+
+.. code:: c++
+
+    #include <fmt/chrono.h>
+
+    int main() {
+      using namespace std::literals::chrono_literals;
+      fmt::print("Default format: {} {}\n", 42s, 100ms);
+      fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
+    }
+
+Output::
+
+    Default format: 42s 100ms
+    strftime-like format: 03:15:30
+
+**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
+
+.. code:: c++
+
+    #include <vector>
+    #include <fmt/ranges.h>
+
+    int main() {
+      std::vector<int> v = {1, 2, 3};
+      fmt::print("{}\n", v);
+    }
+
+Output::
+
+    {1, 2, 3}
+
+**Check a format string at compile time**
+
+.. code:: c++
+
+    std::string s = fmt::format(FMT_STRING("{:d}"), "don't panic");
+
+This gives a compile-time error because ``d`` is an invalid format specifier for
+a string.
+
+**Write a file from a single thread**
+
+.. code:: c++
+
+    #include <fmt/os.h>
+
+    int main() {
+      auto out = fmt::output_file("guide.txt");
+      out.print("Don't {}", "Panic");
+    }
+
+This can be `5 to 9 times faster than fprintf
+<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
+
+**Print with colors and text styles**
+
+.. code:: c++
+
+    #include <fmt/color.h>
+
+    int main() {
+      fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
+                 "Hello, {}!\n", "world");
+      fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
+                 fmt::emphasis::underline, "Hello, {}!\n", "мир");
+      fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
+                 "Hello, {}!\n", "世界");
+    }
+
+Output on a modern terminal:
+
+.. image:: https://user-images.githubusercontent.com/
+           576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
+
+Benchmarks
+----------
+
+Speed tests
+~~~~~~~~~~~
+
+================= ============= ===========
+Library           Method        Run Time, s
+================= ============= ===========
+libc              printf          1.04
+libc++            std::ostream    3.05
+{fmt} 6.1.1       fmt::print      0.75
+Boost Format 1.67 boost::format   7.24
+Folly Format      folly::format   2.23
+================= ============= ===========
+
+{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
+
+The above results were generated by building ``tinyformat_test.cpp`` on macOS
+10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
+best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
+or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
+further details refer to the `source
+<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
+
+{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
+floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
+and faster than `double-conversion <https://github.com/google/double-conversion>`_ and
+`ryu <https://github.com/ulfjack/ryu>`_:
+
+.. image:: https://user-images.githubusercontent.com/576385/
+           95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png
+   :target: https://fmt.dev/unknown_mac64_clang12.0.html
+
+Compile time and code bloat
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The script `bloat-test.py
+<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
+from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
+tests compile time and code bloat for nontrivial projects.
+It generates 100 translation units and uses ``printf()`` or its alternative
+five times in each to simulate a medium sized project.  The resulting
+executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
+macOS Sierra, best of three) is shown in the following tables.
+
+**Optimized build (-O3)**
+
+============= =============== ==================== ==================
+Method        Compile Time, s Executable size, KiB Stripped size, KiB
+============= =============== ==================== ==================
+printf                    2.6                   29                 26
+printf+string            16.4                   29                 26
+iostreams                31.1                   59                 55
+{fmt}                    19.0                   37                 34
+Boost Format             91.9                  226                203
+Folly Format            115.7                  101                 88
+============= =============== ==================== ==================
+
+As you can see, {fmt} has 60% less overhead in terms of resulting binary code
+size compared to iostreams and comes pretty close to ``printf``. Boost Format
+and Folly Format have the largest overheads.
+
+``printf+string`` is the same as ``printf`` but with extra ``<string>``
+include to measure the overhead of the latter.
+
+**Non-optimized build**
+
+============= =============== ==================== ==================
+Method        Compile Time, s Executable size, KiB Stripped size, KiB
+============= =============== ==================== ==================
+printf                    2.2                   33                 30
+printf+string            16.0                   33                 30
+iostreams                28.3                   56                 52
+{fmt}                    18.2                   59                 50
+Boost Format             54.1                  365                303
+Folly Format             79.9                  445                430
+============= =============== ==================== ==================
+
+``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
+compare formatting function overhead only. Boost Format is a
+header-only library so it doesn't provide any linkage options.
+
+Running the tests
+~~~~~~~~~~~~~~~~~
+
+Please refer to `Building the library`__ for the instructions on how to build
+the library and run the unit tests.
+
+__ https://fmt.dev/latest/usage.html#building-the-library
+
+Benchmarks reside in a separate repository,
+`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
+so to run the benchmarks you first need to clone this repository and
+generate Makefiles with CMake::
+
+    $ git clone --recursive https://github.com/fmtlib/format-benchmark.git
+    $ cd format-benchmark
+    $ cmake .
*** OUTPUT TRUNCATED, 13921 LINES SKIPPED ***


More information about the Commits mailing list