mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-23 18:47:12 +02:00
Update fmt library.
This commit is contained in:
160
vendor/Fmt/include/fmt/format-inl.h
vendored
160
vendor/Fmt/include/fmt/format-inl.h
vendored
@ -8,7 +8,7 @@
|
||||
#ifndef FMT_FORMAT_INL_H_
|
||||
#define FMT_FORMAT_INL_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
@ -145,9 +145,9 @@ FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
|
||||
error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
|
||||
auto it = buffer_appender<char>(out);
|
||||
if (message.size() <= inline_buffer_size - error_code_size)
|
||||
format_to(it, "{}{}", message, SEP);
|
||||
format_to(it, "{}{}", ERROR_STR, error_code);
|
||||
assert(out.size() <= inline_buffer_size);
|
||||
format_to(it, FMT_STRING("{}{}"), message, SEP);
|
||||
format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code);
|
||||
FMT_ASSERT(out.size() <= inline_buffer_size, "");
|
||||
}
|
||||
|
||||
FMT_FUNC void report_error(format_func func, int error_code,
|
||||
@ -165,11 +165,8 @@ inline void fwrite_fully(const void* ptr, size_t size, size_t count,
|
||||
size_t written = std::fwrite(ptr, size, count, stream);
|
||||
if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||
namespace detail {
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
template <typename Locale>
|
||||
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
||||
static_assert(std::is_same<Locale, std::locale>::value, "");
|
||||
@ -191,19 +188,18 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
|
||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
||||
.decimal_point();
|
||||
}
|
||||
} // namespace detail
|
||||
#else
|
||||
template <typename Char>
|
||||
FMT_FUNC std::string detail::grouping_impl(locale_ref) {
|
||||
template <typename Char> FMT_FUNC std::string grouping_impl(locale_ref) {
|
||||
return "\03";
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char detail::thousands_sep_impl(locale_ref) {
|
||||
template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref) {
|
||||
return FMT_STATIC_THOUSANDS_SEPARATOR;
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char detail::decimal_point_impl(locale_ref) {
|
||||
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
|
||||
return '.';
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default;
|
||||
FMT_API FMT_FUNC system_error::~system_error() FMT_NOEXCEPT = default;
|
||||
@ -247,9 +243,6 @@ const typename basic_data<T>::digit_pair basic_data<T>::digits[] = {
|
||||
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
|
||||
{'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
|
||||
|
||||
template <typename T>
|
||||
const char basic_data<T>::hex_digits[] = "0123456789abcdef";
|
||||
|
||||
#define FMT_POWERS_OF_10(factor) \
|
||||
factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
|
||||
(factor)*1000000, (factor)*10000000, (factor)*100000000, \
|
||||
@ -1070,10 +1063,14 @@ const char basic_data<T>::background_color[] = "\x1b[48;2;";
|
||||
template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m";
|
||||
template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
|
||||
template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
template <typename T> constexpr const char basic_data<T>::hex_digits[];
|
||||
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
|
||||
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
|
||||
template <typename T>
|
||||
const char basic_data<T>::left_padding_shifts[] = {31, 31, 0, 1, 0};
|
||||
template <typename T>
|
||||
const char basic_data<T>::right_padding_shifts[] = {0, 31, 0, 1, 0};
|
||||
constexpr const char basic_data<T>::right_padding_shifts[];
|
||||
#endif
|
||||
|
||||
template <typename T> struct bits {
|
||||
static FMT_CONSTEXPR_DECL const int value =
|
||||
@ -1228,7 +1225,7 @@ struct accumulator {
|
||||
if (lower < n) ++upper;
|
||||
}
|
||||
void operator>>=(int shift) {
|
||||
assert(shift == 32);
|
||||
FMT_ASSERT(shift == 32, "");
|
||||
(void)shift;
|
||||
lower = (upper << 32) | (lower >> 32);
|
||||
upper >>= 32;
|
||||
@ -1307,7 +1304,7 @@ class bigint {
|
||||
public:
|
||||
bigint() : exp_(0) {}
|
||||
explicit bigint(uint64_t n) { assign(n); }
|
||||
~bigint() { assert(bigits_.capacity() <= bigits_capacity); }
|
||||
~bigint() { FMT_ASSERT(bigits_.capacity() <= bigits_capacity, ""); }
|
||||
|
||||
bigint(const bigint&) = delete;
|
||||
void operator=(const bigint&) = delete;
|
||||
@ -1333,7 +1330,7 @@ class bigint {
|
||||
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
|
||||
|
||||
FMT_NOINLINE bigint& operator<<=(int shift) {
|
||||
assert(shift >= 0);
|
||||
FMT_ASSERT(shift >= 0, "");
|
||||
exp_ += shift / bigit_bits;
|
||||
shift %= bigit_bits;
|
||||
if (shift == 0) return *this;
|
||||
@ -1395,7 +1392,7 @@ class bigint {
|
||||
|
||||
// Assigns pow(10, exp) to this bigint.
|
||||
void assign_pow10(int exp) {
|
||||
assert(exp >= 0);
|
||||
FMT_ASSERT(exp >= 0, "");
|
||||
if (exp == 0) return assign(1);
|
||||
// Find the top bit.
|
||||
int bitmask = 1;
|
||||
@ -1646,8 +1643,7 @@ struct fixed_handler {
|
||||
// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox.
|
||||
namespace dragonbox {
|
||||
// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
|
||||
FMT_SAFEBUFFERS inline uint128_wrapper umul128(uint64_t x,
|
||||
uint64_t y) FMT_NOEXCEPT {
|
||||
inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT {
|
||||
#if FMT_USE_INT128
|
||||
return static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
@ -1675,8 +1671,7 @@ FMT_SAFEBUFFERS inline uint128_wrapper umul128(uint64_t x,
|
||||
}
|
||||
|
||||
// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
|
||||
FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x,
|
||||
uint64_t y) FMT_NOEXCEPT {
|
||||
inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT {
|
||||
#if FMT_USE_INT128
|
||||
auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
|
||||
return static_cast<uint64_t>(p >> 64);
|
||||
@ -1689,8 +1684,7 @@ FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x,
|
||||
|
||||
// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a
|
||||
// 128-bit unsigned integer.
|
||||
FMT_SAFEBUFFERS inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y)
|
||||
FMT_NOEXCEPT {
|
||||
inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
|
||||
uint128_wrapper g0 = umul128(x, y.high());
|
||||
g0 += umul128_upper64(x, y.low());
|
||||
return g0.high();
|
||||
@ -1704,8 +1698,7 @@ inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT {
|
||||
|
||||
// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a
|
||||
// 128-bit unsigned integer.
|
||||
FMT_SAFEBUFFERS inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y)
|
||||
FMT_NOEXCEPT {
|
||||
inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
|
||||
uint64_t g01 = x * y.high();
|
||||
uint64_t g10 = umul128_upper64(x, y.low());
|
||||
return g01 + g10;
|
||||
@ -2124,8 +2117,8 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
|
||||
|
||||
// The main algorithm for shorter interval case
|
||||
template <class T>
|
||||
FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp<T> shorter_interval_case(
|
||||
int exponent) FMT_NOEXCEPT {
|
||||
FMT_ALWAYS_INLINE decimal_fp<T> shorter_interval_case(int exponent)
|
||||
FMT_NOEXCEPT {
|
||||
decimal_fp<T> ret_value;
|
||||
// Compute k and beta
|
||||
const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
|
||||
@ -2171,8 +2164,7 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp<T> shorter_interval_case(
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
|
||||
template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
|
||||
// Step 1: integer promotion & Schubfach multiplier calculation.
|
||||
|
||||
using carrier_uint = typename float_info<T>::carrier_uint;
|
||||
@ -2571,11 +2563,11 @@ int snprintf_float(T value, int precision, float_specs specs,
|
||||
--exp_pos;
|
||||
} while (*exp_pos != 'e');
|
||||
char sign = exp_pos[1];
|
||||
assert(sign == '+' || sign == '-');
|
||||
FMT_ASSERT(sign == '+' || sign == '-', "");
|
||||
int exp = 0;
|
||||
auto p = exp_pos + 2; // Skip 'e' and sign.
|
||||
do {
|
||||
assert(is_digit(*p));
|
||||
FMT_ASSERT(is_digit(*p), "");
|
||||
exp = exp * 10 + (*p++ - '0');
|
||||
} while (p != end);
|
||||
if (sign == '-') exp = -exp;
|
||||
@ -2593,54 +2585,6 @@ int snprintf_float(T value, int precision, float_specs specs,
|
||||
}
|
||||
}
|
||||
|
||||
// A public domain branchless UTF-8 decoder by Christopher Wellons:
|
||||
// https://github.com/skeeto/branchless-utf8
|
||||
/* Decode the next character, c, from buf, reporting errors in e.
|
||||
*
|
||||
* Since this is a branchless decoder, four bytes will be read from the
|
||||
* buffer regardless of the actual length of the next character. This
|
||||
* means the buffer _must_ have at least three bytes of zero padding
|
||||
* following the end of the data stream.
|
||||
*
|
||||
* Errors are reported in e, which will be non-zero if the parsed
|
||||
* character was somehow invalid: invalid byte sequence, non-canonical
|
||||
* encoding, or a surrogate half.
|
||||
*
|
||||
* The function returns a pointer to the next character. When an error
|
||||
* occurs, this pointer will be a guess that depends on the particular
|
||||
* error, but it will always advance at least one byte.
|
||||
*/
|
||||
inline const char* utf8_decode(const char* buf, uint32_t* c, int* e) {
|
||||
static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
|
||||
static const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
|
||||
static const int shiftc[] = {0, 18, 12, 6, 0};
|
||||
static const int shifte[] = {0, 6, 4, 2, 0};
|
||||
|
||||
int len = code_point_length(buf);
|
||||
const char* next = buf + len;
|
||||
|
||||
// Assume a four-byte character and load four bytes. Unused bits are
|
||||
// shifted out.
|
||||
auto s = reinterpret_cast<const unsigned char*>(buf);
|
||||
*c = uint32_t(s[0] & masks[len]) << 18;
|
||||
*c |= uint32_t(s[1] & 0x3f) << 12;
|
||||
*c |= uint32_t(s[2] & 0x3f) << 6;
|
||||
*c |= uint32_t(s[3] & 0x3f) << 0;
|
||||
*c >>= shiftc[len];
|
||||
|
||||
// Accumulate the various error conditions.
|
||||
*e = (*c < mins[len]) << 6; // non-canonical encoding
|
||||
*e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
|
||||
*e |= (*c > 0x10FFFF) << 8; // out of range?
|
||||
*e |= (s[1] & 0xc0) >> 2;
|
||||
*e |= (s[2] & 0xc0) >> 4;
|
||||
*e |= (s[3]) >> 6;
|
||||
*e ^= 0x2a; // top two bits of each tail byte correct?
|
||||
*e >>= shifte[len];
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
struct stringifier {
|
||||
template <typename T> FMT_INLINE std::string operator()(T value) const {
|
||||
return to_string(value);
|
||||
@ -2656,7 +2600,8 @@ struct stringifier {
|
||||
} // namespace detail
|
||||
|
||||
template <> struct formatter<detail::bigint> {
|
||||
format_parse_context::iterator parse(format_parse_context& ctx) {
|
||||
FMT_CONSTEXPR format_parse_context::iterator parse(
|
||||
format_parse_context& ctx) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
@ -2667,23 +2612,21 @@ template <> struct formatter<detail::bigint> {
|
||||
for (auto i = n.bigits_.size(); i > 0; --i) {
|
||||
auto value = n.bigits_[i - 1u];
|
||||
if (first) {
|
||||
out = format_to(out, "{:x}", value);
|
||||
out = format_to(out, FMT_STRING("{:x}"), value);
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
out = format_to(out, "{:08x}", value);
|
||||
out = format_to(out, FMT_STRING("{:08x}"), value);
|
||||
}
|
||||
if (n.exp_ > 0)
|
||||
out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits);
|
||||
out = format_to(out, FMT_STRING("p{}"),
|
||||
n.exp_ * detail::bigint::bigit_bits);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
||||
auto transcode = [this](const char* p) {
|
||||
auto cp = uint32_t();
|
||||
auto error = 0;
|
||||
p = utf8_decode(p, &cp, &error);
|
||||
for_each_codepoint(s, [this](uint32_t cp, int error) {
|
||||
if (error != 0) FMT_THROW(std::runtime_error("invalid utf8"));
|
||||
if (cp <= 0xFFFF) {
|
||||
buffer_.push_back(static_cast<wchar_t>(cp));
|
||||
@ -2692,21 +2635,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
||||
buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));
|
||||
buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));
|
||||
}
|
||||
return p;
|
||||
};
|
||||
auto p = s.data();
|
||||
const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
|
||||
if (s.size() >= block_size) {
|
||||
for (auto end = p + s.size() - block_size + 1; p < end;) p = transcode(p);
|
||||
}
|
||||
if (auto num_chars_left = s.data() + s.size() - p) {
|
||||
char buf[2 * block_size - 1] = {};
|
||||
memcpy(buf, p, to_unsigned(num_chars_left));
|
||||
p = buf;
|
||||
do {
|
||||
p = transcode(p);
|
||||
} while (p - buf < num_chars_left);
|
||||
}
|
||||
});
|
||||
buffer_.push_back(0);
|
||||
}
|
||||
|
||||
@ -2720,8 +2649,8 @@ FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
|
||||
int result =
|
||||
detail::safe_strerror(error_code, system_message, buf.size());
|
||||
if (result == 0) {
|
||||
format_to(detail::buffer_appender<char>(out), "{}: {}", message,
|
||||
system_message);
|
||||
format_to(detail::buffer_appender<char>(out), FMT_STRING("{}: {}"),
|
||||
message, system_message);
|
||||
return;
|
||||
}
|
||||
if (result != ERANGE)
|
||||
@ -2770,12 +2699,13 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
||||
if (_isatty(fd)) {
|
||||
detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
|
||||
auto written = detail::dword();
|
||||
if (!detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
|
||||
u16.c_str(), static_cast<uint32_t>(u16.size()),
|
||||
&written, nullptr)) {
|
||||
FMT_THROW(format_error("failed to write to console"));
|
||||
if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
|
||||
u16.c_str(), static_cast<uint32_t>(u16.size()),
|
||||
&written, nullptr)) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
// Fallback to fwrite on failure. It can happen if the output has been
|
||||
// redirected to NUL.
|
||||
}
|
||||
#endif
|
||||
detail::fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
||||
|
Reference in New Issue
Block a user