1 | #include <cstring> |
2 | #include <string> |
3 | |
4 | template<typename T> |
5 | struct string_builder_helper; |
6 | |
7 | template<typename A, typename B> |
8 | struct string_builder |
9 | { |
10 | typedef string_builder_helper<A> HA; |
11 | typedef string_builder_helper<B> HB; |
12 | operator std::string() const |
13 | { |
14 | std::string s; |
15 | s.reserve(size()); |
16 | HA::append_to(s, a); |
17 | HB::append_to(s, b); |
18 | return s; |
19 | } |
20 | unsigned int size() const |
21 | { |
22 | return HA::size(a) + HB::size(b); |
23 | } |
24 | |
25 | string_builder(const A &a, const B &b) |
26 | : a(a) |
27 | , b(b) |
28 | { |
29 | } |
30 | const A &a; |
31 | const B &b; |
32 | }; |
33 | |
34 | template<> |
35 | struct string_builder_helper<std::string> |
36 | { |
37 | typedef std::string T; |
38 | static unsigned int size(const std::string &s) |
39 | { |
40 | return s.size(); |
41 | } |
42 | static void append_to(std::string &s, const std::string &a) |
43 | { |
44 | s += a; |
45 | } |
46 | }; |
47 | |
48 | template<> |
49 | struct string_builder_helper<const char *> |
50 | { |
51 | typedef const char *T; |
52 | static unsigned int size(const char *s) |
53 | { |
54 | return std::strlen(s: s); |
55 | } |
56 | static void append_to(std::string &s, const char *a) |
57 | { |
58 | s += a; |
59 | } |
60 | }; |
61 | |
62 | template<typename A, typename B> |
63 | struct string_builder_helper<string_builder<A, B>> |
64 | { |
65 | typedef string_builder<A, B> T; |
66 | static unsigned int size(const T &t) |
67 | { |
68 | return t.size(); |
69 | } |
70 | static void append_to(std::string &s, const T &t) |
71 | { |
72 | T::HA::append_to(s, t.a); |
73 | T::HB::append_to(s, t.b); |
74 | } |
75 | }; |
76 | |
77 | template<int N> |
78 | struct string_builder_helper<char[N]> |
79 | { |
80 | typedef char T[N]; |
81 | static unsigned int size(const char *s) |
82 | { |
83 | return N - 1; |
84 | } |
85 | static void append_to(std::string &s, const char *a) |
86 | { |
87 | s.append(s: a, n: N - 1); |
88 | } |
89 | }; |
90 | |
91 | template<typename A, typename B> |
92 | string_builder<typename string_builder_helper<A>::T, typename string_builder_helper<B>::T> |
93 | operator%(const A &a, const B &b) |
94 | { |
95 | return { a, b }; |
96 | } |
97 | |
98 | template<typename T> |
99 | std::string &operator%=(std::string &s, const T &t) |
100 | { |
101 | typedef string_builder_helper<T> H; |
102 | s.reserve(s.size() + H::size(t)); |
103 | H::append_to(s, t); |
104 | return s; |
105 | } |
106 | |
107 | #include <llvm/ADT/StringRef.h> |
108 | template<> |
109 | struct string_builder_helper<llvm::StringRef> |
110 | { |
111 | typedef llvm::StringRef T; |
112 | static unsigned int size(llvm::StringRef s) |
113 | { |
114 | return s.size(); |
115 | } |
116 | static void append_to(std::string &s, llvm::StringRef a) |
117 | { |
118 | s += a; |
119 | } |
120 | }; |
121 | |