Type erase output iterators
This commit is contained in:
parent
18024853b6
commit
9d3cd0afb2
@ -725,6 +725,41 @@ class container_buffer : public buffer<typename Container::value_type> {
|
||||
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
||||
};
|
||||
|
||||
// A buffer that writes to an output iterator when flushed.
|
||||
template <typename OutputIt, typename T>
|
||||
class iterator_buffer : public buffer<T> {
|
||||
private:
|
||||
enum { buffer_size = 256 };
|
||||
|
||||
OutputIt out_;
|
||||
T data_[buffer_size];
|
||||
|
||||
protected:
|
||||
void grow(size_t) final {
|
||||
if (this->size() == buffer_size) flush();
|
||||
}
|
||||
|
||||
public:
|
||||
explicit iterator_buffer(OutputIt out)
|
||||
: buffer<T>(data_, 0, buffer_size), out_(out) {}
|
||||
~iterator_buffer() { flush(); }
|
||||
|
||||
OutputIt out() { return out_; }
|
||||
void flush();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class iterator_buffer<T*, T> : public buffer<T> {
|
||||
protected:
|
||||
void grow(size_t) final {}
|
||||
|
||||
public:
|
||||
explicit iterator_buffer(T* out) : buffer<T>(out, 0, ~size_t()) {}
|
||||
|
||||
T* out() { return &*this->end(); }
|
||||
void flush() {}
|
||||
};
|
||||
|
||||
// An output iterator that appends to the buffer.
|
||||
// It is used to reduce symbol sizes for the common case.
|
||||
template <typename T>
|
||||
@ -1229,6 +1264,9 @@ struct is_contiguous_back_insert_iterator : std::false_type {};
|
||||
template <typename Container>
|
||||
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
|
||||
: is_contiguous<Container> {};
|
||||
template <typename Char>
|
||||
struct is_contiguous_back_insert_iterator<buffer_appender<Char>>
|
||||
: std::true_type {};
|
||||
|
||||
// A type-erased reference to an std::locale to avoid heavy <locale> include.
|
||||
class locale_ref {
|
||||
|
@ -581,6 +581,12 @@ void buffer<T>::append(const U* begin, const U* end) {
|
||||
begin += count;
|
||||
} while (begin != end);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename T>
|
||||
void iterator_buffer<OutputIt, T>::flush() {
|
||||
out_ = std::copy(data_, data_ + this->size(), out_);
|
||||
this->clear();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// The number of characters to store in the basic_memory_buffer object itself
|
||||
@ -3560,9 +3566,12 @@ template <typename OutputIt, typename S, typename... Args,
|
||||
detail::is_string<S>::value)>
|
||||
inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
|
||||
detail::check_format_string<Args...>(format_str);
|
||||
using context = format_context_t<OutputIt, char_t<S>>;
|
||||
return vformat_to(out, to_string_view(format_str),
|
||||
make_format_args<context>(args...));
|
||||
using Char = char_t<S>;
|
||||
detail::iterator_buffer<OutputIt, Char> buf(out);
|
||||
detail::vformat_to(buf, to_string_view(format_str),
|
||||
make_format_args<buffer_context<Char>>(args...));
|
||||
buf.flush();
|
||||
return buf.out();
|
||||
}
|
||||
|
||||
template <typename OutputIt> struct format_to_n_result {
|
||||
|
Loading…
Reference in New Issue
Block a user