diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 57f3a961..a4c7e495 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -19,84 +19,6 @@ FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end, return it + (end - begin); } -template class truncating_iterator_base { - protected: - OutputIt out_; - size_t limit_; - size_t count_ = 0; - - truncating_iterator_base() : out_(), limit_(0) {} - - truncating_iterator_base(OutputIt out, size_t limit) - : out_(out), limit_(limit) {} - - public: - using iterator_category = std::output_iterator_tag; - using value_type = typename std::iterator_traits::value_type; - using difference_type = std::ptrdiff_t; - using pointer = void; - using reference = void; - FMT_UNCHECKED_ITERATOR(truncating_iterator_base); - - OutputIt base() const { return out_; } - size_t count() const { return count_; } -}; - -// An output iterator that truncates the output and counts the number of objects -// written to it. -template ::value_type>::type> -class truncating_iterator; - -template -class truncating_iterator - : public truncating_iterator_base { - mutable typename truncating_iterator_base::value_type blackhole_; - - public: - using value_type = typename truncating_iterator_base::value_type; - - truncating_iterator() = default; - - truncating_iterator(OutputIt out, size_t limit) - : truncating_iterator_base(out, limit) {} - - truncating_iterator& operator++() { - if (this->count_++ < this->limit_) ++this->out_; - return *this; - } - - truncating_iterator operator++(int) { - auto it = *this; - ++*this; - return it; - } - - value_type& operator*() const { - return this->count_ < this->limit_ ? *this->out_ : blackhole_; - } -}; - -template -class truncating_iterator - : public truncating_iterator_base { - public: - truncating_iterator() = default; - - truncating_iterator(OutputIt out, size_t limit) - : truncating_iterator_base(out, limit) {} - - template truncating_iterator& operator=(T val) { - if (this->count_++ < this->limit_) *this->out_++ = val; - return *this; - } - - truncating_iterator& operator++() { return *this; } - truncating_iterator& operator++(int) { return *this; } - truncating_iterator& operator*() { return *this; } -}; - // A compile-time string which is compiled into fast formatting code. class compiled_string {}; @@ -568,9 +490,10 @@ template ::value)> format_to_n_result format_to_n(OutputIt out, size_t n, const S& format_str, Args&&... args) { - auto it = fmt::format_to(detail::truncating_iterator(out, n), - format_str, std::forward(args)...); - return {it.base(), it.count()}; + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + format_to(std::back_inserter(buf), format_str, std::forward(args)...); + return {buf.out(), buf.count()}; } template (p, 3); - auto prev = it++; - EXPECT_EQ(prev.base(), p); - EXPECT_EQ(it.base(), p + 1); -} - -TEST(iterator_test, truncating_iterator_default_construct) { - auto it = fmt::detail::truncating_iterator(); - EXPECT_EQ(nullptr, it.base()); - EXPECT_EQ(std::size_t{0}, it.count()); -} - -#ifdef __cpp_lib_ranges -TEST(iterator_test, truncating_iterator_is_output_iterator) { - static_assert( - std::output_iterator, char>); -} -#endif - -TEST(iterator_test, truncating_back_inserter) { - auto buffer = std::string(); - auto bi = std::back_inserter(buffer); - auto it = fmt::detail::truncating_iterator(bi, 2); - *it++ = '4'; - *it++ = '2'; - *it++ = '1'; - EXPECT_EQ(buffer.size(), 2); - EXPECT_EQ(buffer, "42"); -} - TEST(compile_test, compile_fallback) { // FMT_COMPILE should fallback on runtime formatting when `if constexpr` is // not available.