1 | #include <string> |
2 | #include <cstring> |
3 | |
4 | template<typename T> struct string_builder_helper; |
5 | |
6 | template <typename A, typename B> struct string_builder { |
7 | typedef string_builder_helper<A> HA; |
8 | typedef string_builder_helper<B> HB; |
9 | operator std::string() const { |
10 | std::string s; |
11 | s.reserve(size()); |
12 | HA::append_to(s, a); |
13 | HB::append_to(s, b); |
14 | return s; |
15 | } |
16 | unsigned int size() const { return HA::size(a) + HB::size(b); } |
17 | |
18 | string_builder(const A &a, const B &b) : a(a), b(b) {} |
19 | const A &a; |
20 | const B &b; |
21 | }; |
22 | |
23 | template<> struct string_builder_helper<std::string> { |
24 | typedef std::string T; |
25 | static unsigned int size(const std::string &s) { return s.size(); } |
26 | static void append_to(std::string &s, const std::string &a) { s+=a; } |
27 | }; |
28 | |
29 | template<> struct string_builder_helper<const char *> { |
30 | typedef const char *T; |
31 | static unsigned int size(const char *s) { return std::strlen(s); } |
32 | static void append_to(std::string &s, const char *a) { s+=a; } |
33 | }; |
34 | |
35 | template<typename A, typename B> struct string_builder_helper<string_builder<A,B>> { |
36 | typedef string_builder<A,B> T; |
37 | static unsigned int size(const T &t) { return t.size(); } |
38 | static void append_to(std::string &s, const T &t) { |
39 | T::HA::append_to(s, t.a); |
40 | T::HB::append_to(s, t.b); |
41 | } |
42 | }; |
43 | |
44 | template<int N> struct string_builder_helper<char[N]> { |
45 | typedef char T[N]; |
46 | static unsigned int size(const char *s) { return N-1; } |
47 | static void append_to(std::string &s, const char *a) { s.append(a, N-1); } |
48 | }; |
49 | |
50 | template<typename A, typename B> |
51 | string_builder<typename string_builder_helper<A>::T, typename string_builder_helper<B>::T> |
52 | operator %(const A &a, const B &b) { |
53 | return {a, b}; |
54 | } |
55 | |
56 | template<typename T> std::string &operator %=(std::string &s, const T &t) { |
57 | typedef string_builder_helper<T> H; |
58 | s.reserve(s.size() + H::size(t)); |
59 | H::append_to(s, t); |
60 | return s; |
61 | } |
62 | |
63 | #include <llvm/ADT/StringRef.h> |
64 | template<> struct string_builder_helper<llvm::StringRef> { |
65 | typedef llvm::StringRef T; |
66 | static unsigned int size(llvm::StringRef s) { return s.size(); } |
67 | static void append_to(std::string &s, llvm::StringRef a) { s+=a; } |
68 | }; |
69 | |