forked from fmtlib/fmt
Reuse format_decimal
This commit is contained in:
@@ -882,7 +882,7 @@ struct chrono_formatter {
|
|||||||
to_unsigned(to_nonnegative_int(value, max_value<int>()));
|
to_unsigned(to_nonnegative_int(value, max_value<int>()));
|
||||||
int num_digits = detail::count_digits(n);
|
int num_digits = detail::count_digits(n);
|
||||||
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
||||||
out = format_decimal<char_type>(out, n, num_digits);
|
out = format_decimal<char_type>(out, n, num_digits).end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_nan() { std::copy_n("nan", 3, out); }
|
void write_nan() { std::copy_n("nan", 3, out); }
|
||||||
|
@@ -884,11 +884,19 @@ template <typename Char> void copy2(Char* dst, const char* src) {
|
|||||||
}
|
}
|
||||||
inline void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
|
inline void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
|
||||||
|
|
||||||
// Formats a decimal unsigned integer value writing into out.
|
template <typename Iterator> struct format_decimal_result {
|
||||||
|
Iterator begin;
|
||||||
|
Iterator end;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Formats a decimal unsigned integer value writing into out pointing to a
|
||||||
|
// buffer of specified size. The caller must ensure that the buffer is large
|
||||||
|
// enough.
|
||||||
template <typename Char, typename UInt>
|
template <typename Char, typename UInt>
|
||||||
inline Char* format_decimal(Char* out, UInt value, int num_digits) {
|
inline format_decimal_result<Char*> format_decimal(Char* out, UInt value,
|
||||||
FMT_ASSERT(num_digits >= 0, "invalid digit count");
|
int size) {
|
||||||
out += num_digits;
|
FMT_ASSERT(size >= count_digits(value), "invalid digit count");
|
||||||
|
out += size;
|
||||||
Char* end = out;
|
Char* end = out;
|
||||||
while (value >= 100) {
|
while (value >= 100) {
|
||||||
// Integer division is slow so do it for a group of two digits instead
|
// Integer division is slow so do it for a group of two digits instead
|
||||||
@@ -900,20 +908,22 @@ inline Char* format_decimal(Char* out, UInt value, int num_digits) {
|
|||||||
}
|
}
|
||||||
if (value < 10) {
|
if (value < 10) {
|
||||||
*--out = static_cast<Char>('0' + value);
|
*--out = static_cast<Char>('0' + value);
|
||||||
return end;
|
return {out, end};
|
||||||
}
|
}
|
||||||
copy2(out - 2, data::digits + static_cast<unsigned>(value * 2));
|
out -= 2;
|
||||||
return end;
|
copy2(out, data::digits + static_cast<unsigned>(value * 2));
|
||||||
|
return {out, end};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename UInt, typename Iterator,
|
template <typename Char, typename UInt, typename Iterator,
|
||||||
FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
|
FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
|
||||||
inline Iterator format_decimal(Iterator out, UInt value, int num_digits) {
|
inline format_decimal_result<Iterator> format_decimal(Iterator out, UInt value,
|
||||||
|
int num_digits) {
|
||||||
// Buffer should be large enough to hold all digits (<= digits10 + 1).
|
// Buffer should be large enough to hold all digits (<= digits10 + 1).
|
||||||
enum { max_size = digits10<UInt>() + 1 };
|
enum { max_size = digits10<UInt>() + 1 };
|
||||||
Char buffer[2 * max_size];
|
Char buffer[2 * max_size];
|
||||||
auto end = format_decimal(buffer, value, num_digits);
|
auto end = format_decimal(buffer, value, num_digits).end;
|
||||||
return detail::copy_str<Char>(buffer, end, out);
|
return {out, detail::copy_str<Char>(buffer, end, out)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned BASE_BITS, typename Char, typename UInt>
|
template <unsigned BASE_BITS, typename Char, typename UInt>
|
||||||
@@ -1488,10 +1498,10 @@ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
|
|||||||
|
|
||||||
void on_dec() {
|
void on_dec() {
|
||||||
auto num_digits = count_digits(abs_value);
|
auto num_digits = count_digits(abs_value);
|
||||||
out = write_int(out, num_digits, get_prefix(), specs,
|
out = write_int(
|
||||||
[this, num_digits](iterator it) {
|
out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) {
|
||||||
return format_decimal<Char>(it, abs_value, num_digits);
|
return format_decimal<Char>(it, abs_value, num_digits).end;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_hex() {
|
void on_hex() {
|
||||||
@@ -1710,7 +1720,7 @@ OutputIt write(OutputIt out, T value) {
|
|||||||
int num_digits = count_digits(abs_value);
|
int num_digits = count_digits(abs_value);
|
||||||
auto it = reserve(out, (negative ? 1 : 0) + static_cast<size_t>(num_digits));
|
auto it = reserve(out, (negative ? 1 : 0) + static_cast<size_t>(num_digits));
|
||||||
if (negative) *it++ = static_cast<Char>('-');
|
if (negative) *it++ = static_cast<Char>('-');
|
||||||
it = format_decimal<Char>(it, abs_value, num_digits);
|
it = format_decimal<Char>(it, abs_value, num_digits).end;
|
||||||
return base_iterator(out, it);
|
return base_iterator(out, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2546,8 +2556,9 @@ template <typename Handler, typename Char> struct id_adapter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char, typename Handler>
|
template <typename Char, typename Handler>
|
||||||
FMT_CONSTEXPR const Char* parse_replacement_field(
|
FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin,
|
||||||
const Char* begin, const Char* end, Handler&& handler) {
|
const Char* end,
|
||||||
|
Handler&& handler) {
|
||||||
++begin;
|
++begin;
|
||||||
if (begin == end) return handler.on_error("invalid format string"), end;
|
if (begin == end) return handler.on_error("invalid format string"), end;
|
||||||
if (static_cast<char>(*begin) == '}') {
|
if (static_cast<char>(*begin) == '}') {
|
||||||
@@ -2960,27 +2971,8 @@ class format_int {
|
|||||||
mutable char buffer_[buffer_size];
|
mutable char buffer_[buffer_size];
|
||||||
char* str_;
|
char* str_;
|
||||||
|
|
||||||
// Formats value in reverse and returns a pointer to the beginning.
|
|
||||||
char* format_decimal(unsigned long long value) {
|
char* format_decimal(unsigned long long value) {
|
||||||
char* ptr = buffer_ + (buffer_size - 1); // Parens to workaround MSVC bug.
|
return detail::format_decimal(buffer_, value, buffer_size - 1).begin;
|
||||||
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.
|
|
||||||
auto index = static_cast<unsigned>((value % 100) * 2);
|
|
||||||
value /= 100;
|
|
||||||
ptr -= 2;
|
|
||||||
// memcpy is faster than copying character by character.
|
|
||||||
memcpy(ptr, detail::data::digits + index, 2);
|
|
||||||
}
|
|
||||||
if (value < 10) {
|
|
||||||
*--ptr = static_cast<char>('0' + value);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
auto index = static_cast<unsigned>(value * 2);
|
|
||||||
ptr -= 2;
|
|
||||||
memcpy(ptr, detail::data::digits + index, 2);
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void format_signed(long long value) {
|
void format_signed(long long value) {
|
||||||
|
Reference in New Issue
Block a user