summaryrefslogtreecommitdiff
path: root/libadhocutil/compileTimeFormatter.h
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-12-07 23:23:26 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2016-12-07 23:34:13 +0000
commit7c0d59aab6a2e5a991fc13c73d671d3e6a002272 (patch)
tree0e3ca5f8f296c5779f792352f4459bdb7b505897 /libadhocutil/compileTimeFormatter.h
parentTest exception message formatting (diff)
downloadlibadhocutil-7c0d59aab6a2e5a991fc13c73d671d3e6a002272.tar.bz2
libadhocutil-7c0d59aab6a2e5a991fc13c73d671d3e6a002272.tar.xz
libadhocutil-7c0d59aab6a2e5a991fc13c73d671d3e6a002272.zip
Adds support for the compile time formatter
Diffstat (limited to 'libadhocutil/compileTimeFormatter.h')
-rw-r--r--libadhocutil/compileTimeFormatter.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h
new file mode 100644
index 0000000..aa30e20
--- /dev/null
+++ b/libadhocutil/compileTimeFormatter.h
@@ -0,0 +1,111 @@
+#include <iostream>
+#include <string.h>
+#include <boost/static_assert.hpp>
+
+namespace AdHoc {
+ template <char...> struct Buffer { };
+
+ template <char stop, char ...>
+ struct Upto {
+ template<typename stream>
+ static auto stuff(stream &, const Buffer<> & f)
+ {
+ return f;
+ }
+ };
+ template <char stop, char s0, char... sn>
+ struct Upto<stop, s0, sn...> {
+ template<typename stream, char... sm>
+ static auto stuff(stream & s, const Buffer<sm...> &)
+ {
+ return Upto<stop, sn...>::stuff(s, Buffer<sm..., s0>());
+ }
+ };
+ template <char stop, char... sn>
+ struct Upto<stop, stop, sn...> {
+ template<typename stream, char... sm>
+ static auto stuff(stream & s, const Buffer<sm...> &)
+ {
+ char buf[] = {sm...};
+ s.write(buf, sizeof...(sm));
+ return Buffer<stop, sn...>();
+ }
+ };
+ template <char stop, char... sn>
+ struct Upto<stop, 0, sn...> {
+ template<typename stream, char... sm>
+ static auto stuff(stream & s, const Buffer<sm...> &)
+ {
+ char buf[] = {sm...};
+ s.write(buf, sizeof...(sm));
+ return Buffer<0, sn...>();
+ }
+ };
+
+ template <typename stream, char ... sn>
+ struct StreamWriter {
+ template<typename ... Pn>
+ static void write(stream & s, const Pn & ... pn)
+ {
+ next(s, Upto<'%', sn...>::stuff(s, Buffer<>()), pn...);
+ }
+ template<typename ... Pn, char... ssn, template <char...> class Buffer>
+ static void next(stream & s, const Buffer<ssn...>&, const Pn & ... pn)
+ {
+ StreamWriter<stream, ssn...>::write(s, pn...);
+ }
+ };
+
+ template<typename stream>
+ struct StreamWriter<stream> {
+ template<typename ... Pn>
+ static void write(stream &, const Pn & ...) { }
+ };
+
+ template<typename stream>
+ struct StreamWriter<stream, 0> {
+ template<typename ... Pn>
+ static void write(stream &, const Pn & ...) { }
+ };
+
+ // Default stream writer formatter
+ template<typename stream, char ... sn>
+ struct StreamWriter<stream, '%', '?', sn...> {
+ template<typename P, typename ... Pn>
+ static void write(stream & s, const P & p, const Pn & ... pn)
+ {
+ s << p;
+ StreamWriter<stream, sn...>::write(s, pn...);
+ }
+ };
+
+ // Unknown stream writer formatter
+ template<typename stream, char ... sn>
+ struct StreamWriter<stream, '%', sn...> {
+ template<typename ... Pn>
+ static void write(stream &, const Pn & ...)
+ {
+ BOOST_STATIC_ASSERT_MSG(!&err, "invalid format string/arguments");
+ }
+ static int err;
+ };
+
+ template <const char * const & S, char s0 = *S, int offset = 0, char ... sn>
+ struct Formatter {
+ template<typename stream, typename ... Pn>
+ static void write(stream & s, const Pn & ... pn)
+ {
+ Formatter<S, S[offset], offset + 1, sn..., S[offset]>::write(s, pn...);
+ }
+ };
+
+ template <const char * const & S, int offset, char ... sn>
+ struct Formatter<S, 0, offset, sn...> {
+ template<typename stream, typename ... Pn>
+ static void write(stream & s, const Pn & ... pn)
+ {
+ StreamWriter<stream, sn...>::write(s, pn...);
+ }
+ };
+}
+