add range_put_all which can be overloaded with special optimizations
parent
e4dc237f4d
commit
d6219046be
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue