Commit 322736d3 authored by Victor Zverovich's avatar Victor Zverovich

Add support for arbitrary output iterators

parent 10291194
...@@ -832,25 +832,32 @@ inline Container &get_container(std::back_insert_iterator<Container> it) { ...@@ -832,25 +832,32 @@ inline Container &get_container(std::back_insert_iterator<Container> it) {
} }
} // namespace internal } // namespace internal
// A range where begin() returns back_insert_iterator. template <typename OutputIt, typename T = typename OutputIt::value_type>
template <typename Container> class output_range {
class back_insert_range {
private: private:
Container &container_; OutputIt it_;
// Unused yet.
using sentinel = void;
sentinel end() const;
public: public:
using iterator = std::back_insert_iterator<Container>; using value_type = T;
using value_type = typename Container::value_type;
struct sentinel { explicit output_range(OutputIt it): it_(it) {}
friend bool operator!=(sentinel, iterator) { return false; } OutputIt begin() const { return it_; }
friend bool operator!=(iterator, sentinel) { return false; } };
};
back_insert_range(Container &c) : container_(c) {} // A range where begin() returns back_insert_iterator.
template <typename Container>
class back_insert_range:
public output_range<std::back_insert_iterator<Container>> {
using base = output_range<std::back_insert_iterator<Container>>;
public:
using value_type = typename Container::value_type;
iterator begin() const { return std::back_inserter(container_); } using base::base;
sentinel end() const { return sentinel(); } back_insert_range(Container &c): base(std::back_inserter(c)) {}
}; };
// Formatting context. // Formatting context.
......
...@@ -2023,7 +2023,7 @@ class arg_formatter: public internal::arg_formatter_base<Range> { ...@@ -2023,7 +2023,7 @@ class arg_formatter: public internal::arg_formatter_base<Range> {
\endrst \endrst
*/ */
arg_formatter(basic_context<Range> &ctx, format_specs &spec) arg_formatter(basic_context<Range> &ctx, format_specs &spec)
: base(Range(internal::get_container(ctx.begin())), spec), ctx_(ctx) {} : base(Range(ctx.begin()), spec), ctx_(ctx) {}
using base::operator(); using base::operator();
...@@ -3036,6 +3036,13 @@ inline void format_to(wmemory_buffer &buf, wstring_view format_str, ...@@ -3036,6 +3036,13 @@ inline void format_to(wmemory_buffer &buf, wstring_view format_str,
vformat_to(buf, format_str, make_args<wcontext>(args...)); vformat_to(buf, format_str, make_args<wcontext>(args...));
} }
template <typename Container, typename Context>
typename std::enable_if<!is_contiguous<Container>::value>::type
vformat_to(std::back_insert_iterator<Container> out,
string_view format_str,
basic_format_args<Context> args) {
}
template <typename Container, typename... Args> template <typename Container, typename... Args>
inline typename std::enable_if<is_contiguous<Container>::value>::type inline typename std::enable_if<is_contiguous<Container>::value>::type
format_to(std::back_insert_iterator<Container> out, format_to(std::back_insert_iterator<Container> out,
...@@ -3043,15 +3050,13 @@ inline typename std::enable_if<is_contiguous<Container>::value>::type ...@@ -3043,15 +3050,13 @@ inline typename std::enable_if<is_contiguous<Container>::value>::type
vformat_to(out, format_str, make_args(args...)); vformat_to(out, format_str, make_args(args...));
} }
template <typename Container, typename... Args> template <typename OutputIt, typename... Args>
inline typename std::enable_if<!is_contiguous<Container>::value>::type inline void format_to(OutputIt out, string_view format_str,
format_to(std::back_insert_iterator<Container> out, const Args & ... args) {
string_view format_str, const Args & ... args) { using range = output_range<OutputIt, char>;
using range = back_insert_range<Container>;
auto store = make_args<basic_context<range>>(args...); auto store = make_args<basic_context<range>>(args...);
do_vformat_to<arg_formatter<range>>( do_vformat_to<arg_formatter<range>>(
range(internal::get_container(out)), format_str, range(out), format_str, basic_format_args<basic_context<range>>(store));
basic_format_args<basic_context<range>>(store));
} }
inline std::string vformat(string_view format_str, format_args args) { inline std::string vformat(string_view format_str, format_args args) {
......
...@@ -1910,8 +1910,11 @@ TEST(FormatTest, ToString) { ...@@ -1910,8 +1910,11 @@ TEST(FormatTest, ToString) {
EXPECT_EQ("42", fmt::to_string(42)); EXPECT_EQ("42", fmt::to_string(42));
} }
TEST(WriterTest, NoncontiguousIterator) { TEST(WriterTest, OutputIterators) {
std::list<char> out; std::list<char> out;
fmt::format_to(std::back_inserter(out), "{}", 42); fmt::format_to(std::back_inserter(out), "{}", 42);
EXPECT_EQ("42", std::string(out.begin(), out.end())); EXPECT_EQ("42", std::string(out.begin(), out.end()));
std::stringstream s;
fmt::format_to(std::ostream_iterator<char>(s), "{}", 42);
EXPECT_EQ("42", s.str());
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment