aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dep/PackageList.txt8
-rw-r--r--dep/fmt/CMakeLists.txt18
-rw-r--r--dep/fmt/CONTRIBUTING.rst11
-rw-r--r--dep/fmt/ChangeLog.rst99
-rw-r--r--dep/fmt/README.rst17
-rw-r--r--dep/fmt/cppformat/format.cc971
-rw-r--r--dep/fmt/cppformat/format.h2
-rw-r--r--dep/fmt/cppformat/posix.cc256
-rw-r--r--dep/fmt/cppformat/posix.h2
-rw-r--r--dep/fmt/fmt/container.h82
-rw-r--r--dep/fmt/fmt/format.cc587
-rw-r--r--dep/fmt/fmt/format.h697
-rw-r--r--dep/fmt/fmt/ostream.cc14
-rw-r--r--dep/fmt/fmt/ostream.h63
-rw-r--r--dep/fmt/fmt/posix.cc5
-rw-r--r--dep/fmt/fmt/posix.h65
-rw-r--r--dep/fmt/fmt/printf.cc32
-rw-r--r--dep/fmt/fmt/printf.h603
-rw-r--r--dep/fmt/fmt/string.h148
-rw-r--r--dep/fmt/fmt/time.h94
-rw-r--r--src/common/Utilities/StringFormat.h2
21 files changed, 1715 insertions, 2061 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index c45e2aefc27..9ffc95d89e2 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -12,14 +12,14 @@ bzip2 (a freely available, patent free, high-quality data compressor)
http://www.bzip.org/
Version: 1.0.6
-cppformat (type safe format library)
- https://github.com/cppformat/cppformat
- Version: 3.0.1 7fa8f8fa48b0903deab5bb42e6760477173ac485
-
efws (Entropia File System Watcher - crossplatform file system watcher)
https://bitbucket.org/SpartanJ/efsw
Version: 1.0.0 9a7cbec70b8a88b2e876a382f57c59f3796da0d9
+fmt (a small, safe and fast formatting library)
+ https://github.com/fmtlib/fmt
+ Version: 4.0.0 5f39721c0a41be404a23c3893cdea89e598c9531
+
G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License)
http://g3d.sourceforge.net/
Version: 9.0-Release r4036
diff --git a/dep/fmt/CMakeLists.txt b/dep/fmt/CMakeLists.txt
index 392dd2fa911..2961a0fc139 100644
--- a/dep/fmt/CMakeLists.txt
+++ b/dep/fmt/CMakeLists.txt
@@ -16,10 +16,14 @@ else ()
endif ()
set(FMT_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/fmt/container.h
${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/printf.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fmt/printf.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/fmt/string.h
${CMAKE_CURRENT_SOURCE_DIR}/fmt/time.h)
if (HAVE_OPEN)
@@ -34,7 +38,15 @@ target_include_directories(fmt
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR})
+target_compile_definitions(fmt
+ PUBLIC
+ -DFMT_USE_OVERRIDE
+ -DFMT_USE_VARIADIC_TEMPLATES
+ -DFMT_USE_RVALUE_REFERENCES
+ -DFMT_USE_DELETED_FUNCTIONS
+ -DFMT_USE_EXTERN_TEMPLATES)
+
set_target_properties(fmt
- PROPERTIES
- FOLDER
- "dep")
+ PROPERTIES
+ FOLDER
+ "dep")
diff --git a/dep/fmt/CONTRIBUTING.rst b/dep/fmt/CONTRIBUTING.rst
new file mode 100644
index 00000000000..506811d4a45
--- /dev/null
+++ b/dep/fmt/CONTRIBUTING.rst
@@ -0,0 +1,11 @@
+Contributing to fmt
+===================
+
+All C++ code must adhere to `Google C++ Style Guide
+<https://google.github.io/styleguide/cppguide.html>`_ with the following
+exceptions:
+
+* Exceptions are permitted
+* snake_case should be used instead of UpperCamelCase for function names
+
+Thanks for contributing!
diff --git a/dep/fmt/ChangeLog.rst b/dep/fmt/ChangeLog.rst
index f4df68b6a12..1633bac7121 100644
--- a/dep/fmt/ChangeLog.rst
+++ b/dep/fmt/ChangeLog.rst
@@ -1,3 +1,102 @@
+4.0.1 - TBD
+-----------
+
+4.0.0 - 2017-06-27
+------------------
+
+* Removed old compatibility headers ``cppformat/*.h`` and CMake options (`#527 <https://github.com/pull/527>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
+
+* Added ``string.h`` containing ``fmt::to_string()`` as alternative to ``std::to_string()`` as well as other string writer functionality (`#326 <https://github.com/fmtlib/fmt/issues/326>`_ and `#441 <https://github.com/fmtlib/fmt/pull/441>`_):
+
+ .. code:: c++
+
+ #include "fmt/string.h"
+
+ std::string answer = fmt::to_string(42);
+
+ Thanks to `@glebov-andrey (Andrey Glebov) <https://github.com/glebov-andrey>`_.
+
+* Moved ``fmt::printf()`` to new ``printf.h`` header and allowed ``%s`` as generic specifier (`#453 <https://github.com/fmtlib/fmt/pull/453>`_), made ``%.f`` more conformant to regular ``printf()`` (`#490 <https://github.com/fmtlib/fmt/pull/490>`_), added custom writer support (`#476 <https://github.com/fmtlib/fmt/issues/476>`_) and implemented missing custom argument formatting (`#339 <https://github.com/fmtlib/fmt/pull/339>`_ and `#340 <https://github.com/fmtlib/fmt/pull/340>`_):
+
+ .. code:: c++
+
+ #include "fmt/printf.h"
+
+ // %s format specifier can be used with any argument type.
+ fmt::printf("%s", 42);
+
+ Thanks `@mojoBrendan <https://github.com/mojoBrendan>`_, `@manylegged (Arthur Danskin) <https://github.com/manylegged>`_ and `@spacemoose (Glen Stark) <https://github.com/spacemoose>`_. See also `#360 <https://github.com/fmtlib/fmt/issues/360>`_, `#335 <https://github.com/fmtlib/fmt/issues/335>`_ and `#331 <https://github.com/fmtlib/fmt/issues/331>`_.
+
+* Added ``container.h`` containing a ``BasicContainerWriter`` to write to containers like ``std::vector`` (`#450 <https://github.com/fmtlib/fmt/pull/450>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_.
+
+* Added ``fmt::join()`` function that takes a range and formats its elements separated by a given string (`#466 <https://github.com/fmtlib/fmt/pull/466>`_):
+
+ .. code:: c++
+
+ #include "fmt/format.h"
+
+ std::vector<double> v = {1.2, 3.4, 5.6};
+ // Prints "(+01.20, +03.40, +05.60)".
+ fmt::print("({:+06.2f})", fmt::join(v.begin(), v.end(), ", "));
+
+ Thanks `@olivier80 <https://github.com/olivier80>`_.
+
+* Added support for custom formatting specifications to simplify customization of built-in formatting (`#444 <https://github.com/fmtlib/fmt/pull/444>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_. See also `#439 <https://github.com/fmtlib/fmt/issues/439>`_.
+
+* Added ``fmt::format_system_error()`` for error code formatting (`#323 <https://github.com/fmtlib/fmt/issues/323>`_ and `#526 <https://github.com/fmtlib/fmt/pull/526>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
+
+* Added thread-safe ``fmt::localtime()`` and ``fmt::gmtime()`` as replacement for the standard version to ``time.h`` (`#396 <https://github.com/fmtlib/fmt/pull/396>`_). Thanks `@codicodi <https://github.com/codicodi>`_.
+
+* Internal improvements to ``NamedArg`` and ``ArgLists`` (`#389 <https://github.com/fmtlib/fmt/pull/389>`_ and `#390 <https://github.com/fmtlib/fmt/pull/390>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_.
+
+* Fixed crash due to bug in ``FormatBuf`` (`#493 <https://github.com/fmtlib/fmt/pull/493>`_). Thanks `@effzeh <https://github.com/effzeh>`_. See also `#480 <https://github.com/fmtlib/fmt/issues/480>`_ and `#491 <https://github.com/fmtlib/fmt/issues/491>`_.
+
+* Fixed handling of wide strings in ``fmt::StringWriter``.
+
+* Improved compiler error messages (`#357 <https://github.com/fmtlib/fmt/issues/357>`_).
+
+* Fixed various warnings and issues with various compilers (`#494 <https://github.com/fmtlib/fmt/pull/494>`_, `#499 <https://github.com/fmtlib/fmt/pull/499>`_, `#483 <https://github.com/fmtlib/fmt/pull/483>`_, `#519 <https://github.com/fmtlib/fmt/pull/519>`_, `#485 <https://github.com/fmtlib/fmt/pull/485>`_, `#482 <https://github.com/fmtlib/fmt/pull/482>`_, `#475 <https://github.com/fmtlib/fmt/pull/475>`_, `#473 <https://github.com/fmtlib/fmt/pull/473>`_ and `#414 <https://github.com/fmtlib/fmt/pull/414>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_, `@zhaohuaxishi <https://github.com/zhaohuaxishi>`_, `@pkestene (Pierre Kestener) <https://github.com/pkestene>`_, `@dschmidt (Dominik Schmidt) <https://github.com/dschmidt>`_ and `@0x414c (Alexey Gorishny) <https://github.com/0x414c>`_ .
+
+* Improved CMake: targets are now namespaced (`#511 <https://github.com/fmtlib/fmt/pull/511>`_ and `#513 <https://github.com/fmtlib/fmt/pull/513>`_), supported header-only ``printf.h`` (`#354 <https://github.com/fmtlib/fmt/pull/354>`_), fixed issue with minimal supported library subset (`#418 <https://github.com/fmtlib/fmt/issues/418>`_, `#419 <https://github.com/fmtlib/fmt/pull/419>`_ and `#420 <https://github.com/fmtlib/fmt/pull/420>`_). Thanks `@bjoernthiel (Bjoern Thiel) <https://github.com/bjoernthiel>`_,
+ `@niosHD (Mario Werner) <https://github.com/niosHD>`_, `@LogicalKnight (Sean LK) <https://github.com/LogicalKnight>`_ and `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
+
+* Improved documentation. Thanks to `@pwm1234 (Phil) <https://github.com/pwm1234>`_ for `#393 <https://github.com/fmtlib/fmt/pull/393>`_.
+
+3.0.2 - 2017-06-14
+------------------
+
+* Added ``FMT_VERSION`` macro (`#411 <https://github.com/fmtlib/fmt/issues/411>`_).
+
+* Used ``FMT_NULL`` instead of literal ``0`` (`#409 <https://github.com/fmtlib/fmt/pull/409>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
+
+* Added extern templates for ``format_float`` (`#413 <https://github.com/fmtlib/fmt/issues/413>`_).
+
+* Fixed implicit conversion issue (`#507 <https://github.com/fmtlib/fmt/issues/507>`_).
+
+* Fixed signbit detection (`#423 <https://github.com/fmtlib/fmt/issues/423>`_).
+
+* Fixed naming collision (`#425 <https://github.com/fmtlib/fmt/issues/425>`_).
+
+* Fixed missing intrinsic for C++/CLI (`#457 <https://github.com/fmtlib/fmt/pull/457>`_). Thanks `@calumr (Calum Robinson) <https://github.com/calumr>`_
+
+* Fixed Android detection (`#458 <https://github.com/fmtlib/fmt/pull/458>`_). Thanks `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_.
+
+* Use lean ``windows.h`` if not in header-only mode (`#503 <https://github.com/fmtlib/fmt/pull/503>`_). Thanks `@Quentin01 (Quentin Buathier) <https://github.com/Quentin01>`_.
+
+* Fixed issue with CMake exporting C++11 flag (`#445 <https://github.com/fmtlib/fmt/pull/455>`_). Thanks `@EricWF (Eric) <https://github.com/EricWF>`_.
+
+* Fixed issue with nvcc and MSVC compiler bug and MinGW (`#505 <https://github.com/fmtlib/fmt/issues/505>`_).
+
+* Fixed DLL issues (`#469 <https://github.com/fmtlib/fmt/pull/469>`_ and `#502 <https://github.com/fmtlib/fmt/pull/502>`_). Thanks `@richardeakin (Richard Eakin) <https://github.com/richardeakin>`_ and `@AndreasSchoenle (Andreas Schönle) <https://github.com/AndreasSchoenle>`_.
+
+* Fixed test compilation under FreeBSD (`#433 <https://github.com/fmtlib/fmt/issues/433>`_).
+
+* Fixed various warnings (`#403 <https://github.com/fmtlib/fmt/pull/403>`_, `#410 <https://github.com/fmtlib/fmt/pull/410>`_ and `#510 <https://github.com/fmtlib/fmt/pull/510>`_). Thanks `@Lecetem <https://github.com/Lectem>`_, `@chenhayat (Chen Hayat) <https://github.com/chenhayat>`_ and `@trozen <https://github.com/trozen>`_.
+
+* Removed redundant include (`#479 <https://github.com/fmtlib/fmt/issues/479>`_).
+
+* Fixed documentation issues.
+
3.0.1 - 2016-11-01
------------------
* Fixed handling of thousands seperator (`#353 <https://github.com/fmtlib/fmt/issues/353>`_)
diff --git a/dep/fmt/README.rst b/dep/fmt/README.rst
index 846d0eb0979..32f50257eb8 100644
--- a/dep/fmt/README.rst
+++ b/dep/fmt/README.rst
@@ -40,7 +40,7 @@ Features
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
+* Small code size both in terms of source code (the core library 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
@@ -138,6 +138,12 @@ Projects using this library
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle
+* `Drake <http://drake.mit.edu/>`_: A planning, control, and analysis toolbox for nonlinear dynamical systems (MIT)
+
+* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus (Lyft)
+
+* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
+
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
Player vs Player Gaming Network with tweaks
@@ -145,10 +151,14 @@ Projects using this library
* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
+* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
+
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
+* `OpenSpace <http://openspaceproject.com/>`_: An open-source astrovisualization framework
+
* `PenUltima Online (POL) <http://www.polserver.com/>`_:
An MMO server, compatible with most Ultima Online clients
@@ -402,6 +412,11 @@ It only applies if you distribute the documentation of fmt.
Acknowledgments
---------------
+The fmt library is maintained by Victor Zverovich (`vitaut <https://github.com/vitaut>`_)
+and Jonathan Müller (`foonathan <https://github.com/foonathan>`_) with contributions from many
+other people. See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and `Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. Let us know if your contribution
+is not listed or mentioned incorrectly and we'll make it right.
+
The benchmark section of this readme file and the performance tests are taken
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
written by Chris Foster. Boost Format library is acknowledged transitively
diff --git a/dep/fmt/cppformat/format.cc b/dep/fmt/cppformat/format.cc
deleted file mode 100644
index daccd68f1da..00000000000
--- a/dep/fmt/cppformat/format.cc
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- Formatting library for C++
-
- Copyright (c) 2012 - 2015, 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 FMT_HEADER_ONLY
-# define FMT_FUNC inline
-#else
-# define FMT_FUNC
-#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 {
-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)(fmt::Writer &, int, fmt::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(fmt::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(fmt::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(fmt::Writer &out, int error_code,
- fmt::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 fmt::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 += fmt::internal::count_digits(abs_value);
- if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
- out << message << SEP;
- out << ERROR_STR << error_code;
- assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
-}
-
-void report_error(FormatFunc func,
- int error_code, fmt::StringRef message) FMT_NOEXCEPT {
- fmt::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 fmt::internal::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 fmt::internal::ArgVisitor<WidthHandler, unsigned> {
- private:
- fmt::FormatSpec &spec_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
-
- public:
- explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
-
- void report_unhandled_arg() {
- FMT_THROW(fmt::FormatError("width is not integer"));
- }
-
- template <typename T>
- unsigned visit_any_int(T value) {
- typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
- UnsignedType width = static_cast<UnsignedType>(value);
- if (fmt::internal::is_negative(value)) {
- spec_.align_ = fmt::ALIGN_LEFT;
- width = 0 - width;
- }
- if (width > INT_MAX)
- FMT_THROW(fmt::FormatError("number is too big"));
- return static_cast<unsigned>(width);
- }
-};
-
-class PrecisionHandler :
- public fmt::internal::ArgVisitor<PrecisionHandler, int> {
- public:
- void report_unhandled_arg() {
- FMT_THROW(fmt::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(fmt::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 fmt::internal::ArgVisitor<ArgConverter<T>, void> {
- private:
- fmt::internal::Arg &arg_;
- wchar_t type_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
-
- public:
- ArgConverter(fmt::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 fmt::internal::Arg;
- typedef typename fmt::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 fmt::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<fmt::LongLong>(value);
- } else {
- arg_.type = Arg::ULONG_LONG;
- arg_.ulong_long_value =
- static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
- }
- }
- }
-};
-
-// Converts an integer argument to char for printf.
-class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
- private:
- fmt::internal::Arg &arg_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
-
- public:
- explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
-
- template <typename T>
- void visit_any_int(T value) {
- arg_.type = Arg::CHAR;
- arg_.int_value = static_cast<char>(value);
- }
-};
-
-// Write the content of w to os.
-void write(std::ostream &os, fmt::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);
-}
-} // 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(std::ostream &os, CStringRef format_str,
- ArgList args) {
- MemoryWriter w;
- w.write(format_str, args);
- write(os, w);
-}
-
-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);
-}
-
-FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args) {
- MemoryWriter w;
- printf(w, format, args);
- write(os, w);
- return static_cast<int>(w.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/fmt/cppformat/format.h b/dep/fmt/cppformat/format.h
deleted file mode 100644
index 3fbf86b894c..00000000000
--- a/dep/fmt/cppformat/format.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "../fmt/format.h"
-#warning Including cppformat/format.h is deprecated. Include fmt/format.h instead.
diff --git a/dep/fmt/cppformat/posix.cc b/dep/fmt/cppformat/posix.cc
deleted file mode 100644
index c6c2ae2c413..00000000000
--- a/dep/fmt/cppformat/posix.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- A C++ interface to POSIX functions.
-
- Copyright (c) 2014 - 2015, 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.
- */
-
-// 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_)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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) {
- 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)
- 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)
- 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)
- throw SystemError(errno, "cannot get memory page size");
- return size;
-#endif
-}
diff --git a/dep/fmt/cppformat/posix.h b/dep/fmt/cppformat/posix.h
deleted file mode 100644
index 97b6fadcdea..00000000000
--- a/dep/fmt/cppformat/posix.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "../fmt/posix.h"
-#warning Including cppformat/posix.h is deprecated. Include fmt/posix.h instead.
diff --git a/dep/fmt/fmt/container.h b/dep/fmt/fmt/container.h
new file mode 100644
index 00000000000..cb6303fb7e4
--- /dev/null
+++ b/dep/fmt/fmt/container.h
@@ -0,0 +1,82 @@
+/*
+ Formatting library for C++ - standard container utilities
+
+ Copyright (c) 2012 - 2016, Victor Zverovich
+ All rights reserved.
+
+ For the license information refer to format.h.
+ */
+
+#ifndef FMT_CONTAINER_H_
+#define FMT_CONTAINER_H_
+
+#include "format.h"
+
+namespace fmt {
+
+namespace internal {
+
+/**
+ \rst
+ A "buffer" that appends data to a standard container (e.g. typically a
+ ``std::vector`` or ``std::basic_string``).
+ \endrst
+ */
+template <typename Container>
+class ContainerBuffer : public Buffer<typename Container::value_type> {
+ private:
+ Container& container_;
+
+ protected:
+ virtual void grow(std::size_t size) FMT_OVERRIDE {
+ container_.resize(size);
+ this->ptr_ = &container_[0];
+ this->capacity_ = size;
+ }
+
+ public:
+ explicit ContainerBuffer(Container& container) : container_(container) {
+ this->size_ = container_.size();
+ if (this->size_ > 0) {
+ this->ptr_ = &container_[0];
+ this->capacity_ = this->size_;
+ }
+ }
+};
+} // namespace internal
+
+/**
+ \rst
+ This class template provides operations for formatting and appending data
+ to a standard *container* like ``std::vector`` or ``std::basic_string``.
+
+ **Example**::
+
+ void vecformat(std::vector<char>& dest, fmt::BasicCStringRef<char> format,
+ fmt::ArgList args) {
+ fmt::BasicContainerWriter<std::vector<char> > appender(dest);
+ appender.write(format, args);
+ }
+ FMT_VARIADIC(void, vecformat, std::vector<char>&,
+ fmt::BasicCStringRef<char>);
+ \endrst
+ */
+template <class Container>
+class BasicContainerWriter
+ : public BasicWriter<typename Container::value_type> {
+ private:
+ internal::ContainerBuffer<Container> buffer_;
+
+ public:
+ /**
+ \rst
+ Constructs a :class:`fmt::BasicContainerWriter` object.
+ \endrst
+ */
+ explicit BasicContainerWriter(Container& dest)
+ : BasicWriter<typename Container::value_type>(buffer_), buffer_(dest) {}
+};
+
+} // namespace fmt
+
+#endif // FMT_CONTAINER_H_
diff --git a/dep/fmt/fmt/format.cc b/dep/fmt/fmt/format.cc
index 2bd774e4408..2d236bc641d 100644
--- a/dep/fmt/fmt/format.cc
+++ b/dep/fmt/fmt/format.cc
@@ -41,6 +41,9 @@
#endif
#if FMT_USE_WINDOWS_H
+# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
+# define WIN32_LEAN_AND_MEAN
+# endif
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
# include <windows.h>
# else
@@ -50,8 +53,6 @@
# endif
#endif
-using fmt::internal::Arg;
-
#if FMT_EXCEPTIONS
# define FMT_TRY try
# define FMT_CATCH(x) catch (x)
@@ -71,18 +72,20 @@ using fmt::internal::Arg;
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
+FMT_MAYBE_UNUSED
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
return fmt::internal::Null<>();
}
+FMT_MAYBE_UNUSED
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() {}
+FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
+FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
+FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
namespace {
@@ -105,27 +108,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
# 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);
@@ -141,7 +123,7 @@ typedef void (*FormatFunc)(Writer &, int, StringRef);
// 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");
+ FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
class StrError {
private:
@@ -179,6 +161,11 @@ int safe_strerror(
ERANGE : result;
}
+#ifdef __c2__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
// Fallback to strerror if strerror_r and strerror_s are not available.
int fallback(internal::Null<>) {
errno = 0;
@@ -186,12 +173,15 @@ int safe_strerror(
return errno;
}
+#ifdef __c2__
+# pragma clang diagnostic pop
+#endif
+
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_));
}
};
@@ -230,222 +220,19 @@ void report_error(FormatFunc func, int error_code,
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(
+FMT_FUNC void 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));
+ 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(
+int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, T value) {
if (width == 0) {
@@ -459,7 +246,7 @@ int fmt::internal::CharTraits<char>::format_float(
}
template <typename T>
-int fmt::internal::CharTraits<wchar_t>::format_float(
+int 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) {
@@ -473,7 +260,7 @@ int fmt::internal::CharTraits<wchar_t>::format_float(
}
template <typename T>
-const char fmt::internal::BasicData<T>::DIGITS[] =
+const char internal::BasicData<T>::DIGITS[] =
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
@@ -492,40 +279,40 @@ const char fmt::internal::BasicData<T>::DIGITS[] =
factor * 1000000000
template <typename T>
-const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
+const uint32_t 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[] = {
+const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
0,
FMT_POWERS_OF_10(1),
- FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
+ FMT_POWERS_OF_10(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
+ ULongLong(1000000000) * ULongLong(1000000000) * 10
};
-FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
+FMT_FUNC void 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(FormatError(
+ format("unknown format code '{}' for {}", code, type)));
}
- FMT_THROW(fmt::FormatError(
- fmt::format("unknown format code '\\x{:02x}' for {}",
+ FMT_THROW(FormatError(
+ 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) {
+FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(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);
+ CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1);
@@ -536,30 +323,31 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
buffer_[length] = 0;
}
-FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
+FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(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) {
+FMT_FUNC int internal::UTF16ToUTF8::convert(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);
+ int length = WideCharToMultiByte(
+ CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_.resize(length + 1);
length = WideCharToMultiByte(
- CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
+ CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_[length] = 0;
return 0;
}
-FMT_FUNC void fmt::WindowsError::init(
+FMT_FUNC void WindowsError::init(
int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code;
MemoryWriter w;
@@ -568,17 +356,17 @@ FMT_FUNC void fmt::WindowsError::init(
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_FUNC void internal::format_windows_error(
+ Writer &out, int error_code, 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);
+ int result = FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
if (result != 0) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@@ -597,12 +385,11 @@ FMT_FUNC void fmt::internal::format_windows_error(
#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_FUNC void format_system_error(
+ Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
- MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
- buffer.resize(INLINE_BUFFER_SIZE);
+ internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
+ buffer.resize(internal::INLINE_BUFFER_SIZE);
for (;;) {
char *system_message = &buffer[0];
int result = safe_strerror(error_code, system_message, buffer.size());
@@ -619,63 +406,18 @@ FMT_FUNC void fmt::internal::format_system_error(
}
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) {
+void internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
}
-FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
+FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg(
unsigned arg_index, const char *&error) {
- Arg arg = args_[arg_index];
+ internal::Arg arg = args_[arg_index];
switch (arg.type) {
- case Arg::NONE:
+ case internal::Arg::NONE:
error = "argument index out of range";
break;
- case Arg::NAMED_ARG:
+ case internal::Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer);
break;
default:
@@ -684,203 +426,31 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
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(
+FMT_FUNC void 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);
+ report_error(format_system_error, error_code, message);
}
#if FMT_USE_WINDOWS_H
-FMT_FUNC void fmt::report_windows_error(
+FMT_FUNC void 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);
+ report_error(internal::format_windows_error, error_code, message);
}
#endif
-FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
+FMT_FUNC void 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) {
+FMT_FUNC void print(CStringRef format_str, ArgList args) {
print(stdout, format_str, args);
}
-FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
+FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
char escape[] = "\x1b[30m";
escape[3] = static_cast<char>('0' + c);
std::fputs(escape, stdout);
@@ -888,53 +458,38 @@ FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList 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>;
+template struct 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 void internal::FixedBuffer<char>::grow(std::size_t);
-template int fmt::internal::CharTraits<char>::format_float(
+template FMT_API int 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(
+template FMT_API int 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 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(
+template FMT_API int 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(
+template FMT_API int 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
+} // namespace fmt
+
#ifdef _MSC_VER
# pragma warning(pop)
#endif
diff --git a/dep/fmt/fmt/format.h b/dep/fmt/fmt/format.h
index f8ce147cb38..dd8d2836005 100644
--- a/dep/fmt/fmt/format.h
+++ b/dep/fmt/fmt/format.h
@@ -28,6 +28,7 @@
#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_
+#define FMT_INCLUDE
#include <cassert>
#include <clocale>
#include <cmath>
@@ -38,9 +39,27 @@
#include <stdexcept>
#include <string>
#include <vector>
-#include <utility>
+#include <utility> // for std::pair
+#undef FMT_INCLUDE
-#ifdef _SECURE_SCL
+// The fmt library version in the form major * 10000 + minor * 100 + patch.
+#define FMT_VERSION 40001
+
+#if defined(__has_include)
+# define FMT_HAS_INCLUDE(x) __has_include(x)
+#else
+# define FMT_HAS_INCLUDE(x) 0
+#endif
+
+#if (FMT_HAS_INCLUDE(<string_view>) && __cplusplus > 201402L) || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
+# include <string_view>
+# define FMT_HAS_STRING_VIEW 1
+#else
+# define FMT_HAS_STRING_VIEW 0
+#endif
+
+#if defined _SECURE_SCL && _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
#else
# define FMT_SECURE_SCL 0
@@ -94,7 +113,9 @@ typedef __int64 intmax_t;
# define FMT_HAS_GXX_CXX11 1
# endif
#else
+# define FMT_GCC_VERSION 0
# define FMT_GCC_EXTENSION
+# define FMT_HAS_GXX_CXX11 0
#endif
#if defined(__INTEL_COMPILER)
@@ -104,6 +125,7 @@ typedef __int64 intmax_t;
#endif
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
+# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
# pragma clang diagnostic ignored "-Wpadded"
@@ -131,6 +153,32 @@ typedef __int64 intmax_t;
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
+#if FMT_HAS_CPP_ATTRIBUTE(maybe_unused)
+# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
+// VC++ 1910 support /std: option and that will set _MSVC_LANG macro
+// Clang with Microsoft CodeGen doesn't define _MSVC_LANG macro
+#elif defined(_MSVC_LANG) && _MSVC_LANG > 201402
+# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
+#endif
+
+#ifdef FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
+# define FMT_MAYBE_UNUSED [[maybe_unused]]
+// g++/clang++ also support [[gnu::unused]]. However, we don't use it.
+#elif defined(__GNUC__)
+# define FMT_MAYBE_UNUSED __attribute__((unused))
+#else
+# define FMT_MAYBE_UNUSED
+#endif
+
+// Use the compiler's attribute noreturn
+#if defined(__MINGW32__) || defined(__MINGW64__)
+# define FMT_NORETURN __attribute__((noreturn))
+#elif FMT_HAS_CPP_ATTRIBUTE(noreturn) && __cplusplus >= 201103L
+# define FMT_NORETURN [[noreturn]]
+#else
+# define FMT_NORETURN
+#endif
+
#ifndef FMT_USE_VARIADIC_TEMPLATES
// Variadic templates are available in GCC since version 4.4
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
@@ -152,10 +200,6 @@ typedef __int64 intmax_t;
# endif
#endif
-#if FMT_USE_RVALUE_REFERENCES
-# include <utility> // for std::move
-#endif
-
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@@ -180,22 +224,32 @@ typedef __int64 intmax_t;
# define FMT_USE_NOEXCEPT 0
#endif
-#ifndef FMT_NOEXCEPT
-# if FMT_EXCEPTIONS
-# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
+#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1900
-# define FMT_NOEXCEPT noexcept
-# else
-# define FMT_NOEXCEPT throw()
-# endif
+# define FMT_DETECTED_NOEXCEPT noexcept
+#else
+# define FMT_DETECTED_NOEXCEPT throw()
+#endif
+
+#ifndef FMT_NOEXCEPT
+# if FMT_EXCEPTIONS
+# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
# else
# define FMT_NOEXCEPT
# endif
#endif
+// This is needed because GCC still uses throw() in its headers when exceptions
+// are disabled.
+#if FMT_GCC_VERSION
+# define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
+#else
+# define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
+#endif
+
#ifndef FMT_OVERRIDE
-# if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \
+# if (defined(FMT_USE_OVERRIDE) && FMT_USE_OVERRIDE) || FMT_HAS_FEATURE(cxx_override) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1900
# define FMT_OVERRIDE override
@@ -204,6 +258,15 @@ typedef __int64 intmax_t;
# endif
#endif
+#ifndef FMT_NULL
+# if FMT_HAS_FEATURE(cxx_nullptr) || \
+ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
+ FMT_MSC_VER >= 1600
+# define FMT_NULL nullptr
+# else
+# define FMT_NULL NULL
+# endif
+#endif
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
@@ -224,40 +287,75 @@ typedef __int64 intmax_t;
TypeName& operator=(const TypeName&)
#endif
+#ifndef FMT_USE_DEFAULTED_FUNCTIONS
+# define FMT_USE_DEFAULTED_FUNCTIONS 0
+#endif
+
+#ifndef FMT_DEFAULTED_COPY_CTOR
+# if FMT_USE_DEFAULTED_FUNCTIONS || FMT_HAS_FEATURE(cxx_defaulted_functions) || \
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
+# define FMT_DEFAULTED_COPY_CTOR(TypeName) \
+ TypeName(const TypeName&) = default;
+# else
+# define FMT_DEFAULTED_COPY_CTOR(TypeName)
+# endif
+#endif
+
#ifndef FMT_USE_USER_DEFINED_LITERALS
// 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 && \
+# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
(FMT_HAS_FEATURE(cxx_user_literals) || \
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
+# define FMT_USE_USER_DEFINED_LITERALS 1
+# else
+# define FMT_USE_USER_DEFINED_LITERALS 0
+# endif
+#endif
+
+#ifndef FMT_USE_EXTERN_TEMPLATES
+# define FMT_USE_EXTERN_TEMPLATES \
+ (FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
+#endif
+
+#ifdef FMT_HEADER_ONLY
+// If header only do not use extern templates.
+# undef FMT_USE_EXTERN_TEMPLATES
+# define FMT_USE_EXTERN_TEMPLATES 0
#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
+// __builtin_clz is broken in clang with Microsoft CodeGen:
+// https://github.com/fmtlib/fmt/issues/519
+#ifndef _MSC_VER
+# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
+# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
+# endif
-#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
-# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
+# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
+# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
+# endif
#endif
// 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 FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL)
+#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
namespace fmt {
namespace internal {
-# pragma intrinsic(_BitScanReverse)
+// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
+# ifndef __clang__
+# pragma intrinsic(_BitScanReverse)
+# endif
inline uint32_t clz(uint32_t x) {
unsigned long r = 0;
_BitScanReverse(&r, x);
@@ -271,7 +369,8 @@ inline uint32_t clz(uint32_t x) {
}
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
-# ifdef _WIN64
+// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
+# if defined(_WIN64) && !defined(__clang__)
# pragma intrinsic(_BitScanReverse64)
# endif
@@ -360,8 +459,10 @@ class numeric_limits<fmt::internal::DummyInt> :
// Portable version of signbit.
static bool isnegative(double x) {
using namespace fmt::internal;
- if (const_check(sizeof(signbit(x)) == sizeof(int)))
+ if (const_check(sizeof(signbit(x)) == sizeof(bool) ||
+ sizeof(signbit(x)) == sizeof(int))) {
return signbit(x) != 0;
+ }
if (x < 0) return true;
if (!isnotanumber(x)) return false;
int dec = 0, sign = 0;
@@ -392,13 +493,19 @@ typedef BasicWriter<wchar_t> WWriter;
template <typename Char>
class ArgFormatter;
+struct FormatSpec;
+
+template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
+class BasicPrintfArgFormatter;
+
template <typename CharType,
typename ArgFormatter = fmt::ArgFormatter<CharType> >
class BasicFormatter;
/**
\rst
- A string reference. It can be constructed from a C string or ``std::string``.
+ A string reference. It can be constructed from a C string or
+ ``std::basic_string``.
You can use one of the following typedefs for common character types:
@@ -441,12 +548,34 @@ class BasicStringRef {
/**
\rst
- Constructs a string reference from an ``std::string`` object.
+ Constructs a string reference from a ``std::basic_string`` object.
\endrst
*/
- BasicStringRef(const std::basic_string<Char> &s)
+ template <typename Allocator>
+ BasicStringRef(
+ const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
: data_(s.c_str()), size_(s.size()) {}
+#if FMT_HAS_STRING_VIEW
+ /**
+ \rst
+ Constructs a string reference from a ``std::basic_string_view`` object.
+ \endrst
+ */
+ BasicStringRef(
+ const std::basic_string_view<Char, std::char_traits<Char>> &s)
+ : data_(s.data()), size_(s.size()) {}
+
+ /**
+ \rst
+ Converts a string reference to an ``std::string_view`` object.
+ \endrst
+ */
+ explicit operator std::basic_string_view<Char>() const FMT_NOEXCEPT {
+ return std::basic_string_view<Char>(data_, size_);
+ }
+#endif
+
/**
\rst
Converts a string reference to an ``std::string`` object.
@@ -497,7 +626,7 @@ typedef BasicStringRef<wchar_t> WStringRef;
/**
\rst
A reference to a null terminated string. It can be constructed from a C
- string or ``std::string``.
+ string or ``std::basic_string``.
You can use one of the following typedefs for common character types:
@@ -530,10 +659,13 @@ class BasicCStringRef {
/**
\rst
- Constructs a string reference from an ``std::string`` object.
+ Constructs a string reference from a ``std::basic_string`` object.
\endrst
*/
- BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
+ template <typename Allocator>
+ BasicCStringRef(
+ const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
+ : data_(s.c_str()) {}
/** Returns the pointer to a C string. */
const Char *c_str() const { return data_; }
@@ -547,7 +679,8 @@ class FormatError : public std::runtime_error {
public:
explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {}
- ~FormatError() throw();
+ FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
+ FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
};
namespace internal {
@@ -605,7 +738,7 @@ class Buffer {
std::size_t size_;
std::size_t capacity_;
- Buffer(T *ptr = 0, std::size_t capacity = 0)
+ Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0)
: ptr_(ptr), size_(0), capacity_(capacity) {}
/**
@@ -663,7 +796,8 @@ class Buffer {
template <typename T>
template <typename U>
void Buffer<T>::append(const U *begin, const U *end) {
- std::size_t new_size = size_ + internal::to_unsigned(end - begin);
+ FMT_ASSERT(end >= begin, "negative value");
+ std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
if (new_size > capacity_)
grow(new_size);
std::uninitialized_copy(begin, end,
@@ -691,7 +825,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
public:
explicit MemoryBuffer(const Allocator &alloc = Allocator())
: Allocator(alloc), Buffer<T>(data_, SIZE) {}
- ~MemoryBuffer() { deallocate(); }
+ ~MemoryBuffer() FMT_OVERRIDE { deallocate(); }
#if FMT_USE_RVALUE_REFERENCES
private:
@@ -735,7 +869,7 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
if (size > new_capacity)
new_capacity = size;
- T *new_ptr = this->allocate(new_capacity);
+ T *new_ptr = this->allocate(new_capacity, FMT_NULL);
// The following code doesn't throw, so the raw pointer above doesn't leak.
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
make_ptr(new_ptr, new_capacity));
@@ -757,7 +891,7 @@ class FixedBuffer : public fmt::Buffer<Char> {
FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
protected:
- FMT_API void grow(std::size_t size);
+ FMT_API void grow(std::size_t size) FMT_OVERRIDE;
};
template <typename Char>
@@ -789,6 +923,15 @@ class CharTraits<char> : public BasicCharTraits<char> {
const char *format, unsigned width, int precision, T value);
};
+#if FMT_USE_EXTERN_TEMPLATES
+extern template int CharTraits<char>::format_float<double>
+ (char *buffer, std::size_t size,
+ const char* format, unsigned width, int precision, double value);
+extern template int CharTraits<char>::format_float<long double>
+ (char *buffer, std::size_t size,
+ const char* format, unsigned width, int precision, long double value);
+#endif
+
template <>
class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
public:
@@ -800,6 +943,15 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
const wchar_t *format, unsigned width, int precision, T value);
};
+#if FMT_USE_EXTERN_TEMPLATES
+extern template int CharTraits<wchar_t>::format_float<double>
+ (wchar_t *buffer, std::size_t size,
+ const wchar_t* format, unsigned width, int precision, double value);
+extern template int CharTraits<wchar_t>::format_float<long double>
+ (wchar_t *buffer, std::size_t size,
+ const wchar_t* format, unsigned width, int precision, long double value);
+#endif
+
// Checks if a number is negative - used to avoid warnings.
template <bool IsSigned>
struct SignChecker {
@@ -835,7 +987,7 @@ struct IntTraits {
TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
};
-FMT_API void report_unknown_type(char code, const char *type);
+FMT_API FMT_NORETURN void report_unknown_type(char code, const char *type);
// Static data is placed in this class template to allow header-only
// configuration.
@@ -846,13 +998,7 @@ 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)
+#if FMT_USE_EXTERN_TEMPLATES
extern template struct BasicData<void>;
#endif
@@ -950,7 +1096,8 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
template <typename UInt, typename Char>
inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
- return format_decimal(buffer, value, num_digits, NoThousandsSep());
+ format_decimal(buffer, value, num_digits, NoThousandsSep());
+ return;
}
#ifndef _WIN32
@@ -1000,9 +1147,6 @@ FMT_API void format_windows_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
#endif
-FMT_API void format_system_error(fmt::Writer &out, int error_code,
- fmt::StringRef message) FMT_NOEXCEPT;
-
// A formatting argument value.
struct Value {
template <typename Char>
@@ -1052,6 +1196,8 @@ struct Arg : Value {
template <typename Char>
struct NamedArg;
+template <typename Char, typename T>
+struct NamedArgWithType;
template <typename T = void>
struct Null {};
@@ -1080,17 +1226,17 @@ T &get();
Yes &convert(fmt::ULongLong);
No &convert(...);
-template<typename T, bool ENABLE_CONVERSION>
+template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl {
enum { value = ENABLE_CONVERSION };
};
-template<typename T, bool ENABLE_CONVERSION>
+template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl2 {
enum { value = false };
};
-template<typename T>
+template <typename T>
struct ConvertToIntImpl2<T, true> {
enum {
// Don't convert numeric types.
@@ -1098,9 +1244,11 @@ struct ConvertToIntImpl2<T, true> {
};
};
-template<typename T>
+template <typename T>
struct ConvertToInt {
- enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
+ enum {
+ enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
+ };
enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
};
@@ -1113,26 +1261,29 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
FMT_DISABLE_CONVERSION_TO_INT(double);
FMT_DISABLE_CONVERSION_TO_INT(long double);
-template<bool B, class T = void>
+template <bool B, class T = void>
struct EnableIf {};
-template<class T>
+template <class T>
struct EnableIf<true, T> { typedef T type; };
-template<bool B, class T, class F>
+template <bool B, class T, class F>
struct Conditional { typedef T type; };
-template<class T, class F>
+template <class T, class F>
struct Conditional<false, T, F> { typedef F type; };
// For bcc32 which doesn't understand ! in template arguments.
-template<bool>
+template <bool>
struct Not { enum { value = 0 }; };
-template<>
+template <>
struct Not<false> { enum { value = 1 }; };
-template<typename T, T> struct LConvCheck {
+template <typename T>
+struct FalseType { enum { value = 0 }; };
+
+template <typename T, T> struct LConvCheck {
LConvCheck(int) {}
};
@@ -1147,6 +1298,35 @@ inline StringRef thousands_sep(
inline fmt::StringRef thousands_sep(...) { return ""; }
+#define FMT_CONCAT(a, b) a##b
+
+#if FMT_GCC_VERSION >= 303
+# define FMT_UNUSED __attribute__((unused))
+#else
+# define FMT_UNUSED
+#endif
+
+#ifndef FMT_USE_STATIC_ASSERT
+# define FMT_USE_STATIC_ASSERT 0
+#endif
+
+#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
+ (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
+# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
+#else
+# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
+# define FMT_STATIC_ASSERT(cond, message) \
+ typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
+#endif
+
+template <typename Formatter>
+void format_arg(Formatter&, ...) {
+ FMT_STATIC_ASSERT(FalseType<Formatter>::value,
+ "Cannot format argument. To enable the use of ostream "
+ "operator<< include fmt/ostream.h. Otherwise provide "
+ "an overload of format_arg.");
+}
+
// Makes an Arg object from any type.
template <typename Formatter>
class MakeValue : public Arg {
@@ -1174,6 +1354,9 @@ class MakeValue : public Arg {
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const std::wstring &, Char>::Unsupported);
+#if FMT_HAS_STRING_VIEW
+ MakeValue(typename WCharHelper<const std::wstring_view &, Char>::Unsupported);
+#endif
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
void set_string(StringRef str) {
@@ -1190,9 +1373,9 @@ class MakeValue : public Arg {
template <typename T>
static void format_custom_arg(
void *formatter, const void *arg, void *format_str_ptr) {
- format(*static_cast<Formatter*>(formatter),
- *static_cast<const Char**>(format_str_ptr),
- *static_cast<const T*>(arg));
+ format_arg(*static_cast<Formatter*>(formatter),
+ *static_cast<const Char**>(format_str_ptr),
+ *static_cast<const T*>(arg));
}
public:
@@ -1243,6 +1426,20 @@ class MakeValue : public Arg {
FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
FMT_MAKE_VALUE(char, int_value, CHAR)
+#if __cplusplus >= 201103L
+ template <
+ typename T,
+ typename = typename std::enable_if<
+ std::is_enum<T>::value && ConvertToInt<T>::value>::type>
+ MakeValue(T value) { int_value = value; }
+
+ template <
+ typename T,
+ typename = typename std::enable_if<
+ std::is_enum<T>::value && ConvertToInt<T>::value>::type>
+ static uint64_t type(T) { return Arg::INT; }
+#endif
+
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
int_value = value;
@@ -1261,6 +1458,9 @@ class MakeValue : public Arg {
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)
+#if FMT_HAS_STRING_VIEW
+ FMT_MAKE_STR_VALUE(const std::string_view &, STRING)
+#endif
FMT_MAKE_STR_VALUE(StringRef, STRING)
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
@@ -1273,6 +1473,9 @@ class MakeValue : public Arg {
FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING)
+#if FMT_HAS_STRING_VIEW
+ FMT_MAKE_WSTR_VALUE(const std::wstring_view &, WSTRING)
+#endif
FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING)
FMT_MAKE_VALUE(void *, pointer, POINTER)
@@ -1287,23 +1490,22 @@ class MakeValue : public Arg {
}
template <typename T>
- MakeValue(const T &value,
- typename EnableIf<ConvertToInt<T>::value, int>::type = 0) {
- int_value = value;
- }
-
- template <typename T>
- static uint64_t type(const T &) {
- return ConvertToInt<T>::value ? Arg::INT : Arg::CUSTOM;
+ static typename EnableIf<Not<ConvertToInt<T>::value>::value, uint64_t>::type
+ type(const T &) {
+ return Arg::CUSTOM;
}
// Additional template param `Char_` is needed here because make_type always
// uses char.
template <typename Char_>
MakeValue(const NamedArg<Char_> &value) { pointer = &value; }
+ template <typename Char_, typename T>
+ MakeValue(const NamedArgWithType<Char_, T> &value) { pointer = &value; }
template <typename Char_>
static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }
+ template <typename Char_, typename T>
+ static uint64_t type(const NamedArgWithType<Char_, T> &) { return Arg::NAMED_ARG; }
};
template <typename Formatter>
@@ -1329,16 +1531,20 @@ struct NamedArg : Arg {
: Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {}
};
+template <typename Char, typename T>
+struct NamedArgWithType : NamedArg<Char> {
+ NamedArgWithType(BasicStringRef<Char> argname, const T &value)
+ : NamedArg<Char>(argname, value) {}
+};
+
class RuntimeError : public std::runtime_error {
protected:
RuntimeError() : std::runtime_error("") {}
- ~RuntimeError() throw();
+ RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
+ FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
};
template <typename Char>
-class PrintfArgFormatter;
-
-template <typename Char>
class ArgMap;
} // namespace internal
@@ -1359,10 +1565,7 @@ class ArgList {
};
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);
+ return type(types_, index);
}
template <typename Char>
@@ -1379,6 +1582,8 @@ class ArgList {
ArgList(ULongLong types, const internal::Arg *args)
: types_(types), args_(args) {}
+ uint64_t types() const { return types_; }
+
/** Returns the argument at specified index. */
internal::Arg operator[](unsigned index) const {
using internal::Arg;
@@ -1404,6 +1609,13 @@ class ArgList {
}
return args_[index];
}
+
+ static internal::Arg::Type type(uint64_t types, unsigned index) {
+ unsigned shift = index * 4;
+ uint64_t mask = 0xf;
+ return static_cast<internal::Arg::Type>(
+ (types & (mask << shift)) >> shift);
+ }
};
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
@@ -1588,6 +1800,7 @@ struct TypeSpec : EmptySpec {
int precision() const { return -1; }
bool flag(unsigned) const { return false; }
char type() const { return TYPE; }
+ char type_prefix() const { return TYPE; }
char fill() const { return ' '; }
};
@@ -1623,6 +1836,7 @@ struct AlignTypeSpec : AlignSpec {
bool flag(unsigned) const { return false; }
char type() const { return TYPE; }
+ char type_prefix() const { return TYPE; }
};
// A full format specifier.
@@ -1638,6 +1852,7 @@ struct FormatSpec : AlignSpec {
bool flag(unsigned f) const { return (flags_ & f) != 0; }
int precision() const { return precision_; }
char type() const { return type_; }
+ char type_prefix() const { return type_; }
};
// An integer format specifier.
@@ -1800,24 +2015,69 @@ class ArgMap {
MapType map_;
public:
- FMT_API void init(const ArgList &args);
+ void init(const ArgList &args);
- const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
+ const internal::Arg *find(const fmt::BasicStringRef<Char> &name) const {
// The list is unsorted, so just return the first matching name.
for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
it != end; ++it) {
if (it->first == name)
return &it->second;
}
- return 0;
+ return FMT_NULL;
}
};
-template <typename Impl, typename Char>
+template <typename Char>
+void ArgMap<Char>::init(const ArgList &args) {
+ if (!map_.empty())
+ return;
+ typedef internal::NamedArg<Char> NamedArg;
+ const NamedArg *named_arg = FMT_NULL;
+ 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 Impl, typename Char, typename Spec = fmt::FormatSpec>
class ArgFormatterBase : public ArgVisitor<Impl, void> {
private:
BasicWriter<Char> &writer_;
- FormatSpec &spec_;
+ Spec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatterBase);
@@ -1827,9 +2087,12 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
}
+ // workaround MSVC two-phase lookup issue
+ typedef internal::Arg Arg;
+
protected:
BasicWriter<Char> &writer() { return writer_; }
- FormatSpec &spec() { return spec_; }
+ Spec &spec() { return spec_; }
void write(bool value) {
const char *str_value = value ? "true" : "false";
@@ -1838,12 +2101,14 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
}
void write(const char *value) {
- Arg::StringValue<char> str = {value, value != 0 ? std::strlen(value) : 0};
+ Arg::StringValue<char> str = {value, value ? std::strlen(value) : 0};
writer_.write_str(str, spec_);
}
public:
- ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
+ typedef Spec SpecType;
+
+ ArgFormatterBase(BasicWriter<Char> &w, Spec &s)
: writer_(w), spec_(s) {}
template <typename T>
@@ -1853,8 +2118,10 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
void visit_any_double(T value) { writer_.write_double(value, spec_); }
void visit_bool(bool value) {
- if (spec_.type_)
- return visit_any_int(value);
+ if (spec_.type_) {
+ visit_any_int(value);
+ return;
+ }
write(value);
}
@@ -1894,13 +2161,14 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
write(value);
}
- void visit_string(Arg::StringValue<char> value) {
+ // Qualification with "internal" here and below is a workaround for nvcc.
+ void visit_string(internal::Arg::StringValue<char> value) {
writer_.write_str(value, spec_);
}
using ArgVisitor<Impl, void>::visit_wstring;
- void visit_wstring(Arg::StringValue<Char> value) {
+ void visit_wstring(internal::Arg::StringValue<Char> value) {
writer_.write_str(value, spec_);
}
@@ -1956,26 +2224,6 @@ class FormatterBase {
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
}
};
-
-// A printf formatter.
-template <typename Char>
-class PrintfFormatter : private FormatterBase {
- private:
- void parse_flags(FormatSpec &spec, const Char *&s);
-
- // Returns the argument with specified index or, if arg_index is equal
- // to the maximum unsigned value, the next argument.
- Arg get_arg(const Char *s,
- unsigned arg_index = (std::numeric_limits<unsigned>::max)());
-
- // Parses argument index, flags and width and returns the argument index.
- unsigned parse_header(const Char *&s, FormatSpec &spec);
-
- public:
- explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
- FMT_API void format(BasicWriter<Char> &writer,
- BasicCStringRef<Char> format_str);
-};
} // namespace internal
/**
@@ -1995,8 +2243,8 @@ class PrintfFormatter : private FormatterBase {
will be called.
\endrst
*/
-template <typename Impl, typename Char>
-class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
+template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
+class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec> {
private:
BasicFormatter<Char, Impl> &formatter_;
const Char *format_;
@@ -2011,11 +2259,11 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
\endrst
*/
BasicArgFormatter(BasicFormatter<Char, Impl> &formatter,
- FormatSpec &spec, const Char *fmt)
- : internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec),
+ Spec &spec, const Char *fmt)
+ : internal::ArgFormatterBase<Impl, Char, Spec>(formatter.writer(), spec),
formatter_(formatter), format_(fmt) {}
- /** Formats argument of a custom (user-defined) type. */
+ /** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) {
c.format(&formatter_, c.value, &format_);
}
@@ -2023,12 +2271,14 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
/** The default argument formatter. */
template <typename Char>
-class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
+class ArgFormatter :
+ public BasicArgFormatter<ArgFormatter<Char>, Char, FormatSpec> {
public:
/** Constructs an argument formatter object. */
ArgFormatter(BasicFormatter<Char> &formatter,
FormatSpec &spec, const Char *fmt)
- : BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {}
+ : BasicArgFormatter<ArgFormatter<Char>,
+ Char, FormatSpec>(formatter, spec, fmt) {}
};
/** This template formats data and writes the output to a writer. */
@@ -2104,12 +2354,13 @@ inline uint64_t make_type(const T &arg) {
return MakeValue< BasicFormatter<char> >::type(arg);
}
-template <unsigned N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
+template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
struct ArgArray;
-template <unsigned N>
+template <std::size_t N>
struct ArgArray<N, true/*IsPacked*/> {
- typedef Value Type[N > 0 ? N : 1];
+ // '+' is used to silence GCC -Wduplicated-branches warning.
+ typedef Value Type[N > 0 ? N : +1];
template <typename Formatter, typename T>
static Value make(const T &value) {
@@ -2125,7 +2376,7 @@ struct ArgArray<N, true/*IsPacked*/> {
}
};
-template <unsigned N>
+template <std::size_t N>
struct ArgArray<N, false/*IsPacked*/> {
typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
@@ -2265,7 +2516,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
*/
class SystemError : public internal::RuntimeError {
private:
- void init(int err_code, CStringRef format_str, ArgList args);
+ FMT_API void init(int err_code, CStringRef format_str, ArgList args);
protected:
int error_code_;
@@ -2277,17 +2528,10 @@ class SystemError : public internal::RuntimeError {
public:
/**
\rst
- Constructs a :class:`fmt::SystemError` object with the description
- of the form
-
- .. parsed-literal::
- *<message>*: *<system-message>*
-
- where *<message>* is the formatted message and *<system-message>* is
- the system message corresponding to the error code.
- *error_code* is a system error code as given by ``errno``.
- If *error_code* is not a valid error code such as -1, the system message
- may look like "Unknown error -1" and is platform-dependent.
+ Constructs a :class:`fmt::SystemError` object with a description
+ formatted with `fmt::format_system_error`. *message* and additional
+ arguments passed into the constructor are formatted similarly to
+ `fmt::format`.
**Example**::
@@ -2303,15 +2547,35 @@ class SystemError : public internal::RuntimeError {
SystemError(int error_code, CStringRef message) {
init(error_code, message, ArgList());
}
+ FMT_DEFAULTED_COPY_CTOR(SystemError)
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
- ~SystemError() throw();
+ FMT_API ~SystemError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
int error_code() const { return error_code_; }
};
/**
\rst
+ Formats an error returned by an operating system or a language runtime,
+ for example a file opening error, and writes it to *out* in the following
+ form:
+
+ .. parsed-literal::
+ *<message>*: *<system-message>*
+
+ where *<message>* is the passed message and *<system-message>* is
+ the system message corresponding to the error code.
+ *error_code* is a system error code as given by ``errno``.
+ If *error_code* is not a valid error code such as -1, the system message
+ may look like "Unknown error -1" and is platform-dependent.
+ \endrst
+ */
+FMT_API void format_system_error(fmt::Writer &out, int error_code,
+ fmt::StringRef message) FMT_NOEXCEPT;
+
+/**
+ \rst
This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`.
@@ -2398,16 +2662,16 @@ class BasicWriter {
void write_int(T value, Spec spec);
// Formats a floating-point number (double or long double).
- template <typename T>
- void write_double(T value, const FormatSpec &spec);
+ template <typename T, typename Spec>
+ void write_double(T value, const Spec &spec);
// Writes a formatted string.
template <typename StrChar>
CharPtr write_str(const StrChar *s, std::size_t size, const AlignSpec &spec);
- template <typename StrChar>
+ template <typename StrChar, typename Spec>
void write_str(const internal::Arg::StringValue<StrChar> &str,
- const FormatSpec &spec);
+ const Spec &spec);
// This following methods are private to disallow writing wide characters
// and strings to a char stream. If you want to print a wide string as a
@@ -2426,10 +2690,11 @@ class BasicWriter {
template<typename T>
void append_float_length(Char *&, T) {}
- template <typename Impl, typename Char_>
+ template <typename Impl, typename Char_, typename Spec_>
friend class internal::ArgFormatterBase;
- friend class internal::PrintfArgFormatter<Char>;
+ template <typename Impl, typename Char_, typename Spec_>
+ friend class BasicPrintfArgFormatter;
protected:
/**
@@ -2625,9 +2890,9 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
}
template <typename Char>
-template <typename StrChar>
+template <typename StrChar, typename Spec>
void BasicWriter<Char>::write_str(
- const internal::Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
+ const internal::Arg::StringValue<StrChar> &s, const Spec &spec) {
// Check if StrChar is convertible to Char.
internal::CharTraits<Char>::convert(StrChar());
if (spec.type_ && spec.type_ != 's')
@@ -2751,7 +3016,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
- prefix[prefix_size++] = spec.type();
+ prefix[prefix_size++] = spec.type_prefix();
}
unsigned num_digits = 0;
do {
@@ -2771,7 +3036,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
- prefix[prefix_size++] = spec.type();
+ prefix[prefix_size++] = spec.type_prefix();
}
unsigned num_digits = 0;
do {
@@ -2802,7 +3067,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
case 'n': {
unsigned num_digits = internal::count_digits(abs_value);
fmt::StringRef sep = "";
-#ifndef ANDROID
+#if !(defined(ANDROID) || defined(__ANDROID__))
sep = internal::thousands_sep(std::localeconv());
#endif
unsigned size = static_cast<unsigned>(
@@ -2819,8 +3084,8 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
}
template <typename Char>
-template <typename T>
-void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
+template <typename T, typename Spec>
+void BasicWriter<Char>::write_double(T value, const Spec &spec) {
// Check type.
char type = spec.type();
bool upper = false;
@@ -2921,7 +3186,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
// Format using snprintf.
Char fill = internal::CharTraits<Char>::cast(spec.fill());
unsigned n = 0;
- Char *start = 0;
+ Char *start = FMT_NULL;
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
#if FMT_MSC_VER
@@ -3198,56 +3463,6 @@ FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args);
*/
FMT_API void print(CStringRef format_str, ArgList args);
-template <typename Char>
-void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
- internal::PrintfFormatter<Char>(args).format(w, format);
-}
-
-/**
- \rst
- Formats arguments and returns the result as a string.
-
- **Example**::
-
- std::string message = fmt::sprintf("The answer is %d", 42);
- \endrst
-*/
-inline std::string sprintf(CStringRef format, ArgList args) {
- MemoryWriter w;
- printf(w, format, args);
- return w.str();
-}
-
-inline std::wstring sprintf(WCStringRef format, ArgList args) {
- WMemoryWriter w;
- printf(w, format, args);
- return w.str();
-}
-
-/**
- \rst
- Prints formatted data to the file *f*.
-
- **Example**::
-
- fmt::fprintf(stderr, "Don't %s!", "panic");
- \endrst
- */
-FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
-
-/**
- \rst
- Prints formatted data to ``stdout``.
-
- **Example**::
-
- fmt::printf("Elapsed time: %.2f seconds", 1.23);
- \endrst
- */
-inline int printf(CStringRef format, ArgList args) {
- return fprintf(stdout, format, args);
-}
-
/**
Fast integer formatter.
*/
@@ -3364,13 +3579,13 @@ inline void format_decimal(char *&buffer, T value) {
\endrst
*/
template <typename T>
-inline internal::NamedArg<char> arg(StringRef name, const T &arg) {
- return internal::NamedArg<char>(name, arg);
+inline internal::NamedArgWithType<char, T> arg(StringRef name, const T &arg) {
+ return internal::NamedArgWithType<char, T>(name, arg);
}
template <typename T>
-inline internal::NamedArg<wchar_t> arg(WStringRef name, const T &arg) {
- return internal::NamedArg<wchar_t>(name, arg);
+inline internal::NamedArgWithType<wchar_t, T> arg(WStringRef name, const T &arg) {
+ return internal::NamedArgWithType<wchar_t, T>(name, arg);
}
// The following two functions are deleted intentionally to disable
@@ -3399,7 +3614,6 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
-#define FMT_CONCAT(a, b) a##b
#define FMT_FOR_EACH_(N, f, ...) \
FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
#define FMT_FOR_EACH(f, ...) \
@@ -3513,12 +3727,7 @@ FMT_VARIADIC(std::string, format, CStringRef)
FMT_VARIADIC_W(std::wstring, format, WCStringRef)
FMT_VARIADIC(void, print, CStringRef)
FMT_VARIADIC(void, print, std::FILE *, CStringRef)
-
FMT_VARIADIC(void, print_colored, Color, CStringRef)
-FMT_VARIADIC(std::string, sprintf, CStringRef)
-FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
-FMT_VARIADIC(int, printf, CStringRef)
-FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
namespace internal {
template <typename Char>
@@ -3583,7 +3792,7 @@ inline internal::Arg BasicFormatter<Char, AF>::get_arg(
template <typename Char, typename AF>
inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s) {
- const char *error = 0;
+ const char *error = FMT_NULL;
internal::Arg arg = *s < '0' || *s > '9' ?
next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
if (error) {
@@ -3601,7 +3810,7 @@ inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s) {
do {
c = *++s;
} while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
- const char *error = 0;
+ const char *error = FMT_NULL;
internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
if (error)
FMT_THROW(FormatError(error));
@@ -3613,7 +3822,7 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
const Char *&format_str, const internal::Arg &arg) {
using internal::Arg;
const Char *s = format_str;
- FormatSpec spec;
+ typename ArgFormatter::SpecType spec;
if (*s == ':') {
if (arg.type == Arg::CUSTOM) {
arg.custom.format(this, arg.custom.value, &s);
@@ -3799,6 +4008,66 @@ void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
}
write(writer_, start, s);
}
+
+template <typename Char, typename It>
+struct ArgJoin {
+ It first;
+ It last;
+ BasicCStringRef<Char> sep;
+
+ ArgJoin(It first, It last, const BasicCStringRef<Char>& sep) :
+ first(first),
+ last(last),
+ sep(sep) {}
+};
+
+template <typename It>
+ArgJoin<char, It> join(It first, It last, const BasicCStringRef<char>& sep) {
+ return ArgJoin<char, It>(first, last, sep);
+}
+
+template <typename It>
+ArgJoin<wchar_t, It> join(It first, It last, const BasicCStringRef<wchar_t>& sep) {
+ return ArgJoin<wchar_t, It>(first, last, sep);
+}
+
+#if FMT_HAS_GXX_CXX11
+template <typename Range>
+auto join(const Range& range, const BasicCStringRef<char>& sep)
+ -> ArgJoin<char, decltype(std::begin(range))> {
+ return join(std::begin(range), std::end(range), sep);
+}
+
+template <typename Range>
+auto join(const Range& range, const BasicCStringRef<wchar_t>& sep)
+ -> ArgJoin<wchar_t, decltype(std::begin(range))> {
+ return join(std::begin(range), std::end(range), sep);
+}
+#endif
+
+template <typename ArgFormatter, typename Char, typename It>
+void format_arg(fmt::BasicFormatter<Char, ArgFormatter> &f,
+ const Char *&format_str, const ArgJoin<Char, It>& e) {
+ const Char* end = format_str;
+ if (*end == ':')
+ ++end;
+ while (*end && *end != '}')
+ ++end;
+ if (*end != '}')
+ FMT_THROW(FormatError("missing '}' in format string"));
+
+ It it = e.first;
+ if (it != e.last) {
+ const Char* save = format_str;
+ f.format(format_str, internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(*it++));
+ while (it != e.last) {
+ f.writer().write(e.sep);
+ format_str = save;
+ f.format(format_str, internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(*it++));
+ }
+ }
+ format_str = end + 1;
+}
} // namespace fmt
#if FMT_USE_USER_DEFINED_LITERALS
@@ -3821,7 +4090,7 @@ struct UdlArg {
const Char *str;
template <typename T>
- NamedArg<Char> operator=(T &&value) const {
+ NamedArgWithType<Char, T> operator=(T &&value) const {
return {str, std::forward<T>(value)};
}
};
diff --git a/dep/fmt/fmt/ostream.cc b/dep/fmt/fmt/ostream.cc
index bcb67fe1577..2d443f73054 100644
--- a/dep/fmt/fmt/ostream.cc
+++ b/dep/fmt/fmt/ostream.cc
@@ -11,9 +11,8 @@
namespace fmt {
-namespace {
-// Write the content of w to os.
-void write(std::ostream &os, Writer &w) {
+namespace internal {
+FMT_FUNC void write(std::ostream &os, Writer &w) {
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
@@ -31,13 +30,6 @@ void write(std::ostream &os, Writer &w) {
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());
+ internal::write(os, w);
}
} // namespace fmt
diff --git a/dep/fmt/fmt/ostream.h b/dep/fmt/fmt/ostream.h
index 29483c1bcbd..6848aac28c2 100644
--- a/dep/fmt/fmt/ostream.h
+++ b/dep/fmt/fmt/ostream.h
@@ -24,28 +24,27 @@ class FormatBuf : public std::basic_streambuf<Char> {
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);
- }
+ FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
+
+ protected:
+ // The put-area is actually always empty. This makes the implementation
+ // simpler and has the advantage that the streambuf and the buffer are always
+ // in sync and sputc never writes into uninitialized memory. The obvious
+ // disadvantage is that each call to sputc always results in a (virtual) call
+ // to overflow. There is no disadvantage here for sputn since this always
+ // results in a call to xsputn.
+
+ int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
+ if (!traits_type::eq_int_type(ch, traits_type::eof()))
+ buffer_.push_back(static_cast<Char>(ch));
return ch;
}
- size_t size() const {
- return to_unsigned(this->pptr() - start_);
+ std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
+ buffer_.append(s, s + count);
+ return count;
}
};
@@ -53,32 +52,38 @@ 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<>);
+ template <typename T>
+ typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
};
No &operator<<(std::ostream &, int);
-template<typename T>
+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)
};
};
+
+// Write the content of w to os.
+FMT_API void write(std::ostream &os, Writer &w);
} // 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) {
+template <typename Char, typename ArgFormatter_, typename T>
+void format_arg(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.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value;
- BasicStringRef<Char> str(&buffer[0], format_buf.size());
+ BasicStringRef<Char> str(&buffer[0], buffer.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
@@ -94,18 +99,6 @@ void format(BasicFormatter<Char, ArgFormatter> &f,
*/
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
diff --git a/dep/fmt/fmt/posix.cc b/dep/fmt/fmt/posix.cc
index 76eb7f05eb8..356668c135a 100644
--- a/dep/fmt/fmt/posix.cc
+++ b/dep/fmt/fmt/posix.cc
@@ -21,6 +21,9 @@
#ifndef _WIN32
# include <unistd.h>
#else
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
# include <windows.h>
# include <io.h>
@@ -79,7 +82,7 @@ void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
- file_ = 0;
+ file_ = FMT_NULL;
if (result != 0)
FMT_THROW(SystemError(errno, "cannot close file"));
}
diff --git a/dep/fmt/fmt/posix.h b/dep/fmt/fmt/posix.h
index be1286c425d..88512de5502 100644
--- a/dep/fmt/fmt/posix.h
+++ b/dep/fmt/fmt/posix.h
@@ -51,25 +51,6 @@
# endif
#endif
-#if FMT_GCC_VERSION >= 407
-# define FMT_UNUSED __attribute__((unused))
-#else
-# define FMT_UNUSED
-#endif
-
-#ifndef FMT_USE_STATIC_ASSERT
-# define FMT_USE_STATIC_ASSERT 0
-#endif
-
-#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
- (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
-# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
-#else
-# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
-# define FMT_STATIC_ASSERT(cond, message) \
- typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
-#endif
-
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
@@ -107,10 +88,10 @@ class BufferedFile {
public:
// Constructs a BufferedFile object which doesn't represent any file.
- BufferedFile() FMT_NOEXCEPT : file_(0) {}
+ BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any.
- ~BufferedFile() FMT_NOEXCEPT;
+ FMT_API ~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -129,7 +110,7 @@ public:
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
- f.file_ = 0;
+ f.file_ = FMT_NULL;
}
// A "move assignment operator" for moving from a temporary.
@@ -143,7 +124,7 @@ public:
BufferedFile &operator=(BufferedFile &other) {
close();
file_ = other.file_;
- other.file_ = 0;
+ other.file_ = FMT_NULL;
return *this;
}
@@ -151,7 +132,7 @@ public:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {file_};
- file_ = 0;
+ file_ = FMT_NULL;
return p;
}
@@ -161,29 +142,29 @@ public:
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
- other.file_ = 0;
+ other.file_ = FMT_NULL;
}
BufferedFile& operator=(BufferedFile &&other) {
close();
file_ = other.file_;
- other.file_ = 0;
+ other.file_ = FMT_NULL;
return *this;
}
#endif
// Opens a file.
- BufferedFile(CStringRef filename, CStringRef mode);
+ FMT_API BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file.
- void close();
+ FMT_API void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return file_; }
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
- int (fileno)() const;
+ FMT_API int (fileno)() const;
void print(CStringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args);
@@ -216,7 +197,7 @@ class File {
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
- File(CStringRef path, int oflag);
+ FMT_API File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -279,43 +260,43 @@ class File {
#endif
// Destroys the object closing the file it represents if any.
- ~File() FMT_NOEXCEPT;
+ FMT_API ~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT { return fd_; }
// Closes the file.
- void close();
+ FMT_API void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
- LongLong size() const;
+ FMT_API LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
- std::size_t read(void *buffer, std::size_t count);
+ FMT_API std::size_t read(void *buffer, std::size_t count);
// Attempts to write count bytes from the specified buffer to the file.
- std::size_t write(const void *buffer, std::size_t count);
+ FMT_API std::size_t write(const void *buffer, std::size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
- static File dup(int fd);
+ FMT_API static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
- void dup2(int fd);
+ FMT_API void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
- void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
+ FMT_API void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
- static void pipe(File &read_end, File &write_end);
+ FMT_API static void pipe(File &read_end, File &write_end);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
- BufferedFile fdopen(const char *mode);
+ FMT_API BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
@@ -355,7 +336,7 @@ class Locale {
public:
typedef locale_t Type;
- Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
+ Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
if (!locale_)
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
}
@@ -366,7 +347,7 @@ class Locale {
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const {
- char *end = 0;
+ char *end = FMT_NULL;
double result = strtod_l(str, &end, locale_);
str = end;
return result;
diff --git a/dep/fmt/fmt/printf.cc b/dep/fmt/fmt/printf.cc
new file mode 100644
index 00000000000..95d7a36ab67
--- /dev/null
+++ b/dep/fmt/fmt/printf.cc
@@ -0,0 +1,32 @@
+/*
+ Formatting library for C++
+
+ Copyright (c) 2012 - 2016, Victor Zverovich
+ All rights reserved.
+
+ For the license information refer to format.h.
+ */
+
+#include "format.h"
+#include "printf.h"
+
+namespace fmt {
+
+template <typename Char>
+void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args);
+
+FMT_FUNC int 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 void PrintfFormatter<char>::format(CStringRef format);
+template void PrintfFormatter<wchar_t>::format(WCStringRef format);
+
+#endif // FMT_HEADER_ONLY
+
+} // namespace fmt
diff --git a/dep/fmt/fmt/printf.h b/dep/fmt/fmt/printf.h
new file mode 100644
index 00000000000..db91022c598
--- /dev/null
+++ b/dep/fmt/fmt/printf.h
@@ -0,0 +1,603 @@
+/*
+ Formatting library for C++
+
+ Copyright (c) 2012 - 2016, Victor Zverovich
+ All rights reserved.
+
+ For the license information refer to format.h.
+ */
+
+#ifndef FMT_PRINTF_H_
+#define FMT_PRINTF_H_
+
+#include <algorithm> // std::fill_n
+#include <limits> // std::numeric_limits
+
+#include "ostream.h"
+
+namespace fmt {
+namespace internal {
+
+// 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 = std::numeric_limits<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 >= std::numeric_limits<int>::min() &&
+ value <= std::numeric_limits<int>::max();
+ }
+ static bool fits_in_int(int) { return true; }
+};
+
+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);
+ }
+};
+
+// 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; }
+};
+
+// returns the default type for format specific "%s"
+class DefaultType : public ArgVisitor<DefaultType, char> {
+ public:
+ char visit_char(int) { return 'c'; }
+
+ char visit_bool(bool) { return 's'; }
+
+ char visit_pointer(const void *) { return 'p'; }
+
+ template <typename T>
+ char visit_any_int(T) { return 'd'; }
+
+ template <typename T>
+ char visit_any_double(T) { return 'g'; }
+
+ char visit_unhandled_arg() { return 's'; }
+};
+
+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);
+ }
+
+ void visit_char(int value) {
+ if (type_ != 's')
+ visit_any_int(value);
+ }
+
+ template <typename U>
+ void visit_any_int(U value) {
+ bool is_signed = type_ == 'd' || type_ == 'i';
+ if (type_ == 's') {
+ is_signed = std::numeric_limits<U>::is_signed;
+ }
+
+ 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);
+ }
+};
+
+// 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;
+ }
+ unsigned int_max = std::numeric_limits<int>::max();
+ if (width > int_max)
+ FMT_THROW(FormatError("number is too big"));
+ return static_cast<unsigned>(width);
+ }
+};
+} // namespace internal
+
+/**
+ \rst
+ A ``printf`` argument formatter based on the `curiously recurring template
+ pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
+
+ To use `~fmt::BasicPrintfArgFormatter` 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::BasicPrintfArgFormatter` or its
+ superclass will be called.
+ \endrst
+ */
+template <typename Impl, typename Char, typename Spec>
+class BasicPrintfArgFormatter :
+ public internal::ArgFormatterBase<Impl, Char, Spec> {
+ private:
+ void write_null_pointer() {
+ this->spec().type_ = 0;
+ this->write("(nil)");
+ }
+
+ typedef internal::ArgFormatterBase<Impl, Char, Spec> Base;
+
+ public:
+ /**
+ \rst
+ Constructs an argument formatter object.
+ *writer* is a reference to the output writer and *spec* contains format
+ specifier information for standard argument types.
+ \endrst
+ */
+ BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
+ : internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {}
+
+ /** Formats an argument of type ``bool``. */
+ void visit_bool(bool value) {
+ Spec &fmt_spec = this->spec();
+ if (fmt_spec.type_ != 's')
+ return this->visit_any_int(value);
+ fmt_spec.type_ = 0;
+ this->write(value);
+ }
+
+ /** Formats a character. */
+ void visit_char(int value) {
+ const Spec &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);
+ }
+
+ /** Formats a null-terminated C string. */
+ 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)");
+ }
+
+ /** Formats a pointer. */
+ void visit_pointer(const void *value) {
+ if (value)
+ return Base::visit_pointer(value);
+ this->spec().type_ = 0;
+ write_null_pointer();
+ }
+
+ /** Formats an argument of a custom (user-defined) type. */
+ void visit_custom(internal::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);
+ }
+};
+
+/** The default printf argument formatter. */
+template <typename Char>
+class PrintfArgFormatter :
+ public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec> {
+ public:
+ /** Constructs an argument formatter object. */
+ PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
+ : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {}
+};
+
+/** This template formats data and writes the output to a writer. */
+template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
+class PrintfFormatter : private internal::FormatterBase {
+ private:
+ BasicWriter<Char> &writer_;
+
+ void parse_flags(FormatSpec &spec, const Char *&s);
+
+ // Returns the argument with specified index or, if arg_index is equal
+ // to the maximum unsigned value, the next argument.
+ internal::Arg get_arg(
+ const Char *s,
+ unsigned arg_index = (std::numeric_limits<unsigned>::max)());
+
+ // Parses argument index, flags and width and returns the argument index.
+ unsigned parse_header(const Char *&s, FormatSpec &spec);
+
+ public:
+ /**
+ \rst
+ Constructs a ``PrintfFormatter`` object. References to the arguments and
+ the writer are stored in the formatter object so make sure they have
+ appropriate lifetimes.
+ \endrst
+ */
+ explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
+ : FormatterBase(al), writer_(w) {}
+
+ /** Formats stored arguments and writes the output to the writer. */
+ void format(BasicCStringRef<Char> format_str);
+};
+
+template <typename Char, typename AF>
+void PrintfFormatter<Char, AF>::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, typename AF>
+internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
+ unsigned arg_index) {
+ (void)s;
+ const char *error = FMT_NULL;
+ internal::Arg arg = arg_index == std::numeric_limits<unsigned>::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, typename AF>
+unsigned PrintfFormatter<Char, AF>::parse_header(
+ const Char *&s, FormatSpec &spec) {
+ unsigned arg_index = std::numeric_limits<unsigned>::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 = internal::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_ = internal::parse_nonnegative_int(s);
+ } else if (*s == '*') {
+ ++s;
+ spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
+ }
+ return arg_index;
+}
+
+template <typename Char, typename AF>
+void PrintfFormatter<Char, AF>::format(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>(internal::parse_nonnegative_int(s));
+ } else if (*s == '*') {
+ ++s;
+ spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
+ } else {
+ spec.precision_ = 0;
+ }
+ }
+
+ using internal::Arg;
+ Arg arg = get_arg(s, arg_index);
+ if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
+ spec.flags_ &= ~internal::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.
+ using internal::ArgConverter;
+ 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 (spec.type_ == 's') {
+ // set the format type to the default if 's' is specified
+ spec.type_ = internal::DefaultType().visit(arg);
+ }
+
+ 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
+ internal::CharConverter(arg).visit(arg);
+ break;
+ }
+ }
+
+ start = s;
+
+ // Format argument.
+ AF(writer_, spec).visit(arg);
+ }
+ write(writer_, start, s);
+}
+
+inline void printf(Writer &w, CStringRef format, ArgList args) {
+ PrintfFormatter<char>(args, w).format(format);
+}
+FMT_VARIADIC(void, printf, Writer &, CStringRef)
+
+inline void printf(WWriter &w, WCStringRef format, ArgList args) {
+ PrintfFormatter<wchar_t>(args, w).format(format);
+}
+FMT_VARIADIC(void, printf, WWriter &, WCStringRef)
+
+/**
+ \rst
+ Formats arguments and returns the result as a string.
+
+ **Example**::
+
+ std::string message = fmt::sprintf("The answer is %d", 42);
+ \endrst
+*/
+inline std::string sprintf(CStringRef format, ArgList args) {
+ MemoryWriter w;
+ printf(w, format, args);
+ return w.str();
+}
+FMT_VARIADIC(std::string, sprintf, CStringRef)
+
+inline std::wstring sprintf(WCStringRef format, ArgList args) {
+ WMemoryWriter w;
+ printf(w, format, args);
+ return w.str();
+}
+FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
+
+/**
+ \rst
+ Prints formatted data to the file *f*.
+
+ **Example**::
+
+ fmt::fprintf(stderr, "Don't %s!", "panic");
+ \endrst
+ */
+FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
+FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
+
+/**
+ \rst
+ Prints formatted data to ``stdout``.
+
+ **Example**::
+
+ fmt::printf("Elapsed time: %.2f seconds", 1.23);
+ \endrst
+ */
+inline int printf(CStringRef format, ArgList args) {
+ return fprintf(stdout, format, args);
+}
+FMT_VARIADIC(int, printf, CStringRef)
+
+/**
+ \rst
+ Prints formatted data to the stream *os*.
+
+ **Example**::
+
+ fprintf(cerr, "Don't %s!", "panic");
+ \endrst
+ */
+inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) {
+ MemoryWriter w;
+ printf(w, format_str, args);
+ internal::write(os, w);
+ return static_cast<int>(w.size());
+}
+FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
+} // namespace fmt
+
+#ifdef FMT_HEADER_ONLY
+# include "printf.cc"
+#endif
+
+#endif // FMT_PRINTF_H_
diff --git a/dep/fmt/fmt/string.h b/dep/fmt/fmt/string.h
new file mode 100644
index 00000000000..05996eb5878
--- /dev/null
+++ b/dep/fmt/fmt/string.h
@@ -0,0 +1,148 @@
+/*
+ Formatting library for C++ - string utilities
+
+ Copyright (c) 2012 - 2016, Victor Zverovich
+ All rights reserved.
+
+ For the license information refer to format.h.
+ */
+
+#ifdef FMT_INCLUDE
+# error "Add the fmt's parent directory and not fmt itself to includes."
+#endif
+
+#ifndef FMT_STRING_H_
+#define FMT_STRING_H_
+
+#include "format.h"
+
+namespace fmt {
+
+namespace internal {
+
+// A buffer that stores data in ``std::basic_string``.
+template <typename Char, typename Allocator = std::allocator<Char> >
+class StringBuffer : public Buffer<Char> {
+ public:
+ typedef std::basic_string<Char, std::char_traits<Char>, Allocator> StringType;
+
+ private:
+ StringType data_;
+
+ protected:
+ virtual void grow(std::size_t size) FMT_OVERRIDE {
+ data_.resize(size);
+ this->ptr_ = &data_[0];
+ this->capacity_ = size;
+ }
+
+ public:
+ explicit StringBuffer(const Allocator &allocator = Allocator())
+ : data_(allocator) {}
+
+ // Moves the data to ``str`` clearing the buffer.
+ void move_to(StringType &str) {
+ data_.resize(this->size_);
+ str.swap(data_);
+ this->capacity_ = this->size_ = 0;
+ this->ptr_ = FMT_NULL;
+ }
+};
+} // namespace internal
+
+/**
+ \rst
+ This class template provides operations for formatting and writing data
+ into a character stream. The output is stored in a ``std::basic_string``
+ that grows dynamically.
+
+ You can use one of the following typedefs for common character types
+ and the standard allocator:
+
+ +---------------+----------------------------+
+ | Type | Definition |
+ +===============+============================+
+ | StringWriter | BasicStringWriter<char> |
+ +---------------+----------------------------+
+ | WStringWriter | BasicStringWriter<wchar_t> |
+ +---------------+----------------------------+
+
+ **Example**::
+
+ StringWriter out;
+ out << "The answer is " << 42 << "\n";
+
+ This will write the following output to the ``out`` object:
+
+ .. code-block:: none
+
+ The answer is 42
+
+ The output can be moved to a ``std::basic_string`` with ``out.move_to()``.
+ \endrst
+ */
+template <typename Char, typename Allocator = std::allocator<Char> >
+class BasicStringWriter : public BasicWriter<Char> {
+ private:
+ internal::StringBuffer<Char, Allocator> buffer_;
+
+ public:
+ /**
+ \rst
+ Constructs a :class:`fmt::BasicStringWriter` object.
+ \endrst
+ */
+ explicit BasicStringWriter(const Allocator &allocator = Allocator())
+ : BasicWriter<Char>(buffer_), buffer_(allocator) {}
+
+ /**
+ \rst
+ Moves the buffer content to *str* clearing the buffer.
+ \endrst
+ */
+ void move_to(std::basic_string<Char, std::char_traits<Char>, Allocator> &str) {
+ buffer_.move_to(str);
+ }
+};
+
+typedef BasicStringWriter<char> StringWriter;
+typedef BasicStringWriter<wchar_t> WStringWriter;
+
+/**
+ \rst
+ Converts *value* to ``std::string`` using the default format for type *T*.
+
+ **Example**::
+
+ #include "fmt/string.h"
+
+ std::string answer = fmt::to_string(42);
+ \endrst
+ */
+template <typename T>
+std::string to_string(const T &value) {
+ fmt::MemoryWriter w;
+ w << value;
+ return w.str();
+}
+
+/**
+ \rst
+ Converts *value* to ``std::wstring`` using the default format for type *T*.
+
+ **Example**::
+
+ #include "fmt/string.h"
+
+ std::wstring answer = fmt::to_wstring(42);
+ \endrst
+ */
+template <typename T>
+std::wstring to_wstring(const T &value) {
+ fmt::WMemoryWriter w;
+ w << value;
+ return w.str();
+}
+}
+
+#endif // FMT_STRING_H_
diff --git a/dep/fmt/fmt/time.h b/dep/fmt/fmt/time.h
index 10225c03ef8..c98b0e0116f 100644
--- a/dep/fmt/fmt/time.h
+++ b/dep/fmt/fmt/time.h
@@ -13,10 +13,16 @@
#include "format.h"
#include <ctime>
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4702) // unreachable code
+# pragma warning(disable: 4996) // "deprecated" functions
+#endif
+
namespace fmt {
template <typename ArgFormatter>
-void format(BasicFormatter<char, ArgFormatter> &f,
- const char *&format_str, const std::tm &tm) {
+void format_arg(BasicFormatter<char, ArgFormatter> &f,
+ const char *&format_str, const std::tm &tm) {
if (*format_str == ':')
++format_str;
const char *end = format_str;
@@ -48,6 +54,90 @@ void format(BasicFormatter<char, ArgFormatter> &f,
}
format_str = end + 1;
}
+
+namespace internal{
+inline Null<> localtime_r(...) { return Null<>(); }
+inline Null<> localtime_s(...) { return Null<>(); }
+inline Null<> gmtime_r(...) { return Null<>(); }
+inline Null<> gmtime_s(...) { return Null<>(); }
+}
+
+// Thread-safe replacement for std::localtime
+inline std::tm localtime(std::time_t time) {
+ struct LocalTime {
+ std::time_t time_;
+ std::tm tm_;
+
+ LocalTime(std::time_t t): time_(t) {}
+
+ bool run() {
+ using namespace fmt::internal;
+ return handle(localtime_r(&time_, &tm_));
+ }
+
+ bool handle(std::tm *tm) { return tm != FMT_NULL; }
+
+ bool handle(internal::Null<>) {
+ using namespace fmt::internal;
+ return fallback(localtime_s(&tm_, &time_));
+ }
+
+ bool fallback(int res) { return res == 0; }
+
+ bool fallback(internal::Null<>) {
+ using namespace fmt::internal;
+ std::tm *tm = std::localtime(&time_);
+ if (tm) tm_ = *tm;
+ return tm != FMT_NULL;
+ }
+ };
+ LocalTime lt(time);
+ if (lt.run())
+ return lt.tm_;
+ // Too big time values may be unsupported.
+ FMT_THROW(fmt::FormatError("time_t value out of range"));
+ return std::tm();
}
+// Thread-safe replacement for std::gmtime
+inline std::tm gmtime(std::time_t time) {
+ struct GMTime {
+ std::time_t time_;
+ std::tm tm_;
+
+ GMTime(std::time_t t): time_(t) {}
+
+ bool run() {
+ using namespace fmt::internal;
+ return handle(gmtime_r(&time_, &tm_));
+ }
+
+ bool handle(std::tm *tm) { return tm != FMT_NULL; }
+
+ bool handle(internal::Null<>) {
+ using namespace fmt::internal;
+ return fallback(gmtime_s(&tm_, &time_));
+ }
+
+ bool fallback(int res) { return res == 0; }
+
+ bool fallback(internal::Null<>) {
+ std::tm *tm = std::gmtime(&time_);
+ if (tm != FMT_NULL) tm_ = *tm;
+ return tm != FMT_NULL;
+ }
+ };
+ GMTime gt(time);
+ if (gt.run())
+ return gt.tm_;
+ // Too big time values may be unsupported.
+ FMT_THROW(fmt::FormatError("time_t value out of range"));
+ return std::tm();
+}
+} //namespace fmt
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
#endif // FMT_TIME_H_
diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h
index 12eeb2a6d14..1138b97759e 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 "fmt/format.h"
+#include "fmt/printf.h"
namespace Trinity
{