mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-17 23:57:14 +02:00
Update cpp fmt library.
This commit is contained in:
312
vendor/Fmt/include/fmt/chrono.h
vendored
312
vendor/Fmt/include/fmt/chrono.h
vendored
@ -15,7 +15,6 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "format.h"
|
||||
#include "locale.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
@ -283,12 +282,84 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
#define FMT_NOMACRO
|
||||
|
||||
namespace detail {
|
||||
template <typename T = void> struct null {};
|
||||
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
|
||||
inline null<> localtime_s(...) { return null<>(); }
|
||||
inline null<> gmtime_r(...) { return null<>(); }
|
||||
inline null<> gmtime_s(...) { return null<>(); }
|
||||
|
||||
inline auto do_write(const std::tm& time, const std::locale& loc, char format,
|
||||
char modifier) -> std::string {
|
||||
auto&& os = std::ostringstream();
|
||||
os.imbue(loc);
|
||||
using iterator = std::ostreambuf_iterator<char>;
|
||||
const auto& facet = std::use_facet<std::time_put<char, iterator>>(loc);
|
||||
auto end = facet.put(os, os, ' ', &time, format, modifier);
|
||||
if (end.failed()) FMT_THROW(format_error("failed to format time"));
|
||||
auto str = os.str();
|
||||
if (!detail::is_utf8() || loc == std::locale::classic()) return str;
|
||||
// char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
|
||||
// gcc-4.
|
||||
#if FMT_MSC_VER != 0 || \
|
||||
(defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
|
||||
// The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
|
||||
// and newer.
|
||||
using code_unit = wchar_t;
|
||||
#else
|
||||
using code_unit = char32_t;
|
||||
#endif
|
||||
auto& f = std::use_facet<std::codecvt<code_unit, char, std::mbstate_t>>(loc);
|
||||
auto mb = std::mbstate_t();
|
||||
const char* from_next = nullptr;
|
||||
code_unit* to_next = nullptr;
|
||||
constexpr size_t buf_size = 32;
|
||||
code_unit buf[buf_size] = {};
|
||||
auto result = f.in(mb, str.data(), str.data() + str.size(), from_next, buf,
|
||||
buf + buf_size, to_next);
|
||||
if (result != std::codecvt_base::ok)
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
str.clear();
|
||||
for (code_unit* p = buf; p != to_next; ++p) {
|
||||
uint32_t c = static_cast<uint32_t>(*p);
|
||||
if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) {
|
||||
// surrogate pair
|
||||
++p;
|
||||
if (p == to_next || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
}
|
||||
c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
|
||||
}
|
||||
if (c < 0x80) {
|
||||
str.push_back(static_cast<char>(c));
|
||||
} else if (c < 0x800) {
|
||||
str.push_back(static_cast<char>(0xc0 | (c >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
|
||||
str.push_back(static_cast<char>(0xe0 | (c >> 12)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else if (c >= 0x10000 && c <= 0x10ffff) {
|
||||
str.push_back(static_cast<char>(0xf0 | (c >> 18)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
|
||||
str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
|
||||
str.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else {
|
||||
FMT_THROW(format_error("failed to format time"));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename OutputIt>
|
||||
auto write(OutputIt out, const std::tm& time, const std::locale& loc,
|
||||
char format, char modifier = 0) -> OutputIt {
|
||||
auto str = do_write(time, loc, format, modifier);
|
||||
return std::copy(str.begin(), str.end(), out);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
/**
|
||||
Converts given time since epoch as ``std::time_t`` value into calendar time,
|
||||
expressed in local time. Unlike ``std::localtime``, this function is
|
||||
@ -380,7 +451,8 @@ inline std::tm gmtime(
|
||||
return gmtime(std::chrono::system_clock::to_time_t(time_point));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
inline size_t strftime(char* str, size_t count, const char* format,
|
||||
const std::tm* time) {
|
||||
// Assign to a pointer to suppress GCCs -Wformat-nonliteral
|
||||
@ -399,19 +471,43 @@ inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format,
|
||||
wcsftime = std::wcsftime;
|
||||
return wcsftime(str, count, format, time);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char>
|
||||
: formatter<std::tm, Char> {
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
template <typename Char, typename Duration>
|
||||
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char> : formatter<std::tm, Char> {
|
||||
FMT_CONSTEXPR formatter() {
|
||||
this->specs = {default_specs, sizeof(default_specs) / sizeof(Char)};
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it == ':') ++it;
|
||||
auto end = it;
|
||||
while (end != ctx.end() && *end != '}') ++end;
|
||||
if (end != it) this->specs = {it, detail::to_unsigned(end - it)};
|
||||
return end;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(std::chrono::time_point<std::chrono::system_clock> val,
|
||||
FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
std::tm time = localtime(val);
|
||||
return formatter<std::tm, Char>::format(time, ctx);
|
||||
}
|
||||
|
||||
static constexpr Char default_specs[] = {'%', 'Y', '-', '%', 'm', '-',
|
||||
'%', 'd', ' ', '%', 'H', ':',
|
||||
'%', 'M', ':', '%', 'S'};
|
||||
};
|
||||
|
||||
template <typename Char, typename Duration>
|
||||
constexpr Char
|
||||
formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char>::default_specs[];
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
@ -428,6 +524,10 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
-> decltype(ctx.out()) {
|
||||
basic_memory_buffer<Char> tm_format;
|
||||
tm_format.append(specs.begin(), specs.end());
|
||||
// By appending an extra space we can distinguish an empty result that
|
||||
// indicates insufficient buffer size from a guaranteed non-empty result
|
||||
// https://github.com/fmtlib/fmt/issues/2238
|
||||
tm_format.push_back(' ');
|
||||
tm_format.push_back('\0');
|
||||
basic_memory_buffer<Char> buf;
|
||||
size_t start = buf.size();
|
||||
@ -438,83 +538,40 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
buf.resize(start + count);
|
||||
break;
|
||||
}
|
||||
if (size >= tm_format.size() * 256) {
|
||||
// If the buffer is 256 times larger than the format string, assume
|
||||
// that `strftime` gives an empty result. There doesn't seem to be a
|
||||
// better way to distinguish the two cases:
|
||||
// https://github.com/fmtlib/fmt/issues/367
|
||||
break;
|
||||
}
|
||||
const size_t MIN_GROWTH = 10;
|
||||
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
|
||||
}
|
||||
return std::copy(buf.begin(), buf.end(), ctx.out());
|
||||
// Remove the extra space.
|
||||
return std::copy(buf.begin(), buf.end() - 1, ctx.out());
|
||||
}
|
||||
|
||||
basic_string_view<Char> specs;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename Period> FMT_CONSTEXPR const char* get_units() {
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
template <typename Period> FMT_CONSTEXPR inline const char* get_units() {
|
||||
if (std::is_same<Period, std::atto>::value) return "as";
|
||||
if (std::is_same<Period, std::femto>::value) return "fs";
|
||||
if (std::is_same<Period, std::pico>::value) return "ps";
|
||||
if (std::is_same<Period, std::nano>::value) return "ns";
|
||||
if (std::is_same<Period, std::micro>::value) return "µs";
|
||||
if (std::is_same<Period, std::milli>::value) return "ms";
|
||||
if (std::is_same<Period, std::centi>::value) return "cs";
|
||||
if (std::is_same<Period, std::deci>::value) return "ds";
|
||||
if (std::is_same<Period, std::ratio<1>>::value) return "s";
|
||||
if (std::is_same<Period, std::deca>::value) return "das";
|
||||
if (std::is_same<Period, std::hecto>::value) return "hs";
|
||||
if (std::is_same<Period, std::kilo>::value) return "ks";
|
||||
if (std::is_same<Period, std::mega>::value) return "Ms";
|
||||
if (std::is_same<Period, std::giga>::value) return "Gs";
|
||||
if (std::is_same<Period, std::tera>::value) return "Ts";
|
||||
if (std::is_same<Period, std::peta>::value) return "Ps";
|
||||
if (std::is_same<Period, std::exa>::value) return "Es";
|
||||
if (std::is_same<Period, std::ratio<60>>::value) return "m";
|
||||
if (std::is_same<Period, std::ratio<3600>>::value) return "h";
|
||||
return nullptr;
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::atto>() {
|
||||
return "as";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::femto>() {
|
||||
return "fs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::pico>() {
|
||||
return "ps";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::nano>() {
|
||||
return "ns";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::micro>() {
|
||||
return "µs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::milli>() {
|
||||
return "ms";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::centi>() {
|
||||
return "cs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::deci>() {
|
||||
return "ds";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<1>>() {
|
||||
return "s";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::deca>() {
|
||||
return "das";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::hecto>() {
|
||||
return "hs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::kilo>() {
|
||||
return "ks";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::mega>() {
|
||||
return "Ms";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::giga>() {
|
||||
return "Gs";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::tera>() {
|
||||
return "Ts";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::peta>() {
|
||||
return "Ps";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::exa>() {
|
||||
return "Es";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<60>>() {
|
||||
return "m";
|
||||
}
|
||||
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<3600>>() {
|
||||
return "h";
|
||||
}
|
||||
|
||||
enum class numeric_system {
|
||||
standard,
|
||||
@ -680,34 +737,50 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct chrono_format_checker {
|
||||
FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); }
|
||||
template <typename Derived> struct null_chrono_spec_handler {
|
||||
FMT_CONSTEXPR void unsupported() {
|
||||
static_cast<Derived*>(this)->unsupported();
|
||||
}
|
||||
FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_full_weekday() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); }
|
||||
FMT_CONSTEXPR void on_us_date() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_iso_date() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_12_hour_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_24_hour_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_iso_time() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_am_pm() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_duration_value() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_duration_unit() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_utc_offset() { unsupported(); }
|
||||
FMT_CONSTEXPR void on_tz_name() { unsupported(); }
|
||||
};
|
||||
|
||||
struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
|
||||
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_abbr_month() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_month() { report_no_date(); }
|
||||
FMT_CONSTEXPR void on_24_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_12_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_minute(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_second(numeric_system) {}
|
||||
FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_us_date() { report_no_date(); }
|
||||
FMT_NORETURN void on_iso_date() { report_no_date(); }
|
||||
FMT_CONSTEXPR void on_12_hour_time() {}
|
||||
FMT_CONSTEXPR void on_24_hour_time() {}
|
||||
FMT_CONSTEXPR void on_iso_time() {}
|
||||
FMT_CONSTEXPR void on_am_pm() {}
|
||||
FMT_CONSTEXPR void on_duration_value() {}
|
||||
FMT_CONSTEXPR void on_duration_unit() {}
|
||||
FMT_NORETURN void on_utc_offset() { report_no_date(); }
|
||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||
};
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
@ -859,6 +932,7 @@ struct chrono_formatter {
|
||||
FormatContext& context;
|
||||
OutputIt out;
|
||||
int precision;
|
||||
bool localized = false;
|
||||
// rep is unsigned to avoid overflow.
|
||||
using rep =
|
||||
conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
|
||||
@ -953,13 +1027,9 @@ struct chrono_formatter {
|
||||
|
||||
void format_localized(const tm& time, char format, char modifier = 0) {
|
||||
if (isnan(val)) return write_nan();
|
||||
auto locale = context.locale().template get<std::locale>();
|
||||
auto& facet = std::use_facet<std::time_put<char_type>>(locale);
|
||||
std::basic_ostringstream<char_type> os;
|
||||
os.imbue(locale);
|
||||
facet.put(os, os, ' ', &time, format, modifier);
|
||||
auto str = os.str();
|
||||
std::copy(str.begin(), str.end(), out);
|
||||
const auto& loc = localized ? context.locale().template get<std::locale>()
|
||||
: std::locale::classic();
|
||||
out = detail::write(out, time, loc, format, modifier);
|
||||
}
|
||||
|
||||
void on_text(const char_type* begin, const char_type* end) {
|
||||
@ -1072,7 +1142,48 @@ struct chrono_formatter {
|
||||
out = format_duration_unit<char_type, Period>(out);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
FMT_END_DETAIL_NAMESPACE
|
||||
|
||||
#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
|
||||
using weekday = std::chrono::weekday;
|
||||
#else
|
||||
// A fallback version of weekday.
|
||||
class weekday {
|
||||
private:
|
||||
unsigned char value;
|
||||
|
||||
public:
|
||||
weekday() = default;
|
||||
explicit constexpr weekday(unsigned wd) noexcept
|
||||
: value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
|
||||
constexpr unsigned c_encoding() const noexcept { return value; }
|
||||
};
|
||||
#endif
|
||||
|
||||
// A rudimentary weekday formatter.
|
||||
template <> struct formatter<weekday> {
|
||||
private:
|
||||
bool localized = false;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
if (begin != end && *begin == 'L') {
|
||||
++begin;
|
||||
localized = true;
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
auto format(weekday wd, format_context& ctx) -> decltype(ctx.out()) {
|
||||
auto time = std::tm();
|
||||
time.tm_wday = static_cast<int>(wd.c_encoding());
|
||||
const auto& loc = localized ? ctx.locale().template get<std::locale>()
|
||||
: std::locale::classic();
|
||||
return detail::write(ctx.out(), time, loc, 'a');
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Rep, typename Period, typename Char>
|
||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
@ -1082,6 +1193,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
using arg_ref_type = detail::arg_ref<Char>;
|
||||
arg_ref_type width_ref;
|
||||
arg_ref_type precision_ref;
|
||||
bool localized = false;
|
||||
basic_string_view<Char> format_str;
|
||||
using duration = std::chrono::duration<Rep, Period>;
|
||||
|
||||
@ -1144,6 +1256,10 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
else
|
||||
handler.on_error("precision not allowed for this argument type");
|
||||
}
|
||||
if (begin != end && *begin == 'L') {
|
||||
++begin;
|
||||
localized = true;
|
||||
}
|
||||
end = parse_chrono_format(begin, end, detail::chrono_format_checker());
|
||||
return {begin, end};
|
||||
}
|
||||
@ -1178,13 +1294,15 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
|
||||
ctx, out, d);
|
||||
f.precision = precision_copy;
|
||||
parse_chrono_format(begin, end, f);
|
||||
f.localized = localized;
|
||||
detail::parse_chrono_format(begin, end, f);
|
||||
}
|
||||
return detail::write(
|
||||
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
|
||||
}
|
||||
};
|
||||
|
||||
FMT_MODULE_EXPORT_END
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_CHRONO_H_
|
||||
|
Reference in New Issue
Block a user