xref: /aosp_15_r20/external/abseil-cpp/absl/strings/substitute.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker //
16*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
17*9356374aSAndroid Build Coastguard Worker // File: substitute.h
18*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
19*9356374aSAndroid Build Coastguard Worker //
20*9356374aSAndroid Build Coastguard Worker // This package contains functions for efficiently performing string
21*9356374aSAndroid Build Coastguard Worker // substitutions using a format string with positional notation:
22*9356374aSAndroid Build Coastguard Worker // `Substitute()` and `SubstituteAndAppend()`.
23*9356374aSAndroid Build Coastguard Worker //
24*9356374aSAndroid Build Coastguard Worker // Unlike printf-style format specifiers, `Substitute()` functions do not need
25*9356374aSAndroid Build Coastguard Worker // to specify the type of the substitution arguments. Supported arguments
26*9356374aSAndroid Build Coastguard Worker // following the format string, such as strings, string_views, ints,
27*9356374aSAndroid Build Coastguard Worker // floats, and bools, are automatically converted to strings during the
28*9356374aSAndroid Build Coastguard Worker // substitution process. (See below for a full list of supported types.)
29*9356374aSAndroid Build Coastguard Worker //
30*9356374aSAndroid Build Coastguard Worker // `Substitute()` does not allow you to specify *how* to format a value, beyond
31*9356374aSAndroid Build Coastguard Worker // the default conversion to string. For example, you cannot format an integer
32*9356374aSAndroid Build Coastguard Worker // in hex.
33*9356374aSAndroid Build Coastguard Worker //
34*9356374aSAndroid Build Coastguard Worker // The format string uses positional identifiers indicated by a dollar sign ($)
35*9356374aSAndroid Build Coastguard Worker // and single digit positional ids to indicate which substitution arguments to
36*9356374aSAndroid Build Coastguard Worker // use at that location within the format string.
37*9356374aSAndroid Build Coastguard Worker //
38*9356374aSAndroid Build Coastguard Worker // A '$$' sequence in the format string causes a literal '$' character to be
39*9356374aSAndroid Build Coastguard Worker // output.
40*9356374aSAndroid Build Coastguard Worker //
41*9356374aSAndroid Build Coastguard Worker // Example 1:
42*9356374aSAndroid Build Coastguard Worker //   std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!",
43*9356374aSAndroid Build Coastguard Worker //                              5, "Bob", "Apples");
44*9356374aSAndroid Build Coastguard Worker //   EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
45*9356374aSAndroid Build Coastguard Worker //
46*9356374aSAndroid Build Coastguard Worker // Example 2:
47*9356374aSAndroid Build Coastguard Worker //   std::string s = "Hi. ";
48*9356374aSAndroid Build Coastguard Worker //   SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
49*9356374aSAndroid Build Coastguard Worker //   EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
50*9356374aSAndroid Build Coastguard Worker //
51*9356374aSAndroid Build Coastguard Worker // Supported types:
52*9356374aSAndroid Build Coastguard Worker //   * absl::string_view, std::string, const char* (null is equivalent to "")
53*9356374aSAndroid Build Coastguard Worker //   * int32_t, int64_t, uint32_t, uint64_t
54*9356374aSAndroid Build Coastguard Worker //   * float, double
55*9356374aSAndroid Build Coastguard Worker //   * bool (Printed as "true" or "false")
56*9356374aSAndroid Build Coastguard Worker //   * pointer types other than char* (Printed as "0x<lower case hex string>",
57*9356374aSAndroid Build Coastguard Worker //     except that null is printed as "NULL")
58*9356374aSAndroid Build Coastguard Worker //   * user-defined types via the `AbslStringify()` customization point. See the
59*9356374aSAndroid Build Coastguard Worker //     documentation for `absl::StrCat` for an explanation on how to use this.
60*9356374aSAndroid Build Coastguard Worker //
61*9356374aSAndroid Build Coastguard Worker // If an invalid format string is provided, Substitute returns an empty string
62*9356374aSAndroid Build Coastguard Worker // and SubstituteAndAppend does not change the provided output string.
63*9356374aSAndroid Build Coastguard Worker // A format string is invalid if it:
64*9356374aSAndroid Build Coastguard Worker //   * ends in an unescaped $ character,
65*9356374aSAndroid Build Coastguard Worker //     e.g. "Hello $", or
66*9356374aSAndroid Build Coastguard Worker //   * calls for a position argument which is not provided,
67*9356374aSAndroid Build Coastguard Worker //     e.g. Substitute("Hello $2", "world"), or
68*9356374aSAndroid Build Coastguard Worker //   * specifies a non-digit, non-$ character after an unescaped $ character,
69*9356374aSAndroid Build Coastguard Worker //     e.g. "Hello $f".
70*9356374aSAndroid Build Coastguard Worker // In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program.
71*9356374aSAndroid Build Coastguard Worker 
72*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_STRINGS_SUBSTITUTE_H_
73*9356374aSAndroid Build Coastguard Worker #define ABSL_STRINGS_SUBSTITUTE_H_
74*9356374aSAndroid Build Coastguard Worker 
75*9356374aSAndroid Build Coastguard Worker #include <cstring>
76*9356374aSAndroid Build Coastguard Worker #include <string>
77*9356374aSAndroid Build Coastguard Worker #include <type_traits>
78*9356374aSAndroid Build Coastguard Worker #include <vector>
79*9356374aSAndroid Build Coastguard Worker 
80*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
81*9356374aSAndroid Build Coastguard Worker #include "absl/base/nullability.h"
82*9356374aSAndroid Build Coastguard Worker #include "absl/base/port.h"
83*9356374aSAndroid Build Coastguard Worker #include "absl/strings/ascii.h"
84*9356374aSAndroid Build Coastguard Worker #include "absl/strings/escaping.h"
85*9356374aSAndroid Build Coastguard Worker #include "absl/strings/internal/stringify_sink.h"
86*9356374aSAndroid Build Coastguard Worker #include "absl/strings/numbers.h"
87*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
88*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_split.h"
89*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
90*9356374aSAndroid Build Coastguard Worker #include "absl/strings/strip.h"
91*9356374aSAndroid Build Coastguard Worker 
92*9356374aSAndroid Build Coastguard Worker namespace absl {
93*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
94*9356374aSAndroid Build Coastguard Worker namespace substitute_internal {
95*9356374aSAndroid Build Coastguard Worker 
96*9356374aSAndroid Build Coastguard Worker // Arg
97*9356374aSAndroid Build Coastguard Worker //
98*9356374aSAndroid Build Coastguard Worker // This class provides an argument type for `absl::Substitute()` and
99*9356374aSAndroid Build Coastguard Worker // `absl::SubstituteAndAppend()`. `Arg` handles implicit conversion of various
100*9356374aSAndroid Build Coastguard Worker // types to a string. (`Arg` is very similar to the `AlphaNum` class in
101*9356374aSAndroid Build Coastguard Worker // `StrCat()`.)
102*9356374aSAndroid Build Coastguard Worker //
103*9356374aSAndroid Build Coastguard Worker // This class has implicit constructors.
104*9356374aSAndroid Build Coastguard Worker class Arg {
105*9356374aSAndroid Build Coastguard Worker  public:
106*9356374aSAndroid Build Coastguard Worker   // Overloads for string-y things
107*9356374aSAndroid Build Coastguard Worker   //
108*9356374aSAndroid Build Coastguard Worker   // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(absl::Nullable<const char * > value)109*9356374aSAndroid Build Coastguard Worker   Arg(absl::Nullable<const char*> value)  // NOLINT(google-explicit-constructor)
110*9356374aSAndroid Build Coastguard Worker       : piece_(absl::NullSafeStringView(value)) {}
111*9356374aSAndroid Build Coastguard Worker   template <typename Allocator>
Arg(const std::basic_string<char,std::char_traits<char>,Allocator> & value)112*9356374aSAndroid Build Coastguard Worker   Arg(  // NOLINT
113*9356374aSAndroid Build Coastguard Worker       const std::basic_string<char, std::char_traits<char>, Allocator>&
114*9356374aSAndroid Build Coastguard Worker           value) noexcept
115*9356374aSAndroid Build Coastguard Worker       : piece_(value) {}
Arg(absl::string_view value)116*9356374aSAndroid Build Coastguard Worker   Arg(absl::string_view value)  // NOLINT(google-explicit-constructor)
117*9356374aSAndroid Build Coastguard Worker       : piece_(value) {}
118*9356374aSAndroid Build Coastguard Worker 
119*9356374aSAndroid Build Coastguard Worker   // Overloads for primitives
120*9356374aSAndroid Build Coastguard Worker   //
121*9356374aSAndroid Build Coastguard Worker   // No overloads are available for signed and unsigned char because if people
122*9356374aSAndroid Build Coastguard Worker   // are explicitly declaring their chars as signed or unsigned then they are
123*9356374aSAndroid Build Coastguard Worker   // probably using them as 8-bit integers and would probably prefer an integer
124*9356374aSAndroid Build Coastguard Worker   // representation. However, we can't really know, so we make the caller decide
125*9356374aSAndroid Build Coastguard Worker   // what to do.
Arg(char value)126*9356374aSAndroid Build Coastguard Worker   Arg(char value)  // NOLINT(google-explicit-constructor)
127*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_, 1) {
128*9356374aSAndroid Build Coastguard Worker     scratch_[0] = value;
129*9356374aSAndroid Build Coastguard Worker   }
Arg(short value)130*9356374aSAndroid Build Coastguard Worker   Arg(short value)  // NOLINT(*)
131*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
132*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
133*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
134*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(unsigned short value)135*9356374aSAndroid Build Coastguard Worker   Arg(unsigned short value)  // NOLINT(*)
136*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
137*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
138*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
139*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(int value)140*9356374aSAndroid Build Coastguard Worker   Arg(int value)  // NOLINT(google-explicit-constructor)
141*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
142*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
143*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
144*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(unsigned int value)145*9356374aSAndroid Build Coastguard Worker   Arg(unsigned int value)  // NOLINT(google-explicit-constructor)
146*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
147*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
148*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
149*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(long value)150*9356374aSAndroid Build Coastguard Worker   Arg(long value)  // NOLINT(*)
151*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
152*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
153*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
154*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(unsigned long value)155*9356374aSAndroid Build Coastguard Worker   Arg(unsigned long value)  // NOLINT(*)
156*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
157*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
158*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
159*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(long long value)160*9356374aSAndroid Build Coastguard Worker   Arg(long long value)  // NOLINT(*)
161*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
162*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
163*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
164*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(unsigned long long value)165*9356374aSAndroid Build Coastguard Worker   Arg(unsigned long long value)  // NOLINT(*)
166*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_,
167*9356374aSAndroid Build Coastguard Worker                static_cast<size_t>(
168*9356374aSAndroid Build Coastguard Worker                    numbers_internal::FastIntToBuffer(value, scratch_) -
169*9356374aSAndroid Build Coastguard Worker                    scratch_)) {}
Arg(float value)170*9356374aSAndroid Build Coastguard Worker   Arg(float value)  // NOLINT(google-explicit-constructor)
171*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
172*9356374aSAndroid Build Coastguard Worker   }
Arg(double value)173*9356374aSAndroid Build Coastguard Worker   Arg(double value)  // NOLINT(google-explicit-constructor)
174*9356374aSAndroid Build Coastguard Worker       : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
175*9356374aSAndroid Build Coastguard Worker   }
Arg(bool value)176*9356374aSAndroid Build Coastguard Worker   Arg(bool value)  // NOLINT(google-explicit-constructor)
177*9356374aSAndroid Build Coastguard Worker       : piece_(value ? "true" : "false") {}
178*9356374aSAndroid Build Coastguard Worker 
179*9356374aSAndroid Build Coastguard Worker   template <typename T, typename = typename std::enable_if<
180*9356374aSAndroid Build Coastguard Worker                             HasAbslStringify<T>::value>::type>
181*9356374aSAndroid Build Coastguard Worker   Arg(  // NOLINT(google-explicit-constructor)
182*9356374aSAndroid Build Coastguard Worker       const T& v, strings_internal::StringifySink&& sink = {})
piece_(strings_internal::ExtractStringification (sink,v))183*9356374aSAndroid Build Coastguard Worker       : piece_(strings_internal::ExtractStringification(sink, v)) {}
184*9356374aSAndroid Build Coastguard Worker 
185*9356374aSAndroid Build Coastguard Worker   Arg(Hex hex);  // NOLINT(google-explicit-constructor)
186*9356374aSAndroid Build Coastguard Worker   Arg(Dec dec);  // NOLINT(google-explicit-constructor)
187*9356374aSAndroid Build Coastguard Worker 
188*9356374aSAndroid Build Coastguard Worker   // vector<bool>::reference and const_reference require special help to convert
189*9356374aSAndroid Build Coastguard Worker   // to `Arg` because it requires two user defined conversions.
190*9356374aSAndroid Build Coastguard Worker   template <typename T,
191*9356374aSAndroid Build Coastguard Worker             absl::enable_if_t<
192*9356374aSAndroid Build Coastguard Worker                 std::is_class<T>::value &&
193*9356374aSAndroid Build Coastguard Worker                 (std::is_same<T, std::vector<bool>::reference>::value ||
194*9356374aSAndroid Build Coastguard Worker                  std::is_same<T, std::vector<bool>::const_reference>::value)>* =
195*9356374aSAndroid Build Coastguard Worker                 nullptr>
Arg(T value)196*9356374aSAndroid Build Coastguard Worker   Arg(T value)  // NOLINT(google-explicit-constructor)
197*9356374aSAndroid Build Coastguard Worker       : Arg(static_cast<bool>(value)) {}
198*9356374aSAndroid Build Coastguard Worker 
199*9356374aSAndroid Build Coastguard Worker   // `void*` values, with the exception of `char*`, are printed as
200*9356374aSAndroid Build Coastguard Worker   // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
201*9356374aSAndroid Build Coastguard Worker   Arg(  // NOLINT(google-explicit-constructor)
202*9356374aSAndroid Build Coastguard Worker       absl::Nullable<const void*> value);
203*9356374aSAndroid Build Coastguard Worker 
204*9356374aSAndroid Build Coastguard Worker   // Normal enums are already handled by the integer formatters.
205*9356374aSAndroid Build Coastguard Worker   // This overload matches only scoped enums.
206*9356374aSAndroid Build Coastguard Worker   template <typename T,
207*9356374aSAndroid Build Coastguard Worker             typename = typename std::enable_if<
208*9356374aSAndroid Build Coastguard Worker                 std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
209*9356374aSAndroid Build Coastguard Worker                 !HasAbslStringify<T>::value>::type>
210*9356374aSAndroid Build Coastguard Worker   Arg(T value)  // NOLINT(google-explicit-constructor)
211*9356374aSAndroid Build Coastguard Worker       : Arg(static_cast<typename std::underlying_type<T>::type>(value)) {}
212*9356374aSAndroid Build Coastguard Worker 
213*9356374aSAndroid Build Coastguard Worker   Arg(const Arg&) = delete;
214*9356374aSAndroid Build Coastguard Worker   Arg& operator=(const Arg&) = delete;
215*9356374aSAndroid Build Coastguard Worker 
piece()216*9356374aSAndroid Build Coastguard Worker   absl::string_view piece() const { return piece_; }
217*9356374aSAndroid Build Coastguard Worker 
218*9356374aSAndroid Build Coastguard Worker  private:
219*9356374aSAndroid Build Coastguard Worker   absl::string_view piece_;
220*9356374aSAndroid Build Coastguard Worker   char scratch_[numbers_internal::kFastToBufferSize];
221*9356374aSAndroid Build Coastguard Worker };
222*9356374aSAndroid Build Coastguard Worker 
223*9356374aSAndroid Build Coastguard Worker // Internal helper function. Don't call this from outside this implementation.
224*9356374aSAndroid Build Coastguard Worker // This interface may change without notice.
225*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppendArray(
226*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
227*9356374aSAndroid Build Coastguard Worker     absl::Nullable<const absl::string_view*> args_array, size_t num_args);
228*9356374aSAndroid Build Coastguard Worker 
229*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_BAD_CALL_IF)
CalculateOneBit(absl::Nonnull<const char * > format)230*9356374aSAndroid Build Coastguard Worker constexpr int CalculateOneBit(absl::Nonnull<const char*> format) {
231*9356374aSAndroid Build Coastguard Worker   // Returns:
232*9356374aSAndroid Build Coastguard Worker   // * 2^N for '$N' when N is in [0-9]
233*9356374aSAndroid Build Coastguard Worker   // * 0 for correct '$' escaping: '$$'.
234*9356374aSAndroid Build Coastguard Worker   // * -1 otherwise.
235*9356374aSAndroid Build Coastguard Worker   return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
236*9356374aSAndroid Build Coastguard Worker                                           : (1 << (*format - '0'));
237*9356374aSAndroid Build Coastguard Worker }
238*9356374aSAndroid Build Coastguard Worker 
SkipNumber(absl::Nonnull<const char * > format)239*9356374aSAndroid Build Coastguard Worker constexpr const char* SkipNumber(absl::Nonnull<const char*> format) {
240*9356374aSAndroid Build Coastguard Worker   return !*format ? format : (format + 1);
241*9356374aSAndroid Build Coastguard Worker }
242*9356374aSAndroid Build Coastguard Worker 
PlaceholderBitmask(absl::Nonnull<const char * > format)243*9356374aSAndroid Build Coastguard Worker constexpr int PlaceholderBitmask(absl::Nonnull<const char*> format) {
244*9356374aSAndroid Build Coastguard Worker   return !*format
245*9356374aSAndroid Build Coastguard Worker              ? 0
246*9356374aSAndroid Build Coastguard Worker              : *format != '$' ? PlaceholderBitmask(format + 1)
247*9356374aSAndroid Build Coastguard Worker                               : (CalculateOneBit(format + 1) |
248*9356374aSAndroid Build Coastguard Worker                                  PlaceholderBitmask(SkipNumber(format + 1)));
249*9356374aSAndroid Build Coastguard Worker }
250*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_BAD_CALL_IF
251*9356374aSAndroid Build Coastguard Worker 
252*9356374aSAndroid Build Coastguard Worker }  // namespace substitute_internal
253*9356374aSAndroid Build Coastguard Worker 
254*9356374aSAndroid Build Coastguard Worker //
255*9356374aSAndroid Build Coastguard Worker // PUBLIC API
256*9356374aSAndroid Build Coastguard Worker //
257*9356374aSAndroid Build Coastguard Worker 
258*9356374aSAndroid Build Coastguard Worker // SubstituteAndAppend()
259*9356374aSAndroid Build Coastguard Worker //
260*9356374aSAndroid Build Coastguard Worker // Substitutes variables into a given format string and appends to a given
261*9356374aSAndroid Build Coastguard Worker // output string. See file comments above for usage.
262*9356374aSAndroid Build Coastguard Worker //
263*9356374aSAndroid Build Coastguard Worker // The declarations of `SubstituteAndAppend()` below consist of overloads
264*9356374aSAndroid Build Coastguard Worker // for passing 0 to 10 arguments, respectively.
265*9356374aSAndroid Build Coastguard Worker //
266*9356374aSAndroid Build Coastguard Worker // NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic
267*9356374aSAndroid Build Coastguard Worker // templates to allow a variable number of arguments.
268*9356374aSAndroid Build Coastguard Worker //
269*9356374aSAndroid Build Coastguard Worker // Example:
270*9356374aSAndroid Build Coastguard Worker //  template <typename... Args>
271*9356374aSAndroid Build Coastguard Worker //  void VarMsg(std::string* boilerplate, absl::string_view format,
272*9356374aSAndroid Build Coastguard Worker //      const Args&... args) {
273*9356374aSAndroid Build Coastguard Worker //    absl::SubstituteAndAppend(boilerplate, format, args...);
274*9356374aSAndroid Build Coastguard Worker //  }
275*9356374aSAndroid Build Coastguard Worker //
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format)276*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
277*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format) {
278*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
279*9356374aSAndroid Build Coastguard Worker }
280*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0)281*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
282*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format,
283*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a0) {
284*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece()};
285*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
286*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
287*9356374aSAndroid Build Coastguard Worker }
288*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1)289*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
290*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format,
291*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a0,
292*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a1) {
293*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece()};
294*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
295*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
296*9356374aSAndroid Build Coastguard Worker }
297*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2)298*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
299*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format,
300*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a0,
301*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a1,
302*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a2) {
303*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece()};
304*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
305*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
306*9356374aSAndroid Build Coastguard Worker }
307*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3)308*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
309*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format,
310*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a0,
311*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a1,
312*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a2,
313*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a3) {
314*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
315*9356374aSAndroid Build Coastguard Worker                                     a3.piece()};
316*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
317*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
318*9356374aSAndroid Build Coastguard Worker }
319*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4)320*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
321*9356374aSAndroid Build Coastguard Worker                                 absl::string_view format,
322*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a0,
323*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a1,
324*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a2,
325*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a3,
326*9356374aSAndroid Build Coastguard Worker                                 const substitute_internal::Arg& a4) {
327*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
328*9356374aSAndroid Build Coastguard Worker                                     a3.piece(), a4.piece()};
329*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
330*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
331*9356374aSAndroid Build Coastguard Worker }
332*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5)333*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(
334*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
335*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
336*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
337*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) {
338*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
339*9356374aSAndroid Build Coastguard Worker                                     a3.piece(), a4.piece(), a5.piece()};
340*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
341*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
342*9356374aSAndroid Build Coastguard Worker }
343*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6)344*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(
345*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
346*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
347*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
348*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
349*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6) {
350*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
351*9356374aSAndroid Build Coastguard Worker                                     a3.piece(), a4.piece(), a5.piece(),
352*9356374aSAndroid Build Coastguard Worker                                     a6.piece()};
353*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
354*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
355*9356374aSAndroid Build Coastguard Worker }
356*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7)357*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(
358*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
359*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
360*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
361*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
362*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) {
363*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
364*9356374aSAndroid Build Coastguard Worker                                     a3.piece(), a4.piece(), a5.piece(),
365*9356374aSAndroid Build Coastguard Worker                                     a6.piece(), a7.piece()};
366*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
367*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
368*9356374aSAndroid Build Coastguard Worker }
369*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7,const substitute_internal::Arg & a8)370*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(
371*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
372*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
373*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
374*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
375*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
376*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a8) {
377*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
378*9356374aSAndroid Build Coastguard Worker                                     a3.piece(), a4.piece(), a5.piece(),
379*9356374aSAndroid Build Coastguard Worker                                     a6.piece(), a7.piece(), a8.piece()};
380*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
381*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
382*9356374aSAndroid Build Coastguard Worker }
383*9356374aSAndroid Build Coastguard Worker 
SubstituteAndAppend(absl::Nonnull<std::string * > output,absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7,const substitute_internal::Arg & a8,const substitute_internal::Arg & a9)384*9356374aSAndroid Build Coastguard Worker inline void SubstituteAndAppend(
385*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::string_view format,
386*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
387*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
388*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
389*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
390*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) {
391*9356374aSAndroid Build Coastguard Worker   const absl::string_view args[] = {
392*9356374aSAndroid Build Coastguard Worker       a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(),
393*9356374aSAndroid Build Coastguard Worker       a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()};
394*9356374aSAndroid Build Coastguard Worker   substitute_internal::SubstituteAndAppendArray(output, format, args,
395*9356374aSAndroid Build Coastguard Worker                                                 ABSL_ARRAYSIZE(args));
396*9356374aSAndroid Build Coastguard Worker }
397*9356374aSAndroid Build Coastguard Worker 
398*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_BAD_CALL_IF)
399*9356374aSAndroid Build Coastguard Worker // This body of functions catches cases where the number of placeholders
400*9356374aSAndroid Build Coastguard Worker // doesn't match the number of data arguments.
401*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
402*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format)
403*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
404*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 0,
405*9356374aSAndroid Build Coastguard Worker         "There were no substitution arguments "
406*9356374aSAndroid Build Coastguard Worker         "but this format string either has a $[0-9] in it or contains "
407*9356374aSAndroid Build Coastguard Worker         "an unescaped $ character (use $$ instead)");
408*9356374aSAndroid Build Coastguard Worker 
409*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
410*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format,
411*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a0)
412*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
413*9356374aSAndroid Build Coastguard Worker                      "There was 1 substitution argument given, but "
414*9356374aSAndroid Build Coastguard Worker                      "this format string is missing its $0, contains "
415*9356374aSAndroid Build Coastguard Worker                      "one of $1-$9, or contains an unescaped $ character (use "
416*9356374aSAndroid Build Coastguard Worker                      "$$ instead)");
417*9356374aSAndroid Build Coastguard Worker 
418*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
419*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format,
420*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a0,
421*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a1)
422*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
423*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 3,
424*9356374aSAndroid Build Coastguard Worker         "There were 2 substitution arguments given, but this format string is "
425*9356374aSAndroid Build Coastguard Worker         "missing its $0/$1, contains one of $2-$9, or contains an "
426*9356374aSAndroid Build Coastguard Worker         "unescaped $ character (use $$ instead)");
427*9356374aSAndroid Build Coastguard Worker 
428*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
429*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format,
430*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a0,
431*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a1,
432*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a2)
433*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
434*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 7,
435*9356374aSAndroid Build Coastguard Worker         "There were 3 substitution arguments given, but "
436*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0/$1/$2, contains one of "
437*9356374aSAndroid Build Coastguard Worker         "$3-$9, or contains an unescaped $ character (use $$ instead)");
438*9356374aSAndroid Build Coastguard Worker 
439*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
440*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format,
441*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a0,
442*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a1,
443*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a2,
444*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a3)
445*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
446*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 15,
447*9356374aSAndroid Build Coastguard Worker         "There were 4 substitution arguments given, but "
448*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$3, contains one of "
449*9356374aSAndroid Build Coastguard Worker         "$4-$9, or contains an unescaped $ character (use $$ instead)");
450*9356374aSAndroid Build Coastguard Worker 
451*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(absl::Nonnull<std::string*> output,
452*9356374aSAndroid Build Coastguard Worker                          absl::Nonnull<const char*> format,
453*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a0,
454*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a1,
455*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a2,
456*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a3,
457*9356374aSAndroid Build Coastguard Worker                          const substitute_internal::Arg& a4)
458*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
459*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 31,
460*9356374aSAndroid Build Coastguard Worker         "There were 5 substitution arguments given, but "
461*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$4, contains one of "
462*9356374aSAndroid Build Coastguard Worker         "$5-$9, or contains an unescaped $ character (use $$ instead)");
463*9356374aSAndroid Build Coastguard Worker 
464*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(
465*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
466*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
467*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
468*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5)
469*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
470*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 63,
471*9356374aSAndroid Build Coastguard Worker         "There were 6 substitution arguments given, but "
472*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$5, contains one of "
473*9356374aSAndroid Build Coastguard Worker         "$6-$9, or contains an unescaped $ character (use $$ instead)");
474*9356374aSAndroid Build Coastguard Worker 
475*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(
476*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
477*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
478*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
479*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
480*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6)
481*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
482*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 127,
483*9356374aSAndroid Build Coastguard Worker         "There were 7 substitution arguments given, but "
484*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$6, contains one of "
485*9356374aSAndroid Build Coastguard Worker         "$7-$9, or contains an unescaped $ character (use $$ instead)");
486*9356374aSAndroid Build Coastguard Worker 
487*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(
488*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
489*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
490*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
491*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
492*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7)
493*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
494*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 255,
495*9356374aSAndroid Build Coastguard Worker         "There were 8 substitution arguments given, but "
496*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$7, contains one of "
497*9356374aSAndroid Build Coastguard Worker         "$8-$9, or contains an unescaped $ character (use $$ instead)");
498*9356374aSAndroid Build Coastguard Worker 
499*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(
500*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
501*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
502*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
503*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
504*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
505*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a8)
506*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
507*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 511,
508*9356374aSAndroid Build Coastguard Worker         "There were 9 substitution arguments given, but "
509*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$8, contains a $9, or "
510*9356374aSAndroid Build Coastguard Worker         "contains an unescaped $ character (use $$ instead)");
511*9356374aSAndroid Build Coastguard Worker 
512*9356374aSAndroid Build Coastguard Worker void SubstituteAndAppend(
513*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
514*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
515*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
516*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
517*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
518*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a8, const substitute_internal::Arg& a9)
519*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
520*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 1023,
521*9356374aSAndroid Build Coastguard Worker         "There were 10 substitution arguments given, but this "
522*9356374aSAndroid Build Coastguard Worker         "format string either doesn't contain all of $0 through $9 or "
523*9356374aSAndroid Build Coastguard Worker         "contains an unescaped $ character (use $$ instead)");
524*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_BAD_CALL_IF
525*9356374aSAndroid Build Coastguard Worker 
526*9356374aSAndroid Build Coastguard Worker // Substitute()
527*9356374aSAndroid Build Coastguard Worker //
528*9356374aSAndroid Build Coastguard Worker // Substitutes variables into a given format string. See file comments above
529*9356374aSAndroid Build Coastguard Worker // for usage.
530*9356374aSAndroid Build Coastguard Worker //
531*9356374aSAndroid Build Coastguard Worker // The declarations of `Substitute()` below consist of overloads for passing 0
532*9356374aSAndroid Build Coastguard Worker // to 10 arguments, respectively.
533*9356374aSAndroid Build Coastguard Worker //
534*9356374aSAndroid Build Coastguard Worker // NOTE: A zero-argument `Substitute()` may be used within variadic templates to
535*9356374aSAndroid Build Coastguard Worker // allow a variable number of arguments.
536*9356374aSAndroid Build Coastguard Worker //
537*9356374aSAndroid Build Coastguard Worker // Example:
538*9356374aSAndroid Build Coastguard Worker //  template <typename... Args>
539*9356374aSAndroid Build Coastguard Worker //  void VarMsg(absl::string_view format, const Args&... args) {
540*9356374aSAndroid Build Coastguard Worker //    std::string s = absl::Substitute(format, args...);
541*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format)542*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
543*9356374aSAndroid Build Coastguard Worker   std::string result;
544*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format);
545*9356374aSAndroid Build Coastguard Worker   return result;
546*9356374aSAndroid Build Coastguard Worker }
547*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0)548*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
549*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0) {
550*9356374aSAndroid Build Coastguard Worker   std::string result;
551*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0);
552*9356374aSAndroid Build Coastguard Worker   return result;
553*9356374aSAndroid Build Coastguard Worker }
554*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1)555*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
556*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
557*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1) {
558*9356374aSAndroid Build Coastguard Worker   std::string result;
559*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1);
560*9356374aSAndroid Build Coastguard Worker   return result;
561*9356374aSAndroid Build Coastguard Worker }
562*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2)563*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
564*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
565*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {
566*9356374aSAndroid Build Coastguard Worker   std::string result;
567*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2);
568*9356374aSAndroid Build Coastguard Worker   return result;
569*9356374aSAndroid Build Coastguard Worker }
570*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3)571*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
572*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
573*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
574*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3) {
575*9356374aSAndroid Build Coastguard Worker   std::string result;
576*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3);
577*9356374aSAndroid Build Coastguard Worker   return result;
578*9356374aSAndroid Build Coastguard Worker }
579*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4)580*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
581*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
582*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
583*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {
584*9356374aSAndroid Build Coastguard Worker   std::string result;
585*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4);
586*9356374aSAndroid Build Coastguard Worker   return result;
587*9356374aSAndroid Build Coastguard Worker }
588*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5)589*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
590*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
591*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
592*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
593*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5) {
594*9356374aSAndroid Build Coastguard Worker   std::string result;
595*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5);
596*9356374aSAndroid Build Coastguard Worker   return result;
597*9356374aSAndroid Build Coastguard Worker }
598*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6)599*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
600*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
601*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
602*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
603*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) {
604*9356374aSAndroid Build Coastguard Worker   std::string result;
605*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6);
606*9356374aSAndroid Build Coastguard Worker   return result;
607*9356374aSAndroid Build Coastguard Worker }
608*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7)609*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
610*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
611*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
612*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
613*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
614*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7) {
615*9356374aSAndroid Build Coastguard Worker   std::string result;
616*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7);
617*9356374aSAndroid Build Coastguard Worker   return result;
618*9356374aSAndroid Build Coastguard Worker }
619*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7,const substitute_internal::Arg & a8)620*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
621*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
622*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
623*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
624*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
625*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) {
626*9356374aSAndroid Build Coastguard Worker   std::string result;
627*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8);
628*9356374aSAndroid Build Coastguard Worker   return result;
629*9356374aSAndroid Build Coastguard Worker }
630*9356374aSAndroid Build Coastguard Worker 
Substitute(absl::string_view format,const substitute_internal::Arg & a0,const substitute_internal::Arg & a1,const substitute_internal::Arg & a2,const substitute_internal::Arg & a3,const substitute_internal::Arg & a4,const substitute_internal::Arg & a5,const substitute_internal::Arg & a6,const substitute_internal::Arg & a7,const substitute_internal::Arg & a8,const substitute_internal::Arg & a9)631*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline std::string Substitute(
632*9356374aSAndroid Build Coastguard Worker     absl::string_view format, const substitute_internal::Arg& a0,
633*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
634*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
635*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
636*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
637*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a9) {
638*9356374aSAndroid Build Coastguard Worker   std::string result;
639*9356374aSAndroid Build Coastguard Worker   SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
640*9356374aSAndroid Build Coastguard Worker   return result;
641*9356374aSAndroid Build Coastguard Worker }
642*9356374aSAndroid Build Coastguard Worker 
643*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_BAD_CALL_IF)
644*9356374aSAndroid Build Coastguard Worker // This body of functions catches cases where the number of placeholders
645*9356374aSAndroid Build Coastguard Worker // doesn't match the number of data arguments.
646*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format)
647*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
648*9356374aSAndroid Build Coastguard Worker                      "There were no substitution arguments "
649*9356374aSAndroid Build Coastguard Worker                      "but this format string either has a $[0-9] in it or "
650*9356374aSAndroid Build Coastguard Worker                      "contains an unescaped $ character (use $$ instead)");
651*9356374aSAndroid Build Coastguard Worker 
652*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
653*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0)
654*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
655*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 1,
656*9356374aSAndroid Build Coastguard Worker         "There was 1 substitution argument given, but "
657*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0, contains one of $1-$9, "
658*9356374aSAndroid Build Coastguard Worker         "or contains an unescaped $ character (use $$ instead)");
659*9356374aSAndroid Build Coastguard Worker 
660*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
661*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0,
662*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a1)
663*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
664*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 3,
665*9356374aSAndroid Build Coastguard Worker         "There were 2 substitution arguments given, but "
666*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0/$1, contains one of "
667*9356374aSAndroid Build Coastguard Worker         "$2-$9, or contains an unescaped $ character (use $$ instead)");
668*9356374aSAndroid Build Coastguard Worker 
669*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
670*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0,
671*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a1,
672*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a2)
673*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
674*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 7,
675*9356374aSAndroid Build Coastguard Worker         "There were 3 substitution arguments given, but "
676*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0/$1/$2, contains one of "
677*9356374aSAndroid Build Coastguard Worker         "$3-$9, or contains an unescaped $ character (use $$ instead)");
678*9356374aSAndroid Build Coastguard Worker 
679*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
680*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0,
681*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a1,
682*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a2,
683*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a3)
684*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
685*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 15,
686*9356374aSAndroid Build Coastguard Worker         "There were 4 substitution arguments given, but "
687*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$3, contains one of "
688*9356374aSAndroid Build Coastguard Worker         "$4-$9, or contains an unescaped $ character (use $$ instead)");
689*9356374aSAndroid Build Coastguard Worker 
690*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
691*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0,
692*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a1,
693*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a2,
694*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a3,
695*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a4)
696*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
697*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 31,
698*9356374aSAndroid Build Coastguard Worker         "There were 5 substitution arguments given, but "
699*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$4, contains one of "
700*9356374aSAndroid Build Coastguard Worker         "$5-$9, or contains an unescaped $ character (use $$ instead)");
701*9356374aSAndroid Build Coastguard Worker 
702*9356374aSAndroid Build Coastguard Worker std::string Substitute(absl::Nonnull<const char*> format,
703*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a0,
704*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a1,
705*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a2,
706*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a3,
707*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a4,
708*9356374aSAndroid Build Coastguard Worker                        const substitute_internal::Arg& a5)
709*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
710*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 63,
711*9356374aSAndroid Build Coastguard Worker         "There were 6 substitution arguments given, but "
712*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$5, contains one of "
713*9356374aSAndroid Build Coastguard Worker         "$6-$9, or contains an unescaped $ character (use $$ instead)");
714*9356374aSAndroid Build Coastguard Worker 
715*9356374aSAndroid Build Coastguard Worker std::string Substitute(
716*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
717*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
718*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
719*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
720*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
721*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 127,
722*9356374aSAndroid Build Coastguard Worker         "There were 7 substitution arguments given, but "
723*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$6, contains one of "
724*9356374aSAndroid Build Coastguard Worker         "$7-$9, or contains an unescaped $ character (use $$ instead)");
725*9356374aSAndroid Build Coastguard Worker 
726*9356374aSAndroid Build Coastguard Worker std::string Substitute(
727*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
728*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
729*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
730*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
731*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7)
732*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
733*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 255,
734*9356374aSAndroid Build Coastguard Worker         "There were 8 substitution arguments given, but "
735*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$7, contains one of "
736*9356374aSAndroid Build Coastguard Worker         "$8-$9, or contains an unescaped $ character (use $$ instead)");
737*9356374aSAndroid Build Coastguard Worker 
738*9356374aSAndroid Build Coastguard Worker std::string Substitute(
739*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
740*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
741*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
742*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
743*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
744*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
745*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 511,
746*9356374aSAndroid Build Coastguard Worker         "There were 9 substitution arguments given, but "
747*9356374aSAndroid Build Coastguard Worker         "this format string is missing its $0-$8, contains a $9, or "
748*9356374aSAndroid Build Coastguard Worker         "contains an unescaped $ character (use $$ instead)");
749*9356374aSAndroid Build Coastguard Worker 
750*9356374aSAndroid Build Coastguard Worker std::string Substitute(
751*9356374aSAndroid Build Coastguard Worker     absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
752*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
753*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
754*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
755*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
756*9356374aSAndroid Build Coastguard Worker     const substitute_internal::Arg& a9)
757*9356374aSAndroid Build Coastguard Worker     ABSL_BAD_CALL_IF(
758*9356374aSAndroid Build Coastguard Worker         substitute_internal::PlaceholderBitmask(format) != 1023,
759*9356374aSAndroid Build Coastguard Worker         "There were 10 substitution arguments given, but this "
760*9356374aSAndroid Build Coastguard Worker         "format string either doesn't contain all of $0 through $9 or "
761*9356374aSAndroid Build Coastguard Worker         "contains an unescaped $ character (use $$ instead)");
762*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_BAD_CALL_IF
763*9356374aSAndroid Build Coastguard Worker 
764*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
765*9356374aSAndroid Build Coastguard Worker }  // namespace absl
766*9356374aSAndroid Build Coastguard Worker 
767*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_STRINGS_SUBSTITUTE_H_
768