Skip to content

Commit 15252c8

Browse files
committed
Speed up iterator_buffer
1 parent dc97113 commit 15252c8

File tree

2 files changed

+258
-253
lines changed

2 files changed

+258
-253
lines changed

include/fmt/base.h

Lines changed: 0 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,136 +1856,6 @@ class fixed_buffer_traits {
18561856
}
18571857
};
18581858

1859-
// A buffer that writes to an output iterator when flushed.
1860-
template <typename OutputIt, typename T, typename Traits = buffer_traits>
1861-
class iterator_buffer : public Traits, public buffer<T> {
1862-
private:
1863-
OutputIt out_;
1864-
enum { buffer_size = 256 };
1865-
T data_[buffer_size];
1866-
1867-
static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
1868-
if (buf.size() == buffer_size) static_cast<iterator_buffer&>(buf).flush();
1869-
}
1870-
1871-
void flush() {
1872-
auto size = this->size();
1873-
this->clear();
1874-
const T* begin = data_;
1875-
const T* end = begin + this->limit(size);
1876-
while (begin != end) *out_++ = *begin++;
1877-
}
1878-
1879-
public:
1880-
explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
1881-
: Traits(n), buffer<T>(grow, data_, 0, buffer_size), out_(out) {}
1882-
iterator_buffer(iterator_buffer&& other) noexcept
1883-
: Traits(other),
1884-
buffer<T>(grow, data_, 0, buffer_size),
1885-
out_(other.out_) {}
1886-
~iterator_buffer() {
1887-
// Don't crash if flush fails during unwinding.
1888-
FMT_TRY { flush(); }
1889-
FMT_CATCH(...) {}
1890-
}
1891-
1892-
auto out() -> OutputIt {
1893-
flush();
1894-
return out_;
1895-
}
1896-
auto count() const -> size_t { return Traits::count() + this->size(); }
1897-
};
1898-
1899-
template <typename T>
1900-
class iterator_buffer<T*, T, fixed_buffer_traits> : public fixed_buffer_traits,
1901-
public buffer<T> {
1902-
private:
1903-
T* out_;
1904-
enum { buffer_size = 256 };
1905-
T data_[buffer_size];
1906-
1907-
static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
1908-
if (buf.size() == buf.capacity())
1909-
static_cast<iterator_buffer&>(buf).flush();
1910-
}
1911-
1912-
void flush() {
1913-
size_t n = this->limit(this->size());
1914-
if (this->data() == out_) {
1915-
out_ += n;
1916-
this->set(data_, buffer_size);
1917-
}
1918-
this->clear();
1919-
}
1920-
1921-
public:
1922-
explicit iterator_buffer(T* out, size_t n = buffer_size)
1923-
: fixed_buffer_traits(n), buffer<T>(grow, out, 0, n), out_(out) {}
1924-
iterator_buffer(iterator_buffer&& other) noexcept
1925-
: fixed_buffer_traits(other),
1926-
buffer<T>(static_cast<iterator_buffer&&>(other)),
1927-
out_(other.out_) {
1928-
if (this->data() != out_) {
1929-
this->set(data_, buffer_size);
1930-
this->clear();
1931-
}
1932-
}
1933-
~iterator_buffer() { flush(); }
1934-
1935-
auto out() -> T* {
1936-
flush();
1937-
return out_;
1938-
}
1939-
auto count() const -> size_t {
1940-
return fixed_buffer_traits::count() + this->size();
1941-
}
1942-
};
1943-
1944-
template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
1945-
public:
1946-
explicit iterator_buffer(T* out, size_t = 0)
1947-
: buffer<T>([](buffer<T>&, size_t) {}, out, 0, ~size_t()) {}
1948-
1949-
auto out() -> T* { return &*this->end(); }
1950-
};
1951-
1952-
template <typename Container>
1953-
class container_buffer : public buffer<typename Container::value_type> {
1954-
private:
1955-
using value_type = typename Container::value_type;
1956-
1957-
static FMT_CONSTEXPR void grow(buffer<value_type>& buf, size_t capacity) {
1958-
auto& self = static_cast<container_buffer&>(buf);
1959-
self.container.resize(capacity);
1960-
self.set(&self.container[0], capacity);
1961-
}
1962-
1963-
public:
1964-
Container& container;
1965-
1966-
explicit container_buffer(Container& c)
1967-
: buffer<value_type>(grow, c.size()), container(c) {}
1968-
};
1969-
1970-
// A buffer that writes to a container with the contiguous storage.
1971-
template <typename OutputIt>
1972-
class iterator_buffer<
1973-
OutputIt,
1974-
enable_if_t<is_back_insert_iterator<OutputIt>::value &&
1975-
is_contiguous<typename OutputIt::container_type>::value,
1976-
typename OutputIt::container_type::value_type>>
1977-
: public container_buffer<typename OutputIt::container_type> {
1978-
private:
1979-
using base = container_buffer<typename OutputIt::container_type>;
1980-
1981-
public:
1982-
explicit iterator_buffer(typename OutputIt::container_type& c) : base(c) {}
1983-
explicit iterator_buffer(OutputIt out, size_t = 0)
1984-
: base(get_container(out)) {}
1985-
1986-
auto out() -> OutputIt { return OutputIt(this->container); }
1987-
};
1988-
19891859
// A buffer that counts the number of code units written discarding the output.
19901860
template <typename T = char> class counting_buffer : public buffer<T> {
19911861
private:
@@ -2010,37 +1880,6 @@ template <typename T = char> class counting_buffer : public buffer<T> {
20101880
template <typename T>
20111881
struct is_back_insert_iterator<basic_appender<T>> : std::true_type {};
20121882

2013-
template <typename It, typename Enable = std::true_type>
2014-
struct is_buffer_appender : std::false_type {};
2015-
template <typename It>
2016-
struct is_buffer_appender<
2017-
It, bool_constant<
2018-
is_back_insert_iterator<It>::value &&
2019-
std::is_base_of<buffer<typename It::container_type::value_type>,
2020-
typename It::container_type>::value>>
2021-
: std::true_type {};
2022-
2023-
// Maps an output iterator to a buffer.
2024-
template <typename T, typename OutputIt,
2025-
FMT_ENABLE_IF(!is_buffer_appender<OutputIt>::value)>
2026-
auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
2027-
return iterator_buffer<OutputIt, T>(out);
2028-
}
2029-
template <typename T, typename OutputIt,
2030-
FMT_ENABLE_IF(is_buffer_appender<OutputIt>::value)>
2031-
auto get_buffer(OutputIt out) -> buffer<T>& {
2032-
return get_container(out);
2033-
}
2034-
2035-
template <typename Buf, typename OutputIt>
2036-
auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) {
2037-
return buf.out();
2038-
}
2039-
template <typename T, typename OutputIt>
2040-
auto get_iterator(buffer<T>&, OutputIt out) -> OutputIt {
2041-
return out;
2042-
}
2043-
20441883
// This type is intentionally undefined, only used for errors.
20451884
template <typename T, typename Char> struct type_is_unformattable_for;
20461885

@@ -2722,98 +2561,6 @@ inline auto arg(const char* name, const T& arg) -> detail::named_arg<T> {
27222561
return {name, arg};
27232562
}
27242563

2725-
/// Formats a string and writes the output to `out`.
2726-
template <typename OutputIt,
2727-
FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
2728-
char>::value)>
2729-
// DEPRECATED! Passing out as a forwarding reference.
2730-
auto vformat_to(OutputIt&& out, string_view fmt, format_args args)
2731-
-> remove_cvref_t<OutputIt> {
2732-
auto&& buf = detail::get_buffer<char>(out);
2733-
detail::vformat_to(buf, fmt, args, {});
2734-
return detail::get_iterator(buf, out);
2735-
}
2736-
2737-
/**
2738-
* Formats `args` according to specifications in `fmt`, writes the result to
2739-
* the output iterator `out` and returns the iterator past the end of the output
2740-
* range. `format_to` does not append a terminating null character.
2741-
*
2742-
* **Example**:
2743-
*
2744-
* auto out = std::vector<char>();
2745-
* fmt::format_to(std::back_inserter(out), "{}", 42);
2746-
*/
2747-
template <typename OutputIt, typename... T,
2748-
FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
2749-
char>::value)>
2750-
FMT_INLINE auto format_to(OutputIt&& out, format_string<T...> fmt, T&&... args)
2751-
-> remove_cvref_t<OutputIt> {
2752-
return vformat_to(out, fmt.str, vargs<T...>{{args...}});
2753-
}
2754-
2755-
template <typename OutputIt> struct format_to_n_result {
2756-
OutputIt out; ///< Iterator past the end of the output range.
2757-
size_t size; ///< Total (not truncated) output size.
2758-
};
2759-
2760-
template <typename OutputIt, typename... T,
2761-
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2762-
auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
2763-
-> format_to_n_result<OutputIt> {
2764-
using traits = detail::fixed_buffer_traits;
2765-
auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
2766-
detail::vformat_to(buf, fmt, args, {});
2767-
return {buf.out(), buf.count()};
2768-
}
2769-
2770-
/**
2771-
* Formats `args` according to specifications in `fmt`, writes up to `n`
2772-
* characters of the result to the output iterator `out` and returns the total
2773-
* (not truncated) output size and the iterator past the end of the output
2774-
* range. `format_to_n` does not append a terminating null character.
2775-
*/
2776-
template <typename OutputIt, typename... T,
2777-
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2778-
FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,
2779-
T&&... args) -> format_to_n_result<OutputIt> {
2780-
return vformat_to_n(out, n, fmt.str, vargs<T...>{{args...}});
2781-
}
2782-
2783-
struct format_to_result {
2784-
char* out; ///< Pointer to just after the last successful write.
2785-
bool truncated; ///< Specifies if the output was truncated.
2786-
2787-
FMT_CONSTEXPR operator char*() const {
2788-
// Report truncation to prevent silent data loss.
2789-
if (truncated) report_error("output is truncated");
2790-
return out;
2791-
}
2792-
};
2793-
2794-
template <size_t N>
2795-
FMT_DEPRECATED auto vformat_to(char (&out)[N], string_view fmt,
2796-
format_args args) -> format_to_result {
2797-
auto result = vformat_to_n(out, N, fmt, args);
2798-
return {result.out, result.size > N};
2799-
}
2800-
2801-
template <size_t N, typename... T>
2802-
FMT_INLINE auto format_to(char (&out)[N], format_string<T...> fmt, T&&... args)
2803-
-> format_to_result {
2804-
auto result = vformat_to_n(out, N, fmt.str, vargs<T...>{{args...}});
2805-
return {result.out, result.size > N};
2806-
}
2807-
2808-
/// Returns the number of chars in the output of `format(fmt, args...)`.
2809-
template <typename... T>
2810-
FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,
2811-
T&&... args) -> size_t {
2812-
auto buf = detail::counting_buffer<>();
2813-
detail::vformat_to(buf, fmt.str, vargs<T...>{{args...}}, {});
2814-
return buf.count();
2815-
}
2816-
28172564
FMT_API void vprint(string_view fmt, format_args args);
28182565
FMT_API void vprint(FILE* f, string_view fmt, format_args args);
28192566
FMT_API void vprintln(FILE* f, string_view fmt, format_args args);

0 commit comments

Comments
 (0)