Merge pull request #10652 from shuffle2/fmt
update fmt and fix warnings that popped up with vs 17.2
This commit is contained in:
commit
fcb3f9e35b
|
@ -125,7 +125,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
|
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
|
||||||
|
|
||||||
include(cxx14)
|
include(cxx14)
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
include(JoinPaths)
|
include(JoinPaths)
|
||||||
|
|
||||||
list(FIND CMAKE_CXX_COMPILE_FEATURES "cxx_variadic_templates" index)
|
list(FIND CMAKE_CXX_COMPILE_FEATURES "cxx_variadic_templates" index)
|
||||||
|
@ -209,18 +208,6 @@ if (FMT_MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
|
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(strtod_l_headers stdlib.h)
|
|
||||||
if (APPLE)
|
|
||||||
set(strtod_l_headers ${strtod_l_headers} xlocale.h)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
|
||||||
if (WIN32)
|
|
||||||
check_symbol_exists(_strtod_l "${strtod_l_headers}" HAVE_STRTOD_L)
|
|
||||||
else ()
|
|
||||||
check_symbol_exists(strtod_l "${strtod_l_headers}" HAVE_STRTOD_L)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
function(add_headers VAR)
|
function(add_headers VAR)
|
||||||
set(headers ${${VAR}})
|
set(headers ${${VAR}})
|
||||||
foreach (header ${ARGN})
|
foreach (header ${ARGN})
|
||||||
|
@ -244,17 +231,6 @@ endif ()
|
||||||
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst ChangeLog.rst)
|
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst ChangeLog.rst)
|
||||||
add_library(fmt::fmt ALIAS fmt)
|
add_library(fmt::fmt ALIAS fmt)
|
||||||
|
|
||||||
if (HAVE_STRTOD_L)
|
|
||||||
target_compile_definitions(fmt PUBLIC FMT_LOCALE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (MINGW)
|
|
||||||
check_cxx_compiler_flag("-Wa,-mbig-obj" FMT_HAS_MBIG_OBJ)
|
|
||||||
if (${FMT_HAS_MBIG_OBJ})
|
|
||||||
target_compile_options(fmt PUBLIC "-Wa,-mbig-obj")
|
|
||||||
endif()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (FMT_WERROR)
|
if (FMT_WERROR)
|
||||||
target_compile_options(fmt PRIVATE ${WERROR_FLAG})
|
target_compile_options(fmt PRIVATE ${WERROR_FLAG})
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -275,6 +251,7 @@ set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.")
|
||||||
|
|
||||||
set_target_properties(fmt PROPERTIES
|
set_target_properties(fmt PROPERTIES
|
||||||
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}
|
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}
|
||||||
|
PUBLIC_HEADER "${FMT_HEADERS}"
|
||||||
DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}")
|
DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}")
|
||||||
|
|
||||||
# Set FMT_LIB_NAME for pkg-config fmt.pc. We cannot use the OUTPUT_NAME target
|
# Set FMT_LIB_NAME for pkg-config fmt.pc. We cannot use the OUTPUT_NAME target
|
||||||
|
@ -352,6 +329,8 @@ if (FMT_INSTALL)
|
||||||
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
|
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
|
||||||
LIBRARY DESTINATION ${FMT_LIB_DIR}
|
LIBRARY DESTINATION ${FMT_LIB_DIR}
|
||||||
ARCHIVE DESTINATION ${FMT_LIB_DIR}
|
ARCHIVE DESTINATION ${FMT_LIB_DIR}
|
||||||
|
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
|
||||||
|
FRAMEWORK DESTINATION "."
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
# Use a namespace because CMake provides better diagnostics for namespaced
|
# Use a namespace because CMake provides better diagnostics for namespaced
|
||||||
|
@ -368,7 +347,6 @@ if (FMT_INSTALL)
|
||||||
|
|
||||||
install(FILES $<TARGET_PDB_FILE:${INSTALL_TARGETS}>
|
install(FILES $<TARGET_PDB_FILE:${INSTALL_TARGETS}>
|
||||||
DESTINATION ${FMT_LIB_DIR} OPTIONAL)
|
DESTINATION ${FMT_LIB_DIR} OPTIONAL)
|
||||||
install(FILES ${FMT_HEADERS} DESTINATION "${FMT_INC_DIR}/fmt")
|
|
||||||
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
|
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
`#2696 <https://github.com/fmtlib/fmt/pull/2696>`_).
|
`#2696 <https://github.com/fmtlib/fmt/pull/2696>`_).
|
||||||
Thanks `@saraedum (Julian Rüth) <https://github.com/saraedum>`_.
|
Thanks `@saraedum (Julian Rüth) <https://github.com/saraedum>`_.
|
||||||
|
|
||||||
* Fixed chorno formatting on big endian systems
|
* Fixed chrono formatting on big endian systems
|
||||||
(`#2698 <https://github.com/fmtlib/fmt/issues/2698>`_,
|
(`#2698 <https://github.com/fmtlib/fmt/issues/2698>`_,
|
||||||
`#2699 <https://github.com/fmtlib/fmt/pull/2699>`_).
|
`#2699 <https://github.com/fmtlib/fmt/pull/2699>`_).
|
||||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_ and
|
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_ and
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{fmt}
|
.. image:: https://user-images.githubusercontent.com/
|
||||||
=====
|
576385/156254208-f5b743a9-88cf-439d-b0c0-923d53e8d551.png
|
||||||
|
:width: 25%
|
||||||
|
:alt: {fmt}
|
||||||
|
|
||||||
.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg
|
.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg
|
||||||
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux
|
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux
|
||||||
|
@ -26,9 +28,8 @@
|
||||||
**{fmt}** is an open-source formatting library providing a fast and safe
|
**{fmt}** is an open-source formatting library providing a fast and safe
|
||||||
alternative to C stdio and C++ iostreams.
|
alternative to C stdio and C++ iostreams.
|
||||||
|
|
||||||
If you like this project, please consider donating to the BYSOL
|
If you like this project, please consider donating to one of the funds that
|
||||||
Foundation that helps victims of political repressions in Belarus:
|
help victims of the war in Ukraine: https://www.stopputin.net/.
|
||||||
https://bysol.org/en/bs/general/.
|
|
||||||
|
|
||||||
`Documentation <https://fmt.dev>`__
|
`Documentation <https://fmt.dev>`__
|
||||||
|
|
||||||
|
@ -123,7 +124,7 @@ Output::
|
||||||
Default format: 42s 100ms
|
Default format: 42s 100ms
|
||||||
strftime-like format: 03:15:30
|
strftime-like format: 03:15:30
|
||||||
|
|
||||||
**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
|
**Print a container** (`run <https://godbolt.org/z/MxM1YqjE7>`_)
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
|
|
||||||
|
|
|
@ -95,10 +95,10 @@ class dynamic_format_arg_store
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using stored_type = conditional_t<detail::is_string<T>::value &&
|
using stored_type = conditional_t<
|
||||||
!has_formatter<T, Context>::value &&
|
std::is_convertible<T, std::basic_string<char_type>>::value &&
|
||||||
!detail::is_reference_wrapper<T>::value,
|
!detail::is_reference_wrapper<T>::value,
|
||||||
std::basic_string<char_type>, T>;
|
std::basic_string<char_type>, T>;
|
||||||
|
|
||||||
// Storage of basic_format_arg must be contiguous.
|
// Storage of basic_format_arg must be contiguous.
|
||||||
std::vector<basic_format_arg<Context>> data_;
|
std::vector<basic_format_arg<Context>> data_;
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cmath> // std::isfinite
|
||||||
|
#include <cstring> // std::memcpy
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
@ -321,14 +323,13 @@ constexpr const size_t codecvt_result<CodeUnit>::max_size;
|
||||||
template <typename CodeUnit>
|
template <typename CodeUnit>
|
||||||
void write_codecvt(codecvt_result<CodeUnit>& out, string_view in_buf,
|
void write_codecvt(codecvt_result<CodeUnit>& out, string_view in_buf,
|
||||||
const std::locale& loc) {
|
const std::locale& loc) {
|
||||||
using codecvt = std::codecvt<CodeUnit, char, std::mbstate_t>;
|
|
||||||
#if FMT_CLANG_VERSION
|
#if FMT_CLANG_VERSION
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wdeprecated"
|
# pragma clang diagnostic ignored "-Wdeprecated"
|
||||||
auto& f = std::use_facet<codecvt>(loc);
|
auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
#else
|
#else
|
||||||
auto& f = std::use_facet<codecvt>(loc);
|
auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
|
||||||
#endif
|
#endif
|
||||||
auto mb = std::mbstate_t();
|
auto mb = std::mbstate_t();
|
||||||
const char* from_next = nullptr;
|
const char* from_next = nullptr;
|
||||||
|
@ -562,10 +563,10 @@ inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
|
||||||
constexpr const size_t len = 8;
|
constexpr const size_t len = 8;
|
||||||
if (const_check(is_big_endian())) {
|
if (const_check(is_big_endian())) {
|
||||||
char tmp[len];
|
char tmp[len];
|
||||||
memcpy(tmp, &digits, len);
|
std::memcpy(tmp, &digits, len);
|
||||||
std::reverse_copy(tmp, tmp + len, buf);
|
std::reverse_copy(tmp, tmp + len, buf);
|
||||||
} else {
|
} else {
|
||||||
memcpy(buf, &digits, len);
|
std::memcpy(buf, &digits, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,7 +1215,7 @@ template <typename OutputIt, typename Char> class tm_writer {
|
||||||
char buf[10];
|
char buf[10];
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
if (year >= 0 && year < 10000) {
|
if (year >= 0 && year < 10000) {
|
||||||
copy2(buf, digits2(to_unsigned(year / 100)));
|
copy2(buf, digits2(static_cast<size_t>(year / 100)));
|
||||||
} else {
|
} else {
|
||||||
offset = 4;
|
offset = 4;
|
||||||
write_year_extended(year);
|
write_year_extended(year);
|
||||||
|
@ -1387,15 +1388,6 @@ struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
|
||||||
FMT_CONSTEXPR void on_duration_unit() {}
|
FMT_CONSTEXPR void on_duration_unit() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
inline bool isnan(T) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
|
||||||
inline bool isnan(T value) {
|
|
||||||
return std::isnan(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
inline bool isfinite(T) {
|
inline bool isfinite(T) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1470,14 +1462,23 @@ inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of fractional digits in the range [0, 18] according to the
|
// Counts the number of fractional digits in the range [0, 18] according to the
|
||||||
// C++20 spec. If more than 18 fractional digits are required then returns 6 for
|
// C++20 spec. If more than 18 fractional digits are required then returns 6 for
|
||||||
// microseconds precision.
|
// microseconds precision.
|
||||||
constexpr int count_fractional_digits(long long num, long long den, int n = 0) {
|
template <long long Num, long long Den, int N = 0,
|
||||||
return num % den == 0
|
bool Enabled =
|
||||||
? n
|
(N < 19) && (Num <= std::numeric_limits<long long>::max() / 10)>
|
||||||
: (n > 18 ? 6 : count_fractional_digits(num * 10, den, n + 1));
|
struct count_fractional_digits {
|
||||||
}
|
static constexpr int value =
|
||||||
|
Num % Den == 0 ? N : count_fractional_digits<Num * 10, Den, N + 1>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base case that doesn't instantiate any more templates
|
||||||
|
// in order to avoid overflow.
|
||||||
|
template <long long Num, long long Den, int N>
|
||||||
|
struct count_fractional_digits<Num, Den, N, false> {
|
||||||
|
static constexpr int value = (Num % Den == 0) ? N : 6;
|
||||||
|
};
|
||||||
|
|
||||||
constexpr long long pow10(std::uint32_t n) {
|
constexpr long long pow10(std::uint32_t n) {
|
||||||
return n == 0 ? 1 : 10 * pow10(n - 1);
|
return n == 0 ? 1 : 10 * pow10(n - 1);
|
||||||
|
@ -1663,9 +1664,11 @@ struct chrono_formatter {
|
||||||
out = format_decimal<char_type>(out, n, num_digits).end;
|
out = format_decimal<char_type>(out, n, num_digits).end;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration> void write_fractional_seconds(Duration d) {
|
template <typename Duration> void write_fractional_seconds(Duration d) {
|
||||||
|
FMT_ASSERT(!std::is_floating_point<typename Duration::rep>::value, "");
|
||||||
constexpr auto num_fractional_digits =
|
constexpr auto num_fractional_digits =
|
||||||
count_fractional_digits(Duration::period::num, Duration::period::den);
|
count_fractional_digits<Duration::period::num,
|
||||||
|
Duration::period::den>::value;
|
||||||
|
|
||||||
using subsecond_precision = std::chrono::duration<
|
using subsecond_precision = std::chrono::duration<
|
||||||
typename std::common_type<typename Duration::rep,
|
typename std::common_type<typename Duration::rep,
|
||||||
|
@ -1674,12 +1677,9 @@ struct chrono_formatter {
|
||||||
if (std::ratio_less<typename subsecond_precision::period,
|
if (std::ratio_less<typename subsecond_precision::period,
|
||||||
std::chrono::seconds::period>::value) {
|
std::chrono::seconds::period>::value) {
|
||||||
*out++ = '.';
|
*out++ = '.';
|
||||||
// Don't convert long double to integer seconds to avoid overflow.
|
auto fractional =
|
||||||
using sec = conditional_t<
|
detail::abs(d) - std::chrono::duration_cast<std::chrono::seconds>(d);
|
||||||
std::is_same<typename Duration::rep, long double>::value,
|
auto subseconds =
|
||||||
std::chrono::duration<long double>, std::chrono::seconds>;
|
|
||||||
auto fractional = detail::abs(d) - std::chrono::duration_cast<sec>(d);
|
|
||||||
const auto subseconds =
|
|
||||||
std::chrono::treat_as_floating_point<
|
std::chrono::treat_as_floating_point<
|
||||||
typename subsecond_precision::rep>::value
|
typename subsecond_precision::rep>::value
|
||||||
? fractional.count()
|
? fractional.count()
|
||||||
|
@ -1770,8 +1770,22 @@ struct chrono_formatter {
|
||||||
if (handle_nan_inf()) return;
|
if (handle_nan_inf()) return;
|
||||||
|
|
||||||
if (ns == numeric_system::standard) {
|
if (ns == numeric_system::standard) {
|
||||||
write(second(), 2);
|
if (std::is_floating_point<rep>::value) {
|
||||||
write_fractional_seconds(std::chrono::duration<rep, Period>{val});
|
constexpr auto num_fractional_digits =
|
||||||
|
count_fractional_digits<Period::num, Period::den>::value;
|
||||||
|
auto buf = memory_buffer();
|
||||||
|
format_to(std::back_inserter(buf), runtime("{:.{}f}"),
|
||||||
|
std::fmod(val * static_cast<rep>(Period::num) /
|
||||||
|
static_cast<rep>(Period::den),
|
||||||
|
60),
|
||||||
|
num_fractional_digits);
|
||||||
|
if (negative) *out++ = '-';
|
||||||
|
if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
|
||||||
|
out = std::copy(buf.begin(), buf.end(), out);
|
||||||
|
} else {
|
||||||
|
write(second(), 2);
|
||||||
|
write_fractional_seconds(std::chrono::duration<rep, Period>(val));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto time = tm();
|
auto time = tm();
|
||||||
|
|
|
@ -214,17 +214,16 @@ FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
|
|
||||||
// color is a struct of either a rgb color or a terminal color.
|
// color is a struct of either a rgb color or a terminal color.
|
||||||
struct color_type {
|
struct color_type {
|
||||||
FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
|
FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {}
|
||||||
FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
|
FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} {
|
||||||
value{} {
|
|
||||||
value.rgb_color = static_cast<uint32_t>(rgb_color);
|
value.rgb_color = static_cast<uint32_t>(rgb_color);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
|
FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} {
|
||||||
value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
|
value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
|
||||||
(static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
|
(static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
|
FMT_CONSTEXPR color_type(terminal_color term_color) noexcept
|
||||||
value{} {
|
: is_rgb(), value{} {
|
||||||
value.term_color = static_cast<uint8_t>(term_color);
|
value.term_color = static_cast<uint8_t>(term_color);
|
||||||
}
|
}
|
||||||
bool is_rgb;
|
bool is_rgb;
|
||||||
|
@ -239,10 +238,8 @@ FMT_END_DETAIL_NAMESPACE
|
||||||
/** A text style consisting of foreground and background colors and emphasis. */
|
/** A text style consisting of foreground and background colors and emphasis. */
|
||||||
class text_style {
|
class text_style {
|
||||||
public:
|
public:
|
||||||
FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
|
FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
|
||||||
: set_foreground_color(),
|
: set_foreground_color(), set_background_color(), ems(em) {}
|
||||||
set_background_color(),
|
|
||||||
ems(em) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
|
FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
|
||||||
if (!set_foreground_color) {
|
if (!set_foreground_color) {
|
||||||
|
@ -283,34 +280,32 @@ class text_style {
|
||||||
return lhs.and_assign(rhs);
|
return lhs.and_assign(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR bool has_foreground() const noexcept {
|
||||||
return set_foreground_color;
|
return set_foreground_color;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR bool has_background() const noexcept {
|
||||||
return set_background_color;
|
return set_background_color;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR bool has_emphasis() const noexcept {
|
||||||
return static_cast<uint8_t>(ems) != 0;
|
return static_cast<uint8_t>(ems) != 0;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR detail::color_type get_foreground() const noexcept {
|
||||||
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
|
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
|
||||||
return foreground_color;
|
return foreground_color;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR detail::color_type get_background() const noexcept {
|
||||||
FMT_ASSERT(has_background(), "no background specified for this style");
|
FMT_ASSERT(has_background(), "no background specified for this style");
|
||||||
return background_color;
|
return background_color;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR emphasis get_emphasis() const noexcept {
|
||||||
FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
|
FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
|
||||||
return ems;
|
return ems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FMT_CONSTEXPR text_style(bool is_foreground,
|
FMT_CONSTEXPR text_style(bool is_foreground,
|
||||||
detail::color_type text_color) FMT_NOEXCEPT
|
detail::color_type text_color) noexcept
|
||||||
: set_foreground_color(),
|
: set_foreground_color(), set_background_color(), ems() {
|
||||||
set_background_color(),
|
|
||||||
ems() {
|
|
||||||
if (is_foreground) {
|
if (is_foreground) {
|
||||||
foreground_color = text_color;
|
foreground_color = text_color;
|
||||||
set_foreground_color = true;
|
set_foreground_color = true;
|
||||||
|
@ -345,11 +340,11 @@ class text_style {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
|
friend FMT_CONSTEXPR_DECL text_style
|
||||||
FMT_NOEXCEPT;
|
fg(detail::color_type foreground) noexcept;
|
||||||
|
|
||||||
friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
|
friend FMT_CONSTEXPR_DECL text_style
|
||||||
FMT_NOEXCEPT;
|
bg(detail::color_type background) noexcept;
|
||||||
|
|
||||||
detail::color_type foreground_color;
|
detail::color_type foreground_color;
|
||||||
detail::color_type background_color;
|
detail::color_type background_color;
|
||||||
|
@ -359,17 +354,16 @@ class text_style {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Creates a text style from the foreground (text) color. */
|
/** Creates a text style from the foreground (text) color. */
|
||||||
FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
|
FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) noexcept {
|
||||||
return text_style(true, foreground);
|
return text_style(true, foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a text style from the background color. */
|
/** Creates a text style from the background color. */
|
||||||
FMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT {
|
FMT_CONSTEXPR inline text_style bg(detail::color_type background) noexcept {
|
||||||
return text_style(false, background);
|
return text_style(false, background);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR inline text_style operator|(emphasis lhs,
|
FMT_CONSTEXPR inline text_style operator|(emphasis lhs, emphasis rhs) noexcept {
|
||||||
emphasis rhs) FMT_NOEXCEPT {
|
|
||||||
return text_style(lhs) | rhs;
|
return text_style(lhs) | rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,7 +371,7 @@ FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
|
|
||||||
template <typename Char> struct ansi_color_escape {
|
template <typename Char> struct ansi_color_escape {
|
||||||
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
|
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
|
||||||
const char* esc) FMT_NOEXCEPT {
|
const char* esc) noexcept {
|
||||||
// If we have a terminal color, we need to output another escape code
|
// If we have a terminal color, we need to output another escape code
|
||||||
// sequence.
|
// sequence.
|
||||||
if (!text_color.is_rgb) {
|
if (!text_color.is_rgb) {
|
||||||
|
@ -412,7 +406,7 @@ template <typename Char> struct ansi_color_escape {
|
||||||
to_esc(color.b, buffer + 15, 'm');
|
to_esc(color.b, buffer + 15, 'm');
|
||||||
buffer[19] = static_cast<Char>(0);
|
buffer[19] = static_cast<Char>(0);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
|
FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept {
|
||||||
uint8_t em_codes[num_emphases] = {};
|
uint8_t em_codes[num_emphases] = {};
|
||||||
if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
|
if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
|
||||||
if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
|
if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
|
||||||
|
@ -433,10 +427,10 @@ template <typename Char> struct ansi_color_escape {
|
||||||
}
|
}
|
||||||
buffer[index++] = static_cast<Char>(0);
|
buffer[index++] = static_cast<Char>(0);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }
|
FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; }
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }
|
FMT_CONSTEXPR const Char* begin() const noexcept { return buffer; }
|
||||||
FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const noexcept {
|
||||||
return buffer + std::char_traits<Char>::length(buffer);
|
return buffer + std::char_traits<Char>::length(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,59 +439,64 @@ template <typename Char> struct ansi_color_escape {
|
||||||
Char buffer[7u + 3u * num_emphases + 1u];
|
Char buffer[7u + 3u * num_emphases + 1u];
|
||||||
|
|
||||||
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
|
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
|
||||||
char delimiter) FMT_NOEXCEPT {
|
char delimiter) noexcept {
|
||||||
out[0] = static_cast<Char>('0' + c / 100);
|
out[0] = static_cast<Char>('0' + c / 100);
|
||||||
out[1] = static_cast<Char>('0' + c / 10 % 10);
|
out[1] = static_cast<Char>('0' + c / 10 % 10);
|
||||||
out[2] = static_cast<Char>('0' + c % 10);
|
out[2] = static_cast<Char>('0' + c % 10);
|
||||||
out[3] = static_cast<Char>(delimiter);
|
out[3] = static_cast<Char>(delimiter);
|
||||||
}
|
}
|
||||||
static FMT_CONSTEXPR bool has_emphasis(emphasis em,
|
static FMT_CONSTEXPR bool has_emphasis(emphasis em, emphasis mask) noexcept {
|
||||||
emphasis mask) FMT_NOEXCEPT {
|
|
||||||
return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
|
return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
||||||
detail::color_type foreground) FMT_NOEXCEPT {
|
detail::color_type foreground) noexcept {
|
||||||
return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
|
return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
||||||
detail::color_type background) FMT_NOEXCEPT {
|
detail::color_type background) noexcept {
|
||||||
return ansi_color_escape<Char>(background, "\x1b[48;2;");
|
return ansi_color_escape<Char>(background, "\x1b[48;2;");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
|
FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) noexcept {
|
||||||
return ansi_color_escape<Char>(em);
|
return ansi_color_escape<Char>(em);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char> inline void fputs(const Char* chars, FILE* stream) {
|
||||||
inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
|
int result = std::fputs(chars, stream);
|
||||||
std::fputs(chars, stream);
|
if (result < 0)
|
||||||
|
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) {
|
||||||
inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
|
int result = std::fputws(chars, stream);
|
||||||
std::fputws(chars, stream);
|
if (result < 0)
|
||||||
|
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
|
template <typename Char> inline void reset_color(FILE* stream) {
|
||||||
fputs("\x1b[0m", stream);
|
fputs("\x1b[0m", stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
template <> inline void reset_color<wchar_t>(FILE* stream) {
|
||||||
fputs(L"\x1b[0m", stream);
|
fputs(L"\x1b[0m", stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char> inline void reset_color(buffer<Char>& buffer) {
|
||||||
inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
|
|
||||||
auto reset_color = string_view("\x1b[0m");
|
auto reset_color = string_view("\x1b[0m");
|
||||||
buffer.append(reset_color.begin(), reset_color.end());
|
buffer.append(reset_color.begin(), reset_color.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> struct styled_arg {
|
||||||
|
const T& value;
|
||||||
|
text_style style;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void vformat_to(buffer<Char>& buf, const text_style& ts,
|
void vformat_to(buffer<Char>& buf, const text_style& ts,
|
||||||
basic_string_view<Char> format_str,
|
basic_string_view<Char> format_str,
|
||||||
|
@ -529,8 +528,12 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buf;
|
basic_memory_buffer<Char> buf;
|
||||||
detail::vformat_to(buf, ts, to_string_view(format), args);
|
detail::vformat_to(buf, ts, to_string_view(format), args);
|
||||||
buf.push_back(Char(0));
|
if (detail::is_utf8()) {
|
||||||
detail::fputs(buf.data(), f);
|
detail::print(f, basic_string_view<Char>(buf.begin(), buf.size()));
|
||||||
|
} else {
|
||||||
|
buf.push_back(Char(0));
|
||||||
|
detail::fputs(buf.data(), f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -549,7 +552,7 @@ template <typename S, typename... Args,
|
||||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
vprint(f, ts, format_str,
|
vprint(f, ts, format_str,
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
fmt::make_format_args<buffer_context<char_t<S>>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -594,7 +597,7 @@ template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
return fmt::vformat(ts, to_string_view(format_str),
|
return fmt::vformat(ts, to_string_view(format_str),
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -629,7 +632,60 @@ inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
|
||||||
Args&&... args) ->
|
Args&&... args) ->
|
||||||
typename std::enable_if<enable, OutputIt>::type {
|
typename std::enable_if<enable, OutputIt>::type {
|
||||||
return vformat_to(out, ts, to_string_view(format_str),
|
return vformat_to(out, ts, to_string_view(format_str),
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
fmt::make_format_args<buffer_context<char_t<S>>>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
const auto& ts = arg.style;
|
||||||
|
const auto& value = arg.value;
|
||||||
|
auto out = ctx.out();
|
||||||
|
|
||||||
|
bool has_style = false;
|
||||||
|
if (ts.has_emphasis()) {
|
||||||
|
has_style = true;
|
||||||
|
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
|
||||||
|
out = std::copy(emphasis.begin(), emphasis.end(), out);
|
||||||
|
}
|
||||||
|
if (ts.has_foreground()) {
|
||||||
|
has_style = true;
|
||||||
|
auto foreground =
|
||||||
|
detail::make_foreground_color<Char>(ts.get_foreground());
|
||||||
|
out = std::copy(foreground.begin(), foreground.end(), out);
|
||||||
|
}
|
||||||
|
if (ts.has_background()) {
|
||||||
|
has_style = true;
|
||||||
|
auto background =
|
||||||
|
detail::make_background_color<Char>(ts.get_background());
|
||||||
|
out = std::copy(background.begin(), background.end(), out);
|
||||||
|
}
|
||||||
|
out = formatter<T, Char>::format(value, ctx);
|
||||||
|
if (has_style) {
|
||||||
|
auto reset_color = string_view("\x1b[0m");
|
||||||
|
out = std::copy(reset_color.begin(), reset_color.end(), out);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Returns an argument that will be formatted using ANSI escape sequences,
|
||||||
|
to be used in a formatting function.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
fmt::print("Elapsed time: {s:.2f} seconds",
|
||||||
|
fmt::styled(1.23, fmt::fg(fmt::color::green) | fmt::bg(fmt::color::blue)));
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
FMT_CONSTEXPR auto styled(const T& value, text_style ts)
|
||||||
|
-> detail::styled_arg<remove_cvref_t<T>> {
|
||||||
|
return detail::styled_arg<remove_cvref_t<T>>{value, ts};
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_MODULE_EXPORT_END
|
FMT_MODULE_EXPORT_END
|
||||||
|
|
|
@ -13,45 +13,6 @@
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// An output iterator that counts the number of objects written to it and
|
|
||||||
// discards them.
|
|
||||||
class counting_iterator {
|
|
||||||
private:
|
|
||||||
size_t count_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using iterator_category = std::output_iterator_tag;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using pointer = void;
|
|
||||||
using reference = void;
|
|
||||||
using _Unchecked_type = counting_iterator; // Mark iterator as checked.
|
|
||||||
|
|
||||||
struct value_type {
|
|
||||||
template <typename T> void operator=(const T&) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
counting_iterator() : count_(0) {}
|
|
||||||
|
|
||||||
size_t count() const { return count_; }
|
|
||||||
|
|
||||||
counting_iterator& operator++() {
|
|
||||||
++count_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
counting_iterator operator++(int) {
|
|
||||||
auto it = *this;
|
|
||||||
++*this;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend counting_iterator operator+(counting_iterator it, difference_type n) {
|
|
||||||
it.count_ += static_cast<size_t>(n);
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type operator*() const { return {}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename InputIt>
|
template <typename Char, typename InputIt>
|
||||||
inline counting_iterator copy_str(InputIt begin, InputIt end,
|
inline counting_iterator copy_str(InputIt begin, InputIt end,
|
||||||
counting_iterator it) {
|
counting_iterator it) {
|
||||||
|
@ -75,8 +36,7 @@ template <typename OutputIt> class truncating_iterator_base {
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using pointer = void;
|
using pointer = void;
|
||||||
using reference = void;
|
using reference = void;
|
||||||
using _Unchecked_type =
|
FMT_UNCHECKED_ITERATOR(truncating_iterator_base);
|
||||||
truncating_iterator_base; // Mark iterator as checked.
|
|
||||||
|
|
||||||
OutputIt base() const { return out_; }
|
OutputIt base() const { return out_; }
|
||||||
size_t count() const { return count_; }
|
size_t count() const { return count_; }
|
||||||
|
@ -168,7 +128,7 @@ template <typename Char, size_t N,
|
||||||
fmt::detail_exported::fixed_string<Char, N> Str>
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
struct udl_compiled_string : compiled_string {
|
struct udl_compiled_string : compiled_string {
|
||||||
using char_type = Char;
|
using char_type = Char;
|
||||||
constexpr operator basic_string_view<char_type>() const {
|
explicit constexpr operator basic_string_view<char_type>() const {
|
||||||
return {Str.data, N - 1};
|
return {Str.data, N - 1};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -573,10 +533,11 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||||
detail::unknown_format>()) {
|
detail::unknown_format>()) {
|
||||||
return format(static_cast<basic_string_view<typename S::char_type>>(S()),
|
return fmt::format(
|
||||||
std::forward<Args>(args)...);
|
static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
return format(compiled, std::forward<Args>(args)...);
|
return fmt::format(compiled, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,11 +547,11 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||||
detail::unknown_format>()) {
|
detail::unknown_format>()) {
|
||||||
return format_to(out,
|
return fmt::format_to(
|
||||||
static_cast<basic_string_view<typename S::char_type>>(S()),
|
out, static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
return format_to(out, compiled, std::forward<Args>(args)...);
|
return fmt::format_to(out, compiled, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -599,22 +560,23 @@ template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), format_str,
|
auto it = fmt::format_to(detail::truncating_iterator<OutputIt>(out, n),
|
||||||
std::forward<Args>(args)...);
|
format_str, std::forward<Args>(args)...);
|
||||||
return {it.base(), it.count()};
|
return {it.base(), it.count()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
size_t formatted_size(const S& format_str, const Args&... args) {
|
size_t formatted_size(const S& format_str, const Args&... args) {
|
||||||
return format_to(detail::counting_iterator(), format_str, args...).count();
|
return fmt::format_to(detail::counting_iterator(), format_str, args...)
|
||||||
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
void print(std::FILE* f, const S& format_str, const Args&... args) {
|
void print(std::FILE* f, const S& format_str, const Args&... args) {
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
format_to(std::back_inserter(buffer), format_str, args...);
|
fmt::format_to(std::back_inserter(buffer), format_str, args...);
|
||||||
detail::print(f, {buffer.data(), buffer.size()});
|
detail::print(f, {buffer.data(), buffer.size()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,12 +588,10 @@ void print(const S& format_str, const Args&... args) {
|
||||||
|
|
||||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
template <detail_exported::fixed_string Str>
|
template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
|
||||||
constexpr detail::udl_compiled_string<
|
using char_t = remove_cvref_t<decltype(Str.data[0])>;
|
||||||
remove_cvref_t<decltype(Str.data[0])>,
|
return detail::udl_compiled_string<char_t, sizeof(Str.data) / sizeof(char_t),
|
||||||
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>
|
Str>();
|
||||||
operator""_cf() {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,14 +10,14 @@
|
||||||
|
|
||||||
#include <cstddef> // std::byte
|
#include <cstddef> // std::byte
|
||||||
#include <cstdio> // std::FILE
|
#include <cstdio> // std::FILE
|
||||||
#include <cstring>
|
#include <cstring> // std::strlen
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||||
#define FMT_VERSION 80101
|
#define FMT_VERSION 80102
|
||||||
|
|
||||||
#if defined(__clang__) && !defined(__ibmxl__)
|
#if defined(__clang__) && !defined(__ibmxl__)
|
||||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||||
|
@ -49,6 +49,13 @@
|
||||||
# define FMT_ICC_VERSION 0
|
# define FMT_ICC_VERSION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __NVCOMPILER
|
||||||
|
# define FMT_NVCOMPILER_VERSION \
|
||||||
|
(__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__)
|
||||||
|
#else
|
||||||
|
# define FMT_NVCOMPILER_VERSION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __NVCC__
|
#ifdef __NVCC__
|
||||||
# define FMT_NVCC __NVCC__
|
# define FMT_NVCC __NVCC__
|
||||||
#else
|
#else
|
||||||
|
@ -145,28 +152,6 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
|
|
||||||
#ifndef FMT_USE_NOEXCEPT
|
|
||||||
# define FMT_USE_NOEXCEPT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
|
|
||||||
FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900
|
|
||||||
# define FMT_DETECTED_NOEXCEPT noexcept
|
|
||||||
# define FMT_HAS_CXX11_NOEXCEPT 1
|
|
||||||
#else
|
|
||||||
# define FMT_DETECTED_NOEXCEPT throw()
|
|
||||||
# define FMT_HAS_CXX11_NOEXCEPT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FMT_NOEXCEPT
|
|
||||||
# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT
|
|
||||||
# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
|
|
||||||
# else
|
|
||||||
# define FMT_NOEXCEPT
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code
|
// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code
|
||||||
// warnings.
|
// warnings.
|
||||||
#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \
|
#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \
|
||||||
|
@ -233,6 +218,13 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define FMT_UNCHECKED_ITERATOR(It) \
|
||||||
|
using _Unchecked_type = It // Mark iterator as checked.
|
||||||
|
#else
|
||||||
|
# define FMT_UNCHECKED_ITERATOR(It) using DummyTypeName = It
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef FMT_BEGIN_NAMESPACE
|
#ifndef FMT_BEGIN_NAMESPACE
|
||||||
# define FMT_BEGIN_NAMESPACE \
|
# define FMT_BEGIN_NAMESPACE \
|
||||||
namespace fmt { \
|
namespace fmt { \
|
||||||
|
@ -309,7 +301,7 @@
|
||||||
|
|
||||||
// Enable minimal optimizations for more compact code in debug mode.
|
// Enable minimal optimizations for more compact code in debug mode.
|
||||||
FMT_GCC_PRAGMA("GCC push_options")
|
FMT_GCC_PRAGMA("GCC push_options")
|
||||||
#ifndef __OPTIMIZE__
|
#if !defined(__OPTIMIZE__) && !FMT_NVCOMPILER_VERSION
|
||||||
FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
|
FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -330,6 +322,8 @@ template <typename T>
|
||||||
using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
|
using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
|
||||||
template <typename T> struct type_identity { using type = T; };
|
template <typename T> struct type_identity { using type = T; };
|
||||||
template <typename T> using type_identity_t = typename type_identity<T>::type;
|
template <typename T> using type_identity_t = typename type_identity<T>::type;
|
||||||
|
template <typename T>
|
||||||
|
using underlying_t = typename std::underlying_type<T>::type;
|
||||||
|
|
||||||
struct monostate {
|
struct monostate {
|
||||||
constexpr monostate() {}
|
constexpr monostate() {}
|
||||||
|
@ -351,8 +345,8 @@ FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
// (void)var does not work on many Intel compilers.
|
// (void)var does not work on many Intel compilers.
|
||||||
template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
|
template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
|
||||||
|
|
||||||
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false)
|
constexpr FMT_INLINE auto is_constant_evaluated(
|
||||||
FMT_NOEXCEPT -> bool {
|
bool default_value = false) noexcept -> bool {
|
||||||
#ifdef __cpp_lib_is_constant_evaluated
|
#ifdef __cpp_lib_is_constant_evaluated
|
||||||
ignore_unused(default_value);
|
ignore_unused(default_value);
|
||||||
return std::is_constant_evaluated();
|
return std::is_constant_evaluated();
|
||||||
|
@ -382,12 +376,6 @@ FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cpp_lib_byte
|
|
||||||
using byte = std::byte;
|
|
||||||
#else
|
|
||||||
enum class byte : unsigned char {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FMT_USE_STRING_VIEW)
|
#if defined(FMT_USE_STRING_VIEW)
|
||||||
template <typename Char> using std_string_view = std::basic_string_view<Char>;
|
template <typename Char> using std_string_view = std::basic_string_view<Char>;
|
||||||
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
|
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
|
||||||
|
@ -402,8 +390,8 @@ template <typename T> struct std_string_view {};
|
||||||
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
|
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
|
||||||
!(FMT_CLANG_VERSION && FMT_MSC_VER)
|
!(FMT_CLANG_VERSION && FMT_MSC_VER)
|
||||||
# define FMT_USE_INT128 1
|
# define FMT_USE_INT128 1
|
||||||
using int128_t = __int128_t;
|
using int128_opt = __int128_t; // An optional native 128-bit integer.
|
||||||
using uint128_t = __uint128_t;
|
using uint128_opt = __uint128_t;
|
||||||
template <typename T> inline auto convert_for_visit(T value) -> T {
|
template <typename T> inline auto convert_for_visit(T value) -> T {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -411,12 +399,10 @@ template <typename T> inline auto convert_for_visit(T value) -> T {
|
||||||
# define FMT_USE_INT128 0
|
# define FMT_USE_INT128 0
|
||||||
#endif
|
#endif
|
||||||
#if !FMT_USE_INT128
|
#if !FMT_USE_INT128
|
||||||
enum class int128_t {};
|
enum class int128_opt {};
|
||||||
enum class uint128_t {};
|
enum class uint128_opt {};
|
||||||
// Reduce template instantiations.
|
// Reduce template instantiations.
|
||||||
template <typename T> inline auto convert_for_visit(T) -> monostate {
|
template <typename T> auto convert_for_visit(T) -> monostate { return {}; }
|
||||||
return {};
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Casts a nonnegative integer to unsigned.
|
// Casts a nonnegative integer to unsigned.
|
||||||
|
@ -454,12 +440,11 @@ template <typename Char> class basic_string_view {
|
||||||
using value_type = Char;
|
using value_type = Char;
|
||||||
using iterator = const Char*;
|
using iterator = const Char*;
|
||||||
|
|
||||||
constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {}
|
constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
|
||||||
|
|
||||||
/** Constructs a string reference object from a C string and a size. */
|
/** Constructs a string reference object from a C string and a size. */
|
||||||
constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT
|
constexpr basic_string_view(const Char* s, size_t count) noexcept
|
||||||
: data_(s),
|
: data_(s), size_(count) {}
|
||||||
size_(count) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
|
@ -479,29 +464,28 @@ template <typename Char> class basic_string_view {
|
||||||
/** Constructs a string reference from a ``std::basic_string`` object. */
|
/** Constructs a string reference from a ``std::basic_string`` object. */
|
||||||
template <typename Traits, typename Alloc>
|
template <typename Traits, typename Alloc>
|
||||||
FMT_CONSTEXPR basic_string_view(
|
FMT_CONSTEXPR basic_string_view(
|
||||||
const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT
|
const std::basic_string<Char, Traits, Alloc>& s) noexcept
|
||||||
: data_(s.data()),
|
: data_(s.data()), size_(s.size()) {}
|
||||||
size_(s.size()) {}
|
|
||||||
|
|
||||||
template <typename S, FMT_ENABLE_IF(std::is_same<
|
template <typename S, FMT_ENABLE_IF(std::is_same<
|
||||||
S, detail::std_string_view<Char>>::value)>
|
S, detail::std_string_view<Char>>::value)>
|
||||||
FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()),
|
FMT_CONSTEXPR basic_string_view(S s) noexcept
|
||||||
size_(s.size()) {}
|
: data_(s.data()), size_(s.size()) {}
|
||||||
|
|
||||||
/** Returns a pointer to the string data. */
|
/** Returns a pointer to the string data. */
|
||||||
constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; }
|
constexpr auto data() const noexcept -> const Char* { return data_; }
|
||||||
|
|
||||||
/** Returns the string size. */
|
/** Returns the string size. */
|
||||||
constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
|
constexpr auto size() const noexcept -> size_t { return size_; }
|
||||||
|
|
||||||
constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; }
|
constexpr auto begin() const noexcept -> iterator { return data_; }
|
||||||
constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; }
|
constexpr auto end() const noexcept -> iterator { return data_ + size_; }
|
||||||
|
|
||||||
constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& {
|
constexpr auto operator[](size_t pos) const noexcept -> const Char& {
|
||||||
return data_[pos];
|
return data_[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT {
|
FMT_CONSTEXPR void remove_prefix(size_t n) noexcept {
|
||||||
data_ += n;
|
data_ += n;
|
||||||
size_ -= n;
|
size_ -= n;
|
||||||
}
|
}
|
||||||
|
@ -648,16 +632,14 @@ class basic_format_parse_context : private ErrorHandler {
|
||||||
Returns an iterator to the beginning of the format string range being
|
Returns an iterator to the beginning of the format string range being
|
||||||
parsed.
|
parsed.
|
||||||
*/
|
*/
|
||||||
constexpr auto begin() const FMT_NOEXCEPT -> iterator {
|
constexpr auto begin() const noexcept -> iterator {
|
||||||
return format_str_.begin();
|
return format_str_.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an iterator past the end of the format string range being parsed.
|
Returns an iterator past the end of the format string range being parsed.
|
||||||
*/
|
*/
|
||||||
constexpr auto end() const FMT_NOEXCEPT -> iterator {
|
constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
|
||||||
return format_str_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Advances the begin iterator to ``it``. */
|
/** Advances the begin iterator to ``it``. */
|
||||||
FMT_CONSTEXPR void advance_to(iterator it) {
|
FMT_CONSTEXPR void advance_to(iterator it) {
|
||||||
|
@ -784,18 +766,16 @@ template <typename T> class buffer {
|
||||||
protected:
|
protected:
|
||||||
// Don't initialize ptr_ since it is not accessed to save a few cycles.
|
// Don't initialize ptr_ since it is not accessed to save a few cycles.
|
||||||
FMT_MSC_WARNING(suppress : 26495)
|
FMT_MSC_WARNING(suppress : 26495)
|
||||||
buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
|
buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0,
|
FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
|
||||||
size_t cap = 0) FMT_NOEXCEPT : ptr_(p),
|
: ptr_(p), size_(sz), capacity_(cap) {}
|
||||||
size_(sz),
|
|
||||||
capacity_(cap) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR20 ~buffer() = default;
|
FMT_CONSTEXPR20 ~buffer() = default;
|
||||||
buffer(buffer&&) = default;
|
buffer(buffer&&) = default;
|
||||||
|
|
||||||
/** Sets the buffer data and capacity. */
|
/** Sets the buffer data and capacity. */
|
||||||
FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {
|
FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept {
|
||||||
ptr_ = buf_data;
|
ptr_ = buf_data;
|
||||||
capacity_ = buf_capacity;
|
capacity_ = buf_capacity;
|
||||||
}
|
}
|
||||||
|
@ -810,23 +790,23 @@ template <typename T> class buffer {
|
||||||
buffer(const buffer&) = delete;
|
buffer(const buffer&) = delete;
|
||||||
void operator=(const buffer&) = delete;
|
void operator=(const buffer&) = delete;
|
||||||
|
|
||||||
auto begin() FMT_NOEXCEPT -> T* { return ptr_; }
|
auto begin() noexcept -> T* { return ptr_; }
|
||||||
auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; }
|
auto end() noexcept -> T* { return ptr_ + size_; }
|
||||||
|
|
||||||
auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; }
|
auto begin() const noexcept -> const T* { return ptr_; }
|
||||||
auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; }
|
auto end() const noexcept -> const T* { return ptr_ + size_; }
|
||||||
|
|
||||||
/** Returns the size of this buffer. */
|
/** Returns the size of this buffer. */
|
||||||
constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
|
constexpr auto size() const noexcept -> size_t { return size_; }
|
||||||
|
|
||||||
/** Returns the capacity of this buffer. */
|
/** Returns the capacity of this buffer. */
|
||||||
constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; }
|
constexpr auto capacity() const noexcept -> size_t { return capacity_; }
|
||||||
|
|
||||||
/** Returns a pointer to the buffer data. */
|
/** Returns a pointer to the buffer data. */
|
||||||
FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; }
|
FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; }
|
||||||
|
|
||||||
/** Returns a pointer to the buffer data. */
|
/** Returns a pointer to the buffer data. */
|
||||||
FMT_CONSTEXPR auto data() const FMT_NOEXCEPT -> const T* { return ptr_; }
|
FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
|
||||||
|
|
||||||
/** Clears this buffer. */
|
/** Clears this buffer. */
|
||||||
void clear() { size_ = 0; }
|
void clear() { size_ = 0; }
|
||||||
|
@ -1044,7 +1024,11 @@ struct fallback_formatter {
|
||||||
// Specifies if T has an enabled fallback_formatter specialization.
|
// Specifies if T has an enabled fallback_formatter specialization.
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
using has_fallback_formatter =
|
using has_fallback_formatter =
|
||||||
|
#ifdef FMT_DEPRECATED_OSTREAM
|
||||||
std::is_constructible<fallback_formatter<T, Char>>;
|
std::is_constructible<fallback_formatter<T, Char>>;
|
||||||
|
#else
|
||||||
|
std::false_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct view {};
|
struct view {};
|
||||||
|
|
||||||
|
@ -1164,8 +1148,8 @@ FMT_TYPE_CONSTANT(int, int_type);
|
||||||
FMT_TYPE_CONSTANT(unsigned, uint_type);
|
FMT_TYPE_CONSTANT(unsigned, uint_type);
|
||||||
FMT_TYPE_CONSTANT(long long, long_long_type);
|
FMT_TYPE_CONSTANT(long long, long_long_type);
|
||||||
FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
|
FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
|
||||||
FMT_TYPE_CONSTANT(int128_t, int128_type);
|
FMT_TYPE_CONSTANT(int128_opt, int128_type);
|
||||||
FMT_TYPE_CONSTANT(uint128_t, uint128_type);
|
FMT_TYPE_CONSTANT(uint128_opt, uint128_type);
|
||||||
FMT_TYPE_CONSTANT(bool, bool_type);
|
FMT_TYPE_CONSTANT(bool, bool_type);
|
||||||
FMT_TYPE_CONSTANT(Char, char_type);
|
FMT_TYPE_CONSTANT(Char, char_type);
|
||||||
FMT_TYPE_CONSTANT(float, float_type);
|
FMT_TYPE_CONSTANT(float, float_type);
|
||||||
|
@ -1215,8 +1199,8 @@ template <typename Context> class value {
|
||||||
unsigned uint_value;
|
unsigned uint_value;
|
||||||
long long long_long_value;
|
long long long_long_value;
|
||||||
unsigned long long ulong_long_value;
|
unsigned long long ulong_long_value;
|
||||||
int128_t int128_value;
|
int128_opt int128_value;
|
||||||
uint128_t uint128_value;
|
uint128_opt uint128_value;
|
||||||
bool bool_value;
|
bool bool_value;
|
||||||
char_type char_value;
|
char_type char_value;
|
||||||
float float_value;
|
float float_value;
|
||||||
|
@ -1233,8 +1217,8 @@ template <typename Context> class value {
|
||||||
constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}
|
constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}
|
||||||
constexpr FMT_INLINE value(long long val) : long_long_value(val) {}
|
constexpr FMT_INLINE value(long long val) : long_long_value(val) {}
|
||||||
constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}
|
constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}
|
||||||
FMT_INLINE value(int128_t val) : int128_value(val) {}
|
FMT_INLINE value(int128_opt val) : int128_value(val) {}
|
||||||
FMT_INLINE value(uint128_t val) : uint128_value(val) {}
|
FMT_INLINE value(uint128_opt val) : uint128_value(val) {}
|
||||||
constexpr FMT_INLINE value(float val) : float_value(val) {}
|
constexpr FMT_INLINE value(float val) : float_value(val) {}
|
||||||
constexpr FMT_INLINE value(double val) : double_value(val) {}
|
constexpr FMT_INLINE value(double val) : double_value(val) {}
|
||||||
FMT_INLINE value(long double val) : long_double_value(val) {}
|
FMT_INLINE value(long double val) : long_double_value(val) {}
|
||||||
|
@ -1284,7 +1268,7 @@ template <typename Context> class value {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>;
|
FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context>;
|
||||||
|
|
||||||
// To minimize the number of types we need to deal with, long is translated
|
// To minimize the number of types we need to deal with, long is translated
|
||||||
// either to int or to long long depending on its size.
|
// either to int or to long long depending on its size.
|
||||||
|
@ -1292,6 +1276,21 @@ enum { long_short = sizeof(long) == sizeof(int) };
|
||||||
using long_type = conditional_t<long_short, int, long long>;
|
using long_type = conditional_t<long_short, int, long long>;
|
||||||
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
|
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_byte
|
||||||
|
inline auto format_as(std::byte b) -> unsigned char {
|
||||||
|
return static_cast<unsigned char>(b);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T> struct has_format_as {
|
||||||
|
template <typename U, typename V = decltype(format_as(U())),
|
||||||
|
FMT_ENABLE_IF(std::is_enum<U>::value&& std::is_integral<V>::value)>
|
||||||
|
static auto check(U*) -> std::true_type;
|
||||||
|
static auto check(...) -> std::false_type;
|
||||||
|
|
||||||
|
enum { value = decltype(check(static_cast<T*>(nullptr)))::value };
|
||||||
|
};
|
||||||
|
|
||||||
// Maps formatting arguments to core types.
|
// Maps formatting arguments to core types.
|
||||||
// arg_mapper reports errors by returning unformattable instead of using
|
// arg_mapper reports errors by returning unformattable instead of using
|
||||||
// static_assert because it's used in the is_formattable trait.
|
// static_assert because it's used in the is_formattable trait.
|
||||||
|
@ -1317,8 +1316,12 @@ template <typename Context> struct arg_mapper {
|
||||||
-> unsigned long long {
|
-> unsigned long long {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt {
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }
|
return val;
|
||||||
|
}
|
||||||
|
FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
|
template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
|
||||||
|
@ -1365,20 +1368,19 @@ template <typename Context> struct arg_mapper {
|
||||||
}
|
}
|
||||||
template <typename T,
|
template <typename T,
|
||||||
FMT_ENABLE_IF(
|
FMT_ENABLE_IF(
|
||||||
std::is_constructible<basic_string_view<char_type>, T>::value &&
|
std::is_convertible<T, basic_string_view<char_type>>::value &&
|
||||||
!is_string<T>::value && !has_formatter<T, Context>::value &&
|
!is_string<T>::value && !has_formatter<T, Context>::value &&
|
||||||
!has_fallback_formatter<T, char_type>::value)>
|
!has_fallback_formatter<T, char_type>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
||||||
-> basic_string_view<char_type> {
|
-> basic_string_view<char_type> {
|
||||||
return basic_string_view<char_type>(val);
|
return basic_string_view<char_type>(val);
|
||||||
}
|
}
|
||||||
template <
|
template <typename T,
|
||||||
typename T,
|
FMT_ENABLE_IF(
|
||||||
FMT_ENABLE_IF(
|
std::is_convertible<T, std_string_view<char_type>>::value &&
|
||||||
std::is_constructible<std_string_view<char_type>, T>::value &&
|
!std::is_convertible<T, basic_string_view<char_type>>::value &&
|
||||||
!std::is_constructible<basic_string_view<char_type>, T>::value &&
|
!is_string<T>::value && !has_formatter<T, Context>::value &&
|
||||||
!is_string<T>::value && !has_formatter<T, Context>::value &&
|
!has_fallback_formatter<T, char_type>::value)>
|
||||||
!has_fallback_formatter<T, char_type>::value)>
|
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
||||||
-> basic_string_view<char_type> {
|
-> basic_string_view<char_type> {
|
||||||
return std_string_view<char_type>(val);
|
return std_string_view<char_type>(val);
|
||||||
|
@ -1417,10 +1419,11 @@ template <typename Context> struct arg_mapper {
|
||||||
template <
|
template <
|
||||||
typename T,
|
typename T,
|
||||||
FMT_ENABLE_IF(
|
FMT_ENABLE_IF(
|
||||||
std::is_member_pointer<T>::value ||
|
std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
|
||||||
std::is_function<typename std::remove_pointer<T>::type>::value ||
|
std::is_function<typename std::remove_pointer<T>::type>::value ||
|
||||||
(std::is_convertible<const T&, const void*>::value &&
|
(std::is_convertible<const T&, const void*>::value &&
|
||||||
!std::is_convertible<const T&, const char_type*>::value))>
|
!std::is_convertible<const T&, const char_type*>::value &&
|
||||||
|
!has_formatter<T, Context>::value))>
|
||||||
FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
|
FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -1438,12 +1441,15 @@ template <typename Context> struct arg_mapper {
|
||||||
!has_fallback_formatter<T, char_type>::value)>
|
!has_fallback_formatter<T, char_type>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
||||||
-> decltype(std::declval<arg_mapper>().map(
|
-> decltype(std::declval<arg_mapper>().map(
|
||||||
static_cast<typename std::underlying_type<T>::type>(val))) {
|
static_cast<underlying_t<T>>(val))) {
|
||||||
return map(static_cast<typename std::underlying_type<T>::type>(val));
|
return map(static_cast<underlying_t<T>>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned {
|
template <typename T, FMT_ENABLE_IF(has_format_as<T>::value &&
|
||||||
return map(static_cast<unsigned char>(val));
|
!has_formatter<T, Context>::value)>
|
||||||
|
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
||||||
|
-> decltype(std::declval<arg_mapper>().map(format_as(T()))) {
|
||||||
|
return map(format_as(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U = remove_cvref_t<T>>
|
template <typename T, typename U = remove_cvref_t<T>>
|
||||||
|
@ -1452,8 +1458,9 @@ template <typename Context> struct arg_mapper {
|
||||||
!std::is_const<remove_reference_t<T>>::value ||
|
!std::is_const<remove_reference_t<T>>::value ||
|
||||||
has_fallback_formatter<U, char_type>::value> {};
|
has_fallback_formatter<U, char_type>::value> {};
|
||||||
|
|
||||||
#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910
|
#if (FMT_MSC_VER != 0 && FMT_MSC_VER < 1910) || FMT_ICC_VERSION != 0 || \
|
||||||
// Workaround a bug in MSVC.
|
FMT_NVCC != 0
|
||||||
|
// Workaround a bug in MSVC and Intel (Issue 2746).
|
||||||
template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {
|
template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -1471,6 +1478,8 @@ template <typename Context> struct arg_mapper {
|
||||||
template <typename T, typename U = remove_cvref_t<T>,
|
template <typename T, typename U = remove_cvref_t<T>,
|
||||||
FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value &&
|
FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value &&
|
||||||
!std::is_array<U>::value &&
|
!std::is_array<U>::value &&
|
||||||
|
!std::is_pointer<U>::value &&
|
||||||
|
!has_format_as<U>::value &&
|
||||||
(has_formatter<U, Context>::value ||
|
(has_formatter<U, Context>::value ||
|
||||||
has_fallback_formatter<U, char_type>::value))>
|
has_fallback_formatter<U, char_type>::value))>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(T&& val)
|
FMT_CONSTEXPR FMT_INLINE auto map(T&& val)
|
||||||
|
@ -1513,12 +1522,12 @@ class appender : public std::back_insert_iterator<detail::buffer<char>> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
|
using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
|
||||||
appender(base it) FMT_NOEXCEPT : base(it) {}
|
appender(base it) noexcept : base(it) {}
|
||||||
using _Unchecked_type = appender; // Mark iterator as checked.
|
FMT_UNCHECKED_ITERATOR(appender);
|
||||||
|
|
||||||
auto operator++() FMT_NOEXCEPT -> appender& { return *this; }
|
auto operator++() noexcept -> appender& { return *this; }
|
||||||
|
|
||||||
auto operator++(int) FMT_NOEXCEPT -> appender { return *this; }
|
auto operator++(int) noexcept -> appender { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// A formatting argument. It is a trivially copyable/constructible type to
|
// A formatting argument. It is a trivially copyable/constructible type to
|
||||||
|
@ -1529,7 +1538,7 @@ template <typename Context> class basic_format_arg {
|
||||||
detail::type type_;
|
detail::type type_;
|
||||||
|
|
||||||
template <typename ContextType, typename T>
|
template <typename ContextType, typename T>
|
||||||
friend FMT_CONSTEXPR auto detail::make_arg(const T& value)
|
friend FMT_CONSTEXPR auto detail::make_arg(T&& value)
|
||||||
-> basic_format_arg<ContextType>;
|
-> basic_format_arg<ContextType>;
|
||||||
|
|
||||||
template <typename Visitor, typename Ctx>
|
template <typename Visitor, typename Ctx>
|
||||||
|
@ -1564,7 +1573,7 @@ template <typename Context> class basic_format_arg {
|
||||||
|
|
||||||
constexpr basic_format_arg() : type_(detail::type::none_type) {}
|
constexpr basic_format_arg() : type_(detail::type::none_type) {}
|
||||||
|
|
||||||
constexpr explicit operator bool() const FMT_NOEXCEPT {
|
constexpr explicit operator bool() const noexcept {
|
||||||
return type_ != detail::type::none_type;
|
return type_ != detail::type::none_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1674,7 +1683,7 @@ class locale_ref {
|
||||||
constexpr locale_ref() : locale_(nullptr) {}
|
constexpr locale_ref() : locale_(nullptr) {}
|
||||||
template <typename Locale> explicit locale_ref(const Locale& loc);
|
template <typename Locale> explicit locale_ref(const Locale& loc);
|
||||||
|
|
||||||
explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; }
|
explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||||
|
|
||||||
template <typename Locale> auto get() const -> Locale;
|
template <typename Locale> auto get() const -> Locale;
|
||||||
};
|
};
|
||||||
|
@ -1690,10 +1699,40 @@ constexpr auto encode_types() -> unsigned long long {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {
|
FMT_CONSTEXPR FMT_INLINE auto make_value(T&& val) -> value<Context> {
|
||||||
|
const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
|
||||||
|
|
||||||
|
[[maybe_unused]] constexpr bool formattable_char =
|
||||||
|
!std::is_same<decltype(arg), const unformattable_char&>::value;
|
||||||
|
static_assert(formattable_char, "Mixing character types is disallowed.");
|
||||||
|
|
||||||
|
[[maybe_unused]] constexpr bool formattable_const =
|
||||||
|
!std::is_same<decltype(arg), const unformattable_const&>::value;
|
||||||
|
static_assert(formattable_const, "Cannot format a const argument.");
|
||||||
|
|
||||||
|
// Formatting of arbitrary pointers is disallowed. If you want to output
|
||||||
|
// a pointer cast it to "void *" or "const void *". In particular, this
|
||||||
|
// forbids formatting of "[const] volatile char *" which is printed as bool
|
||||||
|
// by iostreams.
|
||||||
|
[[maybe_unused]] constexpr bool formattable_pointer =
|
||||||
|
!std::is_same<decltype(arg), const unformattable_pointer&>::value;
|
||||||
|
static_assert(formattable_pointer,
|
||||||
|
"Formatting of non-void pointers is disallowed.");
|
||||||
|
|
||||||
|
[[maybe_unused]] constexpr bool formattable =
|
||||||
|
!std::is_same<decltype(arg), const unformattable&>::value;
|
||||||
|
static_assert(
|
||||||
|
formattable,
|
||||||
|
"Cannot format an argument. To make type T formattable provide a "
|
||||||
|
"formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
|
||||||
|
return {arg};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context, typename T>
|
||||||
|
FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context> {
|
||||||
basic_format_arg<Context> arg;
|
basic_format_arg<Context> arg;
|
||||||
arg.type_ = mapped_type_constant<T, Context>::value;
|
arg.type_ = mapped_type_constant<T, Context>::value;
|
||||||
arg.value_ = arg_mapper<Context>().map(value);
|
arg.value_ = make_value<Context>(value);
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,37 +1742,12 @@ FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {
|
||||||
template <bool IS_PACKED, typename Context, type, typename T,
|
template <bool IS_PACKED, typename Context, type, typename T,
|
||||||
FMT_ENABLE_IF(IS_PACKED)>
|
FMT_ENABLE_IF(IS_PACKED)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
||||||
const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
|
return make_value<Context>(val);
|
||||||
|
|
||||||
constexpr bool formattable_char =
|
|
||||||
!std::is_same<decltype(arg), const unformattable_char&>::value;
|
|
||||||
static_assert(formattable_char, "Mixing character types is disallowed.");
|
|
||||||
|
|
||||||
constexpr bool formattable_const =
|
|
||||||
!std::is_same<decltype(arg), const unformattable_const&>::value;
|
|
||||||
static_assert(formattable_const, "Cannot format a const argument.");
|
|
||||||
|
|
||||||
// Formatting of arbitrary pointers is disallowed. If you want to output
|
|
||||||
// a pointer cast it to "void *" or "const void *". In particular, this
|
|
||||||
// forbids formatting of "[const] volatile char *" which is printed as bool
|
|
||||||
// by iostreams.
|
|
||||||
constexpr bool formattable_pointer =
|
|
||||||
!std::is_same<decltype(arg), const unformattable_pointer&>::value;
|
|
||||||
static_assert(formattable_pointer,
|
|
||||||
"Formatting of non-void pointers is disallowed.");
|
|
||||||
|
|
||||||
constexpr bool formattable =
|
|
||||||
!std::is_same<decltype(arg), const unformattable&>::value;
|
|
||||||
static_assert(
|
|
||||||
formattable,
|
|
||||||
"Cannot format an argument. To make type T formattable provide a "
|
|
||||||
"formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
|
|
||||||
return {arg};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool IS_PACKED, typename Context, type, typename T,
|
template <bool IS_PACKED, typename Context, type, typename T,
|
||||||
FMT_ENABLE_IF(!IS_PACKED)>
|
FMT_ENABLE_IF(!IS_PACKED)>
|
||||||
inline auto make_arg(const T& value) -> basic_format_arg<Context> {
|
FMT_CONSTEXPR inline auto make_arg(T&& value) -> basic_format_arg<Context> {
|
||||||
return make_arg<Context>(value);
|
return make_arg<Context>(value);
|
||||||
}
|
}
|
||||||
FMT_END_DETAIL_NAMESPACE
|
FMT_END_DETAIL_NAMESPACE
|
||||||
|
@ -2015,14 +2029,23 @@ template <typename Context> class basic_format_args {
|
||||||
// between clang and gcc on ARM (#1919).
|
// between clang and gcc on ARM (#1919).
|
||||||
using format_args = basic_format_args<format_context>;
|
using format_args = basic_format_args<format_context>;
|
||||||
|
|
||||||
// We cannot use enum classes as bit fields because of a gcc bug
|
// We cannot use enum classes as bit fields because of a gcc bug,
|
||||||
|
// so we put them in namespaces instead.
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
|
||||||
|
// Additionally, if an underlying type is specified, older gcc incorrectly warns
|
||||||
|
// that the type is too small for all the enum values.
|
||||||
|
// Both these bugs are fixed as of gcc 9.3.
|
||||||
|
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
|
||||||
|
# define FMT_ENUM_UNDERLYING_TYPE(type)
|
||||||
|
#else
|
||||||
|
# define FMT_ENUM_UNDERLYING_TYPE(type) : type
|
||||||
|
#endif
|
||||||
namespace align {
|
namespace align {
|
||||||
enum type { none, left, right, center, numeric };
|
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, left, right, center, numeric };
|
||||||
}
|
}
|
||||||
using align_t = align::type;
|
using align_t = align::type;
|
||||||
namespace sign {
|
namespace sign {
|
||||||
enum type { none, minus, plus, space };
|
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, minus, plus, space };
|
||||||
}
|
}
|
||||||
using sign_t = sign::type;
|
using sign_t = sign::type;
|
||||||
|
|
||||||
|
@ -2072,7 +2095,8 @@ enum class presentation_type : unsigned char {
|
||||||
general_upper, // 'G'
|
general_upper, // 'G'
|
||||||
chr, // 'c'
|
chr, // 'c'
|
||||||
string, // 's'
|
string, // 's'
|
||||||
pointer // 'p'
|
pointer, // 'p'
|
||||||
|
debug // '?'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format specifiers for built-in and string types.
|
// Format specifiers for built-in and string types.
|
||||||
|
@ -2231,13 +2255,12 @@ template <typename Char> constexpr bool is_ascii_letter(Char c) {
|
||||||
|
|
||||||
// Converts a character to ASCII. Returns a number > 127 on conversion failure.
|
// Converts a character to ASCII. Returns a number > 127 on conversion failure.
|
||||||
template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
|
template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
|
||||||
constexpr auto to_ascii(Char value) -> Char {
|
constexpr auto to_ascii(Char c) -> Char {
|
||||||
return value;
|
return c;
|
||||||
}
|
}
|
||||||
template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
|
template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
|
||||||
constexpr auto to_ascii(Char value) ->
|
constexpr auto to_ascii(Char c) -> underlying_t<Char> {
|
||||||
typename std::underlying_type<Char>::type {
|
return c;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
|
@ -2302,7 +2325,7 @@ FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||||
FMT_ASSERT(begin != end, "");
|
FMT_ASSERT(begin != end, "");
|
||||||
auto align = align::none;
|
auto align = align::none;
|
||||||
auto p = begin + code_point_length(begin);
|
auto p = begin + code_point_length(begin);
|
||||||
if (p >= end) p = begin;
|
if (end - p <= 0) p = begin;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (to_ascii(*p)) {
|
switch (to_ascii(*p)) {
|
||||||
case '<':
|
case '<':
|
||||||
|
@ -2488,6 +2511,8 @@ FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type {
|
||||||
return presentation_type::string;
|
return presentation_type::string;
|
||||||
case 'p':
|
case 'p':
|
||||||
return presentation_type::pointer;
|
return presentation_type::pointer;
|
||||||
|
case '?':
|
||||||
|
return presentation_type::debug;
|
||||||
default:
|
default:
|
||||||
return presentation_type::none;
|
return presentation_type::none;
|
||||||
}
|
}
|
||||||
|
@ -2661,17 +2686,27 @@ FMT_CONSTEXPR FMT_INLINE void parse_format_string(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct strip_named_arg<T, true> {
|
||||||
|
using type = remove_cvref_t<decltype(T::value)>;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename ParseContext>
|
template <typename T, typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
|
FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
|
||||||
-> decltype(ctx.begin()) {
|
-> decltype(ctx.begin()) {
|
||||||
using char_type = typename ParseContext::char_type;
|
using char_type = typename ParseContext::char_type;
|
||||||
using context = buffer_context<char_type>;
|
using context = buffer_context<char_type>;
|
||||||
|
using stripped_type = typename strip_named_arg<T>::type;
|
||||||
using mapped_type = conditional_t<
|
using mapped_type = conditional_t<
|
||||||
mapped_type_constant<T, context>::value != type::custom_type,
|
mapped_type_constant<T, context>::value != type::custom_type,
|
||||||
decltype(arg_mapper<context>().map(std::declval<const T&>())), T>;
|
decltype(arg_mapper<context>().map(std::declval<const T&>())),
|
||||||
|
stripped_type>;
|
||||||
auto f = conditional_t<has_formatter<mapped_type, context>::value,
|
auto f = conditional_t<has_formatter<mapped_type, context>::value,
|
||||||
formatter<mapped_type, char_type>,
|
formatter<mapped_type, char_type>,
|
||||||
fallback_formatter<T, char_type>>();
|
fallback_formatter<stripped_type, char_type>>();
|
||||||
return f.parse(ctx);
|
return f.parse(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2717,7 +2752,8 @@ template <typename Char, typename ErrorHandler = error_handler>
|
||||||
FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs,
|
FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs,
|
||||||
ErrorHandler&& eh = {}) -> bool {
|
ErrorHandler&& eh = {}) -> bool {
|
||||||
if (specs.type != presentation_type::none &&
|
if (specs.type != presentation_type::none &&
|
||||||
specs.type != presentation_type::chr) {
|
specs.type != presentation_type::chr &&
|
||||||
|
specs.type != presentation_type::debug) {
|
||||||
check_int_type_spec(specs.type, eh);
|
check_int_type_spec(specs.type, eh);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2741,7 +2777,6 @@ struct float_specs {
|
||||||
bool upper : 1;
|
bool upper : 1;
|
||||||
bool locale : 1;
|
bool locale : 1;
|
||||||
bool binary32 : 1;
|
bool binary32 : 1;
|
||||||
bool fallback : 1;
|
|
||||||
bool showpoint : 1;
|
bool showpoint : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2801,7 +2836,8 @@ FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type,
|
||||||
template <typename ErrorHandler = error_handler>
|
template <typename ErrorHandler = error_handler>
|
||||||
FMT_CONSTEXPR void check_string_type_spec(presentation_type type,
|
FMT_CONSTEXPR void check_string_type_spec(presentation_type type,
|
||||||
ErrorHandler&& eh = {}) {
|
ErrorHandler&& eh = {}) {
|
||||||
if (type != presentation_type::none && type != presentation_type::string)
|
if (type != presentation_type::none && type != presentation_type::string &&
|
||||||
|
type != presentation_type::debug)
|
||||||
eh.on_error("invalid type specifier");
|
eh.on_error("invalid type specifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2835,7 +2871,8 @@ template <typename Handler> class specs_checker : public Handler {
|
||||||
FMT_CONSTEXPR void on_sign(sign_t s) {
|
FMT_CONSTEXPR void on_sign(sign_t s) {
|
||||||
require_numeric_argument();
|
require_numeric_argument();
|
||||||
if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
|
if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
|
||||||
arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
|
arg_type_ != type::long_long_type && arg_type_ != type::int128_type &&
|
||||||
|
arg_type_ != type::char_type) {
|
||||||
this->on_error("format specifier requires signed argument");
|
this->on_error("format specifier requires signed argument");
|
||||||
}
|
}
|
||||||
Handler::on_sign(s);
|
Handler::on_sign(s);
|
||||||
|
@ -3043,6 +3080,27 @@ struct formatter<T, Char,
|
||||||
-> decltype(ctx.out());
|
-> decltype(ctx.out());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FMT_FORMAT_AS(Type, Base) \
|
||||||
|
template <typename Char> \
|
||||||
|
struct formatter<Type, Char> : formatter<Base, Char> { \
|
||||||
|
template <typename FormatContext> \
|
||||||
|
auto format(Type const& val, FormatContext& ctx) const \
|
||||||
|
-> decltype(ctx.out()) { \
|
||||||
|
return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_FORMAT_AS(signed char, int);
|
||||||
|
FMT_FORMAT_AS(unsigned char, unsigned);
|
||||||
|
FMT_FORMAT_AS(short, int);
|
||||||
|
FMT_FORMAT_AS(unsigned short, unsigned);
|
||||||
|
FMT_FORMAT_AS(long, long long);
|
||||||
|
FMT_FORMAT_AS(unsigned long, unsigned long long);
|
||||||
|
FMT_FORMAT_AS(Char*, const Char*);
|
||||||
|
FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
|
||||||
|
FMT_FORMAT_AS(std::nullptr_t, const void*);
|
||||||
|
FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
|
||||||
|
|
||||||
template <typename Char> struct basic_runtime { basic_string_view<Char> str; };
|
template <typename Char> struct basic_runtime { basic_string_view<Char> str; };
|
||||||
|
|
||||||
/** A compile-time format string. */
|
/** A compile-time format string. */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -9,10 +9,8 @@
|
||||||
#define FMT_OS_H_
|
#define FMT_OS_H_
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <clocale> // locale_t
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib> // strtod_l
|
|
||||||
#include <system_error> // std::system_error
|
#include <system_error> // std::system_error
|
||||||
|
|
||||||
#if defined __APPLE__ || defined(__FreeBSD__)
|
#if defined __APPLE__ || defined(__FreeBSD__)
|
||||||
|
@ -141,7 +139,7 @@ template <typename Char> struct formatter<std::error_code, Char> {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
FMT_API const std::error_category& system_category() FMT_NOEXCEPT;
|
FMT_API const std::error_category& system_category() noexcept;
|
||||||
|
|
||||||
FMT_BEGIN_DETAIL_NAMESPACE
|
FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
// A converter from UTF-16 to UTF-8.
|
// A converter from UTF-16 to UTF-8.
|
||||||
|
@ -165,7 +163,7 @@ class utf16_to_utf8 {
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||||
const char* message) FMT_NOEXCEPT;
|
const char* message) noexcept;
|
||||||
FMT_END_DETAIL_NAMESPACE
|
FMT_END_DETAIL_NAMESPACE
|
||||||
|
|
||||||
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
||||||
|
@ -207,10 +205,9 @@ std::system_error windows_error(int error_code, string_view message,
|
||||||
|
|
||||||
// Reports a Windows error without throwing an exception.
|
// Reports a Windows error without throwing an exception.
|
||||||
// Can be used to report errors from destructors.
|
// Can be used to report errors from destructors.
|
||||||
FMT_API void report_windows_error(int error_code,
|
FMT_API void report_windows_error(int error_code, const char* message) noexcept;
|
||||||
const char* message) FMT_NOEXCEPT;
|
|
||||||
#else
|
#else
|
||||||
inline const std::error_category& system_category() FMT_NOEXCEPT {
|
inline const std::error_category& system_category() noexcept {
|
||||||
return std::system_category();
|
return std::system_category();
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
@ -237,13 +234,13 @@ class buffered_file {
|
||||||
void operator=(const buffered_file&) = delete;
|
void operator=(const buffered_file&) = delete;
|
||||||
|
|
||||||
// Constructs a buffered_file object which doesn't represent any file.
|
// Constructs a buffered_file object which doesn't represent any file.
|
||||||
buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
|
buffered_file() noexcept : file_(nullptr) {}
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
// Destroys the object closing the file it represents if any.
|
||||||
FMT_API ~buffered_file() FMT_NOEXCEPT;
|
FMT_API ~buffered_file() noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
|
buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
|
||||||
other.file_ = nullptr;
|
other.file_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,10 +258,11 @@ class buffered_file {
|
||||||
FMT_API void close();
|
FMT_API void close();
|
||||||
|
|
||||||
// Returns the pointer to a FILE object representing this file.
|
// Returns the pointer to a FILE object representing this file.
|
||||||
FILE* get() const FMT_NOEXCEPT { return file_; }
|
FILE* get() const noexcept { return file_; }
|
||||||
|
|
||||||
// We place parentheses around fileno to workaround a bug in some versions
|
// We place parentheses around fileno to workaround a bug in some versions
|
||||||
// of MinGW that define fileno as a macro.
|
// of MinGW that define fileno as a macro.
|
||||||
|
// DEPRECATED! Rename to descriptor to avoid issues with macros.
|
||||||
FMT_API int(fileno)() const;
|
FMT_API int(fileno)() const;
|
||||||
|
|
||||||
void vprint(string_view format_str, format_args args) {
|
void vprint(string_view format_str, format_args args) {
|
||||||
|
@ -279,12 +277,12 @@ class buffered_file {
|
||||||
|
|
||||||
#if FMT_USE_FCNTL
|
#if FMT_USE_FCNTL
|
||||||
// A file. Closed file is represented by a file object with descriptor -1.
|
// A file. Closed file is represented by a file object with descriptor -1.
|
||||||
// Methods that are not declared with FMT_NOEXCEPT may throw
|
// Methods that are not declared with noexcept may throw
|
||||||
// fmt::system_error in case of failure. Note that some errors such as
|
// fmt::system_error in case of failure. Note that some errors such as
|
||||||
// closing the file multiple times will cause a crash on Windows rather
|
// closing the file multiple times will cause a crash on Windows rather
|
||||||
// than an exception. You can get standard behavior by overriding the
|
// than an exception. You can get standard behavior by overriding the
|
||||||
// invalid parameter handler with _set_invalid_parameter_handler.
|
// invalid parameter handler with _set_invalid_parameter_handler.
|
||||||
class file {
|
class FMT_API file {
|
||||||
private:
|
private:
|
||||||
int fd_; // File descriptor.
|
int fd_; // File descriptor.
|
||||||
|
|
||||||
|
@ -303,16 +301,16 @@ class file {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructs a file object which doesn't represent any file.
|
// Constructs a file object which doesn't represent any file.
|
||||||
file() FMT_NOEXCEPT : fd_(-1) {}
|
file() noexcept : fd_(-1) {}
|
||||||
|
|
||||||
// Opens a file and constructs a file object representing this file.
|
// Opens a file and constructs a file object representing this file.
|
||||||
FMT_API file(cstring_view path, int oflag);
|
file(cstring_view path, int oflag);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
file(const file&) = delete;
|
file(const file&) = delete;
|
||||||
void operator=(const file&) = delete;
|
void operator=(const file&) = delete;
|
||||||
|
|
||||||
file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
|
file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
|
||||||
|
|
||||||
// Move assignment is not noexcept because close may throw.
|
// Move assignment is not noexcept because close may throw.
|
||||||
file& operator=(file&& other) {
|
file& operator=(file&& other) {
|
||||||
|
@ -323,43 +321,43 @@ class file {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
// Destroys the object closing the file it represents if any.
|
||||||
FMT_API ~file() FMT_NOEXCEPT;
|
~file() noexcept;
|
||||||
|
|
||||||
// Returns the file descriptor.
|
// Returns the file descriptor.
|
||||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
int descriptor() const noexcept { return fd_; }
|
||||||
|
|
||||||
// Closes the file.
|
// Closes the file.
|
||||||
FMT_API void close();
|
void close();
|
||||||
|
|
||||||
// Returns the file size. The size has signed type for consistency with
|
// Returns the file size. The size has signed type for consistency with
|
||||||
// stat::st_size.
|
// stat::st_size.
|
||||||
FMT_API long long size() const;
|
long long size() const;
|
||||||
|
|
||||||
// Attempts to read count bytes from the file into the specified buffer.
|
// Attempts to read count bytes from the file into the specified buffer.
|
||||||
FMT_API size_t read(void* buffer, size_t count);
|
size_t read(void* buffer, size_t count);
|
||||||
|
|
||||||
// Attempts to write count bytes from the specified buffer to the file.
|
// Attempts to write count bytes from the specified buffer to the file.
|
||||||
FMT_API size_t write(const void* buffer, size_t count);
|
size_t write(const void* buffer, size_t count);
|
||||||
|
|
||||||
// Duplicates a file descriptor with the dup function and returns
|
// Duplicates a file descriptor with the dup function and returns
|
||||||
// the duplicate as a file object.
|
// the duplicate as a file object.
|
||||||
FMT_API static file dup(int fd);
|
static file dup(int fd);
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||||
// necessary.
|
// necessary.
|
||||||
FMT_API void dup2(int fd);
|
void dup2(int fd);
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||||
// necessary.
|
// necessary.
|
||||||
FMT_API void dup2(int fd, std::error_code& ec) FMT_NOEXCEPT;
|
void dup2(int fd, std::error_code& ec) noexcept;
|
||||||
|
|
||||||
// Creates a pipe setting up read_end and write_end file objects for reading
|
// Creates a pipe setting up read_end and write_end file objects for reading
|
||||||
// and writing respectively.
|
// and writing respectively.
|
||||||
FMT_API static void pipe(file& read_end, file& write_end);
|
static void pipe(file& read_end, file& write_end);
|
||||||
|
|
||||||
// Creates a buffered_file object associated with this file and detaches
|
// Creates a buffered_file object associated with this file and detaches
|
||||||
// this file object from the file.
|
// this file object from the file.
|
||||||
FMT_API buffered_file fdopen(const char* mode);
|
buffered_file fdopen(const char* mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the memory page size.
|
// Returns the memory page size.
|
||||||
|
@ -462,7 +460,7 @@ class FMT_API ostream final : private detail::buffer<char> {
|
||||||
|
|
||||||
* ``<integer>``: Flags passed to `open
|
* ``<integer>``: Flags passed to `open
|
||||||
<https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_
|
<https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_
|
||||||
(``file::WRONLY | file::CREATE`` by default)
|
(``file::WRONLY | file::CREATE | file::TRUNC`` by default)
|
||||||
* ``buffer_size=<integer>``: Output buffer size
|
* ``buffer_size=<integer>``: Output buffer size
|
||||||
|
|
||||||
**Example**::
|
**Example**::
|
||||||
|
@ -477,50 +475,6 @@ inline ostream output_file(cstring_view path, T... params) {
|
||||||
}
|
}
|
||||||
#endif // FMT_USE_FCNTL
|
#endif // FMT_USE_FCNTL
|
||||||
|
|
||||||
#ifdef FMT_LOCALE
|
|
||||||
// A "C" numeric locale.
|
|
||||||
class locale {
|
|
||||||
private:
|
|
||||||
# ifdef _WIN32
|
|
||||||
using locale_t = _locale_t;
|
|
||||||
|
|
||||||
static void freelocale(locale_t loc) { _free_locale(loc); }
|
|
||||||
|
|
||||||
static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
|
|
||||||
return _strtod_l(nptr, endptr, loc);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
locale_t locale_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = locale_t;
|
|
||||||
locale(const locale&) = delete;
|
|
||||||
void operator=(const locale&) = delete;
|
|
||||||
|
|
||||||
locale() {
|
|
||||||
# ifndef _WIN32
|
|
||||||
locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
|
|
||||||
# else
|
|
||||||
locale_ = _create_locale(LC_NUMERIC, "C");
|
|
||||||
# endif
|
|
||||||
if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
|
|
||||||
}
|
|
||||||
~locale() { freelocale(locale_); }
|
|
||||||
|
|
||||||
type get() const { return locale_; }
|
|
||||||
|
|
||||||
// Converts string to floating-point number and advances str past the end
|
|
||||||
// of the parsed input.
|
|
||||||
FMT_DEPRECATED double strtod(const char*& str) const {
|
|
||||||
char* end = nullptr;
|
|
||||||
double result = strtod_l(str, &end, locale_);
|
|
||||||
str = end;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using Locale FMT_DEPRECATED_ALIAS = locale;
|
|
||||||
#endif // FMT_LOCALE
|
|
||||||
FMT_MODULE_EXPORT_END
|
FMT_MODULE_EXPORT_END
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef FMT_OSTREAM_H_
|
#ifndef FMT_OSTREAM_H_
|
||||||
#define FMT_OSTREAM_H_
|
#define FMT_OSTREAM_H_
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
@ -45,15 +46,57 @@ struct is_streamable<
|
||||||
enable_if_t<
|
enable_if_t<
|
||||||
std::is_arithmetic<T>::value || std::is_array<T>::value ||
|
std::is_arithmetic<T>::value || std::is_array<T>::value ||
|
||||||
std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
|
std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
|
||||||
std::is_same<T, std::basic_string<Char>>::value ||
|
std::is_convertible<T, fmt::basic_string_view<Char>>::value ||
|
||||||
std::is_same<T, std_string_view<Char>>::value ||
|
std::is_same<T, std_string_view<Char>>::value ||
|
||||||
(std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
|
(std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
|
||||||
: std::false_type {};
|
: std::false_type {};
|
||||||
|
|
||||||
|
template <typename Char> FILE* get_file(std::basic_filebuf<Char>&) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dummy_filebuf {
|
||||||
|
FILE* _Myfile;
|
||||||
|
};
|
||||||
|
template <typename T, typename U = int> struct ms_filebuf {
|
||||||
|
using type = dummy_filebuf;
|
||||||
|
};
|
||||||
|
template <typename T> struct ms_filebuf<T, decltype(T::_Myfile, 0)> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
using filebuf_type = ms_filebuf<std::filebuf>::type;
|
||||||
|
|
||||||
|
FILE* get_file(filebuf_type& buf);
|
||||||
|
|
||||||
|
// Generate a unique explicit instantion in every translation unit using a tag
|
||||||
|
// type in an anonymous namespace.
|
||||||
|
namespace {
|
||||||
|
struct filebuf_access_tag {};
|
||||||
|
} // namespace
|
||||||
|
template <typename Tag, typename FileMemberPtr, FileMemberPtr file>
|
||||||
|
class filebuf_access {
|
||||||
|
friend FILE* get_file(filebuf_type& buf) { return buf.*file; }
|
||||||
|
};
|
||||||
|
template class filebuf_access<filebuf_access_tag,
|
||||||
|
decltype(&filebuf_type::_Myfile),
|
||||||
|
&filebuf_type::_Myfile>;
|
||||||
|
|
||||||
|
inline bool write(std::filebuf& buf, fmt::string_view data) {
|
||||||
|
print(get_file(buf), data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Write the content of buf to os.
|
// Write the content of buf to os.
|
||||||
// It is a separate function rather than a part of vprint to simplify testing.
|
// It is a separate function rather than a part of vprint to simplify testing.
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
||||||
|
if (const_check(FMT_MSC_VER)) {
|
||||||
|
auto filebuf = dynamic_cast<std::basic_filebuf<Char>*>(os.rdbuf());
|
||||||
|
if (filebuf && write(*filebuf, {buf.data(), buf.size()})) return;
|
||||||
|
}
|
||||||
const Char* buf_data = buf.data();
|
const Char* buf_data = buf.data();
|
||||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||||
unsigned_streamsize size = buf.size();
|
unsigned_streamsize size = buf.size();
|
||||||
|
@ -76,27 +119,34 @@ void format_value(buffer<Char>& buf, const T& value,
|
||||||
#endif
|
#endif
|
||||||
output << value;
|
output << value;
|
||||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
buf.try_resize(buf.size());
|
|
||||||
}
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||||
template <typename T, typename Char>
|
template <typename Char>
|
||||||
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
|
||||||
: private formatter<basic_string_view<Char>, Char> {
|
template <typename T, typename OutputIt>
|
||||||
using formatter<basic_string_view<Char>, Char>::parse;
|
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
|
||||||
|
|
||||||
template <typename OutputIt>
|
|
||||||
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
|
|
||||||
-> OutputIt {
|
-> OutputIt {
|
||||||
auto buffer = basic_memory_buffer<Char>();
|
auto buffer = basic_memory_buffer<Char>();
|
||||||
format_value(buffer, value, ctx.locale());
|
format_value(buffer, value, ctx.locale());
|
||||||
return formatter<basic_string_view<Char>, Char>::format(
|
return formatter<basic_string_view<Char>, Char>::format(
|
||||||
{buffer.data(), buffer.size()}, ctx);
|
{buffer.data(), buffer.size()}, ctx);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ostream_formatter = basic_ostream_formatter<char>;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
||||||
|
: basic_ostream_formatter<Char> {
|
||||||
|
using basic_ostream_formatter<Char>::format;
|
||||||
// DEPRECATED!
|
// DEPRECATED!
|
||||||
template <typename OutputIt>
|
template <typename OutputIt>
|
||||||
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
|
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) const
|
||||||
-> OutputIt {
|
-> OutputIt {
|
||||||
auto buffer = basic_memory_buffer<Char>();
|
auto buffer = basic_memory_buffer<Char>();
|
||||||
format_value(buffer, value, ctx.locale());
|
format_value(buffer, value, ctx.locale());
|
||||||
|
@ -107,7 +157,8 @@ struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
||||||
|
|
||||||
FMT_MODULE_EXPORT
|
FMT_MODULE_EXPORT
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
void vprint(std::basic_ostream<Char>& os,
|
||||||
|
basic_string_view<type_identity_t<Char>> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
auto buffer = basic_memory_buffer<Char>();
|
auto buffer = basic_memory_buffer<Char>();
|
||||||
detail::vformat_to(buffer, format_str, args);
|
detail::vformat_to(buffer, format_str, args);
|
||||||
|
@ -124,12 +175,19 @@ void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
FMT_MODULE_EXPORT
|
FMT_MODULE_EXPORT
|
||||||
template <typename S, typename... Args,
|
template <typename... T>
|
||||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
||||||
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
vprint(os, fmt, fmt::make_format_args(args...));
|
||||||
vprint(os, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename... Args>
|
||||||
|
void print(std::wostream& os,
|
||||||
|
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
|
||||||
|
Args&&... args) {
|
||||||
|
vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // FMT_OSTREAM_H_
|
#endif // FMT_OSTREAM_H_
|
||||||
|
|
|
@ -203,7 +203,7 @@ using make_index_sequence = make_integer_sequence<size_t, N>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class Tuple, class F, size_t... Is>
|
template <class Tuple, class F, size_t... Is>
|
||||||
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
|
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
|
||||||
using std::get;
|
using std::get;
|
||||||
// using free function get<I>(T) now.
|
// using free function get<I>(T) now.
|
||||||
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
||||||
|
@ -221,9 +221,28 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
||||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FMT_MSC_VER
|
||||||
|
// Older MSVC doesn't get the reference type correctly for arrays.
|
||||||
|
template <typename R> struct range_reference_type_impl {
|
||||||
|
using type = decltype(*detail::range_begin(std::declval<R&>()));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
|
||||||
|
using type = T&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using range_reference_type = typename range_reference_type_impl<T>::type;
|
||||||
|
#else
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
using value_type =
|
using range_reference_type =
|
||||||
remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>;
|
decltype(*detail::range_begin(std::declval<Range&>()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We don't use the Range's value_type for anything, but we do need the Range's
|
||||||
|
// reference type, with cv-ref stripped.
|
||||||
|
template <typename Range>
|
||||||
|
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
|
||||||
|
|
||||||
template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
|
template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
|
||||||
*out++ = ',';
|
*out++ = ',';
|
||||||
|
@ -231,286 +250,9 @@ template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct singleton {
|
|
||||||
unsigned char upper;
|
|
||||||
unsigned char lower_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline auto is_printable(uint16_t x, const singleton* singletons,
|
|
||||||
size_t singletons_size,
|
|
||||||
const unsigned char* singleton_lowers,
|
|
||||||
const unsigned char* normal, size_t normal_size)
|
|
||||||
-> bool {
|
|
||||||
auto upper = x >> 8;
|
|
||||||
auto lower_start = 0;
|
|
||||||
for (size_t i = 0; i < singletons_size; ++i) {
|
|
||||||
auto s = singletons[i];
|
|
||||||
auto lower_end = lower_start + s.lower_count;
|
|
||||||
if (upper < s.upper) break;
|
|
||||||
if (upper == s.upper) {
|
|
||||||
for (auto j = lower_start; j < lower_end; ++j) {
|
|
||||||
if (singleton_lowers[j] == (x & 0xff)) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lower_start = lower_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto xsigned = static_cast<int>(x);
|
|
||||||
auto current = true;
|
|
||||||
for (size_t i = 0; i < normal_size; ++i) {
|
|
||||||
auto v = static_cast<int>(normal[i]);
|
|
||||||
auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;
|
|
||||||
xsigned -= len;
|
|
||||||
if (xsigned < 0) break;
|
|
||||||
current = !current;
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true iff the code point cp is printable.
|
|
||||||
// This code is generated by support/printable.py.
|
|
||||||
inline auto is_printable(uint32_t cp) -> bool {
|
|
||||||
static constexpr singleton singletons0[] = {
|
|
||||||
{0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8},
|
|
||||||
{0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},
|
|
||||||
{0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5},
|
|
||||||
{0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22},
|
|
||||||
{0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3},
|
|
||||||
{0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8},
|
|
||||||
{0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9},
|
|
||||||
};
|
|
||||||
static constexpr unsigned char singletons0_lower[] = {
|
|
||||||
0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,
|
|
||||||
0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,
|
|
||||||
0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,
|
|
||||||
0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,
|
|
||||||
0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,
|
|
||||||
0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,
|
|
||||||
0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
|
|
||||||
0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
|
|
||||||
0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,
|
|
||||||
0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
|
|
||||||
0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
|
|
||||||
0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
|
|
||||||
0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
|
|
||||||
0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
|
|
||||||
0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
|
|
||||||
0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
|
|
||||||
0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,
|
|
||||||
0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
|
|
||||||
0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,
|
|
||||||
0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
|
|
||||||
0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,
|
|
||||||
0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
|
|
||||||
0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,
|
|
||||||
0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
|
|
||||||
0xfe, 0xff,
|
|
||||||
};
|
|
||||||
static constexpr singleton singletons1[] = {
|
|
||||||
{0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2},
|
|
||||||
{0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5},
|
|
||||||
{0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5},
|
|
||||||
{0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2},
|
|
||||||
{0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5},
|
|
||||||
{0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2},
|
|
||||||
{0xfa, 2}, {0xfb, 1},
|
|
||||||
};
|
|
||||||
static constexpr unsigned char singletons1_lower[] = {
|
|
||||||
0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,
|
|
||||||
0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
|
|
||||||
0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,
|
|
||||||
0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
|
|
||||||
0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,
|
|
||||||
0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
|
|
||||||
0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,
|
|
||||||
0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
|
|
||||||
0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,
|
|
||||||
0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
|
|
||||||
0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,
|
|
||||||
0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
|
|
||||||
0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
|
|
||||||
0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
|
|
||||||
0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
|
|
||||||
};
|
|
||||||
static constexpr unsigned char normal0[] = {
|
|
||||||
0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,
|
|
||||||
0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,
|
|
||||||
0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,
|
|
||||||
0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,
|
|
||||||
0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,
|
|
||||||
0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,
|
|
||||||
0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,
|
|
||||||
0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,
|
|
||||||
0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,
|
|
||||||
0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,
|
|
||||||
0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,
|
|
||||||
0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,
|
|
||||||
0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,
|
|
||||||
0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,
|
|
||||||
0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,
|
|
||||||
0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,
|
|
||||||
0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,
|
|
||||||
0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,
|
|
||||||
0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,
|
|
||||||
0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,
|
|
||||||
0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,
|
|
||||||
0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,
|
|
||||||
0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,
|
|
||||||
0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,
|
|
||||||
0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,
|
|
||||||
0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,
|
|
||||||
};
|
|
||||||
static constexpr unsigned char normal1[] = {
|
|
||||||
0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,
|
|
||||||
0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,
|
|
||||||
0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,
|
|
||||||
0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,
|
|
||||||
0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,
|
|
||||||
0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,
|
|
||||||
0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,
|
|
||||||
0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,
|
|
||||||
0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,
|
|
||||||
0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,
|
|
||||||
0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,
|
|
||||||
0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,
|
|
||||||
0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,
|
|
||||||
0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,
|
|
||||||
0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,
|
|
||||||
0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,
|
|
||||||
0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,
|
|
||||||
0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,
|
|
||||||
0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,
|
|
||||||
0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,
|
|
||||||
0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,
|
|
||||||
0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,
|
|
||||||
0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,
|
|
||||||
0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,
|
|
||||||
0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,
|
|
||||||
0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,
|
|
||||||
0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,
|
|
||||||
0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,
|
|
||||||
0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,
|
|
||||||
0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,
|
|
||||||
0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,
|
|
||||||
0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,
|
|
||||||
0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,
|
|
||||||
0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,
|
|
||||||
0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,
|
|
||||||
};
|
|
||||||
auto lower = static_cast<uint16_t>(cp);
|
|
||||||
if (cp < 0x10000) {
|
|
||||||
return is_printable(lower, singletons0,
|
|
||||||
sizeof(singletons0) / sizeof(*singletons0),
|
|
||||||
singletons0_lower, normal0, sizeof(normal0));
|
|
||||||
}
|
|
||||||
if (cp < 0x20000) {
|
|
||||||
return is_printable(lower, singletons1,
|
|
||||||
sizeof(singletons1) / sizeof(*singletons1),
|
|
||||||
singletons1_lower, normal1, sizeof(normal1));
|
|
||||||
}
|
|
||||||
if (0x2a6de <= cp && cp < 0x2a700) return false;
|
|
||||||
if (0x2b735 <= cp && cp < 0x2b740) return false;
|
|
||||||
if (0x2b81e <= cp && cp < 0x2b820) return false;
|
|
||||||
if (0x2cea2 <= cp && cp < 0x2ceb0) return false;
|
|
||||||
if (0x2ebe1 <= cp && cp < 0x2f800) return false;
|
|
||||||
if (0x2fa1e <= cp && cp < 0x30000) return false;
|
|
||||||
if (0x3134b <= cp && cp < 0xe0100) return false;
|
|
||||||
if (0xe01f0 <= cp && cp < 0x110000) return false;
|
|
||||||
return cp < 0x110000;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto needs_escape(uint32_t cp) -> bool {
|
|
||||||
return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
|
|
||||||
!is_printable(cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char> struct find_escape_result {
|
|
||||||
const Char* begin;
|
|
||||||
const Char* end;
|
|
||||||
uint32_t cp;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
auto find_escape(const Char* begin, const Char* end)
|
|
||||||
-> find_escape_result<Char> {
|
|
||||||
for (; begin != end; ++begin) {
|
|
||||||
auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin);
|
|
||||||
if (sizeof(Char) == 1 && cp >= 0x80) continue;
|
|
||||||
if (needs_escape(cp)) return {begin, begin + 1, cp};
|
|
||||||
}
|
|
||||||
return {begin, nullptr, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto find_escape(const char* begin, const char* end)
|
|
||||||
-> find_escape_result<char> {
|
|
||||||
if (!is_utf8()) return find_escape<char>(begin, end);
|
|
||||||
auto result = find_escape_result<char>{end, nullptr, 0};
|
|
||||||
for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
|
|
||||||
[&](uint32_t cp, string_view sv) {
|
|
||||||
if (needs_escape(cp)) {
|
|
||||||
result = {sv.begin(), sv.end(), cp};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
|
auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
|
||||||
*out++ = '"';
|
return write_escaped_string(out, str);
|
||||||
auto begin = str.begin(), end = str.end();
|
|
||||||
do {
|
|
||||||
auto escape = find_escape(begin, end);
|
|
||||||
out = copy_str<Char>(begin, escape.begin, out);
|
|
||||||
begin = escape.end;
|
|
||||||
if (!begin) break;
|
|
||||||
auto c = static_cast<Char>(escape.cp);
|
|
||||||
switch (escape.cp) {
|
|
||||||
case '\n':
|
|
||||||
*out++ = '\\';
|
|
||||||
c = 'n';
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
*out++ = '\\';
|
|
||||||
c = 'r';
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
*out++ = '\\';
|
|
||||||
c = 't';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
FMT_FALLTHROUGH;
|
|
||||||
case '\\':
|
|
||||||
*out++ = '\\';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (is_utf8()) {
|
|
||||||
if (escape.cp < 0x100) {
|
|
||||||
out = format_to(out, "\\x{:02x}", escape.cp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (escape.cp < 0x10000) {
|
|
||||||
out = format_to(out, "\\u{:04x}", escape.cp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (escape.cp < 0x110000) {
|
|
||||||
out = format_to(out, "\\U{:08x}", escape.cp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Char escape_char : basic_string_view<Char>(
|
|
||||||
escape.begin, to_unsigned(escape.end - escape.begin))) {
|
|
||||||
out = format_to(
|
|
||||||
out, "\\x{:02x}",
|
|
||||||
static_cast<typename std::make_unsigned<Char>::type>(escape_char));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*out++ = c;
|
|
||||||
} while (begin != end);
|
|
||||||
*out++ = '"';
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename OutputIt, typename T,
|
template <typename Char, typename OutputIt, typename T,
|
||||||
|
@ -523,10 +265,7 @@ inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
|
||||||
template <typename Char, typename OutputIt, typename Arg,
|
template <typename Char, typename OutputIt, typename Arg,
|
||||||
FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
|
FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
|
||||||
OutputIt write_range_entry(OutputIt out, const Arg v) {
|
OutputIt write_range_entry(OutputIt out, const Arg v) {
|
||||||
*out++ = '\'';
|
return write_escaped_char(out, v);
|
||||||
*out++ = v;
|
|
||||||
*out++ = '\'';
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
@ -565,7 +304,8 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext = format_context>
|
template <typename FormatContext = format_context>
|
||||||
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const TupleT& values, FormatContext& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
auto out = ctx.out();
|
auto out = ctx.out();
|
||||||
*out++ = '(';
|
*out++ = '(';
|
||||||
detail::for_each(values, format_each<FormatContext>{0, out});
|
detail::for_each(values, format_each<FormatContext>{0, out});
|
||||||
|
@ -582,43 +322,96 @@ template <typename T, typename Char> struct is_range {
|
||||||
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Char>
|
namespace detail {
|
||||||
|
template <typename Context> struct range_mapper {
|
||||||
|
using mapper = arg_mapper<Context>;
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||||
|
static auto map(T&& value) -> T&& {
|
||||||
|
return static_cast<T&&>(value);
|
||||||
|
}
|
||||||
|
template <typename T,
|
||||||
|
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||||
|
static auto map(T&& value)
|
||||||
|
-> decltype(mapper().map(static_cast<T&&>(value))) {
|
||||||
|
return mapper().map(static_cast<T&&>(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Char, typename Element>
|
||||||
|
using range_formatter_type = conditional_t<
|
||||||
|
is_formattable<Element, Char>::value,
|
||||||
|
formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
|
||||||
|
std::declval<Element>()))>,
|
||||||
|
Char>,
|
||||||
|
fallback_formatter<Element, Char>>;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
using maybe_const_range =
|
||||||
|
conditional_t<has_const_begin_end<R>::value, const R, R>;
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename R, typename Char>
|
||||||
struct formatter<
|
struct formatter<
|
||||||
T, Char,
|
R, Char,
|
||||||
enable_if_t<
|
enable_if_t<
|
||||||
fmt::is_range<T, Char>::value
|
fmt::is_range<R, Char>::value
|
||||||
// Workaround a bug in MSVC 2019 and earlier.
|
// Workaround a bug in MSVC 2019 and earlier.
|
||||||
#if !FMT_MSC_VER
|
#if !FMT_MSC_VER
|
||||||
&& (is_formattable<detail::value_type<T>, Char>::value ||
|
&&
|
||||||
detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
|
(is_formattable<detail::uncvref_type<detail::maybe_const_range<R>>,
|
||||||
|
Char>::value ||
|
||||||
|
detail::has_fallback_formatter<
|
||||||
|
detail::uncvref_type<detail::maybe_const_range<R>>, Char>::value)
|
||||||
#endif
|
#endif
|
||||||
>> {
|
>> {
|
||||||
|
|
||||||
|
using range_type = detail::maybe_const_range<R>;
|
||||||
|
using formatter_type =
|
||||||
|
detail::range_formatter_type<Char, detail::uncvref_type<range_type>>;
|
||||||
|
formatter_type underlying_;
|
||||||
|
bool custom_specs_ = false;
|
||||||
|
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
return ctx.begin();
|
auto it = ctx.begin();
|
||||||
|
auto end = ctx.end();
|
||||||
|
if (it == end || *it == '}') return it;
|
||||||
|
|
||||||
|
if (*it != ':')
|
||||||
|
FMT_THROW(format_error("no top-level range formatters supported"));
|
||||||
|
|
||||||
|
custom_specs_ = true;
|
||||||
|
++it;
|
||||||
|
ctx.advance_to(it);
|
||||||
|
return underlying_.parse(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <typename FormatContext>
|
||||||
typename FormatContext, typename U,
|
auto format(range_type& range, FormatContext& ctx) const
|
||||||
FMT_ENABLE_IF(
|
-> decltype(ctx.out()) {
|
||||||
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
|
|
||||||
const T, T>>::value)>
|
|
||||||
auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {
|
|
||||||
#ifdef FMT_DEPRECATED_BRACED_RANGES
|
#ifdef FMT_DEPRECATED_BRACED_RANGES
|
||||||
Char prefix = '{';
|
Char prefix = '{';
|
||||||
Char postfix = '}';
|
Char postfix = '}';
|
||||||
#else
|
#else
|
||||||
Char prefix = detail::is_set<T>::value ? '{' : '[';
|
Char prefix = detail::is_set<R>::value ? '{' : '[';
|
||||||
Char postfix = detail::is_set<T>::value ? '}' : ']';
|
Char postfix = detail::is_set<R>::value ? '}' : ']';
|
||||||
#endif
|
#endif
|
||||||
|
detail::range_mapper<buffer_context<Char>> mapper;
|
||||||
auto out = ctx.out();
|
auto out = ctx.out();
|
||||||
*out++ = prefix;
|
*out++ = prefix;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
auto it = std::begin(range);
|
auto it = detail::range_begin(range);
|
||||||
auto end = std::end(range);
|
auto end = detail::range_end(range);
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
if (i > 0) out = detail::write_delimiter(out);
|
if (i > 0) out = detail::write_delimiter(out);
|
||||||
out = detail::write_range_entry<Char>(out, *it);
|
if (custom_specs_) {
|
||||||
|
ctx.advance_to(out);
|
||||||
|
out = underlying_.format(mapper.map(*it), ctx);
|
||||||
|
} else {
|
||||||
|
out = detail::write_range_entry<Char>(out, *it);
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
*out++ = postfix;
|
*out++ = postfix;
|
||||||
|
@ -629,14 +422,14 @@ struct formatter<
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
struct formatter<
|
struct formatter<
|
||||||
T, Char,
|
T, Char,
|
||||||
enable_if_t<
|
enable_if_t<detail::is_map<T>::value
|
||||||
detail::is_map<T>::value
|
|
||||||
// Workaround a bug in MSVC 2019 and earlier.
|
// Workaround a bug in MSVC 2019 and earlier.
|
||||||
#if !FMT_MSC_VER
|
#if !FMT_MSC_VER
|
||||||
&& (is_formattable<detail::value_type<T>, Char>::value ||
|
&& (is_formattable<detail::uncvref_type<T>, Char>::value ||
|
||||||
detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
|
detail::has_fallback_formatter<detail::uncvref_type<T>,
|
||||||
|
Char>::value)
|
||||||
#endif
|
#endif
|
||||||
>> {
|
>> {
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
|
@ -647,7 +440,7 @@ struct formatter<
|
||||||
FMT_ENABLE_IF(
|
FMT_ENABLE_IF(
|
||||||
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
|
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
|
||||||
const T, T>>::value)>
|
const T, T>>::value)>
|
||||||
auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(U& map, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||||
auto out = ctx.out();
|
auto out = ctx.out();
|
||||||
*out++ = '{';
|
*out++ = '{';
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
|
@ -92,8 +92,8 @@ auto vformat(basic_string_view<Char> format_str,
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||||
auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
|
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),
|
||||||
return vformat(to_string_view(format_str), vargs);
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Locale, typename S, typename Char = char_t<S>,
|
template <typename Locale, typename S, typename Char = char_t<S>,
|
||||||
|
@ -113,7 +113,7 @@ template <typename Locale, typename S, typename... Args,
|
||||||
inline auto format(const Locale& loc, const S& format_str, Args&&... args)
|
inline auto format(const Locale& loc, const S& format_str, Args&&... args)
|
||||||
-> std::basic_string<Char> {
|
-> std::basic_string<Char> {
|
||||||
return detail::vformat(loc, to_string_view(format_str),
|
return detail::vformat(loc, to_string_view(format_str),
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
||||||
|
@ -132,8 +132,8 @@ template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||||
detail::is_exotic_char<Char>::value)>
|
detail::is_exotic_char<Char>::value)>
|
||||||
inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
|
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),
|
||||||
return vformat_to(out, to_string_view(fmt), vargs);
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char, size_t SIZE,
|
template <typename S, typename... Args, typename Char, size_t SIZE,
|
||||||
|
@ -141,8 +141,8 @@ template <typename S, typename... Args, typename Char, size_t SIZE,
|
||||||
FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
|
FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
|
||||||
const S& format_str, Args&&... args) ->
|
const S& format_str, Args&&... args) ->
|
||||||
typename buffer_context<Char>::iterator {
|
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),
|
||||||
detail::vformat_to(buf, to_string_view(format_str), vargs, {});
|
fmt::make_format_args<buffer_context<Char>>(args...), {});
|
||||||
return detail::buffer_appender<Char>(buf);
|
return detail::buffer_appender<Char>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +167,8 @@ template <
|
||||||
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
|
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
|
||||||
Args&&... args) ->
|
Args&&... args) ->
|
||||||
typename std::enable_if<enable, OutputIt>::type {
|
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),
|
||||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename... Args,
|
template <typename OutputIt, typename Char, typename... Args,
|
||||||
|
@ -190,16 +190,16 @@ template <typename OutputIt, typename S, typename... Args,
|
||||||
detail::is_exotic_char<Char>::value)>
|
detail::is_exotic_char<Char>::value)>
|
||||||
inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
|
inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
|
||||||
const Args&... args) -> format_to_n_result<OutputIt> {
|
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),
|
||||||
return vformat_to_n(out, n, to_string_view(fmt), vargs);
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||||
inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
|
inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
|
||||||
detail::counting_buffer<Char> buf;
|
detail::counting_buffer<Char> buf;
|
||||||
const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
|
detail::vformat_to(buf, to_string_view(fmt),
|
||||||
detail::vformat_to(buf, to_string_view(fmt), vargs);
|
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||||
return buf.count();
|
return buf.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,24 +56,10 @@ constexpr const char basic_data<T>::right_padding_shifts[];
|
||||||
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
|
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(
|
||||||
int format_float(char* buf, std::size_t size, const char* format, int precision,
|
float x) noexcept;
|
||||||
T value) {
|
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(
|
||||||
#ifdef FMT_FUZZ
|
double x) noexcept;
|
||||||
if (precision > 100000)
|
|
||||||
throw std::runtime_error(
|
|
||||||
"fuzz mode - avoid large allocation inside snprintf");
|
|
||||||
#endif
|
|
||||||
// Suppress the warning about nonliteral format string.
|
|
||||||
int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
|
|
||||||
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
|
||||||
: snprintf_ptr(buf, size, format, precision, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
||||||
|
@ -100,11 +86,6 @@ template FMT_API void detail::vformat_to(
|
||||||
detail::buffer<char>&, string_view,
|
detail::buffer<char>&, string_view,
|
||||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
||||||
|
|
||||||
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
template FMT_API int detail::snprintf_float(long double, int,
|
|
||||||
detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
template FMT_API int detail::format_float(double, int, detail::float_specs,
|
template FMT_API int detail::format_float(double, int, detail::float_specs,
|
||||||
detail::buffer<char>&);
|
detail::buffer<char>&);
|
||||||
template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
||||||
|
|
|
@ -35,9 +35,15 @@
|
||||||
# ifndef S_IRGRP
|
# ifndef S_IRGRP
|
||||||
# define S_IRGRP 0
|
# define S_IRGRP 0
|
||||||
# endif
|
# endif
|
||||||
|
# ifndef S_IWGRP
|
||||||
|
# define S_IWGRP 0
|
||||||
|
# endif
|
||||||
# ifndef S_IROTH
|
# ifndef S_IROTH
|
||||||
# define S_IROTH 0
|
# define S_IROTH 0
|
||||||
# endif
|
# endif
|
||||||
|
# ifndef S_IWOTH
|
||||||
|
# define S_IWOTH 0
|
||||||
|
# endif
|
||||||
# endif // _WIN32
|
# endif // _WIN32
|
||||||
#endif // FMT_USE_FCNTL
|
#endif // FMT_USE_FCNTL
|
||||||
|
|
||||||
|
@ -107,7 +113,7 @@ class system_message {
|
||||||
unsigned long result_;
|
unsigned long result_;
|
||||||
wchar_t* message_;
|
wchar_t* message_;
|
||||||
|
|
||||||
static bool is_whitespace(wchar_t c) FMT_NOEXCEPT {
|
static bool is_whitespace(wchar_t c) noexcept {
|
||||||
return c == L' ' || c == L'\n' || c == L'\r' || c == L'\t' || c == L'\0';
|
return c == L' ' || c == L'\n' || c == L'\r' || c == L'\t' || c == L'\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,15 +132,15 @@ class system_message {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~system_message() { LocalFree(message_); }
|
~system_message() { LocalFree(message_); }
|
||||||
explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
|
explicit operator bool() const noexcept { return result_ != 0; }
|
||||||
operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
|
operator basic_string_view<wchar_t>() const noexcept {
|
||||||
return basic_string_view<wchar_t>(message_, result_);
|
return basic_string_view<wchar_t>(message_, result_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class utf8_system_category final : public std::error_category {
|
class utf8_system_category final : public std::error_category {
|
||||||
public:
|
public:
|
||||||
const char* name() const FMT_NOEXCEPT override { return "system"; }
|
const char* name() const noexcept override { return "system"; }
|
||||||
std::string message(int error_code) const override {
|
std::string message(int error_code) const override {
|
||||||
system_message msg(error_code);
|
system_message msg(error_code);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
@ -149,7 +155,7 @@ class utf8_system_category final : public std::error_category {
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
FMT_API const std::error_category& system_category() FMT_NOEXCEPT {
|
FMT_API const std::error_category& system_category() noexcept {
|
||||||
static const detail::utf8_system_category category;
|
static const detail::utf8_system_category category;
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +167,7 @@ std::system_error vwindows_error(int err_code, string_view format_str,
|
||||||
}
|
}
|
||||||
|
|
||||||
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||||
const char* message) FMT_NOEXCEPT {
|
const char* message) noexcept {
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
system_message msg(error_code);
|
system_message msg(error_code);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
@ -176,12 +182,12 @@ void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||||
format_error_code(out, error_code, message);
|
format_error_code(out, error_code, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void report_windows_error(int error_code, const char* message) FMT_NOEXCEPT {
|
void report_windows_error(int error_code, const char* message) noexcept {
|
||||||
report_error(detail::format_windows_error, error_code, message);
|
report_error(detail::format_windows_error, error_code, message);
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
buffered_file::~buffered_file() FMT_NOEXCEPT {
|
buffered_file::~buffered_file() noexcept {
|
||||||
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
||||||
report_system_error(errno, "cannot close file");
|
report_system_error(errno, "cannot close file");
|
||||||
}
|
}
|
||||||
|
@ -214,7 +220,8 @@ file::file(cstring_view path, int oflag) {
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
using mode_t = int;
|
using mode_t = int;
|
||||||
# endif
|
# endif
|
||||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
constexpr mode_t mode =
|
||||||
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||||
# if defined(_WIN32) && !defined(__MINGW32__)
|
# if defined(_WIN32) && !defined(__MINGW32__)
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
||||||
|
@ -225,7 +232,7 @@ file::file(cstring_view path, int oflag) {
|
||||||
FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
|
FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
file::~file() FMT_NOEXCEPT {
|
file::~file() noexcept {
|
||||||
// Don't retry close in case of EINTR!
|
// Don't retry close in case of EINTR!
|
||||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||||
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
||||||
|
@ -299,7 +306,7 @@ void file::dup2(int fd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::dup2(int fd, std::error_code& ec) FMT_NOEXCEPT {
|
void file::dup2(int fd, std::error_code& ec) noexcept {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||||
if (result == -1) ec = std::error_code(errno, std::generic_category());
|
if (result == -1) ec = std::error_code(errno, std::generic_category());
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
4.2.1
|
5.0.0
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
# C++14 feature support detection
|
# C++14 feature support detection
|
||||||
|
|
||||||
include(CheckCXXSourceCompiles)
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
function (fmt_check_cxx_compiler_flag flag result)
|
||||||
|
if (NOT MSVC)
|
||||||
|
check_cxx_compiler_flag("${flag}" ${result})
|
||||||
|
endif ()
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
if (NOT CMAKE_CXX_STANDARD)
|
if (NOT CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
@ -9,35 +13,38 @@ endif()
|
||||||
message(STATUS "CXX_STANDARD: ${CMAKE_CXX_STANDARD}")
|
message(STATUS "CXX_STANDARD: ${CMAKE_CXX_STANDARD}")
|
||||||
|
|
||||||
if (CMAKE_CXX_STANDARD EQUAL 20)
|
if (CMAKE_CXX_STANDARD EQUAL 20)
|
||||||
check_cxx_compiler_flag(-std=c++20 has_std_20_flag)
|
fmt_check_cxx_compiler_flag(-std=c++20 has_std_20_flag)
|
||||||
check_cxx_compiler_flag(-std=c++2a has_std_2a_flag)
|
fmt_check_cxx_compiler_flag(-std=c++2a has_std_2a_flag)
|
||||||
|
|
||||||
if (has_std_20_flag)
|
if (has_std_20_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++20)
|
set(CXX_STANDARD_FLAG -std=c++20)
|
||||||
elseif (has_std_2a_flag)
|
elseif (has_std_2a_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++2a)
|
set(CXX_STANDARD_FLAG -std=c++2a)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
elseif (CMAKE_CXX_STANDARD EQUAL 17)
|
elseif (CMAKE_CXX_STANDARD EQUAL 17)
|
||||||
check_cxx_compiler_flag(-std=c++17 has_std_17_flag)
|
fmt_check_cxx_compiler_flag(-std=c++17 has_std_17_flag)
|
||||||
check_cxx_compiler_flag(-std=c++1z has_std_1z_flag)
|
fmt_check_cxx_compiler_flag(-std=c++1z has_std_1z_flag)
|
||||||
|
|
||||||
if (has_std_17_flag)
|
if (has_std_17_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++17)
|
set(CXX_STANDARD_FLAG -std=c++17)
|
||||||
elseif (has_std_1z_flag)
|
elseif (has_std_1z_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++1z)
|
set(CXX_STANDARD_FLAG -std=c++1z)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
elseif (CMAKE_CXX_STANDARD EQUAL 14)
|
elseif (CMAKE_CXX_STANDARD EQUAL 14)
|
||||||
check_cxx_compiler_flag(-std=c++14 has_std_14_flag)
|
fmt_check_cxx_compiler_flag(-std=c++14 has_std_14_flag)
|
||||||
check_cxx_compiler_flag(-std=c++1y has_std_1y_flag)
|
fmt_check_cxx_compiler_flag(-std=c++1y has_std_1y_flag)
|
||||||
|
|
||||||
if (has_std_14_flag)
|
if (has_std_14_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++14)
|
set(CXX_STANDARD_FLAG -std=c++14)
|
||||||
elseif (has_std_1y_flag)
|
elseif (has_std_1y_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++1y)
|
set(CXX_STANDARD_FLAG -std=c++1y)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
elseif (CMAKE_CXX_STANDARD EQUAL 11)
|
elseif (CMAKE_CXX_STANDARD EQUAL 11)
|
||||||
check_cxx_compiler_flag(-std=c++11 has_std_11_flag)
|
fmt_check_cxx_compiler_flag(-std=c++11 has_std_11_flag)
|
||||||
check_cxx_compiler_flag(-std=c++0x has_std_0x_flag)
|
fmt_check_cxx_compiler_flag(-std=c++0x has_std_0x_flag)
|
||||||
|
|
||||||
if (has_std_11_flag)
|
if (has_std_11_flag)
|
||||||
set(CXX_STANDARD_FLAG -std=c++11)
|
set(CXX_STANDARD_FLAG -std=c++11)
|
||||||
|
@ -45,26 +52,3 @@ elseif (CMAKE_CXX_STANDARD EQUAL 11)
|
||||||
set(CXX_STANDARD_FLAG -std=c++0x)
|
set(CXX_STANDARD_FLAG -std=c++0x)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG})
|
|
||||||
|
|
||||||
# Check if user-defined literals are available
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
void operator\"\" _udl(long double);
|
|
||||||
int main() {}"
|
|
||||||
SUPPORTS_USER_DEFINED_LITERALS)
|
|
||||||
if (NOT SUPPORTS_USER_DEFINED_LITERALS)
|
|
||||||
set (SUPPORTS_USER_DEFINED_LITERALS OFF)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Check if <variant> is available
|
|
||||||
set(CMAKE_REQUIRED_FLAGS -std=c++1z)
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
#include <variant>
|
|
||||||
int main() {}"
|
|
||||||
FMT_HAS_VARIANT)
|
|
||||||
if (NOT FMT_HAS_VARIANT)
|
|
||||||
set (FMT_HAS_VARIANT OFF)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_FLAGS )
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ def main():
|
||||||
normal1 = compress_normal(normal1)
|
normal1 = compress_normal(normal1)
|
||||||
|
|
||||||
print("""\
|
print("""\
|
||||||
inline auto is_printable(uint32_t cp) -> bool {\
|
FMT_FUNC auto is_printable(uint32_t cp) -> bool {\
|
||||||
""")
|
""")
|
||||||
print_singletons(singletons0u, singletons0l, 'singletons0', 'singletons0_lower')
|
print_singletons(singletons0u, singletons0l, 'singletons0', 'singletons0_lower')
|
||||||
print_singletons(singletons1u, singletons1l, 'singletons1', 'singletons1_lower')
|
print_singletons(singletons1u, singletons1l, 'singletons1', 'singletons1_lower')
|
||||||
|
|
|
@ -94,8 +94,7 @@ void GenericLogFmt(LogLevel level, LogType type, const char* file, int line, con
|
||||||
static_assert(NumFields == sizeof...(args),
|
static_assert(NumFields == sizeof...(args),
|
||||||
"Unexpected number of replacement fields in format string; did you pass too few or "
|
"Unexpected number of replacement fields in format string; did you pass too few or "
|
||||||
"too many arguments?");
|
"too many arguments?");
|
||||||
GenericLogFmtImpl(level, type, file, line, format,
|
GenericLogFmtImpl(level, type, file, line, format, fmt::make_format_args(args...));
|
||||||
fmt::make_args_checked<Args...>(format, args...));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericLog(LogLevel level, LogType type, const char* file, int line, const char* fmt, ...)
|
void GenericLog(LogLevel level, LogType type, const char* file, int line, const char* fmt, ...)
|
||||||
|
|
|
@ -43,7 +43,7 @@ bool MsgAlertFmt(bool yes_no, MsgType style, Common::Log::LogType log_type, cons
|
||||||
"too many arguments?");
|
"too many arguments?");
|
||||||
static_assert(fmt::is_compile_string<S>::value);
|
static_assert(fmt::is_compile_string<S>::value);
|
||||||
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, format,
|
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, format,
|
||||||
fmt::make_args_checked<Args...>(format, args...));
|
fmt::make_format_args(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t NumFields, bool has_non_positional_args, typename S, typename... Args>
|
template <std::size_t NumFields, bool has_non_positional_args, typename S, typename... Args>
|
||||||
|
@ -57,12 +57,7 @@ bool MsgAlertFmtT(bool yes_no, MsgType style, Common::Log::LogType log_type, con
|
||||||
"Unexpected number of replacement fields in format string; did you pass too few or "
|
"Unexpected number of replacement fields in format string; did you pass too few or "
|
||||||
"too many arguments?");
|
"too many arguments?");
|
||||||
static_assert(fmt::is_compile_string<S>::value);
|
static_assert(fmt::is_compile_string<S>::value);
|
||||||
// It's only possible for us to compile-time check the English-language string.
|
auto arg_list = fmt::make_format_args(args...);
|
||||||
// make_args_checked uses static_asserts to verify that a string is formattable with the given
|
|
||||||
// arguments. But it can't do that if the string varies at runtime, so we can't check
|
|
||||||
// translations. Still, verifying that the English string is correct will help ensure that
|
|
||||||
// translations use valid strings.
|
|
||||||
auto arg_list = fmt::make_args_checked<Args...>(format, args...);
|
|
||||||
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, translated_format, arg_list);
|
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, translated_format, arg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)Settings;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)Settings;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)TAS;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)TAS;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)VideoInterface;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)VideoInterface;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<!--Ignore warnings in locally-instantiated fmt templates-->
|
|
||||||
<ExternalTemplatesDiagnostics>false</ExternalTemplatesDiagnostics>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Manifest>
|
<Manifest>
|
||||||
<AdditionalManifestFiles>DolphinQt.manifest;%(AdditionalManifestFiles)</AdditionalManifestFiles>
|
<AdditionalManifestFiles>DolphinQt.manifest;%(AdditionalManifestFiles)</AdditionalManifestFiles>
|
||||||
|
|
|
@ -1231,10 +1231,10 @@ struct fmt::formatter<ScissorPos>
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const ScissorPos& pos, FormatContext& ctx)
|
auto format(const ScissorPos& pos, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
return format_to(ctx.out(),
|
return fmt::format_to(ctx.out(),
|
||||||
"X: {} (raw: {})\n"
|
"X: {} (raw: {})\n"
|
||||||
"Y: {} (raw: {})",
|
"Y: {} (raw: {})",
|
||||||
pos.x - 342, pos.x_full, pos.y - 342, pos.y_full);
|
pos.x - 342, pos.x_full, pos.y - 342, pos.y_full);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1257,10 +1257,10 @@ struct fmt::formatter<ScissorOffset>
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const ScissorOffset& off, FormatContext& ctx)
|
auto format(const ScissorOffset& off, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
return format_to(ctx.out(),
|
return fmt::format_to(ctx.out(),
|
||||||
"X: {} (raw: {})\n"
|
"X: {} (raw: {})\n"
|
||||||
"Y: {} (raw: {})",
|
"Y: {} (raw: {})",
|
||||||
(off.x << 1) - 342, off.x_full, (off.y << 1) - 342, off.y_full);
|
(off.x << 1) - 342, off.x_full, (off.y << 1) - 342, off.y_full);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#define STRINGIFY_HELPER(x) #x
|
#define STRINGIFY_HELPER(x) #x
|
||||||
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
||||||
|
|
||||||
#if defined _MSC_FULL_VER && _MSC_FULL_VER < 193030705
|
#if defined _MSC_FULL_VER && _MSC_FULL_VER < 193231328
|
||||||
#pragma message("Current _MSC_FULL_VER: " STRINGIFY(_MSC_FULL_VER))
|
#pragma message("Current _MSC_FULL_VER: " STRINGIFY(_MSC_FULL_VER))
|
||||||
#error Please update your build environment to the latest Visual Studio 2022!
|
#error Please update your build environment to the latest Visual Studio 2022!
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue