summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/psource.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/psource.h')
-rw-r--r--src/lib/netlist/plib/psource.h175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/psource.h b/src/lib/netlist/plib/psource.h
new file mode 100644
index 00000000000..2db2feb78d4
--- /dev/null
+++ b/src/lib/netlist/plib/psource.h
@@ -0,0 +1,175 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+#ifndef PSOURCE_H_
+#define PSOURCE_H_
+
+///
+/// \file putil.h
+///
+
+#include "palloc.h"
+#include "pexception.h"
+#include "pstring.h"
+#include "pstream.h"
+
+#include <algorithm>
+#include <initializer_list>
+#include <sstream>
+#include <vector>
+
+
+#define PSOURCELOC() plib::source_location(__FILE__, __LINE__)
+
+namespace plib
+{
+
+ /// \brief Source code locations.
+ ///
+ /// The c++20 draft for source locations is based on const char * strings.
+ /// It is thus only suitable for c++ source code and not for programmatic
+ /// parsing of files. This class is a replacement for dynamic use cases.
+ ///
+ struct source_location
+ {
+ source_location() noexcept
+ : m_file("unknown"), m_func(m_file), m_line(0), m_col(0)
+ { }
+
+ source_location(pstring file, unsigned line) noexcept
+ : m_file(std::move(file)), m_func("unknown"), m_line(line), m_col(0)
+ { }
+
+ source_location(pstring file, pstring func, unsigned line) noexcept
+ : m_file(std::move(file)), m_func(std::move(func)), m_line(line), m_col(0)
+ { }
+
+ PCOPYASSIGNMOVE(source_location, default)
+
+ ~source_location() = default;
+
+ unsigned line() const noexcept { return m_line; }
+ unsigned column() const noexcept { return m_col; }
+ pstring file_name() const noexcept { return m_file; }
+ pstring function_name() const noexcept { return m_func; }
+
+ source_location &operator ++() noexcept
+ {
+ ++m_line;
+ return *this;
+ }
+
+ private:
+ pstring m_file;
+ pstring m_func;
+ unsigned m_line;
+ unsigned m_col;
+ };
+
+ /// \brief Base source class.
+ ///
+ /// Pure virtual class all other source implementations are based on.
+ /// Sources provide an abstraction to read input from a variety of
+ /// sources, e.g. files, memory, remote locations.
+ ///
+ class psource_t
+ {
+ public:
+
+ psource_t() noexcept = default;
+
+ PCOPYASSIGNMOVE(psource_t, delete)
+
+ virtual ~psource_t() noexcept = default;
+
+ virtual istream_uptr stream(const pstring &name) = 0;
+ private:
+ };
+
+ /// \brief Generic string source.
+ ///
+ /// Will return the given string when name matches.
+ /// Is used in preprocessor code to eliminate inclusion of certain files.
+ ///
+ class psource_str_t : public psource_t
+ {
+ public:
+ psource_str_t(pstring name, pstring str)
+ : m_name(std::move(name)), m_str(std::move(str))
+ {}
+
+ PCOPYASSIGNMOVE(psource_str_t, delete)
+ ~psource_str_t() noexcept override = default;
+
+ istream_uptr stream(const pstring &name) override
+ {
+ if (name == m_name)
+ return istream_uptr(std::make_unique<std::stringstream>(putf8string(m_str)), name);
+
+ return istream_uptr();
+ }
+ private:
+ pstring m_name;
+ pstring m_str;
+ };
+
+ /// \brief Generic sources collection.
+ ///
+ class psource_collection_t
+ {
+ public:
+ using source_ptr = std::unique_ptr<psource_t>;
+ using list_t = std::vector<source_ptr>;
+
+ psource_collection_t() noexcept = default;
+
+ PCOPYASSIGNMOVE(psource_collection_t, delete)
+ virtual ~psource_collection_t() noexcept = default;
+
+ template <typename S, typename... Args>
+ void add_source(Args&&... args)
+ {
+ static_assert(std::is_base_of<psource_t, S>::value, "S must inherit from plib::psource_t");
+
+ auto src(std::make_unique<S>(std::forward<Args>(args)...));
+ m_collection.push_back(std::move(src));
+ }
+
+ template <typename S = psource_t>
+ istream_uptr get_stream(pstring name)
+ {
+ for (auto &s : m_collection)
+ {
+ auto *source(dynamic_cast<S *>(s.get()));
+ if (source)
+ {
+ auto strm = source->stream(name);
+ if (!strm.empty())
+ return strm;
+ }
+ }
+ return istream_uptr();
+ }
+
+ template <typename S, typename F>
+ bool for_all(F lambda)
+ {
+ for (auto &s : m_collection)
+ {
+ auto *source(dynamic_cast<S *>(s.get()));
+ if (source)
+ {
+ if (lambda(source))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private:
+ list_t m_collection;
+ };
+
+} // namespace plib
+
+#endif // PSOURCE_H_