diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-12-09 12:18:56 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-12-09 12:18:56 +0000 |
commit | 8f9959387b37921a6fb82a7f182ba916dc0dd801 (patch) | |
tree | c5a26b90ee80cb82d05edcc5173427138a2f0b29 | |
parent | Refactor to avoid hitting the template depth limit so early (diff) | |
download | libadhocutil-8f9959387b37921a6fb82a7f182ba916dc0dd801.tar.bz2 libadhocutil-8f9959387b37921a6fb82a7f182ba916dc0dd801.tar.xz libadhocutil-8f9959387b37921a6fb82a7f182ba916dc0dd801.zip |
Bit messy and fiddly, but removes the template string length limit of (just under) compile time template-depth
-rw-r--r-- | libadhocutil/compileTimeFormatter.h | 123 | ||||
-rw-r--r-- | libadhocutil/unittests/testCompileTimeFormatter.cpp | 4 |
2 files changed, 103 insertions, 24 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index 39254e0..1e82956 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -3,42 +3,74 @@ #include <boost/static_assert.hpp> namespace AdHoc { - template <char...> struct Buffer { }; + constexpr int WRAP_AT = 120; - template <char stop, char ...> + template <bool, char...> struct Buffer { }; + + template <char stop, int offset, char ...> struct Upto { template<typename stream> - static auto stuff(stream &, const Buffer<> & f) + static auto stuff(stream &, const Buffer<false> & f) { return f; } }; + template <char stop, int offset, char s0, char... sn> + struct Upto<stop, offset, s0, sn...> { + template<typename stream, char... sm> + static auto stuff(stream & s, const Buffer<false, sm...> &) + { + return Upto<stop, offset + 1, sn...>::stuff(s, Buffer<false, sm..., s0>()); + } + }; + template <char stop, int offset, char... sn> + struct Upto<stop, offset, stop, sn...> { + template<typename stream, char... sm> + static auto stuff(stream & s, const Buffer<false, sm...> &) + { + char buf[] = {sm...}; + s.write(buf, sizeof...(sm)); + return Buffer<false, stop, sn...>(); + } + }; + template <char stop, int offset, char... sn> + struct Upto<stop, offset, 0, sn...> { + template<typename stream, char... sm> + static auto stuff(stream & s, const Buffer<false, sm...> &) + { + char buf[] = {sm...}; + s.write(buf, sizeof...(sm)); + return Buffer<false, 0, sn...>(); + } + }; template <char stop, char s0, char... sn> - struct Upto<stop, s0, sn...> { + struct Upto<stop, WRAP_AT, s0, sn...> { template<typename stream, char... sm> - static auto stuff(stream & s, const Buffer<sm...> &) + static auto stuff(stream & s, const Buffer<false, sm...> &) { - return Upto<stop, sn...>::stuff(s, Buffer<sm..., s0>()); + char buf[] = {sm...}; + s.write(buf, sizeof...(sm)); + return Buffer<false, s0, sn...>(); } }; template <char stop, char... sn> - struct Upto<stop, stop, sn...> { + struct Upto<stop, WRAP_AT, stop, sn...> { template<typename stream, char... sm> - static auto stuff(stream & s, const Buffer<sm...> &) + static auto stuff(stream & s, const Buffer<false, sm...> &) { char buf[] = {sm...}; s.write(buf, sizeof...(sm)); - return Buffer<stop, sn...>(); + return Buffer<false, stop, sn...>(); } }; template <char stop, char... sn> - struct Upto<stop, 0, sn...> { + struct Upto<stop, WRAP_AT, 0, sn...> { template<typename stream, char... sm> - static auto stuff(stream & s, const Buffer<sm...> &) + static auto stuff(stream & s, const Buffer<false, sm...> &) { char buf[] = {sm...}; s.write(buf, sizeof...(sm)); - return Buffer<0, sn...>(); + return Buffer<false, 0, sn...>(); } }; @@ -47,10 +79,10 @@ namespace AdHoc { template<typename ... Pn> static void write(stream & s, const Pn & ... pn) { - next(s, Upto<'%', sn...>::stuff(s, Buffer<>()), pn...); + next(s, Upto<'%', 0, sn...>::stuff(s, Buffer<false>()), pn...); } - template<typename ... Pn, char... ssn, template <char...> class Buffer> - static void next(stream & s, const Buffer<ssn...>&, const Pn & ... pn) + template<typename ... Pn, char... ssn, template <bool, char...> class Buffer> + static void next(stream & s, const Buffer<false, ssn...>&, const Pn & ... pn) { StreamWriter<stream, ssn...>::write(s, pn...); } @@ -90,19 +122,66 @@ namespace AdHoc { static int err; }; - template <const char * const & S, int offset, char s0, char ... sn> + template <const char * const & S, int offset, int roffset, char s0, char ... sn> struct Parser { static auto parse() { - return Parser<S, offset + 1, S[offset + 1], sn..., s0>::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 Buffer<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 Buffer<false, ssn...> & b) + { + return b; + } + template<bool more, char...ssn, char...ssm> + static auto join(const Buffer<true, ssn...> &, const Buffer<more, ssm...> &) + { + return Buffer<more, ssn..., ssm...>(); + } + }; + + template <const char * const & S, int offset, char s0, char ... sn> + struct Parser<S, offset, WRAP_AT, s0, sn...> { + static auto parse() + { + return Buffer<true, sn..., s0>(); + } + static auto innerparse() + { + return Buffer<true, sn..., s0>(); } }; template <const char * const & S, int offset, char ... sn> - struct Parser<S, offset, 0, sn...> { + struct Parser<S, offset, WRAP_AT, 0, sn...> { static auto parse() { - return Buffer<sn..., 0>(); + return Buffer<false, sn...>(); + } + static auto innerparse() + { + return Buffer<false, sn...>(); + } + }; + + template <const char * const & S, int offset, int roffset, char ... sn> + struct Parser<S, offset, roffset, 0, sn...> { + static auto parse() + { + return Buffer<false, sn..., 0>(); + } + static auto innerparse() + { + return Buffer<false, sn..., 0>(); } }; @@ -111,11 +190,11 @@ namespace AdHoc { template<typename stream, typename ... Pn> static void write(stream & s, const Pn & ... pn) { - run(Parser<S, 0, *S>::parse(), s, pn...); + run(Parser<S, 0, 0, *S>::parse(), s, pn...); } - template<typename stream, char...ssn, template<char...> class Buffer, typename ... Pn> - static void run(const Buffer<ssn...> &, stream & s, const Pn & ... pn) + template<typename stream, char...ssn, template<bool, char...> class Buffer, typename ... Pn> + static void run(const Buffer<false, ssn...> &, stream & s, const Pn & ... pn) { StreamWriter<stream, ssn...>::write(s, pn...); } diff --git a/libadhocutil/unittests/testCompileTimeFormatter.cpp b/libadhocutil/unittests/testCompileTimeFormatter.cpp index f19ee0a..00f1e6f 100644 --- a/libadhocutil/unittests/testCompileTimeFormatter.cpp +++ b/libadhocutil/unittests/testCompileTimeFormatter.cpp @@ -136,11 +136,11 @@ BOOST_AUTO_TEST_CASE ( customMultiArgRightAlign ) BOOST_REQUIRE_EQUAL(buf3.str(), "value 123.45"); } -extern constexpr const char * formatStringLong = " "; +extern constexpr const char * formatStringLong = " "; BOOST_AUTO_TEST_CASE ( longFormatString ) { std::stringstream buf; Formatter<formatStringLong>::write(buf); - BOOST_REQUIRE_EQUAL(buf.str().length(), 124); + BOOST_REQUIRE_EQUAL(buf.str().length(), 246); } |