// license:GPL-2.0+ // copyright-holders:Couriersud /* * pstream.c * */ #include "pstream.h" #include "palloc.h" #include #include #include // VS2015 prefers _dup #ifdef _WIN32 #include #else #include #endif namespace plib { pstream::~pstream() { } // ----------------------------------------------------------------------------- // pistream: input stream // ----------------------------------------------------------------------------- pistream::~pistream() { } // ----------------------------------------------------------------------------- // postream: output stream // ----------------------------------------------------------------------------- postream::~postream() { } void postream::write(pistream &strm) { char buf[1024]; pos_type r; while ((r=strm.read(buf, 1024)) > 0) write(buf, r); } // ----------------------------------------------------------------------------- // Input file stream // ----------------------------------------------------------------------------- pifilestream::pifilestream(const pstring &fname) : pistream(0) , m_file(fopen(fname.c_str(), "rb")) , m_pos(0) , m_actually_close(true) , m_filename(fname) { if (m_file == nullptr) throw file_open_e(fname); else init(); } pifilestream::pifilestream(void *file, const pstring &name, const bool do_close) : pistream(0), m_file(file), m_pos(0), m_actually_close(do_close), m_filename(name) { if (m_file == nullptr) throw null_argument_e(m_filename); init(); } void pifilestream::init() { if (ftell(static_cast(m_file)) >= 0) { if (fseek(static_cast(m_file), 0, SEEK_SET) >= 0) set_flag(FLAG_SEEKABLE); } } pifilestream::~pifilestream() { if (m_actually_close) { fclose(static_cast(m_file)); } } pifilestream::pos_type pifilestream::vread(void *buf, const pos_type n) { pos_type r = fread(buf, 1, n, static_cast(m_file)); if (r < n) { if (feof(static_cast(m_file))) set_flag(FLAG_EOF); if (ferror(static_cast(m_file))) throw file_read_e(m_filename); } m_pos += r; return r; } void pifilestream::vseek(const pos_type n) { if (fseek(static_cast(m_file), static_cast(n), SEEK_SET) < 0) throw file_e("File seek failed: {}", m_filename); else m_pos = n; if (feof(static_cast(m_file))) set_flag(FLAG_EOF); else clear_flag(FLAG_EOF); if (ferror(static_cast(m_file))) throw file_e("Generic file operation failed: {}", m_filename); } pifilestream::pos_type pifilestream::vtell() { long ret = ftell(static_cast(m_file)); if (ret < 0) { return m_pos; } else return static_cast(ret); } // ----------------------------------------------------------------------------- // pstdin: reads from stdin // ----------------------------------------------------------------------------- pstdin::pstdin() : pifilestream(stdin, "", false) { /* nothing to do */ } pstdin::~pstdin() { } // ----------------------------------------------------------------------------- // Output file stream // ----------------------------------------------------------------------------- pofilestream::pofilestream(const pstring &fname) : postream(0), m_file(fopen(fname.c_str(), "wb")), m_pos(0), m_actually_close(true), m_filename(fname) { if (m_file == nullptr) throw file_open_e(m_filename); init(); } pofilestream::pofilestream(void *file, const pstring &name, const bool do_close) : postream(0), m_file(file), m_pos(0), m_actually_close(do_close), m_filename(name) { if (m_file == nullptr) throw null_argument_e(m_filename); init(); } void pofilestream::init() { if (ftell(static_cast(m_file)) >= 0) if (fseek(static_cast(m_file), 0, SEEK_SET) >= 0) set_flag(FLAG_SEEKABLE); } pofilestream::~pofilestream() { if (m_actually_close) { fflush(static_cast(m_file)); fclose(static_cast(m_file)); } } void pofilestream::vwrite(const void *buf, const pos_type n) { std::size_t r = fwrite(buf, 1, n, static_cast(m_file)); if (r < n) { //printf("%ld %ld %s\n", r, n, strerror(errno)); if (ferror(static_cast(m_file))) throw file_write_e(m_filename); } m_pos += r; } void pofilestream::vseek(const pos_type n) { if (fseek(static_cast(m_file), static_cast(n), SEEK_SET) < 0) throw file_e("File seek failed: {}", m_filename); else { m_pos = n; if (ferror(static_cast(m_file))) throw file_e("Generic file operation failed: {}", m_filename); } } pstream::pos_type pofilestream::vtell() { std::ptrdiff_t ret = ftell(static_cast(m_file)); if (ret < 0) { return m_pos; } else return static_cast(ret); } postringstream::~postringstream() { } // ----------------------------------------------------------------------------- // pstderr: write to stderr // ----------------------------------------------------------------------------- pstderr::pstderr() #ifdef _WIN32 : pofilestream(fdopen(_dup(fileno(stderr)), "wb"), "", true) #else : pofilestream(fdopen(dup(fileno(stderr)), "wb"), "", true) #endif { } pstderr::~pstderr() { } // ----------------------------------------------------------------------------- // pstdout: write to stdout // ----------------------------------------------------------------------------- pstdout::pstdout() #ifdef _WIN32 : pofilestream(fdopen(_dup(fileno(stdout)), "wb"), "", true) #else : pofilestream(fdopen(dup(fileno(stdout)), "wb"), "", true) #endif { } pstdout::~pstdout() { } // ----------------------------------------------------------------------------- // Memory stream // ----------------------------------------------------------------------------- pimemstream::pimemstream(const void *mem, const pos_type len) : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast(mem)) { } pimemstream::pimemstream(const pomemstream &ostrm) : pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast(ostrm.memory())) { } pimemstream::~pimemstream() { } pimemstream::pos_type pimemstream::vread(void *buf, const pos_type n) { pos_type ret = (m_pos + n <= m_len) ? n : m_len - m_pos; if (ret > 0) { std::copy(m_mem + m_pos, m_mem + m_pos + ret, static_cast(buf)); m_pos += ret; } if (ret < n) set_flag(FLAG_EOF); return ret; } void pimemstream::vseek(const pos_type n) { m_pos = (n>=m_len) ? m_len : n; clear_flag(FLAG_EOF); } pimemstream::pos_type pimemstream::vtell() { return m_pos; } pistringstream::~pistringstream() { } // ----------------------------------------------------------------------------- // Output memory stream // ----------------------------------------------------------------------------- pomemstream::pomemstream() : postream(FLAG_SEEKABLE), m_pos(0), m_capacity(1024), m_size(0) { m_mem = palloc_array(m_capacity); } pomemstream::~pomemstream() { pfree_array(m_mem); } void pomemstream::vwrite(const void *buf, const pos_type n) { if (m_pos + n >= m_capacity) { while (m_pos + n >= m_capacity) m_capacity *= 2; char *o = m_mem; m_mem = palloc_array(m_capacity); if (m_mem == nullptr) { throw out_of_mem_e("pomemstream::vwrite"); } std::copy(o, o + m_pos, m_mem); pfree_array(o); } std::copy(static_cast(buf), static_cast(buf) + n, m_mem + m_pos); m_pos += n; m_size = std::max(m_pos, m_size); } void pomemstream::vseek(const pos_type n) { m_pos = n; m_size = std::max(m_pos, m_size); if (m_size >= m_capacity) { while (m_size >= m_capacity) m_capacity *= 2; char *o = m_mem; m_mem = palloc_array(m_capacity); if (m_mem == nullptr) { throw out_of_mem_e("pomemstream::vseek"); } std::copy(o, o + m_pos, m_mem); pfree_array(o); } } pstream::pos_type pomemstream::vtell() { return m_pos; } bool putf8_reader::readline(pstring &line) { pstring::code_t c = 0; m_linebuf = ""; if (!this->readcode(c)) { line = ""; return false; } while (true) { if (c == 10) break; else if (c != 13) /* ignore CR */ m_linebuf += pstring(c); if (!this->readcode(c)) break; } line = m_linebuf; return true; } putf8_fmt_writer::putf8_fmt_writer(postream &strm) : pfmt_writer_t() , putf8_writer(strm) { } putf8_fmt_writer::~putf8_fmt_writer() { } void putf8_fmt_writer::vdowrite(const pstring &ls) const { write(ls); } }