Coverage Report

Created: 2026-09-14 06:45

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