forked from OctaForge/libostd
remove silly intermediate ranges for writef, print directly to stream
This commit is contained in:
parent
077835e4b6
commit
3e683a2436
32
ostd/io.hh
32
ostd/io.hh
|
@ -165,6 +165,17 @@ namespace detail {
|
|||
) {
|
||||
write_impl(ostd::to_string(v));
|
||||
}
|
||||
|
||||
/* lightweight output range for direct stdout */
|
||||
struct StdoutRange: OutputRange<StdoutRange, char> {
|
||||
StdoutRange() {}
|
||||
bool put(char c) {
|
||||
return putchar(c) != EOF;
|
||||
}
|
||||
size_t put_n(char const *p, size_t n) {
|
||||
return fwrite(p, 1, n, stdout);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -181,38 +192,25 @@ inline void write(T const &v, A const &...args) {
|
|||
template<typename T>
|
||||
inline void writeln(T const &v) {
|
||||
write(v);
|
||||
putc('\n', stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
inline void writeln(T const &v, A const &...args) {
|
||||
write(v);
|
||||
write(args...);
|
||||
putc('\n', stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
template<typename ...A>
|
||||
inline void writef(ConstCharRange fmt, A const &...args) {
|
||||
char buf[512];
|
||||
ptrdiff_t need = format(
|
||||
detail::FormatOutRange<sizeof(buf)>(buf), fmt, args...
|
||||
);
|
||||
if (need < 0) {
|
||||
return;
|
||||
} else if (size_t(need) < sizeof(buf)) {
|
||||
fwrite(buf, 1, need, stdout);
|
||||
return;
|
||||
}
|
||||
std::vector<char> s;
|
||||
s.reserve(need);
|
||||
format(detail::UnsafeWritefRange(s.data()), fmt, args...);
|
||||
fwrite(s.data(), 1, need, stdout);
|
||||
format(detail::StdoutRange{}, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename ...A>
|
||||
inline void writefln(ConstCharRange fmt, A const &...args) {
|
||||
writef(fmt, args...);
|
||||
putc('\n', stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
} /* namespace ostd */
|
||||
|
|
|
@ -35,32 +35,6 @@ enum class StreamSeek {
|
|||
template<typename T = char, bool = IsPod<T>>
|
||||
struct StreamRange;
|
||||
|
||||
namespace detail {
|
||||
template<size_t N>
|
||||
struct FormatOutRange: OutputRange<FormatOutRange<N>, char> {
|
||||
FormatOutRange(char *ibuf): buf(ibuf), idx(0) {}
|
||||
FormatOutRange(FormatOutRange const &r): buf(r.buf), idx(r.idx) {}
|
||||
char *buf;
|
||||
size_t idx;
|
||||
bool put(char v) {
|
||||
if (idx < N) {
|
||||
buf[idx++] = v;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct UnsafeWritefRange: OutputRange<UnsafeWritefRange, char> {
|
||||
UnsafeWritefRange(char *p): p_ptr(p) {}
|
||||
bool put(char c) {
|
||||
*p_ptr++ = c;
|
||||
return true;
|
||||
}
|
||||
char *p_ptr;
|
||||
};
|
||||
}
|
||||
|
||||
struct Stream {
|
||||
private:
|
||||
struct StNat {};
|
||||
|
@ -138,21 +112,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename ...A>
|
||||
bool writef(ConstCharRange fmt, A const &...args) {
|
||||
char buf[512];
|
||||
ptrdiff_t need = format(
|
||||
detail::FormatOutRange<sizeof(buf)>(buf), fmt, args...
|
||||
);
|
||||
if (need < 0) {
|
||||
return false;
|
||||
} else if (size_t(need) < sizeof(buf)) {
|
||||
return write_bytes(buf, need) == size_t(need);
|
||||
}
|
||||
std::vector<char> s;
|
||||
s.reserve(need);
|
||||
format(detail::UnsafeWritefRange(s.data()), fmt, args...);
|
||||
return write_bytes(s.data(), need) == size_t(need);
|
||||
}
|
||||
bool writef(ConstCharRange fmt, A const &...args);
|
||||
|
||||
template<typename ...A>
|
||||
bool writefln(ConstCharRange fmt, A const &...args) {
|
||||
|
@ -246,6 +206,11 @@ inline StreamRange<T> Stream::iter() {
|
|||
return StreamRange<T>(*this);
|
||||
}
|
||||
|
||||
template<typename ...A>
|
||||
inline bool Stream::writef(ConstCharRange fmt, A const &...args) {
|
||||
return format(iter(), fmt, args...) >= 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue