abseil-cpp/absl/strings/internal/str_format/bind.h
Go to the documentation of this file.
1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
16 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
17 
18 #include <array>
19 #include <cstdio>
20 #include <sstream>
21 #include <string>
22 
23 #include "absl/base/port.h"
24 #include "absl/strings/internal/str_format/arg.h"
25 #include "absl/strings/internal/str_format/checker.h"
26 #include "absl/strings/internal/str_format/parser.h"
27 #include "absl/types/span.h"
28 #include "absl/utility/utility.h"
29 
30 namespace absl {
32 
33 class UntypedFormatSpec;
34 
35 namespace str_format_internal {
36 
38  public:
39  const FormatArgImpl* arg() const { return arg_; }
40  void set_arg(const FormatArgImpl* a) { arg_ = a; }
41 
42  private:
44 };
45 
46 // This is the type-erased class that the implementation uses.
48  public:
49  UntypedFormatSpecImpl() = delete;
50 
52  : data_(s.data()), size_(s.size()) {}
55  : data_(pc), size_(~size_t{}) {}
56 
57  bool has_parsed_conversion() const { return size_ == ~size_t{}; }
58 
59  string_view str() const {
60  assert(!has_parsed_conversion());
61  return string_view(static_cast<const char*>(data_), size_);
62  }
64  assert(has_parsed_conversion());
65  return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
66  }
67 
68  template <typename T>
69  static const UntypedFormatSpecImpl& Extract(const T& s) {
70  return s.spec_;
71  }
72 
73  private:
74  const void* data_;
75  size_t size_;
76 };
77 
78 template <typename T, FormatConversionCharSet...>
79 struct MakeDependent {
80  using type = T;
81 };
82 
83 // Implicitly convertible from `const char*`, `string_view`, and the
84 // `ExtendedParsedFormat` type. This abstraction allows all format functions to
85 // operate on any without providing too many overloads.
86 template <FormatConversionCharSet... Args>
88  : public MakeDependent<UntypedFormatSpec, Args...>::type {
90 
91  template <bool res>
92  struct ErrorMaker {
93  constexpr bool operator()(int) const { return res; }
94  };
95 
96  template <int i, int j>
97  static constexpr bool CheckArity(ErrorMaker<true> SpecifierCount = {},
98  ErrorMaker<i == j> ParametersPassed = {}) {
99  static_assert(SpecifierCount(i) == ParametersPassed(j),
100  "Number of arguments passed must match the number of "
101  "conversion specifiers.");
102  return true;
103  }
104 
105  template <FormatConversionCharSet specified, FormatConversionCharSet passed,
106  int arg>
107  static constexpr bool CheckMatch(
108  ErrorMaker<Contains(specified, passed)> MismatchedArgumentNumber = {}) {
109  static_assert(MismatchedArgumentNumber(arg),
110  "Passed argument must match specified format.");
111  return true;
112  }
113 
114  template <FormatConversionCharSet... C, size_t... I>
116  bool res[] = {true, CheckMatch<Args, C, I + 1>()...};
117  (void)res;
118  return true;
119  }
120 
121  public:
122 #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
123 
124  // Honeypot overload for when the string is not constexpr.
125  // We use the 'unavailable' attribute to give a better compiler error than
126  // just 'method is deleted'.
127  FormatSpecTemplate(...) // NOLINT
128  __attribute__((unavailable("Format string is not constexpr.")));
129 
130  // Honeypot overload for when the format is constexpr and invalid.
131  // We use the 'unavailable' attribute to give a better compiler error than
132  // just 'method is deleted'.
133  // To avoid checking the format twice, we just check that the format is
134  // constexpr. If it is valid, then the overload below will kick in.
135  // We add the template here to make this overload have lower priority.
136  template <typename = void>
137  FormatSpecTemplate(const char* s) // NOLINT
138  __attribute__((
139  enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
140  unavailable(
141  "Format specified does not match the arguments passed.")));
142 
143  template <typename T = void>
144  FormatSpecTemplate(string_view s) // NOLINT
146  "constexpr trap")))
147  : Base("to avoid noise in the compiler error") {
148  static_assert(sizeof(T*) == 0,
149  "Format specified does not match the arguments passed.");
150  }
151 
152  // Good format overload.
153  FormatSpecTemplate(const char* s) // NOLINT
154  __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
155  : Base(s) {}
156 
157  FormatSpecTemplate(string_view s) // NOLINT
158  __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
159  : Base(s) {}
160 
161 #else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
162 
163  FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
165 
166 #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
167 
168  template <FormatConversionCharSet... C>
170  : Base(&pc) {
171  CheckArity<sizeof...(C), sizeof...(Args)>();
172  CheckMatches<C...>(absl::make_index_sequence<sizeof...(C)>{});
173  }
174 };
175 
176 class Streamable {
177  public:
180  : format_(format) {
181  if (args.size() <= ABSL_ARRAYSIZE(few_args_)) {
182  for (size_t i = 0; i < args.size(); ++i) {
183  few_args_[i] = args[i];
184  }
185  args_ = absl::MakeSpan(few_args_, args.size());
186  } else {
187  many_args_.assign(args.begin(), args.end());
188  args_ = many_args_;
189  }
190  }
191 
192  std::ostream& Print(std::ostream& os) const;
193 
194  friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
195  return l.Print(os);
196  }
197 
198  private:
201  // if args_.size() is 4 or less:
204  // if args_.size() is more than 4:
205  std::vector<FormatArgImpl> many_args_;
206 };
207 
208 // for testing
211 bool BindWithPack(const UnboundConversion* props,
213 
214 bool FormatUntyped(FormatRawSinkImpl raw_sink,
217 
220 
223 
226 int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
228 
229 // Returned by Streamed(v). Converts via '%s' to the std::string created
230 // by std::ostream << v.
231 template <typename T>
232 class StreamedWrapper {
233  public:
234  explicit StreamedWrapper(const T& v) : v_(v) { }
235 
236  private:
237  template <typename S>
241  const T& v_;
242 };
243 
244 } // namespace str_format_internal
246 } // namespace absl
247 
248 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
absl::str_format_internal::FormatUntyped
bool FormatUntyped(FormatRawSinkImpl raw_sink, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:195
absl::str_format_internal::EnsureConstexpr
constexpr bool EnsureConstexpr(string_view s)
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser.h:206
absl::str_format_internal::FormatArgImpl
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:312
http2_test_server.format
format
Definition: http2_test_server.py:118
absl::str_format_internal::Contains
constexpr bool Contains(FormatConversionCharSet set, char c)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:421
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
absl::UntypedFormatSpec::UntypedFormatSpec
UntypedFormatSpec()=delete
absl::str_format_internal::StreamedWrapper::StreamedWrapper
StreamedWrapper(const T &v)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:234
absl::str_format_internal::UntypedFormatSpecImpl::Extract
static const UntypedFormatSpecImpl & Extract(const T &s)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:69
absl::str_format_internal::UntypedFormatSpecImpl::data_
const void * data_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:74
C
#define C(x)
Definition: abseil-cpp/absl/hash/internal/city_test.cc:49
absl::Span
Definition: abseil-cpp/absl/types/span.h:152
absl::str_format_internal::AppendPack
std::string & AppendPack(std::string *out, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:208
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
absl::str_format_internal::FprintF
int FprintF(std::FILE *output, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:226
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
absl::UntypedFormatSpec
Definition: abseil-cpp/absl/strings/str_format.h:96
absl::str_format_internal::FormatRawSinkImpl
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:40
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
absl::str_format_internal::UnboundConversion
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser.h:43
absl::str_format_internal::UntypedFormatSpecImpl::UntypedFormatSpecImpl
UntypedFormatSpecImpl(const str_format_internal::ParsedFormatBase *pc)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:53
absl::str_format_internal::Streamable
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:176
absl::FormatConversionChar::s
@ s
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
to
size_t to
Definition: abseil-cpp/absl/container/internal/layout_test.cc:1385
absl::str_format_internal::FormatSpecTemplate::CheckArity
static constexpr bool CheckArity(ErrorMaker< true > SpecifierCount={}, ErrorMaker< i==j > ParametersPassed={})
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:97
absl::str_format_internal::Summarize
std::string Summarize(const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:180
ABSL_ARRAYSIZE
#define ABSL_ARRAYSIZE(array)
Definition: abseil-cpp/absl/base/macros.h:44
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::str_format_internal::Streamable::many_args_
std::vector< FormatArgImpl > many_args_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:205
absl::str_format_internal::UntypedFormatSpecImpl::size_
size_t size_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:75
absl::str_format_internal::FormatSpecTemplate::FormatSpecTemplate
FormatSpecTemplate(string_view s)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:164
absl::str_format_internal::FormatSpecTemplate
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:87
T
#define T(upbtypeconst, upbtype, ctype, default_value)
absl::str_format_internal::UntypedFormatSpecImpl::str
string_view str() const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:59
absl::str_format_internal::StreamedWrapper::FormatConvertImpl
friend ArgConvertResult< FormatConversionCharSetInternal::s > FormatConvertImpl(const StreamedWrapper< S > &v, FormatConversionSpecImpl conv, FormatSinkImpl *out)
absl::str_format_internal::BoundConversion
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:37
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
str_format_internal::ParsedFormatBase
hpack_encoder_fixtures::Args
Args({0, 16384})
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
absl::make_index_sequence
make_integer_sequence< size_t, N > make_index_sequence
Definition: abseil-cpp/absl/utility/utility.h:150
absl::integer_sequence
Definition: abseil-cpp/absl/utility/utility.h:76
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
conv
const FormatConversionSpecImpl & conv
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:449
absl::str_format_internal::UntypedFormatSpecImpl::UntypedFormatSpecImpl
UntypedFormatSpecImpl(string_view s)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:51
__attribute__
__attribute__(void) start
absl::str_format_internal::FormatPack
std::string FormatPack(const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:217
absl::str_format_internal::UntypedFormatSpecImpl::has_parsed_conversion
bool has_parsed_conversion() const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:57
arg
Definition: cmdline.cc:40
Base
Definition: bloaty/third_party/googletest/googletest/test/gtest_unittest.cc:5141
absl::str_format_internal::UntypedFormatSpecImpl::parsed_conversion
const str_format_internal::ParsedFormatBase * parsed_conversion() const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:63
absl::str_format_internal::ArgConvertResult
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:99
absl::str_format_internal::BoundConversion::set_arg
void set_arg(const FormatArgImpl *a)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:40
absl::str_format_internal::FormatSinkImpl
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:67
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
absl::str_format_internal::FormatSpecTemplate::FormatSpecTemplate
FormatSpecTemplate(const ExtendedParsedFormat< C... > &pc)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:169
absl::str_format_internal::Streamable::Print
std::ostream & Print(std::ostream &os) const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:203
absl::str_format_internal::StreamedWrapper
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:75
absl::str_format_internal::UntypedFormatSpecImpl
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:47
absl::str_format_internal::Streamable::args_
absl::Span< const FormatArgImpl > args_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:200
absl::str_format_internal::FormatSpecTemplate::FormatSpecTemplate
FormatSpecTemplate(const char *s)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:163
absl::str_format_internal::SnprintF
int SnprintF(char *output, size_t size, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:244
benchmark.FILE
FILE
Definition: benchmark.py:21
absl::str_format_internal::FormatConversionSpecImpl
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:274
I
#define I(b, c, d)
Definition: md5.c:120
absl::str_format_internal::UntypedFormatSpecImpl::UntypedFormatSpecImpl
UntypedFormatSpecImpl()=delete
absl::str_format_internal::BoundConversion::arg_
const FormatArgImpl * arg_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:43
absl::str_format_internal::Streamable::operator<<
friend std::ostream & operator<<(std::ostream &os, const Streamable &l)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:194
absl::str_format_internal::ExtendedParsedFormat
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser.h:310
absl::str_format_internal::BindWithPack
bool BindWithPack(const UnboundConversion *props, absl::Span< const FormatArgImpl > pack, BoundConversion *bound)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.cc:174
absl::str_format_internal::FormatSpecTemplate::CheckMatches
static bool CheckMatches(absl::index_sequence< I... >)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:115
string_view
absl::string_view string_view
Definition: attr.cc:22
absl::str_format_internal::StreamedWrapper::v_
const T & v_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:241
absl::Format
bool Format(FormatRawSink raw_sink, const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:504
absl::str_format_internal::BoundConversion::arg
const FormatArgImpl * arg() const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:39
absl::FormatConversionCharSet
FormatConversionCharSet
Definition: abseil-cpp/absl/strings/str_format.h:737
absl::str_format_internal::Streamable::Streamable
Streamable(const UntypedFormatSpecImpl &format, absl::Span< const FormatArgImpl > args)
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:178
absl::str_format_internal::FormatSpecTemplate::CheckMatch
static constexpr bool CheckMatch(ErrorMaker< Contains(specified, passed)> MismatchedArgumentNumber={})
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:107
absl::str_format_internal::Streamable::few_args_
FormatArgImpl few_args_[4]
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:202
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
absl::out
char * out
Definition: abseil-cpp/absl/synchronization/mutex.h:1048
setup.template
template
Definition: setup.py:47
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::str_format_internal::FormatSpecTemplate::ErrorMaker::operator()
constexpr bool operator()(int) const
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:93
absl::str_format_internal::FormatSpecTemplate::ErrorMaker
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:92
absl::str_format_internal::MakeDependent
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:79
absl::MakeSpan
constexpr Span< T > MakeSpan(T *ptr, size_t size) noexcept
Definition: abseil-cpp/absl/types/span.h:661
str_format_internal
compiler
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc:21
absl::str_format_internal::FormatSpecTemplate::Base
typename MakeDependent< UntypedFormatSpec, Args... >::type Base
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:89
absl::str_format_internal::Streamable::format_
const UntypedFormatSpecImpl & format_
Definition: abseil-cpp/absl/strings/internal/str_format/bind.h:199
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:48