feat(Deps/Fmt): update to 8.0.1 (#6859)
This commit is contained in:
parent
920825b759
commit
7c21d567d5
39
deps/fmt/CMakeLists.txt
vendored
39
deps/fmt/CMakeLists.txt
vendored
@ -28,27 +28,34 @@ else()
|
||||
check_symbol_exists(strtod_l "${strtod_l_headers}" HAVE_STRTOD_L)
|
||||
endif()
|
||||
|
||||
set(FMT_HEADERS
|
||||
include/fmt/args.h
|
||||
include/fmt/chrono.h
|
||||
include/fmt/color.h
|
||||
include/fmt/compile.h
|
||||
include/fmt/core.h
|
||||
include/fmt/format.h
|
||||
include/fmt/format-inl.h
|
||||
include/fmt/locale.h
|
||||
include/fmt/os.h
|
||||
include/fmt/ostream.h
|
||||
include/fmt/printf.h
|
||||
include/fmt/ranges.h)
|
||||
function(add_headers VAR)
|
||||
set(headers ${${VAR}})
|
||||
foreach (header ${ARGN})
|
||||
set(headers ${headers} include/fmt/${header})
|
||||
endforeach()
|
||||
set(${VAR} ${headers} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Define the fmt library, its includes and the needed defines.
|
||||
add_headers(FMT_HEADERS
|
||||
args.h
|
||||
chrono.h
|
||||
color.h
|
||||
compile.h
|
||||
core.h
|
||||
format.h
|
||||
format-inl.h
|
||||
locale.h os.h
|
||||
ostream.h
|
||||
printf.h
|
||||
ranges.h
|
||||
xchar.h)
|
||||
|
||||
set(FMT_SOURCES
|
||||
src/format.cc
|
||||
src/os.cc)
|
||||
|
||||
add_library(fmt STATIC
|
||||
${FMT_SOURCES}
|
||||
${FMT_HEADERS})
|
||||
add_library(fmt STATIC ${FMT_SOURCES} ${FMT_HEADERS})
|
||||
|
||||
if (HAVE_STRTOD_L)
|
||||
target_compile_definitions(fmt
|
||||
|
||||
700
deps/fmt/ChangeLog.rst
vendored
700
deps/fmt/ChangeLog.rst
vendored
@ -1,3 +1,699 @@
|
||||
8.0.1 - 2021-07-02
|
||||
------------------
|
||||
|
||||
* Fixed the version number in the inline namespace
|
||||
(`#2374 <https://github.com/fmtlib/fmt/issues/2374>`_).
|
||||
|
||||
* Added a missing presentation type check for ``std::string``
|
||||
(`#2402 <https://github.com/fmtlib/fmt/issues/2402>`_).
|
||||
|
||||
* Fixed a linkage error when mixing code built with clang and gcc
|
||||
(`#2377 <https://github.com/fmtlib/fmt/issues/2377>`_).
|
||||
|
||||
* Fixed documentation issues
|
||||
(`#2396 <https://github.com/fmtlib/fmt/pull/2396>`_,
|
||||
`#2403 <https://github.com/fmtlib/fmt/issues/2403>`_,
|
||||
`#2406 <https://github.com/fmtlib/fmt/issues/2406>`_).
|
||||
Thanks `@mkurdej (Marek Kurdej) <https://github.com/mkurdej>`_.
|
||||
|
||||
* Removed dead code in FP formatter (
|
||||
`#2398 <https://github.com/fmtlib/fmt/pull/2398>`_).
|
||||
Thanks `@javierhonduco (Javier Honduvilla Coto)
|
||||
<https://github.com/javierhonduco>`_.
|
||||
|
||||
* Fixed various warnings and compilation issues
|
||||
(`#2351 <https://github.com/fmtlib/fmt/issues/2351>`_,
|
||||
`#2359 <https://github.com/fmtlib/fmt/issues/2359>`_,
|
||||
`#2365 <https://github.com/fmtlib/fmt/pull/2365>`_,
|
||||
`#2368 <https://github.com/fmtlib/fmt/issues/2368>`_,
|
||||
`#2370 <https://github.com/fmtlib/fmt/pull/2370>`_,
|
||||
`#2376 <https://github.com/fmtlib/fmt/pull/2376>`_,
|
||||
`#2381 <https://github.com/fmtlib/fmt/pull/2381>`_,
|
||||
`#2382 <https://github.com/fmtlib/fmt/pull/2382>`_,
|
||||
`#2386 <https://github.com/fmtlib/fmt/issues/2386>`_,
|
||||
`#2389 <https://github.com/fmtlib/fmt/pull/2389>`_,
|
||||
`#2395 <https://github.com/fmtlib/fmt/pull/2395>`_,
|
||||
`#2397 <https://github.com/fmtlib/fmt/pull/2397>`_,
|
||||
`#2400 <https://github.com/fmtlib/fmt/issues/2400>`_
|
||||
`#2401 <https://github.com/fmtlib/fmt/issues/2401>`_,
|
||||
`#2407 <https://github.com/fmtlib/fmt/pull/2407>`_).
|
||||
Thanks `@zx2c4 (Jason A. Donenfeld) <https://github.com/zx2c4>`_,
|
||||
`@AidanSun05 (Aidan Sun) <https://github.com/AidanSun05>`_,
|
||||
`@mattiasljungstrom (Mattias Ljungström)
|
||||
<https://github.com/mattiasljungstrom>`_,
|
||||
`@joemmett (Jonathan Emmett) <https://github.com/joemmett>`_,
|
||||
`@erengy (Eren Okka) <https://github.com/erengy>`_,
|
||||
`@patlkli (Patrick Geltinger) <https://github.com/patlkli>`_,
|
||||
`@gsjaardema (Greg Sjaardema) <https://github.com/gsjaardema>`_,
|
||||
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
8.0.0 - 2021-06-21
|
||||
------------------
|
||||
|
||||
* Enabled compile-time format string check by default.
|
||||
For example (`godbolt <https://godbolt.org/z/sMxcohGjz>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{:d}", "I am not a number");
|
||||
}
|
||||
|
||||
gives a compile-time error on compilers with C++20 ``consteval`` support
|
||||
(gcc 10+, clang 11+) because ``d`` is not a valid format specifier for a
|
||||
string.
|
||||
|
||||
To pass a runtime string wrap it in ``fmt::runtime``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::print(fmt::runtime("{:d}"), "I am not a number");
|
||||
|
||||
* Added compile-time formatting
|
||||
(`#2019 <https://github.com/fmtlib/fmt/pull/2019>`_,
|
||||
`#2044 <https://github.com/fmtlib/fmt/pull/2044>`_,
|
||||
`#2056 <https://github.com/fmtlib/fmt/pull/2056>`_,
|
||||
`#2072 <https://github.com/fmtlib/fmt/pull/2072>`_,
|
||||
`#2075 <https://github.com/fmtlib/fmt/pull/2075>`_,
|
||||
`#2078 <https://github.com/fmtlib/fmt/issues/2078>`_,
|
||||
`#2129 <https://github.com/fmtlib/fmt/pull/2129>`_,
|
||||
`#2326 <https://github.com/fmtlib/fmt/pull/2326>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/Mxx9d89jM>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/compile.h>
|
||||
|
||||
consteval auto compile_time_itoa(int value) -> std::array<char, 10> {
|
||||
auto result = std::array<char, 10>();
|
||||
fmt::format_to(result.data(), FMT_COMPILE("{}"), value);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr auto answer = compile_time_itoa(42);
|
||||
|
||||
Most of the formatting functionality is available at compile time with a
|
||||
notable exception of floating-point numbers and pointers.
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Optimized handling of format specifiers during format string compilation.
|
||||
For example, hexadecimal formatting (``"{:x}"``) is now 3-7x faster than
|
||||
before when using ``format_to`` with format string compilation and a
|
||||
stack-allocated buffer (`#1944 <https://github.com/fmtlib/fmt/issues/1944>`_).
|
||||
|
||||
Before (7.1.3)::
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
----------------------------------------------------------------------------
|
||||
FMTCompileOld/0 15.5 ns 15.5 ns 43302898
|
||||
FMTCompileOld/42 16.6 ns 16.6 ns 43278267
|
||||
FMTCompileOld/273123 18.7 ns 18.6 ns 37035861
|
||||
FMTCompileOld/9223372036854775807 19.4 ns 19.4 ns 35243000
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
After (8.x)::
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
----------------------------------------------------------------------------
|
||||
FMTCompileNew/0 1.99 ns 1.99 ns 360523686
|
||||
FMTCompileNew/42 2.33 ns 2.33 ns 279865664
|
||||
FMTCompileNew/273123 3.72 ns 3.71 ns 190230315
|
||||
FMTCompileNew/9223372036854775807 5.28 ns 5.26 ns 130711631
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
It is even faster than ``std::to_chars`` from libc++ compiled with clang on
|
||||
macOS::
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
----------------------------------------------------------------------------
|
||||
ToChars/0 4.42 ns 4.41 ns 160196630
|
||||
ToChars/42 5.00 ns 4.98 ns 140735201
|
||||
ToChars/273123 7.26 ns 7.24 ns 95784130
|
||||
ToChars/9223372036854775807 8.77 ns 8.75 ns 75872534
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
In other cases, especially involving ``std::string`` construction, the
|
||||
speed up is usually lower because handling format specifiers takes a smaller
|
||||
fraction of the total time.
|
||||
|
||||
* Added the ``_cf`` user-defined literal to represent a compiled format string.
|
||||
It can be used instead of the ``FMT_COMPILE`` macro
|
||||
(`#2043 <https://github.com/fmtlib/fmt/pull/2043>`_,
|
||||
`#2242 <https://github.com/fmtlib/fmt/pull/2242>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/compile.h>
|
||||
|
||||
using namespace fmt::literals;
|
||||
auto s = fmt::format(FMT_COMPILE("{}"), 42); // 🙁 not modern
|
||||
auto s = fmt::format("{}"_cf, 42); // 🙂 modern as hell
|
||||
|
||||
It requires compiler support for class types in non-type template parameters
|
||||
(a C++20 feature) which is available in GCC 9.3+.
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Format string compilation now requires ``format`` functions of ``formatter``
|
||||
specializations for user-defined types to be ``const``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
template <> struct fmt::formatter<my_type>: formatter<string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(my_type obj, FormatContext& ctx) const { // Note const here.
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
* Added UDL-based named argument support to format string compilation
|
||||
(`#2243 <https://github.com/fmtlib/fmt/pull/2243>`_,
|
||||
`#2281 <https://github.com/fmtlib/fmt/pull/2281>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/compile.h>
|
||||
|
||||
using namespace fmt::literals;
|
||||
auto s = fmt::format(FMT_COMPILE("{answer}"), "answer"_a = 42);
|
||||
|
||||
Here the argument named "answer" is resolved at compile time with no
|
||||
runtime overhead.
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Added format string compilation support to ``fmt::print``
|
||||
(`#2280 <https://github.com/fmtlib/fmt/issues/2280>`_,
|
||||
`#2304 <https://github.com/fmtlib/fmt/pull/2304>`_).
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Added initial support for compiling {fmt} as a C++20 module
|
||||
(`#2235 <https://github.com/fmtlib/fmt/pull/2235>`_,
|
||||
`#2240 <https://github.com/fmtlib/fmt/pull/2240>`_,
|
||||
`#2260 <https://github.com/fmtlib/fmt/pull/2260>`_,
|
||||
`#2282 <https://github.com/fmtlib/fmt/pull/2282>`_,
|
||||
`#2283 <https://github.com/fmtlib/fmt/pull/2283>`_,
|
||||
`#2288 <https://github.com/fmtlib/fmt/pull/2288>`_,
|
||||
`#2298 <https://github.com/fmtlib/fmt/pull/2298>`_,
|
||||
`#2306 <https://github.com/fmtlib/fmt/pull/2306>`_,
|
||||
`#2307 <https://github.com/fmtlib/fmt/pull/2307>`_,
|
||||
`#2309 <https://github.com/fmtlib/fmt/pull/2309>`_,
|
||||
`#2318 <https://github.com/fmtlib/fmt/pull/2318>`_,
|
||||
`#2324 <https://github.com/fmtlib/fmt/pull/2324>`_,
|
||||
`#2332 <https://github.com/fmtlib/fmt/pull/2332>`_,
|
||||
`#2340 <https://github.com/fmtlib/fmt/pull/2340>`_).
|
||||
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_.
|
||||
|
||||
* Made symbols private by default reducing shared library size
|
||||
(`#2301 <https://github.com/fmtlib/fmt/pull/2301>`_). For example there was
|
||||
a ~15% reported reduction on one platform.
|
||||
Thanks `@sergiud (Sergiu Deitsch) <https://github.com/sergiud>`_.
|
||||
|
||||
* Optimized includes making the result of preprocessing ``fmt/format.h``
|
||||
~20% smaller with libstdc++/C++20 and slightly improving build times
|
||||
(`#1998 <https://github.com/fmtlib/fmt/issues/1998>`_).
|
||||
|
||||
* Added support of ranges with non-const ``begin`` / ``end``
|
||||
(`#1953 <https://github.com/fmtlib/fmt/pull/1953>`_).
|
||||
Thanks `@kitegi (sarah) <https://github.com/kitegi>`_.
|
||||
|
||||
* Added support of ``std::byte`` and other formattable types to ``fmt::join``
|
||||
(`#1981 <https://github.com/fmtlib/fmt/issues/1981>`_,
|
||||
`#2040 <https://github.com/fmtlib/fmt/issues/2040>`_,
|
||||
`#2050 <https://github.com/fmtlib/fmt/pull/2050>`_,
|
||||
`#2262 <https://github.com/fmtlib/fmt/issues/2262>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
auto bytes = std::vector{std::byte(4), std::byte(2)};
|
||||
fmt::print("{}", fmt::join(bytes, ""));
|
||||
}
|
||||
|
||||
prints "42".
|
||||
|
||||
Thanks `@kamibo (Camille Bordignon) <https://github.com/kamibo>`_.
|
||||
|
||||
* Implemented the default format for ``std::chrono::system_clock``
|
||||
(`#2319 <https://github.com/fmtlib/fmt/issues/2319>`_,
|
||||
`#2345 <https://github.com/fmtlib/fmt/pull/2345>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{}", std::chrono::system_clock::now());
|
||||
}
|
||||
|
||||
prints "2021-06-18 15:22:00" (the output depends on the current date and
|
||||
time). Thanks `@sunmy2019 <https://github.com/sunmy2019>`_.
|
||||
|
||||
* Made more chrono specifiers locale independent by default. Use the ``'L'``
|
||||
specifier to get localized formatting. For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
int main() {
|
||||
std::locale::global(std::locale("ru_RU.UTF-8"));
|
||||
auto monday = std::chrono::weekday(1);
|
||||
fmt::print("{}\n", monday); // prints "Mon"
|
||||
fmt::print("{:L}\n", monday); // prints "пн"
|
||||
}
|
||||
|
||||
* Improved locale handling in chrono formatting
|
||||
(`#2337 <https://github.com/fmtlib/fmt/issues/2337>`_,
|
||||
`#2349 <https://github.com/fmtlib/fmt/pull/2349>`_,
|
||||
`#2350 <https://github.com/fmtlib/fmt/pull/2350>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Deprecated ``fmt/locale.h`` moving the formatting functions that take a
|
||||
locale to ``fmt/format.h`` (``char``) and ``fmt/xchar`` (other overloads).
|
||||
This doesn't introduce a dependency on ``<locale>`` so there is virtually no
|
||||
compile time effect.
|
||||
|
||||
* Made parameter order in ``vformat_to`` consistent with ``format_to``
|
||||
(`#2327 <https://github.com/fmtlib/fmt/issues/2327>`_).
|
||||
|
||||
* Added support for time points with arbitrary durations
|
||||
(`#2208 <https://github.com/fmtlib/fmt/issues/2208>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
int main() {
|
||||
using tp = std::chrono::time_point<
|
||||
std::chrono::system_clock, std::chrono::seconds>;
|
||||
fmt::print("{:%S}", tp(std::chrono::seconds(42)));
|
||||
}
|
||||
|
||||
prints "42".
|
||||
|
||||
* Formatting floating-point numbers no longer produces trailing zeros by default
|
||||
for consistency with ``std::format``. For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{0:.3}", 1.1);
|
||||
}
|
||||
|
||||
prints "1.1". Use the ``'#'`` specifier to keep trailing zeros.
|
||||
|
||||
* Dropped a limit on the number of elements in a range and replaced ``{}`` with
|
||||
``[]`` as range delimiters for consistency with Python's ``str.format``.
|
||||
|
||||
* The ``'L'`` specifier for locale-specific numeric formatting can now be
|
||||
combined with presentation specifiers as in ``std::format``. For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <locale>
|
||||
|
||||
int main() {
|
||||
std::locale::global(std::locale("fr_FR.UTF-8"));
|
||||
fmt::print("{0:.2Lf}", 0.42);
|
||||
}
|
||||
|
||||
prints "0,42". The deprecated ``'n'`` specifier has been removed.
|
||||
|
||||
* Made the ``0`` specifier ignored for infinity and NaN
|
||||
(`#2305 <https://github.com/fmtlib/fmt/issues/2305>`_,
|
||||
`#2310 <https://github.com/fmtlib/fmt/pull/2310>`_).
|
||||
Thanks `@Liedtke (Matthias Liedtke) <https://github.com/Liedtke>`_.
|
||||
|
||||
* Made the hexfloat formatting use the right alignment by default
|
||||
(`#2308 <https://github.com/fmtlib/fmt/issues/2308>`_,
|
||||
`#2317 <https://github.com/fmtlib/fmt/pull/2317>`_).
|
||||
Thanks `@Liedtke (Matthias Liedtke) <https://github.com/Liedtke>`_.
|
||||
|
||||
* Removed the deprecated numeric alignment (``'='``). Use the ``'0'`` specifier
|
||||
instead.
|
||||
|
||||
* Removed the deprecated ``fmt/posix.h`` header that has been replaced with
|
||||
``fmt/os.h``.
|
||||
|
||||
* Removed the deprecated ``format_to_n_context``, ``format_to_n_args`` and
|
||||
``make_format_to_n_args``. They have been replaced with ``format_context``,
|
||||
``format_args` and ``make_format_args`` respectively.
|
||||
|
||||
* Moved ``wchar_t``-specific functions and types to ``fmt/xchar.h``.
|
||||
You can define ``FMT_DEPRECATED_INCLUDE_XCHAR`` to automatically include
|
||||
``fmt/xchar.h`` from ``fmt/format.h`` but this will be disabled in the next
|
||||
major release.
|
||||
|
||||
* Fixed handling of the ``'+'`` specifier in localized formatting
|
||||
(`#2133 <https://github.com/fmtlib/fmt/issues/2133>`_).
|
||||
|
||||
* Added support for the ``'s'`` format specifier that gives textual
|
||||
representation of ``bool``
|
||||
(`#2094 <https://github.com/fmtlib/fmt/issues/2094>`_,
|
||||
`#2109 <https://github.com/fmtlib/fmt/pull/2109>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{:s}", true);
|
||||
}
|
||||
|
||||
prints "true".
|
||||
Thanks `@powercoderlol (Ivan Polyakov) <https://github.com/powercoderlol>`_.
|
||||
|
||||
* Made ``fmt::ptr`` work with function pointers
|
||||
(`#2131 <https://github.com/fmtlib/fmt/pull/2131>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("My main: {}\n", fmt::ptr(main));
|
||||
}
|
||||
|
||||
Thanks `@mikecrowe (Mike Crowe) <https://github.com/mikecrowe>`_.
|
||||
|
||||
* Fixed ``fmt::formatted_size`` with format string compilation
|
||||
(`#2141 <https://github.com/fmtlib/fmt/pull/2141>`_,
|
||||
`#2161 <https://github.com/fmtlib/fmt/pull/2161>`_).
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Fixed handling of empty format strings during format string compilation
|
||||
(`#2042 <https://github.com/fmtlib/fmt/issues/2042>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
auto s = fmt::format(FMT_COMPILE(""));
|
||||
|
||||
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
|
||||
|
||||
* Fixed handling of enums in ``fmt::to_string``
|
||||
(`#2036 <https://github.com/fmtlib/fmt/issues/2036>`_).
|
||||
|
||||
* Improved width computation
|
||||
(`#2033 <https://github.com/fmtlib/fmt/issues/2033>`_,
|
||||
`#2091 <https://github.com/fmtlib/fmt/issues/2091>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{:-<10}{}\n", "你好", "世界");
|
||||
fmt::print("{:-<10}{}\n", "hello", "world");
|
||||
}
|
||||
|
||||
prints
|
||||
|
||||
.. image:: https://user-images.githubusercontent.com/576385/
|
||||
119840373-cea3ca80-beb9-11eb-91e0-54266c48e181.png
|
||||
|
||||
on a modern terminal.
|
||||
|
||||
* The experimental fast output stream (``fmt::ostream``) is now truncated by
|
||||
default for consistency with ``fopen``
|
||||
(`#2018 <https://github.com/fmtlib/fmt/issues/2018>`_). For example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/os.h>
|
||||
|
||||
int main() {
|
||||
fmt::ostream out1 = fmt::output_file("guide");
|
||||
out1.print("Zaphod");
|
||||
out1.close();
|
||||
fmt::ostream out2 = fmt::output_file("guide");
|
||||
out2.print("Ford");
|
||||
}
|
||||
|
||||
writes "Ford" to the file "guide". To preserve the old file content if any
|
||||
pass ``fmt::file::WRONLY | fmt::file::CREATE`` flags to ``fmt::output_file``.
|
||||
|
||||
* Fixed moving of ``fmt::ostream`` that holds buffered data
|
||||
(`#2197 <https://github.com/fmtlib/fmt/issues/2197>`_,
|
||||
`#2198 <https://github.com/fmtlib/fmt/pull/2198>`_).
|
||||
Thanks `@vtta <https://github.com/vtta>`_.
|
||||
|
||||
* Replaced the ``fmt::system_error`` exception with a function of the same
|
||||
name that constructs ``std::system_error``
|
||||
(`#2266 <https://github.com/fmtlib/fmt/issues/2266>`_).
|
||||
|
||||
* Replaced the ``fmt::windows_error`` exception with a function of the same
|
||||
name that constructs ``std::system_error`` with the category returned by
|
||||
``fmt::system_category()``
|
||||
(`#2274 <https://github.com/fmtlib/fmt/issues/2274>`_,
|
||||
`#2275 <https://github.com/fmtlib/fmt/pull/2275>`_).
|
||||
The latter is similar to ``std::sytem_category`` but correctly handles UTF-8.
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Replaced ``fmt::error_code`` with ``std::error_code`` and made it formattable
|
||||
(`#2269 <https://github.com/fmtlib/fmt/issues/2269>`_,
|
||||
`#2270 <https://github.com/fmtlib/fmt/pull/2270>`_,
|
||||
`#2273 <https://github.com/fmtlib/fmt/pull/2273>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Added speech synthesis support
|
||||
(`#2206 <https://github.com/fmtlib/fmt/pull/2206>`_).
|
||||
|
||||
* Made ``format_to`` work with a memory buffer that has a custom allocator
|
||||
(`#2300 <https://github.com/fmtlib/fmt/pull/2300>`_).
|
||||
Thanks `@voxmea <https://github.com/voxmea>`_.
|
||||
|
||||
* Added ``Allocator::max_size`` support to ``basic_memory_buffer``.
|
||||
(`#1960 <https://github.com/fmtlib/fmt/pull/1960>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Added wide string support to ``fmt::join``
|
||||
(`#2236 <https://github.com/fmtlib/fmt/pull/2236>`_).
|
||||
Thanks `@crbrz <https://github.com/crbrz>`_.
|
||||
|
||||
* Made iterators passed to ``formatter`` specializations via a format context
|
||||
satisfy C++20 ``std::output_iterator`` requirements
|
||||
(`#2156 <https://github.com/fmtlib/fmt/issues/2156>`_,
|
||||
`#2158 <https://github.com/fmtlib/fmt/pull/2158>`_,
|
||||
`#2195 <https://github.com/fmtlib/fmt/issues/2195>`_,
|
||||
`#2204 <https://github.com/fmtlib/fmt/pull/2204>`_).
|
||||
Thanks `@randomnetcat (Jason Cobb) <https://github.com/randomnetcat>`_.
|
||||
|
||||
* Optimized the ``printf`` implementation
|
||||
(`#1982 <https://github.com/fmtlib/fmt/pull/1982>`_,
|
||||
`#1984 <https://github.com/fmtlib/fmt/pull/1984>`_,
|
||||
`#2016 <https://github.com/fmtlib/fmt/pull/2016>`_,
|
||||
`#2164 <https://github.com/fmtlib/fmt/pull/2164>`_).
|
||||
Thanks `@rimathia <https://github.com/rimathia>`_ and
|
||||
`@moiwi <https://github.com/moiwi>`_.
|
||||
|
||||
* Improved detection of ``constexpr`` ``char_traits``
|
||||
(`#2246 <https://github.com/fmtlib/fmt/pull/2246>`_,
|
||||
`#2257 <https://github.com/fmtlib/fmt/pull/2257>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Fixed writing to ``stdout`` when it is redirected to ``NUL`` on Windows
|
||||
(`#2080 <https://github.com/fmtlib/fmt/issues/2080>`_).
|
||||
|
||||
* Fixed exception propagation from iterators
|
||||
(`#2097 <https://github.com/fmtlib/fmt/issues/2097>`_).
|
||||
|
||||
* Improved ``strftime`` error handling
|
||||
(`#2238 <https://github.com/fmtlib/fmt/issues/2238>`_,
|
||||
`#2244 <https://github.com/fmtlib/fmt/pull/2244>`_).
|
||||
Thanks `@yumeyao <https://github.com/yumeyao>`_.
|
||||
|
||||
* Stopped using deprecated GCC UDL template extension.
|
||||
|
||||
* Added ``fmt/args.h`` to the install target
|
||||
(`#2096 <https://github.com/fmtlib/fmt/issues/2096>`_).
|
||||
|
||||
* Error messages are now passed to assert when exceptions are disabled
|
||||
(`#2145 <https://github.com/fmtlib/fmt/pull/2145>`_).
|
||||
Thanks `@NobodyXu (Jiahao XU) <https://github.com/NobodyXu>`_.
|
||||
|
||||
* Added the ``FMT_MASTER_PROJECT`` CMake option to control build and install
|
||||
targets when {fmt} is included via ``add_subdirectory``
|
||||
(`#2098 <https://github.com/fmtlib/fmt/issues/2098>`_,
|
||||
`#2100 <https://github.com/fmtlib/fmt/pull/2100>`_).
|
||||
Thanks `@randomizedthinking <https://github.com/randomizedthinking>`_.
|
||||
|
||||
* Improved build configuration
|
||||
(`#2026 <https://github.com/fmtlib/fmt/pull/2026>`_,
|
||||
`#2122 <https://github.com/fmtlib/fmt/pull/2122>`_).
|
||||
Thanks `@luncliff (Park DongHa) <https://github.com/luncliff>`_ and
|
||||
`@ibaned (Dan Ibanez) <https://github.com/ibaned>`_.
|
||||
|
||||
* Fixed various warnings and compilation issues
|
||||
(`#1947 <https://github.com/fmtlib/fmt/issues/1947>`_,
|
||||
`#1959 <https://github.com/fmtlib/fmt/pull/1959>`_,
|
||||
`#1963 <https://github.com/fmtlib/fmt/pull/1963>`_,
|
||||
`#1965 <https://github.com/fmtlib/fmt/pull/1965>`_,
|
||||
`#1966 <https://github.com/fmtlib/fmt/issues/1966>`_,
|
||||
`#1974 <https://github.com/fmtlib/fmt/pull/1974>`_,
|
||||
`#1975 <https://github.com/fmtlib/fmt/pull/1975>`_,
|
||||
`#1990 <https://github.com/fmtlib/fmt/pull/1990>`_,
|
||||
`#2000 <https://github.com/fmtlib/fmt/issues/2000>`_,
|
||||
`#2001 <https://github.com/fmtlib/fmt/pull/2001>`_,
|
||||
`#2002 <https://github.com/fmtlib/fmt/issues/2002>`_,
|
||||
`#2004 <https://github.com/fmtlib/fmt/issues/2004>`_,
|
||||
`#2006 <https://github.com/fmtlib/fmt/pull/2006>`_,
|
||||
`#2009 <https://github.com/fmtlib/fmt/pull/2009>`_,
|
||||
`#2010 <https://github.com/fmtlib/fmt/pull/2010>`_,
|
||||
`#2038 <https://github.com/fmtlib/fmt/issues/2038>`_,
|
||||
`#2039 <https://github.com/fmtlib/fmt/issues/2039>`_,
|
||||
`#2047 <https://github.com/fmtlib/fmt/issues/2047>`_,
|
||||
`#2053 <https://github.com/fmtlib/fmt/pull/2053>`_,
|
||||
`#2059 <https://github.com/fmtlib/fmt/issues/2059>`_,
|
||||
`#2065 <https://github.com/fmtlib/fmt/pull/2065>`_,
|
||||
`#2067 <https://github.com/fmtlib/fmt/pull/2067>`_,
|
||||
`#2068 <https://github.com/fmtlib/fmt/pull/2068>`_,
|
||||
`#2073 <https://github.com/fmtlib/fmt/pull/2073>`_,
|
||||
`#2103 <https://github.com/fmtlib/fmt/issues/2103>`_
|
||||
`#2105 <https://github.com/fmtlib/fmt/issues/2105>`_
|
||||
`#2106 <https://github.com/fmtlib/fmt/pull/2106>`_,
|
||||
`#2107 <https://github.com/fmtlib/fmt/pull/2107>`_,
|
||||
`#2116 <https://github.com/fmtlib/fmt/issues/2116>`_
|
||||
`#2117 <https://github.com/fmtlib/fmt/pull/2117>`_,
|
||||
`#2118 <https://github.com/fmtlib/fmt/issues/2118>`_
|
||||
`#2119 <https://github.com/fmtlib/fmt/pull/2119>`_,
|
||||
`#2127 <https://github.com/fmtlib/fmt/issues/2127>`_,
|
||||
`#2128 <https://github.com/fmtlib/fmt/pull/2128>`_,
|
||||
`#2140 <https://github.com/fmtlib/fmt/issues/2140>`_,
|
||||
`#2142 <https://github.com/fmtlib/fmt/issues/2142>`_,
|
||||
`#2143 <https://github.com/fmtlib/fmt/pull/2143>`_,
|
||||
`#2144 <https://github.com/fmtlib/fmt/pull/2144>`_,
|
||||
`#2147 <https://github.com/fmtlib/fmt/issues/2147>`_,
|
||||
`#2148 <https://github.com/fmtlib/fmt/issues/2148>`_,
|
||||
`#2149 <https://github.com/fmtlib/fmt/issues/2149>`_,
|
||||
`#2152 <https://github.com/fmtlib/fmt/pull/2152>`_,
|
||||
`#2160 <https://github.com/fmtlib/fmt/pull/2160>`_,
|
||||
`#2170 <https://github.com/fmtlib/fmt/issues/2170>`_,
|
||||
`#2175 <https://github.com/fmtlib/fmt/issues/2175>`_,
|
||||
`#2176 <https://github.com/fmtlib/fmt/issues/2176>`_,
|
||||
`#2177 <https://github.com/fmtlib/fmt/pull/2177>`_,
|
||||
`#2178 <https://github.com/fmtlib/fmt/issues/2178>`_,
|
||||
`#2179 <https://github.com/fmtlib/fmt/pull/2179>`_,
|
||||
`#2180 <https://github.com/fmtlib/fmt/issues/2180>`_,
|
||||
`#2181 <https://github.com/fmtlib/fmt/issues/2181>`_,
|
||||
`#2183 <https://github.com/fmtlib/fmt/pull/2183>`_,
|
||||
`#2184 <https://github.com/fmtlib/fmt/issues/2184>`_,
|
||||
`#2185 <https://github.com/fmtlib/fmt/issues/2185>`_,
|
||||
`#2186 <https://github.com/fmtlib/fmt/pull/2186>`_,
|
||||
`#2187 <https://github.com/fmtlib/fmt/pull/2187>`_,
|
||||
`#2190 <https://github.com/fmtlib/fmt/pull/2190>`_,
|
||||
`#2192 <https://github.com/fmtlib/fmt/pull/2192>`_,
|
||||
`#2194 <https://github.com/fmtlib/fmt/pull/2194>`_,
|
||||
`#2205 <https://github.com/fmtlib/fmt/pull/2205>`_,
|
||||
`#2210 <https://github.com/fmtlib/fmt/issues/2210>`_,
|
||||
`#2211 <https://github.com/fmtlib/fmt/pull/2211>`_,
|
||||
`#2215 <https://github.com/fmtlib/fmt/pull/2215>`_,
|
||||
`#2216 <https://github.com/fmtlib/fmt/pull/2216>`_,
|
||||
`#2218 <https://github.com/fmtlib/fmt/pull/2218>`_,
|
||||
`#2220 <https://github.com/fmtlib/fmt/pull/2220>`_,
|
||||
`#2228 <https://github.com/fmtlib/fmt/issues/2228>`_,
|
||||
`#2229 <https://github.com/fmtlib/fmt/pull/2229>`_,
|
||||
`#2230 <https://github.com/fmtlib/fmt/pull/2230>`_,
|
||||
`#2233 <https://github.com/fmtlib/fmt/issues/2233>`_,
|
||||
`#2239 <https://github.com/fmtlib/fmt/pull/2239>`_,
|
||||
`#2248 <https://github.com/fmtlib/fmt/issues/2248>`_,
|
||||
`#2252 <https://github.com/fmtlib/fmt/issues/2252>`_,
|
||||
`#2253 <https://github.com/fmtlib/fmt/pull/2253>`_,
|
||||
`#2255 <https://github.com/fmtlib/fmt/pull/2255>`_,
|
||||
`#2261 <https://github.com/fmtlib/fmt/issues/2261>`_,
|
||||
`#2278 <https://github.com/fmtlib/fmt/issues/2278>`_,
|
||||
`#2284 <https://github.com/fmtlib/fmt/issues/2284>`_,
|
||||
`#2287 <https://github.com/fmtlib/fmt/pull/2287>`_,
|
||||
`#2289 <https://github.com/fmtlib/fmt/pull/2289>`_,
|
||||
`#2290 <https://github.com/fmtlib/fmt/pull/2290>`_,
|
||||
`#2293 <https://github.com/fmtlib/fmt/pull/2293>`_,
|
||||
`#2295 <https://github.com/fmtlib/fmt/issues/2295>`_,
|
||||
`#2296 <https://github.com/fmtlib/fmt/pull/2296>`_,
|
||||
`#2297 <https://github.com/fmtlib/fmt/pull/2297>`_,
|
||||
`#2311 <https://github.com/fmtlib/fmt/issues/2311>`_,
|
||||
`#2313 <https://github.com/fmtlib/fmt/pull/2313>`_,
|
||||
`#2315 <https://github.com/fmtlib/fmt/pull/2315>`_,
|
||||
`#2320 <https://github.com/fmtlib/fmt/issues/2320>`_,
|
||||
`#2321 <https://github.com/fmtlib/fmt/pull/2321>`_,
|
||||
`#2323 <https://github.com/fmtlib/fmt/pull/2323>`_,
|
||||
`#2328 <https://github.com/fmtlib/fmt/issues/2328>`_,
|
||||
`#2329 <https://github.com/fmtlib/fmt/pull/2329>`_,
|
||||
`#2333 <https://github.com/fmtlib/fmt/pull/2333>`_,
|
||||
`#2338 <https://github.com/fmtlib/fmt/pull/2338>`_,
|
||||
`#2341 <https://github.com/fmtlib/fmt/pull/2341>`_).
|
||||
Thanks `@darklukee <https://github.com/darklukee>`_,
|
||||
`@fagg (Ashton Fagg) <https://github.com/fagg>`_,
|
||||
`@killerbot242 (Lieven de Cock) <https://github.com/killerbot242>`_,
|
||||
`@jgopel (Jonathan Gopel) <https://github.com/jgopel>`_,
|
||||
`@yeswalrus (Walter Gray) <https://github.com/yeswalrus>`_,
|
||||
`@Finkman <https://github.com/Finkman>`_,
|
||||
`@HazardyKnusperkeks (Björn Schäpers) <https://github.com/HazardyKnusperkeks>`_,
|
||||
`@dkavolis (Daumantas Kavolis) <https://github.com/dkavolis>`_
|
||||
`@concatime (Issam Maghni) <https://github.com/concatime>`_,
|
||||
`@chronoxor (Ivan Shynkarenka) <https://github.com/chronoxor>`_,
|
||||
`@summivox (Yin Zhong) <https://github.com/summivox>`_,
|
||||
`@yNeo <https://github.com/yNeo>`_,
|
||||
`@Apache-HB (Elliot) <https://github.com/Apache-HB>`_,
|
||||
`@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_,
|
||||
`@toojays (John Steele Scott) <https://github.com/toojays>`_,
|
||||
`@Brainy0207 <https://github.com/Brainy0207>`_,
|
||||
`@vadz (VZ) <https://github.com/vadz>`_,
|
||||
`@imsherlock (Ryan Sherlock) <https://github.com/imsherlock>`_,
|
||||
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_,
|
||||
`@white238 (Chris White) <https://github.com/white238>`_,
|
||||
`@yafshar (Yaser Afshar) <https://github.com/yafshar>`_,
|
||||
`@BillyDonahue (Billy Donahue) <https://github.com/BillyDonahue>`_,
|
||||
`@jstaahl <https://github.com/jstaahl>`_,
|
||||
`@denchat <https://github.com/denchat>`_,
|
||||
`@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_,
|
||||
`@ilyakurdyukov (Ilya Kurdyukov) <https://github.com/ilyakurdyukov>`_,
|
||||
`@ilmai <https://github.com/ilmai>`_,
|
||||
`@JessyDL (Jessy De Lannoit) <https://github.com/JessyDL>`_,
|
||||
`@sergiud (Sergiu Deitsch) <https://github.com/sergiud>`_,
|
||||
`@mwinterb <https://github.com/mwinterb>`_,
|
||||
`@sven-herrmann <https://github.com/sven-herrmann>`_,
|
||||
`@jmelas (John Melas) <https://github.com/jmelas>`_,
|
||||
`@twoixter (Jose Miguel Pérez) <https://github.com/twoixter>`_,
|
||||
`@crbrz <https://github.com/crbrz>`_,
|
||||
`@upsj (Tobias Ribizel) <https://github.com/upsj>`_.
|
||||
|
||||
* Improved documentation
|
||||
(`#1986 <https://github.com/fmtlib/fmt/issues/1986>`_,
|
||||
`#2051 <https://github.com/fmtlib/fmt/pull/2051>`_,
|
||||
`#2057 <https://github.com/fmtlib/fmt/issues/2057>`_,
|
||||
`#2081 <https://github.com/fmtlib/fmt/pull/2081>`_,
|
||||
`#2084 <https://github.com/fmtlib/fmt/issues/2084>`_,
|
||||
`#2312 <https://github.com/fmtlib/fmt/pull/2312>`_).
|
||||
Thanks `@imba-tjd (谭九鼎) <https://github.com/imba-tjd>`_,
|
||||
`@0x416c69 (AlιAѕѕaѕѕιN) <https://github.com/0x416c69>`_,
|
||||
`@mordante <https://github.com/mordante>`_.
|
||||
|
||||
* Continuous integration and test improvements
|
||||
(`#1969 <https://github.com/fmtlib/fmt/issues/1969>`_,
|
||||
`#1991 <https://github.com/fmtlib/fmt/pull/1991>`_,
|
||||
`#2020 <https://github.com/fmtlib/fmt/pull/2020>`_,
|
||||
`#2110 <https://github.com/fmtlib/fmt/pull/2110>`_,
|
||||
`#2114 <https://github.com/fmtlib/fmt/pull/2114>`_,
|
||||
`#2196 <https://github.com/fmtlib/fmt/issues/2196>`_,
|
||||
`#2217 <https://github.com/fmtlib/fmt/pull/2217>`_,
|
||||
`#2247 <https://github.com/fmtlib/fmt/pull/2247>`_,
|
||||
`#2256 <https://github.com/fmtlib/fmt/pull/2256>`_,
|
||||
`#2336 <https://github.com/fmtlib/fmt/pull/2336>`_,
|
||||
`#2346 <https://github.com/fmtlib/fmt/pull/2346>`_).
|
||||
Thanks `@jgopel (Jonathan Gopel) <https://github.com/jgopel>`_,
|
||||
`@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_ and
|
||||
`@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_.
|
||||
|
||||
7.1.3 - 2020-11-24
|
||||
------------------
|
||||
|
||||
@ -269,8 +965,8 @@
|
||||
|
||||
Thanks `@Naios (Denis Blank) <https://github.com/Naios>`_.
|
||||
|
||||
* Made the ``#`` specifier emit trailing zeros in addition to the decimal point
|
||||
(`#1797 <https://github.com/fmtlib/fmt/issues/1797>`_). For example
|
||||
* Made the ``'#'`` specifier emit trailing zeros in addition to the decimal
|
||||
point (`#1797 <https://github.com/fmtlib/fmt/issues/1797>`_). For example
|
||||
(`godbolt <https://godbolt.org/z/bhdcW9>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
10
deps/fmt/README.rst
vendored
10
deps/fmt/README.rst
vendored
@ -26,9 +26,9 @@
|
||||
**{fmt}** is an open-source formatting library providing a fast and safe
|
||||
alternative to C stdio and C++ iostreams.
|
||||
|
||||
If you like this project, please consider donating to BY_Help,
|
||||
an initiative to help victims of political repressions in Belarus:
|
||||
https://www.facebook.com/donate/199475051809330/.
|
||||
If you like this project, please consider donating to the BYSOL
|
||||
Foundation that helps victims of political repressions in Belarus:
|
||||
https://bysol.org/en/bs/general/.
|
||||
|
||||
`Documentation <https://fmt.dev>`__
|
||||
|
||||
@ -341,6 +341,10 @@ Projects using this library
|
||||
|
||||
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
|
||||
|
||||
* `Grand Mountain Adventure
|
||||
<https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_:
|
||||
A beautiful open-world ski & snowboarding game
|
||||
|
||||
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||
Player vs Player Gaming Network with tweaks
|
||||
|
||||
|
||||
271
deps/fmt/include/fmt/chrono.h
vendored
271
deps/fmt/include/fmt/chrono.h
vendored
@ -15,7 +15,6 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "format.h"
|
||||
#include "locale.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
@ -283,10 +282,80 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
#define FMT_NOMACRO
|
||||
|
||||
namespace detail {
|
||||
template <typename T = void> struct null {};
|
||||
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
|
||||
inline null<> localtime_s(...) { return null<>(); }
|
||||
inline null<> gmtime_r(...) { return null<>(); }
|
||||
inline null<> gmtime_s(...) { return null<>(); }
|
||||
|
||||
inline auto do_write(const std::tm& time, const std::locale& loc, char format,
|
||||
char modifier) -> std::string {
|
||||
auto&& os = std::ostringstream();
|
||||
os.imbue(loc);
|
||||
using iterator = std::ostreambuf_iterator<char>;
|
||||
const auto& facet = std::use_facet<std::time_put<char, iterator>>(loc);
|
||||
auto end = facet.put(os, os, ' ', &time, format, modifier);
|
||||
if (end.failed()) FMT_THROW(format_error("failed to format time"));
|
||||
auto str = os.str();
|
||||
if (!detail::is_utf8() || loc == std::locale::classic()) return str;
|
||||
// char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
|
||||
// gcc-4.
|
||||
#if FMT_MSC_VER != 0 || \
|
||||
(defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
|
||||
// The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
|
||||
// and newer.
|
||||
using code_unit = wchar_t;
|
||||
#else
|
||||
using code_unit = char32_t;
|
||||
#endif
|
||||
auto& f = std::use_facet<std::codecvt<code_unit, char, std::mbstate_t>>(loc);
|
||||
auto mb = std::mbstate_t();
|
||||
const char* from_next = nullptr;
|
||||
code_unit* to_next = nullptr;
|
||||
constexpr size_t buf_size = 32;
|
||||
code_unit buf[buf_size] = {};
|
||||
auto result = f.in(mb, str.data(), str.data() + str.size(), from_next, buf,
|
||||
buf + buf_size, to_next);
|
||||
if (result != std::codecvt_base::ok)
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
str.clear();
|
||||
for (code_unit* p = buf; p != to_next; ++p) {
|
||||
uint32_t c = static_cast<uint32_t>(*p);
|
||||
if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) {
|
||||
// surrogate pair
|
||||
++p;
|
||||
if (p == to_next || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
}
|
||||
c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
|
||||
}
|
||||
if (c < 0x80) {
|
||||
str.push_back(static_cast<char>(c));
|
||||
} else if (c < 0x800) {
|
||||
str.push_back(static_cast<char>(0xc0 | (c >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
|
||||
str.push_back(static_cast<char>(0xe0 | (c >> 12)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else if (c >= 0x10000 && c <= 0x10ffff) {
|
||||
str.push_back(static_cast<char>(0xf0 | (c >> 18)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else {
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename OutputIt>
|
||||
auto write(OutputIt out, const std::tm& time, const std::locale& loc,
|
||||
char format, char modifier = 0) -> OutputIt {
|
||||
auto str = do_write(time, loc, format, modifier);
|
||||
return std::copy(str.begin(), str.end(), out);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
@ -408,14 +477,37 @@ FMT_END_DETAIL_NAMESPACE
|
||||
template <typename Char, typename Duration>
|
||||
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char> : formatter<std::tm, Char> {
|
||||
FMT_CONSTEXPR formatter() {
|
||||
this->specs = {default_specs, sizeof(default_specs) / sizeof(Char)};
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it == ':') ++it;
|
||||
auto end = it;
|
||||
while (end != ctx.end() && *end != '}') ++end;
|
||||
if (end != it) this->specs = {it, detail::to_unsigned(end - it)};
|
||||
return end;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(std::chrono::time_point<std::chrono::system_clock> val,
|
||||
FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
std::tm time = localtime(val);
|
||||
return formatter<std::tm, Char>::format(time, ctx);
|
||||
}
|
||||
|
||||
static constexpr Char default_specs[] = {'%', 'Y', '-', '%', 'm', '-',
|
||||
'%', 'd', ' ', '%', 'H', ':',
|
||||
'%', 'M', ':', '%', 'S'};
|
||||
};
|
||||
|
||||
template <typename Char, typename Duration>
|
||||
constexpr Char
|
||||
formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char>::default_specs[];
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
@ -458,66 +550,28 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
template <typename Period> FMT_CONSTEXPR const char* get_units() {
|
||||
template <typename Period> FMT_CONSTEXPR inline const char* get_units() {
|
||||
if (std::is_same<Period, std::atto>::value) return "as";
|
||||
if (std::is_same<Period, std::femto>::value) return "fs";
|
||||
if (std::is_same<Period, std::pico>::value) return "ps";
|
||||
if (std::is_same<Period, std::nano>::value) return "ns";
|
||||
if (std::is_same<Period, std::micro>::value) return "µs";
|
||||
if (std::is_same<Period, std::milli>::value) return "ms";
|
||||
if (std::is_same<Period, std::centi>::value) return "cs";
|
||||
if (std::is_same<Period, std::deci>::value) return "ds";
|
||||
if (std::is_same<Period, std::ratio<1>>::value) return "s";
|
||||
if (std::is_same<Period, std::deca>::value) return "das";
|
||||
if (std::is_same<Period, std::hecto>::value) return "hs";
|
||||
if (std::is_same<Period, std::kilo>::value) return "ks";
|
||||
if (std::is_same<Period, std::mega>::value) return "Ms";
|
||||
if (std::is_same<Period, std::giga>::value) return "Gs";
|
||||
if (std::is_same<Period, std::tera>::value) return "Ts";
|
||||
if (std::is_same<Period, std::peta>::value) return "Ps";
|
||||
if (std::is_same<Period, std::exa>::value) return "Es";
|
||||
if (std::is_same<Period, std::ratio<60>>::value) return "m";
|
||||
if (std::is_same<Period, std::ratio<3600>>::value) return "h";
|
||||
return nullptr;
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::atto>() {
|
||||
return "as";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::femto>() {
|
||||
return "fs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::pico>() {
|
||||
return "ps";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::nano>() {
|
||||
return "ns";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::micro>() {
|
||||
return "µs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::milli>() {
|
||||
return "ms";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::centi>() {
|
||||
return "cs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::deci>() {
|
||||
return "ds";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<1>>() {
|
||||
return "s";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::deca>() {
|
||||
return "das";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::hecto>() {
|
||||
return "hs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::kilo>() {
|
||||
return "ks";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::mega>() {
|
||||
return "Ms";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::giga>() {
|
||||
return "Gs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::tera>() {
|
||||
return "Ts";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::peta>() {
|
||||
return "Ps";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::exa>() {
|
||||
return "Es";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<60>>() {
|
||||
return "m";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<3600>>() {
|
||||
return "h";
|
||||
}
|
||||
|
||||
enum class numeric_system {
|
||||
standard,
|
||||
@ -683,34 +737,50 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct chrono_format_checker {
|
||||
FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); }
|
||||
template <typename Derived> struct null_chrono_spec_handler {
|
||||
FMT_CONSTEXPR void unsupported() {
|
||||
static_cast<Derived*>(this)->unsupported();
|
||||
}
|
||||
FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_full_weekday() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_us_date() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_iso_date() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_12_hour_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_24_hour_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_iso_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_am_pm() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_duration_value() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_duration_unit() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_utc_offset() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_tz_name() { unsupported(); }
|
||||
};
|
||||
|
||||
struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
|
||||
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_abbr_month() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_month() { report_no_date(); }
|
||||
FMT_CONSTEXPR void on_24_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_12_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_minute(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_second(numeric_system) {}
|
||||
FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_us_date() { report_no_date(); }
|
||||
FMT_NORETURN void on_iso_date() { report_no_date(); }
|
||||
FMT_CONSTEXPR void on_12_hour_time() {}
|
||||
FMT_CONSTEXPR void on_24_hour_time() {}
|
||||
FMT_CONSTEXPR void on_iso_time() {}
|
||||
FMT_CONSTEXPR void on_am_pm() {}
|
||||
FMT_CONSTEXPR void on_duration_value() {}
|
||||
FMT_CONSTEXPR void on_duration_unit() {}
|
||||
FMT_NORETURN void on_utc_offset() { report_no_date(); }
|
||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||
};
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
@ -957,14 +1027,9 @@ struct chrono_formatter {
|
||||
|
||||
void format_localized(const tm& time, char format, char modifier = 0) {
|
||||
if (isnan(val)) return write_nan();
|
||||
auto locale = localized ? context.locale().template get<std::locale>()
|
||||
: std::locale::classic();
|
||||
auto& facet = std::use_facet<std::time_put<char_type>>(locale);
|
||||
std::basic_ostringstream<char_type> os;
|
||||
os.imbue(locale);
|
||||
facet.put(os, os, ' ', &time, format, modifier);
|
||||
auto str = os.str();
|
||||
std::copy(str.begin(), str.end(), out);
|
||||
const auto& loc = localized ? context.locale().template get<std::locale>()
|
||||
: std::locale::classic();
|
||||
out = detail::write(out, time, loc, format, modifier);
|
||||
}
|
||||
|
||||
void on_text(const char_type* begin, const char_type* end) {
|
||||
@ -1080,6 +1145,46 @@ struct chrono_formatter {
|
||||
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
|
||||
using weekday = std::chrono::weekday;
|
||||
#else
|
||||
// A fallback version of weekday.
|
||||
class weekday {
|
||||
private:
|
||||
unsigned char value;
|
||||
|
||||
public:
|
||||
weekday() = default;
|
||||
explicit constexpr weekday(unsigned wd) noexcept
|
||||
: value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
|
||||
constexpr unsigned c_encoding() const noexcept { return value; }
|
||||
};
|
||||
#endif
|
||||
|
||||
// A rudimentary weekday formatter.
|
||||
template <> struct formatter<weekday> {
|
||||
private:
|
||||
bool localized = false;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
if (begin != end && *begin == 'L') {
|
||||
++begin;
|
||||
localized = true;
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
auto format(weekday wd, format_context& ctx) -> decltype(ctx.out()) {
|
||||
auto time = std::tm();
|
||||
time.tm_wday = static_cast<int>(wd.c_encoding());
|
||||
const auto& loc = localized ? ctx.locale().template get<std::locale>()
|
||||
: std::locale::classic();
|
||||
return detail::write(ctx.out(), time, loc, 'a');
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Rep, typename Period, typename Char>
|
||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
private:
|
||||
@ -1190,7 +1295,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
ctx, out, d);
|
||||
f.precision = precision_copy;
|
||||
f.localized = localized;
|
||||
parse_chrono_format(begin, end, f);
|
||||
detail::parse_chrono_format(begin, end, f);
|
||||
}
|
||||
return detail::write(
|
||||
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
|
||||
|
||||
8
deps/fmt/include/fmt/color.h
vendored
8
deps/fmt/include/fmt/color.h
vendored
@ -507,7 +507,7 @@ void vformat_to(buffer<Char>& buf, const text_style& ts,
|
||||
auto background = detail::make_background_color<Char>(ts.get_background());
|
||||
buf.append(background.begin(), background.end());
|
||||
}
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
detail::vformat_to(buf, format_str, args, {});
|
||||
if (has_style) detail::reset_color<Char>(buf);
|
||||
}
|
||||
|
||||
@ -582,8 +582,8 @@ inline std::basic_string<Char> vformat(
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
return vformat(ts, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
return fmt::vformat(ts, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -594,7 +594,7 @@ template <typename OutputIt, typename Char,
|
||||
OutputIt vformat_to(
|
||||
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, ts, format_str, args);
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
51
deps/fmt/include/fmt/compile.h
vendored
51
deps/fmt/include/fmt/compile.h
vendored
@ -157,13 +157,15 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
||||
\endrst
|
||||
*/
|
||||
#ifdef __cpp_if_constexpr
|
||||
# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
|
||||
# define FMT_COMPILE(s) \
|
||||
FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)
|
||||
#else
|
||||
# define FMT_COMPILE(s) FMT_STRING(s)
|
||||
#endif
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
template <typename Char, size_t N, fixed_string<Char, N> Str>
|
||||
template <typename Char, size_t N,
|
||||
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||
struct udl_compiled_string : compiled_string {
|
||||
using char_type = Char;
|
||||
constexpr operator basic_string_view<char_type>() const {
|
||||
@ -382,24 +384,22 @@ constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
||||
}
|
||||
|
||||
template <typename Char> struct arg_id_handler {
|
||||
constexpr void on_error(const char* message) { throw format_error(message); }
|
||||
arg_ref<Char> arg_id;
|
||||
|
||||
constexpr int on_arg_id() {
|
||||
constexpr int operator()() {
|
||||
FMT_ASSERT(false, "handler cannot be used with automatic indexing");
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr int on_arg_id(int id) {
|
||||
constexpr int operator()(int id) {
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
constexpr int operator()(basic_string_view<Char> id) {
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr int on_arg_id(basic_string_view<Char> id) {
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_ref<Char> arg_id;
|
||||
constexpr void on_error(const char* message) { throw format_error(message); }
|
||||
};
|
||||
|
||||
template <typename Char> struct parse_arg_id_result {
|
||||
@ -410,8 +410,7 @@ template <typename Char> struct parse_arg_id_result {
|
||||
template <int ID, typename Char>
|
||||
constexpr auto parse_arg_id(const Char* begin, const Char* end) {
|
||||
auto handler = arg_id_handler<Char>{arg_ref<Char>{}};
|
||||
auto adapter = id_adapter<arg_id_handler<Char>, Char>{handler, 0};
|
||||
auto arg_id_end = parse_arg_id(begin, end, adapter);
|
||||
auto arg_id_end = parse_arg_id(begin, end, handler);
|
||||
return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};
|
||||
}
|
||||
|
||||
@ -428,7 +427,7 @@ template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,
|
||||
typename S>
|
||||
constexpr auto parse_replacement_field_then_tail(S format_str) {
|
||||
using char_type = typename S::char_type;
|
||||
constexpr basic_string_view<char_type> str = format_str;
|
||||
constexpr auto str = basic_string_view<char_type>(format_str);
|
||||
constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();
|
||||
if constexpr (c == '}') {
|
||||
return parse_tail<Args, END_POS + 1, NEXT_ID>(
|
||||
@ -449,7 +448,7 @@ constexpr auto parse_replacement_field_then_tail(S format_str) {
|
||||
template <typename Args, size_t POS, int ID, typename S>
|
||||
constexpr auto compile_format_string(S format_str) {
|
||||
using char_type = typename S::char_type;
|
||||
constexpr basic_string_view<char_type> str = format_str;
|
||||
constexpr auto str = basic_string_view<char_type>(format_str);
|
||||
if constexpr (str[POS] == '{') {
|
||||
if constexpr (POS + 1 == str.size())
|
||||
throw format_error("unmatched '{' in format string");
|
||||
@ -518,7 +517,7 @@ constexpr auto compile_format_string(S format_str) {
|
||||
template <typename... Args, typename S,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
constexpr auto compile(S format_str) {
|
||||
constexpr basic_string_view<typename S::char_type> str = format_str;
|
||||
constexpr auto str = basic_string_view<typename S::char_type>(format_str);
|
||||
if constexpr (str.size() == 0) {
|
||||
return detail::make_text(str, 0, 0);
|
||||
} else {
|
||||
@ -557,7 +556,7 @@ template <typename S, typename... Args,
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
Args&&... args) {
|
||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||
constexpr basic_string_view<typename S::char_type> str = S();
|
||||
constexpr auto str = basic_string_view<typename S::char_type>(S());
|
||||
if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {
|
||||
const auto& first = detail::first(args...);
|
||||
if constexpr (detail::is_named_arg<
|
||||
@ -608,9 +607,23 @@ size_t formatted_size(const S& format_str, const Args&... args) {
|
||||
return format_to(detail::counting_iterator(), format_str, args...).count();
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
void print(std::FILE* f, const S& format_str, const Args&... args) {
|
||||
memory_buffer buffer;
|
||||
format_to(std::back_inserter(buffer), format_str, args...);
|
||||
detail::print(f, {buffer.data(), buffer.size()});
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
void print(const S& format_str, const Args&... args) {
|
||||
print(stdout, format_str, args...);
|
||||
}
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
inline namespace literals {
|
||||
template <detail::fixed_string Str>
|
||||
template <detail_exported::fixed_string Str>
|
||||
constexpr detail::udl_compiled_string<
|
||||
remove_cvref_t<decltype(Str.data[0])>,
|
||||
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>
|
||||
|
||||
1510
deps/fmt/include/fmt/core.h
vendored
1510
deps/fmt/include/fmt/core.h
vendored
File diff suppressed because it is too large
Load Diff
78
deps/fmt/include/fmt/format-inl.h
vendored
78
deps/fmt/include/fmt/format-inl.h
vendored
@ -10,6 +10,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno> // errno
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
@ -102,23 +103,21 @@ template <typename Locale> Locale locale_ref::get() const {
|
||||
return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
|
||||
}
|
||||
|
||||
template <typename Char> FMT_FUNC std::string grouping_impl(locale_ref loc) {
|
||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()).grouping();
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref loc) {
|
||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
||||
.thousands_sep();
|
||||
template <typename Char>
|
||||
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
|
||||
auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
|
||||
auto grouping = facet.grouping();
|
||||
auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
|
||||
return {std::move(grouping), thousands_sep};
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
|
||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
||||
.decimal_point();
|
||||
}
|
||||
#else
|
||||
template <typename Char> FMT_FUNC std::string grouping_impl(locale_ref) {
|
||||
return "\03";
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref) {
|
||||
return FMT_STATIC_THOUSANDS_SEPARATOR;
|
||||
template <typename Char>
|
||||
FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
|
||||
return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
|
||||
return '.';
|
||||
@ -147,8 +146,7 @@ template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
|
||||
}
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
template <typename T>
|
||||
constexpr const typename basic_data<T>::digit_pair basic_data<T>::digits[];
|
||||
template <typename T> constexpr const char basic_data<T>::digits[][2];
|
||||
template <typename T> constexpr const char basic_data<T>::hex_digits[];
|
||||
template <typename T> constexpr const char basic_data<T>::signs[];
|
||||
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
|
||||
@ -565,7 +563,6 @@ class bigint {
|
||||
(*this)[bigit_index] = static_cast<bigit>(sum);
|
||||
sum >>= bits<bigit>::value;
|
||||
}
|
||||
--num_result_bigits;
|
||||
remove_leading_zeros();
|
||||
exp_ *= 2;
|
||||
}
|
||||
@ -640,8 +637,8 @@ inline uint64_t power_of_10_64(int exp) {
|
||||
// error: the size of the region (lower, upper) outside of which numbers
|
||||
// definitely do not round to value (Delta in Grisu3).
|
||||
template <typename Handler>
|
||||
FMT_ALWAYS_INLINE digits::result grisu_gen_digits(fp value, uint64_t error,
|
||||
int& exp, Handler& handler) {
|
||||
FMT_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, int& exp,
|
||||
Handler& handler) {
|
||||
const fp one(1ULL << -value.e, value.e);
|
||||
// The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
|
||||
// zero because it contains a product of two 64-bit numbers with MSB set (due
|
||||
@ -1919,7 +1916,7 @@ bool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent,
|
||||
}
|
||||
|
||||
// Remove trailing zeros from n and return the number of zeros removed (float)
|
||||
FMT_ALWAYS_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {
|
||||
FMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {
|
||||
#ifdef FMT_BUILTIN_CTZ
|
||||
int t = FMT_BUILTIN_CTZ(n);
|
||||
#else
|
||||
@ -1947,7 +1944,7 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {
|
||||
}
|
||||
|
||||
// Removes trailing zeros and returns the number of zeros removed (double)
|
||||
FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
|
||||
FMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
|
||||
#ifdef FMT_BUILTIN_CTZLL
|
||||
int t = FMT_BUILTIN_CTZLL(n);
|
||||
#else
|
||||
@ -2033,8 +2030,7 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
|
||||
|
||||
// The main algorithm for shorter interval case
|
||||
template <class T>
|
||||
FMT_ALWAYS_INLINE decimal_fp<T> shorter_interval_case(int exponent)
|
||||
FMT_NOEXCEPT {
|
||||
FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT {
|
||||
decimal_fp<T> ret_value;
|
||||
// Compute k and beta
|
||||
const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
|
||||
@ -2500,19 +2496,6 @@ int snprintf_float(T value, int precision, float_specs specs,
|
||||
return exp - fraction_size;
|
||||
}
|
||||
}
|
||||
|
||||
struct stringifier {
|
||||
template <typename T> FMT_INLINE std::string operator()(T value) const {
|
||||
return to_string(value);
|
||||
}
|
||||
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||
memory_buffer buf;
|
||||
format_parse_context parse_ctx({});
|
||||
format_context format_ctx(buffer_appender<char>(buf), {}, {});
|
||||
h.format(parse_ctx, format_ctx);
|
||||
return to_string(buf);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <> struct formatter<detail::bigint> {
|
||||
@ -2575,14 +2558,11 @@ FMT_FUNC void report_system_error(int error_code,
|
||||
report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
FMT_FUNC std::string detail::vformat(string_view format_str, format_args args) {
|
||||
if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
|
||||
auto arg = args.get(0);
|
||||
if (!arg) error_handler().on_error("argument not found");
|
||||
return visit_format_arg(stringifier(), arg);
|
||||
}
|
||||
memory_buffer buffer;
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
FMT_FUNC std::string vformat(string_view fmt, format_args args) {
|
||||
// Don't optimize the "{}" case to keep the binary size small and because it
|
||||
// can be better optimized in fmt::format anyway.
|
||||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, fmt, args);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@ -2594,13 +2574,12 @@ extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( //
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
||||
memory_buffer buffer;
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
namespace detail {
|
||||
FMT_FUNC void print(std::FILE* f, string_view text) {
|
||||
#ifdef _WIN32
|
||||
auto fd = _fileno(f);
|
||||
if (_isatty(fd)) {
|
||||
detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
|
||||
detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));
|
||||
auto written = detail::dword();
|
||||
if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
|
||||
u16.c_str(), static_cast<uint32_t>(u16.size()),
|
||||
@ -2611,7 +2590,14 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
||||
// redirected to NUL.
|
||||
}
|
||||
#endif
|
||||
detail::fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
||||
detail::fwrite_fully(text.data(), 1, text.size(), f);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
||||
memory_buffer buffer;
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
detail::print(f, {buffer.data(), buffer.size()});
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
2051
deps/fmt/include/fmt/format.h
vendored
2051
deps/fmt/include/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
69
deps/fmt/include/fmt/locale.h
vendored
69
deps/fmt/include/fmt/locale.h
vendored
@ -1,67 +1,2 @@
|
||||
// Formatting library for C++ - std::locale support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_LOCALE_H_
|
||||
#define FMT_LOCALE_H_
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
template <typename Char>
|
||||
std::basic_string<Char> vformat(
|
||||
const std::locale& loc, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> vformat(
|
||||
const std::locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
return detail::vformat(loc, to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
return detail::vformat(loc, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
template <typename S, typename OutputIt, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
inline OutputIt vformat_to(
|
||||
OutputIt out, const std::locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to(OutputIt out, const std::locale& loc, const S& format_str,
|
||||
Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT_END
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_LOCALE_H_
|
||||
#include "xchar.h"
|
||||
#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead
|
||||
|
||||
39
deps/fmt/include/fmt/os.h
vendored
39
deps/fmt/include/fmt/os.h
vendored
@ -70,6 +70,7 @@
|
||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -128,7 +129,8 @@ template <typename Char> struct formatter<std::error_code, Char> {
|
||||
FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
out = detail::write<Char>(out, to_string_view(ec.category().name()));
|
||||
out = detail::write_bytes(out, ec.category().name(),
|
||||
basic_format_specs<Char>());
|
||||
out = detail::write<Char>(out, Char(':'));
|
||||
out = detail::write<Char>(out, ec.value());
|
||||
return out;
|
||||
@ -138,7 +140,7 @@ template <typename Char> struct formatter<std::error_code, Char> {
|
||||
#ifdef _WIN32
|
||||
FMT_API const std::error_category& system_category() FMT_NOEXCEPT;
|
||||
|
||||
namespace detail {
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
// A converter from UTF-16 to UTF-8.
|
||||
// It is only provided for Windows since other systems support UTF-8 natively.
|
||||
class utf16_to_utf8 {
|
||||
@ -147,7 +149,7 @@ class utf16_to_utf8 {
|
||||
|
||||
public:
|
||||
utf16_to_utf8() {}
|
||||
FMT_API explicit utf16_to_utf8(wstring_view s);
|
||||
FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s);
|
||||
operator string_view() const { return string_view(&buffer_[0], size()); }
|
||||
size_t size() const { return buffer_.size() - 1; }
|
||||
const char* c_str() const { return &buffer_[0]; }
|
||||
@ -156,12 +158,12 @@ class utf16_to_utf8 {
|
||||
// Performs conversion returning a system error code instead of
|
||||
// throwing exception on conversion error. This method may still throw
|
||||
// in case of memory allocation error.
|
||||
FMT_API int convert(wstring_view s);
|
||||
FMT_API int convert(basic_string_view<wchar_t> s);
|
||||
};
|
||||
|
||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||
const char* message) FMT_NOEXCEPT;
|
||||
} // namespace detail
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
||||
format_args args);
|
||||
@ -197,7 +199,7 @@ FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
||||
template <typename... Args>
|
||||
std::system_error windows_error(int error_code, string_view message,
|
||||
const Args&... args) {
|
||||
return vwindows_error(error_code, message, make_format_args(args...));
|
||||
return vwindows_error(error_code, message, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
// Reports a Windows error without throwing an exception.
|
||||
@ -268,7 +270,7 @@ class buffered_file {
|
||||
|
||||
template <typename... Args>
|
||||
inline void print(string_view format_str, const Args&... args) {
|
||||
vprint(format_str, make_format_args(args...));
|
||||
vprint(format_str, fmt::make_format_args(args...));
|
||||
}
|
||||
};
|
||||
|
||||
@ -360,7 +362,7 @@ class file {
|
||||
// Returns the memory page size.
|
||||
long getpagesize();
|
||||
|
||||
namespace detail {
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
struct buffer_size {
|
||||
buffer_size() = default;
|
||||
@ -389,12 +391,13 @@ struct ostream_params {
|
||||
this->buffer_size = bs.value;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
static constexpr detail::buffer_size buffer_size;
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
constexpr detail::buffer_size buffer_size;
|
||||
|
||||
/** A fast output stream which is not thread-safe. */
|
||||
class ostream final : private detail::buffer<char> {
|
||||
class FMT_API ostream final : private detail::buffer<char> {
|
||||
private:
|
||||
file file_;
|
||||
|
||||
@ -404,7 +407,7 @@ class ostream final : private detail::buffer<char> {
|
||||
clear();
|
||||
}
|
||||
|
||||
FMT_API void grow(size_t) override final;
|
||||
void grow(size_t) override;
|
||||
|
||||
ostream(cstring_view path, const detail::ostream_params& params)
|
||||
: file_(path, params.oflag) {
|
||||
@ -432,13 +435,12 @@ class ostream final : private detail::buffer<char> {
|
||||
}
|
||||
|
||||
/**
|
||||
Formats ``args`` according to specifications in ``format_str`` and writes
|
||||
the output to the file.
|
||||
Formats ``args`` according to specifications in ``fmt`` and writes the
|
||||
output to the file.
|
||||
*/
|
||||
template <typename S, typename... Args>
|
||||
void print(const S& format_str, Args&&... args) {
|
||||
format_to(detail::buffer_appender<char>(*this), format_str,
|
||||
std::forward<Args>(args)...);
|
||||
template <typename... T> void print(format_string<T...> fmt, T&&... args) {
|
||||
vformat_to(detail::buffer_appender<char>(*this), fmt,
|
||||
fmt::make_format_args(args...));
|
||||
}
|
||||
};
|
||||
|
||||
@ -507,6 +509,7 @@ class locale {
|
||||
};
|
||||
using Locale FMT_DEPRECATED_ALIAS = locale;
|
||||
#endif // FMT_LOCALE
|
||||
FMT_MODULE_EXPORT_END
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_OS_H_
|
||||
|
||||
389
deps/fmt/include/fmt/printf.h
vendored
389
deps/fmt/include/fmt/printf.h
vendored
@ -15,7 +15,49 @@
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
template <typename T> struct printf_formatter { printf_formatter() = delete; };
|
||||
|
||||
template <typename Char>
|
||||
class basic_printf_parse_context : public basic_format_parse_context<Char> {
|
||||
using basic_format_parse_context<Char>::basic_format_parse_context;
|
||||
};
|
||||
|
||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
private:
|
||||
OutputIt out_;
|
||||
basic_format_args<basic_printf_context> args_;
|
||||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using format_arg = basic_format_arg<basic_printf_context>;
|
||||
using parse_context_type = basic_printf_parse_context<Char>;
|
||||
template <typename T> using formatter_type = printf_formatter<T>;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``printf_context`` object. References to the arguments are
|
||||
stored in the context object so make sure they have appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_printf_context(OutputIt out,
|
||||
basic_format_args<basic_printf_context> args)
|
||||
: out_(out), args_(args) {}
|
||||
|
||||
OutputIt out() { return out_; }
|
||||
void advance_to(OutputIt it) { out_ = it; }
|
||||
|
||||
detail::locale_ref locale() { return {}; }
|
||||
|
||||
format_arg arg(int id) const { return args_.get(id); }
|
||||
|
||||
FMT_CONSTEXPR void on_error(const char* message) {
|
||||
detail::error_handler().on_error(message);
|
||||
}
|
||||
};
|
||||
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
@ -179,65 +221,34 @@ template <typename Char> class printf_width_handler {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Context>
|
||||
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
Context(buffer_appender<Char>(buf), format, args).format();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// For printing into memory_buffer.
|
||||
template <typename Char, typename Context>
|
||||
FMT_DEPRECATED void printf(detail::buffer<Char>& buf,
|
||||
basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
return detail::vprintf(buf, format, args);
|
||||
}
|
||||
using detail::vprintf;
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
template <typename Char>
|
||||
class basic_printf_parse_context : public basic_format_parse_context<Char> {
|
||||
using basic_format_parse_context<Char>::basic_format_parse_context;
|
||||
};
|
||||
template <typename OutputIt, typename Char> class basic_printf_context;
|
||||
|
||||
FMT_MODULE_EXPORT_END
|
||||
|
||||
/**
|
||||
\rst
|
||||
The ``printf`` argument formatter.
|
||||
\endrst
|
||||
*/
|
||||
// The ``printf`` argument formatter.
|
||||
template <typename OutputIt, typename Char>
|
||||
class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
||||
class printf_arg_formatter : public arg_formatter<Char> {
|
||||
private:
|
||||
using base = detail::arg_formatter_base<OutputIt, Char>;
|
||||
using base = arg_formatter<Char>;
|
||||
using context_type = basic_printf_context<OutputIt, Char>;
|
||||
using format_specs = typename base::format_specs;
|
||||
using format_specs = basic_format_specs<Char>;
|
||||
|
||||
context_type& context_;
|
||||
|
||||
OutputIt write_null_pointer(bool is_string = false) {
|
||||
auto s = this->specs();
|
||||
auto s = this->specs;
|
||||
s.type = 0;
|
||||
return detail::write(this->out(),
|
||||
string_view(is_string ? "(null)" : "(nil)"), s);
|
||||
return write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
|
||||
}
|
||||
|
||||
public:
|
||||
printf_arg_formatter(OutputIt iter, format_specs& specs, context_type& ctx)
|
||||
: base(iter, specs, detail::locale_ref()), context_(ctx) {}
|
||||
printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx)
|
||||
: base{iter, s, locale_ref()}, context_(ctx) {}
|
||||
|
||||
OutputIt operator()(monostate value) { return base::operator()(value); }
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)>
|
||||
template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
|
||||
OutputIt operator()(T value) {
|
||||
// MSVC2013 fails to compile separate overloads for bool and Char so use
|
||||
// std::is_same instead.
|
||||
if (std::is_same<T, Char>::value) {
|
||||
format_specs fmt_specs = this->specs();
|
||||
format_specs fmt_specs = this->specs;
|
||||
if (fmt_specs.type && fmt_specs.type != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_specs.sign = sign::none;
|
||||
@ -247,8 +258,7 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
||||
// ignored for non-numeric types
|
||||
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
|
||||
fmt_specs.align = align::right;
|
||||
return detail::write<Char>(this->out(), static_cast<Char>(value),
|
||||
fmt_specs);
|
||||
return write<Char>(this->out, static_cast<Char>(value), fmt_specs);
|
||||
}
|
||||
return base::operator()(value);
|
||||
}
|
||||
@ -261,13 +271,13 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
||||
/** Formats a null-terminated C string. */
|
||||
OutputIt operator()(const char* value) {
|
||||
if (value) return base::operator()(value);
|
||||
return write_null_pointer(this->specs().type != 'p');
|
||||
return write_null_pointer(this->specs.type != 'p');
|
||||
}
|
||||
|
||||
/** Formats a null-terminated wide C string. */
|
||||
OutputIt operator()(const wchar_t* value) {
|
||||
if (value) return base::operator()(value);
|
||||
return write_null_pointer(this->specs().type != 'p');
|
||||
return write_null_pointer(this->specs.type != 'p');
|
||||
}
|
||||
|
||||
OutputIt operator()(basic_string_view<Char> value) {
|
||||
@ -281,87 +291,16 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
OutputIt operator()(typename basic_format_arg<context_type>::handle handle) {
|
||||
handle.format(context_.parse_context(), context_);
|
||||
return this->out();
|
||||
auto parse_ctx =
|
||||
basic_printf_parse_context<Char>(basic_string_view<Char>());
|
||||
handle.format(parse_ctx, context_);
|
||||
return this->out;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct printf_formatter {
|
||||
printf_formatter() = delete;
|
||||
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const T&, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
return ctx.out();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
This template formats data and writes the output through an output iterator.
|
||||
*/
|
||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
using char_type = Char;
|
||||
using iterator = OutputIt;
|
||||
using format_arg = basic_format_arg<basic_printf_context>;
|
||||
using parse_context_type = basic_printf_parse_context<Char>;
|
||||
template <typename T> using formatter_type = printf_formatter<T>;
|
||||
|
||||
private:
|
||||
using format_specs = basic_format_specs<char_type>;
|
||||
|
||||
OutputIt out_;
|
||||
basic_format_args<basic_printf_context> args_;
|
||||
parse_context_type parse_ctx_;
|
||||
|
||||
static void parse_flags(format_specs& specs, const Char*& it,
|
||||
const Char* end);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is -1, the next
|
||||
// argument.
|
||||
format_arg get_arg(int arg_index = -1);
|
||||
|
||||
// Parses argument index, flags and width and returns the argument index.
|
||||
int parse_header(const Char*& it, const Char* end, format_specs& specs);
|
||||
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``printf_context`` object. References to the arguments are
|
||||
stored in the context object so make sure they have appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||
basic_format_args<basic_printf_context> args)
|
||||
: out_(out), args_(args), parse_ctx_(format_str) {}
|
||||
|
||||
OutputIt out() { return out_; }
|
||||
void advance_to(OutputIt it) { out_ = it; }
|
||||
|
||||
detail::locale_ref locale() { return {}; }
|
||||
|
||||
format_arg arg(int id) const { return args_.get(id); }
|
||||
|
||||
parse_context_type& parse_context() { return parse_ctx_; }
|
||||
|
||||
FMT_CONSTEXPR void on_error(const char* message) {
|
||||
parse_ctx_.on_error(message);
|
||||
}
|
||||
|
||||
/** Formats stored arguments and writes the output to the range. */
|
||||
template <typename ArgFormatter = printf_arg_formatter<OutputIt, Char>>
|
||||
OutputIt format();
|
||||
};
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
||||
const Char*& it,
|
||||
const Char* end) {
|
||||
template <typename Char>
|
||||
void parse_flags(basic_format_specs<Char>& specs, const Char*& it,
|
||||
const Char* end) {
|
||||
for (; it != end; ++it) {
|
||||
switch (*it) {
|
||||
case '-':
|
||||
@ -387,35 +326,24 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
typename basic_printf_context<OutputIt, Char>::format_arg
|
||||
basic_printf_context<OutputIt, Char>::get_arg(int arg_index) {
|
||||
if (arg_index < 0)
|
||||
arg_index = parse_ctx_.next_arg_id();
|
||||
else
|
||||
parse_ctx_.check_arg_id(--arg_index);
|
||||
return detail::get_arg(*this, arg_index);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it,
|
||||
const Char* end,
|
||||
format_specs& specs) {
|
||||
template <typename Char, typename GetArg>
|
||||
int parse_header(const Char*& it, const Char* end,
|
||||
basic_format_specs<Char>& specs, GetArg get_arg) {
|
||||
int arg_index = -1;
|
||||
char_type c = *it;
|
||||
Char c = *it;
|
||||
if (c >= '0' && c <= '9') {
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
// preceded with '0' flag(s).
|
||||
detail::error_handler eh;
|
||||
int value = parse_nonnegative_int(it, end, eh);
|
||||
int value = parse_nonnegative_int(it, end, -1);
|
||||
if (it != end && *it == '$') { // value is an argument index
|
||||
++it;
|
||||
arg_index = value;
|
||||
arg_index = value != -1 ? value : max_value<int>();
|
||||
} else {
|
||||
if (c == '0') specs.fill[0] = '0';
|
||||
if (value != 0) {
|
||||
// Nonzero value means that we parsed width and don't need to
|
||||
// parse it or flags again, so return now.
|
||||
if (value == -1) FMT_THROW(format_error("number is too big"));
|
||||
specs.width = value;
|
||||
return arg_index;
|
||||
}
|
||||
@ -425,30 +353,44 @@ int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it,
|
||||
// Parse width.
|
||||
if (it != end) {
|
||||
if (*it >= '0' && *it <= '9') {
|
||||
detail::error_handler eh;
|
||||
specs.width = parse_nonnegative_int(it, end, eh);
|
||||
specs.width = parse_nonnegative_int(it, end, -1);
|
||||
if (specs.width == -1) FMT_THROW(format_error("number is too big"));
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
specs.width = static_cast<int>(visit_format_arg(
|
||||
detail::printf_width_handler<char_type>(specs), get_arg()));
|
||||
detail::printf_width_handler<Char>(specs), get_arg(-1)));
|
||||
}
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
template <typename ArgFormatter>
|
||||
OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
auto out = this->out();
|
||||
const Char* start = parse_ctx_.begin();
|
||||
const Char* end = parse_ctx_.end();
|
||||
template <typename Char, typename Context>
|
||||
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
using OutputIt = buffer_appender<Char>;
|
||||
auto out = OutputIt(buf);
|
||||
auto context = basic_printf_context<OutputIt, Char>(out, args);
|
||||
auto parse_ctx = basic_printf_parse_context<Char>(format);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is -1, the next
|
||||
// argument.
|
||||
auto get_arg = [&](int arg_index) {
|
||||
if (arg_index < 0)
|
||||
arg_index = parse_ctx.next_arg_id();
|
||||
else
|
||||
parse_ctx.check_arg_id(--arg_index);
|
||||
return detail::get_arg(context, arg_index);
|
||||
};
|
||||
|
||||
const Char* start = parse_ctx.begin();
|
||||
const Char* end = parse_ctx.end();
|
||||
auto it = start;
|
||||
while (it != end) {
|
||||
if (!detail::find<false, Char>(it, end, '%', it)) {
|
||||
it = end; // detail::find leaves it == nullptr if it doesn't find '%'
|
||||
break;
|
||||
}
|
||||
char_type c = *it++;
|
||||
Char c = *it++;
|
||||
if (it != end && *it == c) {
|
||||
out = detail::write(
|
||||
out, basic_string_view<Char>(start, detail::to_unsigned(it - start)));
|
||||
@ -458,30 +400,29 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
out = detail::write(out, basic_string_view<Char>(
|
||||
start, detail::to_unsigned(it - 1 - start)));
|
||||
|
||||
format_specs specs;
|
||||
basic_format_specs<Char> specs;
|
||||
specs.align = align::right;
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
int arg_index = parse_header(it, end, specs);
|
||||
if (arg_index == 0) on_error("argument not found");
|
||||
int arg_index = parse_header(it, end, specs, get_arg);
|
||||
if (arg_index == 0) parse_ctx.on_error("argument not found");
|
||||
|
||||
// Parse precision.
|
||||
if (it != end && *it == '.') {
|
||||
++it;
|
||||
c = it != end ? *it : 0;
|
||||
if ('0' <= c && c <= '9') {
|
||||
detail::error_handler eh;
|
||||
specs.precision = parse_nonnegative_int(it, end, eh);
|
||||
specs.precision = parse_nonnegative_int(it, end, 0);
|
||||
} else if (c == '*') {
|
||||
++it;
|
||||
specs.precision = static_cast<int>(
|
||||
visit_format_arg(detail::printf_precision_handler(), get_arg()));
|
||||
visit_format_arg(detail::printf_precision_handler(), get_arg(-1)));
|
||||
} else {
|
||||
specs.precision = 0;
|
||||
}
|
||||
}
|
||||
|
||||
format_arg arg = get_arg(arg_index);
|
||||
auto arg = get_arg(arg_index);
|
||||
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
||||
// specified, the '0' flag is ignored
|
||||
if (specs.precision >= 0 && arg.is_integral())
|
||||
@ -491,9 +432,10 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
|
||||
auto str_end = str + specs.precision;
|
||||
auto nul = std::find(str, str_end, Char());
|
||||
arg = detail::make_arg<basic_printf_context>(basic_string_view<Char>(
|
||||
str,
|
||||
detail::to_unsigned(nul != str_end ? nul - str : specs.precision)));
|
||||
arg = detail::make_arg<basic_printf_context<OutputIt, Char>>(
|
||||
basic_string_view<Char>(
|
||||
str, detail::to_unsigned(nul != str_end ? nul - str
|
||||
: specs.precision)));
|
||||
}
|
||||
if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))
|
||||
specs.alt = false;
|
||||
@ -507,7 +449,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
|
||||
// Parse length and convert the argument to the required type.
|
||||
c = it != end ? *it++ : 0;
|
||||
char_type t = it != end ? *it : 0;
|
||||
Char t = it != end ? *it : 0;
|
||||
using detail::convert_arg;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
@ -557,8 +499,9 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
specs.type = 'd';
|
||||
break;
|
||||
case 'c':
|
||||
visit_format_arg(detail::char_converter<basic_printf_context>(arg),
|
||||
arg);
|
||||
visit_format_arg(
|
||||
detail::char_converter<basic_printf_context<OutputIt, Char>>(arg),
|
||||
arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -566,13 +509,12 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
start = it;
|
||||
|
||||
// Format argument.
|
||||
out = visit_format_arg(ArgFormatter(out, specs, *this), arg);
|
||||
out = visit_format_arg(
|
||||
detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg);
|
||||
}
|
||||
return detail::write(
|
||||
out, basic_string_view<Char>(start, detail::to_unsigned(it - start)));
|
||||
detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
template <typename Char>
|
||||
using basic_printf_context_t =
|
||||
@ -590,9 +532,9 @@ using wprintf_args = basic_format_args<wprintf_context>;
|
||||
arguments and can be implicitly converted to `~fmt::printf_args`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline format_arg_store<printf_context, Args...> make_printf_args(
|
||||
const Args&... args) {
|
||||
template <typename... T>
|
||||
inline auto make_printf_args(const T&... args)
|
||||
-> format_arg_store<printf_context, T...> {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
@ -602,18 +544,19 @@ inline format_arg_store<printf_context, Args...> make_printf_args(
|
||||
arguments and can be implicitly converted to `~fmt::wprintf_args`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
|
||||
const Args&... args) {
|
||||
template <typename... T>
|
||||
inline auto make_wprintf_args(const T&... args)
|
||||
-> format_arg_store<wprintf_context, T...> {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> vsprintf(
|
||||
const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||
inline auto vsprintf(
|
||||
const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> std::basic_string<Char> {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(format), args);
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@ -626,19 +569,20 @@ inline std::basic_string<Char> vsprintf(
|
||||
std::string message = fmt::sprintf("The answer is %d", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
template <typename S, typename... T,
|
||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
||||
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vsprintf(to_string_view(format), make_format_args<context>(args...));
|
||||
return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vfprintf(
|
||||
std::FILE* f, const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||
inline auto vfprintf(
|
||||
std::FILE* f, const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(format), args);
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
size_t size = buffer.size();
|
||||
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
||||
? -1
|
||||
@ -654,19 +598,19 @@ inline int vfprintf(
|
||||
fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||
inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
||||
template <typename S, typename... T, typename Char = char_t<S>>
|
||||
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(f, to_string_view(format),
|
||||
make_format_args<context>(args...));
|
||||
return vfprintf(f, to_string_view(fmt),
|
||||
fmt::make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vprintf(
|
||||
const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||
return vfprintf(stdout, to_string_view(format), args);
|
||||
inline auto vprintf(
|
||||
const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
return vfprintf(stdout, to_string_view(fmt), args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -678,51 +622,28 @@ inline int vprintf(
|
||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
inline int printf(const S& format_str, const Args&... args) {
|
||||
using context = basic_printf_context_t<char_t<S>>;
|
||||
return vprintf(to_string_view(format_str),
|
||||
make_format_args<context>(args...));
|
||||
template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
inline auto printf(const S& fmt, const T&... args) -> int {
|
||||
return vprintf(
|
||||
to_string_view(fmt),
|
||||
fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vfprintf(
|
||||
std::basic_ostream<Char>& os, const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||
FMT_DEPRECATED auto vfprintf(
|
||||
std::basic_ostream<Char>& os, const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(format), args);
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
os.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
|
||||
return static_cast<int>(buffer.size());
|
||||
}
|
||||
|
||||
/** Formats arguments and writes the output to the range. */
|
||||
template <typename ArgFormatter, typename Char,
|
||||
typename Context =
|
||||
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
||||
typename ArgFormatter::iterator vprintf(
|
||||
detail::buffer<Char>& out, basic_string_view<Char> format_str,
|
||||
basic_format_args<type_identity_t<Context>> args) {
|
||||
typename ArgFormatter::iterator iter(out);
|
||||
Context(iter, format_str, args).template format<ArgFormatter>();
|
||||
return iter;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline int fprintf(std::basic_ostream<Char>& os, const S& format_str,
|
||||
const Args&... args) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(os, to_string_view(format_str),
|
||||
make_format_args<context>(args...));
|
||||
template <typename S, typename... T, typename Char = char_t<S>>
|
||||
FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt,
|
||||
const T&... args) -> int {
|
||||
return vfprintf(os, to_string_view(fmt),
|
||||
fmt::make_format_args<basic_printf_context_t<Char>>(args...));
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT_END
|
||||
|
||||
81
deps/fmt/include/fmt/ranges.h
vendored
81
deps/fmt/include/fmt/ranges.h
vendored
@ -19,15 +19,7 @@
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
template <typename Char> struct formatting_base {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Enable = void>
|
||||
struct formatting_range : formatting_base<Char> {
|
||||
template <typename Char, typename Enable = void> struct formatting_range {
|
||||
#ifdef FMT_DEPRECATED_BRACED_RANGES
|
||||
Char prefix = '{';
|
||||
Char postfix = '}';
|
||||
@ -35,12 +27,21 @@ struct formatting_range : formatting_base<Char> {
|
||||
Char prefix = '[';
|
||||
Char postfix = ']';
|
||||
#endif
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Enable = void>
|
||||
struct formatting_tuple : formatting_base<Char> {
|
||||
template <typename Char, typename Enable = void> struct formatting_tuple {
|
||||
Char prefix = '(';
|
||||
Char postfix = ')';
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -296,8 +297,8 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
||||
}
|
||||
formatting_tuple<Char>& formatting;
|
||||
size_t& i;
|
||||
typename std::add_lvalue_reference<decltype(
|
||||
std::declval<FormatContext>().out())>::type out;
|
||||
typename std::add_lvalue_reference<
|
||||
decltype(std::declval<FormatContext>().out())>::type out;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -362,50 +363,53 @@ struct formatter<
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename... T> struct tuple_arg_join : detail::view {
|
||||
template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
||||
const std::tuple<T...>& tuple;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s)
|
||||
tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
|
||||
: tuple(t), sep{s} {}
|
||||
};
|
||||
|
||||
template <typename Char, typename... T>
|
||||
struct formatter<tuple_arg_join<Char, T...>, Char> {
|
||||
using tuple_arg_join = tuple_join_view<Char, T...>;
|
||||
|
||||
template <typename Char, typename... T>
|
||||
struct formatter<tuple_join_view<Char, T...>, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
typename FormatContext::iterator format(
|
||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
|
||||
auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx) ->
|
||||
typename FormatContext::iterator {
|
||||
return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{});
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename FormatContext, size_t... N>
|
||||
typename FormatContext::iterator format(
|
||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
||||
detail::index_sequence<N...>) {
|
||||
return format_args(value, ctx, std::get<N>(value.tuple)...);
|
||||
auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
|
||||
detail::index_sequence<N...>) ->
|
||||
typename FormatContext::iterator {
|
||||
using std::get;
|
||||
return format_args(value, ctx, get<N>(value.tuple)...);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
typename FormatContext::iterator format_args(
|
||||
const tuple_arg_join<Char, T...>&, FormatContext& ctx) {
|
||||
auto format_args(const tuple_join_view<Char, T...>&, FormatContext& ctx) ->
|
||||
typename FormatContext::iterator {
|
||||
// NOTE: for compilers that support C++17, this empty function instantiation
|
||||
// can be replaced with a constexpr branch in the variadic overload.
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
template <typename FormatContext, typename Arg, typename... Args>
|
||||
typename FormatContext::iterator format_args(
|
||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
||||
const Arg& arg, const Args&... args) {
|
||||
auto format_args(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
|
||||
const Arg& arg, const Args&... args) ->
|
||||
typename FormatContext::iterator {
|
||||
using base = formatter<typename std::decay<Arg>::type, Char>;
|
||||
auto out = ctx.out();
|
||||
out = base{}.format(arg, ctx);
|
||||
auto out = base().format(arg, ctx);
|
||||
if (sizeof...(Args) > 0) {
|
||||
out = std::copy(value.sep.begin(), value.sep.end(), out);
|
||||
ctx.advance_to(out);
|
||||
@ -429,14 +433,15 @@ FMT_MODULE_EXPORT_BEGIN
|
||||
\endrst
|
||||
*/
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
|
||||
string_view sep) {
|
||||
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
|
||||
-> tuple_join_view<char, T...> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
||||
wstring_view sep) {
|
||||
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
|
||||
basic_string_view<wchar_t> sep)
|
||||
-> tuple_join_view<wchar_t, T...> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
@ -452,14 +457,8 @@ FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
||||
\endrst
|
||||
*/
|
||||
template <typename T>
|
||||
arg_join<const T*, const T*, char> join(std::initializer_list<T> list,
|
||||
string_view sep) {
|
||||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
|
||||
wstring_view sep) {
|
||||
auto join(std::initializer_list<T> list, string_view sep)
|
||||
-> join_view<const T*, const T*> {
|
||||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
|
||||
236
deps/fmt/include/fmt/xchar.h
vendored
Normal file
236
deps/fmt/include/fmt/xchar.h
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
// Formatting library for C++ - optional wchar_t and exotic character support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_WCHAR_H_
|
||||
#define FMT_WCHAR_H_
|
||||
|
||||
#include <cwchar>
|
||||
#include <tuple>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
||||
using wformat_context = buffer_context<wchar_t>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
using wmemory_buffer = basic_memory_buffer<wchar_t>;
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
// Workaround broken conversion on older gcc.
|
||||
template <typename... Args> using wformat_string = wstring_view;
|
||||
#else
|
||||
template <typename... Args>
|
||||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
|
||||
#endif
|
||||
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
template <> struct is_char<detail::char8_type> : std::true_type {};
|
||||
template <> struct is_char<char16_t> : std::true_type {};
|
||||
template <> struct is_char<char32_t> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
constexpr format_arg_store<wformat_context, Args...> make_wformat_args(
|
||||
const Args&... args) {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
inline namespace literals {
|
||||
constexpr auto operator"" _format(const wchar_t* s, size_t n)
|
||||
-> detail::udl_formatter<wchar_t> {
|
||||
return {{s, n}};
|
||||
}
|
||||
|
||||
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
|
||||
return {s};
|
||||
}
|
||||
#endif
|
||||
} // namespace literals
|
||||
|
||||
template <typename It, typename Sentinel>
|
||||
auto join(It begin, Sentinel end, wstring_view sep)
|
||||
-> join_view<It, Sentinel, wchar_t> {
|
||||
return {begin, end, sep};
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
auto join(Range&& range, wstring_view sep)
|
||||
-> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
|
||||
wchar_t> {
|
||||
return join(std::begin(range), std::end(range), sep);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto join(std::initializer_list<T> list, wstring_view sep)
|
||||
-> join_view<const T*, const T*, wchar_t> {
|
||||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
auto vformat(basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> std::basic_string<Char> {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
// Pass char_t as a default template parameter instead of using
|
||||
// std::basic_string<char_t<S>> to reduce the symbol size.
|
||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat(to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat(
|
||||
const Locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(loc, to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format(const Locale& loc, const S& format_str, Args&&... args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(loc, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
auto vformat_to(OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, to_string_view(format_str), args);
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
|
||||
return vformat_to(out, to_string_view(fmt), vargs);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args, typename Char, size_t SIZE,
|
||||
typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
|
||||
const S& format_str, Args&&... args) ->
|
||||
typename buffer_context<Char>::iterator {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
detail::vformat_to(buf, to_string_view(format_str), vargs, {});
|
||||
return detail::buffer_appender<Char>(buf);
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename OutputIt, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to(
|
||||
OutputIt out, const Locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
template <
|
||||
typename OutputIt, typename Locale, typename S, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
bool enable = detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value>
|
||||
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
|
||||
Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to_n(
|
||||
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
|
||||
n);
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
|
||||
const Args&... args) -> format_to_n_result<OutputIt> {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
|
||||
return vformat_to_n(out, n, to_string_view(fmt), vargs);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||
inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
|
||||
detail::counting_buffer<Char> buf;
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
|
||||
detail::vformat_to(buf, to_string_view(fmt), vargs);
|
||||
return buf.count();
|
||||
}
|
||||
|
||||
inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
|
||||
wmemory_buffer buffer;
|
||||
detail::vformat_to(buffer, fmt, args);
|
||||
buffer.push_back(L'\0');
|
||||
if (std::fputws(buffer.data(), f) == -1)
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||
}
|
||||
|
||||
inline void vprint(wstring_view fmt, wformat_args args) {
|
||||
vprint(stdout, fmt, args);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
|
||||
return vprint(f, wstring_view(fmt), make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
|
||||
return vprint(wstring_view(fmt), make_wformat_args(args...));
|
||||
}
|
||||
|
||||
/**
|
||||
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
||||
*/
|
||||
template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
|
||||
return format(FMT_STRING(L"{}"), value);
|
||||
}
|
||||
FMT_MODULE_EXPORT_END
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_WCHAR_H_
|
||||
20
deps/fmt/src/fmt.cc
vendored
20
deps/fmt/src/fmt.cc
vendored
@ -1,4 +1,8 @@
|
||||
module;
|
||||
#ifndef __cpp_modules
|
||||
# error Module not supported.
|
||||
#endif
|
||||
|
||||
// put all implementation-provided headers into the global module fragment
|
||||
// to prevent attachment to this module
|
||||
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
|
||||
@ -8,8 +12,10 @@ module;
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
@ -21,9 +27,6 @@ module;
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cwchar>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
@ -79,16 +82,19 @@ export module fmt;
|
||||
|
||||
// all library-provided declarations and definitions
|
||||
// must be in the module purview to be exported
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/args.h"
|
||||
#include "fmt/chrono.h"
|
||||
#include "fmt/color.h"
|
||||
#include "fmt/compile.h"
|
||||
#include "fmt/locale.h"
|
||||
#include "fmt/chrono.h"
|
||||
#include "fmt/printf.h"
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/os.h"
|
||||
#include "fmt/printf.h"
|
||||
#include "fmt/xchar.h"
|
||||
|
||||
// gcc doesn't yet implement private module fragments
|
||||
#if !FMT_GCC_VERSION
|
||||
module : private;
|
||||
#endif
|
||||
|
||||
#include "format.cc"
|
||||
#include "os.cc"
|
||||
|
||||
39
deps/fmt/src/format.cc
vendored
39
deps/fmt/src/format.cc
vendored
@ -28,31 +28,6 @@ template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x)
|
||||
FMT_NOEXCEPT;
|
||||
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x)
|
||||
FMT_NOEXCEPT;
|
||||
|
||||
// DEPRECATED! This function exists for ABI compatibility.
|
||||
template <typename Char>
|
||||
typename basic_format_context<std::back_insert_iterator<buffer<Char>>,
|
||||
Char>::iterator
|
||||
vformat_to(buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>>
|
||||
args) {
|
||||
using iterator = std::back_insert_iterator<buffer<char>>;
|
||||
using context = basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>;
|
||||
auto out = iterator(buf);
|
||||
format_handler<iterator, Char, context> h(out, format_str, args, {});
|
||||
parse_format_string<false>(format_str, h);
|
||||
return out;
|
||||
}
|
||||
template basic_format_context<std::back_insert_iterator<buffer<char>>,
|
||||
char>::iterator
|
||||
vformat_to(buffer<char>&, string_view,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<char>>>,
|
||||
type_identity_t<char>>>);
|
||||
} // namespace detail
|
||||
|
||||
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
||||
@ -66,12 +41,15 @@ template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template FMT_API std::string detail::grouping_impl<char>(locale_ref);
|
||||
template FMT_API char detail::thousands_sep_impl(locale_ref);
|
||||
template FMT_API auto detail::thousands_sep_impl(locale_ref)
|
||||
-> thousands_sep_result<char>;
|
||||
template FMT_API char detail::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
||||
|
||||
// DEPRECATED!
|
||||
// There is no correspondent extern template in format.h because of
|
||||
// incompatibility between clang and gcc (#2377).
|
||||
template FMT_API void detail::vformat_to(
|
||||
detail::buffer<char>&, string_view,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
||||
@ -88,10 +66,13 @@ template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template FMT_API std::string detail::grouping_impl<wchar_t>(locale_ref);
|
||||
template FMT_API wchar_t detail::thousands_sep_impl(locale_ref);
|
||||
template FMT_API auto detail::thousands_sep_impl(locale_ref)
|
||||
-> thousands_sep_result<wchar_t>;
|
||||
template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
|
||||
const wchar_t*);
|
||||
|
||||
template struct detail::basic_data<void>;
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
10
deps/fmt/src/os.cc
vendored
10
deps/fmt/src/os.cc
vendored
@ -72,14 +72,14 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef _WIN32
|
||||
detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
|
||||
detail::utf16_to_utf8::utf16_to_utf8(basic_string_view<wchar_t> s) {
|
||||
if (int error_code = convert(s)) {
|
||||
FMT_THROW(windows_error(error_code,
|
||||
"cannot convert string from UTF-16 to UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
int detail::utf16_to_utf8::convert(wstring_view s) {
|
||||
int detail::utf16_to_utf8::convert(basic_string_view<wchar_t> s) {
|
||||
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
||||
int s_size = static_cast<int>(s.size());
|
||||
if (s_size == 0) {
|
||||
@ -129,8 +129,8 @@ class system_message {
|
||||
}
|
||||
~system_message() { LocalFree(message_); }
|
||||
explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
|
||||
operator wstring_view() const FMT_NOEXCEPT {
|
||||
return wstring_view(message_, result_);
|
||||
operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
|
||||
return basic_string_view<wchar_t>(message_, result_);
|
||||
}
|
||||
};
|
||||
|
||||
@ -159,7 +159,7 @@ FMT_API const std::error_category& system_category() FMT_NOEXCEPT {
|
||||
std::system_error vwindows_error(int err_code, string_view format_str,
|
||||
format_args args) {
|
||||
auto ec = std::error_code(err_code, system_category());
|
||||
throw std::system_error(ec, vformat(format_str, args));
|
||||
return std::system_error(ec, vformat(format_str, args));
|
||||
}
|
||||
|
||||
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user