diff options
Diffstat (limited to 'src/lib/netlist/plib/pfmtlog.h')
-rw-r--r-- | src/lib/netlist/plib/pfmtlog.h | 693 |
1 files changed, 402 insertions, 291 deletions
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index 531b76fafe7..2e45498c637 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -1,372 +1,483 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * pfmtlog.h - */ -#ifndef PFMT_H_ -#define PFMT_H_ +/// +/// \file pfmtlog.h +/// +#ifndef PFMTLOG_H_ +#define PFMTLOG_H_ + +#include "penum.h" +#include "pgsl.h" +#include "ppmf.h" #include "pstring.h" #include "ptypes.h" -#include "putil.h" #include <limits> #include <locale> #include <sstream> +#define PERRMSGV(name, argument_count, str) \ + struct name : public plib::perrmsg \ + { \ + template<typename... Args> explicit name(Args&&... args) \ + : plib::perrmsg(str, std::forward<Args>(args)...) \ + { static_assert((argument_count) == sizeof...(args), "Argument count mismatch"); } \ + }; + namespace plib { -P_ENUM(plog_level, - DEBUG, - VERBOSE, - INFO, - WARNING, - ERROR, - FATAL) - -template <typename T> -struct ptype_traits_base -{ - static const T cast(const T &x) { return x; } - static const bool is_signed = std::numeric_limits<T>::is_signed; - static char32_t fmt_spec() { return 'u'; } -}; - -template <> -struct ptype_traits_base<bool> -{ - static unsigned int cast(const bool &x) { return static_cast<unsigned int>(x); } - static const bool is_signed = std::numeric_limits<bool>::is_signed; - static char32_t fmt_spec() { return 'u'; } -}; - -template <typename T> -struct ptype_traits; - -template<> -struct ptype_traits<bool> : ptype_traits_base<bool> -{ -}; - -template<> -struct ptype_traits<char> : ptype_traits_base<char> -{ - static char32_t fmt_spec() { return is_signed ? 'd' : 'u'; } -}; - -template<> -struct ptype_traits<short> : ptype_traits_base<short> -{ - static char32_t fmt_spec() { return 'd'; } -}; - -template<> -struct ptype_traits<int> : ptype_traits_base<int> -{ - static char32_t fmt_spec() { return 'd'; } -}; - -template<> -struct ptype_traits<long> : ptype_traits_base<long> -{ - static char32_t fmt_spec() { return 'd'; } -}; - -template<> -struct ptype_traits<long long> : ptype_traits_base<long long> -{ - static char32_t fmt_spec() { return 'd'; } -}; - -template<> -struct ptype_traits<signed char> : ptype_traits_base<signed char> -{ - static char32_t fmt_spec() { return 'd'; } -}; - -template<> -struct ptype_traits<unsigned char> : ptype_traits_base<unsigned char> -{ - static char32_t fmt_spec() { return 'u'; } -}; - -template<> -struct ptype_traits<unsigned short> : ptype_traits_base<unsigned short> -{ - static char32_t fmt_spec() { return 'u'; } -}; - -template<> -struct ptype_traits<unsigned int> : ptype_traits_base<unsigned int> -{ - static char32_t fmt_spec() { return 'u'; } -}; - -template<> -struct ptype_traits<unsigned long> : ptype_traits_base<unsigned long> -{ - static char32_t fmt_spec() { return 'u'; } -}; - -template<> -struct ptype_traits<unsigned long long> : ptype_traits_base<unsigned long long> -{ - static char32_t fmt_spec() { return 'u'; } -}; - -template<> -struct ptype_traits<float> : ptype_traits_base<float> -{ - static char32_t fmt_spec() { return 'f'; } -}; - -template<> -struct ptype_traits<double> : ptype_traits_base<double> -{ - static char32_t fmt_spec() { return 'f'; } -}; - -template<> -struct ptype_traits<char *> : ptype_traits_base<char *> -{ - static const char *cast(const char *x) { return x; } - static char32_t fmt_spec() { return 's'; } -}; - -template<> -struct ptype_traits<std::string> : ptype_traits_base<char *> -{ - static const char *cast(const std::string &x) { return x.c_str(); } - static char32_t fmt_spec() { return 's'; } -}; - -class pfmt -{ -public: - explicit pfmt(const pstring &fmt) - : m_str(fmt), m_locale(std::locale::classic()), m_arg(0) - { - } - explicit pfmt(const std::locale &loc, const pstring &fmt) - : m_str(fmt), m_locale(loc), m_arg(0) - { - } - - COPYASSIGNMOVE(pfmt, default) - - ~pfmt() noexcept = default; - - operator pstring() const { return m_str; } + PENUM(plog_level, + DEBUG, + VERBOSE, + INFO, + WARNING, + ERROR, + FATAL) template <typename T> - typename std::enable_if<std::is_floating_point<T>::value, pfmt &>::type - f(const T &x) {return format_element('f', x); } + struct format_traits_base + { + static constexpr const bool is_signed = std::numeric_limits<T>::is_signed; + static char32_t fmt_spec() { return 'u'; } + static void streamify(std::ostream &s, const T &v) + { + s << v; + } + }; - template <typename T> - typename std::enable_if<std::is_floating_point<T>::value, pfmt &>::type - e(const T &x) {return format_element('e', x); } + #if (PUSE_FLOAT128) + template <> + struct format_traits_base<FLOAT128> + { + // FIXME: need native support at some time + static constexpr const bool is_signed = true; + static char32_t fmt_spec() { return 'f'; } + static void streamify(std::ostream &s, const FLOAT128 &v) + { + s << narrow_cast<long double>(v); + } + }; + #endif template <typename T> - typename std::enable_if<std::is_floating_point<T>::value, pfmt &>::type - g(const T &x) {return format_element('g', x); } - - pfmt &operator ()(const void *x) {return format_element('p', x); } - pfmt &operator ()(const pstring &x) {return format_element('s', x.c_str() ); } + struct format_traits; - template<typename T> - pfmt &operator ()(const T &x) + template<> + struct format_traits<compile_info::int128_type> { - return format_element(ptype_traits<T>::fmt_spec(), ptype_traits<T>::cast(x)); - } + // FIXME: need native support at some time + static constexpr const bool is_signed = true; + static char32_t fmt_spec() { return 'd'; } + template <typename T, typename = std::enable_if_t<plib::is_arithmetic<T>::value>> + static void streamify(std::ostream &s, const T &v) + { + s << narrow_cast<long long>(v); + } + }; - template<typename T> - pfmt &operator ()(const T *x) + template<> + struct format_traits<bool> : format_traits_base<bool> { - return format_element(ptype_traits<T *>::fmt_spec(), ptype_traits<T *>::cast(x)); - } + }; - pfmt &operator ()() + template<> + struct format_traits<char> : format_traits_base<char> { - return *this; - } + static char32_t fmt_spec() { return is_signed ? 'd' : 'u'; } + }; + template<> + struct format_traits<short> : format_traits_base<short> + { + static char32_t fmt_spec() { return 'd'; } + }; - template<typename X, typename Y, typename... Args> - pfmt &operator()(X&& x, Y && y, Args&&... args) + template<> + struct format_traits<int> : format_traits_base<int> { - return ((*this)(std::forward<X>(x)))(std::forward<Y>(y), std::forward<Args>(args)...); - } + static char32_t fmt_spec() { return 'd'; } + }; - template<typename T> - typename std::enable_if<std::is_integral<T>::value, pfmt &>::type - x(const T &x) + template<> + struct format_traits<long> : format_traits_base<long> { - return format_element('x', x); - } + static char32_t fmt_spec() { return 'd'; } + }; - template<typename T> - typename std::enable_if<std::is_integral<T>::value, pfmt &>::type - o(const T &x) + template<> + struct format_traits<long long> : format_traits_base<long long> { - return format_element('o', x); - } + static char32_t fmt_spec() { return 'd'; } + }; - friend std::ostream& operator<<(std::ostream &ostrm, const pfmt &fmt) + template<> + struct format_traits<signed char> : format_traits_base<signed char> { - ostrm << fmt.m_str; - return ostrm; - } + static char32_t fmt_spec() { return 'd'; } + }; -protected: + template<> + struct format_traits<unsigned char> : format_traits_base<unsigned char> + { + static char32_t fmt_spec() { return 'u'; } + }; - struct rtype + template<> + struct format_traits<unsigned short> : format_traits_base<unsigned short> { - rtype() : ret(0), p(0), sl(0), pend(0), width(0) {} - int ret; - pstring::size_type p; - pstring::size_type sl; - char32_t pend; - pstring::size_type width; + static char32_t fmt_spec() { return 'u'; } + }; + template<> + struct format_traits<unsigned int> : format_traits_base<unsigned int> + { + static char32_t fmt_spec() { return 'u'; } }; - rtype setfmt(std::stringstream &strm, char32_t cfmt_spec); - template <typename T> - pfmt &format_element(const char32_t cfmt_spec, T &&val) + template<> + struct format_traits<unsigned long> : format_traits_base<unsigned long> { - rtype ret; + static char32_t fmt_spec() { return 'u'; } + }; - m_arg++; + template<> + struct format_traits<unsigned long long> : format_traits_base<unsigned long long> + { + static char32_t fmt_spec() { return 'u'; } + }; - do { - std::stringstream strm; - strm.imbue(m_locale); - ret = setfmt(strm, cfmt_spec); - if (ret.ret>=0) - { - strm << std::forward<T>(val); - const pstring ps(strm.str()); - pstring pad(""); - if (ret.width > ps.length()) - pad = pstring(ret.width - ps.length(), ' '); + template<> + struct format_traits<float> : format_traits_base<float> + { + static char32_t fmt_spec() { return 'f'; } + }; - m_str = m_str.substr(0, ret.p) + pad + ps + m_str.substr(ret.p + ret.sl); - } - } while (ret.ret == 1); + template<> + struct format_traits<double> : format_traits_base<double> + { + static char32_t fmt_spec() { return 'f'; } + }; - return *this; - } + template<> + struct format_traits<long double> : format_traits_base<long double> + { + static char32_t fmt_spec() { return 'f'; } + }; + #if (PUSE_FLOAT128) + template<> + struct format_traits<FLOAT128> : format_traits_base<FLOAT128> + { + static char32_t fmt_spec() { return 'f'; } + }; + #endif -private: - pstring m_str; - std::locale m_locale; - unsigned m_arg; -}; + template<> + struct format_traits<char *> : format_traits_base<char *> + { + static char32_t fmt_spec() { return 's'; } + }; -template <class T, bool build_enabled = true> -class pfmt_writer_t -{ -public: - explicit pfmt_writer_t() : m_enabled(true) { } + template<> + struct format_traits<const char *> : format_traits_base<const char *> + { + static char32_t fmt_spec() { return 's'; } + }; - COPYASSIGNMOVE(pfmt_writer_t, delete) + template<> + struct format_traits<const char16_t *> : format_traits_base<const char16_t *> + { + static char32_t fmt_spec() { return 's'; } + static void streamify(std::ostream &s, const char16_t *v) + { + const putf16string su16(v); + s << putf8string(su16).c_str(); + } + }; - /* runtime enable */ - template<bool enabled, typename... Args> - void log(const pstring & fmt, Args&&... args) const + template<> + struct format_traits<const char32_t *> : format_traits_base<const char32_t *> { - if (build_enabled && enabled && m_enabled) + static char32_t fmt_spec() { return 's'; } + static void streamify(std::ostream &s, const char32_t *v) { - pfmt pf(fmt); - static_cast<T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); + const putf32string su32(v); + s << putf8string(su32).c_str(); } - } + }; + + template<> + struct format_traits<std::string> : format_traits_base<std::string> + { + static char32_t fmt_spec() { return 's'; } + }; + + template<> + struct format_traits<putf8string> : format_traits_base<putf8string> + { + static char32_t fmt_spec() { return 's'; } + }; - template<typename... Args> - void operator ()(const pstring &fmt, Args&&... args) const + template<> + struct format_traits<putf16string> : format_traits_base<putf16string> { - if (build_enabled && m_enabled) + static char32_t fmt_spec() { return 's'; } + static void streamify(std::ostream &s, const putf16string &v) { - pfmt pf(fmt); - static_cast<const T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); + s << putf8string(v).c_str(); } - } + }; + + template<> + struct format_traits<const void *> : format_traits_base<const void *> + { + static char32_t fmt_spec() { return 'p'; } + }; - void set_enabled(const bool v) + class pfmt { - m_enabled = v; - } + public: + explicit pfmt(const pstring &fmt) + : m_str(fmt), m_locale(std::locale::classic()), m_arg(0) + { + } + explicit pfmt(const std::locale &loc, const pstring &fmt) + : m_str(fmt), m_locale(loc), m_arg(0) + { + } - bool is_enabled() const { return m_enabled; } + PCOPYASSIGNMOVE(pfmt, default) -protected: - ~pfmt_writer_t() noexcept = default; + ~pfmt() noexcept = default; -private: - pfmt &xlog(pfmt &fmt) const { return fmt; } + operator pstring() const { return m_str; } - template<typename X, typename... Args> - pfmt &xlog(pfmt &fmt, X&& x, Args&&... args) const + template <typename T> + std::enable_if_t<plib::is_floating_point<T>::value, pfmt &> + f(const T &x) {return format_element('f', x); } + + template <typename T> + std::enable_if_t<plib::is_floating_point<T>::value, pfmt &> + e(const T &x) {return format_element('e', x); } + + template <typename T> + std::enable_if_t<plib::is_floating_point<T>::value, pfmt &> + g(const T &x) {return format_element('g', x); } + + pfmt &operator ()(const void *x) {return format_element('p', x); } + pfmt &operator ()(const pstring &x) {return format_element('s', x.c_str() ); } + + template<typename T> + pfmt &operator ()(const T &x) + { + return format_element(x); + } + + template<typename T> + pfmt &operator ()(const T *x) + { + return format_element(x); + } + + pfmt &operator ()() + { + return *this; + } + + template<typename X, typename Y, typename... Args> + pfmt &operator()(X&& x, Y && y, Args&&... args) + { + return ((*this)(std::forward<X>(x)))(std::forward<Y>(y), std::forward<Args>(args)...); + } + + template<typename T> + std::enable_if_t<plib::is_integral<T>::value, pfmt &> + x(const T &x) + { + return format_element('x', x); + } + + template<typename T> + std::enable_if_t<plib::is_integral<T>::value, pfmt &> + o(const T &x) + { + return format_element('o', x); + } + + friend std::ostream& operator<<(std::ostream &out_stream, const pfmt &fmt) + { + out_stream << putf8string(fmt.m_str); + return out_stream; + } + + protected: + + struct rtype + { + rtype() : ret(0), p(0), sl(0) {} + int ret; + pstring::size_type p; + pstring::size_type sl; + }; + rtype set_format(std::stringstream &strm, char32_t char_format); + + template <typename T> + pfmt &format_element(T &&v) + { + return format_element(format_traits<typename std::decay<T>::type>::fmt_spec(), std::forward<T>(v)); + } + + template <typename T> + pfmt &format_element(const char32_t char_format, T &&v) + { + rtype ret; + + m_arg++; + + do { + std::stringstream strm; + strm.imbue(m_locale); + ret = set_format(strm, char_format); + if (ret.ret>=0) + { + format_traits<typename std::decay<T>::type>::streamify(strm, std::forward<T>(v)); + const pstring ps(putf8string(strm.str())); + m_str = m_str.substr(0, ret.p) + ps + m_str.substr(ret.p + ret.sl); + } + } while (ret.ret == 1); + + return *this; + } + + + private: + + pstring m_str; + std::locale m_locale; + unsigned m_arg; + }; + + template <class T, bool build_enabled = true> + class pfmt_writer_t { - return xlog(fmt(std::forward<X>(x)), std::forward<Args>(args)...); - } + public: + explicit pfmt_writer_t() : m_enabled(true) { } + + PCOPYASSIGNMOVE(pfmt_writer_t, delete) + + // runtime enable + template<bool enabled, typename... Args> + void log(const pstring & fmt, Args&&... args) const noexcept + { + if (build_enabled && enabled && m_enabled) + { + pfmt pf(fmt); + plib::dynamic_downcast<T &>(*this).upstream_write(log_translate(pf, std::forward<Args>(args)...)); + } + } + + template<typename... Args> + void operator ()(const pstring &fmt, Args&&... args) const noexcept + { + if (build_enabled && m_enabled) + { + pfmt pf(fmt); + static_cast<const T &>(*this).upstream_write(log_translate(pf, std::forward<Args>(args)...)); + } + } + + void set_enabled(const bool v) + { + m_enabled = v; + } + + bool is_enabled() const { return m_enabled; } + + protected: + ~pfmt_writer_t() noexcept = default; - bool m_enabled; + private: + pfmt &log_translate(pfmt &fmt) const { return fmt; } -}; + template<typename X, typename... Args> + pfmt &log_translate(pfmt &fmt, X&& x, Args&&... args) const + { + return log_translate(fmt(std::forward<X>(x)), std::forward<Args>(args)...); + } -template <class T, plog_level::E L, bool build_enabled = true> -class plog_channel : public pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled> -{ - friend class pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled>; -public: - explicit plog_channel(T &b) : pfmt_writer_t<plog_channel, build_enabled>(), m_base(b) { } + bool m_enabled; - COPYASSIGNMOVE(plog_channel, delete) + }; - ~plog_channel() noexcept = default; + using plog_delegate = plib::pmfp<void (plog_level, const pstring &)>; -protected: - void vdowrite(const pstring &ls) const + template <plog_level::E L, bool build_enabled = true> + class plog_channel : public pfmt_writer_t<plog_channel<L, build_enabled>, build_enabled> { - m_base.vlog(L, ls); - } + friend class pfmt_writer_t<plog_channel<L, build_enabled>, build_enabled>; + public: + explicit plog_channel(plog_delegate logger) + : pfmt_writer_t<plog_channel, build_enabled>() + , m_logger(logger) { } + + PCOPYASSIGNMOVE(plog_channel, delete) -private: - T &m_base; -}; + ~plog_channel() noexcept = default; -template<class T, bool debug_enabled> -class plog_base -{ -public: + protected: + void upstream_write(const pstring &ls) const noexcept + { + m_logger(L, ls); + } + + private: + plog_delegate m_logger; + }; - explicit plog_base(T &proxy) - : debug(proxy), - info(proxy), - verbose(proxy), - warning(proxy), - error(proxy), - fatal(proxy) - {} + template<bool debug_enabled> + class plog_base + { + public: + + explicit plog_base(plog_delegate logger) + : debug(logger), + info(logger), + verbose(logger), + warning(logger), + error(logger), + fatal(logger) + {} + + PCOPYASSIGNMOVE(plog_base, delete) + virtual ~plog_base() noexcept = default; + + plog_channel<plog_level::DEBUG, debug_enabled> debug; + plog_channel<plog_level::INFO> info; + plog_channel<plog_level::VERBOSE> verbose; + plog_channel<plog_level::WARNING> warning; + plog_channel<plog_level::ERROR> error; + plog_channel<plog_level::FATAL> fatal; + }; - COPYASSIGNMOVE(plog_base, default) - virtual ~plog_base() noexcept = default; + struct perrmsg + { + template<std::size_t N, typename... Args> + explicit perrmsg(const char (&fmt)[N], Args&&... args) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) + : m_msg(plib::pfmt(fmt)(std::forward<Args>(args)...)) + { } + operator pstring const & () const noexcept { return m_msg; } + const pstring & operator ()() const noexcept { return m_msg; } + private: + pstring m_msg; + }; - plog_channel<T, plog_level::DEBUG, debug_enabled> debug; - plog_channel<T, plog_level::INFO> info; - plog_channel<T, plog_level::VERBOSE> verbose; - plog_channel<T, plog_level::WARNING> warning; - plog_channel<T, plog_level::ERROR> error; - plog_channel<T, plog_level::FATAL> fatal; -}; } // namespace plib template<typename T> plib::pfmt& operator<<(plib::pfmt &p, T&& val) { return p(std::forward<T>(val)); } -#endif /* PSTRING_H_ */ +#endif // PFMT_LOG_H_ |