summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/pstream.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/pstream.h')
-rw-r--r--src/lib/netlist/plib/pstream.h322
1 files changed, 245 insertions, 77 deletions
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index ca21bca795a..72a2f242106 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -1,108 +1,208 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * pstream.h
- */
+
#ifndef PSTREAM_H_
#define PSTREAM_H_
+///
+/// \file pstream.h
+///
-#include "palloc.h"
#include "pconfig.h"
-#include "pexception.h"
#include "pfmtlog.h"
+#include "pgsl.h"
#include "pstring.h"
#include <array>
-#include <type_traits>
-#include <vector>
-#include <ios>
#include <fstream>
+#include <ios>
#include <iostream>
+#include <memory>
#include <sstream>
+#include <type_traits>
+#include <vector>
namespace plib {
-// -----------------------------------------------------------------------------
-// putf8reader_t: reader on top of istream
-// -----------------------------------------------------------------------------
+ /// \brief wrapper around istream read
+ ///
+ template <typename S, typename T>
+ static S & istream_read(S &is, T * data, size_t len)
+ {
+ using ct = typename S::char_type;
+ static_assert((sizeof(T) % sizeof(ct)) == 0, "istream_read sizeof issue");
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ return is.read(reinterpret_cast<ct *>(data), gsl::narrow<std::streamsize>(len * sizeof(T)));
+ }
-/* this digests linux & dos/windows text files */
+ /// \brief wrapper around ostream write
+ ///
+ template <typename S, typename T>
+ static S & ostream_write(S &os, const T * data, size_t len)
+ {
+ using ct = typename S::char_type;
+ static_assert((sizeof(T) % sizeof(ct)) == 0, "ostream_write sizeof issue");
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ return os.write(reinterpret_cast<const ct *>(data), gsl::narrow<std::streamsize>(len * sizeof(T)));
+ }
+ /// \brief a named istream pointer container
+ ///
+ /// This moveable object allows to pass istream unique pointers with
+ /// information about the origin (filename). This is useful in error
+ /// reporting where the source of the stream has to be logged.
+ ///
+ struct istream_uptr
+ {
+ explicit istream_uptr() = default;
-template <typename T>
-struct constructor_helper
-{
- plib::unique_ptr<std::istream> operator()(T &&s) { return std::move(plib::make_unique<T>(std::move(s))); }
-};
+ istream_uptr(std::unique_ptr<std::istream> &&strm, const pstring &filename)
+ : m_strm(std::move(strm))
+ , m_filename(filename)
+ {
+ }
+ istream_uptr(const istream_uptr &) = delete;
+ istream_uptr &operator=(const istream_uptr &) = delete;
+ istream_uptr(istream_uptr &&rhs) noexcept
+ : m_strm(std::move(rhs.m_strm))
+ , m_filename(std::move(rhs.m_filename))
+ {
+ }
+ istream_uptr &operator=(istream_uptr &&) = delete;
+
+ ~istream_uptr() = default;
+ std::istream * operator ->() noexcept { return m_strm.get(); }
+ std::istream & operator *() noexcept { return *m_strm; }
+ pstring filename() { return m_filename; }
+
+ bool empty() { return m_strm == nullptr; }
+
+ // FIXME: workaround input context should accept stream_ptr
+
+ std::unique_ptr<std::istream> release_stream() { return std::move(m_strm); }
+ private:
+ std::unique_ptr<std::istream> m_strm;
+ pstring m_filename;
+ };
+
+///
+/// \brief digests linux & dos/windows text files
+///
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class putf8_reader
{
public:
- COPYASSIGN(putf8_reader, delete)
- putf8_reader &operator=(putf8_reader &&src) = delete;
+ PCOPYASSIGN(putf8_reader, delete)
virtual ~putf8_reader() = default;
- template <typename T>
- friend struct constructor_helper;
+ putf8_reader(putf8_reader &&rhs) noexcept
+ : m_strm(std::move(rhs.m_strm))
+ {
+ }
- template <typename T>
- putf8_reader(T &&strm) // NOLINT(cppcoreguidelines-special-member-functions, misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
- : m_strm(std::move(constructor_helper<T>()(std::move(strm)))) // NOLINT(bugprone-move-forwarding-reference)
- {}
+ putf8_reader(std::unique_ptr<std::istream> &&rhs) noexcept
+ : m_strm(std::move(rhs))
+ {
+ // no bad surprises
+ m_strm->imbue(std::locale::classic());
+ }
bool eof() const { return m_strm->eof(); }
- bool readline(pstring &line);
- bool readbyte1(std::istream::char_type &b)
+ /// \brief Read a line of UTF8 characters from the stream.
+ ///
+ /// The line will not contain a trailing linefeed
+ ///
+ /// \param line pstring reference to the result
+ /// \returns Returns false if at end of file
+ ///
+ bool read_line(putf8string &line)
+ {
+ putf8string::code_t c = 0;
+ line = "";
+ if (!this->read_code(c))
+ {
+ return false;
+ }
+ while (true)
+ {
+ if (c == 10)
+ break;
+ if (c != 13) // ignore CR
+ line += putf8string(1, c);
+ if (!this->read_code(c))
+ break;
+ }
+ return true;
+ }
+
+ /// \brief Read a line of UTF8 characters from the stream including trailing linefeed.
+ ///
+ /// The line will contain the trailing linefeed
+ ///
+ /// \param line pstring reference to the result
+ /// \returns Returns false if at end of file
+ ///
+ bool read_line_lf(putf8string &line)
+ {
+ putf8string::code_t c = 0;
+ line = "";
+ if (!this->read_code(c))
+ {
+ return false;
+ }
+ while (true)
+ {
+ if (c != 13) // ignore CR
+ line += putf8string(1, c);
+ if (c == 10)
+ break;
+ if (!this->read_code(c))
+ break;
+ }
+ return true;
+ }
+
+ bool readbyte(std::istream::char_type &b)
{
if (m_strm->eof())
return false;
m_strm->read(&b, 1);
- return true;
+ return (!m_strm->eof());
}
- bool readcode(putf8string::traits_type::code_t &c)
+
+ bool read_code(putf8string::traits_type::code_t &c)
{
std::array<std::istream::char_type, 4> b{0};
if (m_strm->eof())
return false;
m_strm->read(&b[0], 1);
+ if (m_strm->eof())
+ return false;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
const std::size_t l = putf8string::traits_type::codelen(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
for (std::size_t i = 1; i < l; i++)
{
+ m_strm->read(&b[i], 1);
if (m_strm->eof())
return false;
- m_strm->read(&b[i], 1);
}
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
c = putf8string::traits_type::code(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
return true;
}
std::istream &stream() { return *m_strm; }
private:
- plib::unique_ptr<std::istream> m_strm;
- putf8string m_linebuf;
-};
-
-template <>
-struct constructor_helper<putf8_reader>
-{
- plib::unique_ptr<std::istream> operator()(putf8_reader &&s) { return std::move(s.m_strm); }
-};
-
-template <>
-struct constructor_helper<plib::unique_ptr<std::istream>>
-{
- plib::unique_ptr<std::istream> operator()(plib::unique_ptr<std::istream> &&s) { return std::move(s); }
+ std::unique_ptr<std::istream> m_strm;
};
-
-// -----------------------------------------------------------------------------
-// putf8writer_t: writer on top of ostream
-// -----------------------------------------------------------------------------
+///
+/// \brief writer on top of ostream
+///
class putf8_writer
{
@@ -111,12 +211,12 @@ public:
putf8_writer(putf8_writer &&src) noexcept : m_strm(src.m_strm) {}
- COPYASSIGN(putf8_writer, delete)
+ PCOPYASSIGN(putf8_writer, delete)
putf8_writer &operator=(putf8_writer &&src) = delete;
virtual ~putf8_writer() = default;
- void writeline(const pstring &line) const
+ void write_line(const pstring &line) const
{
write(line);
write(10);
@@ -126,15 +226,17 @@ public:
{
// NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
const putf8string conv_utf8(text);
- m_strm->write(conv_utf8.c_str(), static_cast<std::streamsize>(plib::strlen(conv_utf8.c_str())));
+ //m_strm->write(conv_utf8.c_str(), static_cast<std::streamsize>(plib::strlen(conv_utf8.c_str() )));
+ ostream_write(*m_strm, conv_utf8.c_str(), conv_utf8.size());
}
void write(const pstring::value_type c) const
{
- pstring t = pstring("") + c;
+ pstring t(1,c);
write(t);
}
+ void flush() { m_strm->flush(); }
private:
std::ostream *m_strm;
};
@@ -144,24 +246,27 @@ class putf8_fmt_writer : public pfmt_writer_t<putf8_fmt_writer>, public putf8_wr
public:
explicit putf8_fmt_writer(std::ostream *strm)
- : pfmt_writer_t()
- , putf8_writer(strm)
+ : putf8_writer(strm)
{
}
- COPYASSIGNMOVE(putf8_fmt_writer, delete)
+ PCOPYASSIGNMOVE(putf8_fmt_writer, delete)
~putf8_fmt_writer() override = default;
//protected:
- void vdowrite(const pstring &ls) const;
+ void upstream_write(const pstring &s) const
+ {
+ write(s);
+ }
+
private:
};
-// -----------------------------------------------------------------------------
-// pbinary_writer_t: writer on top of ostream
-// -----------------------------------------------------------------------------
+///
+/// \brief writer on top of ostream
+///
class pbinary_writer
{
@@ -169,7 +274,7 @@ 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)
+ PCOPYASSIGN(pbinary_writer, delete)
pbinary_writer &operator=(pbinary_writer &&src) = delete;
virtual ~pbinary_writer() = default;
@@ -177,23 +282,24 @@ public:
template <typename T>
void write(const T &val)
{
- m_strm.write(reinterpret_cast<const std::ostream::char_type *>(&val), sizeof(T));
+ ostream_write(m_strm, &val, 1);
}
void write(const pstring &s)
{
- const auto sm = reinterpret_cast<const std::ostream::char_type *>(s.c_str());
- const std::streamsize sl(static_cast<std::streamsize>(pstring_mem_t_size(s)));
+ const auto *sm = s.c_str();
+ //const auto sl(std::char_traits<pstring::mem_t>::length(sm));
+ const auto sl(s.size());
write(sl);
- m_strm.write(sm, sl);
+ ostream_write(m_strm, sm, sl);
}
template <typename T>
void write(const std::vector<T> &val)
{
- const std::streamsize sz(static_cast<std::streamsize>(val.size()));
+ const typename std::vector<T>::size_type sz(val.size());
write(sz);
- m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * static_cast<std::streamsize>(sizeof(T)));
+ ostream_write(m_strm, val.data(), sz);
}
private:
@@ -206,7 +312,7 @@ 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)
+ PCOPYASSIGN(pbinary_reader, delete)
pbinary_reader &operator=(pbinary_reader &&src) = delete;
virtual ~pbinary_reader() = default;
@@ -214,14 +320,14 @@ public:
template <typename T>
void read(T &val)
{
- m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), sizeof(T));
+ istream_read(m_strm, &val, 1);
}
void read( pstring &s)
{
std::size_t sz = 0;
read(sz);
- std::vector<plib::string_info<pstring>::mem_t> buf(sz+1);
+ std::vector<plib::string_info<putf8string>::mem_t> buf(sz+1);
m_strm.read(buf.data(), static_cast<std::streamsize>(sz));
buf[sz] = 0;
s = pstring(buf.data());
@@ -233,14 +339,14 @@ public:
std::size_t sz = 0;
read(sz);
val.resize(sz);
- m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), static_cast<std::streamsize>(sizeof(T) * sz));
+ istream_read(m_strm, val.data(), sz);
}
private:
std::istream &m_strm;
};
-inline void copystream(std::ostream &dest, std::istream &src)
+inline void copy_stream(std::ostream &dest, std::istream &src)
{
// FIXME: optimize
std::array<std::ostream::char_type, 1024> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
@@ -251,12 +357,71 @@ inline void copystream(std::ostream &dest, std::istream &src)
}
}
+///
+/// \brief utf8 filename aware ifstream wrapper
+///
+class ifstream : public std::ifstream
+{
+public:
+
+ using filename_type = std::conditional<compile_info::win32() && (!compile_info::mingw() || compile_info::version::vmajor()>=9),
+ pstring_t<pwchar_traits>, pstring_t<putf8_traits>>::type;
+
+ template <typename T>
+ explicit ifstream(const pstring_t<T> &name, ios_base::openmode mode = ios_base::in)
+ : std::ifstream(filename_type(name).c_str(), mode)
+ {
+ }
+
+ explicit ifstream(const std::string &name, ios_base::openmode mode = ios_base::in)
+ : std::ifstream(filename_type(putf8string(name)).c_str(), mode)
+ {
+ }
+};
+
+///
+/// \brief utf8 filename aware ofstream wrapper
+///
+class ofstream : public std::ofstream
+{
+public:
+ using filename_type = std::conditional<compile_info::win32() && (!compile_info::mingw() || compile_info::version::vmajor()>=9),
+ pstring_t<pwchar_traits>, pstring_t<putf8_traits>>::type;
+
+ ofstream() : std::ofstream() {}
+
+ template <typename T>
+ explicit ofstream(const pstring_t<T> &name, ios_base::openmode mode = ios_base::out | ios_base::trunc)
+ : std::ofstream(filename_type(name).c_str(), mode)
+ {
+ }
+
+ explicit ofstream(const std::string &name, ios_base::openmode mode = ios_base::out | ios_base::trunc)
+ : std::ofstream(filename_type(putf8string(name)).c_str(), mode)
+ {
+ }
+
+ template <typename T>
+ void open(const pstring_t<T> &name, ios_base::openmode mode = ios_base::out | ios_base::trunc)
+ {
+ std::ofstream::open(filename_type(name).c_str(), mode);
+ }
+
+ template <typename T>
+ void open(const std::string &name, ios_base::openmode mode = ios_base::out | ios_base::trunc)
+ {
+ std::ofstream::open(filename_type(putf8string(name)).c_str(), mode);
+ }
+
+};
+
+
struct perrlogger
{
template <typename ... Args>
explicit perrlogger(Args&& ... args)
{
- h()(std::forward<Args>(args)...);
+ h()(std::forward<Args>(args)...); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
}
private:
static putf8_fmt_writer &h()
@@ -272,14 +437,17 @@ private:
namespace filesystem
{
+
+ // FIXME: u8path should return a path object (c++17)
+
template< class Source >
- pstring /*path */ u8path( const Source& source )
+ pstring u8path( const Source& source )
{
- return pstring(source);
+ return source;
}
-}
+} // namespace filesystem
} // namespace plib
-#endif /* PSTREAM_H_ */
+#endif // PSTREAM_H_