Squashed 'externals/fmt/' changes from 39834389..135ab5cf
135ab5cf Update version 93d95f17 Fix markup 4f15c72f Fix markup e9b19414 Automatically add package to release c3d1f604 Fix markup c96062bf Update changelog and version number f9c97de4 Add note about errno to the documentation 62df6f27 CMakeLists: Use GNUInstallDirs to set install location 493586cb Fix overflow check 1d751bc6 fix warning in header: signed/unsigned comparison 11415bce Update usage.rst 9982dd01 Fix for warning C5030 in VS2015 42e88c4f Silenced MSVC 2017 constant if expression warning 7a9c1ba1 FMT_VARIADIC_CONST - Support for const variadic methods (#591) 324415c0 Use allocator_traits if available. 5f39721c Fix a warning ca96acbe Add examples 708d9509 fix(Clang CodeGen): remove warnings 9328a074 Fix handling of fixed enums in clang (#580) 2c077dd4 Enable stream exceptions (#581) 933a33a7 Added MSVC checking for support for string_view. bef89db6 Fix a bogus -Wduplicated-branches gcc warning (#573) 2a619d96 Make format work with C++17 std::string_view (#571) e051de37 Use less version 2.6.1 and sudo to fix npm install issues on travis 5de459bf Suppress Clang's warning on zero as a null pointer 16589534 Make ArgMap::init not explicitly instantiated (#563) 3e75d3e0 Fix handling of types convertible to int 89654cd1 to_wstring added 37eb419a Fix noreturn attribute detection (#555) 14d85349 Explicitly cast range length to std::size_t to prevent conversion warnings c2201ce0 Accept wide chars as integers to prevent conversion warning 6efbccb3 Add one more CMake warning fix 032c8380 Fix a segfault in test on glibc 2.26 #551, take 2 6655e804 Fix a segfault in test on glibc 2.26 #551 d16c4d20 Suppress warning about missing noreturn attribute (#549) 9c56a8ce Make format_arg() accept class hierarchies ca0e3830 Update README.rst 81790d72 Update format.h to remove C4574 error on MSVC 14.2 30283443 Fix undefined behavior in UDL macro 4045d7fe Fix warning about missing ' character 89c3bc58 Remove warning C4668 in MSVC for FMT_GCC_VERSION and FMT_HAS_GXX_CXX11 4af9421f Adding OpenSpace to the list of projects 1a398b54 Fixed CMake CMP0048 warning. 589ccc16 Bump version c3817046 Add an error on broken includes 16bdd842 Update scripts b492316d Update version list 91f4ce02 Automatically update version in release script (#431) git-subtree-dir: externals/fmt git-subtree-split: 135ab5cf71ed731fc9fa0653051e7d4884a3652f
This commit is contained in:
parent
a9f62a15cd
commit
097203968f
21 changed files with 481 additions and 141 deletions
|
@ -2,6 +2,14 @@ message(STATUS "CMake version: ${CMAKE_VERSION}")
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
if (POLICY CMP0048) # Version variables
|
||||||
|
cmake_policy(SET CMP0048 OLD)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (POLICY CMP0063) # Visibility
|
||||||
|
cmake_policy(SET CMP0063 OLD)
|
||||||
|
endif (POLICY CMP0063)
|
||||||
|
|
||||||
# Determine if fmt is built as a subproject (using add_subdirectory)
|
# Determine if fmt is built as a subproject (using add_subdirectory)
|
||||||
# or if it is the master project.
|
# or if it is the master project.
|
||||||
set(MASTER_PROJECT OFF)
|
set(MASTER_PROJECT OFF)
|
||||||
|
|
|
@ -1,7 +1,32 @@
|
||||||
|
4.1.0 - 2017-12-20
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Added ``fmt::to_wstring()`` in addition to ``fmt::to_string()`` (`#559 <https://github.com/fmtlib/fmt/pull/559>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
|
||||||
|
|
||||||
|
* Added support for C++17 ``std::string_view`` (`#571 <https://github.com/fmtlib/fmt/pull/571>`_ and `#578 <https://github.com/fmtlib/fmt/pull/578>`_). Thanks `@thelostt (Mário Feroldi) <https://github.com/thelostt>`_ and `@mwinterb <https://github.com/mwinterb>`_.
|
||||||
|
|
||||||
|
* Enabled stream exceptions to catch errors (`#581 <https://github.com/fmtlib/fmt/issues/581>`_). Thanks `@crusader-mike <https://github.com/crusader-mike>`_.
|
||||||
|
|
||||||
|
* Allowed formatting of class hierarchies with ``fmt::format_arg()`` (`#547 <https://github.com/fmtlib/fmt/pull/547>`_). Thanks `@rollbear (Björn Fahller) <https://github.com/rollbear>`_.
|
||||||
|
|
||||||
|
* Removed limitations on character types
|
||||||
|
(`#563 <https://github.com/fmtlib/fmt/pull/563>`_).
|
||||||
|
Thanks `@Yelnats321 (Elnar Dakeshov) <https://github.com/Yelnats321>`_.
|
||||||
|
|
||||||
|
* Conditionally enabled use of ``std::allocator_traits`` (`#583 <https://github.com/fmtlib/fmt/pull/583>`_). Thanks `@mwinterb <https://github.com/mwinterb>`_.
|
||||||
|
|
||||||
|
* Added support for ``const`` variadic member function emulation with ``FMT_VARIADIC_CONST`` (`#591 <https://github.com/fmtlib/fmt/pull/591>`_). Thanks `@ludekvodicka (Ludek Vodicka) <https://github.com/ludekvodicka>`_.
|
||||||
|
|
||||||
|
* Various bugfixes: bad overflow check, unsupported implicit type conversion when determining formatting function, test segfaults (`#551 <https://github.com/fmtlib/fmt/issues/551>`_), ill-formed macros (`#542 <https://github.com/fmtlib/fmt/pull/542>`_) and ambiguous overloads (`#580 <https://github.com/fmtlib/fmt/issues/580>`_). Thanks `@xylosper (Byoung-young Lee) <https://github.com/xylosper>`_.
|
||||||
|
|
||||||
|
* Prevented warnings on MSVC (`#605 <https://github.com/fmtlib/fmt/pull/605>`_, `#602 <https://github.com/fmtlib/fmt/pull/602>`_, and `#545 <https://github.com/fmtlib/fmt/pull/545>`_), clang (`#582 <https://github.com/fmtlib/fmt/pull/582>`_), GCC (`#573 <https://github.com/fmtlib/fmt/issues/573>`_), various conversion warnings (`#609 <https://github.com/fmtlib/fmt/pull/609>`_, `#567 <https://github.com/fmtlib/fmt/pull/567>`_, `#553 <https://github.com/fmtlib/fmt/pull/553>`_ and `#553 <https://github.com/fmtlib/fmt/pull/553>`_), and added ``override`` and ``[[noreturn]]`` (`#549 <https://github.com/fmtlib/fmt/pull/549>`_ and `#555 <https://github.com/fmtlib/fmt/issues/555>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_, `@virgiliofornazin (Virgilio Alexandre Fornazin) <https://gihtub.com/virgiliofornazin>`_, `@alexanderbock (Alexander Bock) <https://github.com/alexanderbock>`_, `@yumetodo <https://github.com/yumetodo>`_, `@VaderY (Császár Mátyás) <https://github.com/VaderY>`_, `@jpcima (JP Cimalando) <https://github.com/jpcima>`_, `@thelostt (Mário Feroldi) <https://github.com/thelostt>`_, and `@Manu343726 (Manu Sánchez) <https://github.com/Manu343726>`_.
|
||||||
|
|
||||||
|
* Improved CMake: Used GNUInstallDirs to set installation location (`#610 <https://github.com/fmtlib/fmt/pull/610>`_) and fixed warnings (`#536 <https://github.com/fmtlib/fmt/pull/536>`_ and `#556 <https://github.com/fmtlib/fmt/pull/556>`_). Thanks `@mikecrowe (Mike Crowe) <https://github.com/mikecrowe>`_, `@evgen231 <https://github.com/evgen231>`_ and `@henryiii (Henry Schreiner) <https://github.com/henryiii>`_.
|
||||||
|
|
||||||
4.0.0 - 2017-06-27
|
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>`_.
|
* Removed old compatibility headers ``cppformat/*.h`` and CMake options (`#527 <https://github.com/fmtlib/fmt/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>`_):
|
* 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>`_):
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,8 @@ Projects using this library
|
||||||
|
|
||||||
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus (Lyft)
|
* `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>`_:
|
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||||
Player vs Player Gaming Network with tweaks
|
Player vs Player Gaming Network with tweaks
|
||||||
|
|
||||||
|
@ -155,6 +157,8 @@ Projects using this library
|
||||||
|
|
||||||
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
|
* `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/>`_:
|
* `PenUltima Online (POL) <http://www.polserver.com/>`_:
|
||||||
An MMO server, compatible with most Ultima Online clients
|
An MMO server, compatible with most Ultima Online clients
|
||||||
|
|
||||||
|
|
32
doc/api.rst
32
doc/api.rst
|
@ -84,6 +84,36 @@ Note in the example above the ``format_arg`` function ignores the contents of
|
||||||
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
|
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
|
||||||
the ``format_str`` argument to customize the formatted output.
|
the ``format_str`` argument to customize the formatted output.
|
||||||
|
|
||||||
|
This technique can also be used for formatting class hierarchies::
|
||||||
|
|
||||||
|
namespace local {
|
||||||
|
struct Parent {
|
||||||
|
Parent(int p) : p(p) {}
|
||||||
|
virtual void write(fmt::Writer &w) const {
|
||||||
|
w.write("Parent : p={}", p);
|
||||||
|
}
|
||||||
|
int p;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Child : Parent {
|
||||||
|
Child(int c, int p) : Parent(p), c(c) {}
|
||||||
|
virtual void write(fmt::Writer &w) const {
|
||||||
|
w.write("Child c={} : ", c);
|
||||||
|
Parent::write(w);
|
||||||
|
}
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
void format_arg(fmt::BasicFormatter<char> &f,
|
||||||
|
const char *&format_str, const Parent &p) {
|
||||||
|
p.write(f.writer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Local::Child c(1,2);
|
||||||
|
Local::Parent &p = c;
|
||||||
|
fmt::print("via ref to base: {}\n", p);
|
||||||
|
fmt::print("direct to child: {}\n", c);
|
||||||
|
|
||||||
This section shows how to define a custom format function for a user-defined
|
This section shows how to define a custom format function for a user-defined
|
||||||
type. The next section describes how to get ``fmt`` to use a conventional stream
|
type. The next section describes how to get ``fmt`` to use a conventional stream
|
||||||
output ``operator<<`` when one is defined for a user-defined type.
|
output ``operator<<`` when one is defined for a user-defined type.
|
||||||
|
@ -232,6 +262,8 @@ Utilities
|
||||||
|
|
||||||
.. doxygenfunction:: fmt::to_string(const T&)
|
.. doxygenfunction:: fmt::to_string(const T&)
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::to_wstring(const T&)
|
||||||
|
|
||||||
.. doxygenclass:: fmt::BasicStringRef
|
.. doxygenclass:: fmt::BasicStringRef
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ import errno, os, shutil, sys, tempfile
|
||||||
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
|
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
|
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0']
|
||||||
|
|
||||||
def pip_install(package, commit=None, **kwargs):
|
def pip_install(package, commit=None, **kwargs):
|
||||||
"Install package using pip."
|
"Install package using pip."
|
||||||
min_version = kwargs.get('min_version')
|
min_version = kwargs.get('min_version')
|
||||||
|
@ -93,11 +95,11 @@ def build_docs(version='dev', **kwargs):
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
raise CalledProcessError(p.returncode, cmd)
|
raise CalledProcessError(p.returncode, cmd)
|
||||||
html_dir = os.path.join(work_dir, 'html')
|
html_dir = os.path.join(work_dir, 'html')
|
||||||
versions = ['3.0.0', '2.0.0', '1.1.0']
|
main_versions = reversed(versions[-3:])
|
||||||
check_call(['sphinx-build',
|
check_call(['sphinx-build',
|
||||||
'-Dbreathe_projects.format=' + os.path.abspath(doxyxml_dir),
|
'-Dbreathe_projects.format=' + os.path.abspath(doxyxml_dir),
|
||||||
'-Dversion=' + version, '-Drelease=' + version,
|
'-Dversion=' + version, '-Drelease=' + version,
|
||||||
'-Aversion=' + version, '-Aversions=' + ','.join(versions),
|
'-Aversion=' + version, '-Aversions=' + ','.join(main_versions),
|
||||||
'-b', 'html', doc_dir, html_dir])
|
'-b', 'html', doc_dir, html_dir])
|
||||||
try:
|
try:
|
||||||
check_call(['lessc', '--clean-css',
|
check_call(['lessc', '--clean-css',
|
||||||
|
|
|
@ -143,6 +143,12 @@ its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
|
||||||
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
|
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
|
||||||
needed.
|
needed.
|
||||||
|
|
||||||
|
Note that fmt does not use the value of the ``errno`` global to communicate
|
||||||
|
errors to the user, but it may call system functions which set ``errno``. Since
|
||||||
|
fmt does not attempt to preserve the value of ``errno``, users should not make
|
||||||
|
any assumptions about it and always set it to ``0`` before making any system
|
||||||
|
calls that convey error information via ``errno``.
|
||||||
|
|
||||||
.. _portability:
|
.. _portability:
|
||||||
|
|
||||||
Portability
|
Portability
|
||||||
|
|
|
@ -335,6 +335,16 @@ Aligning the text and specifying a width::
|
||||||
format("{:*^30}", "centered"); // use '*' as a fill char
|
format("{:*^30}", "centered"); // use '*' as a fill char
|
||||||
// Result: "***********centered***********"
|
// Result: "***********centered***********"
|
||||||
|
|
||||||
|
Dynamic width::
|
||||||
|
|
||||||
|
format("{:<{}}", "left aligned", 30);
|
||||||
|
// Result: "left aligned "
|
||||||
|
|
||||||
|
Dynamic precision::
|
||||||
|
|
||||||
|
format("{:.{}f}", 3.14, 1);
|
||||||
|
// Result: "3.1"
|
||||||
|
|
||||||
Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign::
|
Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign::
|
||||||
|
|
||||||
format("{:+f}; {:+f}", 3.14, -3.14); // show it always
|
format("{:+f}; {:+f}", 3.14, -3.14); // show it always
|
||||||
|
@ -359,13 +369,6 @@ Replacing ``%x`` and ``%o`` and converting the value to different bases::
|
||||||
format("{:,}", 1234567890);
|
format("{:,}", 1234567890);
|
||||||
'1,234,567,890'
|
'1,234,567,890'
|
||||||
|
|
||||||
Expressing a percentage::
|
|
||||||
|
|
||||||
>>> points = 19
|
|
||||||
>>> total = 22
|
|
||||||
Format("Correct answers: {:.2%}") << points/total)
|
|
||||||
'Correct answers: 86.36%'
|
|
||||||
|
|
||||||
Using type-specific formatting::
|
Using type-specific formatting::
|
||||||
|
|
||||||
>>> import datetime
|
>>> import datetime
|
||||||
|
|
|
@ -41,6 +41,10 @@ current directory. Now you can build the library by running :command:`make`.
|
||||||
Once the library has been built you can invoke :command:`make test` to run
|
Once the library has been built you can invoke :command:`make test` to run
|
||||||
the tests.
|
the tests.
|
||||||
|
|
||||||
|
You can control generation of the make ``test`` target with the ``FMT_TEST``
|
||||||
|
CMake option. This can be useful if you include fmt as a subdirectory in
|
||||||
|
your project but don't want to add fmt's tests to your ``test`` target.
|
||||||
|
|
||||||
If you use Windows and have Visual Studio installed, a :file:`FORMAT.sln`
|
If you use Windows and have Visual Studio installed, a :file:`FORMAT.sln`
|
||||||
file and several :file:`.vcproj` files will be created. You can then build them
|
file and several :file:`.vcproj` files will be created. You can then build them
|
||||||
using Visual Studio or msbuild.
|
using Visual Studio or msbuild.
|
||||||
|
|
|
@ -49,8 +49,9 @@ endif ()
|
||||||
|
|
||||||
# Install targets.
|
# Install targets.
|
||||||
if (FMT_INSTALL)
|
if (FMT_INSTALL)
|
||||||
|
include(GNUInstallDirs)
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
set(FMT_CMAKE_DIR lib/cmake/fmt CACHE STRING
|
set(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING
|
||||||
"Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
|
"Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
|
||||||
set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
|
set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
|
||||||
set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
|
set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
|
||||||
|
@ -61,9 +62,12 @@ if (FMT_INSTALL)
|
||||||
set(INSTALL_TARGETS ${INSTALL_TARGETS} fmt-header-only)
|
set(INSTALL_TARGETS ${INSTALL_TARGETS} fmt-header-only)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(FMT_LIB_DIR lib CACHE STRING
|
set(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
|
||||||
"Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.")
|
"Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.")
|
||||||
|
|
||||||
|
set(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR}/fmt CACHE STRING
|
||||||
|
"Installation directory for include files, relative to ${CMAKE_INSTALL_PREFIX}.")
|
||||||
|
|
||||||
# Generate the version, config and target files into the build directory.
|
# Generate the version, config and target files into the build directory.
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
${version_config}
|
${version_config}
|
||||||
|
@ -86,5 +90,5 @@ if (FMT_INSTALL)
|
||||||
# Install the library and headers.
|
# Install the library and headers.
|
||||||
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
|
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
|
||||||
DESTINATION ${FMT_LIB_DIR})
|
DESTINATION ${FMT_LIB_DIR})
|
||||||
install(FILES ${FMT_HEADERS} DESTINATION include/fmt)
|
install(FILES ${FMT_HEADERS} DESTINATION ${FMT_INC_DIR})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -72,9 +72,11 @@
|
||||||
|
|
||||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||||
// system functions are not available.
|
// system functions are not available.
|
||||||
|
FMT_MAYBE_UNUSED
|
||||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
||||||
return fmt::internal::Null<>();
|
return fmt::internal::Null<>();
|
||||||
}
|
}
|
||||||
|
FMT_MAYBE_UNUSED
|
||||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
||||||
return fmt::internal::Null<>();
|
return fmt::internal::Null<>();
|
||||||
}
|
}
|
||||||
|
@ -121,7 +123,7 @@ typedef void (*FormatFunc)(Writer &, int, StringRef);
|
||||||
// Buffer should be at least of size 1.
|
// Buffer should be at least of size 1.
|
||||||
int safe_strerror(
|
int safe_strerror(
|
||||||
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
|
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 {
|
class StrError {
|
||||||
private:
|
private:
|
||||||
|
@ -159,6 +161,11 @@ int safe_strerror(
|
||||||
ERANGE : result;
|
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.
|
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||||
int fallback(internal::Null<>) {
|
int fallback(internal::Null<>) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -166,13 +173,15 @@ int safe_strerror(
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __c2__
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StrError(int err_code, char *&buf, std::size_t buf_size)
|
StrError(int err_code, char *&buf, std::size_t buf_size)
|
||||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||||
|
|
||||||
int run() {
|
int run() {
|
||||||
// Suppress a warning about unused strerror_r.
|
|
||||||
strerror_r(0, FMT_NULL, "");
|
|
||||||
return handle(strerror_r(error_code_, buffer_, buffer_size_));
|
return handle(strerror_r(error_code_, buffer_, buffer_size_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -396,51 +405,6 @@ FMT_FUNC void format_system_error(
|
||||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
void internal::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 Char>
|
template <typename Char>
|
||||||
void internal::FixedBuffer<Char>::grow(std::size_t) {
|
void internal::FixedBuffer<Char>::grow(std::size_t) {
|
||||||
FMT_THROW(std::runtime_error("buffer overflow"));
|
FMT_THROW(std::runtime_error("buffer overflow"));
|
||||||
|
@ -502,8 +466,6 @@ template struct internal::BasicData<void>;
|
||||||
|
|
||||||
template void internal::FixedBuffer<char>::grow(std::size_t);
|
template void internal::FixedBuffer<char>::grow(std::size_t);
|
||||||
|
|
||||||
template void internal::ArgMap<char>::init(const ArgList &args);
|
|
||||||
|
|
||||||
template FMT_API int internal::CharTraits<char>::format_float(
|
template FMT_API int internal::CharTraits<char>::format_float(
|
||||||
char *buffer, std::size_t size, const char *format,
|
char *buffer, std::size_t size, const char *format,
|
||||||
unsigned width, int precision, double value);
|
unsigned width, int precision, double value);
|
||||||
|
@ -516,8 +478,6 @@ template FMT_API int internal::CharTraits<char>::format_float(
|
||||||
|
|
||||||
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||||
|
|
||||||
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
|
|
||||||
|
|
||||||
template FMT_API int 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,
|
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||||
unsigned width, int precision, double value);
|
unsigned width, int precision, double value);
|
||||||
|
|
279
fmt/format.h
279
fmt/format.h
|
@ -28,6 +28,7 @@
|
||||||
#ifndef FMT_FORMAT_H_
|
#ifndef FMT_FORMAT_H_
|
||||||
#define FMT_FORMAT_H_
|
#define FMT_FORMAT_H_
|
||||||
|
|
||||||
|
#define FMT_INCLUDE
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -39,11 +40,26 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility> // for std::pair
|
#include <utility> // for std::pair
|
||||||
|
#undef FMT_INCLUDE
|
||||||
|
|
||||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||||
#define FMT_VERSION 40000
|
#define FMT_VERSION 40100
|
||||||
|
|
||||||
#ifdef _SECURE_SCL
|
#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
|
# define FMT_SECURE_SCL _SECURE_SCL
|
||||||
#else
|
#else
|
||||||
# define FMT_SECURE_SCL 0
|
# define FMT_SECURE_SCL 0
|
||||||
|
@ -97,7 +113,9 @@ typedef __int64 intmax_t;
|
||||||
# define FMT_HAS_GXX_CXX11 1
|
# define FMT_HAS_GXX_CXX11 1
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
|
# define FMT_GCC_VERSION 0
|
||||||
# define FMT_GCC_EXTENSION
|
# define FMT_GCC_EXTENSION
|
||||||
|
# define FMT_HAS_GXX_CXX11 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__INTEL_COMPILER)
|
#if defined(__INTEL_COMPILER)
|
||||||
|
@ -135,6 +153,32 @@ typedef __int64 intmax_t;
|
||||||
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
|
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
|
||||||
#endif
|
#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 && _MSC_VER >= 1910
|
||||||
|
# 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
|
#ifndef FMT_USE_VARIADIC_TEMPLATES
|
||||||
// Variadic templates are available in GCC since version 4.4
|
// Variadic templates are available in GCC since version 4.4
|
||||||
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
|
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
|
||||||
|
@ -156,6 +200,12 @@ typedef __int64 intmax_t;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700
|
||||||
|
# define FMT_USE_ALLOCATOR_TRAITS 1
|
||||||
|
#else
|
||||||
|
# define FMT_USE_ALLOCATOR_TRAITS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check if exceptions are disabled.
|
// Check if exceptions are disabled.
|
||||||
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
|
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
|
||||||
# define FMT_EXCEPTIONS 0
|
# define FMT_EXCEPTIONS 0
|
||||||
|
@ -262,11 +312,14 @@ typedef __int64 intmax_t;
|
||||||
// makes the fmt::literals implementation easier. However, an explicit check
|
// makes the fmt::literals implementation easier. However, an explicit check
|
||||||
// for variadic templates is added here just in case.
|
// for variadic templates is added here just in case.
|
||||||
// For Intel's compiler both it and the system gcc/msc must support UDLs.
|
// For Intel's compiler both it and the system gcc/msc must support UDLs.
|
||||||
# define FMT_USE_USER_DEFINED_LITERALS \
|
# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
|
||||||
FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
|
|
||||||
(FMT_HAS_FEATURE(cxx_user_literals) || \
|
(FMT_HAS_FEATURE(cxx_user_literals) || \
|
||||||
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
|
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
|
||||||
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
|
(!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
|
#endif
|
||||||
|
|
||||||
#ifndef FMT_USE_EXTERN_TEMPLATES
|
#ifndef FMT_USE_EXTERN_TEMPLATES
|
||||||
|
@ -305,7 +358,10 @@ typedef __int64 intmax_t;
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
namespace internal {
|
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) {
|
inline uint32_t clz(uint32_t x) {
|
||||||
unsigned long r = 0;
|
unsigned long r = 0;
|
||||||
_BitScanReverse(&r, x);
|
_BitScanReverse(&r, x);
|
||||||
|
@ -319,7 +375,8 @@ inline uint32_t clz(uint32_t x) {
|
||||||
}
|
}
|
||||||
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
|
# 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)
|
# pragma intrinsic(_BitScanReverse64)
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -505,6 +562,26 @@ class BasicStringRef {
|
||||||
const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
|
const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
|
||||||
: data_(s.c_str()), size_(s.size()) {}
|
: 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
|
\rst
|
||||||
Converts a string reference to an ``std::string`` object.
|
Converts a string reference to an ``std::string`` object.
|
||||||
|
@ -609,7 +686,7 @@ class FormatError : public std::runtime_error {
|
||||||
explicit FormatError(CStringRef message)
|
explicit FormatError(CStringRef message)
|
||||||
: std::runtime_error(message.c_str()) {}
|
: std::runtime_error(message.c_str()) {}
|
||||||
FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
|
FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
|
||||||
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT;
|
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -726,7 +803,7 @@ template <typename T>
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void Buffer<T>::append(const U *begin, const U *end) {
|
void Buffer<T>::append(const U *begin, const U *end) {
|
||||||
FMT_ASSERT(end >= begin, "negative value");
|
FMT_ASSERT(end >= begin, "negative value");
|
||||||
std::size_t new_size = size_ + (end - begin);
|
std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
|
||||||
if (new_size > capacity_)
|
if (new_size > capacity_)
|
||||||
grow(new_size);
|
grow(new_size);
|
||||||
std::uninitialized_copy(begin, end,
|
std::uninitialized_copy(begin, end,
|
||||||
|
@ -754,7 +831,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
|
||||||
public:
|
public:
|
||||||
explicit MemoryBuffer(const Allocator &alloc = Allocator())
|
explicit MemoryBuffer(const Allocator &alloc = Allocator())
|
||||||
: Allocator(alloc), Buffer<T>(data_, SIZE) {}
|
: Allocator(alloc), Buffer<T>(data_, SIZE) {}
|
||||||
~MemoryBuffer() { deallocate(); }
|
~MemoryBuffer() FMT_OVERRIDE { deallocate(); }
|
||||||
|
|
||||||
#if FMT_USE_RVALUE_REFERENCES
|
#if FMT_USE_RVALUE_REFERENCES
|
||||||
private:
|
private:
|
||||||
|
@ -798,7 +875,12 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
|
||||||
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
|
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
|
||||||
if (size > new_capacity)
|
if (size > new_capacity)
|
||||||
new_capacity = size;
|
new_capacity = size;
|
||||||
|
#if FMT_USE_ALLOCATOR_TRAITS
|
||||||
|
T *new_ptr =
|
||||||
|
std::allocator_traits<Allocator>::allocate(*this, new_capacity, FMT_NULL);
|
||||||
|
#else
|
||||||
T *new_ptr = this->allocate(new_capacity, FMT_NULL);
|
T *new_ptr = this->allocate(new_capacity, FMT_NULL);
|
||||||
|
#endif
|
||||||
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
||||||
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
|
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
|
||||||
make_ptr(new_ptr, new_capacity));
|
make_ptr(new_ptr, new_capacity));
|
||||||
|
@ -916,7 +998,7 @@ struct IntTraits {
|
||||||
TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
|
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
|
// Static data is placed in this class template to allow header-only
|
||||||
// configuration.
|
// configuration.
|
||||||
|
@ -1155,17 +1237,17 @@ T &get();
|
||||||
Yes &convert(fmt::ULongLong);
|
Yes &convert(fmt::ULongLong);
|
||||||
No &convert(...);
|
No &convert(...);
|
||||||
|
|
||||||
template<typename T, bool ENABLE_CONVERSION>
|
template <typename T, bool ENABLE_CONVERSION>
|
||||||
struct ConvertToIntImpl {
|
struct ConvertToIntImpl {
|
||||||
enum { value = ENABLE_CONVERSION };
|
enum { value = ENABLE_CONVERSION };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, bool ENABLE_CONVERSION>
|
template <typename T, bool ENABLE_CONVERSION>
|
||||||
struct ConvertToIntImpl2 {
|
struct ConvertToIntImpl2 {
|
||||||
enum { value = false };
|
enum { value = false };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct ConvertToIntImpl2<T, true> {
|
struct ConvertToIntImpl2<T, true> {
|
||||||
enum {
|
enum {
|
||||||
// Don't convert numeric types.
|
// Don't convert numeric types.
|
||||||
|
@ -1173,7 +1255,7 @@ struct ConvertToIntImpl2<T, true> {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct ConvertToInt {
|
struct ConvertToInt {
|
||||||
enum {
|
enum {
|
||||||
enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
|
enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
|
||||||
|
@ -1190,16 +1272,16 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
|
||||||
FMT_DISABLE_CONVERSION_TO_INT(double);
|
FMT_DISABLE_CONVERSION_TO_INT(double);
|
||||||
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
||||||
|
|
||||||
template<bool B, class T = void>
|
template <bool B, class T = void>
|
||||||
struct EnableIf {};
|
struct EnableIf {};
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
struct EnableIf<true, T> { typedef T type; };
|
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; };
|
struct Conditional { typedef T type; };
|
||||||
|
|
||||||
template<class T, class F>
|
template <class T, class F>
|
||||||
struct Conditional<false, T, F> { typedef F type; };
|
struct Conditional<false, T, F> { typedef F type; };
|
||||||
|
|
||||||
// For bcc32 which doesn't understand ! in template arguments.
|
// For bcc32 which doesn't understand ! in template arguments.
|
||||||
|
@ -1248,9 +1330,9 @@ inline fmt::StringRef thousands_sep(...) { return ""; }
|
||||||
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename Formatter, typename Char, typename T>
|
template <typename Formatter>
|
||||||
void format_arg(Formatter &, const Char *, const T &) {
|
void format_arg(Formatter&, ...) {
|
||||||
FMT_STATIC_ASSERT(FalseType<T>::value,
|
FMT_STATIC_ASSERT(FalseType<Formatter>::value,
|
||||||
"Cannot format argument. To enable the use of ostream "
|
"Cannot format argument. To enable the use of ostream "
|
||||||
"operator<< include fmt/ostream.h. Otherwise provide "
|
"operator<< include fmt/ostream.h. Otherwise provide "
|
||||||
"an overload of format_arg.");
|
"an overload of format_arg.");
|
||||||
|
@ -1283,6 +1365,9 @@ class MakeValue : public Arg {
|
||||||
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
|
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
|
||||||
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
|
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
|
||||||
MakeValue(typename WCharHelper<const std::wstring &, 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);
|
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
|
||||||
|
|
||||||
void set_string(StringRef str) {
|
void set_string(StringRef str) {
|
||||||
|
@ -1352,6 +1437,20 @@ class MakeValue : public Arg {
|
||||||
FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
|
FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
|
||||||
FMT_MAKE_VALUE(char, int_value, CHAR)
|
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)
|
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||||
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
|
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
|
||||||
int_value = value;
|
int_value = value;
|
||||||
|
@ -1370,6 +1469,9 @@ class MakeValue : public Arg {
|
||||||
FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING)
|
FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING)
|
||||||
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
|
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
|
||||||
FMT_MAKE_STR_VALUE(const std::string &, STRING)
|
FMT_MAKE_STR_VALUE(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_STR_VALUE(StringRef, STRING)
|
||||||
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
|
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
|
||||||
|
|
||||||
|
@ -1382,6 +1484,9 @@ class MakeValue : public Arg {
|
||||||
FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
|
FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
|
||||||
FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
|
FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
|
||||||
FMT_MAKE_WSTR_VALUE(const std::wstring &, 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_WSTR_VALUE(WStringRef, WSTRING)
|
||||||
|
|
||||||
FMT_MAKE_VALUE(void *, pointer, POINTER)
|
FMT_MAKE_VALUE(void *, pointer, POINTER)
|
||||||
|
@ -1447,7 +1552,7 @@ class RuntimeError : public std::runtime_error {
|
||||||
protected:
|
protected:
|
||||||
RuntimeError() : std::runtime_error("") {}
|
RuntimeError() : std::runtime_error("") {}
|
||||||
RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
|
RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
|
||||||
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT;
|
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
|
@ -1921,7 +2026,7 @@ class ArgMap {
|
||||||
MapType map_;
|
MapType map_;
|
||||||
|
|
||||||
public:
|
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.
|
// The list is unsorted, so just return the first matching name.
|
||||||
|
@ -1934,6 +2039,51 @@ class ArgMap {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>
|
template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
|
||||||
class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
||||||
private:
|
private:
|
||||||
|
@ -2220,7 +2370,8 @@ struct ArgArray;
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
struct ArgArray<N, true/*IsPacked*/> {
|
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>
|
template <typename Formatter, typename T>
|
||||||
static Value make(const T &value) {
|
static Value make(const T &value) {
|
||||||
|
@ -2410,7 +2561,7 @@ class SystemError : public internal::RuntimeError {
|
||||||
FMT_DEFAULTED_COPY_CTOR(SystemError)
|
FMT_DEFAULTED_COPY_CTOR(SystemError)
|
||||||
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
|
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
|
||||||
|
|
||||||
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT;
|
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||||
|
|
||||||
int error_code() const { return error_code_; }
|
int error_code() const { return error_code_; }
|
||||||
};
|
};
|
||||||
|
@ -3483,10 +3634,10 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||||
#define FMT_GET_ARG_NAME(type, index) arg##index
|
#define FMT_GET_ARG_NAME(type, index) arg##index
|
||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
|
||||||
template <typename... Args> \
|
template <typename... Args> \
|
||||||
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const Args & ... args) { \
|
const Args & ... args) Const { \
|
||||||
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
|
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
|
||||||
typename ArgArray::Type array{ \
|
typename ArgArray::Type array{ \
|
||||||
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
|
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
|
||||||
|
@ -3496,35 +3647,35 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||||
#else
|
#else
|
||||||
// Defines a wrapper for a function taking __VA_ARGS__ arguments
|
// Defines a wrapper for a function taking __VA_ARGS__ arguments
|
||||||
// and n additional arguments of arbitrary types.
|
// and n additional arguments of arbitrary types.
|
||||||
# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
|
# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \
|
||||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
FMT_GEN(n, FMT_MAKE_ARG)) { \
|
FMT_GEN(n, FMT_MAKE_ARG)) Const { \
|
||||||
fmt::internal::ArgArray<n>::Type arr; \
|
fmt::internal::ArgArray<n>::Type arr; \
|
||||||
FMT_GEN(n, FMT_ASSIGN_##Char); \
|
FMT_GEN(n, FMT_ASSIGN_##Char); \
|
||||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
|
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
|
||||||
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
|
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
|
||||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
|
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \
|
||||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
|
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
|
||||||
} \
|
} \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \
|
FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \
|
||||||
FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__)
|
FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__)
|
||||||
#endif // FMT_USE_VARIADIC_TEMPLATES
|
#endif // FMT_USE_VARIADIC_TEMPLATES
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3555,10 +3706,16 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
#define FMT_VARIADIC(ReturnType, func, ...) \
|
#define FMT_VARIADIC(ReturnType, func, ...) \
|
||||||
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
|
FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FMT_VARIADIC_CONST(ReturnType, func, ...) \
|
||||||
|
FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__)
|
||||||
|
|
||||||
#define FMT_VARIADIC_W(ReturnType, func, ...) \
|
#define FMT_VARIADIC_W(ReturnType, func, ...) \
|
||||||
FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \
|
||||||
|
FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
||||||
|
|
||||||
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
|
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
|
||||||
|
|
||||||
|
@ -3601,17 +3758,19 @@ template <typename Char>
|
||||||
unsigned parse_nonnegative_int(const Char *&s) {
|
unsigned parse_nonnegative_int(const Char *&s) {
|
||||||
assert('0' <= *s && *s <= '9');
|
assert('0' <= *s && *s <= '9');
|
||||||
unsigned value = 0;
|
unsigned value = 0;
|
||||||
do {
|
|
||||||
unsigned new_value = value * 10 + (*s++ - '0');
|
|
||||||
// Check if value wrapped around.
|
|
||||||
if (new_value < value) {
|
|
||||||
value = (std::numeric_limits<unsigned>::max)();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value = new_value;
|
|
||||||
} while ('0' <= *s && *s <= '9');
|
|
||||||
// Convert to unsigned to prevent a warning.
|
// Convert to unsigned to prevent a warning.
|
||||||
unsigned max_int = (std::numeric_limits<int>::max)();
|
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||||
|
unsigned big = max_int / 10;
|
||||||
|
do {
|
||||||
|
// Check for overflow.
|
||||||
|
if (value > big) {
|
||||||
|
value = max_int + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value = value * 10 + (*s - '0');
|
||||||
|
++s;
|
||||||
|
} while ('0' <= *s && *s <= '9');
|
||||||
|
// Convert to unsigned to prevent a warning.
|
||||||
if (value > max_int)
|
if (value > max_int)
|
||||||
FMT_THROW(FormatError("number is too big"));
|
FMT_THROW(FormatError("number is too big"));
|
||||||
return value;
|
return value;
|
||||||
|
@ -3783,7 +3942,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
|
||||||
default:
|
default:
|
||||||
FMT_THROW(FormatError("width is not integer"));
|
FMT_THROW(FormatError("width is not integer"));
|
||||||
}
|
}
|
||||||
if (value > (std::numeric_limits<int>::max)())
|
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||||
|
if (value > max_int)
|
||||||
FMT_THROW(FormatError("number is too big"));
|
FMT_THROW(FormatError("number is too big"));
|
||||||
spec.width_ = static_cast<int>(value);
|
spec.width_ = static_cast<int>(value);
|
||||||
}
|
}
|
||||||
|
@ -3821,7 +3981,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
|
||||||
default:
|
default:
|
||||||
FMT_THROW(FormatError("precision is not integer"));
|
FMT_THROW(FormatError("precision is not integer"));
|
||||||
}
|
}
|
||||||
if (value > (std::numeric_limits<int>::max)())
|
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||||
|
if (value > max_int)
|
||||||
FMT_THROW(FormatError("number is too big"));
|
FMT_THROW(FormatError("number is too big"));
|
||||||
spec.precision_ = static_cast<int>(value);
|
spec.precision_ = static_cast<int>(value);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -52,13 +52,15 @@ Yes &convert(std::ostream &);
|
||||||
|
|
||||||
struct DummyStream : std::ostream {
|
struct DummyStream : std::ostream {
|
||||||
DummyStream(); // Suppress a bogus warning in MSVC.
|
DummyStream(); // Suppress a bogus warning in MSVC.
|
||||||
|
|
||||||
// Hide all operator<< overloads from std::ostream.
|
// 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);
|
No &operator<<(std::ostream &, int);
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct ConvertToIntImpl<T, true> {
|
struct ConvertToIntImpl<T, true> {
|
||||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||||
enum {
|
enum {
|
||||||
|
@ -78,6 +80,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
|
||||||
|
|
||||||
internal::FormatBuf<Char> format_buf(buffer);
|
internal::FormatBuf<Char> format_buf(buffer);
|
||||||
std::basic_ostream<Char> output(&format_buf);
|
std::basic_ostream<Char> output(&format_buf);
|
||||||
|
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
output << value;
|
output << value;
|
||||||
|
|
||||||
BasicStringRef<Char> str(&buffer[0], buffer.size());
|
BasicStringRef<Char> str(&buffer[0], buffer.size());
|
||||||
|
|
|
@ -110,7 +110,7 @@ class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
|
||||||
visit_any_int(value);
|
visit_any_int(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_char(char value) {
|
void visit_char(int value) {
|
||||||
if (type_ != 's')
|
if (type_ != 's')
|
||||||
visit_any_int(value);
|
visit_any_int(value);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
|
||||||
using internal::Arg;
|
using internal::Arg;
|
||||||
typedef typename internal::Conditional<
|
typedef typename internal::Conditional<
|
||||||
is_same<T, void>::value, U, T>::type TargetType;
|
is_same<T, void>::value, U, T>::type TargetType;
|
||||||
if (sizeof(TargetType) <= sizeof(int)) {
|
if (const_check(sizeof(TargetType) <= sizeof(int))) {
|
||||||
// Extra casts are used to silence warnings.
|
// Extra casts are used to silence warnings.
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
arg_.type = Arg::INT;
|
arg_.type = Arg::INT;
|
||||||
|
|
22
fmt/string.h
22
fmt/string.h
|
@ -7,6 +7,10 @@
|
||||||
For the license information refer to format.h.
|
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_
|
#ifndef FMT_STRING_H_
|
||||||
#define FMT_STRING_H_
|
#define FMT_STRING_H_
|
||||||
|
|
||||||
|
@ -121,6 +125,24 @@ std::string to_string(const T &value) {
|
||||||
w << value;
|
w << value;
|
||||||
return w.str();
|
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_
|
#endif // FMT_STRING_H_
|
||||||
|
|
|
@ -8,7 +8,7 @@ Usage:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import datetime, docopt, fileinput, json, os
|
import datetime, docopt, errno, fileinput, json, os
|
||||||
import re, requests, shutil, sys, tempfile
|
import re, requests, shutil, sys, tempfile
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
@ -80,6 +80,7 @@ def create_build_env():
|
||||||
import build
|
import build
|
||||||
|
|
||||||
env.build_dir = 'build'
|
env.build_dir = 'build'
|
||||||
|
env.versions = build.versions
|
||||||
|
|
||||||
# Virtualenv and repos are cached to speed up builds.
|
# Virtualenv and repos are cached to speed up builds.
|
||||||
build.create_build_env(os.path.join(env.build_dir, 'virtualenv'))
|
build.create_build_env(os.path.join(env.build_dir, 'virtualenv'))
|
||||||
|
@ -113,7 +114,7 @@ def update_site(env):
|
||||||
doc_repo = Git(os.path.join(env.build_dir, 'fmtlib.github.io'))
|
doc_repo = Git(os.path.join(env.build_dir, 'fmtlib.github.io'))
|
||||||
doc_repo.update('git@github.com:fmtlib/fmtlib.github.io')
|
doc_repo.update('git@github.com:fmtlib/fmtlib.github.io')
|
||||||
|
|
||||||
for version in ['1.0.0', '1.1.0', '2.0.0', '3.0.0']:
|
for version in env.versions:
|
||||||
clean_checkout(env.fmt_repo, version)
|
clean_checkout(env.fmt_repo, version)
|
||||||
target_doc_dir = os.path.join(env.fmt_repo.dir, 'doc')
|
target_doc_dir = os.path.join(env.fmt_repo.dir, 'doc')
|
||||||
# Remove the old theme.
|
# Remove the old theme.
|
||||||
|
@ -165,7 +166,11 @@ def update_site(env):
|
||||||
os.symlink(target, link)
|
os.symlink(target, link)
|
||||||
# Copy docs to the website.
|
# Copy docs to the website.
|
||||||
version_doc_dir = os.path.join(doc_repo.dir, version)
|
version_doc_dir = os.path.join(doc_repo.dir, version)
|
||||||
shutil.rmtree(version_doc_dir)
|
try:
|
||||||
|
shutil.rmtree(version_doc_dir)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.ENOENT:
|
||||||
|
raise
|
||||||
shutil.move(html_dir, version_doc_dir)
|
shutil.move(html_dir, version_doc_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,27 +209,45 @@ def release(args):
|
||||||
line = '-' * title_len + '\n'
|
line = '-' * title_len + '\n'
|
||||||
title_len = 0
|
title_len = 0
|
||||||
sys.stdout.write(line)
|
sys.stdout.write(line)
|
||||||
# TODO: add new version to manage.py
|
|
||||||
|
# Add the version to the build script.
|
||||||
|
script = os.path.join('doc', 'build.py')
|
||||||
|
script_path = os.path.join(fmt_repo.dir, script)
|
||||||
|
for line in fileinput.input(script_path, inplace=True):
|
||||||
|
m = re.match(r'( *versions = )\[(.+)\]', line)
|
||||||
|
if m:
|
||||||
|
line = '{}[{}, \'{}\']\n'.format(m.group(1), m.group(2), version)
|
||||||
|
sys.stdout.write(line)
|
||||||
|
|
||||||
fmt_repo.checkout('-B', 'release')
|
fmt_repo.checkout('-B', 'release')
|
||||||
fmt_repo.add(changelog, cmakelists)
|
fmt_repo.add(changelog, cmakelists, script)
|
||||||
fmt_repo.commit('-m', 'Update version')
|
fmt_repo.commit('-m', 'Update version')
|
||||||
|
|
||||||
# Build the docs and package.
|
# Build the docs and package.
|
||||||
run = Runner(fmt_repo.dir)
|
run = Runner(fmt_repo.dir)
|
||||||
run('cmake', '.')
|
run('cmake', '.')
|
||||||
run('make', 'doc', 'package_source')
|
run('make', 'doc', 'package_source')
|
||||||
|
|
||||||
update_site(env)
|
update_site(env)
|
||||||
|
|
||||||
# Create a release on GitHub.
|
# Create a release on GitHub.
|
||||||
fmt_repo.push('origin', 'release')
|
fmt_repo.push('origin', 'release')
|
||||||
|
params = {'access_token': os.getenv('FMT_TOKEN')}
|
||||||
r = requests.post('https://api.github.com/repos/fmtlib/fmt/releases',
|
r = requests.post('https://api.github.com/repos/fmtlib/fmt/releases',
|
||||||
params={'access_token': os.getenv('FMT_TOKEN')},
|
params=params,
|
||||||
data=json.dumps({'tag_name': version,
|
data=json.dumps({'tag_name': version,
|
||||||
'target_commitish': 'release',
|
'target_commitish': 'release',
|
||||||
'body': changes, 'draft': True}))
|
'body': changes, 'draft': True}))
|
||||||
if r.status_code != 201:
|
if r.status_code != 201:
|
||||||
raise Exception('Failed to create a release ' + str(r))
|
raise Exception('Failed to create a release ' + str(r))
|
||||||
|
id = r.json()['id']
|
||||||
|
uploads_url = 'https://uploads.github.com/repos/fmtlib/fmt/releases'
|
||||||
|
package = 'fmt-{}.zip'.format(version)
|
||||||
|
with open('build/fmt/' + package, 'rb') as f:
|
||||||
|
r = requests.post(
|
||||||
|
'{}/{}/assets?name={}'.format(uploads_url, id, package),
|
||||||
|
params=params, files={package: f})
|
||||||
|
if r.status_code != 201:
|
||||||
|
raise Exception('Failed to upload an asset ' + str(r))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -30,7 +30,7 @@ def install_dependencies():
|
||||||
'| sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
|
'| sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
|
||||||
check_call(['sudo', 'apt-get', 'update'])
|
check_call(['sudo', 'apt-get', 'update'])
|
||||||
check_call(['sudo', 'apt-get', 'install', 'python-virtualenv', 'nodejs'])
|
check_call(['sudo', 'apt-get', 'install', 'python-virtualenv', 'nodejs'])
|
||||||
check_call(['npm', 'install', '-g', 'less', 'less-plugin-clean-css'])
|
check_call(['sudo', 'npm', 'install', '-g', 'less@2.6.1', 'less-plugin-clean-css'])
|
||||||
deb_file = 'doxygen_1.8.6-2_amd64.deb'
|
deb_file = 'doxygen_1.8.6-2_amd64.deb'
|
||||||
urllib.urlretrieve('http://mirrors.kernel.org/ubuntu/pool/main/d/doxygen/' +
|
urllib.urlretrieve('http://mirrors.kernel.org/ubuntu/pool/main/d/doxygen/' +
|
||||||
deb_file, deb_file)
|
deb_file, deb_file)
|
||||||
|
|
|
@ -151,16 +151,31 @@ TEST(StringRefTest, Ctor) {
|
||||||
|
|
||||||
EXPECT_STREQ("defg", StringRef(std::string("defg")).data());
|
EXPECT_STREQ("defg", StringRef(std::string("defg")).data());
|
||||||
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
|
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
|
||||||
|
|
||||||
|
#if FMT_HAS_STRING_VIEW
|
||||||
|
EXPECT_STREQ("hijk", StringRef(std::string_view("hijk")).data());
|
||||||
|
EXPECT_EQ(4u, StringRef(std::string_view("hijk")).size());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringRefTest, ConvertToString) {
|
TEST(StringRefTest, ConvertToString) {
|
||||||
std::string s = StringRef("abc").to_string();
|
std::string s = StringRef("abc").to_string();
|
||||||
EXPECT_EQ("abc", s);
|
EXPECT_EQ("abc", s);
|
||||||
|
|
||||||
|
#if FMT_HAS_STRING_VIEW
|
||||||
|
StringRef str_ref("defg");
|
||||||
|
std::string_view sv = static_cast<std::string_view>(str_ref);
|
||||||
|
EXPECT_EQ("defg", sv);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CStringRefTest, Ctor) {
|
TEST(CStringRefTest, Ctor) {
|
||||||
EXPECT_STREQ("abc", CStringRef("abc").c_str());
|
EXPECT_STREQ("abc", CStringRef("abc").c_str());
|
||||||
EXPECT_STREQ("defg", CStringRef(std::string("defg")).c_str());
|
EXPECT_STREQ("defg", CStringRef(std::string("defg")).c_str());
|
||||||
|
|
||||||
|
#if FMT_HAS_STRING_VIEW
|
||||||
|
EXPECT_STREQ("hijk", CStringRef(std::string_view("hijk")).c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_USE_TYPE_TRAITS
|
#if FMT_USE_TYPE_TRAITS
|
||||||
|
@ -1378,6 +1393,12 @@ TEST(FormatterTest, FormatCStringRef) {
|
||||||
EXPECT_EQ("test", format("{0}", CStringRef("test")));
|
EXPECT_EQ("test", format("{0}", CStringRef("test")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FMT_HAS_STRING_VIEW
|
||||||
|
TEST(FormatterTest, FormatStringView) {
|
||||||
|
EXPECT_EQ("test", format("{0}", std::string_view("test")));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void format_arg(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
|
void format_arg(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
|
||||||
f.writer() << d.year() << '-' << d.month() << '-' << d.day();
|
f.writer() << d.year() << '-' << d.month() << '-' << d.day();
|
||||||
}
|
}
|
||||||
|
@ -1609,6 +1630,24 @@ TEST(FormatTest, FormatMessageExample) {
|
||||||
format_message(42, "{} happened", "something"));
|
format_message(42, "{} happened", "something"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class test_class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string format_message(int id, const char *format,const fmt::ArgList &args) const {
|
||||||
|
MemoryWriter w;
|
||||||
|
w.write("[{}] ", id);
|
||||||
|
w.write(format, args);
|
||||||
|
return w.str();
|
||||||
|
}
|
||||||
|
FMT_VARIADIC_CONST(std::string, format_message, int, const char *)
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(FormatTest, ConstFormatMessage) {
|
||||||
|
test_class c;
|
||||||
|
EXPECT_EQ("[42] something happened",
|
||||||
|
c.format_message(42, "{} happened", "something"));
|
||||||
|
}
|
||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void print_error(const char *file, int line, const char *format,
|
void print_error(const char *file, int line, const char *format,
|
||||||
|
@ -1660,6 +1699,14 @@ TEST(FormatTest, Enum) {
|
||||||
EXPECT_EQ("0", fmt::format("{}", A));
|
EXPECT_EQ("0", fmt::format("{}", A));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
enum TestFixedEnum : short { B };
|
||||||
|
|
||||||
|
TEST(FormatTest, FixedEnum) {
|
||||||
|
EXPECT_EQ("0", fmt::format("{}", B));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class MockArgFormatter :
|
class MockArgFormatter :
|
||||||
public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
|
public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,7 +36,7 @@ class MockAllocator {
|
||||||
MockAllocator() {}
|
MockAllocator() {}
|
||||||
MockAllocator(const MockAllocator &) {}
|
MockAllocator(const MockAllocator &) {}
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
MOCK_METHOD2_T(allocate, T *(std::size_t n, const T *h));
|
MOCK_METHOD2_T(allocate, T *(std::size_t n, const void *h));
|
||||||
MOCK_METHOD2_T(deallocate, void (T *p, std::size_t n));
|
MOCK_METHOD2_T(deallocate, void (T *p, std::size_t n));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,8 +78,12 @@ class AllocatorRef {
|
||||||
|
|
||||||
Allocator *get() const { return alloc_; }
|
Allocator *get() const { return alloc_; }
|
||||||
|
|
||||||
value_type *allocate(std::size_t n, const value_type *h) {
|
value_type *allocate(std::size_t n, const void *h) {
|
||||||
|
#if FMT_USE_ALLOCATOR_TRAITS
|
||||||
|
return std::allocator_traits<Allocator>::allocate(*alloc_, n, h);
|
||||||
|
#else
|
||||||
return alloc_->allocate(n, h);
|
return alloc_->allocate(n, h);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
|
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -172,3 +172,18 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
|
||||||
} while (size != 0);
|
} while (size != 0);
|
||||||
fmt::internal::write(os, w);
|
fmt::internal::write(os, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ConvertibleToInt {
|
||||||
|
template <typename ValueType>
|
||||||
|
operator ValueType() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &o, ConvertibleToInt) {
|
||||||
|
return o << "foo";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(FormatTest, FormatConvertibleToInt) {
|
||||||
|
EXPECT_EQ("foo", fmt::format("{}", ConvertibleToInt()));
|
||||||
|
}
|
||||||
|
|
|
@ -78,3 +78,7 @@ TEST(StringWriterTest, WString) {
|
||||||
TEST(StringTest, ToString) {
|
TEST(StringTest, ToString) {
|
||||||
EXPECT_EQ("42", fmt::to_string(42));
|
EXPECT_EQ("42", fmt::to_string(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(StringTest, ToWString) {
|
||||||
|
EXPECT_EQ(L"42", fmt::to_wstring(42));
|
||||||
|
}
|
||||||
|
|
|
@ -837,8 +837,21 @@ TEST(UtilTest, FormatSystemError) {
|
||||||
fmt::format_system_error(message, EDOM, "test");
|
fmt::format_system_error(message, EDOM, "test");
|
||||||
EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), message.str());
|
EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), message.str());
|
||||||
message.clear();
|
message.clear();
|
||||||
fmt::format_system_error(
|
|
||||||
message, EDOM, fmt::StringRef(0, std::numeric_limits<size_t>::max()));
|
// Check if std::allocator throws on allocating max size_t / 2 chars.
|
||||||
|
size_t max_size = std::numeric_limits<size_t>::max() / 2;
|
||||||
|
bool throws_on_alloc = false;
|
||||||
|
try {
|
||||||
|
std::allocator<char> alloc;
|
||||||
|
alloc.deallocate(alloc.allocate(max_size), max_size);
|
||||||
|
} catch (std::bad_alloc) {
|
||||||
|
throws_on_alloc = true;
|
||||||
|
}
|
||||||
|
if (!throws_on_alloc) {
|
||||||
|
fmt::print("warning: std::allocator allocates {} chars", max_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fmt::format_system_error(message, EDOM, fmt::StringRef(0, max_size));
|
||||||
EXPECT_EQ(fmt::format("error {}", EDOM), message.str());
|
EXPECT_EQ(fmt::format("error {}", EDOM), message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue