diff options
| -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);  } | 
