diff options
-rw-r--r-- | libadhocutil/compileTimeFormatter.h | 25 | ||||
-rw-r--r-- | libadhocutil/unittests/testCompileTimeFormatter.cpp | 31 |
2 files changed, 41 insertions, 15 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index e17270a..501e0a7 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -1,6 +1,7 @@ #include <iostream> #include <string.h> #include <boost/static_assert.hpp> +#include <boost/preprocessor/variadic/size.hpp> namespace AdHoc { constexpr int WRAP_AT = 120; @@ -69,25 +70,37 @@ namespace AdHoc { static void write(stream &, const Pn & ...) { } }; + template<const char * const & S, int start, int len, typename stream, char ... sn> + struct StreamWriterBase { + template<typename ... Pn> + static void next(stream & s, const Pn & ... pn) + { + StreamWriter<S, start + len, stream, sn...>::write(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...> + // Default stream writer formatter - template<const char * const & S, int start, typename stream, char ... sn> - struct StreamWriter<S, start, stream, '%', '?', sn...> { + StreamWriterT('?') { template<typename P, typename ... Pn> static void write(stream & s, const P & p, const Pn & ... pn) { s << p; - StreamWriter<S, start + 2, stream, sn...>::write(s, pn...); + StreamWriter::next(s, pn...); } }; // Escaped % stream writer formatter - template<const char * const & S, int start, typename stream, char ... sn> - struct StreamWriter<S, start, stream, '%', '%', sn...> { + StreamWriterT('%') { template<typename ... Pn> static void write(stream & s, const Pn & ... pn) { s << '%'; - StreamWriter<S, start + 2, stream, sn...>::write(s, pn...); + StreamWriter::next(s, pn...); } }; diff --git a/libadhocutil/unittests/testCompileTimeFormatter.cpp b/libadhocutil/unittests/testCompileTimeFormatter.cpp index 2c5bedf..7ecd50e 100644 --- a/libadhocutil/unittests/testCompileTimeFormatter.cpp +++ b/libadhocutil/unittests/testCompileTimeFormatter.cpp @@ -16,6 +16,10 @@ extern constexpr const char * formatEdgeCaseFormatLonely = "%?"; extern constexpr const char * formatStringLiteral = "literal"; extern constexpr const char * formatStringSingle = "single %?."; extern constexpr const char * formatStringMulti = "First %?, then %?."; +extern constexpr const char * formatStringCustom = "custom %()"; +extern constexpr const char * formatStringCustomLong = "custom %(longname)"; +extern constexpr const char * formatStringLong = " "; +extern constexpr const char * formatStringMultiArg = "value%ra"; extern constexpr const char * formatStringEscape1 = "literal %% percentage."; extern constexpr const char * formatStringEscape2 = "literal %%? percentage."; extern constexpr const char * formatStringEscape3 = "literal %%%? percentage."; @@ -23,19 +27,25 @@ extern constexpr const char * formatStringEscape4 = "literal %%%?%% percentage." namespace AdHoc { // Custom stream writer formatter, formats as (bracketed expression) - template<const char * const & S, int start, typename stream, char ... sn> - struct StreamWriter<S, start, stream, '%', '(', ')', sn...> { + StreamWriterT('(', ')') { template<typename P, typename ... Pn> static void write(stream & s, const P & p, const Pn & ... pn) { s << "-( " << p << " )-"; - StreamWriter<S, start + 3, stream, sn...>::write(s, pn...); + StreamWriter::next(s, pn...); + } + }; + StreamWriterT('(', 'l', 'o', 'n', 'g', 'n', 'a', 'm', 'e', ')') { + template<typename P, typename ... Pn> + static void write(stream & s, const P & p, const Pn & ... pn) + { + s << "---( " << p << " )---"; + StreamWriter::next(s, pn...); } }; // Custom stream writer formatter, formats // right-aligned by given width - template<const char * const & S, int start, typename stream, char ... sn> - struct StreamWriter<S, start, stream, '%', 'r', 'a', sn...> { + StreamWriterT('r', 'a') { template<typename P, typename ... Pn> static void write(stream & s, int width, const P & p, const Pn & ... pn) { @@ -43,7 +53,7 @@ namespace AdHoc { buf << p; std::string spaces(width - buf.str().length(), ' '); s << spaces << buf.str(); - StreamWriter<S, start + 3, stream, sn...>::write(s, pn...); + StreamWriter::next(s, pn...); } }; } @@ -135,13 +145,18 @@ BOOST_AUTO_TEST_CASE ( escape4 ) BOOST_REQUIRE_EQUAL(this->str(), "literal %3% percentage."); } -extern constexpr const char * formatStringCustom = "custom %()"; BOOST_AUTO_TEST_CASE ( customBracketted ) { Formatter<formatStringCustom>::write(*this, "expr"); BOOST_REQUIRE_EQUAL(this->str(), "custom -( expr )-"); } +BOOST_AUTO_TEST_CASE ( customLongName ) +{ + Formatter<formatStringCustomLong>::write(*this, "some text here"); + BOOST_REQUIRE_EQUAL(this->str(), "custom ---( some text here )---"); +} + typedef Formatter<formatStringCustom> TestFormat; BOOST_AUTO_TEST_CASE ( typedefFormat ) { @@ -149,7 +164,6 @@ BOOST_AUTO_TEST_CASE ( typedefFormat ) BOOST_REQUIRE_EQUAL(this->str(), "custom -( expr )-"); } -extern constexpr const char * formatStringLong = " "; BOOST_AUTO_TEST_CASE ( longFormatString ) { Formatter<formatStringLong>::write(*this); @@ -158,7 +172,6 @@ BOOST_AUTO_TEST_CASE ( longFormatString ) BOOST_AUTO_TEST_SUITE_END(); -extern constexpr const char * formatStringMultiArg = "value%ra"; BOOST_AUTO_TEST_CASE ( customMultiArgRightAlign ) { std::stringstream buf1, buf2, buf3; |