summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-12-09 17:58:26 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2016-12-09 18:00:25 +0000
commitf411e9b86ebc9c8a5fbae7fc2b51c1f017005f74 (patch)
treed6893fb9444ef9961087cc8b561fff8774932d66
parentTest a formatter can be typedef'ed (diff)
downloadlibadhocutil-f411e9b86ebc9c8a5fbae7fc2b51c1f017005f74.tar.bz2
libadhocutil-f411e9b86ebc9c8a5fbae7fc2b51c1f017005f74.tar.xz
libadhocutil-f411e9b86ebc9c8a5fbae7fc2b51c1f017005f74.zip
Macro helper for easily adding new formatters
-rw-r--r--libadhocutil/compileTimeFormatter.h25
-rw-r--r--libadhocutil/unittests/testCompileTimeFormatter.cpp31
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;