mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-30 02:31:44 +00:00
[upstream_utils] Upgrade to fmt 12.2.0 (#9018)
This commit is contained in:
@@ -925,7 +925,7 @@ See http://www.wtfpl.net/ for more details.
|
||||
======
|
||||
fmtlib
|
||||
======
|
||||
Copyright (c) 2012 - present, Victor Zverovich
|
||||
Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -34,7 +34,7 @@ def copy_upstream_src(wpilib_root: Path):
|
||||
def main():
|
||||
name = "fmt"
|
||||
url = "https://github.com/fmtlib/fmt"
|
||||
tag = "12.1.0"
|
||||
tag = "12.2.0"
|
||||
|
||||
fmt = Lib(name, url, tag, copy_upstream_src)
|
||||
fmt.main()
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tyler Veness <calcmogul@gmail.com>
|
||||
Date: Fri, 31 Oct 2025 14:53:37 -0700
|
||||
Subject: [PATCH] Suppress nodiscard
|
||||
|
||||
---
|
||||
include/fmt/base.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/fmt/base.h b/include/fmt/base.h
|
||||
index 0d57867782fcf571e7581b2bc70fa04bf43e4ccc..6a222b50eb515486a47dd5f37b94665e7f3ffef8 100644
|
||||
--- a/include/fmt/base.h
|
||||
+++ b/include/fmt/base.h
|
||||
@@ -927,7 +927,7 @@ class locale_ref {
|
||||
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)>
|
||||
locale_ref(const Locale& loc) : locale_(&loc) {
|
||||
// Check if std::isalpha is found via ADL to reduce the chance of misuse.
|
||||
- isalpha('x', loc);
|
||||
+ static_cast<void>(isalpha('x', loc));
|
||||
}
|
||||
|
||||
inline explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - dynamic argument lists
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -113,8 +113,7 @@ FMT_EXPORT template <typename Context> class dynamic_format_arg_store {
|
||||
data_.emplace_back(arg);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
|
||||
template <typename T> void emplace_arg(const named_arg<T, char_type>& arg) {
|
||||
if (named_info_.empty())
|
||||
data_.insert(data_.begin(), basic_format_arg<Context>(nullptr, 0));
|
||||
data_.emplace_back(detail::unwrap(arg.value));
|
||||
@@ -152,7 +151,7 @@ FMT_EXPORT template <typename Context> class dynamic_format_arg_store {
|
||||
* std::string result = fmt::vformat("{} and {} and {}", store);
|
||||
*/
|
||||
template <typename T> void push_back(const T& arg) {
|
||||
if (detail::const_check(need_copy<T>::value))
|
||||
if FMT_CONSTEXPR20 (need_copy<T>::value)
|
||||
emplace_arg(dynamic_args_.push<stored_t<T>>(arg));
|
||||
else
|
||||
emplace_arg(detail::unwrap(arg));
|
||||
@@ -183,11 +182,10 @@ FMT_EXPORT template <typename Context> class dynamic_format_arg_store {
|
||||
* formatting function. `std::reference_wrapper` is supported to avoid
|
||||
* copying of the argument. The name is always copied into the store.
|
||||
*/
|
||||
template <typename T>
|
||||
void push_back(const detail::named_arg<char_type, T>& arg) {
|
||||
template <typename T> void push_back(const named_arg<T, char_type>& arg) {
|
||||
const char_type* arg_name =
|
||||
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
|
||||
if (detail::const_check(need_copy<T>::value)) {
|
||||
if FMT_CONSTEXPR20 (need_copy<T>::value) {
|
||||
emplace_arg(
|
||||
fmt::arg(arg_name, dynamic_args_.push<stored_t<T>>(arg.value)));
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - chrono support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -52,7 +52,7 @@ FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec)
|
||||
static_assert(T::is_integer, "To must be integral");
|
||||
|
||||
// A and B are both signed, or both unsigned.
|
||||
if (detail::const_check(F::digits <= T::digits)) {
|
||||
if FMT_CONSTEXPR20 (F::digits <= T::digits) {
|
||||
// From fits in To without any problem.
|
||||
} else {
|
||||
// From does not always fit in To, resort to a dynamic check.
|
||||
@@ -79,22 +79,21 @@ FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec)
|
||||
static_assert(F::is_integer, "From must be integral");
|
||||
static_assert(T::is_integer, "To must be integral");
|
||||
|
||||
if (detail::const_check(F::is_signed && !T::is_signed)) {
|
||||
if FMT_CONSTEXPR20 (F::is_signed && !T::is_signed) {
|
||||
// From may be negative, not allowed!
|
||||
if (fmt::detail::is_negative(from)) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
// From is positive. Can it always fit in To?
|
||||
if (detail::const_check(F::digits > T::digits) &&
|
||||
if (F::digits > T::digits &&
|
||||
from > static_cast<From>(detail::max_value<To>())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (detail::const_check(!F::is_signed && T::is_signed &&
|
||||
F::digits >= T::digits) &&
|
||||
if (!F::is_signed && T::is_signed && F::digits >= T::digits &&
|
||||
from > static_cast<From>(detail::max_value<To>())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
@@ -188,7 +187,7 @@ auto safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
}
|
||||
|
||||
// multiply with Factor::num without overflow or underflow
|
||||
if (detail::const_check(Factor::num != 1)) {
|
||||
if FMT_CONSTEXPR20 (Factor::num != 1) {
|
||||
constexpr auto max1 = detail::max_value<IntermediateRep>() /
|
||||
static_cast<IntermediateRep>(Factor::num);
|
||||
if (count > max1) {
|
||||
@@ -205,7 +204,7 @@ auto safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
}
|
||||
|
||||
// this can't go wrong, right? den>0 is checked earlier.
|
||||
if (detail::const_check(Factor::den != 1)) {
|
||||
if FMT_CONSTEXPR20 (Factor::den != 1) {
|
||||
using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;
|
||||
count /= static_cast<common_t>(Factor::den);
|
||||
}
|
||||
@@ -337,7 +336,7 @@ void write_codecvt(codecvt_result<CodeUnit>& out, string_view in,
|
||||
template <typename OutputIt>
|
||||
auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
|
||||
-> OutputIt {
|
||||
if (const_check(detail::use_utf8) && loc != get_classic_locale()) {
|
||||
if (detail::use_utf8 && loc != get_classic_locale()) {
|
||||
// char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
|
||||
// gcc-4.
|
||||
#if FMT_MSC_VERSION != 0 || \
|
||||
@@ -434,14 +433,14 @@ auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
common_rep count = from.count(); // This conversion is lossless.
|
||||
|
||||
// Multiply from.count() by factor and check for overflow.
|
||||
if (const_check(factor::num != 1)) {
|
||||
if FMT_CONSTEXPR20 (factor::num != 1) {
|
||||
if (count > max_value<common_rep>() / factor::num) throw_duration_error();
|
||||
const auto min = (std::numeric_limits<common_rep>::min)() / factor::num;
|
||||
if (const_check(!std::is_unsigned<common_rep>::value) && count < min)
|
||||
if (!std::is_unsigned<common_rep>::value && count < min)
|
||||
throw_duration_error();
|
||||
count *= factor::num;
|
||||
}
|
||||
if (const_check(factor::den != 1)) count /= factor::den;
|
||||
if FMT_CONSTEXPR20 (factor::den != 1) count /= factor::den;
|
||||
int ec = 0;
|
||||
auto to =
|
||||
To(safe_duration_cast::lossless_integral_conversion<typename To::rep>(
|
||||
@@ -544,8 +543,7 @@ namespace detail {
|
||||
// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/.
|
||||
inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
|
||||
unsigned c, char sep) {
|
||||
unsigned long long digits =
|
||||
a | (b << 24) | (static_cast<unsigned long long>(c) << 48);
|
||||
ullong digits = a | (b << 24) | (static_cast<ullong>(c) << 48);
|
||||
// Convert each value to BCD.
|
||||
// We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b.
|
||||
// The difference is
|
||||
@@ -559,12 +557,12 @@ inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
|
||||
// Put low nibbles to high bytes and high nibbles to low bytes.
|
||||
digits = ((digits & 0x00f00000f00000f0) >> 4) |
|
||||
((digits & 0x000f00000f00000f) << 8);
|
||||
auto usep = static_cast<unsigned long long>(sep);
|
||||
auto usep = static_cast<ullong>(sep);
|
||||
// Add ASCII '0' to each digit byte and insert separators.
|
||||
digits |= 0x3030003030003030 | (usep << 16) | (usep << 40);
|
||||
|
||||
constexpr size_t len = 8;
|
||||
if (const_check(is_big_endian())) {
|
||||
if (is_big_endian()) {
|
||||
char tmp[len];
|
||||
std::memcpy(tmp, &digits, len);
|
||||
std::reverse_copy(tmp, tmp + len, buf);
|
||||
@@ -1194,6 +1192,7 @@ class tm_writer {
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(has_tm_zone<T>::value)>
|
||||
void format_tz_name(const T& tm) {
|
||||
if (!tm.tm_zone) FMT_THROW(format_error("no timezone"));
|
||||
out_ = write_tm_str<Char>(out_, tm.tm_zone, loc_);
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(!has_tm_zone<T>::value)>
|
||||
@@ -1576,7 +1575,7 @@ auto format_duration_unit(OutputIt out) -> OutputIt {
|
||||
return copy_unit(string_view(unit), out, Char());
|
||||
*out++ = '[';
|
||||
out = write<Char>(out, Period::num);
|
||||
if (const_check(Period::den != 1)) {
|
||||
if FMT_CONSTEXPR20 (Period::den != 1) {
|
||||
*out++ = '/';
|
||||
out = write<Char>(out, Period::den);
|
||||
}
|
||||
@@ -2179,9 +2178,9 @@ struct formatter<sys_time<Duration>, Char> : private formatter<std::tm, Char> {
|
||||
-> decltype(ctx.out()) {
|
||||
std::tm tm = gmtime(val);
|
||||
using period = typename Duration::period;
|
||||
if (detail::const_check(
|
||||
period::num == 1 && period::den == 1 &&
|
||||
!std::is_floating_point<typename Duration::rep>::value)) {
|
||||
if FMT_CONSTEXPR20 (period::num == 1 && period::den == 1 &&
|
||||
!std::is_floating_point<
|
||||
typename Duration::rep>::value) {
|
||||
detail::set_tm_zone(tm, detail::utc());
|
||||
return formatter<std::tm, Char>::format(tm, ctx);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - color support
|
||||
//
|
||||
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
|
||||
// Copyright (c) 2018 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -155,7 +155,7 @@ enum class color : uint32_t {
|
||||
white_smoke = 0xF5F5F5, // rgb(245,245,245)
|
||||
yellow = 0xFFFF00, // rgb(255,255,0)
|
||||
yellow_green = 0x9ACD32 // rgb(154,205,50)
|
||||
}; // enum class color
|
||||
}; // enum class color
|
||||
|
||||
enum class terminal_color : uint8_t {
|
||||
black = 30,
|
||||
@@ -471,7 +471,7 @@ template <typename Char> inline void reset_color(buffer<Char>& buffer) {
|
||||
template <typename T> struct styled_arg : view {
|
||||
const T& value;
|
||||
text_style style;
|
||||
styled_arg(const T& v, text_style s) : value(v), style(s) {}
|
||||
FMT_CONSTEXPR styled_arg(const T& v, text_style s) : value(v), style(s) {}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
@@ -528,6 +528,42 @@ void print(text_style ts, format_string<T...> fmt, T&&... args) {
|
||||
return print(stdout, ts, fmt, std::forward<T>(args)...);
|
||||
}
|
||||
|
||||
inline void vprintln(FILE* f, text_style ts, string_view fmt,
|
||||
format_args args) {
|
||||
auto buf = memory_buffer();
|
||||
detail::vformat_to(buf, ts, fmt, args);
|
||||
buf.push_back('\n');
|
||||
print(f, FMT_STRING("{}"), string_view(buf.begin(), buf.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string and prints it to the specified file stream followed by a
|
||||
* newline, using ANSI escape sequences to specify text formatting.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* fmt::println(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
* "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template <typename... T>
|
||||
void println(FILE* f, text_style ts, format_string<T...> fmt, T&&... args) {
|
||||
vprintln(f, ts, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string and prints it to stdout followed by a newline, using ANSI
|
||||
* escape sequences to specify text formatting.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* fmt::println(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
* "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template <typename... T>
|
||||
void println(text_style ts, format_string<T...> fmt, T&&... args) {
|
||||
return println(stdout, ts, fmt, std::forward<T>(args)...);
|
||||
}
|
||||
|
||||
inline auto vformat(text_style ts, string_view fmt, format_args args)
|
||||
-> std::string {
|
||||
auto buf = memory_buffer();
|
||||
@@ -583,8 +619,8 @@ inline auto format_to(OutputIt out, text_style ts, format_string<T...> fmt,
|
||||
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()) {
|
||||
FMT_CONSTEXPR auto format(const detail::styled_arg<T>& arg,
|
||||
FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
const auto& ts = arg.style;
|
||||
auto out = ctx.out();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - experimental format string compilation
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -267,13 +267,15 @@ constexpr auto parse_text(basic_string_view<Char> str, size_t pos) -> size_t {
|
||||
return pos;
|
||||
}
|
||||
|
||||
template <typename Args, size_t POS, int ID, typename S>
|
||||
template <typename Args, size_t POS, int ID, bool DYNAMIC_NAMES, typename S>
|
||||
constexpr auto compile_format_string(S fmt);
|
||||
|
||||
template <typename Args, size_t POS, int ID, typename T, typename S>
|
||||
template <typename Args, size_t POS, int ID, bool DYNAMIC_NAMES, typename T,
|
||||
typename S>
|
||||
constexpr auto parse_tail(T head, S fmt) {
|
||||
if constexpr (POS != basic_string_view<typename S::char_type>(fmt).size()) {
|
||||
constexpr auto tail = compile_format_string<Args, POS, ID>(fmt);
|
||||
constexpr auto tail =
|
||||
compile_format_string<Args, POS, ID, DYNAMIC_NAMES>(fmt);
|
||||
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
|
||||
unknown_format>())
|
||||
return tail;
|
||||
@@ -347,13 +349,13 @@ struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> {
|
||||
};
|
||||
|
||||
template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,
|
||||
typename S>
|
||||
bool DYNAMIC_NAMES, typename S>
|
||||
constexpr auto parse_replacement_field_then_tail(S fmt) {
|
||||
using char_type = typename S::char_type;
|
||||
constexpr auto str = basic_string_view<char_type>(fmt);
|
||||
constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();
|
||||
if constexpr (c == '}') {
|
||||
return parse_tail<Args, END_POS + 1, NEXT_ID>(
|
||||
return parse_tail<Args, END_POS + 1, NEXT_ID, DYNAMIC_NAMES>(
|
||||
field<char_type, typename field_type<T>::type, ARG_INDEX>(), fmt);
|
||||
} else if constexpr (c != ':') {
|
||||
FMT_THROW(format_error("expected ':'"));
|
||||
@@ -364,7 +366,8 @@ constexpr auto parse_replacement_field_then_tail(S fmt) {
|
||||
FMT_THROW(format_error("expected '}'"));
|
||||
return 0;
|
||||
} else {
|
||||
return parse_tail<Args, result.end + 1, result.next_arg_id>(
|
||||
return parse_tail<Args, result.end + 1, result.next_arg_id,
|
||||
DYNAMIC_NAMES>(
|
||||
spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
|
||||
result.fmt},
|
||||
fmt);
|
||||
@@ -374,7 +377,7 @@ constexpr auto parse_replacement_field_then_tail(S fmt) {
|
||||
|
||||
// Compiles a non-empty format string and returns the compiled representation
|
||||
// or unknown_format() on unrecognized input.
|
||||
template <typename Args, size_t POS, int ID, typename S>
|
||||
template <typename Args, size_t POS, int ID, bool DYNAMIC_NAMES, typename S>
|
||||
constexpr auto compile_format_string(S fmt) {
|
||||
using char_type = typename S::char_type;
|
||||
constexpr auto str = basic_string_view<char_type>(fmt);
|
||||
@@ -382,14 +385,15 @@ constexpr auto compile_format_string(S fmt) {
|
||||
if constexpr (POS + 1 == str.size())
|
||||
FMT_THROW(format_error("unmatched '{' in format string"));
|
||||
if constexpr (str[POS + 1] == '{') {
|
||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), fmt);
|
||||
return parse_tail<Args, POS + 2, ID, DYNAMIC_NAMES>(
|
||||
make_text(str, POS, 1), fmt);
|
||||
} else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') {
|
||||
static_assert(ID != manual_indexing_id,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
constexpr auto next_id =
|
||||
ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
|
||||
return parse_replacement_field_then_tail<get_type<ID, Args>, Args,
|
||||
POS + 1, ID, next_id>(fmt);
|
||||
return parse_replacement_field_then_tail<
|
||||
get_type<ID, Args>, Args, POS + 1, ID, next_id, DYNAMIC_NAMES>(fmt);
|
||||
} else {
|
||||
constexpr auto arg_id_result =
|
||||
parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size());
|
||||
@@ -402,21 +406,24 @@ constexpr auto compile_format_string(S fmt) {
|
||||
ID == manual_indexing_id || ID == 0,
|
||||
"cannot switch from automatic to manual argument indexing");
|
||||
constexpr auto arg_index = arg_id_result.arg_id.index;
|
||||
return parse_replacement_field_then_tail<get_type<arg_index, Args>,
|
||||
Args, arg_id_end_pos,
|
||||
arg_index, manual_indexing_id>(
|
||||
fmt);
|
||||
return parse_replacement_field_then_tail<
|
||||
get_type<arg_index, Args>, Args, arg_id_end_pos, arg_index,
|
||||
manual_indexing_id, DYNAMIC_NAMES>(fmt);
|
||||
} else if constexpr (arg_id_result.kind == arg_id_kind::name) {
|
||||
constexpr auto arg_index =
|
||||
get_arg_index_by_name(arg_id_result.arg_id.name, Args{});
|
||||
|
||||
static_assert(arg_index >= 0 || DYNAMIC_NAMES,
|
||||
"named argument not found");
|
||||
|
||||
if constexpr (arg_index >= 0) {
|
||||
constexpr auto next_id =
|
||||
ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
|
||||
return parse_replacement_field_then_tail<
|
||||
decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,
|
||||
arg_index, next_id>(fmt);
|
||||
arg_index, next_id, DYNAMIC_NAMES>(fmt);
|
||||
} else if constexpr (c == '}') {
|
||||
return parse_tail<Args, arg_id_end_pos + 1, ID>(
|
||||
return parse_tail<Args, arg_id_end_pos + 1, ID, DYNAMIC_NAMES>(
|
||||
runtime_named_field<char_type>{arg_id_result.arg_id.name}, fmt);
|
||||
} else if constexpr (c == ':') {
|
||||
return unknown_format(); // no type info for specs parsing
|
||||
@@ -426,13 +433,16 @@ constexpr auto compile_format_string(S fmt) {
|
||||
} else if constexpr (str[POS] == '}') {
|
||||
if constexpr (POS + 1 == str.size())
|
||||
FMT_THROW(format_error("unmatched '}' in format string"));
|
||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), fmt);
|
||||
return parse_tail<Args, POS + 2, ID, DYNAMIC_NAMES>(make_text(str, POS, 1),
|
||||
fmt);
|
||||
} else {
|
||||
constexpr auto end = parse_text(str, POS + 1);
|
||||
if constexpr (end - POS > 1) {
|
||||
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS), fmt);
|
||||
return parse_tail<Args, end, ID, DYNAMIC_NAMES>(
|
||||
make_text(str, POS, end - POS), fmt);
|
||||
} else {
|
||||
return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]}, fmt);
|
||||
return parse_tail<Args, end, ID, DYNAMIC_NAMES>(
|
||||
code_unit<char_type>{str[POS]}, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,8 +454,11 @@ constexpr auto compile(S fmt) {
|
||||
if constexpr (str.size() == 0) {
|
||||
return detail::make_text(str, 0, 0);
|
||||
} else {
|
||||
constexpr auto result =
|
||||
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(fmt);
|
||||
constexpr int num_static_named_args =
|
||||
detail::count_static_named_args<Args...>();
|
||||
constexpr auto result = detail::compile_format_string<
|
||||
detail::type_list<Args...>, 0, 0,
|
||||
num_static_named_args != detail::count_named_args<Args...>()>(fmt);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -522,7 +535,7 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
|
||||
fmt::format_to(std::back_inserter(buf), fmt, std::forward<T>(args)...);
|
||||
fmt::format_to(appender(buf), fmt, std::forward<T>(args)...);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
@@ -559,8 +572,8 @@ template <size_t N> class static_format_result {
|
||||
*fmt::format_to(data, fmt, std::forward<T>(args)...) = '\0';
|
||||
}
|
||||
|
||||
auto str() const -> fmt::string_view { return {data, N - 1}; }
|
||||
auto c_str() const -> const char* { return data; }
|
||||
FMT_CONSTEXPR auto str() const -> fmt::string_view { return {data, N - 1}; }
|
||||
FMT_CONSTEXPR auto c_str() const -> const char* { return data; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
// This file is only provided for compatibility and may be removed in future
|
||||
// versions. Use fmt/base.h if you don't need fmt::format and fmt/format.h
|
||||
// otherwise.
|
||||
// Formatting library for C++ - core API
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "format.h"
|
||||
#include "base.h"
|
||||
|
||||
// Using fmt::format via fmt/core.h has been deprecated since version 11
|
||||
// and now requires an explicit opt in.
|
||||
#ifdef FMT_DEPRECATED_HEAVY_CORE
|
||||
# include "format.h"
|
||||
#endif
|
||||
|
||||
201
wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/fmt-c.h
vendored
Normal file
201
wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/fmt-c.h
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// Formatting library for C++ - the C API
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_C_H_
|
||||
#define FMT_C_H_
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdio.h> // FILE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
fmt_int = 1,
|
||||
fmt_uint,
|
||||
fmt_bool = 7,
|
||||
fmt_char,
|
||||
fmt_float,
|
||||
fmt_double,
|
||||
fmt_long_double,
|
||||
fmt_cstring,
|
||||
fmt_pointer = 14
|
||||
} fmt_type;
|
||||
|
||||
typedef struct {
|
||||
fmt_type type;
|
||||
union {
|
||||
long long int_value;
|
||||
unsigned long long uint_value; // Used for FMT_PTR and custom data
|
||||
bool bool_value;
|
||||
char char_value;
|
||||
float float_value;
|
||||
double double_value;
|
||||
long double long_double_value;
|
||||
const char* cstring;
|
||||
const void* pointer;
|
||||
} value;
|
||||
} fmt_arg;
|
||||
|
||||
enum { fmt_error = -1, fmt_error_invalid_arg = -2 };
|
||||
|
||||
int fmt_vformat(char* buffer, size_t size, const char* fmt, const fmt_arg* args,
|
||||
size_t num_args);
|
||||
int fmt_vprint(FILE* stream, const char* fmt, const fmt_arg* args,
|
||||
size_t num_args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
static inline fmt_arg fmt_from_int(long long x) {
|
||||
return (fmt_arg){.type = fmt_int, .value.int_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_uint(unsigned long long x) {
|
||||
return (fmt_arg){.type = fmt_uint, .value.uint_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_bool(bool x) {
|
||||
return (fmt_arg){.type = fmt_bool, .value.bool_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_char(char x) {
|
||||
return (fmt_arg){.type = fmt_char, .value.char_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_float(float x) {
|
||||
return (fmt_arg){.type = fmt_float, .value.float_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_double(double x) {
|
||||
return (fmt_arg){.type = fmt_double, .value.double_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_long_double(long double x) {
|
||||
return (fmt_arg){.type = fmt_long_double, .value.long_double_value = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_str(const char* x) {
|
||||
return (fmt_arg){.type = fmt_cstring, .value.cstring = x};
|
||||
}
|
||||
|
||||
static inline fmt_arg fmt_from_ptr(const void* x) {
|
||||
return (fmt_arg){.type = fmt_pointer, .value.pointer = x};
|
||||
}
|
||||
|
||||
void fmt_unsupported_type(void);
|
||||
|
||||
# if !defined(_MSC_VER) || defined(__clang__)
|
||||
typedef signed char fmt_signed_char;
|
||||
# else
|
||||
typedef enum {} fmt_signed_char;
|
||||
# endif
|
||||
|
||||
// Require modern MSVC with conformant preprocessor.
|
||||
# if defined(_MSC_VER) && !defined(__clang__) && \
|
||||
(!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)
|
||||
# error "C API requires MSVC 2019+ with /Zc:preprocessor flag."
|
||||
# endif
|
||||
|
||||
# define FMT_MAKE_ARG(x) \
|
||||
_Generic((x), \
|
||||
fmt_signed_char: fmt_from_int, \
|
||||
unsigned char: fmt_from_uint, \
|
||||
short: fmt_from_int, \
|
||||
unsigned short: fmt_from_uint, \
|
||||
int: fmt_from_int, \
|
||||
unsigned int: fmt_from_uint, \
|
||||
long: fmt_from_int, \
|
||||
unsigned long: fmt_from_uint, \
|
||||
long long: fmt_from_int, \
|
||||
unsigned long long: fmt_from_uint, \
|
||||
bool: fmt_from_bool, \
|
||||
char: fmt_from_char, \
|
||||
float: fmt_from_float, \
|
||||
double: fmt_from_double, \
|
||||
long double: fmt_from_long_double, \
|
||||
char*: fmt_from_str, \
|
||||
const char*: fmt_from_str, \
|
||||
void*: fmt_from_ptr, \
|
||||
const void*: fmt_from_ptr, \
|
||||
default: fmt_unsupported_type)(x)
|
||||
|
||||
# define FMT_CAT(a, b) FMT_CAT_(a, b)
|
||||
# define FMT_CAT_(a, b) a##b
|
||||
|
||||
# define FMT_NARG_(_unused, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, \
|
||||
_12, _13, _14, _15, _16, N, ...) \
|
||||
N
|
||||
# define FMT_NARG(_unused, ...) \
|
||||
FMT_NARG_(, ##__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, \
|
||||
3, 2, 1, 0)
|
||||
|
||||
# define FMT_MAP_0(...)
|
||||
# define FMT_MAP_1(f, a) f(a)
|
||||
# define FMT_MAP_2(f, a, b) f(a), f(b)
|
||||
# define FMT_MAP_3(f, a, b, c) f(a), f(b), f(c)
|
||||
# define FMT_MAP_4(f, a, b, c, d) f(a), f(b), f(c), f(d)
|
||||
# define FMT_MAP_5(f, a, b, c, d, e) f(a), f(b), f(c), f(d), f(e)
|
||||
# define FMT_MAP_6(f, a, b, c, d, e, g) f(a), f(b), f(c), f(d), f(e), f(g)
|
||||
# define FMT_MAP_7(f, a, b, c, d, e, g, h) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h)
|
||||
# define FMT_MAP_8(f, a, b, c, d, e, g, h, i) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i)
|
||||
# define FMT_MAP_9(f, a, b, c, d, e, g, h, i, j) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j)
|
||||
# define FMT_MAP_10(f, a, b, c, d, e, g, h, i, j, k) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k)
|
||||
# define FMT_MAP_11(f, a, b, c, d, e, g, h, i, j, k, l) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l)
|
||||
# define FMT_MAP_12(f, a, b, c, d, e, g, h, i, j, k, l, m) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l), f(m)
|
||||
# define FMT_MAP_13(f, a, b, c, d, e, g, h, i, j, k, l, m, n) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l), f(m), f(n)
|
||||
# define FMT_MAP_14(f, a, b, c, d, e, g, h, i, j, k, l, m, n, o) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l), f(m), \
|
||||
f(n), f(o)
|
||||
# define FMT_MAP_15(f, a, b, c, d, e, g, h, i, j, k, l, m, n, o, p) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l), f(m), \
|
||||
f(n), f(o), f(p)
|
||||
# define FMT_MAP_16(f, a, b, c, d, e, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
f(a), f(b), f(c), f(d), f(e), f(g), f(h), f(i), f(j), f(k), f(l), f(m), \
|
||||
f(n), f(o), f(p), f(q)
|
||||
|
||||
# define FMT_MAP(f, ...) \
|
||||
FMT_CAT(FMT_MAP_, FMT_NARG(, ##__VA_ARGS__))(f, ##__VA_ARGS__)
|
||||
|
||||
// select between two expressions depending on whether __VA_ARGS__ is empty
|
||||
// expands to e if __VA_ARGS__ is empty and n otherwise
|
||||
# define FMT_VA_SELECT(e, n, ...) \
|
||||
FMT_NARG_(, ##__VA_ARGS__, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, \
|
||||
e)
|
||||
|
||||
# define FMT_MAKE_NULL(...) NULL
|
||||
# define FMT_MAKE_ARGLIST(...) \
|
||||
(fmt_arg[]) { FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__) }
|
||||
# define FMT_EXPAND(v) v
|
||||
|
||||
# define FMT_FORMAT_ARGS(fmt, ...) \
|
||||
(fmt), \
|
||||
FMT_EXPAND(FMT_VA_SELECT(FMT_MAKE_NULL, FMT_MAKE_ARGLIST, \
|
||||
##__VA_ARGS__)(__VA_ARGS__)), \
|
||||
FMT_NARG(, ##__VA_ARGS__)
|
||||
|
||||
# define fmt_format(buffer, size, fmt, ...) \
|
||||
fmt_vformat((buffer), (size), FMT_FORMAT_ARGS((fmt), ##__VA_ARGS__))
|
||||
|
||||
# define fmt_print(stream, fmt, ...) \
|
||||
fmt_vprint((stream), FMT_FORMAT_ARGS((fmt), ##__VA_ARGS__))
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // FMT_C_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Formatting library for C++
|
||||
|
||||
Copyright (c) 2012 - present, Victor Zverovich
|
||||
Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -47,14 +47,12 @@
|
||||
#endif
|
||||
|
||||
#ifndef FMT_MODULE
|
||||
# include <stdint.h> // uint32_t
|
||||
# include <stdlib.h> // malloc, free
|
||||
# include <string.h> // memcpy
|
||||
|
||||
# include <cmath> // std::signbit
|
||||
# include <cstddef> // std::byte
|
||||
# include <cstdint> // uint32_t
|
||||
# include <cstring> // std::memcpy
|
||||
# include <limits> // std::numeric_limits
|
||||
# include <new> // std::bad_alloc
|
||||
# include <cmath> // std::signbit
|
||||
# include <limits> // std::numeric_limits
|
||||
# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
|
||||
// Workaround for pre gcc 5 libstdc++.
|
||||
# include <memory> // std::allocator_traits
|
||||
@@ -122,14 +120,6 @@
|
||||
# define FMT_NOINLINE
|
||||
#endif
|
||||
|
||||
#ifdef FMT_DEPRECATED
|
||||
// Use the provided definition.
|
||||
#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated)
|
||||
# define FMT_DEPRECATED [[deprecated]]
|
||||
#else
|
||||
# define FMT_DEPRECATED /* deprecated */
|
||||
#endif
|
||||
|
||||
// Detect constexpr std::string.
|
||||
#if !FMT_USE_CONSTEVAL
|
||||
# define FMT_USE_CONSTEXPR_STRING 0
|
||||
@@ -224,7 +214,6 @@ namespace detail {
|
||||
|
||||
inline auto clz(uint32_t x) -> int {
|
||||
FMT_ASSERT(x != 0, "");
|
||||
FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse(&r, x);
|
||||
return 31 ^ static_cast<int>(r);
|
||||
@@ -233,7 +222,6 @@ inline auto clz(uint32_t x) -> int {
|
||||
|
||||
inline auto clzll(uint64_t x) -> int {
|
||||
FMT_ASSERT(x != 0, "");
|
||||
FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
|
||||
unsigned long r = 0;
|
||||
# ifdef _WIN64
|
||||
_BitScanReverse64(&r, x);
|
||||
@@ -283,7 +271,7 @@ FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
|
||||
#endif
|
||||
auto to = To();
|
||||
// The cast suppresses a bogus -Wclass-memaccess on GCC.
|
||||
std::memcpy(static_cast<void*>(&to), &from, sizeof(to));
|
||||
memcpy(static_cast<void*>(&to), &from, sizeof(to));
|
||||
return to;
|
||||
}
|
||||
|
||||
@@ -302,13 +290,13 @@ inline auto is_big_endian() -> bool {
|
||||
#endif
|
||||
}
|
||||
|
||||
class uint128_fallback {
|
||||
class uint128 {
|
||||
private:
|
||||
uint64_t lo_, hi_;
|
||||
|
||||
public:
|
||||
constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
|
||||
constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
|
||||
constexpr uint128(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
|
||||
constexpr uint128(uint64_t value = 0) : lo_(value), hi_(0) {}
|
||||
|
||||
constexpr auto high() const noexcept -> uint64_t { return hi_; }
|
||||
constexpr auto low() const noexcept -> uint64_t { return lo_; }
|
||||
@@ -318,92 +306,84 @@ class uint128_fallback {
|
||||
return static_cast<T>(lo_);
|
||||
}
|
||||
|
||||
friend constexpr auto operator==(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs) -> bool {
|
||||
friend constexpr auto operator==(const uint128& lhs, const uint128& rhs)
|
||||
-> bool {
|
||||
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
|
||||
}
|
||||
friend constexpr auto operator!=(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs) -> bool {
|
||||
friend constexpr auto operator!=(const uint128& lhs, const uint128& rhs)
|
||||
-> bool {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
friend constexpr auto operator>(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs) -> bool {
|
||||
friend constexpr auto operator>(const uint128& lhs, const uint128& rhs)
|
||||
-> bool {
|
||||
return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
|
||||
}
|
||||
friend constexpr auto operator|(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs)
|
||||
-> uint128_fallback {
|
||||
friend constexpr auto operator|(const uint128& lhs, const uint128& rhs)
|
||||
-> uint128 {
|
||||
return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
|
||||
}
|
||||
friend constexpr auto operator&(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs)
|
||||
-> uint128_fallback {
|
||||
friend constexpr auto operator&(const uint128& lhs, const uint128& rhs)
|
||||
-> uint128 {
|
||||
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
|
||||
}
|
||||
friend constexpr auto operator~(const uint128_fallback& n)
|
||||
-> uint128_fallback {
|
||||
return {~n.hi_, ~n.lo_};
|
||||
}
|
||||
friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs)
|
||||
-> uint128_fallback {
|
||||
auto result = uint128_fallback(lhs);
|
||||
friend FMT_CONSTEXPR auto operator+(const uint128& lhs, const uint128& rhs)
|
||||
-> uint128 {
|
||||
auto result = uint128(lhs);
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
|
||||
-> uint128_fallback {
|
||||
friend FMT_CONSTEXPR auto operator*(const uint128& lhs, uint32_t rhs)
|
||||
-> uint128 {
|
||||
FMT_ASSERT(lhs.hi_ == 0, "");
|
||||
uint64_t hi = (lhs.lo_ >> 32) * rhs;
|
||||
uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
|
||||
uint64_t new_lo = (hi << 32) + lo;
|
||||
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
|
||||
}
|
||||
friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
||||
-> uint128_fallback {
|
||||
friend constexpr auto operator-(const uint128& lhs, uint64_t rhs) -> uint128 {
|
||||
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
|
||||
}
|
||||
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
|
||||
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128 {
|
||||
if (shift == 64) return {0, hi_};
|
||||
if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64);
|
||||
if (shift > 64) return uint128(0, hi_) >> (shift - 64);
|
||||
return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
|
||||
}
|
||||
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback {
|
||||
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128 {
|
||||
if (shift == 64) return {lo_, 0};
|
||||
if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64);
|
||||
if (shift > 64) return uint128(lo_, 0) << (shift - 64);
|
||||
return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
|
||||
}
|
||||
FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& {
|
||||
FMT_CONSTEXPR auto operator>>=(int shift) -> uint128& {
|
||||
return *this = *this >> shift;
|
||||
}
|
||||
FMT_CONSTEXPR void operator+=(uint128_fallback n) {
|
||||
FMT_CONSTEXPR void operator+=(uint128 n) {
|
||||
uint64_t new_lo = lo_ + n.lo_;
|
||||
uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
|
||||
FMT_ASSERT(new_hi >= hi_, "");
|
||||
lo_ = new_lo;
|
||||
hi_ = new_hi;
|
||||
}
|
||||
FMT_CONSTEXPR void operator&=(uint128_fallback n) {
|
||||
FMT_CONSTEXPR void operator&=(uint128 n) {
|
||||
lo_ &= n.lo_;
|
||||
hi_ &= n.hi_;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& {
|
||||
FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128& {
|
||||
if (is_constant_evaluated()) {
|
||||
lo_ += n;
|
||||
hi_ += (lo_ < n ? 1 : 0);
|
||||
return *this;
|
||||
}
|
||||
#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
|
||||
unsigned long long carry;
|
||||
ullong carry;
|
||||
lo_ = __builtin_addcll(lo_, n, 0, &carry);
|
||||
hi_ += carry;
|
||||
#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
|
||||
unsigned long long result;
|
||||
ullong result;
|
||||
auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
|
||||
lo_ = result;
|
||||
hi_ += carry;
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
#elif defined(_MSC_VER) && defined(_M_AMD64)
|
||||
auto carry = _addcarry_u64(0, lo_, n, &lo_);
|
||||
_addcarry_u64(carry, hi_, 0, &hi_);
|
||||
#else
|
||||
@@ -414,7 +394,7 @@ class uint128_fallback {
|
||||
}
|
||||
};
|
||||
|
||||
using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>;
|
||||
using uint128_t = conditional_t<FMT_USE_INT128, native_uint128, uint128>;
|
||||
|
||||
#ifdef UINTPTR_MAX
|
||||
using uintptr_t = ::uintptr_t;
|
||||
@@ -431,12 +411,12 @@ template <typename T> constexpr auto num_bits() -> int {
|
||||
return std::numeric_limits<T>::digits;
|
||||
}
|
||||
// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
|
||||
template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
|
||||
template <> constexpr auto num_bits<uint128_opt>() -> int { return 128; }
|
||||
template <> constexpr auto num_bits<uint128_fallback>() -> int { return 128; }
|
||||
template <> constexpr auto num_bits<native_int128>() -> int { return 128; }
|
||||
template <> constexpr auto num_bits<native_uint128>() -> int { return 128; }
|
||||
template <> constexpr auto num_bits<uint128>() -> int { return 128; }
|
||||
|
||||
// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
|
||||
// and 128-bit pointers to uint128_fallback.
|
||||
// and 128-bit pointers to uint128.
|
||||
template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))>
|
||||
inline auto bit_cast(const From& from) -> To {
|
||||
constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned short));
|
||||
@@ -444,7 +424,7 @@ inline auto bit_cast(const From& from) -> To {
|
||||
unsigned short value[static_cast<unsigned>(size)];
|
||||
} data = bit_cast<data_t>(from);
|
||||
auto result = To();
|
||||
if (const_check(is_big_endian())) {
|
||||
if (is_big_endian()) {
|
||||
for (int i = 0; i < size; ++i)
|
||||
result = (result << num_bits<unsigned short>()) | data.value[i];
|
||||
} else {
|
||||
@@ -493,8 +473,8 @@ template <typename OutputIt,
|
||||
#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#endif
|
||||
FMT_CONSTEXPR20 inline auto
|
||||
reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
|
||||
FMT_CONSTEXPR20 inline auto reserve(OutputIt it, size_t n) ->
|
||||
typename OutputIt::value_type* {
|
||||
auto& c = get_container(it);
|
||||
size_t size = c.size();
|
||||
c.resize(size + n);
|
||||
@@ -564,10 +544,15 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
|
||||
if (is_constant_evaluated()) return fill_n<T*, Size, T>(out, count, value);
|
||||
static_assert(sizeof(T) == 1,
|
||||
"sizeof(T) must be 1 to use char for initialization");
|
||||
std::memset(out, value, to_unsigned(count));
|
||||
memset(out, value, to_unsigned(count));
|
||||
return out + count;
|
||||
}
|
||||
|
||||
template <typename T, typename V, typename OutputIt>
|
||||
FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
|
||||
return copy<T>(s.begin(), s.end(), out);
|
||||
}
|
||||
|
||||
template <typename OutChar, typename InputIt, typename OutputIt>
|
||||
FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end,
|
||||
OutputIt out) -> OutputIt {
|
||||
@@ -690,13 +675,13 @@ FMT_CONSTEXPR inline auto display_width_of(uint32_t cp) noexcept -> size_t {
|
||||
}
|
||||
|
||||
template <typename T> struct is_integral : std::is_integral<T> {};
|
||||
template <> struct is_integral<int128_opt> : std::true_type {};
|
||||
template <> struct is_integral<native_int128> : std::true_type {};
|
||||
template <> struct is_integral<uint128_t> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_signed =
|
||||
std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
|
||||
std::is_same<T, int128_opt>::value>;
|
||||
std::is_same<T, native_int128>::value>;
|
||||
|
||||
template <typename T>
|
||||
using is_integer =
|
||||
@@ -736,21 +721,17 @@ using fast_float_t = conditional_t<sizeof(T) == sizeof(double), double, float>;
|
||||
template <typename T>
|
||||
using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
|
||||
|
||||
#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
|
||||
# define FMT_USE_FULL_CACHE_DRAGONBOX 0
|
||||
#endif
|
||||
FMT_API auto allocate(size_t size) -> void*;
|
||||
|
||||
// An allocator that uses malloc/free to allow removing dependency on the C++
|
||||
// standard libary runtime. std::decay is used for back_inserter to be found by
|
||||
// standard library runtime. std::decay is used for back_inserter to be found by
|
||||
// ADL when applied to memory_buffer.
|
||||
template <typename T> struct allocator : private std::decay<void> {
|
||||
using value_type = T;
|
||||
|
||||
auto allocate(size_t n) -> T* {
|
||||
FMT_ASSERT(n <= max_value<size_t>() / sizeof(T), "");
|
||||
T* p = static_cast<T*>(malloc(n * sizeof(T)));
|
||||
if (!p) FMT_THROW(std::bad_alloc());
|
||||
return p;
|
||||
return static_cast<T*>(detail::allocate(n * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_t) { free(p); }
|
||||
@@ -984,7 +965,7 @@ FMT_API void print(FILE*, string_view);
|
||||
|
||||
namespace detail {
|
||||
template <typename Char, size_t N> struct fixed_string {
|
||||
FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) {
|
||||
FMT_CONSTEXPR fixed_string(const Char (&s)[N]) {
|
||||
detail::copy<Char, const Char*, Char*>(static_cast<const Char*>(s), s + N,
|
||||
data);
|
||||
}
|
||||
@@ -1031,12 +1012,12 @@ using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;
|
||||
(factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
|
||||
(factor) * 100000000, (factor) * 1000000000
|
||||
|
||||
// Converts value in the range [0, 100) to a string.
|
||||
// GCC generates slightly better code when value is pointer-size.
|
||||
inline auto digits2(size_t value) -> const char* {
|
||||
// Converts value in the range [0, 100) to a string. GCC generates a bit better
|
||||
// code when value is pointer-size (https://www.godbolt.org/z/5fEPMT1cc).
|
||||
inline auto digits2(size_t value) noexcept -> const char* {
|
||||
// Align data since unaligned access may be slower when crossing a
|
||||
// hardware-specific boundary.
|
||||
alignas(2) static const char data[] =
|
||||
alignas(2) static constexpr char data[] =
|
||||
"0001020304050607080910111213141516171819"
|
||||
"2021222324252627282930313233343536373839"
|
||||
"4041424344454647484950515253545556575859"
|
||||
@@ -1045,9 +1026,25 @@ inline auto digits2(size_t value) -> const char* {
|
||||
return &data[value * 2];
|
||||
}
|
||||
|
||||
// Given i in [0, 100), let x be the first 7 digits after
|
||||
// the decimal point of i / 100 in base 2, the first 2 bytes
|
||||
// after digits2_i(x) is the string representation of i.
|
||||
inline auto digits2_i(size_t value) noexcept -> const char* {
|
||||
alignas(2) static constexpr char data[] =
|
||||
"00010203 0405060707080910 1112"
|
||||
"131414151617 18192021 222324 "
|
||||
"25262728 2930313232333435 3637"
|
||||
"383939404142 43444546 474849 "
|
||||
"50515253 5455565757585960 6162"
|
||||
"636464656667 68697071 727374 "
|
||||
"75767778 7980818282838485 8687"
|
||||
"888989909192 93949596 979899 ";
|
||||
return &data[value * 2];
|
||||
}
|
||||
|
||||
template <typename Char> constexpr auto getsign(sign s) -> Char {
|
||||
return static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >>
|
||||
(static_cast<int>(s) * 8));
|
||||
return static_cast<Char>(static_cast<char>(
|
||||
((' ' << 24) | ('+' << 16) | ('-' << 8)) >> (static_cast<int>(s) * 8)));
|
||||
}
|
||||
|
||||
template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
|
||||
@@ -1065,7 +1062,7 @@ template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
|
||||
}
|
||||
}
|
||||
#if FMT_USE_INT128
|
||||
FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int {
|
||||
FMT_CONSTEXPR inline auto count_digits(native_uint128 n) -> int {
|
||||
return count_digits_fallback(n);
|
||||
}
|
||||
#endif
|
||||
@@ -1153,7 +1150,9 @@ FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
|
||||
template <typename Int> constexpr auto digits10() noexcept -> int {
|
||||
return std::numeric_limits<Int>::digits10;
|
||||
}
|
||||
template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; }
|
||||
template <> constexpr auto digits10<native_int128>() noexcept -> int {
|
||||
return 38;
|
||||
}
|
||||
template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; }
|
||||
|
||||
template <typename Char> struct thousands_sep_result {
|
||||
@@ -1166,7 +1165,7 @@ FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
|
||||
template <typename Char>
|
||||
inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {
|
||||
auto result = thousands_sep_impl<char>(loc);
|
||||
return {result.grouping, Char(result.thousands_sep)};
|
||||
return {std::move(result.grouping), Char(result.thousands_sep)};
|
||||
}
|
||||
template <>
|
||||
inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
|
||||
@@ -1213,6 +1212,16 @@ FMT_CONSTEXPR20 FMT_INLINE void write2digits(Char* out, size_t value) {
|
||||
*out = static_cast<Char>('0' + value % 10);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_INLINE void write2digits_i(Char* out, size_t value) {
|
||||
if (std::is_same<Char, char>::value && !FMT_OPTIMIZE_SIZE) {
|
||||
memcpy(out, digits2_i(value), 2);
|
||||
return;
|
||||
}
|
||||
*out++ = static_cast<Char>(digits2_i(value)[0]);
|
||||
*out = static_cast<Char>(digits2_i(value)[1]);
|
||||
}
|
||||
|
||||
// Formats a decimal unsigned integer value writing to out pointing to a buffer
|
||||
// of specified size. The caller must ensure that the buffer is large enough.
|
||||
template <typename Char, typename UInt>
|
||||
@@ -1221,12 +1230,19 @@ FMT_CONSTEXPR20 auto do_format_decimal(Char* out, UInt value, int size)
|
||||
FMT_ASSERT(size >= count_digits(value), "invalid digit count");
|
||||
unsigned n = to_unsigned(size);
|
||||
while (value >= 100) {
|
||||
// Integer division is slow so do it for a group of two digits instead
|
||||
// of for every digit. The idea comes from the talk by Alexandrescu
|
||||
// "Three Optimization Tips for C++". See speed-test for a comparison.
|
||||
n -= 2;
|
||||
write2digits(out + n, static_cast<unsigned>(value % 100));
|
||||
value /= 100;
|
||||
if (!is_constant_evaluated() && sizeof(UInt) == 4) {
|
||||
auto p = value * static_cast<uint64_t>((1ull << 39) / 100 + 1);
|
||||
write2digits_i(out + n, p >> (39 - 7) & ((1 << 7) - 1));
|
||||
value = static_cast<UInt>(p >> 39) +
|
||||
(static_cast<UInt>(value >= (100u << 25)) << 25);
|
||||
} else {
|
||||
// Integer division is slow so do it for a group of two digits instead
|
||||
// of for every digit. The idea comes from the talk by Alexandrescu
|
||||
// "Three Optimization Tips for C++". See speed-test for a comparison.
|
||||
write2digits(out + n, static_cast<unsigned>(value % 100));
|
||||
value /= 100;
|
||||
}
|
||||
}
|
||||
if (value >= 10) {
|
||||
n -= 2;
|
||||
@@ -1311,7 +1327,13 @@ class utf8_to_utf16 {
|
||||
inline auto str() const -> std::wstring { return {&buffer_[0], size()}; }
|
||||
};
|
||||
|
||||
enum class to_utf8_error_policy { abort, replace };
|
||||
enum class to_utf8_error_policy { abort, replace, wtf };
|
||||
|
||||
inline void to_utf8_3bytes(buffer<char>& buf, uint32_t cp) {
|
||||
buf.push_back(static_cast<char>(0xe0 | (cp >> 12)));
|
||||
buf.push_back(static_cast<char>(0x80 | ((cp & 0xfff) >> 6)));
|
||||
buf.push_back(static_cast<char>(0x80 | (cp & 0x3f)));
|
||||
}
|
||||
|
||||
// A converter from UTF-16/UTF-32 (host endian) to UTF-8.
|
||||
template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
|
||||
@@ -1353,8 +1375,13 @@ template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
|
||||
// Handle a surrogate pair.
|
||||
++p;
|
||||
if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
|
||||
if (policy == to_utf8_error_policy::abort) return false;
|
||||
buf.append(string_view("\xEF\xBF\xBD"));
|
||||
switch (policy) {
|
||||
case to_utf8_error_policy::abort: return false;
|
||||
case to_utf8_error_policy::replace:
|
||||
buf.append(string_view("\xEF\xBF\xBD"));
|
||||
break;
|
||||
case to_utf8_error_policy::wtf: to_utf8_3bytes(buf, c); break;
|
||||
}
|
||||
--p;
|
||||
continue;
|
||||
}
|
||||
@@ -1366,9 +1393,7 @@ template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
|
||||
buf.push_back(static_cast<char>(0xc0 | (c >> 6)));
|
||||
buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
} else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
|
||||
buf.push_back(static_cast<char>(0xe0 | (c >> 12)));
|
||||
buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
|
||||
buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
|
||||
to_utf8_3bytes(buf, c);
|
||||
} else if (c >= 0x10000 && c <= 0x10ffff) {
|
||||
buf.push_back(static_cast<char>(0xf0 | (c >> 18)));
|
||||
buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
|
||||
@@ -1383,11 +1408,11 @@ template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
|
||||
};
|
||||
|
||||
// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
|
||||
FMT_INLINE auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback {
|
||||
FMT_INLINE auto umul128(uint64_t x, uint64_t y) noexcept -> uint128 {
|
||||
#if FMT_USE_INT128
|
||||
auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
|
||||
auto p = static_cast<native_uint128>(x) * static_cast<native_uint128>(y);
|
||||
return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)};
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
#elif defined(_MSC_VER) && defined(_M_AMD64)
|
||||
auto hi = uint64_t();
|
||||
auto lo = _umul128(x, y, &hi);
|
||||
return {hi, lo};
|
||||
@@ -1428,9 +1453,9 @@ inline auto floor_log2_pow10(int e) noexcept -> int {
|
||||
// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
|
||||
inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t {
|
||||
#if FMT_USE_INT128
|
||||
auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
|
||||
auto p = static_cast<native_uint128>(x) * static_cast<native_uint128>(y);
|
||||
return static_cast<uint64_t>(p >> 64);
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
#elif defined(_MSC_VER) && defined(_M_AMD64)
|
||||
return __umulh(x, y);
|
||||
#else
|
||||
return umul128(x, y).high();
|
||||
@@ -1439,40 +1464,39 @@ inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t {
|
||||
|
||||
// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
|
||||
// 128-bit unsigned integer.
|
||||
inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept
|
||||
-> uint128_fallback {
|
||||
uint128_fallback r = umul128(x, y.high());
|
||||
inline auto umul192_upper128(uint64_t x, uint128 y) noexcept -> uint128 {
|
||||
uint128 r = umul128(x, y.high());
|
||||
r += umul128_upper64(x, y.low());
|
||||
return r;
|
||||
}
|
||||
|
||||
FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback;
|
||||
FMT_API auto get_cached_power(int k) noexcept -> uint128;
|
||||
|
||||
// Type-specific information that Dragonbox uses.
|
||||
template <typename T, typename Enable = void> struct float_info;
|
||||
|
||||
template <> struct float_info<float> {
|
||||
using carrier_uint = uint32_t;
|
||||
static const int exponent_bits = 8;
|
||||
static const int kappa = 1;
|
||||
static const int big_divisor = 100;
|
||||
static const int small_divisor = 10;
|
||||
static const int min_k = -31;
|
||||
static const int max_k = 46;
|
||||
static const int shorter_interval_tie_lower_threshold = -35;
|
||||
static const int shorter_interval_tie_upper_threshold = -35;
|
||||
static constexpr int exponent_bits = 8;
|
||||
static constexpr int kappa = 1;
|
||||
static constexpr int big_divisor = 100;
|
||||
static constexpr int small_divisor = 10;
|
||||
static constexpr int min_k = -31;
|
||||
enum { max_k = 46 };
|
||||
static constexpr int shorter_interval_tie_lower_threshold = -35;
|
||||
static constexpr int shorter_interval_tie_upper_threshold = -35;
|
||||
};
|
||||
|
||||
template <> struct float_info<double> {
|
||||
using carrier_uint = uint64_t;
|
||||
static const int exponent_bits = 11;
|
||||
static const int kappa = 2;
|
||||
static const int big_divisor = 1000;
|
||||
static const int small_divisor = 100;
|
||||
static const int min_k = -292;
|
||||
static const int max_k = 341;
|
||||
static const int shorter_interval_tie_lower_threshold = -77;
|
||||
static const int shorter_interval_tie_upper_threshold = -77;
|
||||
static constexpr int exponent_bits = 11;
|
||||
static constexpr int kappa = 2;
|
||||
static constexpr int big_divisor = 1000;
|
||||
static constexpr int small_divisor = 100;
|
||||
static constexpr int min_k = -292;
|
||||
enum { max_k = 341 };
|
||||
static constexpr int shorter_interval_tie_lower_threshold = -77;
|
||||
static constexpr int shorter_interval_tie_upper_threshold = -77;
|
||||
};
|
||||
|
||||
// An 80- or 128-bit floating point number.
|
||||
@@ -1608,7 +1632,7 @@ template <typename F> struct basic_fp {
|
||||
}
|
||||
};
|
||||
|
||||
using fp = basic_fp<unsigned long long>;
|
||||
using fp = basic_fp<ullong>;
|
||||
|
||||
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
|
||||
template <int SHIFT = 0, typename F>
|
||||
@@ -1739,7 +1763,7 @@ FMT_API auto is_printable(uint32_t cp) -> bool;
|
||||
|
||||
inline auto needs_escape(uint32_t cp) -> bool {
|
||||
if (cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\') return true;
|
||||
if (const_check(FMT_OPTIMIZE_SIZE > 1)) return false;
|
||||
if FMT_CONSTEXPR20 (FMT_OPTIMIZE_SIZE > 1) return false;
|
||||
return !is_printable(cp);
|
||||
}
|
||||
|
||||
@@ -1754,7 +1778,7 @@ auto find_escape(const Char* begin, const Char* end)
|
||||
-> find_escape_result<Char> {
|
||||
for (; begin != end; ++begin) {
|
||||
uint32_t cp = static_cast<unsigned_char<Char>>(*begin);
|
||||
if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue;
|
||||
if (sizeof(Char) == 1 && cp >= 0x80) continue;
|
||||
if (needs_escape(cp)) return {begin, begin + 1, cp};
|
||||
}
|
||||
return {begin, nullptr, 0};
|
||||
@@ -1762,7 +1786,7 @@ auto find_escape(const Char* begin, const Char* end)
|
||||
|
||||
inline auto find_escape(const char* begin, const char* end)
|
||||
-> find_escape_result<char> {
|
||||
if (const_check(!use_utf8)) return find_escape<char>(begin, end);
|
||||
if FMT_CONSTEXPR20 (!use_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) {
|
||||
@@ -1890,7 +1914,7 @@ template <typename Char> class digit_grouping {
|
||||
explicit digit_grouping(locale_ref loc, bool localized = true) {
|
||||
if (!localized) return;
|
||||
auto sep = thousands_sep<Char>(loc);
|
||||
grouping_ = sep.grouping;
|
||||
grouping_ = std::move(sep.grouping);
|
||||
if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
|
||||
}
|
||||
digit_grouping(std::string grouping, std::basic_string<Char> sep)
|
||||
@@ -2335,9 +2359,8 @@ FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||
++begin;
|
||||
}
|
||||
break;
|
||||
} else if (p == begin) {
|
||||
break;
|
||||
}
|
||||
if (p == begin) break;
|
||||
p = begin;
|
||||
}
|
||||
specs.set_align(alignment);
|
||||
@@ -2534,7 +2557,7 @@ FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP& f,
|
||||
auto grouping = Grouping(loc, specs.localized());
|
||||
size += grouping.count_separators(exp);
|
||||
return write_padded<Char, align::right>(
|
||||
out, specs, to_unsigned(size), [&](iterator it) {
|
||||
out, specs, static_cast<size_t>(size), [&](iterator it) {
|
||||
if (s != sign::none) *it++ = detail::getsign<Char>(s);
|
||||
it = write_significand(it, f.significand, significand_size, exp,
|
||||
decimal_point, grouping);
|
||||
@@ -2550,7 +2573,7 @@ FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP& f,
|
||||
bool pointy = num_zeros != 0 || significand_size != 0 || specs.alt();
|
||||
size += 1 + (pointy ? 1 : 0) + num_zeros;
|
||||
return write_padded<Char, align::right>(
|
||||
out, specs, to_unsigned(size), [&](iterator it) {
|
||||
out, specs, static_cast<size_t>(size), [&](iterator it) {
|
||||
if (s != sign::none) *it++ = detail::getsign<Char>(s);
|
||||
*it++ = Char('0');
|
||||
if (!pointy) return it;
|
||||
@@ -2594,7 +2617,7 @@ FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
|
||||
*it++ = Char(exp_char);
|
||||
return write_exponent<Char>(exp, it);
|
||||
};
|
||||
auto usize = to_unsigned(size);
|
||||
size_t usize = static_cast<size_t>(size);
|
||||
return specs.width > 0
|
||||
? write_padded<Char, align::right>(out, specs, usize, write)
|
||||
: base_iterator(out, write(reserve(out, usize)));
|
||||
@@ -3138,8 +3161,9 @@ constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t {
|
||||
// It is equal to ceil(2^31 + 2^32/10^(k + 1)).
|
||||
// These are stored in a string literal because we cannot have static arrays
|
||||
// in constexpr functions and non-static ones are poorly optimized.
|
||||
return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
|
||||
U"\x800001ae\x8000002b"[index];
|
||||
return uint32_t(u"\x9999\x828f\x8041\x8006\x8000\x8000\x8000\x8000"[index])
|
||||
<< 16u |
|
||||
uint32_t(u"\x999a\x5c29\x8938\x8db9\xa7c6\x10c7\x01ae\x002b"[index]);
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
@@ -3544,8 +3568,8 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
|
||||
memcpy(ptr, prefix, 2);
|
||||
ptr += 2;
|
||||
} else {
|
||||
*ptr++ = prefix[0];
|
||||
*ptr++ = prefix[1];
|
||||
*ptr++ = static_cast<Char>(prefix[0]);
|
||||
*ptr++ = static_cast<Char>(prefix[1]);
|
||||
}
|
||||
if (abs_exponent >= 100) {
|
||||
*ptr++ = static_cast<Char>('0' + abs_exponent / 100);
|
||||
@@ -3697,12 +3721,12 @@ template <typename Char> struct arg_formatter {
|
||||
|
||||
struct dynamic_spec_getter {
|
||||
template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
|
||||
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
|
||||
return is_negative(value) ? ~0ull : static_cast<unsigned long long>(value);
|
||||
FMT_CONSTEXPR auto operator()(T value) -> ullong {
|
||||
return is_negative(value) ? ~0ull : static_cast<ullong>(value);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
|
||||
FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
|
||||
FMT_CONSTEXPR auto operator()(T) -> ullong {
|
||||
report_error("width/precision is not integer");
|
||||
return 0;
|
||||
}
|
||||
@@ -3716,7 +3740,7 @@ FMT_CONSTEXPR void handle_dynamic_spec(
|
||||
auto arg =
|
||||
kind == arg_id_kind::index ? ctx.arg(ref.index) : ctx.arg(ref.name);
|
||||
if (!arg) report_error("argument not found");
|
||||
unsigned long long result = arg.visit(dynamic_spec_getter());
|
||||
ullong result = arg.visit(dynamic_spec_getter());
|
||||
if (result > to_unsigned(max_value<int>()))
|
||||
report_error("width/precision is out of range");
|
||||
value = static_cast<int>(result);
|
||||
@@ -3751,7 +3775,7 @@ struct udl_arg {
|
||||
template <typename Char> struct udl_arg {
|
||||
const Char* str;
|
||||
|
||||
template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
|
||||
template <typename T> auto operator=(T&& value) const -> named_arg<T, Char> {
|
||||
return {str, std::forward<T>(value)};
|
||||
}
|
||||
};
|
||||
@@ -3864,7 +3888,7 @@ template <typename OutputIt, typename Char> class generic_context {
|
||||
|
||||
constexpr auto out() const -> iterator { return out_; }
|
||||
|
||||
void advance_to(iterator it) {
|
||||
FMT_CONSTEXPR void advance_to(iterator it) {
|
||||
if (!detail::is_back_insert_iterator<iterator>()) out_ = it;
|
||||
}
|
||||
|
||||
@@ -3906,8 +3930,8 @@ template <typename Locale> class format_facet : public Locale::facet {
|
||||
explicit format_facet(string_view sep = "", std::string grouping = "\3",
|
||||
std::string decimal_point = ".")
|
||||
: separator_(sep.data(), sep.size()),
|
||||
grouping_(grouping),
|
||||
decimal_point_(decimal_point) {}
|
||||
grouping_(std::move(grouping)),
|
||||
decimal_point_(std::move(decimal_point)) {}
|
||||
|
||||
auto put(appender out, loc_value val, const format_specs& specs) const
|
||||
-> bool {
|
||||
@@ -3943,12 +3967,6 @@ template <typename Char, typename Traits, typename Allocator>
|
||||
class formatter<std::basic_string<Char, Traits, Allocator>, Char>
|
||||
: public formatter<basic_string_view<Char>, Char> {};
|
||||
|
||||
template <int N, typename Char>
|
||||
struct formatter<detail::bitint<N>, Char> : formatter<long long, Char> {};
|
||||
template <int N, typename Char>
|
||||
struct formatter<detail::ubitint<N>, Char>
|
||||
: formatter<unsigned long long, Char> {};
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<detail::float128, Char>
|
||||
: detail::native_formatter<detail::float128, Char,
|
||||
@@ -3997,19 +4015,6 @@ constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> {
|
||||
}
|
||||
} // namespace enums
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
template <typename Char>
|
||||
struct formatter<std::byte, Char> : formatter<unsigned, Char> {
|
||||
static auto format_as(std::byte b) -> unsigned char {
|
||||
return static_cast<unsigned char>(b);
|
||||
}
|
||||
template <typename Context>
|
||||
auto format(std::byte b, Context& ctx) const -> decltype(ctx.out()) {
|
||||
return formatter<unsigned, Char>::format(format_as(b), ctx);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct bytes {
|
||||
string_view data;
|
||||
|
||||
@@ -4142,6 +4147,14 @@ template <typename T, typename Char = char> struct nested_formatter {
|
||||
|
||||
inline namespace literals {
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
/**
|
||||
* User-defined literal equivalent of `fmt::arg`, but with compile-time checks.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* using namespace fmt::literals;
|
||||
* fmt::print("The answer is {answer}.", "answer"_a=42);
|
||||
*/
|
||||
template <detail::fixed_string S> constexpr auto operator""_a() {
|
||||
using char_t = remove_cvref_t<decltype(*S.data)>;
|
||||
return detail::udl_arg<char_t, sizeof(S.data) / sizeof(char_t), S>();
|
||||
@@ -4166,7 +4179,7 @@ class format_int {
|
||||
private:
|
||||
// Buffer should be large enough to hold all digits (digits10 + 1),
|
||||
// a sign and a null character.
|
||||
enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
|
||||
enum { buffer_size = std::numeric_limits<ullong>::digits10 + 3 };
|
||||
mutable char buffer_[buffer_size];
|
||||
char* str_;
|
||||
|
||||
@@ -4196,7 +4209,7 @@ class format_int {
|
||||
: str_(format_unsigned(value)) {}
|
||||
FMT_CONSTEXPR20 explicit format_int(unsigned long value)
|
||||
: str_(format_unsigned(value)) {}
|
||||
FMT_CONSTEXPR20 explicit format_int(unsigned long long value)
|
||||
FMT_CONSTEXPR20 explicit format_int(ullong value)
|
||||
: str_(format_unsigned(value)) {}
|
||||
|
||||
/// Returns the number of characters written to the output buffer.
|
||||
@@ -4248,7 +4261,11 @@ class format_int {
|
||||
* // A compile-time error because 'd' is an invalid specifier for strings.
|
||||
* std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
|
||||
*/
|
||||
#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string)
|
||||
#if FMT_USE_CONSTEVAL
|
||||
# define FMT_STRING(s) s
|
||||
#else
|
||||
# define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string)
|
||||
#endif // FMT_USE_CONSTEVAL
|
||||
|
||||
FMT_API auto vsystem_error(int error_code, string_view fmt, format_args args)
|
||||
-> std::system_error;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - optional OS-specific functionality
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -161,14 +161,6 @@ inline auto system_category() noexcept -> const std::error_category& {
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
// std::system is not available on some platforms such as iOS (#2248).
|
||||
#ifdef __OSX__
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
void say(const S& fmt, Args&&... args) {
|
||||
std::system(format("say \"{}\"", format(fmt, args...)).c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// A buffered file.
|
||||
class buffered_file {
|
||||
private:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - std::ostream support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -38,7 +38,7 @@ namespace detail {
|
||||
namespace {
|
||||
struct file_access_tag {};
|
||||
} // namespace
|
||||
template <typename Tag, typename BufType, FILE* BufType::*FileMemberPtr>
|
||||
template <typename Tag, typename BufType, FILE* BufType::* FileMemberPtr>
|
||||
class file_access {
|
||||
friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
|
||||
};
|
||||
@@ -150,7 +150,7 @@ inline void vprint(std::ostream& os, string_view fmt, format_args args) {
|
||||
FMT_EXPORT template <typename... T>
|
||||
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
||||
fmt::vargs<T...> vargs = {{args...}};
|
||||
if (detail::const_check(detail::use_utf8)) return vprint(os, fmt.str, vargs);
|
||||
if FMT_CONSTEXPR20 (detail::use_utf8) return vprint(os, fmt.str, vargs);
|
||||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, fmt.str, vargs);
|
||||
detail::write_buffer(os, buffer);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - legacy printf implementation
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -136,7 +136,7 @@ template <typename T, typename Context> class arg_converter {
|
||||
void operator()(U value) {
|
||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
|
||||
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
||||
if FMT_CONSTEXPR20 (sizeof(target_type) <= sizeof(int)) {
|
||||
// Extra casts are used to silence warnings.
|
||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||
if (is_signed)
|
||||
@@ -330,6 +330,7 @@ template <typename Char, typename GetArg>
|
||||
auto parse_header(const Char*& it, const Char* end, format_specs& specs,
|
||||
GetArg get_arg) -> int {
|
||||
int arg_index = -1;
|
||||
if (it == end) return arg_index;
|
||||
Char c = *it;
|
||||
if (c >= '0' && c <= '9') {
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
@@ -357,8 +358,21 @@ auto parse_header(const Char*& it, const Char* end, format_specs& specs,
|
||||
if (specs.width == -1) report_error("number is too big");
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
specs.width = static_cast<int>(
|
||||
get_arg(-1).visit(detail::printf_width_handler(specs)));
|
||||
// Check for positional width argument like *1$
|
||||
if (it != end && *it >= '0' && *it <= '9') {
|
||||
int width_index = parse_nonnegative_int(it, end, -1);
|
||||
if (it != end && *it == '$') {
|
||||
++it;
|
||||
specs.width = static_cast<int>(
|
||||
get_arg(width_index).visit(detail::printf_width_handler(specs)));
|
||||
} else {
|
||||
// Invalid format, rewind and treat as non-positional
|
||||
report_error("invalid format specifier");
|
||||
}
|
||||
} else {
|
||||
specs.width = static_cast<int>(
|
||||
get_arg(-1).visit(detail::printf_width_handler(specs)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return arg_index;
|
||||
@@ -424,6 +438,8 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
}
|
||||
write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start)));
|
||||
|
||||
if (it == end) report_error("invalid format string");
|
||||
|
||||
auto specs = format_specs();
|
||||
specs.set_align(align::right);
|
||||
|
||||
@@ -439,15 +455,28 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
specs.precision = parse_nonnegative_int(it, end, 0);
|
||||
} else if (c == '*') {
|
||||
++it;
|
||||
specs.precision =
|
||||
static_cast<int>(get_arg(-1).visit(printf_precision_handler()));
|
||||
// Check for positional precision argument like .*1$
|
||||
if (it != end && *it >= '0' && *it <= '9') {
|
||||
int precision_index = parse_nonnegative_int(it, end, -1);
|
||||
if (it != end && *it == '$') {
|
||||
++it;
|
||||
specs.precision = static_cast<int>(
|
||||
get_arg(precision_index).visit(printf_precision_handler()));
|
||||
} else {
|
||||
// Invalid format, rewind and treat as non-positional
|
||||
report_error("invalid format specifier");
|
||||
}
|
||||
} else {
|
||||
specs.precision =
|
||||
static_cast<int>(get_arg(-1).visit(printf_precision_handler()));
|
||||
}
|
||||
} else {
|
||||
specs.precision = 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto arg = get_arg(arg_index);
|
||||
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
||||
// For d, i, o, u, x and X conversion specifiers, if a precision is
|
||||
// specified, the '0' flag is ignored
|
||||
if (specs.precision >= 0 && is_integral_type(arg.type())) {
|
||||
// Ignore '0' for non-numeric types or if '-' present.
|
||||
@@ -560,7 +589,7 @@ inline auto vsprintf(basic_string_view<Char> fmt,
|
||||
|
||||
/**
|
||||
* Formats `args` according to specifications in `fmt` and returns the result
|
||||
* as as string.
|
||||
* as string.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
|
||||
@@ -69,11 +69,12 @@ struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
|
||||
|
||||
// Member function overloads.
|
||||
template <typename T>
|
||||
auto range_begin(T&& rng) -> decltype(static_cast<T&&>(rng).begin()) {
|
||||
FMT_CONSTEXPR auto range_begin(T&& rng)
|
||||
-> decltype(static_cast<T&&>(rng).begin()) {
|
||||
return static_cast<T&&>(rng).begin();
|
||||
}
|
||||
template <typename T>
|
||||
auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
|
||||
FMT_CONSTEXPR auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
|
||||
return static_cast<T&&>(rng).end();
|
||||
}
|
||||
|
||||
@@ -129,6 +130,13 @@ template <typename T> class is_tuple_like_ {
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename _ = void>
|
||||
struct is_optional_like_ : std::false_type {};
|
||||
template <typename T>
|
||||
struct is_optional_like_<T, void_t<decltype(std::declval<T>().has_value()),
|
||||
decltype(std::declval<T>().value())>>
|
||||
: std::true_type {};
|
||||
|
||||
// Check for integer_sequence
|
||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
|
||||
template <typename T, T... N>
|
||||
@@ -343,8 +351,9 @@ struct formatter<Tuple, Char,
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T, typename Char> struct is_range {
|
||||
static constexpr bool value =
|
||||
detail::is_range_<T>::value && !detail::has_to_string_view<T>::value;
|
||||
static constexpr bool value = detail::is_range_<T>::value &&
|
||||
!detail::is_optional_like_<T>::value &&
|
||||
!detail::has_to_string_view<T>::value;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@@ -460,7 +469,8 @@ struct range_formatter<
|
||||
}
|
||||
|
||||
template <typename R, typename FormatContext>
|
||||
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(R&& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
auto it = detail::range_begin(range);
|
||||
auto end = detail::range_end(range);
|
||||
@@ -505,8 +515,7 @@ struct formatter<
|
||||
using nonlocking = void;
|
||||
|
||||
FMT_CONSTEXPR formatter() {
|
||||
if (detail::const_check(range_format_kind<R, Char>::value !=
|
||||
range_format::set))
|
||||
if FMT_CONSTEXPR20 (range_format_kind<R, Char>::value != range_format::set)
|
||||
return;
|
||||
range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
|
||||
detail::string_literal<Char, '}'>{});
|
||||
@@ -517,7 +526,7 @@ struct formatter<
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return range_formatter_.format(range, ctx);
|
||||
}
|
||||
@@ -607,13 +616,14 @@ struct formatter<
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
if (detail::const_check(range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string))
|
||||
if FMT_CONSTEXPR20 (range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string) {
|
||||
*out++ = '"';
|
||||
}
|
||||
out = underlying_.format(
|
||||
string_type{detail::range_begin(range), detail::range_end(range)}, ctx);
|
||||
if (detail::const_check(range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string))
|
||||
if FMT_CONSTEXPR20 (range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string)
|
||||
*out++ = '"';
|
||||
return out;
|
||||
}
|
||||
@@ -625,7 +635,7 @@ struct join_view : detail::view {
|
||||
Sentinel end;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
join_view(It b, Sentinel e, basic_string_view<Char> s)
|
||||
FMT_CONSTEXPR join_view(It b, Sentinel e, basic_string_view<Char> s)
|
||||
: begin(std::move(b)), end(e), sep(s) {}
|
||||
};
|
||||
|
||||
@@ -652,7 +662,8 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(view& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
using iter =
|
||||
conditional_t<std::is_copy_constructible<view>::value, It, It&>;
|
||||
iter it = value.begin;
|
||||
@@ -675,7 +686,7 @@ template <typename Tuple, typename Char> struct tuple_join_view : detail::view {
|
||||
const Tuple& tuple;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
tuple_join_view(const Tuple& t, basic_string_view<Char> s)
|
||||
FMT_CONSTEXPR tuple_join_view(const Tuple& t, basic_string_view<Char> s)
|
||||
: tuple(t), sep{s} {}
|
||||
};
|
||||
|
||||
@@ -694,8 +705,9 @@ struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx) const -> typename FormatContext::iterator {
|
||||
FMT_CONSTEXPR auto format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx) const ->
|
||||
typename FormatContext::iterator {
|
||||
return do_format(value, ctx, std::tuple_size<Tuple>());
|
||||
}
|
||||
|
||||
@@ -726,15 +738,17 @@ struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto do_format(const tuple_join_view<Tuple, Char>&, FormatContext& ctx,
|
||||
std::integral_constant<size_t, 0>) const ->
|
||||
FMT_CONSTEXPR auto do_format(const tuple_join_view<Tuple, Char>&,
|
||||
FormatContext& ctx,
|
||||
std::integral_constant<size_t, 0>) const ->
|
||||
typename FormatContext::iterator {
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
template <typename FormatContext, size_t N>
|
||||
auto do_format(const tuple_join_view<Tuple, Char>& value, FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
FMT_CONSTEXPR auto do_format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
typename FormatContext::iterator {
|
||||
using std::get;
|
||||
auto out =
|
||||
@@ -748,9 +762,20 @@ struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// Check if T has an interface like a container adaptor (e.g. std::stack,
|
||||
// std::queue, std::priority_queue).
|
||||
template <typename T> class is_container_adaptor_like {
|
||||
template <typename Container> struct all {
|
||||
const Container& c;
|
||||
auto begin() const -> typename Container::const_iterator { return c.begin(); }
|
||||
auto end() const -> typename Container::const_iterator { return c.end(); }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Specifies if `T` is a container adaptor (like `std::stack`) that should be
|
||||
* formatted as the underlying container.
|
||||
*/
|
||||
FMT_EXPORT
|
||||
template <typename T> struct is_container_adaptor {
|
||||
private:
|
||||
template <typename U> static auto check(U* p) -> typename U::container_type;
|
||||
template <typename> static void check(...);
|
||||
|
||||
@@ -759,17 +784,10 @@ template <typename T> class is_container_adaptor_like {
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename Container> struct all {
|
||||
const Container& c;
|
||||
auto begin() const -> typename Container::const_iterator { return c.begin(); }
|
||||
auto end() const -> typename Container::const_iterator { return c.end(); }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<
|
||||
T, Char,
|
||||
enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
|
||||
enable_if_t<conjunction<is_container_adaptor<T>,
|
||||
bool_constant<range_format_kind<T, Char>::value ==
|
||||
range_format::disabled>>::value>>
|
||||
: formatter<detail::all<typename T::container_type>, Char> {
|
||||
@@ -809,7 +827,7 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
|
||||
* // Output: 01, 02, 03
|
||||
*/
|
||||
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& r, string_view sep)
|
||||
FMT_CONSTEXPR auto join(Range&& r, string_view sep)
|
||||
-> join_view<decltype(detail::range_begin(r)),
|
||||
decltype(detail::range_end(r))> {
|
||||
return {detail::range_begin(r), detail::range_end(r), sep};
|
||||
@@ -840,7 +858,7 @@ FMT_CONSTEXPR auto join(const Tuple& tuple FMT_LIFETIMEBOUND, string_view sep)
|
||||
* // Output: "1, 2, 3"
|
||||
*/
|
||||
template <typename T>
|
||||
auto join(std::initializer_list<T> list, string_view sep)
|
||||
FMT_DEPRECATED auto join(std::initializer_list<T> list, string_view sep)
|
||||
-> join_view<const T*, const T*> {
|
||||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - formatters for standard library types
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -15,7 +15,8 @@
|
||||
# include <atomic>
|
||||
# include <bitset>
|
||||
# include <complex>
|
||||
# include <exception>
|
||||
# include <cstddef> // std::byte
|
||||
# include <exception> // std::exception
|
||||
# include <functional> // std::reference_wrapper
|
||||
# include <memory>
|
||||
# include <thread>
|
||||
@@ -79,15 +80,34 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
#ifdef FMT_USE_BITINT
|
||||
// Use the provided definition.
|
||||
#elif FMT_CLANG_VERSION >= 1500 && !defined(__CUDACC__)
|
||||
# define FMT_USE_BITINT 1
|
||||
#else
|
||||
# define FMT_USE_BITINT 0
|
||||
#endif
|
||||
|
||||
#if FMT_USE_BITINT
|
||||
FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension")
|
||||
template <int N> using bitint = _BitInt(N);
|
||||
template <int N> using ubitint = unsigned _BitInt(N);
|
||||
#else
|
||||
template <int N> struct bitint {};
|
||||
template <int N> struct ubitint {};
|
||||
#endif // FMT_USE_BITINT
|
||||
|
||||
#if FMT_CPP_LIB_FILESYSTEM
|
||||
|
||||
template <typename Char, typename PathChar>
|
||||
auto get_path_string(const std::filesystem::path& p,
|
||||
const std::basic_string<PathChar>& native) {
|
||||
if constexpr (std::is_same_v<Char, char> && std::is_same_v<PathChar, wchar_t>)
|
||||
return to_utf8<wchar_t>(native, to_utf8_error_policy::replace);
|
||||
else
|
||||
if constexpr (std::is_same_v<Char, char> &&
|
||||
std::is_same_v<PathChar, wchar_t>) {
|
||||
return to_utf8<wchar_t>(native, to_utf8_error_policy::wtf);
|
||||
} else {
|
||||
return p.string<Char>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char, typename PathChar>
|
||||
@@ -113,8 +133,8 @@ void write_escaped_path(basic_memory_buffer<Char>& quoted,
|
||||
#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT
|
||||
|
||||
template <typename Char, typename OutputIt, typename T, typename FormatContext>
|
||||
auto write_escaped_alternative(OutputIt out, const T& v, FormatContext& ctx)
|
||||
-> OutputIt {
|
||||
FMT_CONSTEXPR auto write_escaped_alternative(OutputIt out, const T& v,
|
||||
FormatContext& ctx) -> OutputIt {
|
||||
if constexpr (has_to_string_view<T>::value)
|
||||
return write_escaped_string<Char>(out, detail::to_string_view(v));
|
||||
if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v);
|
||||
@@ -434,6 +454,26 @@ struct formatter<std::expected<T, E>, Char,
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename E, typename Char>
|
||||
struct formatter<std::unexpected<E>, Char,
|
||||
std::enable_if_t<is_formattable<E, Char>::value>> {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::unexpected<E>& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
|
||||
out = detail::write<Char>(out, "unexpected(");
|
||||
out = detail::write_escaped_alternative<Char>(out, value.error(), ctx);
|
||||
|
||||
*out++ = ')';
|
||||
return out;
|
||||
}
|
||||
};
|
||||
#endif // __cpp_lib_expected
|
||||
|
||||
#ifdef __cpp_lib_source_location
|
||||
@@ -468,7 +508,7 @@ template <typename Char> struct formatter<std::monostate, Char> {
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::monostate&, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR auto format(const std::monostate&, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return detail::write<Char>(ctx.out(), "monostate");
|
||||
}
|
||||
@@ -484,7 +524,7 @@ struct formatter<Variant, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Variant& value, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR20 auto format(const Variant& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
|
||||
@@ -609,6 +649,30 @@ struct formatter<
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, typename Char>
|
||||
struct formatter<detail::bitint<N>, Char> : formatter<long long, Char> {
|
||||
static_assert(N <= 64, "unsupported _BitInt");
|
||||
static auto format_as(detail::bitint<N> x) -> long long {
|
||||
return static_cast<long long>(x);
|
||||
}
|
||||
template <typename Context>
|
||||
auto format(detail::bitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
|
||||
return formatter<long long, Char>::format(format_as(x), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, typename Char>
|
||||
struct formatter<detail::ubitint<N>, Char> : formatter<ullong, Char> {
|
||||
static_assert(N <= 64, "unsupported _BitInt");
|
||||
static auto format_as(detail::ubitint<N> x) -> ullong {
|
||||
return static_cast<ullong>(x);
|
||||
}
|
||||
template <typename Context>
|
||||
auto format(detail::ubitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
|
||||
return formatter<ullong, Char>::format(format_as(x), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
// We can't use std::vector<bool, Allocator>::reference and
|
||||
// std::bitset<N>::reference because the compiler can't deduce Allocator and N
|
||||
// in partial specialization.
|
||||
@@ -623,6 +687,20 @@ struct formatter<BitRef, Char,
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
template <typename Char>
|
||||
struct formatter<std::byte, Char> : formatter<unsigned, Char> {
|
||||
FMT_CONSTEXPR static auto format_as(std::byte b) -> unsigned char {
|
||||
return static_cast<unsigned char>(b);
|
||||
}
|
||||
template <typename Context>
|
||||
FMT_CONSTEXPR auto format(std::byte b, Context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return formatter<unsigned, Char>::format(format_as(b), ctx);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<std::atomic<T>, Char,
|
||||
enable_if_t<is_formattable<T, Char>::value>>
|
||||
@@ -645,6 +723,11 @@ struct formatter<std::atomic_flag, Char> : formatter<bool, Char> {
|
||||
};
|
||||
#endif // __cpp_lib_atomic_flag_test
|
||||
|
||||
template <typename T> struct is_tuple_like;
|
||||
|
||||
template <typename T>
|
||||
struct is_tuple_like<std::complex<T>> : std::false_type {};
|
||||
|
||||
template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
||||
private:
|
||||
detail::dynamic_format_specs<Char> specs_;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - optional wchar_t and exotic character support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -109,7 +109,7 @@ template <typename Char, typename... T> struct basic_fstring {
|
||||
}
|
||||
basic_fstring(runtime_format_string<Char> fmt) : str_(fmt.str) {}
|
||||
|
||||
operator basic_string_view<Char>() const { return str_; }
|
||||
FMT_DEPRECATED operator basic_string_view<Char>() const { return str_; }
|
||||
auto get() const -> basic_string_view<Char> { return str_; }
|
||||
};
|
||||
|
||||
@@ -136,29 +136,42 @@ inline auto operator""_a(const wchar_t* s, size_t) -> detail::udl_arg<wchar_t> {
|
||||
} // namespace literals
|
||||
#endif
|
||||
|
||||
template <typename It, typename Sentinel>
|
||||
auto join(It begin, Sentinel end, wstring_view sep)
|
||||
-> join_view<It, Sentinel, wchar_t> {
|
||||
return {begin, end, sep};
|
||||
template <typename T>
|
||||
auto arg(const wchar_t* name, const T& arg) -> named_arg<T, wchar_t> {
|
||||
return {name, arg};
|
||||
}
|
||||
|
||||
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& range, wstring_view sep)
|
||||
-> join_view<decltype(std::begin(range)), decltype(std::end(range)),
|
||||
wchar_t> {
|
||||
return join(std::begin(range), std::end(range), sep);
|
||||
template <typename It, typename Sentinel, typename S,
|
||||
typename Char = typename decltype(detail::to_string_view(
|
||||
std::declval<S>()))::value_type,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||
auto join(It begin, Sentinel end, S&& sep) -> join_view<It, Sentinel, Char> {
|
||||
return {begin, end, detail::to_string_view(sep)};
|
||||
}
|
||||
|
||||
template <typename Range, typename S,
|
||||
typename Char = typename decltype(detail::to_string_view(
|
||||
std::declval<S>()))::value_type,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value &&
|
||||
!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& range, S&& sep)
|
||||
-> join_view<decltype(std::begin(range)), decltype(std::end(range)), Char> {
|
||||
return {std::begin(range), std::end(range), detail::to_string_view(sep)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto join(std::initializer_list<T> list, wstring_view sep)
|
||||
FMT_DEPRECATED auto join(std::initializer_list<T> list, wstring_view sep)
|
||||
-> join_view<const T*, const T*, wchar_t> {
|
||||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
|
||||
auto join(const Tuple& tuple, basic_string_view<wchar_t> sep)
|
||||
-> tuple_join_view<Tuple, wchar_t> {
|
||||
return {tuple, sep};
|
||||
template <typename Tuple, typename S,
|
||||
typename Char = typename decltype(detail::to_string_view(
|
||||
std::declval<S>()))::value_type,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value&&
|
||||
is_tuple_like<Tuple>::value)>
|
||||
auto join(const Tuple& tuple, S&& sep) -> tuple_join_view<Tuple, Char> {
|
||||
return {tuple, detail::to_string_view(sep)};
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
@@ -172,14 +185,13 @@ auto vformat(basic_string_view<Char> fmt,
|
||||
|
||||
template <typename... T>
|
||||
auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
|
||||
return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
|
||||
return vformat(fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename... T>
|
||||
auto format_to(OutputIt out, wformat_string<T...> fmt, T&&... args)
|
||||
-> OutputIt {
|
||||
return vformat_to(out, fmt::wstring_view(fmt),
|
||||
fmt::make_wformat_args(args...));
|
||||
return vformat_to(out, fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
// Pass char_t as a default template parameter instead of using
|
||||
@@ -267,10 +279,18 @@ inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view<Char> fmt,
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename... T,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, wchar_t>::value)>
|
||||
FMT_INLINE auto format_to_n(OutputIt out, size_t n, wformat_string<T...> fmt,
|
||||
T&&... args) -> format_to_n_result<OutputIt> {
|
||||
return vformat_to_n(out, n, fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... T,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value &&
|
||||
!std::is_same<Char, char>::value &&
|
||||
!std::is_same<Char, wchar_t>::value)>
|
||||
inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
return vformat_to_n(out, n, fmt::basic_string_view<Char>(fmt),
|
||||
@@ -301,11 +321,11 @@ inline void vprint(wstring_view fmt, wformat_args args) {
|
||||
|
||||
template <typename... T>
|
||||
void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
|
||||
return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
|
||||
return vprint(f, fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
|
||||
return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
|
||||
return vprint(fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
@@ -327,7 +347,7 @@ inline auto vformat(text_style ts, wstring_view fmt, wformat_args args)
|
||||
template <typename... T>
|
||||
inline auto format(text_style ts, wformat_string<T...> fmt, T&&... args)
|
||||
-> std::wstring {
|
||||
return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...));
|
||||
return fmt::vformat(ts, fmt.get(), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) {
|
||||
@@ -338,7 +358,8 @@ inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) {
|
||||
|
||||
template <typename... T>
|
||||
void print(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
|
||||
vprint(os, fmt, fmt::make_format_args<buffered_context<wchar_t>>(args...));
|
||||
vprint(os, fmt.get(),
|
||||
fmt::make_format_args<buffered_context<wchar_t>>(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
||||
67
wpiutil/src/main/native/thirdparty/fmtlib/src/fmt-c.cpp
vendored
Normal file
67
wpiutil/src/main/native/thirdparty/fmtlib/src/fmt-c.cpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Formatting library for C++ - the C API
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "fmt/fmt-c.h"
|
||||
|
||||
#include <fmt/base.h>
|
||||
|
||||
constexpr size_t max_c_format_args = 16;
|
||||
|
||||
static int convert_c_format_args(
|
||||
fmt::basic_format_arg<fmt::format_context>* format_args,
|
||||
const fmt_arg* args, size_t num_args) {
|
||||
if (num_args > max_c_format_args) return fmt_error_invalid_arg;
|
||||
|
||||
for (size_t i = 0; i < num_args; ++i) {
|
||||
switch (args[i].type) {
|
||||
case fmt_int: format_args[i] = args[i].value.int_value; break;
|
||||
case fmt_uint: format_args[i] = args[i].value.uint_value; break;
|
||||
case fmt_bool: format_args[i] = args[i].value.bool_value; break;
|
||||
case fmt_char: format_args[i] = args[i].value.char_value; break;
|
||||
case fmt_float: format_args[i] = args[i].value.float_value; break;
|
||||
case fmt_double: format_args[i] = args[i].value.double_value; break;
|
||||
case fmt_long_double:
|
||||
format_args[i] = args[i].value.long_double_value;
|
||||
break;
|
||||
case fmt_cstring: format_args[i] = args[i].value.cstring; break;
|
||||
case fmt_pointer: format_args[i] = args[i].value.pointer; break;
|
||||
default: return fmt_error_invalid_arg;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
|
||||
const fmt_arg* args, size_t num_args) {
|
||||
fmt::basic_format_arg<fmt::format_context> format_args[max_c_format_args];
|
||||
int error = convert_c_format_args(format_args, args, num_args);
|
||||
if (error != 0) return error;
|
||||
|
||||
FMT_TRY {
|
||||
auto result = fmt::vformat_to_n(
|
||||
buffer, size, fmt,
|
||||
fmt::format_args(format_args, static_cast<int>(num_args)));
|
||||
return static_cast<int>(result.size);
|
||||
}
|
||||
FMT_CATCH(...) {}
|
||||
return fmt_error;
|
||||
}
|
||||
|
||||
extern "C" int fmt_vprint(FILE* stream, const char* fmt, const fmt_arg* args,
|
||||
size_t num_args) {
|
||||
fmt::basic_format_arg<fmt::format_context> format_args[max_c_format_args];
|
||||
int error = convert_c_format_args(format_args, args, num_args);
|
||||
if (error != 0) return error;
|
||||
|
||||
FMT_TRY {
|
||||
fmt::vprint(stream, fmt,
|
||||
fmt::format_args(format_args, static_cast<int>(num_args)));
|
||||
return 0;
|
||||
}
|
||||
FMT_CATCH(...) {}
|
||||
return fmt_error;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Formatting library for C++ - optional OS-specific functionality
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "fmt/os.h"
|
||||
|
||||
#ifndef FMT_MODULE
|
||||
# include <climits>
|
||||
|
||||
# if FMT_USE_FCNTL
|
||||
# include <sys/stat.h>
|
||||
@@ -35,6 +34,8 @@
|
||||
|
||||
# ifdef _WIN32
|
||||
# include <windows.h>
|
||||
|
||||
# include <climits> // CHAR_BIT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -61,6 +62,7 @@
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
|
||||
// Return type of read and write functions.
|
||||
using rwresult = int;
|
||||
|
||||
@@ -69,18 +71,6 @@ using rwresult = int;
|
||||
inline unsigned convert_rwcount(size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#elif FMT_USE_FCNTL
|
||||
// Return type of read and write functions.
|
||||
using rwresult = ssize_t;
|
||||
|
||||
inline auto convert_rwcount(size_t count) -> size_t { return count; }
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace detail {
|
||||
|
||||
class system_message {
|
||||
system_message(const system_message&) = delete;
|
||||
@@ -109,8 +99,8 @@ class system_message {
|
||||
}
|
||||
~system_message() { LocalFree(message_); }
|
||||
explicit operator bool() const noexcept { return result_ != 0; }
|
||||
operator basic_string_view<wchar_t>() const noexcept {
|
||||
return basic_string_view<wchar_t>(message_, result_);
|
||||
operator fmt::basic_string_view<wchar_t>() const noexcept {
|
||||
return fmt::basic_string_view<wchar_t>(message_, result_);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +110,7 @@ class utf8_system_category final : public std::error_category {
|
||||
std::string message(int error_code) const override {
|
||||
auto&& msg = system_message(error_code);
|
||||
if (msg) {
|
||||
auto utf8_message = to_utf8<wchar_t>();
|
||||
auto utf8_message = fmt::detail::to_utf8<wchar_t>();
|
||||
if (utf8_message.convert(msg)) {
|
||||
return utf8_message.str();
|
||||
}
|
||||
@@ -129,10 +119,22 @@ class utf8_system_category final : public std::error_category {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#elif FMT_USE_FCNTL
|
||||
|
||||
// Return type of read and write functions.
|
||||
using rwresult = ssize_t;
|
||||
|
||||
inline auto convert_rwcount(size_t count) -> size_t { return count; }
|
||||
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
FMT_API const std::error_category& system_category() noexcept {
|
||||
static const detail::utf8_system_category category;
|
||||
static const utf8_system_category category;
|
||||
return category;
|
||||
}
|
||||
|
||||
@@ -162,6 +164,7 @@ void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||
void report_windows_error(int error_code, const char* message) noexcept {
|
||||
do_report_error(detail::format_windows_error, error_code, message);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
buffered_file::~buffered_file() noexcept {
|
||||
|
||||
Reference in New Issue
Block a user