Coverage Report

Created: 2026-05-30 06:40

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
#if defined(__cpp_nontype_template_parameter_auto)
313
// If C++17 is available, an 'extended' format is also allowed that can specify
314
// multiple conversion characters per format argument, using a combination of
315
// `absl::FormatConversionCharSet` enum values (logically a set union)
316
//  via the `|` operator. (Single character-based arguments are still accepted,
317
// but cannot be combined). Some common conversions also have predefined enum
318
// values, such as `absl::FormatConversionCharSet::kIntegral`.
319
//
320
// Example:
321
//   // Extended format supports multiple conversion characters per argument,
322
//   // specified via a combination of `FormatConversionCharSet` enums.
323
//   using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
324
//                                       absl::FormatConversionCharSet::x>;
325
//   MyFormat GetFormat(bool use_hex) {
326
//     if (use_hex) return MyFormat("foo %x bar");
327
//     return MyFormat("foo %d bar");
328
//   }
329
//   // `format` can be used with any value that supports 'd' and 'x',
330
//   // like `int`.
331
//   auto format = GetFormat(use_hex);
332
//   value = StringF(format, i);
333
template <auto... Conv>
334
using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
335
    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
336
#else
337
template <char... Conv>
338
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
339
    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
340
#endif  // defined(__cpp_nontype_template_parameter_auto)
341
342
// StrFormat()
343
//
344
// Returns a `string` given a `printf()`-style format string and zero or more
345
// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the
346
// primary formatting function within the `str_format` library, and should be
347
// used in most cases where you need type-safe conversion of types into
348
// formatted strings.
349
//
350
// The format string generally consists of ordinary character data along with
351
// one or more format conversion specifiers (denoted by the `%` character).
352
// Ordinary character data is returned unchanged into the result string, while
353
// each conversion specification performs a type substitution from
354
// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full
355
// information on the makeup of this format string.
356
//
357
// Example:
358
//
359
//   std::string s = absl::StrFormat(
360
//       "Welcome to %s, Number %d!", "The Village", 6);
361
//   EXPECT_EQ("Welcome to The Village, Number 6!", s);
362
//
363
// Returns an empty string in case of error.
364
template <typename... Args>
365
[[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,
366
0
                                    const Args&... args) {
367
0
  return str_format_internal::FormatPack(
368
0
      str_format_internal::UntypedFormatSpecImpl::Extract(format),
369
0
      {str_format_internal::FormatArgImpl(args)...});
370
0
}
371
372
// StrAppendFormat()
373
//
374
// Appends to a `dst` string given a format string, and zero or more additional
375
// arguments, returning `*dst` as a convenience for chaining purposes. Appends
376
// nothing in case of error (but possibly alters its capacity).
377
//
378
// Example:
379
//
380
//   std::string orig("For example PI is approximately ");
381
//   std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
382
template <typename... Args>
383
std::string& StrAppendFormat(std::string* absl_nonnull dst,
384
                             const FormatSpec<Args...>& format,
385
                             const Args&... args) {
386
  return str_format_internal::AppendPack(
387
      dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
388
      {str_format_internal::FormatArgImpl(args)...});
389
}
390
391
// StreamFormat()
392
//
393
// Writes to an output stream given a format string and zero or more arguments,
394
// generally in a manner that is more efficient than streaming the result of
395
// `absl::StrFormat()`. The returned object must be streamed before the full
396
// expression ends.
397
//
398
// Example:
399
//
400
//   std::cout << StreamFormat("%12.6f", 3.14);
401
template <typename... Args>
402
[[nodiscard]] str_format_internal::Streamable StreamFormat(
403
0
    const FormatSpec<Args...>& format, const Args&... args) {
404
0
  return str_format_internal::Streamable(
405
0
      str_format_internal::UntypedFormatSpecImpl::Extract(format),
406
0
      {str_format_internal::FormatArgImpl(args)...});
407
0
}
408
409
// PrintF()
410
//
411
// Writes to stdout given a format string and zero or more arguments. This
412
// function is functionally equivalent to `std::printf()` (and type-safe);
413
// prefer `absl::PrintF()` over `std::printf()`.
414
//
415
// Example:
416
//
417
//   std::string_view s = "Ulaanbaatar";
418
//   absl::PrintF("The capital of Mongolia is %s", s);
419
//
420
//   Outputs: "The capital of Mongolia is Ulaanbaatar"
421
//
422
template <typename... Args>
423
int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
424
  return str_format_internal::FprintF(
425
      stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),
426
      {str_format_internal::FormatArgImpl(args)...});
427
}
428
429
// FPrintF()
430
//
431
// Writes to a file given a format string and zero or more arguments. This
432
// function is functionally equivalent to `std::fprintf()` (and type-safe);
433
// prefer `absl::FPrintF()` over `std::fprintf()`.
434
//
435
// Example:
436
//
437
//   std::string_view s = "Ulaanbaatar";
438
//   absl::FPrintF(stdout, "The capital of Mongolia is %s", s);
439
//
440
//   Outputs: "The capital of Mongolia is Ulaanbaatar"
441
//
442
template <typename... Args>
443
int FPrintF(std::FILE* absl_nonnull output, const FormatSpec<Args...>& format,
444
            const Args&... args) {
445
  return str_format_internal::FprintF(
446
      output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
447
      {str_format_internal::FormatArgImpl(args)...});
448
}
449
450
// SNPrintF()
451
//
452
// Writes to a sized buffer given a format string and zero or more arguments.
453
// This function is functionally equivalent to `std::snprintf()` (and
454
// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
455
//
456
// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
457
// bytes of the formatted output to `output`, including a NUL-terminator, and
458
// returns the number of bytes that would have been written if truncation did
459
// not occur. In the event of an error, a negative value is returned and `errno`
460
// is set.
461
//
462
// Example:
463
//
464
//   std::string_view s = "Ulaanbaatar";
465
//   char output[128];
466
//   absl::SNPrintF(output, sizeof(output),
467
//                  "The capital of Mongolia is %s", s);
468
//
469
//   Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
470
//
471
template <typename... Args>
472
int SNPrintF(char* absl_nonnull output, std::size_t size,
473
0
             const FormatSpec<Args...>& format, const Args&... args) {
474
0
  return str_format_internal::SnprintF(
475
0
      output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
476
0
      {str_format_internal::FormatArgImpl(args)...});
477
0
}
478
479
// -----------------------------------------------------------------------------
480
// Custom Output Formatting Functions
481
// -----------------------------------------------------------------------------
482
483
// FormatRawSink
484
//
485
// FormatRawSink is a type erased wrapper around arbitrary sink objects
486
// specifically used as an argument to `Format()`.
487
//
488
// All the object has to do define an overload of `AbslFormatFlush()` for the
489
// sink, usually by adding a ADL-based free function in the same namespace as
490
// the sink:
491
//
492
//   void AbslFormatFlush(MySink* dest, absl::string_view part);
493
//
494
// where `dest` is the pointer passed to `absl::Format()`. The function should
495
// append `part` to `dest`.
496
//
497
// FormatRawSink does not own the passed sink object. The passed object must
498
// outlive the FormatRawSink.
499
class FormatRawSink {
500
 public:
501
  // Implicitly convert from any type that provides the hook function as
502
  // described above.
503
  template <typename T,
504
            typename = typename std::enable_if<std::is_constructible<
505
                str_format_internal::FormatRawSinkImpl, T*>::value>::type>
506
  FormatRawSink(T* absl_nonnull raw)  // NOLINT
507
      : sink_(raw) {}
508
509
 private:
510
  friend str_format_internal::FormatRawSinkImpl;
511
  str_format_internal::FormatRawSinkImpl sink_;
512
};
513
514
// Format()
515
//
516
// Writes a formatted string to an arbitrary sink object (implementing the
517
// `absl::FormatRawSink` interface), using a format string and zero or more
518
// additional arguments.
519
//
520
// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
521
// destination objects. If a `std::string` is used the formatted string is
522
// appended to it.
523
//
524
// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
525
// custom sinks. The format string, like format strings for `StrFormat()`, is
526
// checked at compile-time.
527
//
528
// On failure, this function returns `false` and the state of the sink is
529
// unspecified.
530
template <typename... Args>
531
bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,
532
            const Args&... args) {
533
  return str_format_internal::FormatUntyped(
534
      str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
535
      str_format_internal::UntypedFormatSpecImpl::Extract(format),
536
      {str_format_internal::FormatArgImpl(args)...});
537
}
538
539
// FormatArg
540
//
541
// A type-erased handle to a format argument specifically used as an argument to
542
// `FormatUntyped()`. You may construct `FormatArg` by passing
543
// reference-to-const of any printable type. `FormatArg` is both copyable and
544
// assignable. The source data must outlive the `FormatArg` instance. See
545
// example below.
546
//
547
using FormatArg = str_format_internal::FormatArgImpl;
548
549
// FormatUntyped()
550
//
551
// Writes a formatted string to an arbitrary sink object (implementing the
552
// `absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or
553
// more additional arguments.
554
//
555
// This function acts as the most generic formatting function in the
556
// `str_format` library. The caller provides a raw sink, an unchecked format
557
// string, and (usually) a runtime specified list of arguments; no compile-time
558
// checking of formatting is performed within this function. As a result, a
559
// caller should check the return value to verify that no error occurred.
560
// On failure, this function returns `false` and the state of the sink is
561
// unspecified.
562
//
563
// The arguments are provided in an `absl::Span<const absl::FormatArg>`.
564
// Each `absl::FormatArg` object binds to a single argument and keeps a
565
// reference to it. The values used to create the `FormatArg` objects must
566
// outlive this function call.
567
//
568
// Example:
569
//
570
//   std::optional<std::string> FormatDynamic(
571
//       const std::string& in_format,
572
//       const vector<std::string>& in_args) {
573
//     std::string out;
574
//     std::vector<absl::FormatArg> args;
575
//     for (const auto& v : in_args) {
576
//       // It is important that 'v' is a reference to the objects in in_args.
577
//       // The values we pass to FormatArg must outlive the call to
578
//       // FormatUntyped.
579
//       args.emplace_back(v);
580
//     }
581
//     absl::UntypedFormatSpec format(in_format);
582
//     if (!absl::FormatUntyped(&out, format, args)) {
583
//       return std::nullopt;
584
//     }
585
//     return std::move(out);
586
//   }
587
//
588
[[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,
589
                                        const UntypedFormatSpec& format,
590
0
                                        absl::Span<const FormatArg> args) {
591
0
  return str_format_internal::FormatUntyped(
592
0
      str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
593
0
      str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
594
0
}
595
596
//------------------------------------------------------------------------------
597
// StrFormat Extensions
598
//------------------------------------------------------------------------------
599
//
600
// AbslStringify()
601
//
602
// A simpler customization API for formatting user-defined types using
603
// absl::StrFormat(). The API relies on detecting an overload in the
604
// user-defined type's namespace of a free (non-member) `AbslStringify()`
605
// function as a friend definition with the following signature:
606
//
607
// template <typename Sink>
608
// void AbslStringify(Sink& sink, const X& value);
609
//
610
// An `AbslStringify()` overload for a type should only be declared in the same
611
// file and namespace as said type.
612
//
613
// Note that unlike with AbslFormatConvert(), AbslStringify() does not allow
614
// customization of allowed conversion characters. AbslStringify() uses `%v` as
615
// the underlying conversion specifier. Additionally, AbslStringify() supports
616
// use with absl::StrCat while AbslFormatConvert() does not.
617
//
618
// Example:
619
//
620
// struct Point {
621
//   // To add formatting support to `Point`, we simply need to add a free
622
//   // (non-member) function `AbslStringify()`. This method prints in the
623
//   // request format using the underlying `%v` specifier. You can add such a
624
//   // free function using a friend declaration within the body of the class.
625
//   // The sink parameter is a templated type to avoid requiring dependencies.
626
//   template <typename Sink>
627
//   friend void AbslStringify(Sink& sink, const Point& p) {
628
//     absl::Format(&sink, "(%v, %v)", p.x, p.y);
629
//   }
630
//
631
//   int x;
632
//   int y;
633
// };
634
//
635
// AbslFormatConvert()
636
//
637
// The StrFormat library provides a customization API for formatting
638
// user-defined types using absl::StrFormat(). The API relies on detecting an
639
// overload in the user-defined type's namespace of a free (non-member)
640
// `AbslFormatConvert()` function, usually as a friend definition with the
641
// following signature:
642
//
643
// absl::FormatConvertResult<...> AbslFormatConvert(
644
//     const X& value,
645
//     const absl::FormatConversionSpec& spec,
646
//     absl::FormatSink *sink);
647
//
648
// An `AbslFormatConvert()` overload for a type should only be declared in the
649
// same file and namespace as said type.
650
//
651
// The abstractions within this definition include:
652
//
653
// * An `absl::FormatConversionSpec` to specify the fields to pull from a
654
//   user-defined type's format string
655
// * An `absl::FormatSink` to hold the converted string data during the
656
//   conversion process.
657
// * An `absl::FormatConvertResult` to hold the status of the returned
658
//   formatting operation
659
//
660
// The return type encodes all the conversion characters that your
661
// AbslFormatConvert() routine accepts.  The return value should be {true}.
662
// A return value of {false} will result in `StrFormat()` returning
663
// an empty string.  This result will be propagated to the result of
664
// `FormatUntyped`.
665
//
666
// Example:
667
//
668
// struct Point {
669
//   // To add formatting support to `Point`, we simply need to add a free
670
//   // (non-member) function `AbslFormatConvert()`.  This method interprets
671
//   // `spec` to print in the request format. The allowed conversion characters
672
//   // can be restricted via the type of the result, in this example
673
//   // string and integral formatting are allowed (but not, for instance
674
//   // floating point characters like "%f").  You can add such a free function
675
//   // using a friend declaration within the body of the class:
676
//   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
677
//                                    absl::FormatConversionCharSet::kIntegral>
678
//   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
679
//                     absl::FormatSink* s) {
680
//     if (spec.conversion_char() == absl::FormatConversionChar::s) {
681
//       absl::Format(s, "x=%vy=%v", p.x, p.y);
682
//     } else {
683
//       absl::Format(s, "%v,%v", p.x, p.y);
684
//     }
685
//     return {true};
686
//   }
687
//
688
//   int x;
689
//   int y;
690
// };
691
692
// clang-format off
693
694
// FormatConversionChar
695
//
696
// Specifies the formatting character provided in the format string
697
// passed to `StrFormat()`.
698
enum class FormatConversionChar : uint8_t {
699
  c, s,                    // text
700
  d, i, o, u, x, X,        // int
701
  f, F, e, E, g, G, a, A,  // float
702
  n, p, v                  // misc
703
};
704
// clang-format on
705
706
// FormatConversionSpec
707
//
708
// Specifies modifications to the conversion of the format string, through use
709
// of one or more format flags in the source format string.
710
class FormatConversionSpec {
711
 public:
712
  // FormatConversionSpec::is_basic()
713
  //
714
  // Indicates that width and precision are not specified, and no additional
715
  // flags are set for this conversion character in the format string.
716
0
  bool is_basic() const { return impl_.is_basic(); }
717
718
  // FormatConversionSpec::has_left_flag()
719
  //
720
  // Indicates whether the result should be left justified for this conversion
721
  // character in the format string. This flag is set through use of a '-'
722
  // character in the format string. E.g. "%-s"
723
0
  bool has_left_flag() const { return impl_.has_left_flag(); }
724
725
  // FormatConversionSpec::has_show_pos_flag()
726
  //
727
  // Indicates whether a sign column is prepended to the result for this
728
  // conversion character in the format string, even if the result is positive.
729
  // This flag is set through use of a '+' character in the format string.
730
  // E.g. "%+d"
731
0
  bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
732
733
  // FormatConversionSpec::has_sign_col_flag()
734
  //
735
  // Indicates whether a mandatory sign column is added to the result for this
736
  // conversion character. This flag is set through use of a space character
737
  // (' ') in the format string. E.g. "% i"
738
0
  bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
739
740
  // FormatConversionSpec::has_alt_flag()
741
  //
742
  // Indicates whether an "alternate" format is applied to the result for this
743
  // conversion character. Alternative forms depend on the type of conversion
744
  // character, and unallowed alternatives are undefined. This flag is set
745
  // through use of a '#' character in the format string. E.g. "%#h"
746
0
  bool has_alt_flag() const { return impl_.has_alt_flag(); }
747
748
  // FormatConversionSpec::has_zero_flag()
749
  //
750
  // Indicates whether zeroes should be prepended to the result for this
751
  // conversion character instead of spaces. This flag is set through use of the
752
  // '0' character in the format string. E.g. "%0f"
753
0
  bool has_zero_flag() const { return impl_.has_zero_flag(); }
754
755
  // FormatConversionSpec::conversion_char()
756
  //
757
  // Returns the underlying conversion character.
758
0
  FormatConversionChar conversion_char() const {
759
0
    return impl_.conversion_char();
760
0
  }
761
762
  // FormatConversionSpec::width()
763
  //
764
  // Returns the specified width (indicated through use of a non-zero integer
765
  // value or '*' character) of the conversion character. If width is
766
  // unspecified, it returns a negative value.
767
0
  int width() const { return impl_.width(); }
768
769
  // FormatConversionSpec::precision()
770
  //
771
  // Returns the specified precision (through use of the '.' character followed
772
  // by a non-zero integer value or '*' character) of the conversion character.
773
  // If precision is unspecified, it returns a negative value.
774
0
  int precision() const { return impl_.precision(); }
775
776
 private:
777
  explicit FormatConversionSpec(
778
      str_format_internal::FormatConversionSpecImpl impl)
779
0
      : impl_(impl) {}
780
781
  friend str_format_internal::FormatConversionSpecImpl;
782
783
  absl::str_format_internal::FormatConversionSpecImpl impl_;
784
};
785
786
// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
787
// conversion chars in custom format converters.
788
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
789
0
                                            FormatConversionCharSet b) {
790
0
  return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
791
0
                                              static_cast<uint64_t>(b));
792
0
}
793
794
// FormatConversionCharSet
795
//
796
// Specifies the _accepted_ conversion types as a template parameter to
797
// FormatConvertResult for custom implementations of `AbslFormatConvert`.
798
// Note the helper predefined alias definitions (kIntegral, etc.) below.
799
enum class FormatConversionCharSet : uint64_t {
800
  // text
801
  c = str_format_internal::FormatConversionCharToConvInt('c'),
802
  s = str_format_internal::FormatConversionCharToConvInt('s'),
803
  // integer
804
  d = str_format_internal::FormatConversionCharToConvInt('d'),
805
  i = str_format_internal::FormatConversionCharToConvInt('i'),
806
  o = str_format_internal::FormatConversionCharToConvInt('o'),
807
  u = str_format_internal::FormatConversionCharToConvInt('u'),
808
  x = str_format_internal::FormatConversionCharToConvInt('x'),
809
  X = str_format_internal::FormatConversionCharToConvInt('X'),
810
  // Float
811
  f = str_format_internal::FormatConversionCharToConvInt('f'),
812
  F = str_format_internal::FormatConversionCharToConvInt('F'),
813
  e = str_format_internal::FormatConversionCharToConvInt('e'),
814
  E = str_format_internal::FormatConversionCharToConvInt('E'),
815
  g = str_format_internal::FormatConversionCharToConvInt('g'),
816
  G = str_format_internal::FormatConversionCharToConvInt('G'),
817
  a = str_format_internal::FormatConversionCharToConvInt('a'),
818
  A = str_format_internal::FormatConversionCharToConvInt('A'),
819
  // misc
820
  n = str_format_internal::FormatConversionCharToConvInt('n'),
821
  p = str_format_internal::FormatConversionCharToConvInt('p'),
822
  v = str_format_internal::FormatConversionCharToConvInt('v'),
823
824
  // Used for width/precision '*' specification.
825
  kStar = static_cast<uint64_t>(
826
      absl::str_format_internal::FormatConversionCharSetInternal::kStar),
827
  // Some predefined values:
828
  kIntegral = d | i | u | o | x | X,
829
  kFloating = a | e | f | g | A | E | F | G,
830
  kNumeric = kIntegral | kFloating,
831
  kString = s,
832
  kPointer = p,
833
};
834
835
// FormatSink
836
//
837
// A format sink is a generic abstraction to which conversions may write their
838
// formatted string data. `absl::FormatConvert()` uses this sink to write its
839
// formatted string.
840
//
841
class FormatSink {
842
 public:
843
  // FormatSink::Append()
844
  //
845
  // Appends `count` copies of `ch` to the format sink.
846
0
  void Append(size_t count, char ch) { sink_->Append(count, ch); }
847
848
  // Overload of FormatSink::Append() for appending the characters of a string
849
  // view to a format sink.
850
0
  void Append(string_view v) { sink_->Append(v); }
851
852
  // FormatSink::PutPaddedString()
853
  //
854
  // Appends `precision` number of bytes of `v` to the format sink. If this is
855
  // less than `width`, spaces will be appended first (if `left` is false), or
856
  // after (if `left` is true) to ensure the total amount appended is
857
  // at least `width`.
858
0
  bool PutPaddedString(string_view v, int width, int precision, bool left) {
859
0
    return sink_->PutPaddedString(v, width, precision, left);
860
0
  }
861
862
  // Support `absl::Format(&sink, format, args...)`.
863
  friend void AbslFormatFlush(FormatSink* absl_nonnull sink,
864
0
                              absl::string_view v) {
865
0
    sink->Append(v);
866
0
  }
867
868
 private:
869
  friend str_format_internal::FormatSinkImpl;
870
  explicit FormatSink(str_format_internal::FormatSinkImpl* absl_nonnull s)
871
0
      : sink_(s) {}
872
  str_format_internal::FormatSinkImpl* absl_nonnull sink_;
873
};
874
875
// FormatConvertResult
876
//
877
// Indicates whether a call to AbslFormatConvert() was successful.
878
// This return type informs the StrFormat extension framework (through
879
// ADL but using the return type) of what conversion characters are supported.
880
// It is strongly discouraged to return {false}, as this will result in an
881
// empty string in StrFormat.
882
template <FormatConversionCharSet C>
883
struct FormatConvertResult {
884
  bool value;
885
};
886
887
ABSL_NAMESPACE_END
888
}  // namespace absl
889
890
#endif  // ABSL_STRINGS_STR_FORMAT_H_