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));
|
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>
|
template<typename T>
|
||||||
|
@ -181,38 +192,25 @@ inline void write(T const &v, A const &...args) {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void writeln(T const &v) {
|
inline void writeln(T const &v) {
|
||||||
write(v);
|
write(v);
|
||||||
putc('\n', stdout);
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ...A>
|
template<typename T, typename ...A>
|
||||||
inline void writeln(T const &v, A const &...args) {
|
inline void writeln(T const &v, A const &...args) {
|
||||||
write(v);
|
write(v);
|
||||||
write(args...);
|
write(args...);
|
||||||
putc('\n', stdout);
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
inline void writef(ConstCharRange fmt, A const &...args) {
|
inline void writef(ConstCharRange fmt, A const &...args) {
|
||||||
char buf[512];
|
format(detail::StdoutRange{}, fmt, args...);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
inline void writefln(ConstCharRange fmt, A const &...args) {
|
inline void writefln(ConstCharRange fmt, A const &...args) {
|
||||||
writef(fmt, args...);
|
writef(fmt, args...);
|
||||||
putc('\n', stdout);
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
|
@ -35,32 +35,6 @@ enum class StreamSeek {
|
||||||
template<typename T = char, bool = IsPod<T>>
|
template<typename T = char, bool = IsPod<T>>
|
||||||
struct StreamRange;
|
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 {
|
struct Stream {
|
||||||
private:
|
private:
|
||||||
struct StNat {};
|
struct StNat {};
|
||||||
|
@ -138,21 +112,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
bool writef(ConstCharRange fmt, A const &...args) {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
bool writefln(ConstCharRange fmt, A const &...args) {
|
bool writefln(ConstCharRange fmt, A const &...args) {
|
||||||
|
@ -246,6 +206,11 @@ inline StreamRange<T> Stream::iter() {
|
||||||
return StreamRange<T>(*this);
|
return StreamRange<T>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ...A>
|
||||||
|
inline bool Stream::writef(ConstCharRange fmt, A const &...args) {
|
||||||
|
return format(iter(), fmt, args...) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue