1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker //
16*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
17*9356374aSAndroid Build Coastguard Worker // File: str_cat.h
18*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
19*9356374aSAndroid Build Coastguard Worker //
20*9356374aSAndroid Build Coastguard Worker // This package contains functions for efficiently concatenating and appending
21*9356374aSAndroid Build Coastguard Worker // strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
22*9356374aSAndroid Build Coastguard Worker // is actually handled through use of a special AlphaNum type, which was
23*9356374aSAndroid Build Coastguard Worker // designed to be used as a parameter type that efficiently manages conversion
24*9356374aSAndroid Build Coastguard Worker // to strings and avoids copies in the above operations.
25*9356374aSAndroid Build Coastguard Worker //
26*9356374aSAndroid Build Coastguard Worker // Any routine accepting either a string or a number may accept `AlphaNum`.
27*9356374aSAndroid Build Coastguard Worker // The basic idea is that by accepting a `const AlphaNum &` as an argument
28*9356374aSAndroid Build Coastguard Worker // to your function, your callers will automagically convert bools, integers,
29*9356374aSAndroid Build Coastguard Worker // and floating point values to strings for you.
30*9356374aSAndroid Build Coastguard Worker //
31*9356374aSAndroid Build Coastguard Worker // NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported
32*9356374aSAndroid Build Coastguard Worker // except for the specific case of function parameters of type `AlphaNum` or
33*9356374aSAndroid Build Coastguard Worker // `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
34*9356374aSAndroid Build Coastguard Worker // stack variable is not supported.
35*9356374aSAndroid Build Coastguard Worker //
36*9356374aSAndroid Build Coastguard Worker // Conversion from 8-bit values is not accepted because, if it were, then an
37*9356374aSAndroid Build Coastguard Worker // attempt to pass ':' instead of ":" might result in a 58 ending up in your
38*9356374aSAndroid Build Coastguard Worker // result.
39*9356374aSAndroid Build Coastguard Worker //
40*9356374aSAndroid Build Coastguard Worker // Bools convert to "0" or "1". Pointers to types other than `char *` are not
41*9356374aSAndroid Build Coastguard Worker // valid inputs. No output is generated for null `char *` pointers.
42*9356374aSAndroid Build Coastguard Worker //
43*9356374aSAndroid Build Coastguard Worker // Floating point numbers are formatted with six-digit precision, which is
44*9356374aSAndroid Build Coastguard Worker // the default for "std::cout <<" or printf "%g" (the same as "%.6g").
45*9356374aSAndroid Build Coastguard Worker //
46*9356374aSAndroid Build Coastguard Worker // You can convert to hexadecimal output rather than decimal output using the
47*9356374aSAndroid Build Coastguard Worker // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
48*9356374aSAndroid Build Coastguard Worker // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
49*9356374aSAndroid Build Coastguard Worker // a `PadSpec` enum.
50*9356374aSAndroid Build Coastguard Worker //
51*9356374aSAndroid Build Coastguard Worker // User-defined types can be formatted with the `AbslStringify()` customization
52*9356374aSAndroid Build Coastguard Worker // point. The API relies on detecting an overload in the user-defined type's
53*9356374aSAndroid Build Coastguard Worker // namespace of a free (non-member) `AbslStringify()` function as a definition
54*9356374aSAndroid Build Coastguard Worker // (typically declared as a friend and implemented in-line.
55*9356374aSAndroid Build Coastguard Worker // with the following signature:
56*9356374aSAndroid Build Coastguard Worker //
57*9356374aSAndroid Build Coastguard Worker // class MyClass { ... };
58*9356374aSAndroid Build Coastguard Worker //
59*9356374aSAndroid Build Coastguard Worker // template <typename Sink>
60*9356374aSAndroid Build Coastguard Worker // void AbslStringify(Sink& sink, const MyClass& value);
61*9356374aSAndroid Build Coastguard Worker //
62*9356374aSAndroid Build Coastguard Worker // An `AbslStringify()` overload for a type should only be declared in the same
63*9356374aSAndroid Build Coastguard Worker // file and namespace as said type.
64*9356374aSAndroid Build Coastguard Worker //
65*9356374aSAndroid Build Coastguard Worker // Note that `AbslStringify()` also supports use with `absl::StrFormat()` and
66*9356374aSAndroid Build Coastguard Worker // `absl::Substitute()`.
67*9356374aSAndroid Build Coastguard Worker //
68*9356374aSAndroid Build Coastguard Worker // Example:
69*9356374aSAndroid Build Coastguard Worker //
70*9356374aSAndroid Build Coastguard Worker // struct Point {
71*9356374aSAndroid Build Coastguard Worker // // To add formatting support to `Point`, we simply need to add a free
72*9356374aSAndroid Build Coastguard Worker // // (non-member) function `AbslStringify()`. This method specifies how
73*9356374aSAndroid Build Coastguard Worker // // Point should be printed when absl::StrCat() is called on it. You can add
74*9356374aSAndroid Build Coastguard Worker // // such a free function using a friend declaration within the body of the
75*9356374aSAndroid Build Coastguard Worker // // class. The sink parameter is a templated type to avoid requiring
76*9356374aSAndroid Build Coastguard Worker // // dependencies.
77*9356374aSAndroid Build Coastguard Worker // template <typename Sink> friend void AbslStringify(Sink&
78*9356374aSAndroid Build Coastguard Worker // sink, const Point& p) {
79*9356374aSAndroid Build Coastguard Worker // absl::Format(&sink, "(%v, %v)", p.x, p.y);
80*9356374aSAndroid Build Coastguard Worker // }
81*9356374aSAndroid Build Coastguard Worker //
82*9356374aSAndroid Build Coastguard Worker // int x;
83*9356374aSAndroid Build Coastguard Worker // int y;
84*9356374aSAndroid Build Coastguard Worker // };
85*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
86*9356374aSAndroid Build Coastguard Worker
87*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_STRINGS_STR_CAT_H_
88*9356374aSAndroid Build Coastguard Worker #define ABSL_STRINGS_STR_CAT_H_
89*9356374aSAndroid Build Coastguard Worker
90*9356374aSAndroid Build Coastguard Worker #include <algorithm>
91*9356374aSAndroid Build Coastguard Worker #include <array>
92*9356374aSAndroid Build Coastguard Worker #include <cassert>
93*9356374aSAndroid Build Coastguard Worker #include <cstddef>
94*9356374aSAndroid Build Coastguard Worker #include <cstdint>
95*9356374aSAndroid Build Coastguard Worker #include <cstring>
96*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
97*9356374aSAndroid Build Coastguard Worker #include <limits>
98*9356374aSAndroid Build Coastguard Worker #include <string>
99*9356374aSAndroid Build Coastguard Worker #include <type_traits>
100*9356374aSAndroid Build Coastguard Worker #include <utility>
101*9356374aSAndroid Build Coastguard Worker #include <vector>
102*9356374aSAndroid Build Coastguard Worker
103*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
104*9356374aSAndroid Build Coastguard Worker #include "absl/base/nullability.h"
105*9356374aSAndroid Build Coastguard Worker #include "absl/base/port.h"
106*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h"
107*9356374aSAndroid Build Coastguard Worker #include "absl/strings/has_absl_stringify.h"
108*9356374aSAndroid Build Coastguard Worker #include "absl/strings/internal/resize_uninitialized.h"
109*9356374aSAndroid Build Coastguard Worker #include "absl/strings/internal/stringify_sink.h"
110*9356374aSAndroid Build Coastguard Worker #include "absl/strings/numbers.h"
111*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
112*9356374aSAndroid Build Coastguard Worker
113*9356374aSAndroid Build Coastguard Worker namespace absl {
114*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
115*9356374aSAndroid Build Coastguard Worker
116*9356374aSAndroid Build Coastguard Worker namespace strings_internal {
117*9356374aSAndroid Build Coastguard Worker // AlphaNumBuffer allows a way to pass a string to StrCat without having to do
118*9356374aSAndroid Build Coastguard Worker // memory allocation. It is simply a pair of a fixed-size character array, and
119*9356374aSAndroid Build Coastguard Worker // a size. Please don't use outside of absl, yet.
120*9356374aSAndroid Build Coastguard Worker template <size_t max_size>
121*9356374aSAndroid Build Coastguard Worker struct AlphaNumBuffer {
122*9356374aSAndroid Build Coastguard Worker std::array<char, max_size> data;
123*9356374aSAndroid Build Coastguard Worker size_t size;
124*9356374aSAndroid Build Coastguard Worker };
125*9356374aSAndroid Build Coastguard Worker
126*9356374aSAndroid Build Coastguard Worker } // namespace strings_internal
127*9356374aSAndroid Build Coastguard Worker
128*9356374aSAndroid Build Coastguard Worker // Enum that specifies the number of significant digits to return in a `Hex` or
129*9356374aSAndroid Build Coastguard Worker // `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
130*9356374aSAndroid Build Coastguard Worker // would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
131*9356374aSAndroid Build Coastguard Worker // would produce hexadecimal strings such as " a"," f".
132*9356374aSAndroid Build Coastguard Worker enum PadSpec : uint8_t {
133*9356374aSAndroid Build Coastguard Worker kNoPad = 1,
134*9356374aSAndroid Build Coastguard Worker kZeroPad2,
135*9356374aSAndroid Build Coastguard Worker kZeroPad3,
136*9356374aSAndroid Build Coastguard Worker kZeroPad4,
137*9356374aSAndroid Build Coastguard Worker kZeroPad5,
138*9356374aSAndroid Build Coastguard Worker kZeroPad6,
139*9356374aSAndroid Build Coastguard Worker kZeroPad7,
140*9356374aSAndroid Build Coastguard Worker kZeroPad8,
141*9356374aSAndroid Build Coastguard Worker kZeroPad9,
142*9356374aSAndroid Build Coastguard Worker kZeroPad10,
143*9356374aSAndroid Build Coastguard Worker kZeroPad11,
144*9356374aSAndroid Build Coastguard Worker kZeroPad12,
145*9356374aSAndroid Build Coastguard Worker kZeroPad13,
146*9356374aSAndroid Build Coastguard Worker kZeroPad14,
147*9356374aSAndroid Build Coastguard Worker kZeroPad15,
148*9356374aSAndroid Build Coastguard Worker kZeroPad16,
149*9356374aSAndroid Build Coastguard Worker kZeroPad17,
150*9356374aSAndroid Build Coastguard Worker kZeroPad18,
151*9356374aSAndroid Build Coastguard Worker kZeroPad19,
152*9356374aSAndroid Build Coastguard Worker kZeroPad20,
153*9356374aSAndroid Build Coastguard Worker
154*9356374aSAndroid Build Coastguard Worker kSpacePad2 = kZeroPad2 + 64,
155*9356374aSAndroid Build Coastguard Worker kSpacePad3,
156*9356374aSAndroid Build Coastguard Worker kSpacePad4,
157*9356374aSAndroid Build Coastguard Worker kSpacePad5,
158*9356374aSAndroid Build Coastguard Worker kSpacePad6,
159*9356374aSAndroid Build Coastguard Worker kSpacePad7,
160*9356374aSAndroid Build Coastguard Worker kSpacePad8,
161*9356374aSAndroid Build Coastguard Worker kSpacePad9,
162*9356374aSAndroid Build Coastguard Worker kSpacePad10,
163*9356374aSAndroid Build Coastguard Worker kSpacePad11,
164*9356374aSAndroid Build Coastguard Worker kSpacePad12,
165*9356374aSAndroid Build Coastguard Worker kSpacePad13,
166*9356374aSAndroid Build Coastguard Worker kSpacePad14,
167*9356374aSAndroid Build Coastguard Worker kSpacePad15,
168*9356374aSAndroid Build Coastguard Worker kSpacePad16,
169*9356374aSAndroid Build Coastguard Worker kSpacePad17,
170*9356374aSAndroid Build Coastguard Worker kSpacePad18,
171*9356374aSAndroid Build Coastguard Worker kSpacePad19,
172*9356374aSAndroid Build Coastguard Worker kSpacePad20,
173*9356374aSAndroid Build Coastguard Worker };
174*9356374aSAndroid Build Coastguard Worker
175*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
176*9356374aSAndroid Build Coastguard Worker // Hex
177*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
178*9356374aSAndroid Build Coastguard Worker //
179*9356374aSAndroid Build Coastguard Worker // `Hex` stores a set of hexadecimal string conversion parameters for use
180*9356374aSAndroid Build Coastguard Worker // within `AlphaNum` string conversions.
181*9356374aSAndroid Build Coastguard Worker struct Hex {
182*9356374aSAndroid Build Coastguard Worker uint64_t value;
183*9356374aSAndroid Build Coastguard Worker uint8_t width;
184*9356374aSAndroid Build Coastguard Worker char fill;
185*9356374aSAndroid Build Coastguard Worker
186*9356374aSAndroid Build Coastguard Worker template <typename Int>
187*9356374aSAndroid Build Coastguard Worker explicit Hex(
188*9356374aSAndroid Build Coastguard Worker Int v, PadSpec spec = absl::kNoPad,
189*9356374aSAndroid Build Coastguard Worker typename std::enable_if<sizeof(Int) == 1 &&
190*9356374aSAndroid Build Coastguard Worker !std::is_pointer<Int>::value>::type* = nullptr)
HexHex191*9356374aSAndroid Build Coastguard Worker : Hex(spec, static_cast<uint8_t>(v)) {}
192*9356374aSAndroid Build Coastguard Worker template <typename Int>
193*9356374aSAndroid Build Coastguard Worker explicit Hex(
194*9356374aSAndroid Build Coastguard Worker Int v, PadSpec spec = absl::kNoPad,
195*9356374aSAndroid Build Coastguard Worker typename std::enable_if<sizeof(Int) == 2 &&
196*9356374aSAndroid Build Coastguard Worker !std::is_pointer<Int>::value>::type* = nullptr)
HexHex197*9356374aSAndroid Build Coastguard Worker : Hex(spec, static_cast<uint16_t>(v)) {}
198*9356374aSAndroid Build Coastguard Worker template <typename Int>
199*9356374aSAndroid Build Coastguard Worker explicit Hex(
200*9356374aSAndroid Build Coastguard Worker Int v, PadSpec spec = absl::kNoPad,
201*9356374aSAndroid Build Coastguard Worker typename std::enable_if<sizeof(Int) == 4 &&
202*9356374aSAndroid Build Coastguard Worker !std::is_pointer<Int>::value>::type* = nullptr)
HexHex203*9356374aSAndroid Build Coastguard Worker : Hex(spec, static_cast<uint32_t>(v)) {}
204*9356374aSAndroid Build Coastguard Worker template <typename Int>
205*9356374aSAndroid Build Coastguard Worker explicit Hex(
206*9356374aSAndroid Build Coastguard Worker Int v, PadSpec spec = absl::kNoPad,
207*9356374aSAndroid Build Coastguard Worker typename std::enable_if<sizeof(Int) == 8 &&
208*9356374aSAndroid Build Coastguard Worker !std::is_pointer<Int>::value>::type* = nullptr)
HexHex209*9356374aSAndroid Build Coastguard Worker : Hex(spec, static_cast<uint64_t>(v)) {}
210*9356374aSAndroid Build Coastguard Worker template <typename Pointee>
211*9356374aSAndroid Build Coastguard Worker explicit Hex(absl::Nullable<Pointee*> v, PadSpec spec = absl::kNoPad)
HexHex212*9356374aSAndroid Build Coastguard Worker : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
213*9356374aSAndroid Build Coastguard Worker
214*9356374aSAndroid Build Coastguard Worker template <typename S>
AbslStringifyHex215*9356374aSAndroid Build Coastguard Worker friend void AbslStringify(S& sink, Hex hex) {
216*9356374aSAndroid Build Coastguard Worker static_assert(
217*9356374aSAndroid Build Coastguard Worker numbers_internal::kFastToBufferSize >= 32,
218*9356374aSAndroid Build Coastguard Worker "This function only works when output buffer >= 32 bytes long");
219*9356374aSAndroid Build Coastguard Worker char buffer[numbers_internal::kFastToBufferSize];
220*9356374aSAndroid Build Coastguard Worker char* const end = &buffer[numbers_internal::kFastToBufferSize];
221*9356374aSAndroid Build Coastguard Worker auto real_width =
222*9356374aSAndroid Build Coastguard Worker absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
223*9356374aSAndroid Build Coastguard Worker if (real_width >= hex.width) {
224*9356374aSAndroid Build Coastguard Worker sink.Append(absl::string_view(end - real_width, real_width));
225*9356374aSAndroid Build Coastguard Worker } else {
226*9356374aSAndroid Build Coastguard Worker // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
227*9356374aSAndroid Build Coastguard Worker // max pad width can be up to 20.
228*9356374aSAndroid Build Coastguard Worker std::memset(end - 32, hex.fill, 16);
229*9356374aSAndroid Build Coastguard Worker // Patch up everything else up to the real_width.
230*9356374aSAndroid Build Coastguard Worker std::memset(end - real_width - 16, hex.fill, 16);
231*9356374aSAndroid Build Coastguard Worker sink.Append(absl::string_view(end - hex.width, hex.width));
232*9356374aSAndroid Build Coastguard Worker }
233*9356374aSAndroid Build Coastguard Worker }
234*9356374aSAndroid Build Coastguard Worker
235*9356374aSAndroid Build Coastguard Worker private:
HexHex236*9356374aSAndroid Build Coastguard Worker Hex(PadSpec spec, uint64_t v)
237*9356374aSAndroid Build Coastguard Worker : value(v),
238*9356374aSAndroid Build Coastguard Worker width(spec == absl::kNoPad
239*9356374aSAndroid Build Coastguard Worker ? 1
240*9356374aSAndroid Build Coastguard Worker : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
241*9356374aSAndroid Build Coastguard Worker : spec - absl::kZeroPad2 + 2),
242*9356374aSAndroid Build Coastguard Worker fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
243*9356374aSAndroid Build Coastguard Worker };
244*9356374aSAndroid Build Coastguard Worker
245*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
246*9356374aSAndroid Build Coastguard Worker // Dec
247*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
248*9356374aSAndroid Build Coastguard Worker //
249*9356374aSAndroid Build Coastguard Worker // `Dec` stores a set of decimal string conversion parameters for use
250*9356374aSAndroid Build Coastguard Worker // within `AlphaNum` string conversions. Dec is slower than the default
251*9356374aSAndroid Build Coastguard Worker // integer conversion, so use it only if you need padding.
252*9356374aSAndroid Build Coastguard Worker struct Dec {
253*9356374aSAndroid Build Coastguard Worker uint64_t value;
254*9356374aSAndroid Build Coastguard Worker uint8_t width;
255*9356374aSAndroid Build Coastguard Worker char fill;
256*9356374aSAndroid Build Coastguard Worker bool neg;
257*9356374aSAndroid Build Coastguard Worker
258*9356374aSAndroid Build Coastguard Worker template <typename Int>
259*9356374aSAndroid Build Coastguard Worker explicit Dec(Int v, PadSpec spec = absl::kNoPad,
260*9356374aSAndroid Build Coastguard Worker typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
261*9356374aSAndroid Build Coastguard Worker : value(v >= 0 ? static_cast<uint64_t>(v)
262*9356374aSAndroid Build Coastguard Worker : uint64_t{0} - static_cast<uint64_t>(v)),
263*9356374aSAndroid Build Coastguard Worker width(spec == absl::kNoPad ? 1
264*9356374aSAndroid Build Coastguard Worker : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
265*9356374aSAndroid Build Coastguard Worker : spec - absl::kZeroPad2 + 2),
266*9356374aSAndroid Build Coastguard Worker fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
267*9356374aSAndroid Build Coastguard Worker neg(v < 0) {}
268*9356374aSAndroid Build Coastguard Worker
269*9356374aSAndroid Build Coastguard Worker template <typename S>
AbslStringifyDec270*9356374aSAndroid Build Coastguard Worker friend void AbslStringify(S& sink, Dec dec) {
271*9356374aSAndroid Build Coastguard Worker assert(dec.width <= numbers_internal::kFastToBufferSize);
272*9356374aSAndroid Build Coastguard Worker char buffer[numbers_internal::kFastToBufferSize];
273*9356374aSAndroid Build Coastguard Worker char* const end = &buffer[numbers_internal::kFastToBufferSize];
274*9356374aSAndroid Build Coastguard Worker char* const minfill = end - dec.width;
275*9356374aSAndroid Build Coastguard Worker char* writer = end;
276*9356374aSAndroid Build Coastguard Worker uint64_t val = dec.value;
277*9356374aSAndroid Build Coastguard Worker while (val > 9) {
278*9356374aSAndroid Build Coastguard Worker *--writer = '0' + (val % 10);
279*9356374aSAndroid Build Coastguard Worker val /= 10;
280*9356374aSAndroid Build Coastguard Worker }
281*9356374aSAndroid Build Coastguard Worker *--writer = '0' + static_cast<char>(val);
282*9356374aSAndroid Build Coastguard Worker if (dec.neg) *--writer = '-';
283*9356374aSAndroid Build Coastguard Worker
284*9356374aSAndroid Build Coastguard Worker ptrdiff_t fillers = writer - minfill;
285*9356374aSAndroid Build Coastguard Worker if (fillers > 0) {
286*9356374aSAndroid Build Coastguard Worker // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
287*9356374aSAndroid Build Coastguard Worker // But...: if the fill character is '0', then it's <+/-><fill><digits>
288*9356374aSAndroid Build Coastguard Worker bool add_sign_again = false;
289*9356374aSAndroid Build Coastguard Worker if (dec.neg && dec.fill == '0') { // If filling with '0',
290*9356374aSAndroid Build Coastguard Worker ++writer; // ignore the sign we just added
291*9356374aSAndroid Build Coastguard Worker add_sign_again = true; // and re-add the sign later.
292*9356374aSAndroid Build Coastguard Worker }
293*9356374aSAndroid Build Coastguard Worker writer -= fillers;
294*9356374aSAndroid Build Coastguard Worker std::fill_n(writer, fillers, dec.fill);
295*9356374aSAndroid Build Coastguard Worker if (add_sign_again) *--writer = '-';
296*9356374aSAndroid Build Coastguard Worker }
297*9356374aSAndroid Build Coastguard Worker
298*9356374aSAndroid Build Coastguard Worker sink.Append(absl::string_view(writer, static_cast<size_t>(end - writer)));
299*9356374aSAndroid Build Coastguard Worker }
300*9356374aSAndroid Build Coastguard Worker };
301*9356374aSAndroid Build Coastguard Worker
302*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
303*9356374aSAndroid Build Coastguard Worker // AlphaNum
304*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
305*9356374aSAndroid Build Coastguard Worker //
306*9356374aSAndroid Build Coastguard Worker // The `AlphaNum` class acts as the main parameter type for `StrCat()` and
307*9356374aSAndroid Build Coastguard Worker // `StrAppend()`, providing efficient conversion of numeric, boolean, decimal,
308*9356374aSAndroid Build Coastguard Worker // and hexadecimal values (through the `Dec` and `Hex` types) into strings.
309*9356374aSAndroid Build Coastguard Worker // `AlphaNum` should only be used as a function parameter. Do not instantiate
310*9356374aSAndroid Build Coastguard Worker // `AlphaNum` directly as a stack variable.
311*9356374aSAndroid Build Coastguard Worker
312*9356374aSAndroid Build Coastguard Worker class AlphaNum {
313*9356374aSAndroid Build Coastguard Worker public:
314*9356374aSAndroid Build Coastguard Worker // No bool ctor -- bools convert to an integral type.
315*9356374aSAndroid Build Coastguard Worker // A bool ctor would also convert incoming pointers (bletch).
316*9356374aSAndroid Build Coastguard Worker
317*9356374aSAndroid Build Coastguard Worker // Prevent brace initialization
318*9356374aSAndroid Build Coastguard Worker template <typename T>
319*9356374aSAndroid Build Coastguard Worker AlphaNum(std::initializer_list<T>) = delete; // NOLINT(runtime/explicit)
320*9356374aSAndroid Build Coastguard Worker
AlphaNum(int x)321*9356374aSAndroid Build Coastguard Worker AlphaNum(int x) // NOLINT(runtime/explicit)
322*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
323*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
324*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
AlphaNum(unsigned int x)325*9356374aSAndroid Build Coastguard Worker AlphaNum(unsigned int x) // NOLINT(runtime/explicit)
326*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
327*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
328*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
AlphaNum(long x)329*9356374aSAndroid Build Coastguard Worker AlphaNum(long x) // NOLINT(*)
330*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
331*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
332*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
AlphaNum(unsigned long x)333*9356374aSAndroid Build Coastguard Worker AlphaNum(unsigned long x) // NOLINT(*)
334*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
335*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
336*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
AlphaNum(long long x)337*9356374aSAndroid Build Coastguard Worker AlphaNum(long long x) // NOLINT(*)
338*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
339*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
340*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
AlphaNum(unsigned long long x)341*9356374aSAndroid Build Coastguard Worker AlphaNum(unsigned long long x) // NOLINT(*)
342*9356374aSAndroid Build Coastguard Worker : piece_(digits_, static_cast<size_t>(
343*9356374aSAndroid Build Coastguard Worker numbers_internal::FastIntToBuffer(x, digits_) -
344*9356374aSAndroid Build Coastguard Worker &digits_[0])) {}
345*9356374aSAndroid Build Coastguard Worker
AlphaNum(float f)346*9356374aSAndroid Build Coastguard Worker AlphaNum(float f) // NOLINT(runtime/explicit)
347*9356374aSAndroid Build Coastguard Worker : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
AlphaNum(double f)348*9356374aSAndroid Build Coastguard Worker AlphaNum(double f) // NOLINT(runtime/explicit)
349*9356374aSAndroid Build Coastguard Worker : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
350*9356374aSAndroid Build Coastguard Worker
351*9356374aSAndroid Build Coastguard Worker template <size_t size>
AlphaNum(const strings_internal::AlphaNumBuffer<size> & buf ABSL_ATTRIBUTE_LIFETIME_BOUND)352*9356374aSAndroid Build Coastguard Worker AlphaNum( // NOLINT(runtime/explicit)
353*9356374aSAndroid Build Coastguard Worker const strings_internal::AlphaNumBuffer<size>& buf
354*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_LIFETIME_BOUND)
355*9356374aSAndroid Build Coastguard Worker : piece_(&buf.data[0], buf.size) {}
356*9356374aSAndroid Build Coastguard Worker
AlphaNum(absl::Nullable<const char * > c_str ABSL_ATTRIBUTE_LIFETIME_BOUND)357*9356374aSAndroid Build Coastguard Worker AlphaNum(absl::Nullable<const char*> c_str // NOLINT(runtime/explicit)
358*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_LIFETIME_BOUND)
359*9356374aSAndroid Build Coastguard Worker : piece_(NullSafeStringView(c_str)) {}
AlphaNum(absl::string_view pc ABSL_ATTRIBUTE_LIFETIME_BOUND)360*9356374aSAndroid Build Coastguard Worker AlphaNum(absl::string_view pc // NOLINT(runtime/explicit)
361*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_LIFETIME_BOUND)
362*9356374aSAndroid Build Coastguard Worker : piece_(pc) {}
363*9356374aSAndroid Build Coastguard Worker
364*9356374aSAndroid Build Coastguard Worker template <typename T, typename = typename std::enable_if<
365*9356374aSAndroid Build Coastguard Worker HasAbslStringify<T>::value>::type>
366*9356374aSAndroid Build Coastguard Worker AlphaNum( // NOLINT(runtime/explicit)
367*9356374aSAndroid Build Coastguard Worker const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND,
368*9356374aSAndroid Build Coastguard Worker strings_internal::StringifySink&& sink ABSL_ATTRIBUTE_LIFETIME_BOUND = {})
piece_(strings_internal::ExtractStringification (sink,v))369*9356374aSAndroid Build Coastguard Worker : piece_(strings_internal::ExtractStringification(sink, v)) {}
370*9356374aSAndroid Build Coastguard Worker
371*9356374aSAndroid Build Coastguard Worker template <typename Allocator>
AlphaNum(const std::basic_string<char,std::char_traits<char>,Allocator> & str ABSL_ATTRIBUTE_LIFETIME_BOUND)372*9356374aSAndroid Build Coastguard Worker AlphaNum( // NOLINT(runtime/explicit)
373*9356374aSAndroid Build Coastguard Worker const std::basic_string<char, std::char_traits<char>, Allocator>& str
374*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_LIFETIME_BOUND)
375*9356374aSAndroid Build Coastguard Worker : piece_(str) {}
376*9356374aSAndroid Build Coastguard Worker
377*9356374aSAndroid Build Coastguard Worker // Use string literals ":" instead of character literals ':'.
378*9356374aSAndroid Build Coastguard Worker AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
379*9356374aSAndroid Build Coastguard Worker
380*9356374aSAndroid Build Coastguard Worker AlphaNum(const AlphaNum&) = delete;
381*9356374aSAndroid Build Coastguard Worker AlphaNum& operator=(const AlphaNum&) = delete;
382*9356374aSAndroid Build Coastguard Worker
size()383*9356374aSAndroid Build Coastguard Worker absl::string_view::size_type size() const { return piece_.size(); }
data()384*9356374aSAndroid Build Coastguard Worker absl::Nullable<const char*> data() const { return piece_.data(); }
Piece()385*9356374aSAndroid Build Coastguard Worker absl::string_view Piece() const { return piece_; }
386*9356374aSAndroid Build Coastguard Worker
387*9356374aSAndroid Build Coastguard Worker // Match unscoped enums. Use integral promotion so that a `char`-backed
388*9356374aSAndroid Build Coastguard Worker // enum becomes a wider integral type AlphaNum will accept.
389*9356374aSAndroid Build Coastguard Worker template <typename T,
390*9356374aSAndroid Build Coastguard Worker typename = typename std::enable_if<
391*9356374aSAndroid Build Coastguard Worker std::is_enum<T>{} && std::is_convertible<T, int>{} &&
392*9356374aSAndroid Build Coastguard Worker !HasAbslStringify<T>::value>::type>
393*9356374aSAndroid Build Coastguard Worker AlphaNum(T e) // NOLINT(runtime/explicit)
394*9356374aSAndroid Build Coastguard Worker : AlphaNum(+e) {}
395*9356374aSAndroid Build Coastguard Worker
396*9356374aSAndroid Build Coastguard Worker // This overload matches scoped enums. We must explicitly cast to the
397*9356374aSAndroid Build Coastguard Worker // underlying type, but use integral promotion for the same reason as above.
398*9356374aSAndroid Build Coastguard Worker template <typename T,
399*9356374aSAndroid Build Coastguard Worker typename std::enable_if<std::is_enum<T>{} &&
400*9356374aSAndroid Build Coastguard Worker !std::is_convertible<T, int>{} &&
401*9356374aSAndroid Build Coastguard Worker !HasAbslStringify<T>::value,
402*9356374aSAndroid Build Coastguard Worker char*>::type = nullptr>
403*9356374aSAndroid Build Coastguard Worker AlphaNum(T e) // NOLINT(runtime/explicit)
404*9356374aSAndroid Build Coastguard Worker : AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {}
405*9356374aSAndroid Build Coastguard Worker
406*9356374aSAndroid Build Coastguard Worker // vector<bool>::reference and const_reference require special help to
407*9356374aSAndroid Build Coastguard Worker // convert to `AlphaNum` because it requires two user defined conversions.
408*9356374aSAndroid Build Coastguard Worker template <
409*9356374aSAndroid Build Coastguard Worker typename T,
410*9356374aSAndroid Build Coastguard Worker typename std::enable_if<
411*9356374aSAndroid Build Coastguard Worker std::is_class<T>::value &&
412*9356374aSAndroid Build Coastguard Worker (std::is_same<T, std::vector<bool>::reference>::value ||
413*9356374aSAndroid Build Coastguard Worker std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
414*9356374aSAndroid Build Coastguard Worker nullptr>
AlphaNum(T e)415*9356374aSAndroid Build Coastguard Worker AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit)
416*9356374aSAndroid Build Coastguard Worker
417*9356374aSAndroid Build Coastguard Worker private:
418*9356374aSAndroid Build Coastguard Worker absl::string_view piece_;
419*9356374aSAndroid Build Coastguard Worker char digits_[numbers_internal::kFastToBufferSize];
420*9356374aSAndroid Build Coastguard Worker };
421*9356374aSAndroid Build Coastguard Worker
422*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
423*9356374aSAndroid Build Coastguard Worker // StrCat()
424*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
425*9356374aSAndroid Build Coastguard Worker //
426*9356374aSAndroid Build Coastguard Worker // Merges given strings or numbers, using no delimiter(s), returning the merged
427*9356374aSAndroid Build Coastguard Worker // result as a string.
428*9356374aSAndroid Build Coastguard Worker //
429*9356374aSAndroid Build Coastguard Worker // `StrCat()` is designed to be the fastest possible way to construct a string
430*9356374aSAndroid Build Coastguard Worker // out of a mix of raw C strings, string_views, strings, bool values,
431*9356374aSAndroid Build Coastguard Worker // and numeric values.
432*9356374aSAndroid Build Coastguard Worker //
433*9356374aSAndroid Build Coastguard Worker // Don't use `StrCat()` for user-visible strings. The localization process
434*9356374aSAndroid Build Coastguard Worker // works poorly on strings built up out of fragments.
435*9356374aSAndroid Build Coastguard Worker //
436*9356374aSAndroid Build Coastguard Worker // For clarity and performance, don't use `StrCat()` when appending to a
437*9356374aSAndroid Build Coastguard Worker // string. Use `StrAppend()` instead. In particular, avoid using any of these
438*9356374aSAndroid Build Coastguard Worker // (anti-)patterns:
439*9356374aSAndroid Build Coastguard Worker //
440*9356374aSAndroid Build Coastguard Worker // str.append(StrCat(...))
441*9356374aSAndroid Build Coastguard Worker // str += StrCat(...)
442*9356374aSAndroid Build Coastguard Worker // str = StrCat(str, ...)
443*9356374aSAndroid Build Coastguard Worker //
444*9356374aSAndroid Build Coastguard Worker // The last case is the worst, with a potential to change a loop
445*9356374aSAndroid Build Coastguard Worker // from a linear time operation with O(1) dynamic allocations into a
446*9356374aSAndroid Build Coastguard Worker // quadratic time operation with O(n) dynamic allocations.
447*9356374aSAndroid Build Coastguard Worker //
448*9356374aSAndroid Build Coastguard Worker // See `StrAppend()` below for more information.
449*9356374aSAndroid Build Coastguard Worker
450*9356374aSAndroid Build Coastguard Worker namespace strings_internal {
451*9356374aSAndroid Build Coastguard Worker
452*9356374aSAndroid Build Coastguard Worker // Do not call directly - this is not part of the public API.
453*9356374aSAndroid Build Coastguard Worker std::string CatPieces(std::initializer_list<absl::string_view> pieces);
454*9356374aSAndroid Build Coastguard Worker void AppendPieces(absl::Nonnull<std::string*> dest,
455*9356374aSAndroid Build Coastguard Worker std::initializer_list<absl::string_view> pieces);
456*9356374aSAndroid Build Coastguard Worker
457*9356374aSAndroid Build Coastguard Worker template <typename Integer>
IntegerToString(Integer i)458*9356374aSAndroid Build Coastguard Worker std::string IntegerToString(Integer i) {
459*9356374aSAndroid Build Coastguard Worker // Any integer (signed/unsigned) up to 64 bits can be formatted into a buffer
460*9356374aSAndroid Build Coastguard Worker // with 22 bytes (including NULL at the end).
461*9356374aSAndroid Build Coastguard Worker constexpr size_t kMaxDigits10 = 22;
462*9356374aSAndroid Build Coastguard Worker std::string result;
463*9356374aSAndroid Build Coastguard Worker strings_internal::STLStringResizeUninitialized(&result, kMaxDigits10);
464*9356374aSAndroid Build Coastguard Worker char* start = &result[0];
465*9356374aSAndroid Build Coastguard Worker // note: this can be optimized to not write last zero.
466*9356374aSAndroid Build Coastguard Worker char* end = numbers_internal::FastIntToBuffer(i, start);
467*9356374aSAndroid Build Coastguard Worker auto size = static_cast<size_t>(end - start);
468*9356374aSAndroid Build Coastguard Worker assert((size < result.size()) &&
469*9356374aSAndroid Build Coastguard Worker "StrCat(Integer) does not fit into kMaxDigits10");
470*9356374aSAndroid Build Coastguard Worker result.erase(size);
471*9356374aSAndroid Build Coastguard Worker return result;
472*9356374aSAndroid Build Coastguard Worker }
473*9356374aSAndroid Build Coastguard Worker template <typename Float>
FloatToString(Float f)474*9356374aSAndroid Build Coastguard Worker std::string FloatToString(Float f) {
475*9356374aSAndroid Build Coastguard Worker std::string result;
476*9356374aSAndroid Build Coastguard Worker strings_internal::STLStringResizeUninitialized(
477*9356374aSAndroid Build Coastguard Worker &result, numbers_internal::kSixDigitsToBufferSize);
478*9356374aSAndroid Build Coastguard Worker char* start = &result[0];
479*9356374aSAndroid Build Coastguard Worker result.erase(numbers_internal::SixDigitsToBuffer(f, start));
480*9356374aSAndroid Build Coastguard Worker return result;
481*9356374aSAndroid Build Coastguard Worker }
482*9356374aSAndroid Build Coastguard Worker
483*9356374aSAndroid Build Coastguard Worker // `SingleArgStrCat` overloads take built-in `int`, `long` and `long long` types
484*9356374aSAndroid Build Coastguard Worker // (signed / unsigned) to avoid ambiguity on the call side. If we used int32_t
485*9356374aSAndroid Build Coastguard Worker // and int64_t, then at least one of the three (`int` / `long` / `long long`)
486*9356374aSAndroid Build Coastguard Worker // would have been ambiguous when passed to `SingleArgStrCat`.
SingleArgStrCat(int x)487*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(int x) { return IntegerToString(x); }
SingleArgStrCat(unsigned int x)488*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(unsigned int x) {
489*9356374aSAndroid Build Coastguard Worker return IntegerToString(x);
490*9356374aSAndroid Build Coastguard Worker }
491*9356374aSAndroid Build Coastguard Worker // NOLINTNEXTLINE
SingleArgStrCat(long x)492*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(long x) { return IntegerToString(x); }
493*9356374aSAndroid Build Coastguard Worker // NOLINTNEXTLINE
SingleArgStrCat(unsigned long x)494*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(unsigned long x) {
495*9356374aSAndroid Build Coastguard Worker return IntegerToString(x);
496*9356374aSAndroid Build Coastguard Worker }
497*9356374aSAndroid Build Coastguard Worker // NOLINTNEXTLINE
SingleArgStrCat(long long x)498*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(long long x) { return IntegerToString(x); }
499*9356374aSAndroid Build Coastguard Worker // NOLINTNEXTLINE
SingleArgStrCat(unsigned long long x)500*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(unsigned long long x) {
501*9356374aSAndroid Build Coastguard Worker return IntegerToString(x);
502*9356374aSAndroid Build Coastguard Worker }
SingleArgStrCat(float x)503*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(float x) { return FloatToString(x); }
SingleArgStrCat(double x)504*9356374aSAndroid Build Coastguard Worker inline std::string SingleArgStrCat(double x) { return FloatToString(x); }
505*9356374aSAndroid Build Coastguard Worker
506*9356374aSAndroid Build Coastguard Worker // As of September 2023, the SingleArgStrCat() optimization is only enabled for
507*9356374aSAndroid Build Coastguard Worker // libc++. The reasons for this are:
508*9356374aSAndroid Build Coastguard Worker // 1) The SSO size for libc++ is 23, while libstdc++ and MSSTL have an SSO size
509*9356374aSAndroid Build Coastguard Worker // of 15. Since IntegerToString unconditionally resizes the string to 22 bytes,
510*9356374aSAndroid Build Coastguard Worker // this causes both libstdc++ and MSSTL to allocate.
511*9356374aSAndroid Build Coastguard Worker // 2) strings_internal::STLStringResizeUninitialized() only has an
512*9356374aSAndroid Build Coastguard Worker // implementation that avoids initialization when using libc++. This isn't as
513*9356374aSAndroid Build Coastguard Worker // relevant as (1), and the cost should be benchmarked if (1) ever changes on
514*9356374aSAndroid Build Coastguard Worker // libstc++ or MSSTL.
515*9356374aSAndroid Build Coastguard Worker #ifdef _LIBCPP_VERSION
516*9356374aSAndroid Build Coastguard Worker #define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE true
517*9356374aSAndroid Build Coastguard Worker #else
518*9356374aSAndroid Build Coastguard Worker #define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE false
519*9356374aSAndroid Build Coastguard Worker #endif
520*9356374aSAndroid Build Coastguard Worker
521*9356374aSAndroid Build Coastguard Worker template <typename T, typename = std::enable_if_t<
522*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE &&
523*9356374aSAndroid Build Coastguard Worker std::is_arithmetic<T>{} && !std::is_same<T, char>{}>>
524*9356374aSAndroid Build Coastguard Worker using EnableIfFastCase = T;
525*9356374aSAndroid Build Coastguard Worker
526*9356374aSAndroid Build Coastguard Worker #undef ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE
527*9356374aSAndroid Build Coastguard Worker
528*9356374aSAndroid Build Coastguard Worker } // namespace strings_internal
529*9356374aSAndroid Build Coastguard Worker
StrCat()530*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); }
531*9356374aSAndroid Build Coastguard Worker
532*9356374aSAndroid Build Coastguard Worker template <typename T>
StrCat(strings_internal::EnableIfFastCase<T> a)533*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string StrCat(
534*9356374aSAndroid Build Coastguard Worker strings_internal::EnableIfFastCase<T> a) {
535*9356374aSAndroid Build Coastguard Worker return strings_internal::SingleArgStrCat(a);
536*9356374aSAndroid Build Coastguard Worker }
StrCat(const AlphaNum & a)537*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
538*9356374aSAndroid Build Coastguard Worker return std::string(a.data(), a.size());
539*9356374aSAndroid Build Coastguard Worker }
540*9356374aSAndroid Build Coastguard Worker
541*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
542*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
543*9356374aSAndroid Build Coastguard Worker const AlphaNum& c);
544*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
545*9356374aSAndroid Build Coastguard Worker const AlphaNum& c, const AlphaNum& d);
546*9356374aSAndroid Build Coastguard Worker
547*9356374aSAndroid Build Coastguard Worker // Support 5 or more arguments
548*9356374aSAndroid Build Coastguard Worker template <typename... AV>
StrCat(const AlphaNum & a,const AlphaNum & b,const AlphaNum & c,const AlphaNum & d,const AlphaNum & e,const AV &...args)549*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string StrCat(
550*9356374aSAndroid Build Coastguard Worker const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
551*9356374aSAndroid Build Coastguard Worker const AlphaNum& e, const AV&... args) {
552*9356374aSAndroid Build Coastguard Worker return strings_internal::CatPieces(
553*9356374aSAndroid Build Coastguard Worker {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
554*9356374aSAndroid Build Coastguard Worker static_cast<const AlphaNum&>(args).Piece()...});
555*9356374aSAndroid Build Coastguard Worker }
556*9356374aSAndroid Build Coastguard Worker
557*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
558*9356374aSAndroid Build Coastguard Worker // StrAppend()
559*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
560*9356374aSAndroid Build Coastguard Worker //
561*9356374aSAndroid Build Coastguard Worker // Appends a string or set of strings to an existing string, in a similar
562*9356374aSAndroid Build Coastguard Worker // fashion to `StrCat()`.
563*9356374aSAndroid Build Coastguard Worker //
564*9356374aSAndroid Build Coastguard Worker // WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
565*9356374aSAndroid Build Coastguard Worker // a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
566*9356374aSAndroid Build Coastguard Worker // not try to check each of its input arguments to be sure that they are not
567*9356374aSAndroid Build Coastguard Worker // a subset of the string being appended to. That is, while this will work:
568*9356374aSAndroid Build Coastguard Worker //
569*9356374aSAndroid Build Coastguard Worker // std::string s = "foo";
570*9356374aSAndroid Build Coastguard Worker // s += s;
571*9356374aSAndroid Build Coastguard Worker //
572*9356374aSAndroid Build Coastguard Worker // This output is undefined:
573*9356374aSAndroid Build Coastguard Worker //
574*9356374aSAndroid Build Coastguard Worker // std::string s = "foo";
575*9356374aSAndroid Build Coastguard Worker // StrAppend(&s, s);
576*9356374aSAndroid Build Coastguard Worker //
577*9356374aSAndroid Build Coastguard Worker // This output is undefined as well, since `absl::string_view` does not own its
578*9356374aSAndroid Build Coastguard Worker // data:
579*9356374aSAndroid Build Coastguard Worker //
580*9356374aSAndroid Build Coastguard Worker // std::string s = "foobar";
581*9356374aSAndroid Build Coastguard Worker // absl::string_view p = s;
582*9356374aSAndroid Build Coastguard Worker // StrAppend(&s, p);
583*9356374aSAndroid Build Coastguard Worker
StrAppend(absl::Nonnull<std::string * >)584*9356374aSAndroid Build Coastguard Worker inline void StrAppend(absl::Nonnull<std::string*>) {}
585*9356374aSAndroid Build Coastguard Worker void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a);
586*9356374aSAndroid Build Coastguard Worker void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
587*9356374aSAndroid Build Coastguard Worker const AlphaNum& b);
588*9356374aSAndroid Build Coastguard Worker void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
589*9356374aSAndroid Build Coastguard Worker const AlphaNum& b, const AlphaNum& c);
590*9356374aSAndroid Build Coastguard Worker void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
591*9356374aSAndroid Build Coastguard Worker const AlphaNum& b, const AlphaNum& c, const AlphaNum& d);
592*9356374aSAndroid Build Coastguard Worker
593*9356374aSAndroid Build Coastguard Worker // Support 5 or more arguments
594*9356374aSAndroid Build Coastguard Worker template <typename... AV>
StrAppend(absl::Nonnull<std::string * > dest,const AlphaNum & a,const AlphaNum & b,const AlphaNum & c,const AlphaNum & d,const AlphaNum & e,const AV &...args)595*9356374aSAndroid Build Coastguard Worker inline void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
596*9356374aSAndroid Build Coastguard Worker const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
597*9356374aSAndroid Build Coastguard Worker const AlphaNum& e, const AV&... args) {
598*9356374aSAndroid Build Coastguard Worker strings_internal::AppendPieces(
599*9356374aSAndroid Build Coastguard Worker dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
600*9356374aSAndroid Build Coastguard Worker static_cast<const AlphaNum&>(args).Piece()...});
601*9356374aSAndroid Build Coastguard Worker }
602*9356374aSAndroid Build Coastguard Worker
603*9356374aSAndroid Build Coastguard Worker // Helper function for the future StrCat default floating-point format, %.6g
604*9356374aSAndroid Build Coastguard Worker // This is fast.
605*9356374aSAndroid Build Coastguard Worker inline strings_internal::AlphaNumBuffer<
606*9356374aSAndroid Build Coastguard Worker numbers_internal::kSixDigitsToBufferSize>
SixDigits(double d)607*9356374aSAndroid Build Coastguard Worker SixDigits(double d) {
608*9356374aSAndroid Build Coastguard Worker strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
609*9356374aSAndroid Build Coastguard Worker result;
610*9356374aSAndroid Build Coastguard Worker result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
611*9356374aSAndroid Build Coastguard Worker return result;
612*9356374aSAndroid Build Coastguard Worker }
613*9356374aSAndroid Build Coastguard Worker
614*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
615*9356374aSAndroid Build Coastguard Worker } // namespace absl
616*9356374aSAndroid Build Coastguard Worker
617*9356374aSAndroid Build Coastguard Worker #endif // ABSL_STRINGS_STR_CAT_H_
618