add range_put_all which can be overloaded with special optimizations

master
Daniel Kolesa 2017-02-19 18:14:09 +01:00
parent e4dc237f4d
commit d6219046be
5 changed files with 31 additions and 45 deletions

View File

@ -7,6 +7,7 @@
#include <ostd/io.hh>
using namespace ostd;
using namespace ostd::string_literals;
struct Foo {
};
@ -16,10 +17,10 @@ template<typename R>
void to_format(Foo const &, R &writer, format_spec const &fs) {
switch (fs.spec()) {
case 'i':
writer.put_string("Foo1");
range_put_all(writer, "Foo1"_sr);
break;
default:
writer.put_string("Foo2");
range_put_all(writer, "Foo2"_sr);
break;
}
}
@ -30,10 +31,10 @@ struct Bar {
void to_format(R &writer, format_spec const &fs) const {
switch (fs.spec()) {
case 'i':
writer.put_string("Bar1");
range_put_all(writer, "Bar1"_sr);
break;
default:
writer.put_string("Bar2");
range_put_all(writer, "Bar2"_sr);
break;
}
}

View File

@ -574,9 +574,7 @@ inline auto slice_until(R &&range) {
template<typename R1, typename R2>
inline R2 copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_front()) {
orange.put(irange.front());
}
range_put_all(orange, irange);
return orange;
}

View File

@ -196,8 +196,8 @@ struct format_spec {
if (p_flags & FMT_FLAG_HASH ) {
out.put('#');
}
out = ostd::copy(string_range{"*.*"}, out);
out = ostd::copy(spec, out);
range_put_all(out, string_range{"*.*"});
range_put_all(out, spec);
return std::forward<R>(out);
}
@ -467,7 +467,7 @@ namespace detail {
if (sign) {
writer.put(neg ? '-' : *((" \0+") + lsgn * 2));
}
writer = ostd::copy(string_range{pfx, pfx + pfxlen}, writer);
range_put_all(writer, string_range{pfx, pfx + pfxlen});
if (zero) {
fl->write_spaces(writer, n + pfxlen + sign, true, '0');
}
@ -556,7 +556,7 @@ namespace detail {
range.pop_front();
/* write the rest (if any) */
for (; !range.empty(); range.pop_front()) {
writer = ostd::copy(sep, writer);
range_put_all(writer, sep);
format_ritem(
writer, escape, expandval, fl->rest(), range.front()
);
@ -646,7 +646,7 @@ namespace detail {
n = this->precision();
}
this->write_spaces(writer, n, true);
writer = ostd::copy(val.slice(0, n), writer);
range_put_all(writer, val.slice(0, n));
this->write_spaces(writer, n, false);
}
@ -718,19 +718,18 @@ namespace detail {
/* see above */
throw format_error{"invalid float format"};
}
writer = ostd::copy(string_range{dbuf, dbuf + ret}, writer);
range_put_all(writer, string_range{dbuf, dbuf + ret});
delete[] dbuf;
} else {
writer = ostd::copy(string_range{rbuf, rbuf + ret}, writer);
range_put_all(writer, string_range{rbuf, rbuf + ret});
}
}
template<typename R, typename T>
void write_val(R &writer, bool escape, T const &val) const {
/* stuff fhat can be custom-formatted goes first */
if constexpr(fmt_tofmt_test<T, tostr_range<R>>) {
tostr_range<R> sink(writer);
to_format(val, sink, *this);
if constexpr(fmt_tofmt_test<T, noop_output_range<char>>) {
to_format(val, writer, *this);
return;
}
/* second best, we can convert to string slice */

View File

@ -694,6 +694,13 @@ struct output_range {
using range_category = output_range_tag;
};
template<typename OR, typename IR>
inline void range_put_all(OR &orange, IR range) {
for (; !range.empty(); range.pop_front()) {
orange.put(range.front());
}
}
template<typename T>
struct noop_output_range: output_range<noop_output_range<T>> {
using value_type = T;

View File

@ -439,7 +439,7 @@ namespace detail {
struct ConcatPut<T, true, B> {
template<typename R>
static void put(R &sink, string_range v) {
sink = ostd::copy(v, sink);
range_put_all(sink, v);
}
};
@ -466,7 +466,7 @@ R &&concat(R &&sink, T const &v, string_range sep, F func) {
if (range.empty()) {
break;
}
sink = ostd::copy(sep, sink);
range_put_all(sink, sep);
}
return std::forward<R>(sink);
}
@ -479,12 +479,12 @@ R &&concat(R &&sink, T const &v, string_range sep = " ") {
}
for (;;) {
string_range ret = range.front();
sink = ostd::copy(ret, sink);
range_put_all(sink, ret);
range.pop_front();
if (range.empty()) {
break;
}
sink = ostd::copy(sep, sink);
range_put_all(sink, sep);
}
return std::forward<R>(sink);
}
@ -500,25 +500,6 @@ R &&concat(R &&sink, std::initializer_list<T> v, string_range sep = " ") {
}
namespace detail {
template<typename R>
struct tostr_range: output_range<tostr_range<R>> {
using value_type = char;
using reference = char &;
using size_type = size_t;
using difference_type = ptrdiff_t;
tostr_range() = delete;
tostr_range(R &out): p_out(out) {}
void put(char v) {
p_out.put(v);
}
void put_string(string_range r) {
p_out = ostd::copy(r, p_out);
}
private:
R &p_out;
};
template<typename T, typename R>
static std::true_type test_stringify(
decltype(std::declval<T const &>().to_string(std::declval<R &>())) *
@ -560,12 +541,11 @@ struct to_string<T, std::enable_if_t<detail::iterable_test<T>>> {
template<typename T>
struct to_string<T, std::enable_if_t<
detail::stringify_test<T, detail::tostr_range<appender_range<std::string>>>
detail::stringify_test<T, appender_range<std::string>>
>> {
std::string operator()(T const &v) const {
auto app = appender_range<std::string>{};
detail::tostr_range<appender_range<std::string>> sink(app);
if (!v.to_string(sink)) {
auto app = appender<std::string>();
if (!v.to_string(app)) {
return std::string{};
}
return std::move(app.get());
@ -735,7 +715,8 @@ public:
p_buf = sbuf;
}
char_range bufr{p_buf, p_buf + input.size()};
ostd::copy(input, bufr).put('\0');
range_put_all(bufr, input);
bufr.put('\0');
}
~temp_c_string() {
if (p_allocated) {