From 2249f5571ec25e9c1d352299672486e2f8b05041 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 3 Jul 2019 15:30:45 -0700 Subject: [PATCH] Simplify thousands separator handling and cleanup --- include/fmt/format.h | 133 +++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 81 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 241fa748..9b15ea10 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -359,15 +359,6 @@ class truncating_iterator truncating_iterator& operator*() { return *this; } }; -#ifndef FMT_USE_GRISU -# define FMT_USE_GRISU 1 -#endif - -template constexpr bool use_grisu() { - return FMT_USE_GRISU && std::numeric_limits::is_iec559 && - sizeof(T) <= sizeof(double); -} - // A range with the specified output iterator and value type. template class output_range { @@ -395,6 +386,50 @@ class buffer_range : output_range(std::back_inserter(buf)) {} }; +template +inline size_t count_code_points(basic_string_view s) { + return s.size(); +} + +// Counts the number of code points in a UTF-8 string. +inline size_t count_code_points(basic_string_view s) { + const char8_t* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80) ++num_code_points; + } + return num_code_points; +} + +inline char8_t to_char8_t(char c) { return static_cast(c); } + +template +using needs_conversion = bool_constant< + std::is_same::value_type, + char>::value && + std::is_same::value>; + +template ::value)> +OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { + return std::copy(begin, end, it); +} + +template ::value)> +OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { + return std::transform(begin, end, it, to_char8_t); +} + +#ifndef FMT_USE_GRISU +# define FMT_USE_GRISU 1 +#endif + +template constexpr bool use_grisu() { + return FMT_USE_GRISU && std::numeric_limits::is_iec559 && + sizeof(T) <= sizeof(double); +} + template template void buffer::append(const U* begin, const U* end) { @@ -578,8 +613,7 @@ template struct int_traits { conditional_t::digits <= 32, uint32_t, uint64_t>; }; -// Static data is placed in this class template to allow header-only -// configuration. +// Static data is placed in this class template for the header-only config. template struct FMT_EXTERN_TEMPLATE_API basic_data { static const uint64_t POWERS_OF_10_64[]; static const uint32_t ZERO_OR_POWERS_OF_10_32[]; @@ -596,7 +630,7 @@ template struct FMT_EXTERN_TEMPLATE_API basic_data { FMT_EXTERN template struct basic_data; -// This is a struct rather than a typedef to avoid shadowing warnings in gcc. +// This is a struct rather than an alias to avoid shadowing warnings in gcc. struct data : basic_data<> {}; #ifdef FMT_BUILTIN_CLZLL @@ -637,42 +671,6 @@ template inline int count_digits(UInt n) { template <> int count_digits<4>(internal::fallback_uintptr n); -template -inline size_t count_code_points(basic_string_view s) { - return s.size(); -} - -// Counts the number of code points in a UTF-8 string. -inline size_t count_code_points(basic_string_view s) { - const char8_t* data = s.data(); - size_t num_code_points = 0; - for (size_t i = 0, size = s.size(); i != size; ++i) { - if ((data[i] & 0xc0) != 0x80) ++num_code_points; - } - return num_code_points; -} - -inline char8_t to_char8_t(char c) { return static_cast(c); } - -template -struct needs_conversion - : bool_constant< - std::is_same::value_type, - char>::value && - std::is_same::value> {}; - -template ::value)> -OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { - return std::copy(begin, end, it); -} - -template ::value)> -OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) { - return std::transform(begin, end, it, to_char8_t); -} - #if FMT_HAS_CPP_ATTRIBUTE(always_inline) # define FMT_ALWAYS_INLINE __attribute__((always_inline)) #else @@ -736,18 +734,6 @@ class decimal_formatter { } }; -// An lg handler that formats a decimal number with a terminating null. -class decimal_formatter_null : public decimal_formatter { - public: - explicit decimal_formatter_null(char* buf) : decimal_formatter(buf) {} - - template char* on(uint32_t u) { - char* buf = decimal_formatter::on(u); - *buf = '\0'; - return buf; - } -}; - #ifdef FMT_BUILTIN_CLZ // Optional version of count_digits for better performance on 32-bit platforms. inline int count_digits(uint32_t n) { @@ -756,16 +742,7 @@ inline int count_digits(uint32_t n) { } #endif -// A functor that doesn't add a thousands separator. -struct no_thousands_sep { - typedef char char_type; - - template void operator()(Char*) {} - - enum { size = 0 }; -}; - -// A functor that adds a thousands separator. +// A callable that adds a thousands separator. template class add_thousands_sep { private: basic_string_view sep_; @@ -774,8 +751,6 @@ template class add_thousands_sep { unsigned digit_index_; public: - typedef Char char_type; - explicit add_thousands_sep(basic_string_view sep) : sep_(sep), digit_index_(0) {} @@ -785,8 +760,6 @@ template class add_thousands_sep { std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(), internal::make_checked(buffer, sep_.size())); } - - enum { size = 1 }; }; template FMT_API Char thousands_sep_impl(locale_ref loc); @@ -830,23 +803,21 @@ inline Char* format_decimal(Char* buffer, UInt value, int num_digits, return end; } -template inline Iterator format_decimal(Iterator out, UInt value, int num_digits, ThousandsSep sep) { FMT_ASSERT(num_digits >= 0, "invalid digit count"); - typedef typename ThousandsSep::char_type char_type; // Buffer should be large enough to hold all digits (<= digits10 + 1). enum { max_size = std::numeric_limits::digits10 + 1 }; - FMT_ASSERT(ThousandsSep::size <= 1, "invalid separator"); - char_type buffer[max_size + max_size / 3]; + Char buffer[max_size + max_size / 3]; auto end = format_decimal(buffer, value, num_digits, sep); - return internal::copy_str(buffer, end, out); + return internal::copy_str(buffer, end, out); } -template +template inline It format_decimal(It out, UInt value, int num_digits) { - return format_decimal(out, value, num_digits, no_thousands_sep()); + return format_decimal(out, value, num_digits, [](Char*) {}); } template