mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-02 06:20:09 +00:00
Simplify integer formatter
This commit is contained in:
parent
05bc87a66f
commit
a457e16360
@ -174,9 +174,9 @@ FMT_END_NAMESPACE
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
|
// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
|
||||||
// int_writer template instances to just one by only using the largest integer
|
// integer formatter template instantiations to just one by only using the
|
||||||
// type. This results in a reduction in binary size but will cause a decrease in
|
// largest integer type. This results in a reduction in binary size but will
|
||||||
// integer formatting performance.
|
// cause a decrease in integer formatting performance.
|
||||||
#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
|
#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
|
||||||
# define FMT_REDUCE_INT_INSTANTIATIONS 0
|
# define FMT_REDUCE_INT_INSTANTIATIONS 0
|
||||||
#endif
|
#endif
|
||||||
@ -402,6 +402,10 @@ template <typename Iterator> constexpr Iterator& reserve(Iterator& it, size_t) {
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt>
|
||||||
|
using reserve_iterator =
|
||||||
|
remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
|
||||||
|
|
||||||
template <typename T, typename OutputIt>
|
template <typename T, typename OutputIt>
|
||||||
constexpr T* to_pointer(OutputIt, size_t) {
|
constexpr T* to_pointer(OutputIt, size_t) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -1634,18 +1638,17 @@ constexpr OutputIt write_padded(OutputIt out,
|
|||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
OutputIt write_bytes(OutputIt out, string_view bytes,
|
OutputIt write_bytes(OutputIt out, string_view bytes,
|
||||||
const basic_format_specs<Char>& specs) {
|
const basic_format_specs<Char>& specs) {
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
return write_padded(out, specs, bytes.size(),
|
||||||
return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
|
[bytes](reserve_iterator<OutputIt> it) {
|
||||||
const char* data = bytes.data();
|
const char* data = bytes.data();
|
||||||
return copy_str<Char>(data, data + bytes.size(), it);
|
return copy_str<Char>(data, data + bytes.size(), it);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
constexpr OutputIt write_char(OutputIt out, Char value,
|
constexpr OutputIt write_char(OutputIt out, Char value,
|
||||||
const basic_format_specs<Char>& specs) {
|
const basic_format_specs<Char>& specs) {
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
|
||||||
return write_padded(out, specs, 1, [=](iterator it) {
|
|
||||||
*it++ = value;
|
*it++ = value;
|
||||||
return it;
|
return it;
|
||||||
});
|
});
|
||||||
@ -1681,16 +1684,154 @@ FMT_CONSTEXPR OutputIt write_int(OutputIt out, int num_digits,
|
|||||||
string_view prefix,
|
string_view prefix,
|
||||||
const basic_format_specs<Char>& specs, F f) {
|
const basic_format_specs<Char>& specs, F f) {
|
||||||
auto data = write_int_data<Char>(num_digits, prefix, specs);
|
auto data = write_int_data<Char>(num_digits, prefix, specs);
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
return write_padded<align::right>(
|
||||||
return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
|
out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
|
||||||
if (prefix.size() != 0)
|
if (prefix.size() != 0)
|
||||||
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
||||||
it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
|
it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
|
||||||
return f(it);
|
return f(it);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StrChar, typename Char, typename OutputIt>
|
template <typename OutputIt, typename UInt, typename Char>
|
||||||
|
FMT_CONSTEXPR OutputIt write_dec(OutputIt out, UInt value, string_view prefix,
|
||||||
|
const basic_format_specs<Char>& specs) {
|
||||||
|
auto num_digits = count_digits(value);
|
||||||
|
return write_int(out, num_digits, prefix, specs,
|
||||||
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
|
return format_decimal<Char>(it, value, num_digits).end;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt, typename UInt, typename Char>
|
||||||
|
OutputIt write_int_localized(OutputIt out, UInt value, string_view prefix,
|
||||||
|
const basic_format_specs<Char>& specs,
|
||||||
|
locale_ref loc) {
|
||||||
|
const auto sep_size = 1;
|
||||||
|
std::string groups = grouping<Char>(loc);
|
||||||
|
if (groups.empty()) return write_dec(out, value, prefix, specs);
|
||||||
|
auto sep = thousands_sep<Char>(loc);
|
||||||
|
if (!sep) return write_dec(out, value, prefix, specs);
|
||||||
|
int num_digits = count_digits(value);
|
||||||
|
int size = num_digits, n = num_digits;
|
||||||
|
std::string::const_iterator group = groups.cbegin();
|
||||||
|
while (group != groups.cend() && n > *group && *group > 0 &&
|
||||||
|
*group != max_value<char>()) {
|
||||||
|
size += sep_size;
|
||||||
|
n -= *group;
|
||||||
|
++group;
|
||||||
|
}
|
||||||
|
if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
|
||||||
|
char digits[40];
|
||||||
|
format_decimal(digits, value, num_digits);
|
||||||
|
basic_memory_buffer<Char> buffer;
|
||||||
|
size += static_cast<int>(prefix.size());
|
||||||
|
const auto usize = to_unsigned(size);
|
||||||
|
buffer.resize(usize);
|
||||||
|
basic_string_view<Char> s(&sep, sep_size);
|
||||||
|
// Index of a decimal digit with the least significant digit having index 0.
|
||||||
|
int digit_index = 0;
|
||||||
|
group = groups.cbegin();
|
||||||
|
auto p = buffer.data() + size - 1;
|
||||||
|
for (int i = num_digits - 1; i > 0; --i) {
|
||||||
|
*p-- = static_cast<Char>(digits[i]);
|
||||||
|
if (*group <= 0 || ++digit_index % *group != 0 ||
|
||||||
|
*group == max_value<char>())
|
||||||
|
continue;
|
||||||
|
if (group + 1 != groups.cend()) {
|
||||||
|
digit_index = 0;
|
||||||
|
++group;
|
||||||
|
}
|
||||||
|
std::uninitialized_copy(s.data(), s.data() + s.size(),
|
||||||
|
make_checked(p, s.size()));
|
||||||
|
p -= s.size();
|
||||||
|
}
|
||||||
|
*p-- = static_cast<Char>(*digits);
|
||||||
|
if (prefix.size() != 0) *p = static_cast<Char>(prefix[0]);
|
||||||
|
auto data = buffer.data();
|
||||||
|
return write_padded<align::right>(
|
||||||
|
out, specs, usize, usize, [=](reserve_iterator<OutputIt> it) {
|
||||||
|
return copy_str<Char>(data, data + size, it);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt, typename T, typename Char>
|
||||||
|
FMT_CONSTEXPR OutputIt write_int(OutputIt out, T value,
|
||||||
|
const basic_format_specs<Char>& specs,
|
||||||
|
locale_ref loc) {
|
||||||
|
using uint_type = uint32_or_64_or_128_t<T>;
|
||||||
|
auto abs_value = static_cast<uint_type>(value);
|
||||||
|
|
||||||
|
char prefix[4] = {};
|
||||||
|
auto prefix_size = 0u;
|
||||||
|
if (is_negative(value)) {
|
||||||
|
prefix[0] = '-';
|
||||||
|
++prefix_size;
|
||||||
|
abs_value = 0 - abs_value;
|
||||||
|
} else if (specs.sign != sign::none && specs.sign != sign::minus) {
|
||||||
|
prefix[0] = specs.sign == sign::plus ? '+' : ' ';
|
||||||
|
++prefix_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (specs.type) {
|
||||||
|
case 0:
|
||||||
|
case 'd':
|
||||||
|
return specs.localized
|
||||||
|
? write_int_localized(out, abs_value, {prefix, prefix_size},
|
||||||
|
specs, loc)
|
||||||
|
: write_dec(out, abs_value, {prefix, prefix_size}, specs);
|
||||||
|
case 'x':
|
||||||
|
case 'X': {
|
||||||
|
if (specs.alt) {
|
||||||
|
prefix[prefix_size++] = '0';
|
||||||
|
prefix[prefix_size++] = specs.type;
|
||||||
|
}
|
||||||
|
bool upper = specs.type != 'x';
|
||||||
|
int num_digits = count_digits<4>(abs_value);
|
||||||
|
return write_int(out, num_digits, {prefix, prefix_size}, specs,
|
||||||
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
|
return format_uint<4, Char>(it, abs_value, num_digits,
|
||||||
|
upper);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
case 'B': {
|
||||||
|
if (specs.alt) {
|
||||||
|
prefix[prefix_size++] = '0';
|
||||||
|
prefix[prefix_size++] = static_cast<char>(specs.type);
|
||||||
|
}
|
||||||
|
int num_digits = count_digits<1>(abs_value);
|
||||||
|
return write_int(out, num_digits, {prefix, prefix_size}, specs,
|
||||||
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
|
return format_uint<1, Char>(it, abs_value, num_digits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'o': {
|
||||||
|
int num_digits = count_digits<3>(abs_value);
|
||||||
|
if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
|
||||||
|
// Octal prefix '0' is counted as a digit, so only add it if precision
|
||||||
|
// is not greater than the number of digits.
|
||||||
|
prefix[prefix_size++] = '0';
|
||||||
|
}
|
||||||
|
return write_int(out, num_digits, {prefix, prefix_size}, specs,
|
||||||
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
|
return format_uint<3, Char>(it, abs_value, num_digits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#ifdef FMT_DEPRECATED_N_SPECIFIER
|
||||||
|
case 'n':
|
||||||
|
return write_int_localized(out, abs_value, {prefix, prefix_size}, specs,
|
||||||
|
loc);
|
||||||
|
#endif
|
||||||
|
case 'c':
|
||||||
|
return write_char(out, static_cast<Char>(abs_value), specs);
|
||||||
|
default:
|
||||||
|
FMT_THROW(format_error("invalid type specifier"));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt, typename StrChar, typename Char>
|
||||||
FMT_CONSTEXPR OutputIt write(OutputIt out, basic_string_view<StrChar> s,
|
FMT_CONSTEXPR OutputIt write(OutputIt out, basic_string_view<StrChar> s,
|
||||||
const basic_format_specs<Char>& specs) {
|
const basic_format_specs<Char>& specs) {
|
||||||
auto data = s.data();
|
auto data = s.data();
|
||||||
@ -1700,154 +1841,12 @@ FMT_CONSTEXPR OutputIt write(OutputIt out, basic_string_view<StrChar> s,
|
|||||||
auto width = specs.width != 0
|
auto width = specs.width != 0
|
||||||
? compute_width(basic_string_view<StrChar>(data, size))
|
? compute_width(basic_string_view<StrChar>(data, size))
|
||||||
: 0;
|
: 0;
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
return write_padded(out, specs, size, width,
|
||||||
return write_padded(out, specs, size, width, [=](iterator it) {
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
return copy_str<Char>(data, data + size, it);
|
return copy_str<Char>(data, data + size, it);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The handle_int_type_spec handler that writes an integer.
|
|
||||||
template <typename OutputIt, typename Char, typename UInt> struct int_writer {
|
|
||||||
OutputIt out;
|
|
||||||
locale_ref locale;
|
|
||||||
const basic_format_specs<Char>& specs;
|
|
||||||
UInt abs_value;
|
|
||||||
char prefix[4];
|
|
||||||
unsigned prefix_size;
|
|
||||||
|
|
||||||
using iterator =
|
|
||||||
remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
|
|
||||||
|
|
||||||
constexpr string_view get_prefix() const {
|
|
||||||
return string_view(prefix, prefix_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void write_dec() {
|
|
||||||
auto num_digits = count_digits(abs_value);
|
|
||||||
out = write_int(
|
|
||||||
out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) {
|
|
||||||
return format_decimal<Char>(it, abs_value, num_digits).end;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
FMT_CONSTEXPR int_writer(OutputIt output, locale_ref loc, Int value,
|
|
||||||
const basic_format_specs<Char>& s)
|
|
||||||
: out(output),
|
|
||||||
locale(loc),
|
|
||||||
specs(s),
|
|
||||||
abs_value(static_cast<UInt>(value)),
|
|
||||||
prefix_size(0) {
|
|
||||||
static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value, "");
|
|
||||||
if (is_negative(value)) {
|
|
||||||
prefix[0] = '-';
|
|
||||||
++prefix_size;
|
|
||||||
abs_value = 0 - abs_value;
|
|
||||||
} else if (specs.sign != sign::none && specs.sign != sign::minus) {
|
|
||||||
prefix[0] = specs.sign == sign::plus ? '+' : ' ';
|
|
||||||
++prefix_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_dec() {
|
|
||||||
if (specs.localized) return on_num();
|
|
||||||
write_dec();
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_hex() {
|
|
||||||
if (specs.alt) {
|
|
||||||
prefix[prefix_size++] = '0';
|
|
||||||
prefix[prefix_size++] = specs.type;
|
|
||||||
}
|
|
||||||
int num_digits = count_digits<4>(abs_value);
|
|
||||||
out = write_int(out, num_digits, get_prefix(), specs,
|
|
||||||
[this, num_digits](iterator it) {
|
|
||||||
return format_uint<4, Char>(it, abs_value, num_digits,
|
|
||||||
specs.type != 'x');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_bin() {
|
|
||||||
if (specs.alt) {
|
|
||||||
prefix[prefix_size++] = '0';
|
|
||||||
prefix[prefix_size++] = static_cast<char>(specs.type);
|
|
||||||
}
|
|
||||||
int num_digits = count_digits<1>(abs_value);
|
|
||||||
out = write_int(out, num_digits, get_prefix(), specs,
|
|
||||||
[this, num_digits](iterator it) {
|
|
||||||
return format_uint<1, Char>(it, abs_value, num_digits);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_oct() {
|
|
||||||
int num_digits = count_digits<3>(abs_value);
|
|
||||||
if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
|
|
||||||
// Octal prefix '0' is counted as a digit, so only add it if precision
|
|
||||||
// is not greater than the number of digits.
|
|
||||||
prefix[prefix_size++] = '0';
|
|
||||||
}
|
|
||||||
out = write_int(out, num_digits, get_prefix(), specs,
|
|
||||||
[this, num_digits](iterator it) {
|
|
||||||
return format_uint<3, Char>(it, abs_value, num_digits);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
enum { sep_size = 1 };
|
|
||||||
|
|
||||||
void on_num() {
|
|
||||||
std::string groups = grouping<Char>(locale);
|
|
||||||
if (groups.empty()) return write_dec();
|
|
||||||
auto sep = thousands_sep<Char>(locale);
|
|
||||||
if (!sep) return write_dec();
|
|
||||||
int num_digits = count_digits(abs_value);
|
|
||||||
int size = num_digits, n = num_digits;
|
|
||||||
std::string::const_iterator group = groups.cbegin();
|
|
||||||
while (group != groups.cend() && n > *group && *group > 0 &&
|
|
||||||
*group != max_value<char>()) {
|
|
||||||
size += sep_size;
|
|
||||||
n -= *group;
|
|
||||||
++group;
|
|
||||||
}
|
|
||||||
if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
|
|
||||||
char digits[40];
|
|
||||||
format_decimal(digits, abs_value, num_digits);
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
size += static_cast<int>(prefix_size);
|
|
||||||
const auto usize = to_unsigned(size);
|
|
||||||
buffer.resize(usize);
|
|
||||||
basic_string_view<Char> s(&sep, sep_size);
|
|
||||||
// Index of a decimal digit with the least significant digit having index 0.
|
|
||||||
int digit_index = 0;
|
|
||||||
group = groups.cbegin();
|
|
||||||
auto p = buffer.data() + size - 1;
|
|
||||||
for (int i = num_digits - 1; i > 0; --i) {
|
|
||||||
*p-- = static_cast<Char>(digits[i]);
|
|
||||||
if (*group <= 0 || ++digit_index % *group != 0 ||
|
|
||||||
*group == max_value<char>())
|
|
||||||
continue;
|
|
||||||
if (group + 1 != groups.cend()) {
|
|
||||||
digit_index = 0;
|
|
||||||
++group;
|
|
||||||
}
|
|
||||||
std::uninitialized_copy(s.data(), s.data() + s.size(),
|
|
||||||
make_checked(p, s.size()));
|
|
||||||
p -= s.size();
|
|
||||||
}
|
|
||||||
*p-- = static_cast<Char>(*digits);
|
|
||||||
if (prefix_size != 0) *p = static_cast<Char>(prefix[0]);
|
|
||||||
auto data = buffer.data();
|
|
||||||
out = write_padded<align::right>(
|
|
||||||
out, specs, usize, usize,
|
|
||||||
[=](iterator it) { return copy_str<Char>(data, data + size, it); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_chr() { out = write_char(out, static_cast<Char>(abs_value), specs); }
|
|
||||||
|
|
||||||
FMT_NORETURN void on_error() {
|
|
||||||
FMT_THROW(format_error("invalid type specifier"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
OutputIt write_nonfinite(OutputIt out, bool isinf,
|
OutputIt write_nonfinite(OutputIt out, bool isinf,
|
||||||
const basic_format_specs<Char>& specs,
|
const basic_format_specs<Char>& specs,
|
||||||
@ -1857,8 +1856,7 @@ OutputIt write_nonfinite(OutputIt out, bool isinf,
|
|||||||
constexpr size_t str_size = 3;
|
constexpr size_t str_size = 3;
|
||||||
auto sign = fspecs.sign;
|
auto sign = fspecs.sign;
|
||||||
auto size = str_size + (sign ? 1 : 0);
|
auto size = str_size + (sign ? 1 : 0);
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
|
||||||
return write_padded(out, specs, size, [=](iterator it) {
|
|
||||||
if (sign) *it++ = static_cast<Char>(data::signs[sign]);
|
if (sign) *it++ = static_cast<Char>(data::signs[sign]);
|
||||||
return copy_str<Char>(str, str + str_size, it);
|
return copy_str<Char>(str, str + str_size, it);
|
||||||
});
|
});
|
||||||
@ -1938,7 +1936,7 @@ OutputIt write_float(OutputIt out, const DecimalFP& fp,
|
|||||||
static const Char zero = static_cast<Char>('0');
|
static const Char zero = static_cast<Char>('0');
|
||||||
auto sign = fspecs.sign;
|
auto sign = fspecs.sign;
|
||||||
size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
|
size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
using iterator = reserve_iterator<OutputIt>;
|
||||||
|
|
||||||
int output_exp = fp.exponent + significand_size - 1;
|
int output_exp = fp.exponent + significand_size - 1;
|
||||||
auto use_exp_format = [=]() {
|
auto use_exp_format = [=]() {
|
||||||
@ -2113,8 +2111,7 @@ OutputIt write_ptr(OutputIt out, UIntPtr value,
|
|||||||
const basic_format_specs<Char>* specs) {
|
const basic_format_specs<Char>* specs) {
|
||||||
int num_digits = count_digits<4>(value);
|
int num_digits = count_digits<4>(value);
|
||||||
auto size = to_unsigned(num_digits) + size_t(2);
|
auto size = to_unsigned(num_digits) + size_t(2);
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
auto write = [=](reserve_iterator<OutputIt> it) {
|
||||||
auto write = [=](iterator it) {
|
|
||||||
*it++ = static_cast<Char>('0');
|
*it++ = static_cast<Char>('0');
|
||||||
*it++ = static_cast<Char>('x');
|
*it++ = static_cast<Char>('x');
|
||||||
return format_uint<4, Char>(it, value, num_digits);
|
return format_uint<4, Char>(it, value, num_digits);
|
||||||
@ -2265,17 +2262,6 @@ class arg_formatter_base {
|
|||||||
return detail::reserve(out_, n);
|
return detail::reserve(out_, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
using reserve_iterator = remove_reference_t<decltype(
|
|
||||||
detail::reserve(std::declval<iterator&>(), 0))>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
FMT_CONSTEXPR void write_int(T value, const format_specs& specs) {
|
|
||||||
using uint_type = uint32_or_64_or_128_t<T>;
|
|
||||||
int_writer<iterator, Char, uint_type> w(out_, locale_, value, specs);
|
|
||||||
handle_int_type_spec(specs.type, w);
|
|
||||||
out_ = w.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(char value) {
|
void write(char value) {
|
||||||
auto&& it = reserve(1);
|
auto&& it = reserve(1);
|
||||||
*it++ = value;
|
*it++ = value;
|
||||||
@ -2300,9 +2286,10 @@ class arg_formatter_base {
|
|||||||
void write(const Ch* s, size_t size, const format_specs& specs) {
|
void write(const Ch* s, size_t size, const format_specs& specs) {
|
||||||
auto width =
|
auto width =
|
||||||
specs.width != 0 ? compute_width(basic_string_view<Ch>(s, size)) : 0;
|
specs.width != 0 ? compute_width(basic_string_view<Ch>(s, size)) : 0;
|
||||||
out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) {
|
out_ = write_padded(out_, specs, size, width,
|
||||||
return copy_str<Char>(s, s + size, it);
|
[=](reserve_iterator<OutputIt> it) {
|
||||||
});
|
return copy_str<Char>(s, s + size, it);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ch>
|
template <typename Ch>
|
||||||
@ -2324,7 +2311,9 @@ class arg_formatter_base {
|
|||||||
|
|
||||||
FMT_CONSTEXPR void on_int() {
|
FMT_CONSTEXPR void on_int() {
|
||||||
// char is only formatted as int if there are specs.
|
// char is only formatted as int if there are specs.
|
||||||
formatter.write_int(static_cast<int>(value), *formatter.specs_);
|
formatter.out_ =
|
||||||
|
detail::write_int(formatter.out_, static_cast<int>(value),
|
||||||
|
*formatter.specs_, formatter.locale_);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR void on_char() {
|
FMT_CONSTEXPR void on_char() {
|
||||||
if (formatter.specs_)
|
if (formatter.specs_)
|
||||||
@ -2377,11 +2366,8 @@ class arg_formatter_base {
|
|||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE iterator operator()(T value) {
|
FMT_CONSTEXPR FMT_INLINE iterator operator()(T value) {
|
||||||
if (specs_)
|
return out_ = specs_ ? detail::write_int(out_, value, *specs_, locale_)
|
||||||
write_int(value, *specs_);
|
: detail::write<Char>(out_, value);
|
||||||
else
|
|
||||||
out_ = detail::write<Char>(out_, value);
|
|
||||||
return out_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR iterator operator()(Char value) {
|
FMT_CONSTEXPR iterator operator()(Char value) {
|
||||||
|
Loading…
Reference in New Issue
Block a user