/src/abseil-cpp/absl/strings/str_format.h
Line  | Count  | Source  | 
1  |  | //  | 
2  |  | // Copyright 2018 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_format.h  | 
18  |  | // -----------------------------------------------------------------------------  | 
19  |  | //  | 
20  |  | // The `str_format` library is a typesafe replacement for the family of  | 
21  |  | // `printf()` string formatting routines within the `<cstdio>` standard library  | 
22  |  | // header. Like the `printf` family, `str_format` uses a "format string" to  | 
23  |  | // perform argument substitutions based on types. See the `FormatSpec` section  | 
24  |  | // below for format string documentation.  | 
25  |  | //  | 
26  |  | // Example:  | 
27  |  | //  | 
28  |  | //   std::string s = absl::StrFormat(  | 
29  |  | //                      "%s %s You have $%d!", "Hello", name, dollars);  | 
30  |  | //  | 
31  |  | // The library consists of the following basic utilities:  | 
32  |  | //  | 
33  |  | //   * `absl::StrFormat()`, a type-safe replacement for `std::sprintf()`, to  | 
34  |  | //     write a format string to a `string` value.  | 
35  |  | //   * `absl::StrAppendFormat()` to append a format string to a `string`  | 
36  |  | //   * `absl::StreamFormat()` to more efficiently write a format string to a  | 
37  |  | //     stream, such as`std::cout`.  | 
38  |  | //   * `absl::PrintF()`, `absl::FPrintF()` and `absl::SNPrintF()` as  | 
39  |  | //     drop-in replacements for `std::printf()`, `std::fprintf()` and  | 
40  |  | //     `std::snprintf()`.  | 
41  |  | //  | 
42  |  | //     Note: An `absl::SPrintF()` drop-in replacement is not supported as it  | 
43  |  | //     is generally unsafe due to buffer overflows. Use `absl::StrFormat` which  | 
44  |  | //     returns the string as output instead of expecting a pre-allocated buffer.  | 
45  |  | //  | 
46  |  | // Additionally, you can provide a format string (and its associated arguments)  | 
47  |  | // using one of the following abstractions:  | 
48  |  | //  | 
49  |  | //   * A `FormatSpec` class template fully encapsulates a format string and its  | 
50  |  | //     type arguments and is usually provided to `str_format` functions as a  | 
51  |  | //     variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>`  | 
52  |  | //     template is evaluated at compile-time, providing type safety.  | 
53  |  | //   * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled  | 
54  |  | //     format string for a specific set of type(s), and which can be passed  | 
55  |  | //     between API boundaries. (The `FormatSpec` type should not be used  | 
56  |  | //     directly except as an argument type for wrapper functions.)  | 
57  |  | //  | 
58  |  | // The `str_format` library provides the ability to output its format strings to  | 
59  |  | // arbitrary sink types:  | 
60  |  | //  | 
61  |  | //   * A generic `Format()` function to write outputs to arbitrary sink types,  | 
62  |  | //     which must implement a `FormatRawSink` interface.  | 
63  |  | //  | 
64  |  | //   * A `FormatUntyped()` function that is similar to `Format()` except it is  | 
65  |  | //     loosely typed. `FormatUntyped()` is not a template and does not perform  | 
66  |  | //     any compile-time checking of the format string; instead, it returns a  | 
67  |  | //     boolean from a runtime check.  | 
68  |  | //  | 
69  |  | // In addition, the `str_format` library provides extension points for  | 
70  |  | // augmenting formatting to new types.  See "StrFormat Extensions" below.  | 
71  |  |  | 
72  |  | #ifndef ABSL_STRINGS_STR_FORMAT_H_  | 
73  |  | #define ABSL_STRINGS_STR_FORMAT_H_  | 
74  |  |  | 
75  |  | #include <cstdint>  | 
76  |  | #include <cstdio>  | 
77  |  | #include <string>  | 
78  |  | #include <type_traits>  | 
79  |  |  | 
80  |  | #include "absl/base/attributes.h"  | 
81  |  | #include "absl/base/config.h"  | 
82  |  | #include "absl/base/nullability.h"  | 
83  |  | #include "absl/strings/internal/str_format/arg.h"  // IWYU pragma: export  | 
84  |  | #include "absl/strings/internal/str_format/bind.h"  // IWYU pragma: export  | 
85  |  | #include "absl/strings/internal/str_format/checker.h"  // IWYU pragma: export  | 
86  |  | #include "absl/strings/internal/str_format/extension.h"  // IWYU pragma: export  | 
87  |  | #include "absl/strings/internal/str_format/parser.h"  // IWYU pragma: export  | 
88  |  | #include "absl/strings/string_view.h"  | 
89  |  | #include "absl/types/span.h"  | 
90  |  |  | 
91  |  | namespace absl { | 
92  |  | ABSL_NAMESPACE_BEGIN  | 
93  |  |  | 
94  |  | // UntypedFormatSpec  | 
95  |  | //  | 
96  |  | // A type-erased class that can be used directly within untyped API entry  | 
97  |  | // points. An `UntypedFormatSpec` is specifically used as an argument to  | 
98  |  | // `FormatUntyped()`.  | 
99  |  | //  | 
100  |  | // Example:  | 
101  |  | //  | 
102  |  | //   absl::UntypedFormatSpec format("%d"); | 
103  |  | //   std::string out;  | 
104  |  | //   CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)})); | 
105  |  | class UntypedFormatSpec { | 
106  |  |  public:  | 
107  |  |   UntypedFormatSpec() = delete;  | 
108  |  |   UntypedFormatSpec(const UntypedFormatSpec&) = delete;  | 
109  |  |   UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;  | 
110  |  |  | 
111  | 4.12M  |   explicit UntypedFormatSpec(string_view s) : spec_(s) {} | 
112  |  |  | 
113  |  |  protected:  | 
114  |  |   explicit UntypedFormatSpec(  | 
115  |  |       const str_format_internal::ParsedFormatBase* absl_nonnull pc)  | 
116  | 0  |       : spec_(pc) {} | 
117  |  |  | 
118  |  |  private:  | 
119  |  |   friend str_format_internal::UntypedFormatSpecImpl;  | 
120  |  |   str_format_internal::UntypedFormatSpecImpl spec_;  | 
121  |  | };  | 
122  |  |  | 
123  |  | // FormatStreamed()  | 
124  |  | //  | 
125  |  | // Takes a streamable argument and returns an object that can print it  | 
126  |  | // with '%s'. Allows printing of types that have an `operator<<` but no  | 
127  |  | // intrinsic type support within `StrFormat()` itself.  | 
128  |  | //  | 
129  |  | // Example:  | 
130  |  | //  | 
131  |  | //   absl::StrFormat("%s", absl::FormatStreamed(obj)); | 
132  |  | template <typename T>  | 
133  |  | str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) { | 
134  |  |   return str_format_internal::StreamedWrapper<T>(v);  | 
135  |  | }  | 
136  |  |  | 
137  |  | // FormatCountCapture  | 
138  |  | //  | 
139  |  | // This class provides a way to safely wrap `StrFormat()` captures of `%n`  | 
140  |  | // conversions, which denote the number of characters written by a formatting  | 
141  |  | // operation to this point, into an integer value.  | 
142  |  | //  | 
143  |  | // This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in  | 
144  |  | // the `printf()` family of functions, `%n` is not safe to use, as the `int *`  | 
145  |  | // buffer can be used to capture arbitrary data.  | 
146  |  | //  | 
147  |  | // Example:  | 
148  |  | //  | 
149  |  | //   int n = 0;  | 
150  |  | //   std::string s = absl::StrFormat("%s%d%n", "hello", 123, | 
151  |  | //                       absl::FormatCountCapture(&n));  | 
152  |  | //   EXPECT_EQ(8, n);  | 
153  |  | class FormatCountCapture { | 
154  |  |  public:  | 
155  | 0  |   explicit FormatCountCapture(int* absl_nonnull p) : p_(p) {} | 
156  |  |  | 
157  |  |  private:  | 
158  |  |   // FormatCountCaptureHelper is used to define FormatConvertImpl() for this  | 
159  |  |   // class.  | 
160  |  |   friend struct str_format_internal::FormatCountCaptureHelper;  | 
161  |  |   // Unused() is here because of the false positive from -Wunused-private-field  | 
162  |  |   // p_ is used in the templated function of the friend FormatCountCaptureHelper  | 
163  |  |   // class.  | 
164  | 0  |   int* absl_nonnull Unused() { return p_; } | 
165  |  |   int* absl_nonnull p_;  | 
166  |  | };  | 
167  |  |  | 
168  |  | // FormatSpec  | 
169  |  | //  | 
170  |  | // The `FormatSpec` type defines the makeup of a format string within the  | 
171  |  | // `str_format` library. It is a variadic class template that is evaluated at  | 
172  |  | // compile-time, according to the format string and arguments that are passed to  | 
173  |  | // it.  | 
174  |  | //  | 
175  |  | // You should not need to manipulate this type directly. You should only name it  | 
176  |  | // if you are writing wrapper functions which accept format arguments that will  | 
177  |  | // be provided unmodified to functions in this library. Such a wrapper function  | 
178  |  | // might be a class method that provides format arguments and/or internally uses  | 
179  |  | // the result of formatting.  | 
180  |  | //  | 
181  |  | // For a `FormatSpec` to be valid at compile-time, it must be provided as  | 
182  |  | // either:  | 
183  |  | //  | 
184  |  | // * A `constexpr` literal or `absl::string_view`, which is how it is most often  | 
185  |  | //   used.  | 
186  |  | // * A `ParsedFormat` instantiation, which ensures the format string is  | 
187  |  | //   valid before use. (See below.)  | 
188  |  | //  | 
189  |  | // Example:  | 
190  |  | //  | 
191  |  | //   // Provided as a string literal.  | 
192  |  | //   absl::StrFormat("Welcome to %s, Number %d!", "The Village", 6); | 
193  |  | //  | 
194  |  | //   // Provided as a constexpr absl::string_view.  | 
195  |  | //   constexpr absl::string_view formatString = "Welcome to %s, Number %d!";  | 
196  |  | //   absl::StrFormat(formatString, "The Village", 6);  | 
197  |  | //  | 
198  |  | //   // Provided as a pre-compiled ParsedFormat object.  | 
199  |  | //   // Note that this example is useful only for illustration purposes.  | 
200  |  | //   absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!"); | 
201  |  | //   absl::StrFormat(formatString, "TheVillage", 6);  | 
202  |  | //  | 
203  |  | // A format string generally follows the POSIX syntax as used within the POSIX  | 
204  |  | // `printf` specification. (Exceptions are noted below.)  | 
205  |  | //  | 
206  |  | // (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html)  | 
207  |  | //  | 
208  |  | // In specific, the `FormatSpec` supports the following type specifiers:  | 
209  |  | //   * `c` for characters  | 
210  |  | //   * `s` for strings  | 
211  |  | //   * `d` or `i` for integers  | 
212  |  | //   * `o` for unsigned integer conversions into octal  | 
213  |  | //   * `x` or `X` for unsigned integer conversions into hex  | 
214  |  | //   * `u` for unsigned integers  | 
215  |  | //   * `f` or `F` for floating point values into decimal notation  | 
216  |  | //   * `e` or `E` for floating point values into exponential notation  | 
217  |  | //   * `a` or `A` for floating point values into hex exponential notation  | 
218  |  | //   * `g` or `G` for floating point values into decimal or exponential  | 
219  |  | //     notation based on their precision  | 
220  |  | //   * `p` for pointer address values  | 
221  |  | //   * `n` for the special case of writing out the number of characters  | 
222  |  | //     written to this point. The resulting value must be captured within an  | 
223  |  | //     `absl::FormatCountCapture` type.  | 
224  |  | //   * `v` for values using the default format for a deduced type. These deduced  | 
225  |  | //     types include many of the primitive types denoted here as well as  | 
226  |  | //     user-defined types containing the proper extensions. (See below for more  | 
227  |  | //     information.)  | 
228  |  | //  | 
229  |  | // Implementation-defined behavior:  | 
230  |  | //   * A null pointer provided to "%s" or "%p" is output as "(nil)".  | 
231  |  | //   * A non-null pointer provided to "%p" is output in hex as if by %#x or  | 
232  |  | //     %#lx.  | 
233  |  | //  | 
234  |  | // NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned  | 
235  |  | // counterpart before formatting.  | 
236  |  | //  | 
237  |  | // Examples:  | 
238  |  | //     "%c", 'a'                -> "a"  | 
239  |  | //     "%c", 32                 -> " "  | 
240  |  | //     "%s", "C"                -> "C"  | 
241  |  | //     "%s", std::string("C++") -> "C++" | 
242  |  | //     "%d", -10                -> "-10"  | 
243  |  | //     "%o", 10                 -> "12"  | 
244  |  | //     "%x", 16                 -> "10"  | 
245  |  | //     "%f", 123456789          -> "123456789.000000"  | 
246  |  | //     "%e", .01                -> "1.00000e-2"  | 
247  |  | //     "%a", -3.0               -> "-0x1.8p+1"  | 
248  |  | //     "%g", .01                -> "1e-2"  | 
249  |  | //     "%p", (void*)&value      -> "0x7ffdeb6ad2a4"  | 
250  |  | //  | 
251  |  | //     int n = 0;  | 
252  |  | //     std::string s = absl::StrFormat(  | 
253  |  | //         "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));  | 
254  |  | //     EXPECT_EQ(8, n);  | 
255  |  | //  | 
256  |  | // NOTE: the `v` specifier (for "value") is a type specifier not present in the  | 
257  |  | // POSIX specification. %v will format values according to their deduced type.  | 
258  |  | // `v` uses `d` for signed integer values, `u` for unsigned integer values, `g`  | 
259  |  | // for floating point values, and formats boolean values as "true"/"false"  | 
260  |  | // (instead of 1 or 0 for booleans formatted using d). `const char*` is not  | 
261  |  | // supported; please use `std::string` and `string_view`. `char` is also not  | 
262  |  | // supported due to ambiguity of the type. This specifier does not support  | 
263  |  | // modifiers.  | 
264  |  | //  | 
265  |  | // The `FormatSpec` intrinsically supports all of these fundamental C++ types:  | 
266  |  | //  | 
267  |  | // *   Characters: `char`, `signed char`, `unsigned char`, `wchar_t`  | 
268  |  | // *   Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`,  | 
269  |  | //         `unsigned long`, `long long`, `unsigned long long`  | 
270  |  | // *   Enums: printed as their underlying integral value  | 
271  |  | // *   Floating-point: `float`, `double`, `long double`  | 
272  |  | //  | 
273  |  | // However, in the `str_format` library, a format conversion specifies a broader  | 
274  |  | // C++ conceptual category instead of an exact type. For example, `%s` binds to  | 
275  |  | // any string-like argument, so `std::string`, `std::wstring`,  | 
276  |  | // `absl::string_view`, `const char*`, and `const wchar_t*` are all accepted.  | 
277  |  | // Likewise, `%d` accepts any integer-like argument, etc.  | 
278  |  |  | 
279  |  | template <typename... Args>  | 
280  |  | using FormatSpec = str_format_internal::FormatSpecTemplate<  | 
281  |  |     str_format_internal::ArgumentToConv<Args>()...>;  | 
282  |  |  | 
283  |  | // ParsedFormat  | 
284  |  | //  | 
285  |  | // A `ParsedFormat` is a class template representing a preparsed `FormatSpec`,  | 
286  |  | // with template arguments specifying the conversion characters used within the  | 
287  |  | // format string. Such characters must be valid format type specifiers, and  | 
288  |  | // these type specifiers are checked at compile-time.  | 
289  |  | //  | 
290  |  | // Instances of `ParsedFormat` can be created, copied, and reused to speed up  | 
291  |  | // formatting loops. A `ParsedFormat` may either be constructed statically, or  | 
292  |  | // dynamically through its `New()` factory function, which only constructs a  | 
293  |  | // runtime object if the format is valid at that time.  | 
294  |  | //  | 
295  |  | // Example:  | 
296  |  | //  | 
297  |  | //   // Verified at compile time.  | 
298  |  | //   absl::ParsedFormat<'s', 'd'> format_string("Welcome to %s, Number %d!"); | 
299  |  | //   absl::StrFormat(format_string, "TheVillage", 6);  | 
300  |  | //  | 
301  |  | //   // Verified at runtime.  | 
302  |  | //   auto format_runtime = absl::ParsedFormat<'d'>::New(format_string);  | 
303  |  | //   if (format_runtime) { | 
304  |  | //     value = absl::StrFormat(*format_runtime, i);  | 
305  |  | //   } else { | 
306  |  | //     ... error case ...  | 
307  |  | //   }  | 
308  |  |  | 
309  |  | #if defined(__cpp_nontype_template_parameter_auto)  | 
310  |  | // If C++17 is available, an 'extended' format is also allowed that can specify  | 
311  |  | // multiple conversion characters per format argument, using a combination of  | 
312  |  | // `absl::FormatConversionCharSet` enum values (logically a set union)  | 
313  |  | //  via the `|` operator. (Single character-based arguments are still accepted,  | 
314  |  | // but cannot be combined). Some common conversions also have predefined enum  | 
315  |  | // values, such as `absl::FormatConversionCharSet::kIntegral`.  | 
316  |  | //  | 
317  |  | // Example:  | 
318  |  | //   // Extended format supports multiple conversion characters per argument,  | 
319  |  | //   // specified via a combination of `FormatConversionCharSet` enums.  | 
320  |  | //   using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |  | 
321  |  | //                                       absl::FormatConversionCharSet::x>;  | 
322  |  | //   MyFormat GetFormat(bool use_hex) { | 
323  |  | //     if (use_hex) return MyFormat("foo %x bar"); | 
324  |  | //     return MyFormat("foo %d bar"); | 
325  |  | //   }  | 
326  |  | //   // `format` can be used with any value that supports 'd' and 'x',  | 
327  |  | //   // like `int`.  | 
328  |  | //   auto format = GetFormat(use_hex);  | 
329  |  | //   value = StringF(format, i);  | 
330  |  | template <auto... Conv>  | 
331  |  | using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<  | 
332  |  |     absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;  | 
333  |  | #else  | 
334  |  | template <char... Conv>  | 
335  |  | using ParsedFormat = str_format_internal::ExtendedParsedFormat<  | 
336  |  |     absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;  | 
337  |  | #endif  // defined(__cpp_nontype_template_parameter_auto)  | 
338  |  |  | 
339  |  | // StrFormat()  | 
340  |  | //  | 
341  |  | // Returns a `string` given a `printf()`-style format string and zero or more  | 
342  |  | // additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the  | 
343  |  | // primary formatting function within the `str_format` library, and should be  | 
344  |  | // used in most cases where you need type-safe conversion of types into  | 
345  |  | // formatted strings.  | 
346  |  | //  | 
347  |  | // The format string generally consists of ordinary character data along with  | 
348  |  | // one or more format conversion specifiers (denoted by the `%` character).  | 
349  |  | // Ordinary character data is returned unchanged into the result string, while  | 
350  |  | // each conversion specification performs a type substitution from  | 
351  |  | // `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full  | 
352  |  | // information on the makeup of this format string.  | 
353  |  | //  | 
354  |  | // Example:  | 
355  |  | //  | 
356  |  | //   std::string s = absl::StrFormat(  | 
357  |  | //       "Welcome to %s, Number %d!", "The Village", 6);  | 
358  |  | //   EXPECT_EQ("Welcome to The Village, Number 6!", s); | 
359  |  | //  | 
360  |  | // Returns an empty string in case of error.  | 
361  |  | template <typename... Args>  | 
362  |  | [[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,  | 
363  | 0  |                                     const Args&... args) { | 
364  | 0  |   return str_format_internal::FormatPack(  | 
365  | 0  |       str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
366  | 0  |       {str_format_internal::FormatArgImpl(args)...}); | 
367  | 0  | } Unexecuted instantiation: _ZN4absl9StrFormatIJifEEENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS_19str_format_internal18FormatSpecTemplateIJXspclsr19str_format_internalE14ArgumentToConvIT_EEEEEEDpRKSA_ Unexecuted instantiation: _ZN4absl9StrFormatIJidEEENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS_19str_format_internal18FormatSpecTemplateIJXspclsr19str_format_internalE14ArgumentToConvIT_EEEEEEDpRKSA_ Unexecuted instantiation: _ZN4absl9StrFormatIJciiiiiliNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEiPKcS5_EEENS1_12basic_stringIcS4_NS1_9allocatorIcEEEERKNS_19str_format_internal18FormatSpecTemplateIJXspclsr19str_format_internalE14ArgumentToConvIT_EEEEEEDpRKSE_  | 
368  |  |  | 
369  |  | // StrAppendFormat()  | 
370  |  | //  | 
371  |  | // Appends to a `dst` string given a format string, and zero or more additional  | 
372  |  | // arguments, returning `*dst` as a convenience for chaining purposes. Appends  | 
373  |  | // nothing in case of error (but possibly alters its capacity).  | 
374  |  | //  | 
375  |  | // Example:  | 
376  |  | //  | 
377  |  | //   std::string orig("For example PI is approximately "); | 
378  |  | //   std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);  | 
379  |  | template <typename... Args>  | 
380  |  | std::string& StrAppendFormat(std::string* absl_nonnull dst,  | 
381  |  |                              const FormatSpec<Args...>& format,  | 
382  |  |                              const Args&... args) { | 
383  |  |   return str_format_internal::AppendPack(  | 
384  |  |       dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
385  |  |       {str_format_internal::FormatArgImpl(args)...}); | 
386  |  | }  | 
387  |  |  | 
388  |  | // StreamFormat()  | 
389  |  | //  | 
390  |  | // Writes to an output stream given a format string and zero or more arguments,  | 
391  |  | // generally in a manner that is more efficient than streaming the result of  | 
392  |  | // `absl::StrFormat()`. The returned object must be streamed before the full  | 
393  |  | // expression ends.  | 
394  |  | //  | 
395  |  | // Example:  | 
396  |  | //  | 
397  |  | //   std::cout << StreamFormat("%12.6f", 3.14); | 
398  |  | template <typename... Args>  | 
399  |  | [[nodiscard]] str_format_internal::Streamable StreamFormat(  | 
400  | 0  |     const FormatSpec<Args...>& format, const Args&... args) { | 
401  | 0  |   return str_format_internal::Streamable(  | 
402  | 0  |       str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
403  | 0  |       {str_format_internal::FormatArgImpl(args)...}); | 
404  | 0  | }  | 
405  |  |  | 
406  |  | // PrintF()  | 
407  |  | //  | 
408  |  | // Writes to stdout given a format string and zero or more arguments. This  | 
409  |  | // function is functionally equivalent to `std::printf()` (and type-safe);  | 
410  |  | // prefer `absl::PrintF()` over `std::printf()`.  | 
411  |  | //  | 
412  |  | // Example:  | 
413  |  | //  | 
414  |  | //   std::string_view s = "Ulaanbaatar";  | 
415  |  | //   absl::PrintF("The capital of Mongolia is %s", s); | 
416  |  | //  | 
417  |  | //   Outputs: "The capital of Mongolia is Ulaanbaatar"  | 
418  |  | //  | 
419  |  | template <typename... Args>  | 
420  |  | int PrintF(const FormatSpec<Args...>& format, const Args&... args) { | 
421  |  |   return str_format_internal::FprintF(  | 
422  |  |       stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
423  |  |       {str_format_internal::FormatArgImpl(args)...}); | 
424  |  | }  | 
425  |  |  | 
426  |  | // FPrintF()  | 
427  |  | //  | 
428  |  | // Writes to a file given a format string and zero or more arguments. This  | 
429  |  | // function is functionally equivalent to `std::fprintf()` (and type-safe);  | 
430  |  | // prefer `absl::FPrintF()` over `std::fprintf()`.  | 
431  |  | //  | 
432  |  | // Example:  | 
433  |  | //  | 
434  |  | //   std::string_view s = "Ulaanbaatar";  | 
435  |  | //   absl::FPrintF(stdout, "The capital of Mongolia is %s", s);  | 
436  |  | //  | 
437  |  | //   Outputs: "The capital of Mongolia is Ulaanbaatar"  | 
438  |  | //  | 
439  |  | template <typename... Args>  | 
440  |  | int FPrintF(std::FILE* absl_nonnull output, const FormatSpec<Args...>& format,  | 
441  |  |             const Args&... args) { | 
442  |  |   return str_format_internal::FprintF(  | 
443  |  |       output, str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
444  |  |       {str_format_internal::FormatArgImpl(args)...}); | 
445  |  | }  | 
446  |  |  | 
447  |  | // SNPrintF()  | 
448  |  | //  | 
449  |  | // Writes to a sized buffer given a format string and zero or more arguments.  | 
450  |  | // This function is functionally equivalent to `std::snprintf()` (and  | 
451  |  | // type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.  | 
452  |  | //  | 
453  |  | // In particular, a successful call to `absl::SNPrintF()` writes at most `size`  | 
454  |  | // bytes of the formatted output to `output`, including a NUL-terminator, and  | 
455  |  | // returns the number of bytes that would have been written if truncation did  | 
456  |  | // not occur. In the event of an error, a negative value is returned and `errno`  | 
457  |  | // is set.  | 
458  |  | //  | 
459  |  | // Example:  | 
460  |  | //  | 
461  |  | //   std::string_view s = "Ulaanbaatar";  | 
462  |  | //   char output[128];  | 
463  |  | //   absl::SNPrintF(output, sizeof(output),  | 
464  |  | //                  "The capital of Mongolia is %s", s);  | 
465  |  | //  | 
466  |  | //   Post-condition: output == "The capital of Mongolia is Ulaanbaatar"  | 
467  |  | //  | 
468  |  | template <typename... Args>  | 
469  |  | int SNPrintF(char* absl_nonnull output, std::size_t size,  | 
470  | 4.12M  |              const FormatSpec<Args...>& format, const Args&... args) { | 
471  | 4.12M  |   return str_format_internal::SnprintF(  | 
472  | 4.12M  |       output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
473  | 4.12M  |       {str_format_internal::FormatArgImpl(args)...}); | 
474  | 4.12M  | }  | 
475  |  |  | 
476  |  | // -----------------------------------------------------------------------------  | 
477  |  | // Custom Output Formatting Functions  | 
478  |  | // -----------------------------------------------------------------------------  | 
479  |  |  | 
480  |  | // FormatRawSink  | 
481  |  | //  | 
482  |  | // FormatRawSink is a type erased wrapper around arbitrary sink objects  | 
483  |  | // specifically used as an argument to `Format()`.  | 
484  |  | //  | 
485  |  | // All the object has to do define an overload of `AbslFormatFlush()` for the  | 
486  |  | // sink, usually by adding a ADL-based free function in the same namespace as  | 
487  |  | // the sink:  | 
488  |  | //  | 
489  |  | //   void AbslFormatFlush(MySink* dest, absl::string_view part);  | 
490  |  | //  | 
491  |  | // where `dest` is the pointer passed to `absl::Format()`. The function should  | 
492  |  | // append `part` to `dest`.  | 
493  |  | //  | 
494  |  | // FormatRawSink does not own the passed sink object. The passed object must  | 
495  |  | // outlive the FormatRawSink.  | 
496  |  | class FormatRawSink { | 
497  |  |  public:  | 
498  |  |   // Implicitly convert from any type that provides the hook function as  | 
499  |  |   // described above.  | 
500  |  |   template <typename T,  | 
501  |  |             typename = typename std::enable_if<std::is_constructible<  | 
502  |  |                 str_format_internal::FormatRawSinkImpl, T*>::value>::type>  | 
503  |  |   FormatRawSink(T* absl_nonnull raw)  // NOLINT  | 
504  |  |       : sink_(raw) {} | 
505  |  |  | 
506  |  |  private:  | 
507  |  |   friend str_format_internal::FormatRawSinkImpl;  | 
508  |  |   str_format_internal::FormatRawSinkImpl sink_;  | 
509  |  | };  | 
510  |  |  | 
511  |  | // Format()  | 
512  |  | //  | 
513  |  | // Writes a formatted string to an arbitrary sink object (implementing the  | 
514  |  | // `absl::FormatRawSink` interface), using a format string and zero or more  | 
515  |  | // additional arguments.  | 
516  |  | //  | 
517  |  | // By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as  | 
518  |  | // destination objects. If a `std::string` is used the formatted string is  | 
519  |  | // appended to it.  | 
520  |  | //  | 
521  |  | // `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for  | 
522  |  | // custom sinks. The format string, like format strings for `StrFormat()`, is  | 
523  |  | // checked at compile-time.  | 
524  |  | //  | 
525  |  | // On failure, this function returns `false` and the state of the sink is  | 
526  |  | // unspecified.  | 
527  |  | template <typename... Args>  | 
528  |  | bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,  | 
529  |  |             const Args&... args) { | 
530  |  |   return str_format_internal::FormatUntyped(  | 
531  |  |       str_format_internal::FormatRawSinkImpl::Extract(raw_sink),  | 
532  |  |       str_format_internal::UntypedFormatSpecImpl::Extract(format),  | 
533  |  |       {str_format_internal::FormatArgImpl(args)...}); | 
534  |  | }  | 
535  |  |  | 
536  |  | // FormatArg  | 
537  |  | //  | 
538  |  | // A type-erased handle to a format argument specifically used as an argument to  | 
539  |  | // `FormatUntyped()`. You may construct `FormatArg` by passing  | 
540  |  | // reference-to-const of any printable type. `FormatArg` is both copyable and  | 
541  |  | // assignable. The source data must outlive the `FormatArg` instance. See  | 
542  |  | // example below.  | 
543  |  | //  | 
544  |  | using FormatArg = str_format_internal::FormatArgImpl;  | 
545  |  |  | 
546  |  | // FormatUntyped()  | 
547  |  | //  | 
548  |  | // Writes a formatted string to an arbitrary sink object (implementing the  | 
549  |  | // `absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or  | 
550  |  | // more additional arguments.  | 
551  |  | //  | 
552  |  | // This function acts as the most generic formatting function in the  | 
553  |  | // `str_format` library. The caller provides a raw sink, an unchecked format  | 
554  |  | // string, and (usually) a runtime specified list of arguments; no compile-time  | 
555  |  | // checking of formatting is performed within this function. As a result, a  | 
556  |  | // caller should check the return value to verify that no error occurred.  | 
557  |  | // On failure, this function returns `false` and the state of the sink is  | 
558  |  | // unspecified.  | 
559  |  | //  | 
560  |  | // The arguments are provided in an `absl::Span<const absl::FormatArg>`.  | 
561  |  | // Each `absl::FormatArg` object binds to a single argument and keeps a  | 
562  |  | // reference to it. The values used to create the `FormatArg` objects must  | 
563  |  | // outlive this function call.  | 
564  |  | //  | 
565  |  | // Example:  | 
566  |  | //  | 
567  |  | //   std::optional<std::string> FormatDynamic(  | 
568  |  | //       const std::string& in_format,  | 
569  |  | //       const vector<std::string>& in_args) { | 
570  |  | //     std::string out;  | 
571  |  | //     std::vector<absl::FormatArg> args;  | 
572  |  | //     for (const auto& v : in_args) { | 
573  |  | //       // It is important that 'v' is a reference to the objects in in_args.  | 
574  |  | //       // The values we pass to FormatArg must outlive the call to  | 
575  |  | //       // FormatUntyped.  | 
576  |  | //       args.emplace_back(v);  | 
577  |  | //     }  | 
578  |  | //     absl::UntypedFormatSpec format(in_format);  | 
579  |  | //     if (!absl::FormatUntyped(&out, format, args)) { | 
580  |  | //       return std::nullopt;  | 
581  |  | //     }  | 
582  |  | //     return std::move(out);  | 
583  |  | //   }  | 
584  |  | //  | 
585  |  | [[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,  | 
586  |  |                                         const UntypedFormatSpec& format,  | 
587  | 0  |                                         absl::Span<const FormatArg> args) { | 
588  | 0  |   return str_format_internal::FormatUntyped(  | 
589  | 0  |       str_format_internal::FormatRawSinkImpl::Extract(raw_sink),  | 
590  | 0  |       str_format_internal::UntypedFormatSpecImpl::Extract(format), args);  | 
591  | 0  | }  | 
592  |  |  | 
593  |  | //------------------------------------------------------------------------------  | 
594  |  | // StrFormat Extensions  | 
595  |  | //------------------------------------------------------------------------------  | 
596  |  | //  | 
597  |  | // AbslStringify()  | 
598  |  | //  | 
599  |  | // A simpler customization API for formatting user-defined types using  | 
600  |  | // absl::StrFormat(). The API relies on detecting an overload in the  | 
601  |  | // user-defined type's namespace of a free (non-member) `AbslStringify()`  | 
602  |  | // function as a friend definition with the following signature:  | 
603  |  | //  | 
604  |  | // template <typename Sink>  | 
605  |  | // void AbslStringify(Sink& sink, const X& value);  | 
606  |  | //  | 
607  |  | // An `AbslStringify()` overload for a type should only be declared in the same  | 
608  |  | // file and namespace as said type.  | 
609  |  | //  | 
610  |  | // Note that unlike with AbslFormatConvert(), AbslStringify() does not allow  | 
611  |  | // customization of allowed conversion characters. AbslStringify() uses `%v` as  | 
612  |  | // the underlying conversion specifier. Additionally, AbslStringify() supports  | 
613  |  | // use with absl::StrCat while AbslFormatConvert() does not.  | 
614  |  | //  | 
615  |  | // Example:  | 
616  |  | //  | 
617  |  | // struct Point { | 
618  |  | //   // To add formatting support to `Point`, we simply need to add a free  | 
619  |  | //   // (non-member) function `AbslStringify()`. This method prints in the  | 
620  |  | //   // request format using the underlying `%v` specifier. You can add such a  | 
621  |  | //   // free function using a friend declaration within the body of the class.  | 
622  |  | //   // The sink parameter is a templated type to avoid requiring dependencies.  | 
623  |  | //   template <typename Sink>  | 
624  |  | //   friend void AbslStringify(Sink& sink, const Point& p) { | 
625  |  | //     absl::Format(&sink, "(%v, %v)", p.x, p.y);  | 
626  |  | //   }  | 
627  |  | //  | 
628  |  | //   int x;  | 
629  |  | //   int y;  | 
630  |  | // };  | 
631  |  | //  | 
632  |  | // AbslFormatConvert()  | 
633  |  | //  | 
634  |  | // The StrFormat library provides a customization API for formatting  | 
635  |  | // user-defined types using absl::StrFormat(). The API relies on detecting an  | 
636  |  | // overload in the user-defined type's namespace of a free (non-member)  | 
637  |  | // `AbslFormatConvert()` function, usually as a friend definition with the  | 
638  |  | // following signature:  | 
639  |  | //  | 
640  |  | // absl::FormatConvertResult<...> AbslFormatConvert(  | 
641  |  | //     const X& value,  | 
642  |  | //     const absl::FormatConversionSpec& spec,  | 
643  |  | //     absl::FormatSink *sink);  | 
644  |  | //  | 
645  |  | // An `AbslFormatConvert()` overload for a type should only be declared in the  | 
646  |  | // same file and namespace as said type.  | 
647  |  | //  | 
648  |  | // The abstractions within this definition include:  | 
649  |  | //  | 
650  |  | // * An `absl::FormatConversionSpec` to specify the fields to pull from a  | 
651  |  | //   user-defined type's format string  | 
652  |  | // * An `absl::FormatSink` to hold the converted string data during the  | 
653  |  | //   conversion process.  | 
654  |  | // * An `absl::FormatConvertResult` to hold the status of the returned  | 
655  |  | //   formatting operation  | 
656  |  | //  | 
657  |  | // The return type encodes all the conversion characters that your  | 
658  |  | // AbslFormatConvert() routine accepts.  The return value should be {true}. | 
659  |  | // A return value of {false} will result in `StrFormat()` returning | 
660  |  | // an empty string.  This result will be propagated to the result of  | 
661  |  | // `FormatUntyped`.  | 
662  |  | //  | 
663  |  | // Example:  | 
664  |  | //  | 
665  |  | // struct Point { | 
666  |  | //   // To add formatting support to `Point`, we simply need to add a free  | 
667  |  | //   // (non-member) function `AbslFormatConvert()`.  This method interprets  | 
668  |  | //   // `spec` to print in the request format. The allowed conversion characters  | 
669  |  | //   // can be restricted via the type of the result, in this example  | 
670  |  | //   // string and integral formatting are allowed (but not, for instance  | 
671  |  | //   // floating point characters like "%f").  You can add such a free function  | 
672  |  | //   // using a friend declaration within the body of the class:  | 
673  |  | //   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |  | 
674  |  | //                                    absl::FormatConversionCharSet::kIntegral>  | 
675  |  | //   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,  | 
676  |  | //                     absl::FormatSink* s) { | 
677  |  | //     if (spec.conversion_char() == absl::FormatConversionChar::s) { | 
678  |  | //       absl::Format(s, "x=%vy=%v", p.x, p.y);  | 
679  |  | //     } else { | 
680  |  | //       absl::Format(s, "%v,%v", p.x, p.y);  | 
681  |  | //     }  | 
682  |  | //     return {true}; | 
683  |  | //   }  | 
684  |  | //  | 
685  |  | //   int x;  | 
686  |  | //   int y;  | 
687  |  | // };  | 
688  |  |  | 
689  |  | // clang-format off  | 
690  |  |  | 
691  |  | // FormatConversionChar  | 
692  |  | //  | 
693  |  | // Specifies the formatting character provided in the format string  | 
694  |  | // passed to `StrFormat()`.  | 
695  |  | enum class FormatConversionChar : uint8_t { | 
696  |  |   c, s,                    // text  | 
697  |  |   d, i, o, u, x, X,        // int  | 
698  |  |   f, F, e, E, g, G, a, A,  // float  | 
699  |  |   n, p, v                  // misc  | 
700  |  | };  | 
701  |  | // clang-format on  | 
702  |  |  | 
703  |  | // FormatConversionSpec  | 
704  |  | //  | 
705  |  | // Specifies modifications to the conversion of the format string, through use  | 
706  |  | // of one or more format flags in the source format string.  | 
707  |  | class FormatConversionSpec { | 
708  |  |  public:  | 
709  |  |   // FormatConversionSpec::is_basic()  | 
710  |  |   //  | 
711  |  |   // Indicates that width and precision are not specified, and no additional  | 
712  |  |   // flags are set for this conversion character in the format string.  | 
713  | 0  |   bool is_basic() const { return impl_.is_basic(); } | 
714  |  |  | 
715  |  |   // FormatConversionSpec::has_left_flag()  | 
716  |  |   //  | 
717  |  |   // Indicates whether the result should be left justified for this conversion  | 
718  |  |   // character in the format string. This flag is set through use of a '-'  | 
719  |  |   // character in the format string. E.g. "%-s"  | 
720  | 0  |   bool has_left_flag() const { return impl_.has_left_flag(); } | 
721  |  |  | 
722  |  |   // FormatConversionSpec::has_show_pos_flag()  | 
723  |  |   //  | 
724  |  |   // Indicates whether a sign column is prepended to the result for this  | 
725  |  |   // conversion character in the format string, even if the result is positive.  | 
726  |  |   // This flag is set through use of a '+' character in the format string.  | 
727  |  |   // E.g. "%+d"  | 
728  | 0  |   bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); } | 
729  |  |  | 
730  |  |   // FormatConversionSpec::has_sign_col_flag()  | 
731  |  |   //  | 
732  |  |   // Indicates whether a mandatory sign column is added to the result for this  | 
733  |  |   // conversion character. This flag is set through use of a space character  | 
734  |  |   // (' ') in the format string. E.g. "% i" | 
735  | 0  |   bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); } | 
736  |  |  | 
737  |  |   // FormatConversionSpec::has_alt_flag()  | 
738  |  |   //  | 
739  |  |   // Indicates whether an "alternate" format is applied to the result for this  | 
740  |  |   // conversion character. Alternative forms depend on the type of conversion  | 
741  |  |   // character, and unallowed alternatives are undefined. This flag is set  | 
742  |  |   // through use of a '#' character in the format string. E.g. "%#h"  | 
743  | 0  |   bool has_alt_flag() const { return impl_.has_alt_flag(); } | 
744  |  |  | 
745  |  |   // FormatConversionSpec::has_zero_flag()  | 
746  |  |   //  | 
747  |  |   // Indicates whether zeroes should be prepended to the result for this  | 
748  |  |   // conversion character instead of spaces. This flag is set through use of the  | 
749  |  |   // '0' character in the format string. E.g. "%0f"  | 
750  | 0  |   bool has_zero_flag() const { return impl_.has_zero_flag(); } | 
751  |  |  | 
752  |  |   // FormatConversionSpec::conversion_char()  | 
753  |  |   //  | 
754  |  |   // Returns the underlying conversion character.  | 
755  | 0  |   FormatConversionChar conversion_char() const { | 
756  | 0  |     return impl_.conversion_char();  | 
757  | 0  |   }  | 
758  |  |  | 
759  |  |   // FormatConversionSpec::width()  | 
760  |  |   //  | 
761  |  |   // Returns the specified width (indicated through use of a non-zero integer  | 
762  |  |   // value or '*' character) of the conversion character. If width is  | 
763  |  |   // unspecified, it returns a negative value.  | 
764  | 0  |   int width() const { return impl_.width(); } | 
765  |  |  | 
766  |  |   // FormatConversionSpec::precision()  | 
767  |  |   //  | 
768  |  |   // Returns the specified precision (through use of the '.' character followed  | 
769  |  |   // by a non-zero integer value or '*' character) of the conversion character.  | 
770  |  |   // If precision is unspecified, it returns a negative value.  | 
771  | 0  |   int precision() const { return impl_.precision(); } | 
772  |  |  | 
773  |  |  private:  | 
774  |  |   explicit FormatConversionSpec(  | 
775  |  |       str_format_internal::FormatConversionSpecImpl impl)  | 
776  | 0  |       : impl_(impl) {} | 
777  |  |  | 
778  |  |   friend str_format_internal::FormatConversionSpecImpl;  | 
779  |  |  | 
780  |  |   absl::str_format_internal::FormatConversionSpecImpl impl_;  | 
781  |  | };  | 
782  |  |  | 
783  |  | // Type safe OR operator for FormatConversionCharSet to allow accepting multiple  | 
784  |  | // conversion chars in custom format converters.  | 
785  |  | constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,  | 
786  | 0  |                                             FormatConversionCharSet b) { | 
787  | 0  |   return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |  | 
788  | 0  |                                               static_cast<uint64_t>(b));  | 
789  | 0  | }  | 
790  |  |  | 
791  |  | // FormatConversionCharSet  | 
792  |  | //  | 
793  |  | // Specifies the _accepted_ conversion types as a template parameter to  | 
794  |  | // FormatConvertResult for custom implementations of `AbslFormatConvert`.  | 
795  |  | // Note the helper predefined alias definitions (kIntegral, etc.) below.  | 
796  |  | enum class FormatConversionCharSet : uint64_t { | 
797  |  |   // text  | 
798  |  |   c = str_format_internal::FormatConversionCharToConvInt('c'), | 
799  |  |   s = str_format_internal::FormatConversionCharToConvInt('s'), | 
800  |  |   // integer  | 
801  |  |   d = str_format_internal::FormatConversionCharToConvInt('d'), | 
802  |  |   i = str_format_internal::FormatConversionCharToConvInt('i'), | 
803  |  |   o = str_format_internal::FormatConversionCharToConvInt('o'), | 
804  |  |   u = str_format_internal::FormatConversionCharToConvInt('u'), | 
805  |  |   x = str_format_internal::FormatConversionCharToConvInt('x'), | 
806  |  |   X = str_format_internal::FormatConversionCharToConvInt('X'), | 
807  |  |   // Float  | 
808  |  |   f = str_format_internal::FormatConversionCharToConvInt('f'), | 
809  |  |   F = str_format_internal::FormatConversionCharToConvInt('F'), | 
810  |  |   e = str_format_internal::FormatConversionCharToConvInt('e'), | 
811  |  |   E = str_format_internal::FormatConversionCharToConvInt('E'), | 
812  |  |   g = str_format_internal::FormatConversionCharToConvInt('g'), | 
813  |  |   G = str_format_internal::FormatConversionCharToConvInt('G'), | 
814  |  |   a = str_format_internal::FormatConversionCharToConvInt('a'), | 
815  |  |   A = str_format_internal::FormatConversionCharToConvInt('A'), | 
816  |  |   // misc  | 
817  |  |   n = str_format_internal::FormatConversionCharToConvInt('n'), | 
818  |  |   p = str_format_internal::FormatConversionCharToConvInt('p'), | 
819  |  |   v = str_format_internal::FormatConversionCharToConvInt('v'), | 
820  |  |  | 
821  |  |   // Used for width/precision '*' specification.  | 
822  |  |   kStar = static_cast<uint64_t>(  | 
823  |  |       absl::str_format_internal::FormatConversionCharSetInternal::kStar),  | 
824  |  |   // Some predefined values:  | 
825  |  |   kIntegral = d | i | u | o | x | X,  | 
826  |  |   kFloating = a | e | f | g | A | E | F | G,  | 
827  |  |   kNumeric = kIntegral | kFloating,  | 
828  |  |   kString = s,  | 
829  |  |   kPointer = p,  | 
830  |  | };  | 
831  |  |  | 
832  |  | // FormatSink  | 
833  |  | //  | 
834  |  | // A format sink is a generic abstraction to which conversions may write their  | 
835  |  | // formatted string data. `absl::FormatConvert()` uses this sink to write its  | 
836  |  | // formatted string.  | 
837  |  | //  | 
838  |  | class FormatSink { | 
839  |  |  public:  | 
840  |  |   // FormatSink::Append()  | 
841  |  |   //  | 
842  |  |   // Appends `count` copies of `ch` to the format sink.  | 
843  | 0  |   void Append(size_t count, char ch) { sink_->Append(count, ch); } | 
844  |  |  | 
845  |  |   // Overload of FormatSink::Append() for appending the characters of a string  | 
846  |  |   // view to a format sink.  | 
847  | 0  |   void Append(string_view v) { sink_->Append(v); } | 
848  |  |  | 
849  |  |   // FormatSink::PutPaddedString()  | 
850  |  |   //  | 
851  |  |   // Appends `precision` number of bytes of `v` to the format sink. If this is  | 
852  |  |   // less than `width`, spaces will be appended first (if `left` is false), or  | 
853  |  |   // after (if `left` is true) to ensure the total amount appended is  | 
854  |  |   // at least `width`.  | 
855  | 0  |   bool PutPaddedString(string_view v, int width, int precision, bool left) { | 
856  | 0  |     return sink_->PutPaddedString(v, width, precision, left);  | 
857  | 0  |   }  | 
858  |  |  | 
859  |  |   // Support `absl::Format(&sink, format, args...)`.  | 
860  |  |   friend void AbslFormatFlush(FormatSink* absl_nonnull sink,  | 
861  | 0  |                               absl::string_view v) { | 
862  | 0  |     sink->Append(v);  | 
863  | 0  |   }  | 
864  |  |  | 
865  |  |  private:  | 
866  |  |   friend str_format_internal::FormatSinkImpl;  | 
867  |  |   explicit FormatSink(str_format_internal::FormatSinkImpl* absl_nonnull s)  | 
868  | 0  |       : sink_(s) {} | 
869  |  |   str_format_internal::FormatSinkImpl* absl_nonnull sink_;  | 
870  |  | };  | 
871  |  |  | 
872  |  | // FormatConvertResult  | 
873  |  | //  | 
874  |  | // Indicates whether a call to AbslFormatConvert() was successful.  | 
875  |  | // This return type informs the StrFormat extension framework (through  | 
876  |  | // ADL but using the return type) of what conversion characters are supported.  | 
877  |  | // It is strongly discouraged to return {false}, as this will result in an | 
878  |  | // empty string in StrFormat.  | 
879  |  | template <FormatConversionCharSet C>  | 
880  |  | struct FormatConvertResult { | 
881  |  |   bool value;  | 
882  |  | };  | 
883  |  |  | 
884  |  | ABSL_NAMESPACE_END  | 
885  |  | }  // namespace absl  | 
886  |  |  | 
887  |  | #endif  // ABSL_STRINGS_STR_FORMAT_H_  |