Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / third_party / abseil-cpp / absl / strings / str_cat.h
1 //
2 // Copyright 2017 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 // -----------------------------------------------------------------------------
17 // File: str_cat.h
18 // -----------------------------------------------------------------------------
19 //
20 // This package contains functions for efficiently concatenating and appending
21 // strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
22 // is actually handled through use of a special AlphaNum type, which was
23 // designed to be used as a parameter type that efficiently manages conversion
24 // to strings and avoids copies in the above operations.
25 //
26 // Any routine accepting either a string or a number may accept `AlphaNum`.
27 // The basic idea is that by accepting a `const AlphaNum &` as an argument
28 // to your function, your callers will automagically convert bools, integers,
29 // and floating point values to strings for you.
30 //
31 // NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported
32 // except for the specific case of function parameters of type `AlphaNum` or
33 // `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
34 // stack variable is not supported.
35 //
36 // Conversion from 8-bit values is not accepted because, if it were, then an
37 // attempt to pass ':' instead of ":" might result in a 58 ending up in your
38 // result.
39 //
40 // Bools convert to "0" or "1". Pointers to types other than `char *` are not
41 // valid inputs. No output is generated for null `char *` pointers.
42 //
43 // Floating point numbers are formatted with six-digit precision, which is
44 // the default for "std::cout <<" or printf "%g" (the same as "%.6g").
45 //
46 // You can convert to hexadecimal output rather than decimal output using the
47 // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
48 // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
49 // a `PadSpec` enum.
50 //
51 // -----------------------------------------------------------------------------
52
53 #ifndef ABSL_STRINGS_STR_CAT_H_
54 #define ABSL_STRINGS_STR_CAT_H_
55
56 #include <array>
57 #include <cstdint>
58 #include <string>
59 #include <type_traits>
60 #include <vector>
61
62 #include "absl/base/port.h"
63 #include "absl/strings/numbers.h"
64 #include "absl/strings/string_view.h"
65
66 namespace absl {
67
68 namespace strings_internal {
69 // AlphaNumBuffer allows a way to pass a string to StrCat without having to do
70 // memory allocation.  It is simply a pair of a fixed-size character array, and
71 // a size.  Please don't use outside of absl, yet.
72 template <size_t max_size>
73 struct AlphaNumBuffer {
74   std::array<char, max_size> data;
75   size_t size;
76 };
77
78 }  // namespace strings_internal
79
80 // Enum that specifies the number of significant digits to return in a `Hex` or
81 // `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
82 // would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
83 // would produce hexadecimal strings such as "    a","    f".
84 enum PadSpec : uint8_t {
85   kNoPad = 1,
86   kZeroPad2,
87   kZeroPad3,
88   kZeroPad4,
89   kZeroPad5,
90   kZeroPad6,
91   kZeroPad7,
92   kZeroPad8,
93   kZeroPad9,
94   kZeroPad10,
95   kZeroPad11,
96   kZeroPad12,
97   kZeroPad13,
98   kZeroPad14,
99   kZeroPad15,
100   kZeroPad16,
101   kZeroPad17,
102   kZeroPad18,
103   kZeroPad19,
104   kZeroPad20,
105
106   kSpacePad2 = kZeroPad2 + 64,
107   kSpacePad3,
108   kSpacePad4,
109   kSpacePad5,
110   kSpacePad6,
111   kSpacePad7,
112   kSpacePad8,
113   kSpacePad9,
114   kSpacePad10,
115   kSpacePad11,
116   kSpacePad12,
117   kSpacePad13,
118   kSpacePad14,
119   kSpacePad15,
120   kSpacePad16,
121   kSpacePad17,
122   kSpacePad18,
123   kSpacePad19,
124   kSpacePad20,
125 };
126
127 // -----------------------------------------------------------------------------
128 // Hex
129 // -----------------------------------------------------------------------------
130 //
131 // `Hex` stores a set of hexadecimal string conversion parameters for use
132 // within `AlphaNum` string conversions.
133 struct Hex {
134   uint64_t value;
135   uint8_t width;
136   char fill;
137
138   template <typename Int>
139   explicit Hex(
140       Int v, PadSpec spec = absl::kNoPad,
141       typename std::enable_if<sizeof(Int) == 1 &&
142                               !std::is_pointer<Int>::value>::type* = nullptr)
143       : Hex(spec, static_cast<uint8_t>(v)) {}
144   template <typename Int>
145   explicit Hex(
146       Int v, PadSpec spec = absl::kNoPad,
147       typename std::enable_if<sizeof(Int) == 2 &&
148                               !std::is_pointer<Int>::value>::type* = nullptr)
149       : Hex(spec, static_cast<uint16_t>(v)) {}
150   template <typename Int>
151   explicit Hex(
152       Int v, PadSpec spec = absl::kNoPad,
153       typename std::enable_if<sizeof(Int) == 4 &&
154                               !std::is_pointer<Int>::value>::type* = nullptr)
155       : Hex(spec, static_cast<uint32_t>(v)) {}
156   template <typename Int>
157   explicit Hex(
158       Int v, PadSpec spec = absl::kNoPad,
159       typename std::enable_if<sizeof(Int) == 8 &&
160                               !std::is_pointer<Int>::value>::type* = nullptr)
161       : Hex(spec, static_cast<uint64_t>(v)) {}
162   template <typename Pointee>
163   explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad)
164       : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
165
166  private:
167   Hex(PadSpec spec, uint64_t v)
168       : value(v),
169         width(spec == absl::kNoPad
170                   ? 1
171                   : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
172                                              : spec - absl::kZeroPad2 + 2),
173         fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
174 };
175
176 // -----------------------------------------------------------------------------
177 // Dec
178 // -----------------------------------------------------------------------------
179 //
180 // `Dec` stores a set of decimal string conversion parameters for use
181 // within `AlphaNum` string conversions.  Dec is slower than the default
182 // integer conversion, so use it only if you need padding.
183 struct Dec {
184   uint64_t value;
185   uint8_t width;
186   char fill;
187   bool neg;
188
189   template <typename Int>
190   explicit Dec(Int v, PadSpec spec = absl::kNoPad,
191                typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
192       : value(v >= 0 ? static_cast<uint64_t>(v)
193                      : uint64_t{0} - static_cast<uint64_t>(v)),
194         width(spec == absl::kNoPad
195                   ? 1
196                   : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
197                                              : spec - absl::kZeroPad2 + 2),
198         fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
199         neg(v < 0) {}
200 };
201
202 // -----------------------------------------------------------------------------
203 // AlphaNum
204 // -----------------------------------------------------------------------------
205 //
206 // The `AlphaNum` class acts as the main parameter type for `StrCat()` and
207 // `StrAppend()`, providing efficient conversion of numeric, boolean, and
208 // hexadecimal values (through the `Hex` type) into strings.
209
210 class AlphaNum {
211  public:
212   // No bool ctor -- bools convert to an integral type.
213   // A bool ctor would also convert incoming pointers (bletch).
214
215   AlphaNum(int x)  // NOLINT(runtime/explicit)
216       : piece_(digits_,
217                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
218   AlphaNum(unsigned int x)  // NOLINT(runtime/explicit)
219       : piece_(digits_,
220                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
221   AlphaNum(long x)  // NOLINT(*)
222       : piece_(digits_,
223                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
224   AlphaNum(unsigned long x)  // NOLINT(*)
225       : piece_(digits_,
226                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
227   AlphaNum(long long x)  // NOLINT(*)
228       : piece_(digits_,
229                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
230   AlphaNum(unsigned long long x)  // NOLINT(*)
231       : piece_(digits_,
232                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
233
234   AlphaNum(float f)  // NOLINT(runtime/explicit)
235       : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
236   AlphaNum(double f)  // NOLINT(runtime/explicit)
237       : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
238
239   AlphaNum(Hex hex);  // NOLINT(runtime/explicit)
240   AlphaNum(Dec dec);  // NOLINT(runtime/explicit)
241
242   template <size_t size>
243   AlphaNum(  // NOLINT(runtime/explicit)
244       const strings_internal::AlphaNumBuffer<size>& buf)
245       : piece_(&buf.data[0], buf.size) {}
246
247   AlphaNum(const char* c_str) : piece_(c_str) {}  // NOLINT(runtime/explicit)
248   AlphaNum(absl::string_view pc) : piece_(pc) {}  // NOLINT(runtime/explicit)
249
250   template <typename Allocator>
251   AlphaNum(  // NOLINT(runtime/explicit)
252       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
253       : piece_(str) {}
254
255   // Use std::string literals ":" instead of character literals ':'.
256   AlphaNum(char c) = delete;  // NOLINT(runtime/explicit)
257
258   AlphaNum(const AlphaNum&) = delete;
259   AlphaNum& operator=(const AlphaNum&) = delete;
260
261   absl::string_view::size_type size() const { return piece_.size(); }
262   const char* data() const { return piece_.data(); }
263   absl::string_view Piece() const { return piece_; }
264
265   // Normal enums are already handled by the integer formatters.
266   // This overload matches only scoped enums.
267   template <typename T,
268             typename = typename std::enable_if<
269                 std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
270   AlphaNum(T e)  // NOLINT(runtime/explicit)
271       : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
272
273   // vector<bool>::reference and const_reference require special help to
274   // convert to `AlphaNum` because it requires two user defined conversions.
275   template <
276       typename T,
277       typename std::enable_if<
278           std::is_class<T>::value &&
279           (std::is_same<T, std::vector<bool>::reference>::value ||
280            std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
281           nullptr>
282   AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {}  // NOLINT(runtime/explicit)
283
284  private:
285   absl::string_view piece_;
286   char digits_[numbers_internal::kFastToBufferSize];
287 };
288
289 // -----------------------------------------------------------------------------
290 // StrCat()
291 // -----------------------------------------------------------------------------
292 //
293 // Merges given strings or numbers, using no delimiter(s).
294 //
295 // `StrCat()` is designed to be the fastest possible way to construct a string
296 // out of a mix of raw C strings, string_views, strings, bool values,
297 // and numeric values.
298 //
299 // Don't use `StrCat()` for user-visible strings. The localization process
300 // works poorly on strings built up out of fragments.
301 //
302 // For clarity and performance, don't use `StrCat()` when appending to a
303 // string. Use `StrAppend()` instead. In particular, avoid using any of these
304 // (anti-)patterns:
305 //
306 //   str.append(StrCat(...))
307 //   str += StrCat(...)
308 //   str = StrCat(str, ...)
309 //
310 // The last case is the worst, with a potential to change a loop
311 // from a linear time operation with O(1) dynamic allocations into a
312 // quadratic time operation with O(n) dynamic allocations.
313 //
314 // See `StrAppend()` below for more information.
315
316 namespace strings_internal {
317
318 // Do not call directly - this is not part of the public API.
319 std::string CatPieces(std::initializer_list<absl::string_view> pieces);
320 void AppendPieces(std::string* dest,
321                   std::initializer_list<absl::string_view> pieces);
322
323 }  // namespace strings_internal
324
325 ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); }
326
327 ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
328   return std::string(a.data(), a.size());
329 }
330
331 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
332 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
333                                         const AlphaNum& c);
334 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
335                                         const AlphaNum& c, const AlphaNum& d);
336
337 // Support 5 or more arguments
338 template <typename... AV>
339 ABSL_MUST_USE_RESULT inline std::string StrCat(
340     const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
341     const AlphaNum& e, const AV&... args) {
342   return strings_internal::CatPieces(
343       {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
344        static_cast<const AlphaNum&>(args).Piece()...});
345 }
346
347 // -----------------------------------------------------------------------------
348 // StrAppend()
349 // -----------------------------------------------------------------------------
350 //
351 // Appends a string or set of strings to an existing string, in a similar
352 // fashion to `StrCat()`.
353 //
354 // WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
355 // a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
356 // not try to check each of its input arguments to be sure that they are not
357 // a subset of the string being appended to. That is, while this will work:
358 //
359 //   std::string s = "foo";
360 //   s += s;
361 //
362 // This output is undefined:
363 //
364 //   std::string s = "foo";
365 //   StrAppend(&s, s);
366 //
367 // This output is undefined as well, since `absl::string_view` does not own its
368 // data:
369 //
370 //   std::string s = "foobar";
371 //   absl::string_view p = s;
372 //   StrAppend(&s, p);
373
374 inline void StrAppend(std::string*) {}
375 void StrAppend(std::string* dest, const AlphaNum& a);
376 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b);
377 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
378                const AlphaNum& c);
379 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
380                const AlphaNum& c, const AlphaNum& d);
381
382 // Support 5 or more arguments
383 template <typename... AV>
384 inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
385                       const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
386                       const AV&... args) {
387   strings_internal::AppendPieces(
388       dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
389              static_cast<const AlphaNum&>(args).Piece()...});
390 }
391
392 // Helper function for the future StrCat default floating-point format, %.6g
393 // This is fast.
394 inline strings_internal::AlphaNumBuffer<
395     numbers_internal::kSixDigitsToBufferSize>
396 SixDigits(double d) {
397   strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
398       result;
399   result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
400   return result;
401 }
402
403 }  // namespace absl
404
405 #endif  // ABSL_STRINGS_STR_CAT_H_