mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-27 15:35:18 +00:00
Reduce library size
This commit is contained in:
parent
e9fdea90b5
commit
d6abb2fa03
@ -602,7 +602,7 @@ class bigint {
|
|||||||
|
|
||||||
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
|
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
|
||||||
|
|
||||||
bigint& operator<<=(int shift) {
|
FMT_NOINLINE bigint& operator<<=(int shift) {
|
||||||
assert(shift >= 0);
|
assert(shift >= 0);
|
||||||
exp_ += shift / bigit_bits;
|
exp_ += shift / bigit_bits;
|
||||||
shift %= bigit_bits;
|
shift %= bigit_bits;
|
||||||
|
@ -1413,31 +1413,47 @@ inline OutputIt write_padded(OutputIt out,
|
|||||||
return write_padded(out, specs, size, size, f);
|
return write_padded(out, specs, size, size, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char> struct write_int_params {
|
// Data for write_int that doesn't depend on output iterator type. It is used to
|
||||||
|
// avoid template code bloat.
|
||||||
|
template <typename Char> struct write_int_data {
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
std::size_t padding;
|
std::size_t padding;
|
||||||
Char fill;
|
Char fill;
|
||||||
|
|
||||||
|
write_int_data(int num_digits, string_view prefix,
|
||||||
|
basic_format_specs<Char>& specs)
|
||||||
|
: size(prefix.size() + to_unsigned(num_digits)),
|
||||||
|
padding(0),
|
||||||
|
fill(specs.fill[0]) {
|
||||||
|
if (specs.align == align::numeric) {
|
||||||
|
auto width = to_unsigned(specs.width);
|
||||||
|
if (width > size) {
|
||||||
|
padding = width - size;
|
||||||
|
size = width;
|
||||||
|
}
|
||||||
|
} else if (specs.precision > num_digits) {
|
||||||
|
size = prefix.size() + to_unsigned(specs.precision);
|
||||||
|
padding = to_unsigned(specs.precision - num_digits);
|
||||||
|
fill = static_cast<Char>('0');
|
||||||
|
}
|
||||||
|
if (specs.align == align::none) specs.align = align::right;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char>
|
// Writes an integer in the format
|
||||||
write_int_params<Char> make_write_int_params(int num_digits, string_view prefix,
|
// <left-padding><prefix><numeric-padding><digits><right-padding>
|
||||||
basic_format_specs<Char>& specs) {
|
// where <digits> are written by f(it).
|
||||||
std::size_t size = prefix.size() + to_unsigned(num_digits);
|
template <typename OutputIt, typename Char, typename F>
|
||||||
Char fill = specs.fill[0];
|
OutputIt write_int(OutputIt out, int num_digits, string_view prefix,
|
||||||
std::size_t padding = 0;
|
basic_format_specs<Char> specs, F f) {
|
||||||
if (specs.align == align::numeric) {
|
auto data = write_int_data<Char>(num_digits, prefix, specs);
|
||||||
auto width = to_unsigned(specs.width);
|
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||||
if (width > size) {
|
return write_padded(out, specs, data.size, [=](iterator it) {
|
||||||
padding = width - size;
|
if (prefix.size() != 0)
|
||||||
size = width;
|
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
||||||
}
|
it = std::fill_n(it, data.padding, data.fill);
|
||||||
} else if (specs.precision > num_digits) {
|
return f(it);
|
||||||
size = prefix.size() + to_unsigned(specs.precision);
|
});
|
||||||
padding = to_unsigned(specs.precision - num_digits);
|
|
||||||
fill = static_cast<Char>('0');
|
|
||||||
}
|
|
||||||
if (specs.align == align::none) specs.align = align::right;
|
|
||||||
return {size, padding, fill};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This template provides operations for formatting and writing data into a
|
// This template provides operations for formatting and writing data into a
|
||||||
@ -1458,21 +1474,6 @@ template <typename Range> class basic_writer {
|
|||||||
return internal::reserve(out_, n);
|
return internal::reserve(out_, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an integer in the format
|
|
||||||
// <left-padding><prefix><numeric-padding><digits><right-padding>
|
|
||||||
// where <digits> are written by f(it).
|
|
||||||
template <typename F>
|
|
||||||
void write_int(int num_digits, string_view prefix, format_specs specs, F f) {
|
|
||||||
auto params = make_write_int_params(num_digits, prefix, specs);
|
|
||||||
out_ = write_padded(out_, specs, params.size, [=](reserve_iterator it) {
|
|
||||||
if (prefix.size() != 0)
|
|
||||||
it = copy_str<char_type>(prefix.begin(), prefix.end(), it);
|
|
||||||
it = std::fill_n(it, params.padding, params.fill);
|
|
||||||
f(it);
|
|
||||||
return it;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes a decimal integer.
|
// Writes a decimal integer.
|
||||||
template <typename Int> void write_decimal(Int value) {
|
template <typename Int> void write_decimal(Int value) {
|
||||||
auto abs_value = static_cast<uint32_or_64_or_128_t<Int>>(value);
|
auto abs_value = static_cast<uint32_or_64_or_128_t<Int>>(value);
|
||||||
@ -1486,22 +1487,23 @@ template <typename Range> class basic_writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The handle_int_type_spec handler that writes an integer.
|
// The handle_int_type_spec handler that writes an integer.
|
||||||
template <typename Int, typename Specs> struct int_writer {
|
template <typename UInt> struct int_writer {
|
||||||
using unsigned_type = uint32_or_64_or_128_t<Int>;
|
|
||||||
|
|
||||||
basic_writer<Range>& writer;
|
basic_writer<Range>& writer;
|
||||||
const Specs& specs;
|
const basic_format_specs<char_type>& specs;
|
||||||
unsigned_type abs_value;
|
UInt abs_value;
|
||||||
char prefix[4];
|
char prefix[4];
|
||||||
unsigned prefix_size;
|
unsigned prefix_size;
|
||||||
|
|
||||||
string_view get_prefix() const { return string_view(prefix, prefix_size); }
|
string_view get_prefix() const { return string_view(prefix, prefix_size); }
|
||||||
|
|
||||||
int_writer(basic_writer<Range>& w, Int value, const Specs& s)
|
template <typename Int>
|
||||||
|
int_writer(basic_writer<Range>& w, Int value,
|
||||||
|
const basic_format_specs<char_type>& s)
|
||||||
: writer(w),
|
: writer(w),
|
||||||
specs(s),
|
specs(s),
|
||||||
abs_value(static_cast<unsigned_type>(value)),
|
abs_value(static_cast<UInt>(value)),
|
||||||
prefix_size(0) {
|
prefix_size(0) {
|
||||||
|
static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value, "");
|
||||||
if (is_negative(value)) {
|
if (is_negative(value)) {
|
||||||
prefix[0] = '-';
|
prefix[0] = '-';
|
||||||
++prefix_size;
|
++prefix_size;
|
||||||
@ -1512,58 +1514,40 @@ template <typename Range> class basic_writer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dec_writer {
|
|
||||||
unsigned_type abs_value;
|
|
||||||
int num_digits;
|
|
||||||
|
|
||||||
template <typename It> void operator()(It&& it) const {
|
|
||||||
it = internal::format_decimal<char_type>(it, abs_value, num_digits);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void on_dec() {
|
void on_dec() {
|
||||||
int num_digits = count_digits(abs_value);
|
auto num_digits = count_digits(abs_value);
|
||||||
writer.write_int(num_digits, get_prefix(), specs,
|
writer.out_ = internal::write_int(writer.out_, num_digits, get_prefix(),
|
||||||
dec_writer{abs_value, num_digits});
|
specs, [=](reserve_iterator it) {
|
||||||
|
return format_decimal<char_type>(
|
||||||
|
it, abs_value, num_digits);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hex_writer {
|
|
||||||
int_writer& self;
|
|
||||||
int num_digits;
|
|
||||||
|
|
||||||
template <typename It> void operator()(It&& it) const {
|
|
||||||
it = format_uint<4, char_type>(it, self.abs_value, num_digits,
|
|
||||||
self.specs.type != 'x');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void on_hex() {
|
void on_hex() {
|
||||||
if (specs.alt) {
|
if (specs.alt) {
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
prefix[prefix_size++] = specs.type;
|
prefix[prefix_size++] = specs.type;
|
||||||
}
|
}
|
||||||
int num_digits = count_digits<4>(abs_value);
|
int num_digits = count_digits<4>(abs_value);
|
||||||
writer.write_int(num_digits, get_prefix(), specs,
|
writer.out_ = internal::write_int(writer.out_, num_digits, get_prefix(),
|
||||||
hex_writer{*this, num_digits});
|
specs, [=](reserve_iterator it) {
|
||||||
|
return format_uint<4, char_type>(
|
||||||
|
it, abs_value, num_digits,
|
||||||
|
specs.type != 'x');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int BITS> struct bin_writer {
|
|
||||||
unsigned_type abs_value;
|
|
||||||
int num_digits;
|
|
||||||
|
|
||||||
template <typename It> void operator()(It&& it) const {
|
|
||||||
it = format_uint<BITS, char_type>(it, abs_value, num_digits);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void on_bin() {
|
void on_bin() {
|
||||||
if (specs.alt) {
|
if (specs.alt) {
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
prefix[prefix_size++] = static_cast<char>(specs.type);
|
prefix[prefix_size++] = static_cast<char>(specs.type);
|
||||||
}
|
}
|
||||||
int num_digits = count_digits<1>(abs_value);
|
int num_digits = count_digits<1>(abs_value);
|
||||||
writer.write_int(num_digits, get_prefix(), specs,
|
writer.out_ = internal::write_int(writer.out_, num_digits, get_prefix(),
|
||||||
bin_writer<1>{abs_value, num_digits});
|
specs, [=](reserve_iterator it) {
|
||||||
|
return format_uint<1, char_type>(
|
||||||
|
it, abs_value, num_digits);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_oct() {
|
void on_oct() {
|
||||||
@ -1573,25 +1557,28 @@ template <typename Range> class basic_writer {
|
|||||||
// is not greater than the number of digits.
|
// is not greater than the number of digits.
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
}
|
}
|
||||||
writer.write_int(num_digits, get_prefix(), specs,
|
writer.out_ = internal::write_int(writer.out_, num_digits, get_prefix(),
|
||||||
bin_writer<3>{abs_value, num_digits});
|
specs, [=](reserve_iterator it) {
|
||||||
|
return format_uint<3, char_type>(
|
||||||
|
it, abs_value, num_digits);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { sep_size = 1 };
|
enum { sep_size = 1 };
|
||||||
|
|
||||||
struct num_writer {
|
struct num_writer {
|
||||||
unsigned_type abs_value;
|
UInt abs_value;
|
||||||
int size;
|
int size;
|
||||||
const std::string& groups;
|
const std::string& groups;
|
||||||
char_type sep;
|
char_type sep;
|
||||||
|
|
||||||
template <typename It> void operator()(It&& it) const {
|
template <typename It> It operator()(It it) const {
|
||||||
basic_string_view<char_type> s(&sep, sep_size);
|
basic_string_view<char_type> s(&sep, sep_size);
|
||||||
// Index of a decimal digit with the least significant digit having
|
// Index of a decimal digit with the least significant digit having
|
||||||
// index 0.
|
// index 0.
|
||||||
int digit_index = 0;
|
int digit_index = 0;
|
||||||
std::string::const_iterator group = groups.cbegin();
|
std::string::const_iterator group = groups.cbegin();
|
||||||
it = format_decimal<char_type>(
|
return format_decimal<char_type>(
|
||||||
it, abs_value, size,
|
it, abs_value, size,
|
||||||
[this, s, &group, &digit_index](char_type*& buffer) {
|
[this, s, &group, &digit_index](char_type*& buffer) {
|
||||||
if (*group <= 0 || ++digit_index % *group != 0 ||
|
if (*group <= 0 || ++digit_index % *group != 0 ||
|
||||||
@ -1624,8 +1611,9 @@ template <typename Range> class basic_writer {
|
|||||||
}
|
}
|
||||||
if (group == groups.cend())
|
if (group == groups.cend())
|
||||||
size += sep_size * ((num_digits - 1) / groups.back());
|
size += sep_size * ((num_digits - 1) / groups.back());
|
||||||
writer.write_int(size, get_prefix(), specs,
|
writer.out_ =
|
||||||
num_writer{abs_value, size, groups, sep});
|
internal::write_int(writer.out_, size, get_prefix(), specs,
|
||||||
|
num_writer{abs_value, size, groups, sep});
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_NORETURN void on_error() {
|
FMT_NORETURN void on_error() {
|
||||||
@ -1655,9 +1643,9 @@ template <typename Range> class basic_writer {
|
|||||||
void write(uint128_t value) { write_decimal(value); }
|
void write(uint128_t value) { write_decimal(value); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename Spec>
|
template <typename T> void write_int(T value, const format_specs& spec) {
|
||||||
void write_int(T value, const Spec& spec) {
|
using uint_type = uint32_or_64_or_128_t<T>;
|
||||||
handle_int_type_spec(spec.type, int_writer<T, Spec>(*this, value, spec));
|
handle_int_type_spec(spec.type, int_writer<uint_type>(*this, value, spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user