Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:41:04

0001 //
0002 // Copyright 2017 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 //
0016 // -----------------------------------------------------------------------------
0017 // File: substitute.h
0018 // -----------------------------------------------------------------------------
0019 //
0020 // This package contains functions for efficiently performing string
0021 // substitutions using a format string with positional notation:
0022 // `Substitute()` and `SubstituteAndAppend()`.
0023 //
0024 // Unlike printf-style format specifiers, `Substitute()` functions do not need
0025 // to specify the type of the substitution arguments. Supported arguments
0026 // following the format string, such as strings, string_views, ints,
0027 // floats, and bools, are automatically converted to strings during the
0028 // substitution process. (See below for a full list of supported types.)
0029 //
0030 // `Substitute()` does not allow you to specify *how* to format a value, beyond
0031 // the default conversion to string. For example, you cannot format an integer
0032 // in hex.
0033 //
0034 // The format string uses positional identifiers indicated by a dollar sign ($)
0035 // and single digit positional ids to indicate which substitution arguments to
0036 // use at that location within the format string.
0037 //
0038 // A '$$' sequence in the format string causes a literal '$' character to be
0039 // output.
0040 //
0041 // Example 1:
0042 //   std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!",
0043 //                              5, "Bob", "Apples");
0044 //   EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
0045 //
0046 // Example 2:
0047 //   std::string s = "Hi. ";
0048 //   SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
0049 //   EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
0050 //
0051 // Supported types:
0052 //   * absl::string_view, std::string, const char* (null is equivalent to "")
0053 //   * int32_t, int64_t, uint32_t, uint64_t
0054 //   * float, double
0055 //   * bool (Printed as "true" or "false")
0056 //   * pointer types other than char* (Printed as "0x<lower case hex string>",
0057 //     except that null is printed as "NULL")
0058 //   * user-defined types via the `AbslStringify()` customization point. See the
0059 //     documentation for `absl::StrCat` for an explanation on how to use this.
0060 //
0061 // If an invalid format string is provided, Substitute returns an empty string
0062 // and SubstituteAndAppend does not change the provided output string.
0063 // A format string is invalid if it:
0064 //   * ends in an unescaped $ character,
0065 //     e.g. "Hello $", or
0066 //   * calls for a position argument which is not provided,
0067 //     e.g. Substitute("Hello $2", "world"), or
0068 //   * specifies a non-digit, non-$ character after an unescaped $ character,
0069 //     e.g. "Hello $f".
0070 // In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program.
0071 
0072 #ifndef ABSL_STRINGS_SUBSTITUTE_H_
0073 #define ABSL_STRINGS_SUBSTITUTE_H_
0074 
0075 #include <cstring>
0076 #include <string>
0077 #include <type_traits>
0078 #include <vector>
0079 
0080 #include "absl/base/macros.h"
0081 #include "absl/base/nullability.h"
0082 #include "absl/base/port.h"
0083 #include "absl/strings/ascii.h"
0084 #include "absl/strings/escaping.h"
0085 #include "absl/strings/internal/stringify_sink.h"
0086 #include "absl/strings/numbers.h"
0087 #include "absl/strings/str_cat.h"
0088 #include "absl/strings/str_split.h"
0089 #include "absl/strings/string_view.h"
0090 #include "absl/strings/strip.h"
0091 
0092 namespace absl {
0093 ABSL_NAMESPACE_BEGIN
0094 namespace substitute_internal {
0095 
0096 // Arg
0097 //
0098 // This class provides an argument type for `absl::Substitute()` and
0099 // `absl::SubstituteAndAppend()`. `Arg` handles implicit conversion of various
0100 // types to a string. (`Arg` is very similar to the `AlphaNum` class in
0101 // `StrCat()`.)
0102 //
0103 // This class has implicit constructors.
0104 class Arg {
0105  public:
0106   // Overloads for string-y things
0107   //
0108   // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
0109   Arg(absl::Nullable<const char*> value)  // NOLINT(google-explicit-constructor)
0110       : piece_(absl::NullSafeStringView(value)) {}
0111   template <typename Allocator>
0112   Arg(  // NOLINT
0113       const std::basic_string<char, std::char_traits<char>, Allocator>&
0114           value) noexcept
0115       : piece_(value) {}
0116   Arg(absl::string_view value)  // NOLINT(google-explicit-constructor)
0117       : piece_(value) {}
0118 
0119   // Overloads for primitives
0120   //
0121   // No overloads are available for signed and unsigned char because if people
0122   // are explicitly declaring their chars as signed or unsigned then they are
0123   // probably using them as 8-bit integers and would probably prefer an integer
0124   // representation. However, we can't really know, so we make the caller decide
0125   // what to do.
0126   Arg(char value)  // NOLINT(google-explicit-constructor)
0127       : piece_(scratch_, 1) {
0128     scratch_[0] = value;
0129   }
0130   Arg(short value)  // NOLINT(*)
0131       : piece_(scratch_,
0132                static_cast<size_t>(
0133                    numbers_internal::FastIntToBuffer(value, scratch_) -
0134                    scratch_)) {}
0135   Arg(unsigned short value)  // NOLINT(*)
0136       : piece_(scratch_,
0137                static_cast<size_t>(
0138                    numbers_internal::FastIntToBuffer(value, scratch_) -
0139                    scratch_)) {}
0140   Arg(int value)  // NOLINT(google-explicit-constructor)
0141       : piece_(scratch_,
0142                static_cast<size_t>(
0143                    numbers_internal::FastIntToBuffer(value, scratch_) -
0144                    scratch_)) {}
0145   Arg(unsigned int value)  // NOLINT(google-explicit-constructor)
0146       : piece_(scratch_,
0147                static_cast<size_t>(
0148                    numbers_internal::FastIntToBuffer(value, scratch_) -
0149                    scratch_)) {}
0150   Arg(long value)  // NOLINT(*)
0151       : piece_(scratch_,
0152                static_cast<size_t>(
0153                    numbers_internal::FastIntToBuffer(value, scratch_) -
0154                    scratch_)) {}
0155   Arg(unsigned long value)  // NOLINT(*)
0156       : piece_(scratch_,
0157                static_cast<size_t>(
0158                    numbers_internal::FastIntToBuffer(value, scratch_) -
0159                    scratch_)) {}
0160   Arg(long long value)  // NOLINT(*)
0161       : piece_(scratch_,
0162                static_cast<size_t>(
0163                    numbers_internal::FastIntToBuffer(value, scratch_) -
0164                    scratch_)) {}
0165   Arg(unsigned long long value)  // NOLINT(*)
0166       : piece_(scratch_,
0167                static_cast<size_t>(
0168                    numbers_internal::FastIntToBuffer(value, scratch_) -
0169                    scratch_)) {}
0170   Arg(float value)  // NOLINT(google-explicit-constructor)
0171       : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
0172   }
0173   Arg(double value)  // NOLINT(google-explicit-constructor)
0174       : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
0175   }
0176   Arg(bool value)  // NOLINT(google-explicit-constructor)
0177       : piece_(value ? "true" : "false") {}
0178 
0179   template <typename T, typename = typename std::enable_if<
0180                             HasAbslStringify<T>::value>::type>
0181   Arg(  // NOLINT(google-explicit-constructor)
0182       const T& v, strings_internal::StringifySink&& sink = {})
0183       : piece_(strings_internal::ExtractStringification(sink, v)) {}
0184 
0185   Arg(Hex hex);  // NOLINT(google-explicit-constructor)
0186   Arg(Dec dec);  // NOLINT(google-explicit-constructor)
0187 
0188   // vector<bool>::reference and const_reference require special help to convert
0189   // to `Arg` because it requires two user defined conversions.
0190   template <typename T,
0191             absl::enable_if_t<
0192                 std::is_class<T>::value &&
0193                 (std::is_same<T, std::vector<bool>::reference>::value ||
0194                  std::is_same<T, std::vector<bool>::const_reference>::value)>* =
0195                 nullptr>
0196   Arg(T value)  // NOLINT(google-explicit-constructor)
0197       : Arg(static_cast<bool>(value)) {}
0198 
0199   // `void*` values, with the exception of `char*`, are printed as
0200   // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
0201   Arg(  // NOLINT(google-explicit-constructor)
0202       absl::Nullable<const void*> value);
0203 
0204   // Normal enums are already handled by the integer formatters.
0205   // This overload matches only scoped enums.
0206   template <typename T,
0207             typename = typename std::enable_if<
0208                 std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
0209                 !HasAbslStringify<T>::value>::type>
0210   Arg(T value)  // NOLINT(google-explicit-constructor)
0211       : Arg(static_cast<typename std::underlying_type<T>::type>(value)) {}
0212 
0213   Arg(const Arg&) = delete;
0214   Arg& operator=(const Arg&) = delete;
0215 
0216   absl::string_view piece() const { return piece_; }
0217 
0218  private:
0219   absl::string_view piece_;
0220   char scratch_[numbers_internal::kFastToBufferSize];
0221 };
0222 
0223 // Internal helper function. Don't call this from outside this implementation.
0224 // This interface may change without notice.
0225 void SubstituteAndAppendArray(
0226     absl::Nonnull<std::string*> output, absl::string_view format,
0227     absl::Nullable<const absl::string_view*> args_array, size_t num_args);
0228 
0229 #if defined(ABSL_BAD_CALL_IF)
0230 constexpr int CalculateOneBit(absl::Nonnull<const char*> format) {
0231   // Returns:
0232   // * 2^N for '$N' when N is in [0-9]
0233   // * 0 for correct '$' escaping: '$$'.
0234   // * -1 otherwise.
0235   return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
0236                                           : (1 << (*format - '0'));
0237 }
0238 
0239 constexpr const char* SkipNumber(absl::Nonnull<const char*> format) {
0240   return !*format ? format : (format + 1);
0241 }
0242 
0243 constexpr int PlaceholderBitmask(absl::Nonnull<const char*> format) {
0244   return !*format
0245              ? 0
0246              : *format != '$' ? PlaceholderBitmask(format + 1)
0247                               : (CalculateOneBit(format + 1) |
0248                                  PlaceholderBitmask(SkipNumber(format + 1)));
0249 }
0250 #endif  // ABSL_BAD_CALL_IF
0251 
0252 }  // namespace substitute_internal
0253 
0254 //
0255 // PUBLIC API
0256 //
0257 
0258 // SubstituteAndAppend()
0259 //
0260 // Substitutes variables into a given format string and appends to a given
0261 // output string. See file comments above for usage.
0262 //
0263 // The declarations of `SubstituteAndAppend()` below consist of overloads
0264 // for passing 0 to 10 arguments, respectively.
0265 //
0266 // NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic
0267 // templates to allow a variable number of arguments.
0268 //
0269 // Example:
0270 //  template <typename... Args>
0271 //  void VarMsg(std::string* boilerplate, absl::string_view format,
0272 //      const Args&... args) {
0273 //    absl::SubstituteAndAppend(boilerplate, format, args...);
0274 //  }
0275 //
0276 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0277                                 absl::string_view format) {
0278   substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
0279 }
0280 
0281 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0282                                 absl::string_view format,
0283                                 const substitute_internal::Arg& a0) {
0284   const absl::string_view args[] = {a0.piece()};
0285   substitute_internal::SubstituteAndAppendArray(output, format, args,
0286                                                 ABSL_ARRAYSIZE(args));
0287 }
0288 
0289 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0290                                 absl::string_view format,
0291                                 const substitute_internal::Arg& a0,
0292                                 const substitute_internal::Arg& a1) {
0293   const absl::string_view args[] = {a0.piece(), a1.piece()};
0294   substitute_internal::SubstituteAndAppendArray(output, format, args,
0295                                                 ABSL_ARRAYSIZE(args));
0296 }
0297 
0298 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0299                                 absl::string_view format,
0300                                 const substitute_internal::Arg& a0,
0301                                 const substitute_internal::Arg& a1,
0302                                 const substitute_internal::Arg& a2) {
0303   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece()};
0304   substitute_internal::SubstituteAndAppendArray(output, format, args,
0305                                                 ABSL_ARRAYSIZE(args));
0306 }
0307 
0308 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0309                                 absl::string_view format,
0310                                 const substitute_internal::Arg& a0,
0311                                 const substitute_internal::Arg& a1,
0312                                 const substitute_internal::Arg& a2,
0313                                 const substitute_internal::Arg& a3) {
0314   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0315                                     a3.piece()};
0316   substitute_internal::SubstituteAndAppendArray(output, format, args,
0317                                                 ABSL_ARRAYSIZE(args));
0318 }
0319 
0320 inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0321                                 absl::string_view format,
0322                                 const substitute_internal::Arg& a0,
0323                                 const substitute_internal::Arg& a1,
0324                                 const substitute_internal::Arg& a2,
0325                                 const substitute_internal::Arg& a3,
0326                                 const substitute_internal::Arg& a4) {
0327   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0328                                     a3.piece(), a4.piece()};
0329   substitute_internal::SubstituteAndAppendArray(output, format, args,
0330                                                 ABSL_ARRAYSIZE(args));
0331 }
0332 
0333 inline void SubstituteAndAppend(
0334     absl::Nonnull<std::string*> output, absl::string_view format,
0335     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0336     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0337     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) {
0338   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0339                                     a3.piece(), a4.piece(), a5.piece()};
0340   substitute_internal::SubstituteAndAppendArray(output, format, args,
0341                                                 ABSL_ARRAYSIZE(args));
0342 }
0343 
0344 inline void SubstituteAndAppend(
0345     absl::Nonnull<std::string*> output, absl::string_view format,
0346     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0347     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0348     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0349     const substitute_internal::Arg& a6) {
0350   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0351                                     a3.piece(), a4.piece(), a5.piece(),
0352                                     a6.piece()};
0353   substitute_internal::SubstituteAndAppendArray(output, format, args,
0354                                                 ABSL_ARRAYSIZE(args));
0355 }
0356 
0357 inline void SubstituteAndAppend(
0358     absl::Nonnull<std::string*> output, absl::string_view format,
0359     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0360     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0361     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0362     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) {
0363   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0364                                     a3.piece(), a4.piece(), a5.piece(),
0365                                     a6.piece(), a7.piece()};
0366   substitute_internal::SubstituteAndAppendArray(output, format, args,
0367                                                 ABSL_ARRAYSIZE(args));
0368 }
0369 
0370 inline void SubstituteAndAppend(
0371     absl::Nonnull<std::string*> output, absl::string_view format,
0372     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0373     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0374     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0375     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
0376     const substitute_internal::Arg& a8) {
0377   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
0378                                     a3.piece(), a4.piece(), a5.piece(),
0379                                     a6.piece(), a7.piece(), a8.piece()};
0380   substitute_internal::SubstituteAndAppendArray(output, format, args,
0381                                                 ABSL_ARRAYSIZE(args));
0382 }
0383 
0384 inline void SubstituteAndAppend(
0385     absl::Nonnull<std::string*> output, absl::string_view format,
0386     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0387     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0388     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0389     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
0390     const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) {
0391   const absl::string_view args[] = {
0392       a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(),
0393       a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()};
0394   substitute_internal::SubstituteAndAppendArray(output, format, args,
0395                                                 ABSL_ARRAYSIZE(args));
0396 }
0397 
0398 #if defined(ABSL_BAD_CALL_IF)
0399 // This body of functions catches cases where the number of placeholders
0400 // doesn't match the number of data arguments.
0401 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0402                          absl::Nonnull<const char*> format)
0403     ABSL_BAD_CALL_IF(
0404         substitute_internal::PlaceholderBitmask(format) != 0,
0405         "There were no substitution arguments "
0406         "but this format string either has a $[0-9] in it or contains "
0407         "an unescaped $ character (use $$ instead)");
0408 
0409 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0410                          absl::Nonnull<const char*> format,
0411                          const substitute_internal::Arg& a0)
0412     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
0413                      "There was 1 substitution argument given, but "
0414                      "this format string is missing its $0, contains "
0415                      "one of $1-$9, or contains an unescaped $ character (use "
0416                      "$$ instead)");
0417 
0418 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0419                          absl::Nonnull<const char*> format,
0420                          const substitute_internal::Arg& a0,
0421                          const substitute_internal::Arg& a1)
0422     ABSL_BAD_CALL_IF(
0423         substitute_internal::PlaceholderBitmask(format) != 3,
0424         "There were 2 substitution arguments given, but this format string is "
0425         "missing its $0/$1, contains one of $2-$9, or contains an "
0426         "unescaped $ character (use $$ instead)");
0427 
0428 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0429                          absl::Nonnull<const char*> format,
0430                          const substitute_internal::Arg& a0,
0431                          const substitute_internal::Arg& a1,
0432                          const substitute_internal::Arg& a2)
0433     ABSL_BAD_CALL_IF(
0434         substitute_internal::PlaceholderBitmask(format) != 7,
0435         "There were 3 substitution arguments given, but "
0436         "this format string is missing its $0/$1/$2, contains one of "
0437         "$3-$9, or contains an unescaped $ character (use $$ instead)");
0438 
0439 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0440                          absl::Nonnull<const char*> format,
0441                          const substitute_internal::Arg& a0,
0442                          const substitute_internal::Arg& a1,
0443                          const substitute_internal::Arg& a2,
0444                          const substitute_internal::Arg& a3)
0445     ABSL_BAD_CALL_IF(
0446         substitute_internal::PlaceholderBitmask(format) != 15,
0447         "There were 4 substitution arguments given, but "
0448         "this format string is missing its $0-$3, contains one of "
0449         "$4-$9, or contains an unescaped $ character (use $$ instead)");
0450 
0451 void SubstituteAndAppend(absl::Nonnull<std::string*> output,
0452                          absl::Nonnull<const char*> format,
0453                          const substitute_internal::Arg& a0,
0454                          const substitute_internal::Arg& a1,
0455                          const substitute_internal::Arg& a2,
0456                          const substitute_internal::Arg& a3,
0457                          const substitute_internal::Arg& a4)
0458     ABSL_BAD_CALL_IF(
0459         substitute_internal::PlaceholderBitmask(format) != 31,
0460         "There were 5 substitution arguments given, but "
0461         "this format string is missing its $0-$4, contains one of "
0462         "$5-$9, or contains an unescaped $ character (use $$ instead)");
0463 
0464 void SubstituteAndAppend(
0465     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
0466     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0467     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0468     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5)
0469     ABSL_BAD_CALL_IF(
0470         substitute_internal::PlaceholderBitmask(format) != 63,
0471         "There were 6 substitution arguments given, but "
0472         "this format string is missing its $0-$5, contains one of "
0473         "$6-$9, or contains an unescaped $ character (use $$ instead)");
0474 
0475 void SubstituteAndAppend(
0476     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
0477     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0478     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0479     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0480     const substitute_internal::Arg& a6)
0481     ABSL_BAD_CALL_IF(
0482         substitute_internal::PlaceholderBitmask(format) != 127,
0483         "There were 7 substitution arguments given, but "
0484         "this format string is missing its $0-$6, contains one of "
0485         "$7-$9, or contains an unescaped $ character (use $$ instead)");
0486 
0487 void SubstituteAndAppend(
0488     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
0489     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0490     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0491     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0492     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7)
0493     ABSL_BAD_CALL_IF(
0494         substitute_internal::PlaceholderBitmask(format) != 255,
0495         "There were 8 substitution arguments given, but "
0496         "this format string is missing its $0-$7, contains one of "
0497         "$8-$9, or contains an unescaped $ character (use $$ instead)");
0498 
0499 void SubstituteAndAppend(
0500     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
0501     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0502     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0503     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0504     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
0505     const substitute_internal::Arg& a8)
0506     ABSL_BAD_CALL_IF(
0507         substitute_internal::PlaceholderBitmask(format) != 511,
0508         "There were 9 substitution arguments given, but "
0509         "this format string is missing its $0-$8, contains a $9, or "
0510         "contains an unescaped $ character (use $$ instead)");
0511 
0512 void SubstituteAndAppend(
0513     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
0514     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
0515     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
0516     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
0517     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
0518     const substitute_internal::Arg& a8, const substitute_internal::Arg& a9)
0519     ABSL_BAD_CALL_IF(
0520         substitute_internal::PlaceholderBitmask(format) != 1023,
0521         "There were 10 substitution arguments given, but this "
0522         "format string either doesn't contain all of $0 through $9 or "
0523         "contains an unescaped $ character (use $$ instead)");
0524 #endif  // ABSL_BAD_CALL_IF
0525 
0526 // Substitute()
0527 //
0528 // Substitutes variables into a given format string. See file comments above
0529 // for usage.
0530 //
0531 // The declarations of `Substitute()` below consist of overloads for passing 0
0532 // to 10 arguments, respectively.
0533 //
0534 // NOTE: A zero-argument `Substitute()` may be used within variadic templates to
0535 // allow a variable number of arguments.
0536 //
0537 // Example:
0538 //  template <typename... Args>
0539 //  void VarMsg(absl::string_view format, const Args&... args) {
0540 //    std::string s = absl::Substitute(format, args...);
0541 
0542 ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
0543   std::string result;
0544   SubstituteAndAppend(&result, format);
0545   return result;
0546 }
0547 
0548 ABSL_MUST_USE_RESULT inline std::string Substitute(
0549     absl::string_view format, const substitute_internal::Arg& a0) {
0550   std::string result;
0551   SubstituteAndAppend(&result, format, a0);
0552   return result;
0553 }
0554 
0555 ABSL_MUST_USE_RESULT inline std::string Substitute(
0556     absl::string_view format, const substitute_internal::Arg& a0,
0557     const substitute_internal::Arg& a1) {
0558   std::string result;
0559   SubstituteAndAppend(&result, format, a0, a1);
0560   return result;
0561 }
0562 
0563 ABSL_MUST_USE_RESULT inline std::string Substitute(
0564     absl::string_view format, const substitute_internal::Arg& a0,
0565     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {
0566   std::string result;
0567   SubstituteAndAppend(&result, format, a0, a1, a2);
0568   return result;
0569 }
0570 
0571 ABSL_MUST_USE_RESULT inline std::string Substitute(
0572     absl::string_view format, const substitute_internal::Arg& a0,
0573     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0574     const substitute_internal::Arg& a3) {
0575   std::string result;
0576   SubstituteAndAppend(&result, format, a0, a1, a2, a3);
0577   return result;
0578 }
0579 
0580 ABSL_MUST_USE_RESULT inline std::string Substitute(
0581     absl::string_view format, const substitute_internal::Arg& a0,
0582     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0583     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {
0584   std::string result;
0585   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4);
0586   return result;
0587 }
0588 
0589 ABSL_MUST_USE_RESULT inline std::string Substitute(
0590     absl::string_view format, const substitute_internal::Arg& a0,
0591     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0592     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0593     const substitute_internal::Arg& a5) {
0594   std::string result;
0595   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5);
0596   return result;
0597 }
0598 
0599 ABSL_MUST_USE_RESULT inline std::string Substitute(
0600     absl::string_view format, const substitute_internal::Arg& a0,
0601     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0602     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0603     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) {
0604   std::string result;
0605   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6);
0606   return result;
0607 }
0608 
0609 ABSL_MUST_USE_RESULT inline std::string Substitute(
0610     absl::string_view format, const substitute_internal::Arg& a0,
0611     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0612     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0613     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0614     const substitute_internal::Arg& a7) {
0615   std::string result;
0616   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7);
0617   return result;
0618 }
0619 
0620 ABSL_MUST_USE_RESULT inline std::string Substitute(
0621     absl::string_view format, const substitute_internal::Arg& a0,
0622     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0623     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0624     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0625     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) {
0626   std::string result;
0627   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8);
0628   return result;
0629 }
0630 
0631 ABSL_MUST_USE_RESULT inline std::string Substitute(
0632     absl::string_view format, const substitute_internal::Arg& a0,
0633     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0634     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0635     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0636     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
0637     const substitute_internal::Arg& a9) {
0638   std::string result;
0639   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
0640   return result;
0641 }
0642 
0643 #if defined(ABSL_BAD_CALL_IF)
0644 // This body of functions catches cases where the number of placeholders
0645 // doesn't match the number of data arguments.
0646 std::string Substitute(absl::Nonnull<const char*> format)
0647     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
0648                      "There were no substitution arguments "
0649                      "but this format string either has a $[0-9] in it or "
0650                      "contains an unescaped $ character (use $$ instead)");
0651 
0652 std::string Substitute(absl::Nonnull<const char*> format,
0653                        const substitute_internal::Arg& a0)
0654     ABSL_BAD_CALL_IF(
0655         substitute_internal::PlaceholderBitmask(format) != 1,
0656         "There was 1 substitution argument given, but "
0657         "this format string is missing its $0, contains one of $1-$9, "
0658         "or contains an unescaped $ character (use $$ instead)");
0659 
0660 std::string Substitute(absl::Nonnull<const char*> format,
0661                        const substitute_internal::Arg& a0,
0662                        const substitute_internal::Arg& a1)
0663     ABSL_BAD_CALL_IF(
0664         substitute_internal::PlaceholderBitmask(format) != 3,
0665         "There were 2 substitution arguments given, but "
0666         "this format string is missing its $0/$1, contains one of "
0667         "$2-$9, or contains an unescaped $ character (use $$ instead)");
0668 
0669 std::string Substitute(absl::Nonnull<const char*> format,
0670                        const substitute_internal::Arg& a0,
0671                        const substitute_internal::Arg& a1,
0672                        const substitute_internal::Arg& a2)
0673     ABSL_BAD_CALL_IF(
0674         substitute_internal::PlaceholderBitmask(format) != 7,
0675         "There were 3 substitution arguments given, but "
0676         "this format string is missing its $0/$1/$2, contains one of "
0677         "$3-$9, or contains an unescaped $ character (use $$ instead)");
0678 
0679 std::string Substitute(absl::Nonnull<const char*> format,
0680                        const substitute_internal::Arg& a0,
0681                        const substitute_internal::Arg& a1,
0682                        const substitute_internal::Arg& a2,
0683                        const substitute_internal::Arg& a3)
0684     ABSL_BAD_CALL_IF(
0685         substitute_internal::PlaceholderBitmask(format) != 15,
0686         "There were 4 substitution arguments given, but "
0687         "this format string is missing its $0-$3, contains one of "
0688         "$4-$9, or contains an unescaped $ character (use $$ instead)");
0689 
0690 std::string Substitute(absl::Nonnull<const char*> format,
0691                        const substitute_internal::Arg& a0,
0692                        const substitute_internal::Arg& a1,
0693                        const substitute_internal::Arg& a2,
0694                        const substitute_internal::Arg& a3,
0695                        const substitute_internal::Arg& a4)
0696     ABSL_BAD_CALL_IF(
0697         substitute_internal::PlaceholderBitmask(format) != 31,
0698         "There were 5 substitution arguments given, but "
0699         "this format string is missing its $0-$4, contains one of "
0700         "$5-$9, or contains an unescaped $ character (use $$ instead)");
0701 
0702 std::string Substitute(absl::Nonnull<const char*> format,
0703                        const substitute_internal::Arg& a0,
0704                        const substitute_internal::Arg& a1,
0705                        const substitute_internal::Arg& a2,
0706                        const substitute_internal::Arg& a3,
0707                        const substitute_internal::Arg& a4,
0708                        const substitute_internal::Arg& a5)
0709     ABSL_BAD_CALL_IF(
0710         substitute_internal::PlaceholderBitmask(format) != 63,
0711         "There were 6 substitution arguments given, but "
0712         "this format string is missing its $0-$5, contains one of "
0713         "$6-$9, or contains an unescaped $ character (use $$ instead)");
0714 
0715 std::string Substitute(
0716     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
0717     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0718     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0719     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
0720     ABSL_BAD_CALL_IF(
0721         substitute_internal::PlaceholderBitmask(format) != 127,
0722         "There were 7 substitution arguments given, but "
0723         "this format string is missing its $0-$6, contains one of "
0724         "$7-$9, or contains an unescaped $ character (use $$ instead)");
0725 
0726 std::string Substitute(
0727     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
0728     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0729     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0730     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0731     const substitute_internal::Arg& a7)
0732     ABSL_BAD_CALL_IF(
0733         substitute_internal::PlaceholderBitmask(format) != 255,
0734         "There were 8 substitution arguments given, but "
0735         "this format string is missing its $0-$7, contains one of "
0736         "$8-$9, or contains an unescaped $ character (use $$ instead)");
0737 
0738 std::string Substitute(
0739     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
0740     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0741     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0742     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0743     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
0744     ABSL_BAD_CALL_IF(
0745         substitute_internal::PlaceholderBitmask(format) != 511,
0746         "There were 9 substitution arguments given, but "
0747         "this format string is missing its $0-$8, contains a $9, or "
0748         "contains an unescaped $ character (use $$ instead)");
0749 
0750 std::string Substitute(
0751     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
0752     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
0753     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
0754     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
0755     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
0756     const substitute_internal::Arg& a9)
0757     ABSL_BAD_CALL_IF(
0758         substitute_internal::PlaceholderBitmask(format) != 1023,
0759         "There were 10 substitution arguments given, but this "
0760         "format string either doesn't contain all of $0 through $9 or "
0761         "contains an unescaped $ character (use $$ instead)");
0762 #endif  // ABSL_BAD_CALL_IF
0763 
0764 ABSL_NAMESPACE_END
0765 }  // namespace absl
0766 
0767 #endif  // ABSL_STRINGS_SUBSTITUTE_H_