// license:GPL-2.0+ // copyright-holders:Couriersud /* * pstream.h */ #ifndef PSTREAM_H_ #define PSTREAM_H_ #include "palloc.h" #include "pconfig.h" #include "pexception.h" #include "pfmtlog.h" #include "pstring.h" #include "pstrutil.h" #include #include #include #include #include #include #include namespace plib { // ----------------------------------------------------------------------------- // putf8reader_t: reader on top of istream // ----------------------------------------------------------------------------- /* this digests linux & dos/windows text files */ template struct constructor_helper { plib::unique_ptr operator()(T &&s) { return std::move(plib::make_unique(std::move(s))); } }; // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) class putf8_reader { public: COPYASSIGN(putf8_reader, delete) putf8_reader &operator=(putf8_reader &&src) = delete; virtual ~putf8_reader() = default; template friend struct constructor_helper; template putf8_reader(T &&strm) // NOLINT(cppcoreguidelines-special-member-functions, misc-forwarding-reference-overload, bugprone-forwarding-reference-overload) : m_strm(std::move(constructor_helper()(std::move(strm)))) // NOLINT(bugprone-move-forwarding-reference) {} bool eof() const { return m_strm->eof(); } bool readline(pstring &line) { putf8string::code_t c = 0; m_linebuf = putf8string(""); if (!this->readcode(c)) { line = ""; return false; } while (true) { if (c == 10) break; else if (c != 13) /* ignore CR */ m_linebuf += putf8string(1, c); if (!this->readcode(c)) break; } line = m_linebuf; return true; } bool readbyte(std::istream::char_type &b) { if (m_strm->eof()) return false; m_strm->read(&b, 1); return true; } bool readcode(putf8string::traits_type::code_t &c) { std::array b{0}; if (m_strm->eof()) return false; m_strm->read(&b[0], 1); const std::size_t l = putf8string::traits_type::codelen(reinterpret_cast(&b)); for (std::size_t i = 1; i < l; i++) { if (m_strm->eof()) return false; m_strm->read(&b[i], 1); } c = putf8string::traits_type::code(reinterpret_cast(&b)); return true; } std::istream &stream() { return *m_strm; } private: plib::unique_ptr m_strm; putf8string m_linebuf; }; template <> struct constructor_helper { plib::unique_ptr operator()(putf8_reader &&s) { return std::move(s.m_strm); } }; template <> struct constructor_helper> { plib::unique_ptr operator()(plib::unique_ptr &&s) { return std::move(s); } }; // ----------------------------------------------------------------------------- // putf8writer_t: writer on top of ostream // ----------------------------------------------------------------------------- class putf8_writer { public: explicit putf8_writer(std::ostream *strm) : m_strm(strm) {} putf8_writer(putf8_writer &&src) noexcept : m_strm(src.m_strm) {} COPYASSIGN(putf8_writer, delete) putf8_writer &operator=(putf8_writer &&src) = delete; virtual ~putf8_writer() = default; void writeline(const pstring &line) const { write(line); write(10); } void write(const pstring &text) const { // NOLINTNEXTLINE(performance-unnecessary-copy-initialization) const putf8string conv_utf8(text); m_strm->write(conv_utf8.c_str(), static_cast(plib::strlen(conv_utf8.c_str()))); } void write(const pstring::value_type c) const { pstring t(1,c); write(t); } private: std::ostream *m_strm; }; class putf8_fmt_writer : public pfmt_writer_t, public putf8_writer { public: explicit putf8_fmt_writer(std::ostream *strm) : pfmt_writer_t() , putf8_writer(strm) { } COPYASSIGNMOVE(putf8_fmt_writer, delete) ~putf8_fmt_writer() override = default; //protected: void vdowrite(const pstring &s) const { write(s); } private: }; // ----------------------------------------------------------------------------- // pbinary_writer_t: writer on top of ostream // ----------------------------------------------------------------------------- class pbinary_writer { public: explicit pbinary_writer(std::ostream &strm) : m_strm(strm) {} pbinary_writer(pbinary_writer &&src) noexcept : m_strm(src.m_strm) {} COPYASSIGN(pbinary_writer, delete) pbinary_writer &operator=(pbinary_writer &&src) = delete; virtual ~pbinary_writer() = default; template void write(const T &val) { m_strm.write(reinterpret_cast(&val), sizeof(T)); } void write(const pstring &s) { const auto sm = reinterpret_cast(s.c_str()); const auto sl(static_cast(pstring_mem_t_size(s))); write(sl); m_strm.write(sm, sl); } template void write(const std::vector &val) { const auto sz(static_cast(val.size())); write(sz); m_strm.write(reinterpret_cast(val.data()), sz * static_cast(sizeof(T))); } private: std::ostream &m_strm; }; class pbinary_reader { public: explicit pbinary_reader(std::istream &strm) : m_strm(strm) {} pbinary_reader(pbinary_reader &&src) noexcept : m_strm(src.m_strm) { } COPYASSIGN(pbinary_reader, delete) pbinary_reader &operator=(pbinary_reader &&src) = delete; virtual ~pbinary_reader() = default; template void read(T &val) { m_strm.read(reinterpret_cast(&val), sizeof(T)); } void read( pstring &s) { std::size_t sz = 0; read(sz); std::vector::mem_t> buf(sz+1); m_strm.read(buf.data(), static_cast(sz)); buf[sz] = 0; s = pstring(buf.data()); } template void read(std::vector &val) { std::size_t sz = 0; read(sz); val.resize(sz); m_strm.read(reinterpret_cast(val.data()), static_cast(sizeof(T) * sz)); } private: std::istream &m_strm; }; inline void copystream(std::ostream &dest, std::istream &src) { // FIXME: optimize std::array buf; // NOLINT(cppcoreguidelines-pro-type-member-init) while (!src.eof()) { src.read(buf.data(), 1); dest.write(buf.data(), 1); } } struct perrlogger { template explicit perrlogger(Args&& ... args) { h()(std::forward(args)...); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay) } private: static putf8_fmt_writer &h() { static plib::putf8_fmt_writer perr(&std::cerr); return perr; } }; // ----------------------------------------------------------------------------- // c++17 preparation // ----------------------------------------------------------------------------- namespace filesystem { template< class Source > pstring /*path */ u8path( const Source& source ) { return source; } } // namespace filesystem } // namespace plib #endif /* PSTREAM_H_ */