diff options
-rw-r--r-- | libadhocutil/compileTimeFormatter.h | 198 |
1 files changed, 104 insertions, 94 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index 7734f9c..4f980d2 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -7,51 +7,16 @@ namespace AdHoc { /// @cond constexpr int WRAP_AT = 120; - template <int, char...> struct Buffer { }; - - template <const char * const & S, int start, int offset, char ...> - struct Upto { - template<typename stream> - static auto scan(stream &, const Buffer<start> & f) - { - return f; - } - }; - template <const char * const & S, int start, int offset, char s0, char... sn> - struct Upto<S, start, offset, s0, sn...> { - template<typename stream, int len, char... sm> - static auto scan(stream & s, const Buffer<len, sm...> &) - { - return Upto<S, start, offset + 1, sn...>::scan(s, Buffer<len, sm..., s0>()); - } - }; - template <const char * const & S, int start, char... sn> - struct UptoWrite { - template<typename stream, int len, char... sm> - static auto scan(stream & s, const Buffer<len, sm...> &) - { - s.write(S + start, sizeof...(sm)); - return Buffer<sizeof...(sm), sn...>(); - } - }; - template <const char * const & S, int start, int offset, char... sn> - struct Upto<S, start, offset, '%', sn...> : public UptoWrite<S, start, '%', sn...> { }; - template <const char * const & S, int start, int offset, char... sn> - struct Upto<S, start, offset, 0, sn...> : public UptoWrite<S, start, 0, sn...> { }; - template <const char * const & S, int start, char s0, char... sn> - struct Upto<S, start, WRAP_AT, s0, sn...> : public UptoWrite<S, start, s0, sn...> { }; - template <const char * const & S, int start, char... sn> - struct Upto<S, start, WRAP_AT, '%', sn...> : public UptoWrite<S, start, '%', sn...> { }; - template <const char * const & S, int start, char... sn> - struct Upto<S, start, WRAP_AT, 0, sn...> : public UptoWrite<S, start, 0, sn...> { }; + namespace FormatterImpl { + template <bool, char...> struct ParserBuffer { }; + template <int, char...> struct Buffer { }; + } template <const char * const & S, int start, typename stream, char ... sn> struct StreamWriter { template<typename ... Pn> - static void write(stream & s, const Pn & ... pn) - { - next(s, Upto<S, start, 0, sn...>::scan(s, Buffer<0>()), 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) { @@ -121,63 +86,99 @@ namespace AdHoc { static int err; }; - template <bool, char...> struct ParserBuffer { }; - - template <const char * const & S, int offset, int roffset, char s0, char ... sn> - struct Parser { - static auto parse() - { - return append(innerparse()); - } - static auto innerparse() - { - return Parser<S, offset + 1, roffset + 1, S[offset + 1], sn..., s0>::innerparse(); - } - template<char...ssn> - static auto append(const ParserBuffer<true, ssn...> & b) - { - return join(b, Parser<S, offset + 1 + WRAP_AT, 0, S[offset + 1 + WRAP_AT]>::parse()); - } - template<char...ssn> - static auto append(const ParserBuffer<false, ssn...> & b) - { - return b; - } - template<bool more, char...ssn, char...ssm> - static auto join(const ParserBuffer<true, ssn...> &, const ParserBuffer<more, ssm...> &) - { - return ParserBuffer<more, ssn..., ssm...>(); - } - }; - - template <const char * const & S, bool more, char ... sn> - struct ParserBase { - static auto parse() - { - return innerparse(); - } - static auto innerparse() - { - return ParserBuffer<more, sn...>(); - } - }; - - template <const char * const & S, int offset, char s0, char ... sn> - struct Parser<S, offset, WRAP_AT, s0, sn...> : public ParserBase<S, true, sn..., s0> { }; - - template <const char * const & S, int offset, char ... sn> - struct Parser<S, offset, WRAP_AT, 0, sn...> : public ParserBase<S, true, sn..., 0> { }; - - template <const char * const & S, int offset, int roffset, char ... sn> - struct Parser<S, offset, roffset, 0, sn...> : public ParserBase<S, false, sn..., 0>{ }; - /// @endcond - /** * Compile time string formatter. * @param S the format string. */ template <const char * const & 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>{ }; + public: /** * Get a string containing the result of formatting. @@ -188,7 +189,7 @@ namespace AdHoc { static std::string get(const Pn & ... pn) { std::stringstream s; - return run(Parser<S, 0, 0, *S>::parse(), s, pn...).str(); + return run(Parser<0, 0, *S>::parse(), s, pn...).str(); } /** @@ -200,7 +201,7 @@ namespace AdHoc { template<typename stream, typename ... Pn> static stream & write(stream & s, const Pn & ... pn) { - return run(Parser<S, 0, 0, *S>::parse(), s, pn...); + return run(Parser<0, 0, *S>::parse(), s, pn...); } private: @@ -211,6 +212,15 @@ namespace AdHoc { return s; } }; + + /// @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) \ |