diff options
-rw-r--r-- | dep/CMakeLists.txt | 2 | ||||
-rw-r--r-- | dep/PackageList.txt | 2 | ||||
-rw-r--r-- | dep/fmt/CMakeLists.txt (renamed from dep/cppformat/CMakeLists.txt) | 17 | ||||
-rw-r--r-- | dep/fmt/ChangeLog.rst (renamed from dep/cppformat/ChangeLog.rst) | 495 | ||||
-rw-r--r-- | dep/fmt/LICENSE.rst (renamed from dep/cppformat/LICENSE.rst) | 2 | ||||
-rw-r--r-- | dep/fmt/README.rst (renamed from dep/cppformat/README.rst) | 96 | ||||
-rw-r--r-- | dep/fmt/cppformat/format.cc (renamed from dep/cppformat/cppformat/format.cc) | 0 | ||||
-rw-r--r-- | dep/fmt/cppformat/format.h | 2 | ||||
-rw-r--r-- | dep/fmt/cppformat/posix.cc (renamed from dep/cppformat/cppformat/posix.cc) | 0 | ||||
-rw-r--r-- | dep/fmt/cppformat/posix.h | 2 | ||||
-rw-r--r-- | dep/fmt/fmt/format.cc | 940 | ||||
-rw-r--r-- | dep/fmt/fmt/format.h (renamed from dep/cppformat/cppformat/format.h) | 666 | ||||
-rw-r--r-- | dep/fmt/fmt/ostream.cc | 43 | ||||
-rw-r--r-- | dep/fmt/fmt/ostream.h | 115 | ||||
-rw-r--r-- | dep/fmt/fmt/posix.cc | 238 | ||||
-rw-r--r-- | dep/fmt/fmt/posix.h (renamed from dep/cppformat/cppformat/posix.h) | 35 | ||||
-rw-r--r-- | dep/fmt/fmt/time.h | 53 | ||||
-rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/common/Utilities/StringFormat.h | 2 |
19 files changed, 2215 insertions, 497 deletions
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index 86fdd8f38ad..1a02ca3ec5c 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -24,7 +24,7 @@ if(SERVERS OR TOOLS) add_subdirectory(zlib) add_subdirectory(g3dlite) add_subdirectory(recastnavigation) - add_subdirectory(cppformat) + add_subdirectory(fmt) add_subdirectory(SFMT) add_subdirectory(utf8cpp) add_subdirectory(valgrind) diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 574c27d2042..43416499c21 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -14,7 +14,7 @@ bzip2 (a freely available, patent free, high-quality data compressor) cppformat (type safe format library) https://github.com/cppformat/cppformat - Version: 5174b8ca281426af604b85fdf53be8a748b33f56 + Version: 3.0.1 7fa8f8fa48b0903deab5bb42e6760477173ac485 efws (Entropia File System Watcher - crossplatform file system watcher) https://bitbucket.org/SpartanJ/efsw diff --git a/dep/cppformat/CMakeLists.txt b/dep/fmt/CMakeLists.txt index 1cbff49b871..6d25fb49791 100644 --- a/dep/cppformat/CMakeLists.txt +++ b/dep/fmt/CMakeLists.txt @@ -16,22 +16,25 @@ else () endif () set(FMT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/format.h - ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/format.cc) + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/format.h + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/format.cc + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/ostream.h + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/ostream.cc + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/time.h) if (HAVE_OPEN) set(FMT_SOURCES ${FMT_SOURCES} - ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/posix.h - ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/posix.cc) + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/posix.h + ${CMAKE_CURRENT_SOURCE_DIR}/fmt/posix.cc) endif() -add_library(cppformat STATIC ${FMT_SOURCES}) +add_library(fmt STATIC ${FMT_SOURCES}) -target_include_directories(cppformat +target_include_directories(fmt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -set_target_properties(cppformat +set_target_properties(fmt PROPERTIES FOLDER "dep") diff --git a/dep/cppformat/ChangeLog.rst b/dep/fmt/ChangeLog.rst index d2a77f8712f..f4df68b6a12 100644 --- a/dep/cppformat/ChangeLog.rst +++ b/dep/fmt/ChangeLog.rst @@ -1,3 +1,232 @@ +3.0.1 - 2016-11-01 +------------------ +* Fixed handling of thousands seperator (`#353 <https://github.com/fmtlib/fmt/issues/353>`_) + +* Fixed handling of ``unsigned char`` strings (`#373 <https://github.com/fmtlib/fmt/issues/373>`_) + +* Corrected buffer growth when formatting time (`#367 <https://github.com/fmtlib/fmt/issues/367>`_) + +* Removed warnings under MSVC and clang (`#318 <https://github.com/fmtlib/fmt/issues/318>`_, `#250 <https://github.com/fmtlib/fmt/issues/250>`_, also merged `#385 <https://github.com/fmtlib/fmt/pull/385>`_ and `#361 <https://github.com/fmtlib/fmt/pull/361>`_). Thanks `@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_ and `@nmoehrle (Nils Moehrle) <https://github.com/nmoehrle>`_. + +* Fixed compilation issues under Android (`#327 <https://github.com/fmtlib/fmt/pull/327>`_, `#345 <https://github.com/fmtlib/fmt/issues/345>`_ and `#381 <https://github.com/fmtlib/fmt/pull/381>`_), FreeBSD (`#358 <https://github.com/fmtlib/fmt/pull/358>`_), Cygwin (`#388 <https://github.com/fmtlib/fmt/issues/388>`_), MinGW (`#355 <https://github.com/fmtlib/fmt/issues/355>`_) as well as other issues (`#350 <https://github.com/fmtlib/fmt/issues/350>`_, `#366 <https://github.com/fmtlib/fmt/issues/355>`_, `#348 <https://github.com/fmtlib/fmt/pull/348>`_, `#402 <https://github.com/fmtlib/fmt/pull/402>`_, `#405 <https://github.com/fmtlib/fmt/pull/405>`_). Thanks to `@dpantele (Dmitry) <https://github.com/dpantele>`_, `@hghwng (Hugh Wang) <https://github.com/hghwng>`_, `@arvedarved (Tilman Keskinöz) <https://github.com/arvedarved>`_, `@LogicalKnight (Sean) <https://github.com/LogicalKnight>`_ and `@JanHellwig (Jan Hellwig) <https://github.com/janhellwig>`_. + +* Fixed some documentation issues and extended specification (`#320 <https://github.com/fmtlib/fmt/issues/320>`_, `#333 <https://github.com/fmtlib/fmt/pull/333>`_, `#347 <https://github.com/fmtlib/fmt/issues/347>`_, `#362 <https://github.com/fmtlib/fmt/pull/362>`_). Thanks to `@smellman (Taro Matsuzawa aka. btm) <https://github.com/smellman>`_. + +3.0.0 - 2016-05-07 +------------------ + +* The project has been renamed from C++ Format (cppformat) to fmt for + consistency with the used namespace and macro prefix + (`#307 <https://github.com/fmtlib/fmt/issues/307>`_). + Library headers are now located in the ``fmt`` directory: + + .. code:: c++ + + #include "fmt/format.h" + + Including ``format.h`` from the ``cppformat`` directory is deprecated + but works via a proxy header which will be removed in the next major version. + + The documentation is now available at http://fmtlib.net. + +* Added support for `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like + `date and time formatting <http://fmtlib.net/3.0.0/api.html#date-and-time-formatting>`_ + (`#283 <https://github.com/fmtlib/fmt/issues/283>`_): + + .. code:: c++ + + #include "fmt/time.h" + + std::time_t t = std::time(nullptr); + // Prints "The date is 2016-04-29." (with the current date) + fmt::print("The date is {:%Y-%m-%d}.", *std::localtime(&t)); + +* ``std::ostream`` support including formatting of user-defined types that provide + overloaded ``operator<<`` has been moved to ``fmt/ostream.h``: + + .. code:: c++ + + #include "fmt/ostream.h" + + class Date { + int year_, month_, day_; + public: + Date(int year, int month, int day) : year_(year), month_(month), day_(day) {} + + friend std::ostream &operator<<(std::ostream &os, const Date &d) { + return os << d.year_ << '-' << d.month_ << '-' << d.day_; + } + }; + + std::string s = fmt::format("The date is {}", Date(2012, 12, 9)); + // s == "The date is 2012-12-9" + +* Added support for `custom argument formatters + <http://fmtlib.net/3.0.0/api.html#argument-formatters>`_ + (`#235 <https://github.com/fmtlib/fmt/issues/235>`_). + +* Added support for locale-specific integer formatting with the ``n`` specifier + (`#305 <https://github.com/fmtlib/fmt/issues/305>`_): + + .. code:: c++ + + std::setlocale(LC_ALL, "en_US.utf8"); + fmt::print("cppformat: {:n}\n", 1234567); // prints 1,234,567 + +* Sign is now preserved when formatting an integer with an incorrect ``printf`` + format specifier (`#265 <https://github.com/fmtlib/fmt/issues/265>`_): + + .. code:: c++ + + fmt::printf("%lld", -42); // prints -42 + + Note that it would be an undefined behavior in ``std::printf``. + +* Length modifiers such as ``ll`` are now optional in printf formatting + functions and the correct type is determined automatically + (`#255 <https://github.com/fmtlib/fmt/issues/255>`_): + + .. code:: c++ + + fmt::printf("%d", std::numeric_limits<long long>::max()); + + Note that it would be an undefined behavior in ``std::printf``. + +* Added initial support for custom formatters + (`#231 <https://github.com/fmtlib/fmt/issues/231>`_). + +* Fixed detection of user-defined literal support on Intel C++ compiler + (`#311 <https://github.com/fmtlib/fmt/issues/311>`_, + `#312 <https://github.com/fmtlib/fmt/pull/312>`_). + Thanks to `@dean0x7d (Dean Moldovan) <https://github.com/dean0x7d>`_ and + `@speth (Ray Speth) <https://github.com/speth>`_. + +* Reduced compile time + (`#243 <https://github.com/fmtlib/fmt/pull/243>`_, + `#249 <https://github.com/fmtlib/fmt/pull/249>`_, + `#317 <https://github.com/fmtlib/fmt/issues/317>`_): + + .. image:: https://cloud.githubusercontent.com/assets/4831417/11614060/ + b9e826d2-9c36-11e5-8666-d4131bf503ef.png + + .. image:: https://cloud.githubusercontent.com/assets/4831417/11614080/ + 6ac903cc-9c37-11e5-8165-26df6efae364.png + + Thanks to `@dean0x7d (Dean Moldovan) <https://github.com/dean0x7d>`_. + +* Compile test fixes (`#313 <https://github.com/fmtlib/fmt/pull/313>`_). + Thanks to `@dean0x7d (Dean Moldovan) <https://github.com/dean0x7d>`_. + +* Documentation fixes (`#239 <https://github.com/fmtlib/fmt/pull/239>`_, + `#248 <https://github.com/fmtlib/fmt/issues/248>`_, + `#252 <https://github.com/fmtlib/fmt/issues/252>`_, + `#258 <https://github.com/fmtlib/fmt/pull/258>`_, + `#260 <https://github.com/fmtlib/fmt/issues/260>`_, + `#301 <https://github.com/fmtlib/fmt/issues/301>`_, + `#309 <https://github.com/fmtlib/fmt/pull/309>`_). + Thanks to `@ReadmeCritic <https://github.com/ReadmeCritic>`_ + `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_ and + `@jwilk (Jakub Wilk) <https://github.com/jwilk>`_. + +* Fixed compiler and sanitizer warnings ( + `#244 <https://github.com/fmtlib/fmt/issues/244>`_, + `#256 <https://github.com/fmtlib/fmt/pull/256>`_, + `#259 <https://github.com/fmtlib/fmt/pull/259>`_, + `#263 <https://github.com/fmtlib/fmt/issues/263>`_, + `#274 <https://github.com/fmtlib/fmt/issues/274>`_, + `#277 <https://github.com/fmtlib/fmt/pull/277>`_, + `#286 <https://github.com/fmtlib/fmt/pull/286>`_, + `#291 <https://github.com/fmtlib/fmt/issues/291>`_, + `#296 <https://github.com/fmtlib/fmt/issues/296>`_, + `#308 <https://github.com/fmtlib/fmt/issues/308>`_) + Thanks to `@mwinterb <https://github.com/mwinterb>`_, + `@pweiskircher (Patrik Weiskircher) <https://github.com/pweiskircher>`_, + `@Naios <https://github.com/Naios>`_. + +* Improved compatibility with Windows Store apps + (`#280 <https://github.com/fmtlib/fmt/issues/280>`_, + `#285 <https://github.com/fmtlib/fmt/pull/285>`_) + Thanks to `@mwinterb <https://github.com/mwinterb>`_. + +* Added tests of compatibility with older C++ standards + (`#273 <https://github.com/fmtlib/fmt/pull/273>`_). + Thanks to `@niosHD <https://github.com/niosHD>`_. + +* Fixed Android build (`#271 <https://github.com/fmtlib/fmt/pull/271>`_). + Thanks to `@newnon <https://github.com/newnon>`_. + +* Changed ``ArgMap`` to be backed by a vector instead of a map. + (`#261 <https://github.com/fmtlib/fmt/issues/261>`_, + `#262 <https://github.com/fmtlib/fmt/pull/262>`_). + Thanks to `@mwinterb <https://github.com/mwinterb>`_. + +* Added ``fprintf`` overload that writes to a ``std::ostream`` + (`#251 <https://github.com/fmtlib/fmt/pull/251>`_). + Thanks to `nickhutchinson (Nicholas Hutchinson) <https://github.com/nickhutchinson>`_. + +* Export symbols when building a Windows DLL + (`#245 <https://github.com/fmtlib/fmt/pull/245>`_). + Thanks to `macdems (Maciek Dems) <https://github.com/macdems>`_. + +* Fixed compilation on Cygwin (`#304 <https://github.com/fmtlib/fmt/issues/304>`_). + +* Implemented a workaround for a bug in Apple LLVM version 4.2 of clang + (`#276 <https://github.com/fmtlib/fmt/issues/276>`_). + +* Implemented a workaround for Google Test bug + `#705 <https://github.com/google/googletest/issues/705>`_ on gcc 6 + (`#268 <https://github.com/fmtlib/fmt/issues/268>`_). + Thanks to `octoploid <https://github.com/octoploid>`_. + +* Removed Biicode support because the latter has been discontinued. + +2.1.1 - 2016-04-11 +------------------ + +* The install location for generated CMake files is now configurable via + the ``FMT_CMAKE_DIR`` CMake variable + (`#299 <https://github.com/fmtlib/fmt/pull/299>`_). + Thanks to `@niosHD <https://github.com/niosHD>`_. + +* Documentation fixes (`#252 <https://github.com/fmtlib/fmt/issues/252>`_). + +2.1.0 - 2016-03-21 +------------------ + +* Project layout and build system improvements + (`#267 <https://github.com/fmtlib/fmt/pull/267>`_): + + * The code have been moved to the ``cppformat`` directory. + Including ``format.h`` from the top-level directory is deprecated + but works via a proxy header which will be removed in the next + major version. + + * C++ Format CMake targets now have proper interface definitions. + + * Installed version of the library now supports the header-only + configuration. + + * Targets ``doc``, ``install``, and ``test`` are now disabled if C++ Format + is included as a CMake subproject. They can be enabled by setting + ``FMT_DOC``, ``FMT_INSTALL``, and ``FMT_TEST`` in the parent project. + + Thanks to `@niosHD <https://github.com/niosHD>`_. + +2.0.1 - 2016-03-13 +------------------ + +* Improved CMake find and package support + (`#264 <https://github.com/fmtlib/fmt/issues/264>`_). + Thanks to `@niosHD <https://github.com/niosHD>`_. + +* Fix compile error with Android NDK and mingw32 + (`#241 <https://github.com/fmtlib/fmt/issues/241>`_). + Thanks to `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_. + +* Documentation fixes + (`#248 <https://github.com/fmtlib/fmt/issues/248>`_, + `#260 <https://github.com/fmtlib/fmt/issues/260>`_). + 2.0.0 - 2015-12-01 ------------------ @@ -5,9 +234,9 @@ General ~~~~~~~ * [Breaking] Named arguments - (`#169 <https://github.com/cppformat/cppformat/pull/169>`_, - `#173 <https://github.com/cppformat/cppformat/pull/173>`_, - `#174 <https://github.com/cppformat/cppformat/pull/174>`_): + (`#169 <https://github.com/fmtlib/fmt/pull/169>`_, + `#173 <https://github.com/fmtlib/fmt/pull/173>`_, + `#174 <https://github.com/fmtlib/fmt/pull/174>`_): .. code:: c++ @@ -16,9 +245,9 @@ General Thanks to `@jamboree <https://github.com/jamboree>`_. * [Experimental] User-defined literals for format and named arguments - (`#204 <https://github.com/cppformat/cppformat/pull/204>`_, - `#206 <https://github.com/cppformat/cppformat/pull/206>`_, - `#207 <https://github.com/cppformat/cppformat/pull/207>`_): + (`#204 <https://github.com/fmtlib/fmt/pull/204>`_, + `#206 <https://github.com/fmtlib/fmt/pull/206>`_, + `#207 <https://github.com/fmtlib/fmt/pull/207>`_): .. code:: c++ @@ -29,11 +258,11 @@ General * [Breaking] Formatting of more than 16 arguments is now supported when using variadic templates - (`#141 <https://github.com/cppformat/cppformat/issues/141>`_). + (`#141 <https://github.com/fmtlib/fmt/issues/141>`_). Thanks to `@Shauren <https://github.com/Shauren>`_. * Runtime width specification - (`#168 <https://github.com/cppformat/cppformat/pull/168>`_): + (`#168 <https://github.com/fmtlib/fmt/pull/168>`_): .. code:: c++ @@ -43,10 +272,10 @@ General * [Breaking] Enums are now formatted with an overloaded ``std::ostream`` insertion operator (``operator<<``) if available - (`#232 <https://github.com/cppformat/cppformat/issues/232>`_). + (`#232 <https://github.com/fmtlib/fmt/issues/232>`_). * [Breaking] Changed default ``bool`` format to textual, "true" or "false" - (`#170 <https://github.com/cppformat/cppformat/issues/170>`_): + (`#170 <https://github.com/fmtlib/fmt/issues/170>`_): .. code:: c++ @@ -60,7 +289,7 @@ General * ``fmt::printf`` and ``fmt::sprintf`` now support formatting of ``bool`` with the ``%s`` specifier giving textual output, "true" or "false" - (`#223 <https://github.com/cppformat/cppformat/pull/223>`_): + (`#223 <https://github.com/fmtlib/fmt/pull/223>`_): .. code:: c++ @@ -69,10 +298,10 @@ General Thanks to `@LarsGullik <https://github.com/LarsGullik>`_. * [Breaking] ``signed char`` and ``unsigned char`` are now formatted as integers by default - (`#217 <https://github.com/cppformat/cppformat/pull/217>`_). + (`#217 <https://github.com/fmtlib/fmt/pull/217>`_). * [Breaking] Pointers to C strings can now be formatted with the ``p`` specifier - (`#223 <https://github.com/cppformat/cppformat/pull/223>`_): + (`#223 <https://github.com/fmtlib/fmt/pull/223>`_): .. code:: c++ @@ -82,12 +311,12 @@ General * [Breaking] ``fmt::printf`` and ``fmt::sprintf`` now print null pointers as ``(nil)`` and null strings as ``(null)`` for consistency with glibc - (`#226 <https://github.com/cppformat/cppformat/pull/226>`_). + (`#226 <https://github.com/fmtlib/fmt/pull/226>`_). Thanks to `@LarsGullik <https://github.com/LarsGullik>`_. * [Breaking] ``fmt::(s)printf`` now supports formatting of objects of user-defined types that provide an overloaded ``std::ostream`` insertion operator (``operator<<``) - (`#201 <https://github.com/cppformat/cppformat/issues/201>`_): + (`#201 <https://github.com/fmtlib/fmt/issues/201>`_): .. code:: c++ @@ -95,15 +324,15 @@ General * [Breaking] The ``Buffer`` template is now part of the public API and can be used to implement custom memory buffers - (`#140 <https://github.com/cppformat/cppformat/issues/140>`_). + (`#140 <https://github.com/fmtlib/fmt/issues/140>`_). Thanks to `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_. * [Breaking] Improved compatibility between ``BasicStringRef`` and `std::experimental::basic_string_view <http://en.cppreference.com/w/cpp/experimental/basic_string_view>`_ - (`#100 <https://github.com/cppformat/cppformat/issues/100>`_, - `#159 <https://github.com/cppformat/cppformat/issues/159>`_, - `#183 <https://github.com/cppformat/cppformat/issues/183>`_): + (`#100 <https://github.com/fmtlib/fmt/issues/100>`_, + `#159 <https://github.com/fmtlib/fmt/issues/159>`_, + `#183 <https://github.com/fmtlib/fmt/issues/183>`_): - Comparison operators now compare string content, not pointers - ``BasicStringRef::c_str`` replaced by ``BasicStringRef::data`` @@ -113,40 +342,40 @@ General ``BasicCStringRef``. * Dependency on pthreads introduced by Google Test is now optional - (`#185 <https://github.com/cppformat/cppformat/issues/185>`_). + (`#185 <https://github.com/fmtlib/fmt/issues/185>`_). * New CMake options ``FMT_DOC``, ``FMT_INSTALL`` and ``FMT_TEST`` to control generation of ``doc``, ``install`` and ``test`` targets respectively, on by default - (`#197 <https://github.com/cppformat/cppformat/issues/197>`_, - `#198 <https://github.com/cppformat/cppformat/issues/198>`_, - `#200 <https://github.com/cppformat/cppformat/issues/200>`_). + (`#197 <https://github.com/fmtlib/fmt/issues/197>`_, + `#198 <https://github.com/fmtlib/fmt/issues/198>`_, + `#200 <https://github.com/fmtlib/fmt/issues/200>`_). Thanks to `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_. * ``noexcept`` is now used when compiling with MSVC2015 - (`#215 <https://github.com/cppformat/cppformat/pull/215>`_). + (`#215 <https://github.com/fmtlib/fmt/pull/215>`_). Thanks to `@dmkrepo (Dmitriy) <https://github.com/dmkrepo>`_. * Added an option to disable use of ``windows.h`` when ``FMT_USE_WINDOWS_H`` is defined as 0 before including ``format.h`` - (`#171 <https://github.com/cppformat/cppformat/issues/171>`_). + (`#171 <https://github.com/fmtlib/fmt/issues/171>`_). Thanks to `@alfps (Alf P. Steinbach) <https://github.com/alfps>`_. * [Breaking] ``windows.h`` is now included with ``NOMINMAX`` unless ``FMT_WIN_MINMAX`` is defined. This is done to prevent breaking code using ``std::min`` and ``std::max`` and only affects the header-only configuration - (`#152 <https://github.com/cppformat/cppformat/issues/152>`_, - `#153 <https://github.com/cppformat/cppformat/pull/153>`_, - `#154 <https://github.com/cppformat/cppformat/pull/154>`_). + (`#152 <https://github.com/fmtlib/fmt/issues/152>`_, + `#153 <https://github.com/fmtlib/fmt/pull/153>`_, + `#154 <https://github.com/fmtlib/fmt/pull/154>`_). Thanks to `@DevO2012 <https://github.com/DevO2012>`_. * Improved support for custom character types - (`#171 <https://github.com/cppformat/cppformat/issues/171>`_). + (`#171 <https://github.com/fmtlib/fmt/issues/171>`_). Thanks to `@alfps (Alf P. Steinbach) <https://github.com/alfps>`_. * Added an option to disable use of IOStreams when ``FMT_USE_IOSTREAMS`` is defined as 0 before including ``format.h`` - (`#205 <https://github.com/cppformat/cppformat/issues/205>`_, - `#208 <https://github.com/cppformat/cppformat/pull/208>`_). + (`#205 <https://github.com/fmtlib/fmt/issues/205>`_, + `#208 <https://github.com/fmtlib/fmt/pull/208>`_). Thanks to `@JodiTheTigger <https://github.com/JodiTheTigger>`_. * Improved detection of ``isnan``, ``isinf`` and ``signbit``. @@ -155,31 +384,31 @@ Optimization ~~~~~~~~~~~~ * Made formatting of user-defined types more efficient with a custom stream buffer - (`#92 <https://github.com/cppformat/cppformat/issues/92>`_, - `#230 <https://github.com/cppformat/cppformat/pull/230>`_). + (`#92 <https://github.com/fmtlib/fmt/issues/92>`_, + `#230 <https://github.com/fmtlib/fmt/pull/230>`_). Thanks to `@NotImplemented <https://github.com/NotImplemented>`_. * Further improved performance of ``fmt::Writer`` on integer formatting and fixed a minor regression. Now it is ~7% faster than ``karma::generate`` on Karma's benchmark - (`#186 <https://github.com/cppformat/cppformat/issues/186>`_). + (`#186 <https://github.com/fmtlib/fmt/issues/186>`_). * [Breaking] Reduced `compiled code size - <https://github.com/cppformat/cppformat#compile-time-and-code-bloat>`_ - (`#143 <https://github.com/cppformat/cppformat/issues/143>`_, - `#149 <https://github.com/cppformat/cppformat/pull/149>`_). + <https://github.com/fmtlib/fmt#compile-time-and-code-bloat>`_ + (`#143 <https://github.com/fmtlib/fmt/issues/143>`_, + `#149 <https://github.com/fmtlib/fmt/pull/149>`_). Distribution ~~~~~~~~~~~~ * [Breaking] Headers are now installed in ``${CMAKE_INSTALL_PREFIX}/include/cppformat`` - (`#178 <https://github.com/cppformat/cppformat/issues/178>`_). + (`#178 <https://github.com/fmtlib/fmt/issues/178>`_). Thanks to `@jackyf (Eugene V. Lyubimkin) <https://github.com/jackyf>`_. * [Breaking] Changed the library name from ``format`` to ``cppformat`` for consistency with the project name and to avoid potential conflicts - (`#178 <https://github.com/cppformat/cppformat/issues/178>`_). + (`#178 <https://github.com/fmtlib/fmt/issues/178>`_). Thanks to `@jackyf (Eugene V. Lyubimkin) <https://github.com/jackyf>`_. * C++ Format is now available in `Debian <https://www.debian.org/>`_ GNU/Linux @@ -187,7 +416,7 @@ Distribution `sid <https://packages.debian.org/source/sid/cppformat>`_) and derived distributions such as `Ubuntu <https://launchpad.net/ubuntu/+source/cppformat>`_ 15.10 and later - (`#155 <https://github.com/cppformat/cppformat/issues/155>`_):: + (`#155 <https://github.com/fmtlib/fmt/issues/155>`_):: $ sudo apt-get install libcppformat1-dev @@ -197,7 +426,7 @@ Distribution are now available. Thanks to Dave Johansen. * C++ Format can now be installed via `Homebrew <http://brew.sh/>`_ on OS X - (`#157 <https://github.com/cppformat/cppformat/issues/157>`_):: + (`#157 <https://github.com/fmtlib/fmt/issues/157>`_):: $ brew install cppformat @@ -208,47 +437,47 @@ Documentation * Migrated from ReadTheDocs to GitHub Pages for better responsiveness and reliability - (`#128 <https://github.com/cppformat/cppformat/issues/128>`_). + (`#128 <https://github.com/fmtlib/fmt/issues/128>`_). New documentation address is http://cppformat.github.io/. * Added `Building the documentation - <http://cppformat.github.io/dev/usage.html#building-the-documentation>`_ + <http://fmtlib.net/2.0.0/usage.html#building-the-documentation>`_ section to the documentation. * Documentation build script is now compatible with Python 3 and newer pip versions. - (`#189 <https://github.com/cppformat/cppformat/pull/189>`_, - `#209 <https://github.com/cppformat/cppformat/issues/209>`_). + (`#189 <https://github.com/fmtlib/fmt/pull/189>`_, + `#209 <https://github.com/fmtlib/fmt/issues/209>`_). Thanks to `@JodiTheTigger <https://github.com/JodiTheTigger>`_ and `@xentec <https://github.com/xentec>`_. * Documentation fixes and improvements - (`#36 <https://github.com/cppformat/cppformat/issues/36>`_, - `#75 <https://github.com/cppformat/cppformat/issues/75>`_, - `#125 <https://github.com/cppformat/cppformat/issues/125>`_, - `#160 <https://github.com/cppformat/cppformat/pull/160>`_, - `#161 <https://github.com/cppformat/cppformat/pull/161>`_, - `#162 <https://github.com/cppformat/cppformat/issues/162>`_, - `#165 <https://github.com/cppformat/cppformat/issues/165>`_, - `#210 <https://github.com/cppformat/cppformat/issues/210>`_). + (`#36 <https://github.com/fmtlib/fmt/issues/36>`_, + `#75 <https://github.com/fmtlib/fmt/issues/75>`_, + `#125 <https://github.com/fmtlib/fmt/issues/125>`_, + `#160 <https://github.com/fmtlib/fmt/pull/160>`_, + `#161 <https://github.com/fmtlib/fmt/pull/161>`_, + `#162 <https://github.com/fmtlib/fmt/issues/162>`_, + `#165 <https://github.com/fmtlib/fmt/issues/165>`_, + `#210 <https://github.com/fmtlib/fmt/issues/210>`_). Thanks to `@syohex (Syohei YOSHIDA) <https://github.com/syohex>`_ and bug reporters. * Fixed out-of-tree documentation build - (`#177 <https://github.com/cppformat/cppformat/issues/177>`_). + (`#177 <https://github.com/fmtlib/fmt/issues/177>`_). Thanks to `@jackyf (Eugene V. Lyubimkin) <https://github.com/jackyf>`_. Fixes ~~~~~ * Fixed ``initializer_list`` detection - (`#136 <https://github.com/cppformat/cppformat/issues/136>`_). + (`#136 <https://github.com/fmtlib/fmt/issues/136>`_). Thanks to `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_. * [Breaking] Fixed formatting of enums with numeric format specifiers in ``fmt::(s)printf`` - (`#131 <https://github.com/cppformat/cppformat/issues/131>`_, - `#139 <https://github.com/cppformat/cppformat/issues/139>`_): + (`#131 <https://github.com/fmtlib/fmt/issues/131>`_, + `#139 <https://github.com/fmtlib/fmt/issues/139>`_): .. code:: c++ @@ -258,51 +487,53 @@ Fixes Thanks to `@Naios <https://github.com/Naios>`_. * Improved compatibility with old versions of MinGW - (`#129 <https://github.com/cppformat/cppformat/issues/129>`_, - `#130 <https://github.com/cppformat/cppformat/pull/130>`_, - `#132 <https://github.com/cppformat/cppformat/issues/132>`_). + (`#129 <https://github.com/fmtlib/fmt/issues/129>`_, + `#130 <https://github.com/fmtlib/fmt/pull/130>`_, + `#132 <https://github.com/fmtlib/fmt/issues/132>`_). Thanks to `@cstamford (Christopher Stamford) <https://github.com/cstamford>`_. * Fixed a compile error on MSVC with disabled exceptions - (`#144 <https://github.com/cppformat/cppformat/issues/144>`_). + (`#144 <https://github.com/fmtlib/fmt/issues/144>`_). * Added a workaround for broken implementation of variadic templates in MSVC2012 - (`#148 <https://github.com/cppformat/cppformat/issues/148>`_). + (`#148 <https://github.com/fmtlib/fmt/issues/148>`_). * Placed the anonymous namespace within ``fmt`` namespace for the header-only configuration - (`#171 <https://github.com/cppformat/cppformat/issues/171>`_). + (`#171 <https://github.com/fmtlib/fmt/issues/171>`_). Thanks to `@alfps (Alf P. Steinbach) <https://github.com/alfps>`_. * Fixed issues reported by Coverity Scan - (`#187 <https://github.com/cppformat/cppformat/issues/187>`_, - `#192 <https://github.com/cppformat/cppformat/issues/192>`_). + (`#187 <https://github.com/fmtlib/fmt/issues/187>`_, + `#192 <https://github.com/fmtlib/fmt/issues/192>`_). * Implemented a workaround for a name lookup bug in MSVC2010 - (`#188 <https://github.com/cppformat/cppformat/issues/188>`_). + (`#188 <https://github.com/fmtlib/fmt/issues/188>`_). * Fixed compiler warnings - (`#95 <https://github.com/cppformat/cppformat/issues/95>`_, - `#96 <https://github.com/cppformat/cppformat/issues/96>`_, - `#114 <https://github.com/cppformat/cppformat/pull/114>`_, - `#135 <https://github.com/cppformat/cppformat/issues/135>`_, - `#142 <https://github.com/cppformat/cppformat/issues/142>`_, - `#145 <https://github.com/cppformat/cppformat/issues/145>`_, - `#146 <https://github.com/cppformat/cppformat/issues/146>`_, - `#158 <https://github.com/cppformat/cppformat/issues/158>`_, - `#163 <https://github.com/cppformat/cppformat/issues/163>`_, - `#175 <https://github.com/cppformat/cppformat/issues/175>`_, - `#190 <https://github.com/cppformat/cppformat/issues/190>`_, - `#191 <https://github.com/cppformat/cppformat/pull/191>`_, - `#194 <https://github.com/cppformat/cppformat/issues/194>`_, - `#196 <https://github.com/cppformat/cppformat/pull/196>`_, - `#216 <https://github.com/cppformat/cppformat/issues/216>`_, - `#218 <https://github.com/cppformat/cppformat/pull/218>`_, - `#220 <https://github.com/cppformat/cppformat/pull/220>`_, - `#229 <https://github.com/cppformat/cppformat/pull/229>`_, - `#233 <https://github.com/cppformat/cppformat/issues/233>`_, - `#234 <https://github.com/cppformat/cppformat/issues/234>`_, - `#236 <https://github.com/cppformat/cppformat/pull/236>`_). + (`#95 <https://github.com/fmtlib/fmt/issues/95>`_, + `#96 <https://github.com/fmtlib/fmt/issues/96>`_, + `#114 <https://github.com/fmtlib/fmt/pull/114>`_, + `#135 <https://github.com/fmtlib/fmt/issues/135>`_, + `#142 <https://github.com/fmtlib/fmt/issues/142>`_, + `#145 <https://github.com/fmtlib/fmt/issues/145>`_, + `#146 <https://github.com/fmtlib/fmt/issues/146>`_, + `#158 <https://github.com/fmtlib/fmt/issues/158>`_, + `#163 <https://github.com/fmtlib/fmt/issues/163>`_, + `#175 <https://github.com/fmtlib/fmt/issues/175>`_, + `#190 <https://github.com/fmtlib/fmt/issues/190>`_, + `#191 <https://github.com/fmtlib/fmt/pull/191>`_, + `#194 <https://github.com/fmtlib/fmt/issues/194>`_, + `#196 <https://github.com/fmtlib/fmt/pull/196>`_, + `#216 <https://github.com/fmtlib/fmt/issues/216>`_, + `#218 <https://github.com/fmtlib/fmt/pull/218>`_, + `#220 <https://github.com/fmtlib/fmt/pull/220>`_, + `#229 <https://github.com/fmtlib/fmt/pull/229>`_, + `#233 <https://github.com/fmtlib/fmt/issues/233>`_, + `#234 <https://github.com/fmtlib/fmt/issues/234>`_, + `#236 <https://github.com/fmtlib/fmt/pull/236>`_, + `#281 <https://github.com/fmtlib/fmt/issues/281>`_, + `#289 <https://github.com/fmtlib/fmt/issues/289>`_). Thanks to `@seanmiddleditch (Sean Middleditch) <https://github.com/seanmiddleditch>`_, `@dixlorenz (Dix Lorenz) <https://github.com/dixlorenz>`_, `@CarterLi (李通洲) <https://github.com/CarterLi>`_, @@ -319,36 +550,36 @@ Fixes * Fixed portability issues (mostly causing test failures) on ARM, ppc64, ppc64le, s390x and SunOS 5.11 i386 ( - `#138 <https://github.com/cppformat/cppformat/issues/138>`_, - `#179 <https://github.com/cppformat/cppformat/issues/179>`_, - `#180 <https://github.com/cppformat/cppformat/issues/180>`_, - `#202 <https://github.com/cppformat/cppformat/issues/202>`_, - `#225 <https://github.com/cppformat/cppformat/issues/225>`_, + `#138 <https://github.com/fmtlib/fmt/issues/138>`_, + `#179 <https://github.com/fmtlib/fmt/issues/179>`_, + `#180 <https://github.com/fmtlib/fmt/issues/180>`_, + `#202 <https://github.com/fmtlib/fmt/issues/202>`_, + `#225 <https://github.com/fmtlib/fmt/issues/225>`_, `Red Hat Bugzilla Bug 1260297 <https://bugzilla.redhat.com/show_bug.cgi?id=1260297>`_). Thanks to `@Naios <https://github.com/Naios>`_, `@jackyf (Eugene V. Lyubimkin) <https://github.com/jackyf>`_ and Dave Johansen. * Fixed a name conflict with macro ``free`` defined in ``crtdbg.h`` when ``_CRTDBG_MAP_ALLOC`` is set - (`#211 <https://github.com/cppformat/cppformat/issues/211>`_). + (`#211 <https://github.com/fmtlib/fmt/issues/211>`_). * Fixed shared library build on OS X - (`#212 <https://github.com/cppformat/cppformat/pull/212>`_). + (`#212 <https://github.com/fmtlib/fmt/pull/212>`_). Thanks to `@dean0x7d (Dean Moldovan) <https://github.com/dean0x7d>`_. * Fixed an overload conflict on MSVC when ``/Zc:wchar_t-`` option is specified - (`#214 <https://github.com/cppformat/cppformat/pull/214>`_). + (`#214 <https://github.com/fmtlib/fmt/pull/214>`_). Thanks to `@slavanap (Vyacheslav Napadovsky) <https://github.com/slavanap>`_. * Improved compatibility with MSVC 2008 - (`#236 <https://github.com/cppformat/cppformat/pull/236>`_). + (`#236 <https://github.com/fmtlib/fmt/pull/236>`_). Thanks to `@Jopie64 (Johan) <https://github.com/Jopie64>`_. * Improved compatibility with bcc32 - (`#227 <https://github.com/cppformat/cppformat/issues/227>`_). + (`#227 <https://github.com/fmtlib/fmt/issues/227>`_). * Fixed ``static_assert`` detection on Clang - (`#228 <https://github.com/cppformat/cppformat/pull/228>`_). + (`#228 <https://github.com/fmtlib/fmt/pull/228>`_). Thanks to `@dean0x7d (Dean Moldovan) <https://github.com/dean0x7d>`_. 1.1.0 - 2015-03-06 @@ -356,8 +587,8 @@ Fixes * Added ``BasicArrayWriter``, a class template that provides operations for formatting and writing data into a fixed-size array - (`#105 <https://github.com/cppformat/cppformat/issues/105>`_ and - `#122 <https://github.com/cppformat/cppformat/issues/122>`_): + (`#105 <https://github.com/fmtlib/fmt/issues/105>`_ and + `#122 <https://github.com/fmtlib/fmt/issues/122>`_): .. code:: c++ @@ -369,58 +600,58 @@ Fixes <http://www.polserver.com/>`_ to the list of notable projects using C++ Format. * C++ Format now uses MSVC intrinsics for better formatting performance - (`#115 <https://github.com/cppformat/cppformat/pull/115>`_, - `#116 <https://github.com/cppformat/cppformat/pull/116>`_, - `#118 <https://github.com/cppformat/cppformat/pull/118>`_ and - `#121 <https://github.com/cppformat/cppformat/pull/121>`_). + (`#115 <https://github.com/fmtlib/fmt/pull/115>`_, + `#116 <https://github.com/fmtlib/fmt/pull/116>`_, + `#118 <https://github.com/fmtlib/fmt/pull/118>`_ and + `#121 <https://github.com/fmtlib/fmt/pull/121>`_). Previously these optimizations where only used on GCC and Clang. Thanks to `@CarterLi <https://github.com/CarterLi>`_ and `@objectx <https://github.com/objectx>`_. -* CMake install target (`#119 <https://github.com/cppformat/cppformat/pull/119>`_). +* CMake install target (`#119 <https://github.com/fmtlib/fmt/pull/119>`_). Thanks to `@TrentHouliston <https://github.com/TrentHouliston>`_. You can now install C++ Format with ``make install`` command. * Improved `Biicode <http://www.biicode.com/>`_ support - (`#98 <https://github.com/cppformat/cppformat/pull/98>`_ and - `#104 <https://github.com/cppformat/cppformat/pull/104>`_). Thanks to + (`#98 <https://github.com/fmtlib/fmt/pull/98>`_ and + `#104 <https://github.com/fmtlib/fmt/pull/104>`_). Thanks to `@MariadeAnton <https://github.com/MariadeAnton>`_ and `@franramirez688 <https://github.com/franramirez688>`_. -* Improved support for bulding with `Android NDK +* Improved support for building with `Android NDK <https://developer.android.com/tools/sdk/ndk/index.html>`_ - (`#107 <https://github.com/cppformat/cppformat/pull/107>`_). + (`#107 <https://github.com/fmtlib/fmt/pull/107>`_). Thanks to `@newnon <https://github.com/newnon>`_. - The `android-ndk-example <https://github.com/cppformat/android-ndk-example>`_ + The `android-ndk-example <https://github.com/fmtlib/android-ndk-example>`_ repository provides and example of using C++ Format with Android NDK: - .. image:: https://raw.githubusercontent.com/cppformat/android-ndk-example/ + .. image:: https://raw.githubusercontent.com/fmtlib/android-ndk-example/ master/screenshot.png * Improved documentation of ``SystemError`` and ``WindowsError`` - (`#54 <https://github.com/cppformat/cppformat/issues/54>`_). + (`#54 <https://github.com/fmtlib/fmt/issues/54>`_). * Various code improvements - (`#110 <https://github.com/cppformat/cppformat/pull/110>`_, - `#111 <https://github.com/cppformat/cppformat/pull/111>`_ - `#112 <https://github.com/cppformat/cppformat/pull/112>`_). + (`#110 <https://github.com/fmtlib/fmt/pull/110>`_, + `#111 <https://github.com/fmtlib/fmt/pull/111>`_ + `#112 <https://github.com/fmtlib/fmt/pull/112>`_). Thanks to `@CarterLi <https://github.com/CarterLi>`_. * Improved compile-time errors when formatting wide into narrow strings - (`#117 <https://github.com/cppformat/cppformat/issues/117>`_). + (`#117 <https://github.com/fmtlib/fmt/issues/117>`_). * Fixed ``BasicWriter::write`` without formatting arguments when C++11 support - is disabled (`#109 <https://github.com/cppformat/cppformat/issues/109>`_). + is disabled (`#109 <https://github.com/fmtlib/fmt/issues/109>`_). * Fixed header-only build on OS X with GCC 4.9 - (`#124 <https://github.com/cppformat/cppformat/issues/124>`_). + (`#124 <https://github.com/fmtlib/fmt/issues/124>`_). -* Fixed packaging issues (`#94 <https://github.com/cppformat/cppformat/issues/94>`_). +* Fixed packaging issues (`#94 <https://github.com/fmtlib/fmt/issues/94>`_). -* Added `changelog <https://github.com/cppformat/cppformat/blob/master/ChangeLog.rst>`_ - (`#103 <https://github.com/cppformat/cppformat/issues/103>`_). +* Added `changelog <https://github.com/fmtlib/fmt/blob/master/ChangeLog.rst>`_ + (`#103 <https://github.com/fmtlib/fmt/issues/103>`_). 1.0.0 - 2015-02-05 ------------------ @@ -435,29 +666,29 @@ Fixes * Compute string length in the constructor of ``BasicStringRef`` instead of the ``size`` method - (`#79 <https://github.com/cppformat/cppformat/issues/79>`_). + (`#79 <https://github.com/fmtlib/fmt/issues/79>`_). This eliminates size computation for string literals on reasonable optimizing compilers. * Fix formatting of types with overloaded ``operator <<`` for ``std::wostream`` - (`#86 <https://github.com/cppformat/cppformat/issues/86>`_): + (`#86 <https://github.com/fmtlib/fmt/issues/86>`_): .. code:: c++ fmt::format(L"The date is {0}", Date(2012, 12, 9)); * Fix linkage of tests on Arch Linux - (`#89 <https://github.com/cppformat/cppformat/issues/89>`_). + (`#89 <https://github.com/fmtlib/fmt/issues/89>`_). * Allow precision specifier for non-float arguments - (`#90 <https://github.com/cppformat/cppformat/issues/90>`_): + (`#90 <https://github.com/fmtlib/fmt/issues/90>`_): .. code:: c++ fmt::print("{:.3}\n", "Carpet"); // prints "Car" * Fix build on Android NDK - (`#93 <https://github.com/cppformat/cppformat/issues/93>`_) + (`#93 <https://github.com/fmtlib/fmt/issues/93>`_) * Improvements to documentation build procedure. @@ -498,17 +729,17 @@ Fixes This doesn't affect the formatting API. * Support for custom memory allocators - (`#69 <https://github.com/cppformat/cppformat/issues/69>`_) + (`#69 <https://github.com/fmtlib/fmt/issues/69>`_) * Formatting functions now accept `signed char` and `unsigned char` strings as - arguments (`#73 <https://github.com/cppformat/cppformat/issues/73>`_): + arguments (`#73 <https://github.com/fmtlib/fmt/issues/73>`_): .. code:: c++ auto s = format("GLSL version: {}", glGetString(GL_VERSION)); * Reduced code bloat. According to the new `benchmark results - <https://github.com/cppformat/cppformat#compile-time-and-code-bloat>`_, + <https://github.com/fmtlib/fmt#compile-time-and-code-bloat>`_, cppformat is close to ``printf`` and by the order of magnitude better than Boost Format in terms of compiled code size. @@ -538,7 +769,7 @@ Fixes fmt::printf("%1$s, %3$d %2$s", weekday, month, day); * Arguments of ``char`` type can now be formatted as integers - (Issue `#55 <https://github.com/cppformat/cppformat/issues/55>`_): + (Issue `#55 <https://github.com/fmtlib/fmt/issues/55>`_): .. code:: c++ @@ -574,7 +805,7 @@ Fixes Apart from a more natural syntax, this also improves performance as there is no need to construct temporary formatter objects and control arguments' - lifetimes. Because the wrapper functions are very ligthweight, this doesn't + lifetimes. Because the wrapper functions are very lightweight, this doesn't cause code bloat even in pre-C++11 mode. * Simplified common case of formatting an ``std::string``. Now it requires a @@ -607,7 +838,7 @@ Fixes Now all public functions are lowercase following the standard library conventions. Previously it was a combination of lowercase and CapitalizedWords. - Issue `#50 <https://github.com/cppformat/cppformat/issues/50>`_. + Issue `#50 <https://github.com/fmtlib/fmt/issues/50>`_. * Old functions are marked as deprecated and will be removed in the next release. diff --git a/dep/cppformat/LICENSE.rst b/dep/fmt/LICENSE.rst index b1c96ca02c8..eb6be6503e9 100644 --- a/dep/cppformat/LICENSE.rst +++ b/dep/fmt/LICENSE.rst @@ -1,4 +1,4 @@ -Copyright (c) 2012 - 2015, Victor Zverovich +Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. diff --git a/dep/cppformat/README.rst b/dep/fmt/README.rst index e859f909466..846d0eb0979 100644 --- a/dep/cppformat/README.rst +++ b/dep/fmt/README.rst @@ -1,62 +1,64 @@ -C++ Format -========== +{fmt} +===== -.. image:: https://travis-ci.org/cppformat/cppformat.png?branch=master - :target: https://travis-ci.org/cppformat/cppformat +.. 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/qk0bhyhqp1ekpat8 - :target: https://ci.appveyor.com/project/vitaut/cppformat +.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v + :target: https://ci.appveyor.com/project/vitaut/fmt .. image:: https://badges.gitter.im/Join%20Chat.svg - :alt: Join the chat at https://gitter.im/cppformat/cppformat - :target: https://gitter.im/cppformat/cppformat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge + :alt: Join the chat at https://gitter.im/fmtlib/fmt + :target: https://gitter.im/fmtlib/fmt -C++ Format is an open-source formatting library for C++. +**fmt** is an open-source formatting library for C++. It can be used as a safe alternative to printf or as a fast alternative to IOStreams. -`Documentation <http://cppformat.github.io/latest/>`_ +`Documentation <http://fmtlib.net/latest/>`_ Features -------- -* Two APIs: faster concatenation-based write API and slower (but still - very fast) replacement-based format API with positional arguments for - localization. +* Two APIs: faster concatenation-based `write API + <http://fmtlib.net/latest/api.html#write-api>`_ and slower, + but still very fast, replacement-based `format API + <http://fmtlib.net/latest/api.html#format-api>`_ with positional arguments + for localization. * Write API similar to the one used by IOStreams but stateless allowing faster implementation. * Format API with `format string syntax - <http://cppformat.github.io/latest/syntax.html>`_ + <http://fmtlib.net/latest/syntax.html>`_ similar to the one used by `str.format <https://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python. * Safe `printf implementation - <http://cppformat.github.io/latest/api.html#printf-formatting-functions>`_ + <http://fmtlib.net/latest/api.html#printf-formatting-functions>`_ including the POSIX extension for positional arguments. * Support for user-defined types. * High speed: performance of the format API is close to that of glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_ - and better than performance of IOStreams. See `Speed tests`_ and + and better than the performance of IOStreams. See `Speed tests`_ and `Fast integer to string conversion in C++ <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_. * Small code size both in terms of source code (format consists of a single header file and a single source file) and compiled code. See `Compile time and code bloat`_. * Reliability: the library has an extensive set of `unit tests - <https://github.com/cppformat/cppformat/tree/master/test>`_. + <https://github.com/fmtlib/fmt/tree/master/test>`_. * Safety: the library is fully type safe, errors in format strings are reported using exceptions, automatic memory management prevents buffer overflow errors. * Ease of use: small self-contained code base, no external dependencies, permissive BSD `license - <https://github.com/cppformat/cppformat/blob/master/LICENSE.rst>`_ -* `Portability <http://cppformat.github.io#portability>`_ with consistent output + <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_ +* `Portability <http://fmtlib.net/latest/index.html#portability>`_ with consistent output across platforms and support for older compilers. * Clean warning-free codebase even on high warning levels (-Wall -Wextra -pedantic). * Support for wide strings. * Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro. -See the `documentation <http://cppformat.github.io/latest/>`_ for more details. +See the `documentation <http://fmtlib.net/latest/>`_ for more details. Examples -------- @@ -75,7 +77,7 @@ Arguments can be accessed by position and arguments' indices can be repeated: std::string s = fmt::format("{0}{1}{0}", "abra", "cad"); // s == "abracadabra" -C++ Format can be used as a safe portable replacement for ``itoa``: +fmt can be used as a safe portable replacement for ``itoa``: .. code:: c++ @@ -89,6 +91,8 @@ An object of any user-defined type for which there is an overloaded .. code:: c++ + #include "fmt/ostream.h" + class Date { int year_, month_, day_; public: @@ -103,10 +107,10 @@ An object of any user-defined type for which there is an overloaded // s == "The date is 2012-12-9" You can use the `FMT_VARIADIC -<http://cppformat.github.io/latest/api.html#utilities>`_ +<http://fmtlib.net/latest/api.html#utilities>`_ macro to create your own functions similar to `format -<http://cppformat.github.io/latest/api.html#format>`_ and -`print <http://cppformat.github.io/latest/api.html#print>`_ +<http://fmtlib.net/latest/api.html#format>`_ and +`print <http://fmtlib.net/latest/api.html#print>`_ which take arbitrary arguments: .. code:: c++ @@ -132,6 +136,8 @@ Projects using this library * `AMPL/MP <https://github.com/ampl/mp>`_: An open-source library for mathematical programming +* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle + * `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_: Player vs Player Gaming Network with tweaks @@ -158,6 +164,12 @@ Projects using this library * `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_: Business intelligence software +* `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store that can handle + 1 million transactions per second on a single server + +* `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ framework for + high-performance server applications on modern hardware + * `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library * `Stellar <https://www.stellar.org/>`_: Financial platform @@ -170,7 +182,7 @@ Projects using this library If you are aware of other projects using this library, please let me know by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an -`issue <https://github.com/cppformat/cppformat/issues>`_. +`issue <https://github.com/fmtlib/fmt/issues>`_. Motivation ---------- @@ -281,14 +293,14 @@ The following speed tests results were generated by building runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or equivalent is filled 2000000 times with output sent to ``/dev/null``; for further details see the `source -<https://github.com/cppformat/format-benchmark/blob/master/tinyformat_test.cpp>`_. +<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_. ================= ============= =========== Library Method Run Time, s ================= ============= =========== EGLIBC 2.19 printf 1.30 libstdc++ 4.8.2 std::ostream 1.85 -C++ Format 1.0 fmt::print 1.42 +fmt 1.0 fmt::print 1.42 tinyformat 2.0.1 tfm::printf 2.25 Boost Format 1.54 boost::format 9.94 ================= ============= =========== @@ -297,7 +309,7 @@ As you can see ``boost::format`` is much slower than the alternative methods; th is confirmed by `other tests <http://accu.org/index.php/journals/1539>`_. Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat cannot be faster than the IOStreams because it uses them internally. -Performance of cppformat is close to that of printf, being `faster than printf on integer +Performance of fmt is close to that of printf, being `faster than printf on integer formatting <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_, but slower on floating-point formatting which dominates this benchmark. @@ -305,8 +317,8 @@ Compile time and code bloat ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The script `bloat-test.py -<https://github.com/cppformat/format-benchmark/blob/master/bloat-test.py>`_ -from `format-benchmark <https://github.com/cppformat/format-benchmark>`_ +<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 @@ -320,12 +332,12 @@ Method Compile Time, s Executable size, KiB Stripped size, KiB ============ =============== ==================== ================== printf 2.6 41 30 IOStreams 19.4 92 70 -C++ Format 46.8 46 34 +fmt 46.8 46 34 tinyformat 64.6 418 386 Boost Format 222.8 990 923 ============ =============== ==================== ================== -As you can see, C++ Format has two times less overhead in terms of resulting +As you can see, fmt has two times less overhead in terms of resulting code size compared to IOStreams and comes pretty close to ``printf``. Boost Format has by far the largest overheads. @@ -336,12 +348,12 @@ Method Compile Time, s Executable size, KiB Stripped size, KiB ============ =============== ==================== ================== printf 2.1 41 30 IOStreams 19.7 86 62 -C++ Format 47.9 108 86 +fmt 47.9 108 86 tinyformat 27.7 234 190 Boost Format 122.6 884 763 ============ =============== ==================== ================== -``libc``, ``libstdc++`` and ``libformat`` are all linked as shared +``libc``, ``libstdc++`` and ``libfmt`` are all linked as shared libraries to compare formatting function overhead only. Boost Format and tinyformat are header-only libraries so they don't provide any linkage options. @@ -352,14 +364,14 @@ Running the tests Please refer to `Building the library`__ for the instructions on how to build the library and run the unit tests. -__ http://cppformat.github.io/latest/usage.html#building-the-library +__ http://fmtlib.net/latest/usage.html#building-the-library Benchmarks reside in a separate repository, -`format-benchmarks <https://github.com/cppformat/format-benchmark>`_, +`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/cppformat/format-benchmark.git + $ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake . @@ -374,18 +386,18 @@ or the bloat test:: License ------- -C++ Format is distributed under the BSD `license -<https://github.com/cppformat/cppformat/blob/master/LICENSE.rst>`_. +fmt is distributed under the BSD `license +<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_. The `Format String Syntax -<http://cppformat.github.io/latest/syntax.html>`_ +<http://fmtlib.net/latest/syntax.html>`_ section in the documentation is based on the one from Python `string module documentation <https://docs.python.org/3/library/string.html#module-string>`_ adapted for the current library. For this reason the documentation is distributed under the Python Software Foundation license available in `doc/python-license.txt -<https://raw.github.com/cppformat/cppformat/master/doc/python-license.txt>`_. -It only applies if you distribute the documentation of C++ Format. +<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_. +It only applies if you distribute the documentation of fmt. Acknowledgments --------------- diff --git a/dep/cppformat/cppformat/format.cc b/dep/fmt/cppformat/format.cc index daccd68f1da..daccd68f1da 100644 --- a/dep/cppformat/cppformat/format.cc +++ b/dep/fmt/cppformat/format.cc diff --git a/dep/fmt/cppformat/format.h b/dep/fmt/cppformat/format.h new file mode 100644 index 00000000000..3fbf86b894c --- /dev/null +++ b/dep/fmt/cppformat/format.h @@ -0,0 +1,2 @@ +#include "../fmt/format.h" +#warning Including cppformat/format.h is deprecated. Include fmt/format.h instead. diff --git a/dep/cppformat/cppformat/posix.cc b/dep/fmt/cppformat/posix.cc index c6c2ae2c413..c6c2ae2c413 100644 --- a/dep/cppformat/cppformat/posix.cc +++ b/dep/fmt/cppformat/posix.cc diff --git a/dep/fmt/cppformat/posix.h b/dep/fmt/cppformat/posix.h new file mode 100644 index 00000000000..97b6fadcdea --- /dev/null +++ b/dep/fmt/cppformat/posix.h @@ -0,0 +1,2 @@ +#include "../fmt/posix.h" +#warning Including cppformat/posix.h is deprecated. Include fmt/posix.h instead. diff --git a/dep/fmt/fmt/format.cc b/dep/fmt/fmt/format.cc new file mode 100644 index 00000000000..2bd774e4408 --- /dev/null +++ b/dep/fmt/fmt/format.cc @@ -0,0 +1,940 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "format.h" + +#include <string.h> + +#include <cctype> +#include <cerrno> +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstddef> // for std::ptrdiff_t + +#if defined(_WIN32) && defined(__MINGW32__) +# include <cstring> +#endif + +#if FMT_USE_WINDOWS_H +# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) +# include <windows.h> +# else +# define NOMINMAX +# include <windows.h> +# undef NOMINMAX +# endif +#endif + +using fmt::internal::Arg; + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4702) // unreachable code +// Disable deprecation warning for strerror. The latter is not called but +// MSVC fails to detect it. +# pragma warning(disable: 4996) +#endif + +// Dummy implementations of strerror_r and strerror_s called if corresponding +// system functions are not available. +static inline fmt::internal::Null<> strerror_r(int, char *, ...) { + return fmt::internal::Null<>(); +} +static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { + return fmt::internal::Null<>(); +} + +namespace fmt { + +FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {} +FMT_FUNC FormatError::~FormatError() throw() {} +FMT_FUNC SystemError::~SystemError() throw() {} + +namespace { + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else // _MSC_VER +inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); + va_end(args); + return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) +# define FMT_SWPRINTF snwprintf +#else +# define FMT_SWPRINTF swprintf +#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template <bool IsSigned> +struct IntChecker { + template <typename T> + static bool fits_in_int(T value) { + unsigned max = INT_MAX; + return value <= max; + } + static bool fits_in_int(bool) { return true; } +}; + +template <> +struct IntChecker<true> { + template <typename T> + static bool fits_in_int(T value) { + return value >= INT_MIN && value <= INT_MAX; + } + static bool fits_in_int(int) { return true; } +}; + +const char RESET_COLOR[] = "\x1b[0m"; + +typedef void (*FormatFunc)(Writer &, int, StringRef); + +// Portable thread-safe version of strerror. +// Sets buffer to point to a string describing the error code. +// This can be either a pointer to a string stored in buffer, +// or a pointer to some static immutable string. +// Returns one of the following values: +// 0 - success +// ERANGE - buffer is not large enough to store the error message +// other - failure +// Buffer should be at least of size 1. +int safe_strerror( + int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { + FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); + + class StrError { + private: + int error_code_; + char *&buffer_; + std::size_t buffer_size_; + + // A noop assignment operator to avoid bogus warnings. + void operator=(const StrError &) {} + + // Handle the result of XSI-compliant version of strerror_r. + int handle(int result) { + // glibc versions before 2.13 return result in errno. + return result == -1 ? errno : result; + } + + // Handle the result of GNU-specific version of strerror_r. + int handle(char *message) { + // If the buffer is full then the message is probably truncated. + if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1) + return ERANGE; + buffer_ = message; + return 0; + } + + // Handle the case when strerror_r is not available. + int handle(internal::Null<>) { + return fallback(strerror_s(buffer_, buffer_size_, error_code_)); + } + + // Fallback to strerror_s when strerror_r is not available. + int fallback(int result) { + // If the buffer is full then the message is probably truncated. + return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? + ERANGE : result; + } + + // Fallback to strerror if strerror_r and strerror_s are not available. + int fallback(internal::Null<>) { + errno = 0; + buffer_ = strerror(error_code_); + return errno; + } + + public: + StrError(int err_code, char *&buf, std::size_t buf_size) + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} + + int run() { + strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. + return handle(strerror_r(error_code_, buffer_, buffer_size_)); + } + }; + return StrError(error_code, buffer, buffer_size).run(); +} + +void format_error_code(Writer &out, int error_code, + StringRef message) FMT_NOEXCEPT { + // Report error code making sure that the output fits into + // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential + // bad_alloc. + out.clear(); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + typedef internal::IntTraits<int>::MainType MainType; + MainType abs_value = static_cast<MainType>(error_code); + if (internal::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += internal::count_digits(abs_value); + if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) + out << message << SEP; + out << ERROR_STR << error_code; + assert(out.size() <= internal::INLINE_BUFFER_SIZE); +} + +void report_error(FormatFunc func, int error_code, + StringRef message) FMT_NOEXCEPT { + MemoryWriter full_message; + func(full_message, error_code, message); + // Use Writer::data instead of Writer::c_str to avoid potential memory + // allocation. + std::fwrite(full_message.data(), full_message.size(), 1, stderr); + std::fputc('\n', stderr); +} + +// IsZeroInt::visit(arg) returns true iff arg is a zero integer. +class IsZeroInt : public ArgVisitor<IsZeroInt, bool> { + public: + template <typename T> + bool visit_any_int(T value) { return value == 0; } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class WidthHandler : public ArgVisitor<WidthHandler, unsigned> { + private: + FormatSpec &spec_; + + FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); + + public: + explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} + + void report_unhandled_arg() { + FMT_THROW(FormatError("width is not integer")); + } + + template <typename T> + unsigned visit_any_int(T value) { + typedef typename internal::IntTraits<T>::MainType UnsignedType; + UnsignedType width = static_cast<UnsignedType>(value); + if (internal::is_negative(value)) { + spec_.align_ = ALIGN_LEFT; + width = 0 - width; + } + if (width > INT_MAX) + FMT_THROW(FormatError("number is too big")); + return static_cast<unsigned>(width); + } +}; + +class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> { + public: + void report_unhandled_arg() { + FMT_THROW(FormatError("precision is not integer")); + } + + template <typename T> + int visit_any_int(T value) { + if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) + FMT_THROW(FormatError("number is too big")); + return static_cast<int>(value); + } +}; + +template <typename T, typename U> +struct is_same { + enum { value = 0 }; +}; + +template <typename T> +struct is_same<T, T> { + enum { value = 1 }; +}; + +// An argument visitor that converts an integer argument to T for printf, +// if T is an integral type. If T is void, the argument is converted to +// corresponding signed or unsigned type depending on the type specifier: +// 'd' and 'i' - signed, other - unsigned) +template <typename T = void> +class ArgConverter : public ArgVisitor<ArgConverter<T>, void> { + private: + internal::Arg &arg_; + wchar_t type_; + + FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); + + public: + ArgConverter(internal::Arg &arg, wchar_t type) + : arg_(arg), type_(type) {} + + void visit_bool(bool value) { + if (type_ != 's') + visit_any_int(value); + } + + template <typename U> + void visit_any_int(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using internal::Arg; + typedef typename internal::Conditional< + is_same<T, void>::value, U, T>::type TargetType; + if (sizeof(TargetType) <= sizeof(int)) { + // Extra casts are used to silence warnings. + if (is_signed) { + arg_.type = Arg::INT; + arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); + } else { + arg_.type = Arg::UINT; + typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; + arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); + } + } else { + if (is_signed) { + arg_.type = Arg::LONG_LONG; + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + arg_.long_long_value = static_cast<LongLong>(value); + } else { + arg_.type = Arg::ULONG_LONG; + arg_.ulong_long_value = + static_cast<typename internal::MakeUnsigned<U>::Type>(value); + } + } + } +}; + +// Converts an integer argument to char for printf. +class CharConverter : public ArgVisitor<CharConverter, void> { + private: + internal::Arg &arg_; + + FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); + + public: + explicit CharConverter(internal::Arg &arg) : arg_(arg) {} + + template <typename T> + void visit_any_int(T value) { + arg_.type = internal::Arg::CHAR; + arg_.int_value = static_cast<char>(value); + } +}; +} // namespace + +namespace internal { + +template <typename Char> +class PrintfArgFormatter : + public ArgFormatterBase<PrintfArgFormatter<Char>, Char> { + + void write_null_pointer() { + this->spec().type_ = 0; + this->write("(nil)"); + } + + typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base; + + public: + PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) + : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {} + + void visit_bool(bool value) { + FormatSpec &fmt_spec = this->spec(); + if (fmt_spec.type_ != 's') + return this->visit_any_int(value); + fmt_spec.type_ = 0; + this->write(value); + } + + void visit_char(int value) { + const FormatSpec &fmt_spec = this->spec(); + BasicWriter<Char> &w = this->writer(); + if (fmt_spec.type_ && fmt_spec.type_ != 'c') + w.write_int(value, fmt_spec); + typedef typename BasicWriter<Char>::CharPtr CharPtr; + CharPtr out = CharPtr(); + if (fmt_spec.width_ > 1) { + Char fill = ' '; + out = w.grow_buffer(fmt_spec.width_); + if (fmt_spec.align_ != ALIGN_LEFT) { + std::fill_n(out, fmt_spec.width_ - 1, fill); + out += fmt_spec.width_ - 1; + } else { + std::fill_n(out + 1, fmt_spec.width_ - 1, fill); + } + } else { + out = w.grow_buffer(1); + } + *out = static_cast<Char>(value); + } + + void visit_cstring(const char *value) { + if (value) + Base::visit_cstring(value); + else if (this->spec().type_ == 'p') + write_null_pointer(); + else + this->write("(null)"); + } + + void visit_pointer(const void *value) { + if (value) + return Base::visit_pointer(value); + this->spec().type_ = 0; + write_null_pointer(); + } + + void visit_custom(Arg::CustomValue c) { + BasicFormatter<Char> formatter(ArgList(), this->writer()); + const Char format_str[] = {'}', 0}; + const Char *format = format_str; + c.format(&formatter, c.value, &format); + } +}; +} // namespace internal +} // namespace fmt + +FMT_FUNC void fmt::SystemError::init( + int err_code, CStringRef format_str, ArgList args) { + error_code_ = err_code; + MemoryWriter w; + internal::format_system_error(w, err_code, format(format_str, args)); + std::runtime_error &base = *this; + base = std::runtime_error(w.str()); +} + +template <typename T> +int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, T value) { + if (width == 0) { + return precision < 0 ? + FMT_SNPRINTF(buffer, size, format, value) : + FMT_SNPRINTF(buffer, size, format, precision, value); + } + return precision < 0 ? + FMT_SNPRINTF(buffer, size, format, width, value) : + FMT_SNPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, T value) { + if (width == 0) { + return precision < 0 ? + FMT_SWPRINTF(buffer, size, format, value) : + FMT_SWPRINTF(buffer, size, format, precision, value); + } + return precision < 0 ? + FMT_SWPRINTF(buffer, size, format, width, value) : + FMT_SWPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +const char fmt::internal::BasicData<T>::DIGITS[] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, \ + factor * 100, \ + factor * 1000, \ + factor * 10000, \ + factor * 100000, \ + factor * 1000000, \ + factor * 10000000, \ + factor * 100000000, \ + factor * 1000000000 + +template <typename T> +const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = { + 0, FMT_POWERS_OF_10(1) +}; + +template <typename T> +const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = { + 0, + FMT_POWERS_OF_10(1), + FMT_POWERS_OF_10(fmt::ULongLong(1000000000)), + // Multiply several constants instead of using a single long long constant + // to avoid warnings about C++98 not supporting long long. + fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10 +}; + +FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { + (void)type; + if (std::isprint(static_cast<unsigned char>(code))) { + FMT_THROW(fmt::FormatError( + fmt::format("unknown format code '{}' for {}", code, type))); + } + FMT_THROW(fmt::FormatError( + fmt::format("unknown format code '\\x{:02x}' for {}", + static_cast<unsigned>(code), type))); +} + +#if FMT_USE_WINDOWS_H + +FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { + static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; + if (s.size() > INT_MAX) + FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); + int s_size = static_cast<int>(s.size()); + int length = MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0); + if (length == 0) + FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); + buffer_.resize(length + 1); + length = MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); + if (length == 0) + FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); + buffer_[length] = 0; +} + +FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { + if (int error_code = convert(s)) { + FMT_THROW(WindowsError(error_code, + "cannot convert string from UTF-16 to UTF-8")); + } +} + +FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { + if (s.size() > INT_MAX) + return ERROR_INVALID_PARAMETER; + int s_size = static_cast<int>(s.size()); + int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0); + if (length == 0) + return GetLastError(); + buffer_.resize(length + 1); + length = WideCharToMultiByte( + CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0); + if (length == 0) + return GetLastError(); + buffer_[length] = 0; + return 0; +} + +FMT_FUNC void fmt::WindowsError::init( + int err_code, CStringRef format_str, ArgList args) { + error_code_ = err_code; + MemoryWriter w; + internal::format_windows_error(w, err_code, format(format_str, args)); + std::runtime_error &base = *this; + base = std::runtime_error(w.str()); +} + +FMT_FUNC void fmt::internal::format_windows_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; + buffer.resize(INLINE_BUFFER_SIZE); + for (;;) { + wchar_t *system_message = &buffer[0]; + int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + system_message, static_cast<uint32_t>(buffer.size()), 0); + if (result != 0) { + UTF16ToUTF8 utf8_message; + if (utf8_message.convert(system_message) == ERROR_SUCCESS) { + out << message << ": " << utf8_message; + return; + } + break; + } + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; // Can't get error message, report error code instead. + buffer.resize(buffer.size() * 2); + } + } FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. +} + +#endif // FMT_USE_WINDOWS_H + +FMT_FUNC void fmt::internal::format_system_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer; + buffer.resize(INLINE_BUFFER_SIZE); + for (;;) { + char *system_message = &buffer[0]; + int result = safe_strerror(error_code, system_message, buffer.size()); + if (result == 0) { + out << message << ": " << system_message; + return; + } + if (result != ERANGE) + break; // Can't get error message, report error code instead. + buffer.resize(buffer.size() * 2); + } + } FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. +} + +template <typename Char> +void fmt::internal::ArgMap<Char>::init(const ArgList &args) { + if (!map_.empty()) + return; + typedef internal::NamedArg<Char> NamedArg; + const NamedArg *named_arg = 0; + bool use_values = + args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; + if (use_values) { + for (unsigned i = 0;/*nothing*/; ++i) { + internal::Arg::Type arg_type = args.type(i); + switch (arg_type) { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast<const NamedArg*>(args.values_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/; + } + } + return; + } + for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) { + internal::Arg::Type arg_type = args.type(i); + if (arg_type == internal::Arg::NAMED_ARG) { + named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + } + } + for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { + switch (args.args_[i].type) { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/; + } + } +} + +template <typename Char> +void fmt::internal::FixedBuffer<Char>::grow(std::size_t) { + FMT_THROW(std::runtime_error("buffer overflow")); +} + +FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( + unsigned arg_index, const char *&error) { + Arg arg = args_[arg_index]; + switch (arg.type) { + case Arg::NONE: + error = "argument index out of range"; + break; + case Arg::NAMED_ARG: + arg = *static_cast<const internal::Arg*>(arg.pointer); + break; + default: + /*nothing*/; + } + return arg; +} + +template <typename Char> +void fmt::internal::PrintfFormatter<Char>::parse_flags( + FormatSpec &spec, const Char *&s) { + for (;;) { + switch (*s++) { + case '-': + spec.align_ = ALIGN_LEFT; + break; + case '+': + spec.flags_ |= SIGN_FLAG | PLUS_FLAG; + break; + case '0': + spec.fill_ = '0'; + break; + case ' ': + spec.flags_ |= SIGN_FLAG; + break; + case '#': + spec.flags_ |= HASH_FLAG; + break; + default: + --s; + return; + } + } +} + +template <typename Char> +Arg fmt::internal::PrintfFormatter<Char>::get_arg( + const Char *s, unsigned arg_index) { + (void)s; + const char *error = 0; + Arg arg = arg_index == UINT_MAX ? + next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + if (error) + FMT_THROW(FormatError(!*s ? "invalid format string" : error)); + return arg; +} + +template <typename Char> +unsigned fmt::internal::PrintfFormatter<Char>::parse_header( + const Char *&s, FormatSpec &spec) { + unsigned arg_index = UINT_MAX; + Char c = *s; + if (c >= '0' && c <= '9') { + // Parse an argument index (if followed by '$') or a width possibly + // preceded with '0' flag(s). + unsigned value = parse_nonnegative_int(s); + if (*s == '$') { // value is an argument index + ++s; + arg_index = value; + } else { + if (c == '0') + spec.fill_ = '0'; + if (value != 0) { + // Nonzero value means that we parsed width and don't need to + // parse it or flags again, so return now. + spec.width_ = value; + return arg_index; + } + } + } + parse_flags(spec, s); + // Parse width. + if (*s >= '0' && *s <= '9') { + spec.width_ = parse_nonnegative_int(s); + } else if (*s == '*') { + ++s; + spec.width_ = WidthHandler(spec).visit(get_arg(s)); + } + return arg_index; +} + +template <typename Char> +void fmt::internal::PrintfFormatter<Char>::format( + BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) { + const Char *start = format_str.c_str(); + const Char *s = start; + while (*s) { + Char c = *s++; + if (c != '%') continue; + if (*s == c) { + write(writer, start, s); + start = ++s; + continue; + } + write(writer, start, s - 1); + + FormatSpec spec; + spec.align_ = ALIGN_RIGHT; + + // Parse argument index, flags and width. + unsigned arg_index = parse_header(s, spec); + + // Parse precision. + if (*s == '.') { + ++s; + if ('0' <= *s && *s <= '9') { + spec.precision_ = static_cast<int>(parse_nonnegative_int(s)); + } else if (*s == '*') { + ++s; + spec.precision_ = PrecisionHandler().visit(get_arg(s)); + } + } + + Arg arg = get_arg(s, arg_index); + if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg)) + spec.flags_ &= ~to_unsigned<int>(HASH_FLAG); + if (spec.fill_ == '0') { + if (arg.type <= Arg::LAST_NUMERIC_TYPE) + spec.align_ = ALIGN_NUMERIC; + else + spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. + } + + // Parse length and convert the argument to the required type. + switch (*s++) { + case 'h': + if (*s == 'h') + ArgConverter<signed char>(arg, *++s).visit(arg); + else + ArgConverter<short>(arg, *s).visit(arg); + break; + case 'l': + if (*s == 'l') + ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); + else + ArgConverter<long>(arg, *s).visit(arg); + break; + case 'j': + ArgConverter<intmax_t>(arg, *s).visit(arg); + break; + case 'z': + ArgConverter<std::size_t>(arg, *s).visit(arg); + break; + case 't': + ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); + break; + case 'L': + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. + break; + default: + --s; + ArgConverter<void>(arg, *s).visit(arg); + } + + // Parse type. + if (!*s) + FMT_THROW(FormatError("invalid format string")); + spec.type_ = static_cast<char>(*s++); + if (arg.type <= Arg::LAST_INTEGER_TYPE) { + // Normalize type. + switch (spec.type_) { + case 'i': case 'u': + spec.type_ = 'd'; + break; + case 'c': + // TODO: handle wchar_t + CharConverter(arg).visit(arg); + break; + } + } + + start = s; + + // Format argument. + internal::PrintfArgFormatter<Char>(writer, spec).visit(arg); + } + write(writer, start, s); +} + +FMT_FUNC void fmt::report_system_error( + int error_code, fmt::StringRef message) FMT_NOEXCEPT { + // 'fmt::' is for bcc32. + fmt::report_error(internal::format_system_error, error_code, message); +} + +#if FMT_USE_WINDOWS_H +FMT_FUNC void fmt::report_windows_error( + int error_code, fmt::StringRef message) FMT_NOEXCEPT { + // 'fmt::' is for bcc32. + fmt::report_error(internal::format_windows_error, error_code, message); +} +#endif + +FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) { + MemoryWriter w; + w.write(format_str, args); + std::fwrite(w.data(), 1, w.size(), f); +} + +FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { + print(stdout, format_str, args); +} + +FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { + char escape[] = "\x1b[30m"; + escape[3] = static_cast<char>('0' + c); + std::fputs(escape, stdout); + print(format, args); + std::fputs(RESET_COLOR, stdout); +} + +FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + std::size_t size = w.size(); + return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); +} + +#ifndef FMT_HEADER_ONLY + +template struct fmt::internal::BasicData<void>; + +// Explicit instantiations for char. + +template void fmt::internal::FixedBuffer<char>::grow(std::size_t); + +template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args); + +template void fmt::internal::PrintfFormatter<char>::format( + BasicWriter<char> &writer, CStringRef format); + +template int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, double value); + +template int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, long double value); + +// Explicit instantiations for wchar_t. + +template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t); + +template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args); + +template void fmt::internal::PrintfFormatter<wchar_t>::format( + BasicWriter<wchar_t> &writer, WCStringRef format); + +template int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, double value); + +template int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, long double value); + +#endif // FMT_HEADER_ONLY + +#ifdef _MSC_VER +# pragma warning(pop) +#endif diff --git a/dep/cppformat/cppformat/format.h b/dep/fmt/fmt/format.h index 08bb9b5d9e8..f8ce147cb38 100644 --- a/dep/cppformat/cppformat/format.h +++ b/dep/fmt/fmt/format.h @@ -1,7 +1,7 @@ /* Formatting library for C++ - Copyright (c) 2012 - 2015, Victor Zverovich + Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ #define FMT_FORMAT_H_ #include <cassert> +#include <clocale> #include <cmath> #include <cstdio> #include <cstring> @@ -39,14 +40,6 @@ #include <vector> #include <utility> -#ifndef FMT_USE_IOSTREAMS -# define FMT_USE_IOSTREAMS 1 -#endif - -#if FMT_USE_IOSTREAMS -# include <ostream> -#endif - #ifdef _SECURE_SCL # define FMT_SECURE_SCL _SECURE_SCL #else @@ -57,7 +50,13 @@ # include <iterator> #endif -#if defined(_MSC_VER) && _MSC_VER <= 1500 +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +#else +# define FMT_MSC_VER 0 +#endif + +#if FMT_MSC_VER && FMT_MSC_VER <= 1500 typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int64 intmax_t; @@ -98,9 +97,16 @@ typedef __int64 intmax_t; # define FMT_GCC_EXTENSION #endif -#if defined(__clang__) && !defined(__INTEL_COMPILER) +#if defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#elif defined(__ICL) +# define FMT_ICC_VERSION __ICL +#endif + +#if defined(__clang__) && !defined(FMT_ICC_VERSION) # pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdocumentation" +# pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +# pragma clang diagnostic ignored "-Wpadded" #endif #ifdef __GNUC_LIBSTD__ @@ -131,7 +137,7 @@ typedef __int64 intmax_t; // since version 2013. # define FMT_USE_VARIADIC_TEMPLATES \ (FMT_HAS_FEATURE(cxx_variadic_templates) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800) + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800) #endif #ifndef FMT_USE_RVALUE_REFERENCES @@ -142,7 +148,7 @@ typedef __int64 intmax_t; # else # define FMT_USE_RVALUE_REFERENCES \ (FMT_HAS_FEATURE(cxx_rvalue_references) || \ - (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600) + (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600) # endif #endif @@ -154,7 +160,7 @@ typedef __int64 intmax_t; #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 #endif -#if defined(_MSC_VER) && !_HAS_EXCEPTIONS +#if FMT_MSC_VER && !_HAS_EXCEPTIONS # define FMT_EXCEPTIONS 0 #endif #ifndef FMT_EXCEPTIONS @@ -169,7 +175,7 @@ typedef __int64 intmax_t; # endif #endif -// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). +// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). #ifndef FMT_USE_NOEXCEPT # define FMT_USE_NOEXCEPT 0 #endif @@ -178,7 +184,7 @@ typedef __int64 intmax_t; # if FMT_EXCEPTIONS # if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - _MSC_VER >= 1900 + FMT_MSC_VER >= 1900 # define FMT_NOEXCEPT noexcept # else # define FMT_NOEXCEPT throw() @@ -188,6 +194,17 @@ typedef __int64 intmax_t; # endif #endif +#ifndef FMT_OVERRIDE +# if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ + FMT_MSC_VER >= 1900 +# define FMT_OVERRIDE override +# else +# define FMT_OVERRIDE +# endif +#endif + + // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #ifndef FMT_USE_DELETED_FUNCTIONS @@ -195,7 +212,7 @@ typedef __int64 intmax_t; #endif #if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800 + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800 # define FMT_DELETED_OR_UNDEFINED = delete # define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ @@ -211,17 +228,18 @@ typedef __int64 intmax_t; // All compilers which support UDLs also support variadic templates. This // makes the fmt::literals implementation easier. However, an explicit check // for variadic templates is added here just in case. +// For Intel's compiler both it and the system gcc/msc must support UDLs. # define FMT_USE_USER_DEFINED_LITERALS \ FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \ (FMT_HAS_FEATURE(cxx_user_literals) || \ - (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900) + (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \ + (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) #endif #ifndef FMT_ASSERT # define FMT_ASSERT(condition, message) assert((condition) && message) #endif - #if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) # define FMT_BUILTIN_CLZ(n) __builtin_clz(n) #endif @@ -230,11 +248,11 @@ typedef __int64 intmax_t; # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) #endif -// Some compilers masquerade as both MSVC and GCC-likes or +// Some compilers masquerade as both MSVC and GCC-likes or // otherwise support __builtin_clz and __builtin_clzll, so // only define FMT_BUILTIN_CLZ using the MSVC intrinsics // if the clz and clzll builtins are not available. -#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL) +#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) # include <intrin.h> // _BitScanReverse, _BitScanReverse64 namespace fmt { @@ -246,7 +264,7 @@ inline uint32_t clz(uint32_t x) { assert(x != 0); // Static analysis complains about using uninitialized data - // "r", but the only way that can happen is if "x" is 0, + // "r", but the only way that can happen is if "x" is 0, // which the callers guarantee to not happen. # pragma warning(suppress: 6102) return 31 - r; @@ -272,7 +290,7 @@ inline uint32_t clzll(uint64_t x) { assert(x != 0); // Static analysis complains about using uninitialized data - // "r", but the only way that can happen is if "x" is 0, + // "r", but the only way that can happen is if "x" is 0, // which the callers guarantee to not happen. # pragma warning(suppress: 6102) return 63 - r; @@ -302,7 +320,7 @@ inline DummyInt _isnan(...) { return DummyInt(); } // A helper function to suppress bogus "conditional expression is constant" // warnings. template <typename T> -inline T check(T value) { return value; } +inline T const_check(T value) { return value; } } } // namespace fmt @@ -321,8 +339,8 @@ class numeric_limits<fmt::internal::DummyInt> : using namespace fmt::internal; // The resolution "priority" is: // isinf macro > std::isinf > ::isinf > fmt::internal::isinf - if (check(sizeof(isinf(x)) == sizeof(bool) || - sizeof(isinf(x)) == sizeof(int))) { + if (const_check(sizeof(isinf(x)) == sizeof(bool) || + sizeof(isinf(x)) == sizeof(int))) { return isinf(x) != 0; } return !_finite(static_cast<double>(x)); @@ -332,8 +350,8 @@ class numeric_limits<fmt::internal::DummyInt> : template <typename T> static bool isnotanumber(T x) { using namespace fmt::internal; - if (check(sizeof(isnan(x)) == sizeof(bool) || - sizeof(isnan(x)) == sizeof(int))) { + if (const_check(sizeof(isnan(x)) == sizeof(bool) || + sizeof(isnan(x)) == sizeof(int))) { return isnan(x) != 0; } return _isnan(static_cast<double>(x)) != 0; @@ -342,7 +360,7 @@ class numeric_limits<fmt::internal::DummyInt> : // Portable version of signbit. static bool isnegative(double x) { using namespace fmt::internal; - if (check(sizeof(signbit(x)) == sizeof(int))) + if (const_check(sizeof(signbit(x)) == sizeof(int))) return signbit(x) != 0; if (x < 0) return true; if (!isnotanumber(x)) return false; @@ -372,10 +390,11 @@ typedef BasicWriter<char> Writer; typedef BasicWriter<wchar_t> WWriter; template <typename Char> -class BasicFormatter; +class ArgFormatter; -template <typename Char, typename T> -void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value); +template <typename CharType, + typename ArgFormatter = fmt::ArgFormatter<CharType> > +class BasicFormatter; /** \rst @@ -523,13 +542,12 @@ class BasicCStringRef { typedef BasicCStringRef<char> CStringRef; typedef BasicCStringRef<wchar_t> WCStringRef; -/** - A formatting error such as invalid format string. -*/ +/** A formatting error such as invalid format string. */ class FormatError : public std::runtime_error { public: explicit FormatError(CStringRef message) : std::runtime_error(message.c_str()) {} + ~FormatError() throw(); }; namespace internal { @@ -655,8 +673,8 @@ void Buffer<T>::append(const U *begin, const U *end) { namespace internal { -// A memory buffer for trivially copyable/constructible types with the first SIZE -// elements stored in the object itself. +// A memory buffer for trivially copyable/constructible types with the first +// SIZE elements stored in the object itself. template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> > class MemoryBuffer : private Allocator, public Buffer<T> { private: @@ -668,7 +686,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> { } protected: - void grow(std::size_t size); + void grow(std::size_t size) FMT_OVERRIDE; public: explicit MemoryBuffer(const Allocator &alloc = Allocator()) @@ -828,6 +846,16 @@ struct FMT_API BasicData { static const char DIGITS[]; }; +#ifndef FMT_USE_EXTERN_TEMPLATES +// Clang doesn't have a feature check for extern templates so we check +// for variadic templates which were introduced in the same version. +# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES) +#endif + +#if FMT_USE_EXTERN_TEMPLATES && !defined(FMT_HEADER_ONLY) +extern template struct BasicData<void>; +#endif + typedef BasicData<> Data; #ifdef FMT_BUILTIN_CLZLL @@ -865,9 +893,39 @@ inline unsigned count_digits(uint32_t n) { } #endif +// A functor that doesn't add a thousands separator. +struct NoThousandsSep { + template <typename Char> + void operator()(Char *) {} +}; + +// A functor that adds a thousands separator. +class ThousandsSep { + private: + fmt::StringRef sep_; + + // Index of a decimal digit with the least significant digit having index 0. + unsigned digit_index_; + + public: + explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {} + + template <typename Char> + void operator()(Char *&buffer) { + if (++digit_index_ % 3 != 0) + return; + buffer -= sep_.size(); + std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(), + internal::make_ptr(buffer, sep_.size())); + } +}; + // Formats a decimal unsigned integer value writing into buffer. -template <typename UInt, typename Char> -inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { +// thousands_sep is a functor that is called after writing each char to +// add a thousands separator if necessary. +template <typename UInt, typename Char, typename ThousandsSep> +inline void format_decimal(Char *buffer, UInt value, unsigned num_digits, + ThousandsSep thousands_sep) { buffer += num_digits; while (value >= 100) { // Integer division is slow so do it for a group of two digits instead @@ -876,7 +934,9 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { unsigned index = static_cast<unsigned>((value % 100) * 2); value /= 100; *--buffer = Data::DIGITS[index + 1]; + thousands_sep(buffer); *--buffer = Data::DIGITS[index]; + thousands_sep(buffer); } if (value < 10) { *--buffer = static_cast<char>('0' + value); @@ -884,9 +944,15 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { } unsigned index = static_cast<unsigned>(value * 2); *--buffer = Data::DIGITS[index + 1]; + thousands_sep(buffer); *--buffer = Data::DIGITS[index]; } +template <typename UInt, typename Char> +inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { + return format_decimal(buffer, value, num_digits, NoThousandsSep()); +} + #ifndef _WIN32 # define FMT_USE_WINDOWS_H 0 #elif !defined(FMT_USE_WINDOWS_H) @@ -1007,33 +1073,16 @@ struct WCharHelper<T, wchar_t> { typedef char Yes[1]; typedef char No[2]; -// These are non-members to workaround an overload resolution bug in bcc32. -Yes &convert(fmt::ULongLong); -Yes &convert(std::ostream &); -No &convert(...); - template <typename T> T &get(); -struct DummyStream : std::ostream { - DummyStream(); // Suppress a bogus warning in MSVC. - // Hide all operator<< overloads from std::ostream. - void operator<<(Null<>); -}; - -No &operator<<(std::ostream &, int); +// These are non-members to workaround an overload resolution bug in bcc32. +Yes &convert(fmt::ULongLong); +No &convert(...); template<typename T, bool ENABLE_CONVERSION> struct ConvertToIntImpl { - enum { value = false }; -}; - -template<typename T> -struct ConvertToIntImpl<T, true> { - // Convert to int only if T doesn't have an overloaded operator<<. - enum { - value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) - }; + enum { value = ENABLE_CONVERSION }; }; template<typename T, bool ENABLE_CONVERSION> @@ -1083,6 +1132,21 @@ struct Not { enum { value = 0 }; }; template<> struct Not<false> { enum { value = 1 }; }; +template<typename T, T> struct LConvCheck { + LConvCheck(int) {} +}; + +// Returns the thousands separator for the current locale. +// We check if ``lconv`` contains ``thousands_sep`` because on Android +// ``lconv`` is stubbed as an empty struct. +template <typename LConv> +inline StringRef thousands_sep( + LConv *lc, LConvCheck<char *LConv::*, &LConv::thousands_sep> = 0) { + return lc->thousands_sep; +} + +inline fmt::StringRef thousands_sep(...) { return ""; } + // Makes an Arg object from any type. template <typename Formatter> class MakeValue : public Arg { @@ -1104,7 +1168,7 @@ class MakeValue : public Arg { // characters and strings into narrow strings as in // fmt::format("{}", L"test"); // To fix this, use a wide format string: fmt::format(L"{}", L"test"). -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +#if !FMT_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED) MakeValue(typename WCharHelper<wchar_t, Char>::Unsupported); #endif MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported); @@ -1150,7 +1214,7 @@ class MakeValue : public Arg { MakeValue(long value) { // To minimize the number of types we need to deal with, long is // translated either to int or to long long depending on its size. - if (check(sizeof(long) == sizeof(int))) + if (const_check(sizeof(long) == sizeof(int))) int_value = static_cast<int>(value); else long_long_value = value; @@ -1160,7 +1224,7 @@ class MakeValue : public Arg { } MakeValue(unsigned long value) { - if (check(sizeof(unsigned long) == sizeof(unsigned))) + if (const_check(sizeof(unsigned long) == sizeof(unsigned))) uint_value = static_cast<unsigned>(value); else ulong_long_value = value; @@ -1192,7 +1256,9 @@ class MakeValue : public Arg { FMT_MAKE_VALUE(char *, string.value, CSTRING) FMT_MAKE_VALUE(const char *, string.value, CSTRING) + FMT_MAKE_VALUE(signed char *, sstring.value, CSTRING) FMT_MAKE_VALUE(const signed char *, sstring.value, CSTRING) + FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING) FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING) FMT_MAKE_STR_VALUE(const std::string &, STRING) FMT_MAKE_STR_VALUE(StringRef, STRING) @@ -1246,7 +1312,7 @@ public: MakeArg() { type = Arg::NONE; } - + template <typename T> MakeArg(const T &value) : Arg(MakeValue<Formatter>(value)) { @@ -1263,30 +1329,114 @@ struct NamedArg : Arg { : Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {} }; +class RuntimeError : public std::runtime_error { + protected: + RuntimeError() : std::runtime_error("") {} + ~RuntimeError() throw(); +}; + +template <typename Char> +class PrintfArgFormatter; + +template <typename Char> +class ArgMap; +} // namespace internal + +/** An argument list. */ +class ArgList { + private: + // To reduce compiled code size per formatting function call, types of first + // MAX_PACKED_ARGS arguments are passed in the types_ field. + uint64_t types_; + union { + // If the number of arguments is less than MAX_PACKED_ARGS, the argument + // values are stored in values_, otherwise they are stored in args_. + // This is done to reduce compiled code size as storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const internal::Value *values_; + const internal::Arg *args_; + }; + + internal::Arg::Type type(unsigned index) const { + unsigned shift = index * 4; + uint64_t mask = 0xf; + return static_cast<internal::Arg::Type>( + (types_ & (mask << shift)) >> shift); + } + + template <typename Char> + friend class internal::ArgMap; + + public: + // Maximum number of arguments with packed types. + enum { MAX_PACKED_ARGS = 16 }; + + ArgList() : types_(0) {} + + ArgList(ULongLong types, const internal::Value *values) + : types_(types), values_(values) {} + ArgList(ULongLong types, const internal::Arg *args) + : types_(types), args_(args) {} + + /** Returns the argument at specified index. */ + internal::Arg operator[](unsigned index) const { + using internal::Arg; + Arg arg; + bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE; + if (index < MAX_PACKED_ARGS) { + Arg::Type arg_type = type(index); + internal::Value &val = arg; + if (arg_type != Arg::NONE) + val = use_values ? values_[index] : args_[index]; + arg.type = arg_type; + return arg; + } + if (use_values) { + // The index is greater than the number of arguments that can be stored + // in values, so return a "none" argument. + arg.type = Arg::NONE; + return arg; + } + for (unsigned i = MAX_PACKED_ARGS; i <= index; ++i) { + if (args_[i].type == Arg::NONE) + return args_[i]; + } + return args_[index]; + } +}; + #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call -// An argument visitor. -// To use ArgVisitor define a subclass that implements some or all of the -// visit methods with the same signatures as the methods in ArgVisitor, -// for example, visit_int(int). -// Specify the subclass name as the Impl template parameter. Then calling -// ArgVisitor::visit for some argument will dispatch to a visit method -// specific to the argument type. For example, if the argument type is -// double then visit_double(double) method of a subclass will be called. -// If the subclass doesn't contain a method with this signature, then -// a corresponding method of ArgVisitor will be called. -// -// Example: -// class MyArgVisitor : public ArgVisitor<MyArgVisitor, void> { -// public: -// void visit_int(int value) { print("{}", value); } -// void visit_double(double value) { print("{}", value ); } -// }; -// -// ArgVisitor uses the curiously recurring template pattern: -// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern +/** + \rst + An argument visitor based on the `curiously recurring template pattern + <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_. + + To use `~fmt::ArgVisitor` define a subclass that implements some or all of the + visit methods with the same signatures as the methods in `~fmt::ArgVisitor`, + for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. Then calling + `~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::ArgVisitor` will be called. + + **Example**:: + + class MyArgVisitor : public fmt::ArgVisitor<MyArgVisitor, void> { + public: + void visit_int(int value) { fmt::print("{}", value); } + void visit_double(double value) { fmt::print("{}", value ); } + }; + \endrst + */ template <typename Impl, typename Result> class ArgVisitor { + private: + typedef internal::Arg Arg; + public: void report_unhandled_arg() {} @@ -1295,61 +1445,97 @@ class ArgVisitor { return Result(); } + /** Visits an ``int`` argument. **/ Result visit_int(int value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits a ``long long`` argument. **/ Result visit_long_long(LongLong value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits an ``unsigned`` argument. **/ Result visit_uint(unsigned value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits an ``unsigned long long`` argument. **/ Result visit_ulong_long(ULongLong value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits a ``bool`` argument. **/ Result visit_bool(bool value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits a ``char`` or ``wchar_t`` argument. **/ Result visit_char(int value) { return FMT_DISPATCH(visit_any_int(value)); } + + /** Visits an argument of any integral type. **/ template <typename T> Result visit_any_int(T) { return FMT_DISPATCH(visit_unhandled_arg()); } + /** Visits a ``double`` argument. **/ Result visit_double(double value) { return FMT_DISPATCH(visit_any_double(value)); } + + /** Visits a ``long double`` argument. **/ Result visit_long_double(long double value) { return FMT_DISPATCH(visit_any_double(value)); } + + /** Visits a ``double`` or ``long double`` argument. **/ template <typename T> Result visit_any_double(T) { return FMT_DISPATCH(visit_unhandled_arg()); } + /** Visits a null-terminated C string (``const char *``) argument. **/ Result visit_cstring(const char *) { return FMT_DISPATCH(visit_unhandled_arg()); } + + /** Visits a string argument. **/ Result visit_string(Arg::StringValue<char>) { return FMT_DISPATCH(visit_unhandled_arg()); } + + /** Visits a wide string argument. **/ Result visit_wstring(Arg::StringValue<wchar_t>) { return FMT_DISPATCH(visit_unhandled_arg()); } + + /** Visits a pointer argument. **/ Result visit_pointer(const void *) { return FMT_DISPATCH(visit_unhandled_arg()); } + + /** Visits an argument of a custom (user-defined) type. **/ Result visit_custom(Arg::CustomValue) { return FMT_DISPATCH(visit_unhandled_arg()); } + /** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be + called. + \endrst + */ Result visit(const Arg &arg) { switch (arg.type) { - default: + case Arg::NONE: + case Arg::NAMED_ARG: FMT_ASSERT(false, "invalid argument type"); - return Result(); + break; case Arg::INT: return FMT_DISPATCH(visit_int(arg.int_value)); case Arg::UINT: @@ -1377,82 +1563,7 @@ class ArgVisitor { case Arg::CUSTOM: return FMT_DISPATCH(visit_custom(arg.custom)); } - } -}; - -class RuntimeError : public std::runtime_error { - protected: - RuntimeError() : std::runtime_error("") {} -}; - -template <typename Char> -class PrintfArgFormatter; - -template <typename Char> -class ArgMap; -} // namespace internal - -/** An argument list. */ -class ArgList { - private: - // To reduce compiled code size per formatting function call, types of first - // MAX_PACKED_ARGS arguments are passed in the types_ field. - uint64_t types_; - union { - // If the number of arguments is less than MAX_PACKED_ARGS, the argument - // values are stored in values_, otherwise they are stored in args_. - // This is done to reduce compiled code size as storing larger objects - // may require more code (at least on x86-64) even if the same amount of - // data is actually copied to stack. It saves ~10% on the bloat test. - const internal::Value *values_; - const internal::Arg *args_; - }; - - internal::Arg::Type type(unsigned index) const { - unsigned shift = index * 4; - uint64_t mask = 0xf; - return static_cast<internal::Arg::Type>( - (types_ & (mask << shift)) >> shift); - } - - template <typename Char> - friend class internal::ArgMap; - - public: - // Maximum number of arguments with packed types. - enum { MAX_PACKED_ARGS = 16 }; - - ArgList() : types_(0) {} - - ArgList(ULongLong types, const internal::Value *values) - : types_(types), values_(values) {} - ArgList(ULongLong types, const internal::Arg *args) - : types_(types), args_(args) {} - - /** Returns the argument at specified index. */ - internal::Arg operator[](unsigned index) const { - using internal::Arg; - Arg arg; - bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE; - if (index < MAX_PACKED_ARGS) { - Arg::Type arg_type = type(index); - internal::Value &val = arg; - if (arg_type != Arg::NONE) - val = use_values ? values_[index] : args_[index]; - arg.type = arg_type; - return arg; - } - if (use_values) { - // The index is greater than the number of arguments that can be stored - // in values, so return a "none" argument. - arg.type = Arg::NONE; - return arg; - } - for (unsigned i = MAX_PACKED_ARGS; i <= index; ++i) { - if (args_[i].type == Arg::NONE) - return args_[i]; - } - return args_[index]; + return Result(); } }; @@ -1682,7 +1793,8 @@ namespace internal { template <typename Char> class ArgMap { private: - typedef std::vector<std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType; + typedef std::vector< + std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType; typedef typename MapType::value_type Pair; MapType map_; @@ -1757,21 +1869,21 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> { typedef typename BasicWriter<Char>::CharPtr CharPtr; Char fill = internal::CharTraits<Char>::cast(spec_.fill()); CharPtr out = CharPtr(); - const unsigned CHAR_WIDTH = 1; - if (spec_.width_ > CHAR_WIDTH) { + const unsigned CHAR_SIZE = 1; + if (spec_.width_ > CHAR_SIZE) { out = writer_.grow_buffer(spec_.width_); if (spec_.align_ == ALIGN_RIGHT) { - std::uninitialized_fill_n(out, spec_.width_ - CHAR_WIDTH, fill); - out += spec_.width_ - CHAR_WIDTH; + std::uninitialized_fill_n(out, spec_.width_ - CHAR_SIZE, fill); + out += spec_.width_ - CHAR_SIZE; } else if (spec_.align_ == ALIGN_CENTER) { out = writer_.fill_padding(out, spec_.width_, - internal::check(CHAR_WIDTH), fill); + internal::const_check(CHAR_SIZE), fill); } else { - std::uninitialized_fill_n(out + CHAR_WIDTH, - spec_.width_ - CHAR_WIDTH, fill); + std::uninitialized_fill_n(out + CHAR_SIZE, + spec_.width_ - CHAR_SIZE, fill); } } else { - out = writer_.grow_buffer(CHAR_WIDTH); + out = writer_.grow_buffer(CHAR_SIZE); } *out = internal::CharTraits<Char>::cast(value); } @@ -1799,24 +1911,6 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> { } }; -// An argument formatter. -template <typename Char> -class BasicArgFormatter : - public ArgFormatterBase<BasicArgFormatter<Char>, Char> { - private: - BasicFormatter<Char> &formatter_; - const Char *format_; - - public: - BasicArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt) - : ArgFormatterBase<BasicArgFormatter<Char>, Char>(f.writer(), s), - formatter_(f), format_(fmt) {} - - void visit_custom(Arg::CustomValue c) { - c.format(&formatter_, c.value, &format_); - } -}; - class FormatterBase { private: ArgList args_; @@ -1884,8 +1978,61 @@ class PrintfFormatter : private FormatterBase { }; } // namespace internal +/** + \rst + An argument formatter based on the `curiously recurring template pattern + <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_. + + To use `~fmt::BasicArgFormatter` define a subclass that implements some or + all of the visit methods with the same signatures as the methods in + `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. When a formatting + function processes an argument, it will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::BasicArgFormatter` or its superclass + will be called. + \endrst + */ +template <typename Impl, typename Char> +class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> { + private: + BasicFormatter<Char, Impl> &formatter_; + const Char *format_; + + public: + /** + \rst + Constructs an argument formatter object. + *formatter* is a reference to the main formatter object, *spec* contains + format specifier information for standard argument types, and *fmt* points + to the part of the format string being parsed for custom argument types. + \endrst + */ + BasicArgFormatter(BasicFormatter<Char, Impl> &formatter, + FormatSpec &spec, const Char *fmt) + : internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec), + formatter_(formatter), format_(fmt) {} + + /** Formats argument of a custom (user-defined) type. */ + void visit_custom(internal::Arg::CustomValue c) { + c.format(&formatter_, c.value, &format_); + } +}; + +/** The default argument formatter. */ +template <typename Char> +class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> { + public: + /** Constructs an argument formatter object. */ + ArgFormatter(BasicFormatter<Char> &formatter, + FormatSpec &spec, const Char *fmt) + : BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {} +}; + /** This template formats data and writes the output to a writer. */ -template <typename CharType> +template <typename CharType, typename ArgFormatter> class BasicFormatter : private internal::FormatterBase { public: /** The character type for the output. */ @@ -1963,14 +2110,18 @@ struct ArgArray; template <unsigned N> struct ArgArray<N, true/*IsPacked*/> { typedef Value Type[N > 0 ? N : 1]; - + template <typename Formatter, typename T> static Value make(const T &value) { +#ifdef __clang__ Value result = MakeValue<Formatter>(value); // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: - // https://github.com/cppformat/cppformat/issues/276 + // https://github.com/fmtlib/fmt/issues/276 (void)result.custom.format; return result; +#else + return MakeValue<Formatter>(value); +#endif } }; @@ -2008,38 +2159,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { (t12.type << 48) | (t13.type << 52) | (t14.type << 56); } #endif - -template <class Char> -class FormatBuf : public std::basic_streambuf<Char> { - private: - typedef typename std::basic_streambuf<Char>::int_type int_type; - typedef typename std::basic_streambuf<Char>::traits_type traits_type; - - Buffer<Char> &buffer_; - Char *start_; - - public: - FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) { - this->setp(start_, start_ + buffer_.capacity()); - } - - int_type overflow(int_type ch = traits_type::eof()) { - if (!traits_type::eq_int_type(ch, traits_type::eof())) { - size_t size = this->size(); - buffer_.resize(size); - buffer_.reserve(size * 2); - - start_ = &buffer_[0]; - start_[size] = traits_type::to_char_type(ch); - this->setp(start_+ size + 1, start_ + size * 2); - } - return ch; - } - - size_t size() const { - return to_unsigned(this->pptr() - start_); - } -}; } // namespace internal # define FMT_MAKE_TEMPLATE_ARG(n) typename T##n @@ -2186,6 +2305,8 @@ class SystemError : public internal::RuntimeError { } FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef) + ~SystemError() throw(); + int error_code() const { return error_code_; } }; @@ -2476,6 +2597,8 @@ class BasicWriter { } void clear() FMT_NOEXCEPT { buffer_.clear(); } + + Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; } }; template <typename Char> @@ -2514,7 +2637,6 @@ void BasicWriter<Char>::write_str( if (str_size == 0) { if (!str_value) { FMT_THROW(FormatError("string pointer is null")); - return; } } std::size_t precision = static_cast<std::size_t>(spec.precision_); @@ -2621,9 +2743,8 @@ void BasicWriter<Char>::write_int(T value, Spec spec) { switch (spec.type()) { case 0: case 'd': { unsigned num_digits = internal::count_digits(abs_value); - CharPtr p = prepare_int_buffer( - num_digits, spec, prefix, prefix_size) + 1 - num_digits; - internal::format_decimal(get(p), abs_value, num_digits); + CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1; + internal::format_decimal(get(p), abs_value, 0); break; } case 'x': case 'X': { @@ -2678,6 +2799,18 @@ void BasicWriter<Char>::write_int(T value, Spec spec) { } while ((n >>= 3) != 0); break; } + case 'n': { + unsigned num_digits = internal::count_digits(abs_value); + fmt::StringRef sep = ""; +#ifndef ANDROID + sep = internal::thousands_sep(std::localeconv()); +#endif + unsigned size = static_cast<unsigned>( + num_digits + sep.size() * ((num_digits - 1) / 3)); + CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; + internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep)); + break; + } default: internal::report_unknown_type( spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); @@ -2698,7 +2831,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) { case 'e': case 'f': case 'g': case 'a': break; case 'F': -#ifdef _MSC_VER +#if FMT_MSC_VER // MSVC's printf doesn't support 'F'. type = 'f'; #endif @@ -2791,7 +2924,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) { Char *start = 0; for (;;) { std::size_t buffer_size = buffer_.capacity() - offset; -#ifdef _MSC_VER +#if FMT_MSC_VER // MSVC's vsnprintf_s doesn't work with zero size, so reserve // space for at least one extra character to make the size non-zero. // Note that the buffer's capacity will increase by more than 1. @@ -2958,20 +3091,6 @@ class BasicArrayWriter : public BasicWriter<Char> { typedef BasicArrayWriter<char> ArrayWriter; typedef BasicArrayWriter<wchar_t> WArrayWriter; -// Formats a value. -template <typename Char, typename T> -void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) { - internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; - - internal::FormatBuf<Char> format_buf(buffer); - std::basic_ostream<Char> output(&format_buf); - output << value; - - BasicStringRef<Char> str(&buffer[0], format_buf.size()); - typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; - format_str = f.format(format_str, MakeArg(str)); -} - // Reports a system error without throwing an exception. // Can be used to report errors from destructors. FMT_API void report_system_error(int error_code, @@ -3401,32 +3520,6 @@ FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) -#if FMT_USE_IOSTREAMS -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - print(cerr, "Don't {}!", "panic"); - \endrst - */ -FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); -FMT_VARIADIC(void, print, std::ostream &, CStringRef) - -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - fprintf(cerr, "Don't %s!", "panic"); - \endrst - */ -FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); -FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) -#endif - namespace internal { template <typename Char> inline bool is_name_start(Char c) { @@ -3475,9 +3568,9 @@ void check_sign(const Char *&s, const Arg &arg) { } } // namespace internal -template <typename Char> -inline internal::Arg BasicFormatter<Char>::get_arg( - BasicStringRef<Char> arg_name, const char *&error) { +template <typename Char, typename AF> +inline internal::Arg BasicFormatter<Char, AF>::get_arg( + BasicStringRef<Char> arg_name, const char *&error) { if (check_no_auto_index(error)) { map_.init(args()); const internal::Arg *arg = map_.find(arg_name); @@ -3488,8 +3581,8 @@ inline internal::Arg BasicFormatter<Char>::get_arg( return internal::Arg(); } -template <typename Char> -inline internal::Arg BasicFormatter<Char>::parse_arg_index(const Char *&s) { +template <typename Char, typename AF> +inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s) { const char *error = 0; internal::Arg arg = *s < '0' || *s > '9' ? next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error); @@ -3500,8 +3593,8 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_index(const Char *&s) { return arg; } -template <typename Char> -inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s) { +template <typename Char, typename AF> +inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s) { assert(internal::is_name_start(*s)); const Char *start = s; Char c; @@ -3515,8 +3608,8 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s) { return arg; } -template <typename Char> -const Char *BasicFormatter<Char>::format( +template <typename Char, typename ArgFormatter> +const Char *BasicFormatter<Char, ArgFormatter>::format( const Char *&format_str, const internal::Arg &arg) { using internal::Arg; const Char *s = format_str; @@ -3681,12 +3774,12 @@ const Char *BasicFormatter<Char>::format( FMT_THROW(FormatError("missing '}' in format string")); // Format argument. - internal::BasicArgFormatter<Char>(*this, spec, s - 1).visit(arg); + ArgFormatter(*this, spec, s - 1).visit(arg); return s; } -template <typename Char> -void BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) { +template <typename Char, typename AF> +void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) { const Char *s = format_str.c_str(); const Char *start = s; while (*s) { @@ -3776,12 +3869,15 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; } # pragma GCC diagnostic pop #endif -#if defined(__clang__) && !defined(__INTEL_COMPILER) +#if defined(__clang__) && !defined(FMT_ICC_VERSION) # pragma clang diagnostic pop #endif #ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline # include "format.cc" +#else +# define FMT_FUNC #endif #endif // FMT_FORMAT_H_ diff --git a/dep/fmt/fmt/ostream.cc b/dep/fmt/fmt/ostream.cc new file mode 100644 index 00000000000..bcb67fe1577 --- /dev/null +++ b/dep/fmt/fmt/ostream.cc @@ -0,0 +1,43 @@ +/* + Formatting library for C++ - std::ostream support + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#include "ostream.h" + +namespace fmt { + +namespace { +// Write the content of w to os. +void write(std::ostream &os, Writer &w) { + const char *data = w.data(); + typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize; + UnsignedStreamSize size = w.size(); + UnsignedStreamSize max_size = + internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); + do { + UnsignedStreamSize n = size <= max_size ? size : max_size; + os.write(data, static_cast<std::streamsize>(n)); + data += n; + size -= n; + } while (size != 0); +} +} + +FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { + MemoryWriter w; + w.write(format_str, args); + write(os, w); +} + +FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + write(os, w); + return static_cast<int>(w.size()); +} +} // namespace fmt diff --git a/dep/fmt/fmt/ostream.h b/dep/fmt/fmt/ostream.h new file mode 100644 index 00000000000..29483c1bcbd --- /dev/null +++ b/dep/fmt/fmt/ostream.h @@ -0,0 +1,115 @@ +/* + Formatting library for C++ - std::ostream support + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +#include "format.h" +#include <ostream> + +namespace fmt { + +namespace internal { + +template <class Char> +class FormatBuf : public std::basic_streambuf<Char> { + private: + typedef typename std::basic_streambuf<Char>::int_type int_type; + typedef typename std::basic_streambuf<Char>::traits_type traits_type; + + Buffer<Char> &buffer_; + Char *start_; + + public: + FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) { + this->setp(start_, start_ + buffer_.capacity()); + } + + int_type overflow(int_type ch = traits_type::eof()) { + if (!traits_type::eq_int_type(ch, traits_type::eof())) { + size_t buf_size = size(); + buffer_.resize(buf_size); + buffer_.reserve(buf_size * 2); + + start_ = &buffer_[0]; + start_[buf_size] = traits_type::to_char_type(ch); + this->setp(start_+ buf_size + 1, start_ + buf_size * 2); + } + return ch; + } + + size_t size() const { + return to_unsigned(this->pptr() - start_); + } +}; + +Yes &convert(std::ostream &); + +struct DummyStream : std::ostream { + DummyStream(); // Suppress a bogus warning in MSVC. + // Hide all operator<< overloads from std::ostream. + void operator<<(Null<>); +}; + +No &operator<<(std::ostream &, int); + +template<typename T> +struct ConvertToIntImpl<T, true> { + // Convert to int only if T doesn't have an overloaded operator<<. + enum { + value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) + }; +}; +} // namespace internal + +// Formats a value. +template <typename Char, typename ArgFormatter, typename T> +void format(BasicFormatter<Char, ArgFormatter> &f, + const Char *&format_str, const T &value) { + internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; + + internal::FormatBuf<Char> format_buf(buffer); + std::basic_ostream<Char> output(&format_buf); + output << value; + + BasicStringRef<Char> str(&buffer[0], format_buf.size()); + typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; + format_str = f.format(format_str, MakeArg(str)); +} + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + print(cerr, "Don't {}!", "panic"); + \endrst + */ +FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(void, print, std::ostream &, CStringRef) + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + fprintf(cerr, "Don't %s!", "panic"); + \endrst + */ +FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) +} // namespace fmt + +#ifdef FMT_HEADER_ONLY +# include "ostream.cc" +#endif + +#endif // FMT_OSTREAM_H_ diff --git a/dep/fmt/fmt/posix.cc b/dep/fmt/fmt/posix.cc new file mode 100644 index 00000000000..76eb7f05eb8 --- /dev/null +++ b/dep/fmt/fmt/posix.cc @@ -0,0 +1,238 @@ +/* + A C++ interface to POSIX functions. + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +// Disable bogus MSVC warnings. +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif + +#include "posix.h" + +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifndef _WIN32 +# include <unistd.h> +#else +# include <windows.h> +# include <io.h> + +# define O_CREAT _O_CREAT +# define O_TRUNC _O_TRUNC + +# ifndef S_IRUSR +# define S_IRUSR _S_IREAD +# endif + +# ifndef S_IWUSR +# define S_IWUSR _S_IWRITE +# endif + +# ifdef __MINGW32__ +# define _SH_DENYNO 0x40 +# endif + +#endif // _WIN32 + +#ifdef fileno +# undef fileno +#endif + +namespace { +#ifdef _WIN32 +// Return type of read and write functions. +typedef int RWResult; + +// On Windows the count argument to read and write is unsigned, so convert +// it from size_t preventing integer overflow. +inline unsigned convert_rwcount(std::size_t count) { + return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX; +} +#else +// Return type of read and write functions. +typedef ssize_t RWResult; + +inline std::size_t convert_rwcount(std::size_t count) { return count; } +#endif +} + +fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { + if (file_ && FMT_SYSTEM(fclose(file_)) != 0) + fmt::report_system_error(errno, "cannot close file"); +} + +fmt::BufferedFile::BufferedFile( + fmt::CStringRef filename, fmt::CStringRef mode) { + FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0); + if (!file_) + FMT_THROW(SystemError(errno, "cannot open file {}", filename)); +} + +void fmt::BufferedFile::close() { + if (!file_) + return; + int result = FMT_SYSTEM(fclose(file_)); + file_ = 0; + if (result != 0) + FMT_THROW(SystemError(errno, "cannot close file")); +} + +// A macro used to prevent expansion of fileno on broken versions of MinGW. +#define FMT_ARGS + +int fmt::BufferedFile::fileno() const { + int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_)); + if (fd == -1) + FMT_THROW(SystemError(errno, "cannot get file descriptor")); + return fd; +} + +fmt::File::File(fmt::CStringRef path, int oflag) { + int mode = S_IRUSR | S_IWUSR; +#if defined(_WIN32) && !defined(__MINGW32__) + fd_ = -1; + FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); +#else + FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode))); +#endif + if (fd_ == -1) + FMT_THROW(SystemError(errno, "cannot open file {}", path)); +} + +fmt::File::~File() FMT_NOEXCEPT { + // Don't retry close in case of EINTR! + // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0) + fmt::report_system_error(errno, "cannot close file"); +} + +void fmt::File::close() { + if (fd_ == -1) + return; + // Don't retry close in case of EINTR! + // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + int result = FMT_POSIX_CALL(close(fd_)); + fd_ = -1; + if (result != 0) + FMT_THROW(SystemError(errno, "cannot close file")); +} + +fmt::LongLong fmt::File::size() const { +#ifdef _WIN32 + // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT + // is less than 0x0500 as is the case with some default MinGW builds. + // Both functions support large file sizes. + DWORD size_upper = 0; + HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_)); + DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper)); + if (size_lower == INVALID_FILE_SIZE) { + DWORD error = GetLastError(); + if (error != NO_ERROR) + FMT_THROW(WindowsError(GetLastError(), "cannot get file size")); + } + fmt::ULongLong long_size = size_upper; + return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower; +#else + typedef struct stat Stat; + Stat file_stat = Stat(); + if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) + FMT_THROW(SystemError(errno, "cannot get file attributes")); + FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size), + "return type of File::size is not large enough"); + return file_stat.st_size; +#endif +} + +std::size_t fmt::File::read(void *buffer, std::size_t count) { + RWResult result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count)))); + if (result < 0) + FMT_THROW(SystemError(errno, "cannot read from file")); + return internal::to_unsigned(result); +} + +std::size_t fmt::File::write(const void *buffer, std::size_t count) { + RWResult result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count)))); + if (result < 0) + FMT_THROW(SystemError(errno, "cannot write to file")); + return internal::to_unsigned(result); +} + +fmt::File fmt::File::dup(int fd) { + // Don't retry as dup doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html + int new_fd = FMT_POSIX_CALL(dup(fd)); + if (new_fd == -1) + FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd)); + return File(new_fd); +} + +void fmt::File::dup2(int fd) { + int result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); + if (result == -1) { + FMT_THROW(SystemError(errno, + "cannot duplicate file descriptor {} to {}", fd_, fd)); + } +} + +void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT { + int result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); + if (result == -1) + ec = ErrorCode(errno); +} + +void fmt::File::pipe(File &read_end, File &write_end) { + // Close the descriptors first to make sure that assignments don't throw + // and there are no leaks. + read_end.close(); + write_end.close(); + int fds[2] = {}; +#ifdef _WIN32 + // Make the default pipe capacity same as on Linux 2.6.11+. + enum { DEFAULT_CAPACITY = 65536 }; + int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY)); +#else + // Don't retry as the pipe function doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html + int result = FMT_POSIX_CALL(pipe(fds)); +#endif + if (result != 0) + FMT_THROW(SystemError(errno, "cannot create pipe")); + // The following assignments don't throw because read_fd and write_fd + // are closed. + read_end = File(fds[0]); + write_end = File(fds[1]); +} + +fmt::BufferedFile fmt::File::fdopen(const char *mode) { + // Don't retry as fdopen doesn't return EINTR. + FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); + if (!f) + FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor")); + BufferedFile file(f); + fd_ = -1; + return file; +} + +long fmt::getpagesize() { +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE)); + if (size < 0) + FMT_THROW(SystemError(errno, "cannot get memory page size")); + return size; +#endif +} diff --git a/dep/cppformat/cppformat/posix.h b/dep/fmt/fmt/posix.h index bfbd3851838..be1286c425d 100644 --- a/dep/cppformat/cppformat/posix.h +++ b/dep/fmt/fmt/posix.h @@ -1,34 +1,16 @@ /* A C++ interface to POSIX functions. - Copyright (c) 2014 - 2015, Victor Zverovich + Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + For the license information refer to format.h. */ #ifndef FMT_POSIX_H_ #define FMT_POSIX_H_ -#ifdef __MINGW32__ +#if defined(__MINGW32__) || defined(__CYGWIN__) // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. # undef __STRICT_ANSI__ #endif @@ -41,7 +23,7 @@ #include <cstddef> -#ifdef __APPLE__ +#if defined __APPLE__ || defined(__FreeBSD__) # include <xlocale.h> // for LC_NUMERIC_MASK on OS X #endif @@ -145,7 +127,7 @@ public: // A "move constructor" for moving from a temporary. BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {} - // A "move constructor" for for moving from an lvalue. + // A "move constructor" for moving from an lvalue. BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) { f.file_ = 0; } @@ -251,7 +233,7 @@ class File { // A "move constructor" for moving from a temporary. File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {} - // A "move constructor" for for moving from an lvalue. + // A "move constructor" for moving from an lvalue. File(File &other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } @@ -339,7 +321,8 @@ class File { // Returns the memory page size. long getpagesize(); -#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER) +#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ + !defined(__ANDROID__) && !defined(__CYGWIN__) # define FMT_LOCALE #endif @@ -374,7 +357,7 @@ class Locale { Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) { if (!locale_) - throw fmt::SystemError(errno, "cannot create locale"); + FMT_THROW(fmt::SystemError(errno, "cannot create locale")); } ~Locale() { freelocale(locale_); } diff --git a/dep/fmt/fmt/time.h b/dep/fmt/fmt/time.h new file mode 100644 index 00000000000..10225c03ef8 --- /dev/null +++ b/dep/fmt/fmt/time.h @@ -0,0 +1,53 @@ +/* + Formatting library for C++ - time formatting + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#ifndef FMT_TIME_H_ +#define FMT_TIME_H_ + +#include "format.h" +#include <ctime> + +namespace fmt { +template <typename ArgFormatter> +void format(BasicFormatter<char, ArgFormatter> &f, + const char *&format_str, const std::tm &tm) { + if (*format_str == ':') + ++format_str; + const char *end = format_str; + while (*end && *end != '}') + ++end; + if (*end != '}') + FMT_THROW(FormatError("missing '}' in format string")); + internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format; + format.append(format_str, end + 1); + format[format.size() - 1] = '\0'; + Buffer<char> &buffer = f.writer().buffer(); + std::size_t start = buffer.size(); + for (;;) { + std::size_t size = buffer.capacity() - start; + std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm); + if (count != 0) { + buffer.resize(start + count); + break; + } + if (size >= format.size() * 256) { + // If the buffer is 256 times larger than the format string, assume + // that `strftime` gives an empty result. There doesn't seem to be a + // better way to distinguish the two cases: + // https://github.com/fmtlib/fmt/issues/367 + break; + } + const std::size_t MIN_GROWTH = 10; + buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); + } + format_str = end + 1; +} +} + +#endif // FMT_TIME_H_ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 0428738f2dd..6855ac871da 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -63,7 +63,7 @@ target_include_directories(common target_link_libraries(common PUBLIC boost - cppformat + fmt g3dlib Detour sfmt diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h index e21b1024e87..6f101a78ef1 100644 --- a/src/common/Utilities/StringFormat.h +++ b/src/common/Utilities/StringFormat.h @@ -19,7 +19,7 @@ #ifndef TRINITYCORE_STRING_FORMAT_H #define TRINITYCORE_STRING_FORMAT_H -#include "cppformat/format.h" +#include "fmt/format.h" namespace Trinity { |