forked from OctaForge/libostd
cleanups and optimizations
parent
78e6771148
commit
3a82495a4c
16
ostd/io.hh
16
ostd/io.hh
|
@ -193,6 +193,22 @@ namespace detail {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
inline void range_put_all(stdout_range &r, R range) {
|
||||||
|
if constexpr(
|
||||||
|
is_contiguous_range<R> &&
|
||||||
|
std::is_same_v<std::remove_const_t<range_value_t<R>>, char>
|
||||||
|
) {
|
||||||
|
if (fwrite(range.data(), 1, range.size(), stdout) != range.size()) {
|
||||||
|
throw io_error{"stdout write error"};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (; !range.empty(); range.pop_front()) {
|
||||||
|
r.put(range.front());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -431,30 +431,7 @@ inline namespace string_literals {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
/* TODO: redesign this */
|
||||||
template<
|
|
||||||
typename T, bool = std::is_convertible_v<T, string_range>,
|
|
||||||
bool = std::is_convertible_v<T, char>
|
|
||||||
>
|
|
||||||
struct ConcatPut;
|
|
||||||
|
|
||||||
template<typename T, bool B>
|
|
||||||
struct ConcatPut<T, true, B> {
|
|
||||||
template<typename R>
|
|
||||||
static void put(R &sink, string_range v) {
|
|
||||||
range_put_all(sink, v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct ConcatPut<T, false, true> {
|
|
||||||
template<typename R>
|
|
||||||
static void put(R &sink, char v) {
|
|
||||||
sink.put(v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R, typename T, typename F>
|
template<typename R, typename T, typename F>
|
||||||
R &&concat(R &&sink, T const &v, string_range sep, F func) {
|
R &&concat(R &&sink, T const &v, string_range sep, F func) {
|
||||||
auto range = ostd::iter(v);
|
auto range = ostd::iter(v);
|
||||||
|
@ -462,9 +439,17 @@ R &&concat(R &&sink, T const &v, string_range sep, F func) {
|
||||||
return std::forward<R>(sink);
|
return std::forward<R>(sink);
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
detail::ConcatPut<
|
using VT = decltype(func(range.front()));
|
||||||
decltype(func(range.front()))
|
static_assert(
|
||||||
>::put(sink, func(range.front()));
|
std::is_convertible_v<VT, string_range> ||
|
||||||
|
std::is_convertible_v<VT, char>,
|
||||||
|
"range value must be convertible to string range or char"
|
||||||
|
);
|
||||||
|
if constexpr(std::is_convertible_v<VT, string_range>) {
|
||||||
|
range_put_all(sink, string_range{func(range.front())});
|
||||||
|
} else {
|
||||||
|
sink.put(func(range.front()));
|
||||||
|
}
|
||||||
range.pop_front();
|
range.pop_front();
|
||||||
if (range.empty()) {
|
if (range.empty()) {
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue