/root/doris/be/src/gutil/strings/strcat.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2008 and onwards Google, Inc. |
2 | | // |
3 | | // #status: RECOMMENDED |
4 | | // #category: operations on strings |
5 | | // #summary: Merges strings or numbers with no delimiter. |
6 | | // |
7 | | #pragma once |
8 | | |
9 | | #include <string.h> |
10 | | #include <string> |
11 | | #include <utility> |
12 | | |
13 | | using std::string; |
14 | | |
15 | | #include "gutil/integral_types.h" |
16 | | #include "gutil/strings/numbers.h" |
17 | | #include "gutil/strings/stringpiece.h" |
18 | | #include "gutil/stringprintf.h" |
19 | | |
20 | | // The AlphaNum type was designed to be used as the parameter type for StrCat(). |
21 | | // I suppose that any routine accepting either a string or a number could accept |
22 | | // it. The basic idea is that by accepting a "const AlphaNum &" as an argument |
23 | | // to your function, your callers will automagically convert bools, integers, |
24 | | // and floating point values to strings for you. |
25 | | // |
26 | | // Conversion from 8-bit values is not accepted because if it were, then an |
27 | | // attempt to pass ':' instead of ":" might result in a 58 ending up in your |
28 | | // result. |
29 | | // |
30 | | // Bools convert to "0" or "1". |
31 | | // |
32 | | // Floating point values are converted to a string which, if passed to strtod(), |
33 | | // would produce the exact same original double (except in case of NaN; all NaNs |
34 | | // are considered the same value). We try to keep the string short but it's not |
35 | | // guaranteed to be as short as possible. |
36 | | // |
37 | | // This class has implicit constructors. |
38 | | // Style guide exception granted: |
39 | | // http://goto/style-guide-exception-20978288 |
40 | | // |
41 | | struct AlphaNum { |
42 | | StringPiece piece; |
43 | | char digits[kFastToBufferSize]; |
44 | | |
45 | | // No bool ctor -- bools convert to an integral type. |
46 | | // A bool ctor would also convert incoming pointers (bletch). |
47 | | |
48 | | AlphaNum(int32 i32) // NOLINT(runtime/explicit) |
49 | 0 | : piece(digits, FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} |
50 | | AlphaNum(uint32 u32) // NOLINT(runtime/explicit) |
51 | 0 | : piece(digits, FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} |
52 | | AlphaNum(int64 i64) // NOLINT(runtime/explicit) |
53 | 299 | : piece(digits, FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} |
54 | | AlphaNum(uint64 u64) // NOLINT(runtime/explicit) |
55 | 0 | : piece(digits, FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} |
56 | | |
57 | | #if defined(__APPLE__) |
58 | | AlphaNum(size_t size) // NOLINT(runtime/explicit) |
59 | | : piece(digits, FastUInt64ToBufferLeft(size, digits) - &digits[0]) {} |
60 | | #endif |
61 | | |
62 | | AlphaNum(float f) // NOLINT(runtime/explicit) |
63 | 0 | : piece(digits, strlen(FloatToBuffer(f, digits))) {} |
64 | | AlphaNum(double f) // NOLINT(runtime/explicit) |
65 | 0 | : piece(digits, strlen(DoubleToBuffer(f, digits))) {} |
66 | | |
67 | 1 | AlphaNum(const char* c_str) : piece(c_str) {} // NOLINT(runtime/explicit) |
68 | 0 | AlphaNum(StringPiece pc) : piece(std::move(pc)) {} // NOLINT(runtime/explicit) |
69 | 299 | AlphaNum(const string& s) : piece(s) {} // NOLINT(runtime/explicit) |
70 | | |
71 | 1.79k | StringPiece::size_type size() const { return piece.size(); } |
72 | 598 | const char* data() const { return piece.data(); } |
73 | | |
74 | | private: |
75 | | // Use ":" not ':' |
76 | | AlphaNum(char c); // NOLINT(runtime/explicit) |
77 | | }; |
78 | | |
79 | | extern AlphaNum gEmptyAlphaNum; |
80 | | |
81 | | // ---------------------------------------------------------------------- |
82 | | // StrCat() |
83 | | // This merges the given strings or numbers, with no delimiter. This |
84 | | // is designed to be the fastest possible way to construct a string out |
85 | | // of a mix of raw C strings, StringPieces, strings, bool values, |
86 | | // and numeric values. |
87 | | // |
88 | | // Don't use this for user-visible strings. The localization process |
89 | | // works poorly on strings built up out of fragments. |
90 | | // |
91 | | // For clarity and performance, don't use StrCat when appending to a |
92 | | // string. In particular, avoid using any of these (anti-)patterns: |
93 | | // str.append(StrCat(...) |
94 | | // str += StrCat(...) |
95 | | // str = StrCat(str, ...) |
96 | | // where the last is the worse, with the potential to change a loop |
97 | | // from a linear time operation with O(1) dynamic allocations into a |
98 | | // quadratic time operation with O(n) dynamic allocations. StrAppend |
99 | | // is a better choice than any of the above, subject to the restriction |
100 | | // of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may |
101 | | // be a reference into str. |
102 | | // ---------------------------------------------------------------------- |
103 | | |
104 | | string StrCat(const AlphaNum& a); |
105 | | string StrCat(const AlphaNum& a, const AlphaNum& b); |
106 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c); |
107 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d); |
108 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
109 | | const AlphaNum& e); |
110 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
111 | | const AlphaNum& e, const AlphaNum& f); |
112 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
113 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g); |
114 | | string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
115 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h); |
116 | | |
117 | | namespace strings { |
118 | | namespace internal { |
119 | | |
120 | | // Do not call directly - this is not part of the public API. |
121 | | string StrCatNineOrMore(const AlphaNum* a1, ...); |
122 | | |
123 | | } // namespace internal |
124 | | } // namespace strings |
125 | | |
126 | | // Support 9 or more arguments |
127 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
128 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
129 | 0 | const AlphaNum& i) { |
130 | 0 | const AlphaNum* null_alphanum = NULL; |
131 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, null_alphanum); |
132 | 0 | } |
133 | | |
134 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
135 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
136 | 0 | const AlphaNum& i, const AlphaNum& j) { |
137 | 0 | const AlphaNum* null_alphanum = NULL; |
138 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, |
139 | 0 | null_alphanum); |
140 | 0 | } |
141 | | |
142 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
143 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
144 | 0 | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k) { |
145 | 0 | const AlphaNum* null_alphanum = NULL; |
146 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, |
147 | 0 | null_alphanum); |
148 | 0 | } |
149 | | |
150 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
151 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
152 | 0 | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l) { |
153 | 0 | const AlphaNum* null_alphanum = NULL; |
154 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, |
155 | 0 | null_alphanum); |
156 | 0 | } |
157 | | |
158 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
159 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
160 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
161 | 0 | const AlphaNum& m) { |
162 | 0 | const AlphaNum* null_alphanum = NULL; |
163 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
164 | 0 | null_alphanum); |
165 | 0 | } |
166 | | |
167 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
168 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
169 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
170 | 0 | const AlphaNum& m, const AlphaNum& n) { |
171 | 0 | const AlphaNum* null_alphanum = NULL; |
172 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
173 | 0 | &n, null_alphanum); |
174 | 0 | } |
175 | | |
176 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
177 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
178 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
179 | 0 | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o) { |
180 | 0 | const AlphaNum* null_alphanum = NULL; |
181 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
182 | 0 | &n, &o, null_alphanum); |
183 | 0 | } |
184 | | |
185 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
186 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
187 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
188 | 0 | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p) { |
189 | 0 | const AlphaNum* null_alphanum = NULL; |
190 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
191 | 0 | &n, &o, &p, null_alphanum); |
192 | 0 | } |
193 | | |
194 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
195 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
196 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
197 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
198 | 0 | const AlphaNum& q) { |
199 | 0 | const AlphaNum* null_alphanum = NULL; |
200 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
201 | 0 | &n, &o, &p, &q, null_alphanum); |
202 | 0 | } |
203 | | |
204 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
205 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
206 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
207 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
208 | 0 | const AlphaNum& q, const AlphaNum& r) { |
209 | 0 | const AlphaNum* null_alphanum = NULL; |
210 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
211 | 0 | &n, &o, &p, &q, &r, null_alphanum); |
212 | 0 | } |
213 | | |
214 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
215 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
216 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
217 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
218 | 0 | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s) { |
219 | 0 | const AlphaNum* null_alphanum = NULL; |
220 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
221 | 0 | &n, &o, &p, &q, &r, &s, null_alphanum); |
222 | 0 | } |
223 | | |
224 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
225 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
226 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
227 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
228 | 0 | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t) { |
229 | 0 | const AlphaNum* null_alphanum = NULL; |
230 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
231 | 0 | &n, &o, &p, &q, &r, &s, &t, null_alphanum); |
232 | 0 | } |
233 | | |
234 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
235 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
236 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
237 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
238 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
239 | 0 | const AlphaNum& u) { |
240 | 0 | const AlphaNum* null_alphanum = NULL; |
241 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
242 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, null_alphanum); |
243 | 0 | } |
244 | | |
245 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
246 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
247 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
248 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
249 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
250 | 0 | const AlphaNum& u, const AlphaNum& v) { |
251 | 0 | const AlphaNum* null_alphanum = NULL; |
252 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
253 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, &v, null_alphanum); |
254 | 0 | } |
255 | | |
256 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
257 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
258 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
259 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
260 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
261 | 0 | const AlphaNum& u, const AlphaNum& v, const AlphaNum& w) { |
262 | 0 | const AlphaNum* null_alphanum = NULL; |
263 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
264 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, &v, &w, |
265 | 0 | null_alphanum); |
266 | 0 | } |
267 | | |
268 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
269 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
270 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
271 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
272 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
273 | 0 | const AlphaNum& u, const AlphaNum& v, const AlphaNum& w, const AlphaNum& x) { |
274 | 0 | const AlphaNum* null_alphanum = NULL; |
275 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
276 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, &v, &w, &x, |
277 | 0 | null_alphanum); |
278 | 0 | } |
279 | | |
280 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
281 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
282 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
283 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
284 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
285 | | const AlphaNum& u, const AlphaNum& v, const AlphaNum& w, const AlphaNum& x, |
286 | 0 | const AlphaNum& y) { |
287 | 0 | const AlphaNum* null_alphanum = NULL; |
288 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
289 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, &v, &w, &x, &y, |
290 | 0 | null_alphanum); |
291 | 0 | } |
292 | | |
293 | | inline string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, |
294 | | const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h, |
295 | | const AlphaNum& i, const AlphaNum& j, const AlphaNum& k, const AlphaNum& l, |
296 | | const AlphaNum& m, const AlphaNum& n, const AlphaNum& o, const AlphaNum& p, |
297 | | const AlphaNum& q, const AlphaNum& r, const AlphaNum& s, const AlphaNum& t, |
298 | | const AlphaNum& u, const AlphaNum& v, const AlphaNum& w, const AlphaNum& x, |
299 | 0 | const AlphaNum& y, const AlphaNum& z) { |
300 | 0 | const AlphaNum* null_alphanum = NULL; |
301 | 0 | return strings::internal::StrCatNineOrMore(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, |
302 | 0 | &n, &o, &p, &q, &r, &s, &t, &u, &v, &w, &x, &y, &z, |
303 | 0 | null_alphanum); |
304 | 0 | } |
305 | | |
306 | | // ---------------------------------------------------------------------- |
307 | | // StrAppend() |
308 | | // Same as above, but adds the output to the given string. |
309 | | // WARNING: For speed, StrAppend does not try to check each of its input |
310 | | // arguments to be sure that they are not a subset of the string being |
311 | | // appended to. That is, while this will work: |
312 | | // |
313 | | // string s = "foo"; |
314 | | // s += s; |
315 | | // |
316 | | // This will not (necessarily) work: |
317 | | // |
318 | | // string s = "foo"; |
319 | | // StrAppend(&s, s); |
320 | | // |
321 | | // Note: while StrCat supports appending up to 12 arguments, StrAppend |
322 | | // is currently limited to 9. That's rarely an issue except when |
323 | | // automatically transforming StrCat to StrAppend, and can easily be |
324 | | // worked around as consecutive calls to StrAppend are quite efficient. |
325 | | // ---------------------------------------------------------------------- |
326 | | |
327 | | void StrAppend(string* dest, const AlphaNum& a); |
328 | | void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b); |
329 | | void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c); |
330 | | void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, |
331 | | const AlphaNum& d); |
332 | | |
333 | | // Support up to 9 params by using a default empty AlphaNum. |
334 | | void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, |
335 | | const AlphaNum& d, const AlphaNum& e, const AlphaNum& f = gEmptyAlphaNum, |
336 | | const AlphaNum& g = gEmptyAlphaNum, const AlphaNum& h = gEmptyAlphaNum, |
337 | | const AlphaNum& i = gEmptyAlphaNum); |