tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

str_format.h (36086B)


      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  explicit UntypedFormatSpec(string_view s) : spec_(s) {}
    112 
    113 protected:
    114  explicit UntypedFormatSpec(
    115      absl::Nonnull<const str_format_internal::ParsedFormatBase*> pc)
    116      : 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  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  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 [[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,
    363                                    const Args&... args) {
    364  return str_format_internal::FormatPack(
    365      str_format_internal::UntypedFormatSpecImpl::Extract(format),
    366      {str_format_internal::FormatArgImpl(args)...});
    367 }
    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 [[nodiscard]] 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 [[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,
    586                                        const UntypedFormatSpec& format,
    587                                        absl::Span<const FormatArg> args) {
    588  return str_format_internal::FormatUntyped(
    589      str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
    590      str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
    591 }
    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  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  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  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  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  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  bool has_zero_flag() const { return impl_.has_zero_flag(); }
    751 
    752  // FormatConversionSpec::conversion_char()
    753  //
    754  // Returns the underlying conversion character.
    755  FormatConversionChar conversion_char() const {
    756    return impl_.conversion_char();
    757  }
    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  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  int precision() const { return impl_.precision(); }
    772 
    773 private:
    774  explicit FormatConversionSpec(
    775      str_format_internal::FormatConversionSpecImpl impl)
    776      : 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                                            FormatConversionCharSet b) {
    787  return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
    788                                              static_cast<uint64_t>(b));
    789 }
    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  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  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  bool PutPaddedString(string_view v, int width, int precision, bool left) {
    856    return sink_->PutPaddedString(v, width, precision, left);
    857  }
    858 
    859  // Support `absl::Format(&sink, format, args...)`.
    860  friend void AbslFormatFlush(absl::Nonnull<FormatSink*> sink,
    861                              absl::string_view v) {
    862    sink->Append(v);
    863  }
    864 
    865 private:
    866  friend str_format_internal::FormatSinkImpl;
    867  explicit FormatSink(absl::Nonnull<str_format_internal::FormatSinkImpl*> s)
    868      : 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_