Line | Count | Source (jump to first uncovered line) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.96k | explicit UntypedFormatSpec(string_view s) : spec_(s) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
112 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
113 | protected: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
114 | explicit UntypedFormatSpec( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
115 | absl::Nonnull<const str_format_internal::ParsedFormatBase*> 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(absl::Nonnull<int*> 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 | absl::Nonnull<int*> Unused() { return p_; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
165 | absl::Nonnull<int*> 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 | ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
363 | 4.96k | const Args&... args) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
364 | 4.96k | return str_format_internal::FormatPack( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
365 | 4.96k | str_format_internal::UntypedFormatSpecImpl::Extract(format), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
366 | 4.96k | {str_format_internal::FormatArgImpl(args)...}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
367 | 4.96k | }
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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(absl::Nonnull<std::string*> 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 | ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
400 | const FormatSpec<Args...>& format, const Args&... args) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
401 | return str_format_internal::Streamable( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
402 | str_format_internal::UntypedFormatSpecImpl::Extract(format), | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
403 | {str_format_internal::FormatArgImpl(args)...}); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
404 | } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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(absl::Nonnull<std::FILE*> 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(absl::Nonnull<char*> output, std::size_t size, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
470 | const FormatSpec<Args...>& format, const Args&... args) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
471 | return str_format_internal::SnprintF( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
472 | output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format), | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
473 | {str_format_internal::FormatArgImpl(args)...}); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
474 | } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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(absl::Nonnull<T*> 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 | ABSL_MUST_USE_RESULT inline bool FormatUntyped( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
586 | FormatRawSink raw_sink, 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 specififer. 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(absl::Nonnull<FormatSink*> 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(absl::Nonnull<str_format_internal::FormatSinkImpl*> s) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
868 | 0 | : sink_(s) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
869 | absl::Nonnull<str_format_internal::FormatSinkImpl*> 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_ |