diff options
-rw-r--r-- | libadhocutil/compileTimeFormatter.h | 194 |
1 files changed, 48 insertions, 146 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index d55012e..4b268f7 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -34,61 +34,35 @@ namespace AdHoc { return off; } - /// @cond - inline constexpr int WRAP_AT = 120; + template <const char * const &, auto> class Formatter; - namespace FormatterImpl { - template <bool, char...> struct ParserBuffer { }; - template <int, char...> struct Buffer { }; - } - - template <const char * const & S, int start, typename stream, char ... sn> + template<const char * const & S, auto L, auto pos, typename stream, char ...> struct StreamWriter { - template<typename ... Pn> - static void write(stream & s, const Pn & ... pn); - - template<typename ... Pn, int len, char... ssn, template <int, char...> class Buffer> - static void next(stream & s, const Buffer<len, ssn...>&, const Pn & ... pn) - { - StreamWriter<S, start + len, stream, ssn...>::write(s, pn...); - } - }; - - template<const char * const & S, int start, typename stream> - struct StreamWriter<S, start, stream> { - template<typename ... Pn> - static void write(stream &, const Pn & ...) { } }; - template<const char * const & S, int start, typename stream> - struct StreamWriter<S, start, stream, 0> { - template<typename ... Pn> - static void write(stream &, const Pn & ...) { } - }; - - template<const char * const & S, int start, int len, typename stream, char ... sn> + template<const char * const & S, auto L, auto pos, typename stream> struct StreamWriterBase { template<typename ... Pn> - static void next(stream & s, const Pn & ... pn) + static inline void next(stream & s, const Pn & ... pn) { - StreamWriter<S, start + len, stream, sn...>::write(s, pn...); + Formatter<S, L>::template Parser<stream, pos + 1, Pn...>::run(s, pn...); } }; #define StreamWriterT(C...) \ - template<const char * const & S, int start, typename stream, char ... sn> \ - struct StreamWriter<S, start, stream, '%', C, sn...> : \ - public StreamWriterBase<S, start, BOOST_PP_VARIADIC_SIZE(C) + 1, stream, sn...> + template<const char * const & S, auto L, auto pos, typename stream, char ... sn> \ + struct StreamWriter<S, L, pos, stream, '%', C, sn...> : \ + public StreamWriterBase<S, L, BOOST_PP_VARIADIC_SIZE(C) + pos, stream> #define StreamWriterTP(P, C...) \ - template<const char * const & S, int start, typename stream, char P, char ... sn> \ - struct StreamWriter<S, start, stream, '%', C, sn...> : \ - public StreamWriterBase<S, start, BOOST_PP_VARIADIC_SIZE(C) + 1, stream, sn...> + template<const char * const & S, auto L, auto pos, typename stream, char P, char ... sn> \ + struct StreamWriter<S, L, pos, stream, '%', C, sn...> : \ + public StreamWriterBase<S, L, BOOST_PP_VARIADIC_SIZE(C) + pos, stream> // Default stream writer formatter StreamWriterT('?') { template<typename P, typename ... Pn> - static void write(stream & s, const P & p, const Pn & ... pn) + static inline void write(stream & s, const P & p, const Pn & ... pn) { s << p; StreamWriter::next(s, pn...); @@ -98,7 +72,7 @@ namespace AdHoc { // Escaped % stream writer formatter StreamWriterT('%') { template<typename ... Pn> - static void write(stream & s, const Pn & ... pn) + static inline void write(stream & s, const Pn & ... pn) { s << '%'; StreamWriter::next(s, pn...); @@ -106,8 +80,8 @@ namespace AdHoc { }; // Unknown stream writer formatter - template<const char * const & S, int start, typename stream, char ... sn> - struct StreamWriter<S, start, stream, '%', sn...> { + template<const char * const & S, auto L, auto pos, typename stream, char ... sn> + struct StreamWriter<S, L, pos, stream, '%', sn...> { template<typename ... Pn> static void write(stream &, const Pn & ...) { @@ -120,94 +94,10 @@ namespace AdHoc { * Compile time string formatter. * @param S the format string. */ - template <const char * const & S> + template <const char * const & S, auto L = strlen<S>()> class Formatter { private: - template<const char * const &, int, typename, char ...> friend struct StreamWriter; - - template <int start, int offset, char ...> - struct Upto { - template<typename stream> - static auto scan(stream &, const FormatterImpl::Buffer<start> & f) - { - return f; - } - }; - template <int start, int offset, char s0, char... sn> - struct Upto<start, offset, s0, sn...> { - template<typename stream, int len, char... sm> - static auto scan(stream & s, const FormatterImpl::Buffer<len, sm...> &) - { - return Upto<start, offset + 1, sn...>::scan(s, FormatterImpl::Buffer<len, sm..., s0>()); - } - }; - template <int start, char... sn> - struct UptoWrite { - template<typename stream, int len, char... sm> - static auto scan(stream & s, const FormatterImpl::Buffer<len, sm...> &) - { - s.write(S + start, sizeof...(sm)); - return FormatterImpl::Buffer<sizeof...(sm), sn...>(); - } - }; - template <int start, int offset, char... sn> - struct Upto<start, offset, '%', sn...> : public UptoWrite<start, '%', sn...> { }; - template <int start, int offset, char... sn> - struct Upto<start, offset, 0, sn...> : public UptoWrite<start, 0, sn...> { }; - template <int start, char s0, char... sn> - struct Upto<start, WRAP_AT, s0, sn...> : public UptoWrite<start, s0, sn...> { }; - template <int start, char... sn> - struct Upto<start, WRAP_AT, '%', sn...> : public UptoWrite<start, '%', sn...> { }; - template <int start, char... sn> - struct Upto<start, WRAP_AT, 0, sn...> : public UptoWrite<start, 0, sn...> { }; - - template <int offset, int roffset, char s0, char ... sn> - struct Parser { - static auto parse() - { - return append(innerparse()); - } - static auto innerparse() - { - return Parser<offset + 1, roffset + 1, S[offset + 1], sn..., s0>::innerparse(); - } - template<char...ssn> - static auto append(const FormatterImpl::ParserBuffer<true, ssn...> & b) - { - return join(b, Parser<offset + 1 + WRAP_AT, 0, S[offset + 1 + WRAP_AT]>::parse()); - } - template<char...ssn> - static auto append(const FormatterImpl::ParserBuffer<false, ssn...> & b) - { - return b; - } - template<bool more, char...ssn, char...ssm> - static auto join(const FormatterImpl::ParserBuffer<true, ssn...> &, const FormatterImpl::ParserBuffer<more, ssm...> &) - { - return FormatterImpl::ParserBuffer<more, ssn..., ssm...>(); - } - }; - - template <bool more, char ... sn> - struct ParserBase { - static auto parse() - { - return innerparse(); - } - static auto innerparse() - { - return FormatterImpl::ParserBuffer<more, sn...>(); - } - }; - - template <int offset, char s0, char ... sn> - struct Parser<offset, WRAP_AT, s0, sn...> : public ParserBase<true, sn..., s0> { }; - - template <int offset, char ... sn> - struct Parser<offset, WRAP_AT, 0, sn...> : public ParserBase<true, sn..., 0> { }; - - template <int offset, int roffset, char ... sn> - struct Parser<offset, roffset, 0, sn...> : public ParserBase<false, sn..., 0>{ }; + template<const char * const &, auto, auto, typename> friend struct StreamWriterBase; public: /** @@ -216,10 +106,10 @@ namespace AdHoc { * @return the formatted string. */ template<typename ... Pn> - static std::string get(const Pn & ... pn) + static inline std::string get(const Pn & ... pn) { std::stringstream s; - return run(Parser<0, 0, *S>::parse(), s, pn...).str(); + return write(s, pn...).str(); } /** @@ -229,28 +119,40 @@ namespace AdHoc { * @return the stream. */ template<typename stream, typename ... Pn> - static stream & write(stream & s, const Pn & ... pn) + static inline stream & write(stream & s, const Pn & ... pn) { - return run(Parser<0, 0, *S>::parse(), s, pn...); + return Parser<stream, 0, Pn...>::run(s, pn...); } private: - template<typename stream, char...ssn, template<bool, char...> class ParserBuffer, typename ... Pn> - static stream & run(const ParserBuffer<false, ssn...> &, stream & s, const Pn & ... pn) - { - StreamWriter<S, 0, stream, ssn...>::write(s, pn...); - return s; - } + template<typename stream, int pos, typename ... Pn> + struct Parser { + static inline stream & + run(stream & s, const Pn & ... pn) + { + if (pos != L) { + constexpr int ph = strchrnul<S, '%', pos>(); + if constexpr (ph != pos) { + s.write((S + pos), ph - pos); + } + if constexpr (ph != L) { + packAndWrite<ph>(s, pn...); + } + } + return s; + } + template<int ph, int off = 0, char ... Pck> + static inline void packAndWrite(stream & s, const Pn & ... pn) + { + if constexpr (ph + off == L || sizeof...(Pck) == 32) { + StreamWriter<S, L, ph, stream, Pck...>::write(s, pn...); + } + else if constexpr (ph + off < L) { + packAndWrite<ph, off + 1, Pck..., S[ph + off]>(s, pn...); + } + } + }; }; - - /// @cond - template <const char * const & S, int start, typename stream, char ... sn> - template<typename ... Pn> - void StreamWriter<S, start, stream, sn...>::write(stream & s, const Pn & ... pn) - { - next(s, Formatter<S>::template Upto<start, 0, sn...>::scan(s, FormatterImpl::Buffer<0>()), pn...); - } - /// @endcond } #define AdHocFormatterTypedef(name, str, id) \ |