// license:GPL-2.0+ // copyright-holders:Couriersud /* * pfmtlog.h */ #ifndef PFMT_H_ #define PFMT_H_ #include "pstring.h" #include "ptypes.h" #include namespace plib { P_ENUM(plog_level, DEBUG, INFO, VERBOSE, WARNING, ERROR, FATAL) template struct ptype_traits_base { static const T cast(const T &x) { return x; } static const bool is_signed = std::numeric_limits::is_signed; static const char *size_spec() { return ""; } static char32_t fmt_spec() { return 'u'; } }; template <> struct ptype_traits_base { static unsigned int cast(bool &x) { return static_cast(x); } static unsigned int cast(const bool &x) { return static_cast(x); } static const bool is_signed = std::numeric_limits::is_signed; static const char *size_spec() { return ""; } static char32_t fmt_spec() { return 'u'; } }; template struct ptype_traits; template<> struct ptype_traits : ptype_traits_base { }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "h"; } static char32_t fmt_spec() { return is_signed ? 'd' : 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "h"; } static char32_t fmt_spec() { return 'd'; } }; template<> struct ptype_traits : ptype_traits_base { static char32_t fmt_spec() { return 'd'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "l"; } static char32_t fmt_spec() { return 'd'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "ll"; } static char32_t fmt_spec() { return 'd'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "h"; } static char32_t fmt_spec() { return 'd'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "h"; } static char32_t fmt_spec() { return 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "h"; } static char32_t fmt_spec() { return 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static char32_t fmt_spec() { return 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "l"; } static char32_t fmt_spec() { return 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *size_spec() { return "ll"; } static char32_t fmt_spec() { return 'u'; } }; template<> struct ptype_traits : ptype_traits_base { static char32_t fmt_spec() { return 'f'; } }; template<> struct ptype_traits : ptype_traits_base { static char32_t fmt_spec() { return 'f'; } }; template<> struct ptype_traits : ptype_traits_base { static const char *cast(const char *x) { return x; } static char32_t fmt_spec() { return 's'; } }; class pfmt { public: explicit pfmt(const pstring &fmt) : m_str(fmt), m_arg(0) { } pfmt(const pfmt &rhs) : m_str(rhs.m_str), m_arg(rhs.m_arg) { } ~pfmt() { } operator pstring() const { return m_str; } pfmt & e(const double &x) {return format_element("", 'e', x); } pfmt & g(const double &x) {return format_element("", 'g', x); } pfmt & e(const float &x) {return format_element("", 'e', static_cast(x)); } pfmt & g(const float &x) {return format_element("", 'g', static_cast(x)); } pfmt &operator ()(const void *x) {return format_element("", 'p', x); } pfmt &operator ()(const pstring &x) {return format_element("", 's', x.c_str() ); } template pfmt &operator ()(const T &x) { return format_element(ptype_traits::size_spec(), ptype_traits::fmt_spec(), ptype_traits::cast(x)); } template pfmt &operator ()(const T *x) { return format_element(ptype_traits::size_spec(), ptype_traits::fmt_spec(), ptype_traits::cast(x)); } template pfmt &x(const T &x) { return format_element(ptype_traits::size_spec(), 'x', x); } template pfmt &o(const T &x) { return format_element(ptype_traits::size_spec(), 'o', x); } protected: pfmt &format_element(const char *l, const unsigned fmt_spec, ...); private: pstring m_str; unsigned m_arg; }; template class pfmt_writer_t : plib::nocopyassignmove { public: explicit pfmt_writer_t() : m_enabled(true) { } /* runtime enable */ template void log(const pstring & fmt, Args&&... args) const { if (build_enabled && enabled && m_enabled) { pfmt pf(fmt); static_cast(this)->vdowrite(xlog(pf, std::forward(args)...)); } } template void operator ()(const pstring &fmt, Args&&... args) const { if (build_enabled && m_enabled) { pfmt pf(fmt); static_cast(this)->vdowrite(xlog(pf, std::forward(args)...)); } } void set_enabled(const bool v) { m_enabled = v; } bool is_enabled() const { return m_enabled; } protected: ~pfmt_writer_t() { } private: pfmt &xlog(pfmt &fmt) const { return fmt; } template pfmt &xlog(pfmt &fmt, X&& x, Args&&... args) const { return xlog(fmt(std::forward(x)), std::forward(args)...); } bool m_enabled; }; template class plog_channel : public pfmt_writer_t, build_enabled> { friend class pfmt_writer_t, build_enabled>; public: explicit plog_channel(T &b) : pfmt_writer_t(), m_base(b) { } ~plog_channel() { } protected: void vdowrite(const pstring &ls) const { m_base.vlog(L, ls); } private: T &m_base; }; template class plog_base { public: explicit plog_base(T &proxy) : debug(proxy), info(proxy), verbose(proxy), warning(proxy), error(proxy), fatal(proxy) {} virtual ~plog_base() {} plog_channel debug; plog_channel info; plog_channel verbose; plog_channel warning; plog_channel error; plog_channel fatal; }; } template plib::pfmt& operator<<(plib::pfmt &p, T&& val) { return p(std::forward(val)); } #endif /* PSTRING_H_ */