diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2018-06-17 14:01:38 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2018-06-17 14:01:38 +0100 | 
| commit | 8d84ec6d1c40ed2769556c3642bd4fa785c1905c (patch) | |
| tree | 8c1eae8c1de465ffccd7fe2786e8d09443bfcad5 | |
| parent | Add template string utils (diff) | |
| download | libadhocutil-8d84ec6d1c40ed2769556c3642bd4fa785c1905c.tar.bz2 libadhocutil-8d84ec6d1c40ed2769556c3642bd4fa785c1905c.tar.xz libadhocutil-8d84ec6d1c40ed2769556c3642bd4fa785c1905c.zip | |
Massively simplified CTF with C++17 constexpr
| -rw-r--r-- | libadhocutil/compileTimeFormatter.h | 194 | 
1 files changed, 48 insertions, 146 deletions
| diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index d55012e..4b268f7 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -34,61 +34,35 @@ namespace AdHoc {  		return off;  	} -	/// @cond -	inline constexpr int WRAP_AT = 120; +	template <const char * const &, auto> class Formatter; -	namespace FormatterImpl { -		template <bool, char...> struct ParserBuffer { }; -		template <int, char...> struct Buffer { }; -	} - -	template <const char * const & S, int start, typename stream, char ... sn> +	template<const char * const & S, auto L, auto pos, typename stream, char ...>  	struct StreamWriter { -		template<typename ... Pn> -		static void write(stream & s, const Pn & ... pn); - -		template<typename ... Pn, int len, char... ssn, template <int, char...> class Buffer> -		static void next(stream & s, const Buffer<len, ssn...>&, const Pn & ... pn) -		{ -			StreamWriter<S, start + len, stream, ssn...>::write(s, pn...); -		} -	}; - -	template<const char * const & S, int start, typename stream> -	struct StreamWriter<S, start, stream> { -		template<typename ... Pn> -		static void write(stream &, const Pn & ...) { }  	}; -	template<const char * const & S, int start, typename stream> -	struct StreamWriter<S, start, stream, 0> { -		template<typename ... Pn> -		static void write(stream &, const Pn & ...) { } -	}; - -	template<const char * const & S, int start, int len, typename stream, char ... sn> +	template<const char * const & S, auto L, auto pos, typename stream>  	struct StreamWriterBase {  		template<typename ... Pn> -		static void next(stream & s, const Pn & ... pn) +		static inline void next(stream & s, const Pn & ... pn)  		{ -			StreamWriter<S, start + len, stream, sn...>::write(s, pn...); +			Formatter<S, L>::template Parser<stream, pos + 1, Pn...>::run(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...> +	template<const char * const & S, auto L, auto pos, typename stream, char ... sn> \ +	struct StreamWriter<S, L, pos, stream, '%', C, sn...> : \ +		public StreamWriterBase<S, L, BOOST_PP_VARIADIC_SIZE(C) + pos, stream>  #define StreamWriterTP(P, C...) \ -	template<const char * const & S, int start, typename stream, char P, char ... sn> \ -	struct StreamWriter<S, start, stream, '%', C, sn...> : \ -		public StreamWriterBase<S, start, BOOST_PP_VARIADIC_SIZE(C) + 1, stream, sn...> +	template<const char * const & S, auto L, auto pos, typename stream, char P, char ... sn> \ +	struct StreamWriter<S, L, pos, stream, '%', C, sn...> : \ +		public StreamWriterBase<S, L, BOOST_PP_VARIADIC_SIZE(C) + pos, stream>  	// Default stream writer formatter  	StreamWriterT('?') {  		template<typename P, typename ... Pn> -		static void write(stream & s, const P & p, const Pn & ... pn) +		static inline void write(stream & s, const P & p, const Pn & ... pn)  		{  			s << p;  			StreamWriter::next(s, pn...); @@ -98,7 +72,7 @@ namespace AdHoc {  	// Escaped % stream writer formatter  	StreamWriterT('%') {  		template<typename ... Pn> -		static void write(stream & s, const Pn & ... pn) +		static inline void write(stream & s, const Pn & ... pn)  		{  			s << '%';  			StreamWriter::next(s, pn...); @@ -106,8 +80,8 @@ namespace AdHoc {  	};  	// Unknown stream writer formatter -	template<const char * const & S, int start, typename stream, char ... sn> -	struct StreamWriter<S, start, stream, '%', sn...> { +	template<const char * const & S, auto L, auto pos, typename stream, char ... sn> +	struct StreamWriter<S, L, pos, stream, '%', sn...> {  		template<typename ... Pn>  		static void write(stream &, const Pn & ...)  		{ @@ -120,94 +94,10 @@ namespace AdHoc {  	 * Compile time string formatter.  	 * @param S the format string.  	 */ -	template <const char * const & S> +	template <const char * const & S, auto L = strlen<S>()>  	class Formatter {  		private: -			template<const char * const &, int, typename, char ...> friend struct StreamWriter; - -			template <int start, int offset, char ...> -			struct Upto { -				template<typename stream> -				static auto scan(stream &, const FormatterImpl::Buffer<start> & f) -				{ -					return f; -				} -			}; -			template <int start, int offset, char s0, char... sn> -			struct Upto<start, offset, s0, sn...> { -				template<typename stream, int len, char... sm> -				static auto scan(stream & s, const FormatterImpl::Buffer<len, sm...> &) -				{ -					return Upto<start, offset + 1, sn...>::scan(s, FormatterImpl::Buffer<len, sm..., s0>()); -				} -			}; -			template <int start, char... sn> -			struct UptoWrite { -				template<typename stream, int len, char... sm> -				static auto scan(stream & s, const FormatterImpl::Buffer<len, sm...> &) -				{ -					s.write(S + start, sizeof...(sm)); -					return FormatterImpl::Buffer<sizeof...(sm), sn...>(); -				} -			}; -			template <int start, int offset, char... sn> -			struct Upto<start, offset, '%', sn...> : public UptoWrite<start, '%', sn...> { }; -			template <int start, int offset, char... sn> -			struct Upto<start, offset, 0, sn...> : public UptoWrite<start, 0, sn...> { }; -			template <int start, char s0, char... sn> -			struct Upto<start, WRAP_AT, s0, sn...> : public UptoWrite<start, s0, sn...> { }; -			template <int start, char... sn> -			struct Upto<start, WRAP_AT, '%', sn...> : public UptoWrite<start, '%', sn...> { }; -			template <int start, char... sn> -			struct Upto<start, WRAP_AT, 0, sn...> : public UptoWrite<start, 0, sn...> { }; - -			template <int offset, int roffset, char s0, char ... sn> -			struct Parser { -				static auto parse() -				{ -					return append(innerparse()); -				} -				static auto innerparse() -				{ -					return Parser<offset + 1, roffset + 1, S[offset + 1], sn..., s0>::innerparse(); -				} -				template<char...ssn> -				static auto append(const FormatterImpl::ParserBuffer<true, ssn...> & b) -				{ -					return join(b, Parser<offset + 1 + WRAP_AT, 0, S[offset + 1 + WRAP_AT]>::parse()); -				} -				template<char...ssn> -				static auto append(const FormatterImpl::ParserBuffer<false, ssn...> & b) -				{ -					return b; -				} -				template<bool more, char...ssn, char...ssm> -				static auto join(const FormatterImpl::ParserBuffer<true, ssn...> &, const FormatterImpl::ParserBuffer<more, ssm...> &) -				{ -					return FormatterImpl::ParserBuffer<more, ssn..., ssm...>(); -				} -			}; - -			template <bool more, char ... sn> -			struct ParserBase { -				static auto parse() -				{ -					return innerparse(); -				} -				static auto innerparse() -				{ -					return FormatterImpl::ParserBuffer<more, sn...>(); -				} -			}; - -			template <int offset, char s0, char ... sn> -			struct Parser<offset, WRAP_AT, s0, sn...> : public ParserBase<true, sn..., s0> { }; - -			template <int offset, char ... sn> -			struct Parser<offset, WRAP_AT, 0, sn...> : public ParserBase<true, sn..., 0> { }; - -			template <int offset, int roffset, char ... sn> -			struct Parser<offset, roffset, 0, sn...> : public ParserBase<false, sn..., 0>{ }; +			template<const char * const &, auto, auto, typename> friend struct StreamWriterBase;  		public:  			/** @@ -216,10 +106,10 @@ namespace AdHoc {  			 * @return the formatted string.  			 */  			template<typename ... Pn> -			static std::string get(const Pn & ... pn) +			static inline std::string get(const Pn & ... pn)  			{  				std::stringstream s; -				return run(Parser<0, 0, *S>::parse(), s, pn...).str(); +				return write(s, pn...).str();  			}  			/** @@ -229,28 +119,40 @@ namespace AdHoc {  			 * @return the stream.  			 */  			template<typename stream, typename ... Pn> -			static stream & write(stream & s, const Pn & ... pn) +			static inline stream & write(stream & s, const Pn & ... pn)  			{ -				return run(Parser<0, 0, *S>::parse(), s, pn...); +				return Parser<stream, 0, Pn...>::run(s, pn...);  			}  		private: -			template<typename stream, char...ssn, template<bool, char...> class ParserBuffer, typename ... Pn> -			static stream & run(const ParserBuffer<false, ssn...> &, stream & s, const Pn & ... pn) -			{ -				StreamWriter<S, 0, stream, ssn...>::write(s, pn...); -				return s; -			} +			template<typename stream, int pos, typename ... Pn> +			struct Parser { +				static inline stream & +				run(stream & s, const Pn & ... pn) +				{ +					if (pos != L) { +						constexpr int ph = strchrnul<S, '%', pos>(); +						if constexpr (ph != pos) { +							s.write((S + pos), ph - pos); +						} +						if constexpr (ph != L) { +							packAndWrite<ph>(s, pn...); +						} +					} +					return s; +				} +				template<int ph, int off = 0, char ... Pck> +				static inline void packAndWrite(stream & s, const Pn & ... pn) +				{ +					if constexpr (ph + off == L || sizeof...(Pck) == 32) { +						StreamWriter<S, L, ph, stream, Pck...>::write(s, pn...); +					} +					else if constexpr (ph + off < L) { +						packAndWrite<ph, off + 1, Pck..., S[ph + off]>(s, pn...); +					} +				} +			};  	}; - -	/// @cond -	template <const char * const & S, int start, typename stream, char ... sn> -	template<typename ... Pn> -	void StreamWriter<S, start, stream, sn...>::write(stream & s, const Pn & ... pn) -	{ -		next(s, Formatter<S>::template Upto<start, 0, sn...>::scan(s, FormatterImpl::Buffer<0>()), pn...); -	} -	/// @endcond  }  #define AdHocFormatterTypedef(name, str, id) \ | 
