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


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:37