From 64973fb160635ee2770d07732290c97e06ab0493 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 7 Jul 2020 15:04:17 -0700 Subject: [PATCH] Remove allocating containers from on_num Use std::string_view and std::array containers when FMT_STATIC_THOUSANDS_SEPARATOR is defined. This will help in the case for embedded system where even using containers that can potentially allocate results in malloc/free and new/delete being linked into the binary. In many embedded cases dynamic library allocation is prohibited and even the cost of linking in these libraries costs too high of a cost in flash size. Resolves #1762 --- include/fmt/core.h | 7 +++++++ include/fmt/format.h | 14 ++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index 761162eb..0a9f3c7f 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -392,6 +392,13 @@ template class basic_string_view { constexpr iterator begin() const { return data_; } constexpr iterator end() const { return data_ + size_; } + constexpr iterator cbegin() const { return data_; } + constexpr iterator cend() const { return data_ + size_; } + + constexpr bool empty() const { return size_ == 0; }; + + constexpr Char back() const { return data_[size_ - 1]; } + constexpr const Char& operator[](size_t pos) const { return data_[pos]; } FMT_CONSTEXPR void remove_prefix(size_t n) { diff --git a/include/fmt/format.h b/include/fmt/format.h index ddf086f8..795ec538 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -34,6 +34,7 @@ #define FMT_FORMAT_H_ #include +#include #include #include #include @@ -1552,13 +1553,18 @@ template struct int_writer { enum { sep_size = 1 }; void on_num() { +#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) std::string groups = grouping(locale); +#else + constexpr const char kDefaultGroups[] = "\03"; + basic_string_view groups(kDefaultGroups, sizeof(kDefaultGroups)); +#endif if (groups.empty()) return on_dec(); auto sep = thousands_sep(locale); if (!sep) return on_dec(); int num_digits = count_digits(abs_value); int size = num_digits, n = num_digits; - std::string::const_iterator group = groups.cbegin(); + auto group = groups.cbegin(); while (group != groups.cend() && num_digits > *group && *group > 0 && *group != max_value()) { size += sep_size; @@ -1568,9 +1574,9 @@ template struct int_writer { if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back()); char digits[40]; format_decimal(digits, abs_value, num_digits); - basic_memory_buffer buffer; + // TODO(kammce): remove the * 2! + std::array buffer; size += prefix_size; - buffer.resize(size); basic_string_view s(&sep, sep_size); // Index of a decimal digit with the least significant digit having index 0. int digit_index = 0; @@ -1590,7 +1596,7 @@ template struct int_writer { make_checked(p, s.size())); } if (prefix_size != 0) p[-1] = static_cast('-'); - write(out, basic_string_view(buffer.data(), buffer.size()), specs); + write(out, basic_string_view(buffer.data(), size), specs); } void on_chr() { *out++ = static_cast(abs_value); }