summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-12-09 12:18:56 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2016-12-09 12:18:56 +0000
commit8f9959387b37921a6fb82a7f182ba916dc0dd801 (patch)
treec5a26b90ee80cb82d05edcc5173427138a2f0b29
parentRefactor to avoid hitting the template depth limit so early (diff)
downloadlibadhocutil-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.h123
-rw-r--r--libadhocutil/unittests/testCompileTimeFormatter.cpp4
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);
}