abseil-cpp/absl/strings/internal/str_format/arg.cc
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 //
16 // POSIX spec:
17 // http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
18 //
19 #include "absl/strings/internal/str_format/arg.h"
20 
21 #include <cassert>
22 #include <cerrno>
23 #include <cstdlib>
24 #include <string>
25 #include <type_traits>
26 
27 #include "absl/base/port.h"
28 #include "absl/strings/internal/str_format/float_conversion.h"
29 #include "absl/strings/numbers.h"
30 
31 namespace absl {
34 namespace {
35 
36 // Reduce *capacity by s.size(), clipped to a 0 minimum.
37 void ReducePadding(string_view s, size_t *capacity) {
38  *capacity = Excess(s.size(), *capacity);
39 }
40 
41 // Reduce *capacity by n, clipped to a 0 minimum.
42 void ReducePadding(size_t n, size_t *capacity) {
43  *capacity = Excess(n, *capacity);
44 }
45 
46 template <typename T>
47 struct MakeUnsigned : std::make_unsigned<T> {};
48 template <>
49 struct MakeUnsigned<absl::int128> {
50  using type = absl::uint128;
51 };
52 template <>
53 struct MakeUnsigned<absl::uint128> {
54  using type = absl::uint128;
55 };
56 
57 template <typename T>
58 struct IsSigned : std::is_signed<T> {};
59 template <>
60 struct IsSigned<absl::int128> : std::true_type {};
61 template <>
62 struct IsSigned<absl::uint128> : std::false_type {};
63 
64 // Integral digit printer.
65 // Call one of the PrintAs* routines after construction once.
66 // Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
67 class IntDigits {
68  public:
69  // Print the unsigned integer as octal.
70  // Supports unsigned integral types and uint128.
71  template <typename T>
72  void PrintAsOct(T v) {
73  static_assert(!IsSigned<T>::value, "");
74  char *p = storage_ + sizeof(storage_);
75  do {
76  *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
77  v >>= 3;
78  } while (v);
79  start_ = p;
80  size_ = storage_ + sizeof(storage_) - p;
81  }
82 
83  // Print the signed or unsigned integer as decimal.
84  // Supports all integral types.
85  template <typename T>
86  void PrintAsDec(T v) {
87  static_assert(std::is_integral<T>::value, "");
88  start_ = storage_;
90  }
91 
92  void PrintAsDec(int128 v) {
93  auto u = static_cast<uint128>(v);
94  bool add_neg = false;
95  if (v < 0) {
96  add_neg = true;
97  u = uint128{} - u;
98  }
99  PrintAsDec(u, add_neg);
100  }
101 
102  void PrintAsDec(uint128 v, bool add_neg = false) {
103  // This function can be sped up if needed. We can call FastIntToBuffer
104  // twice, or fix FastIntToBuffer to support uint128.
105  char *p = storage_ + sizeof(storage_);
106  do {
107  p -= 2;
108  numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
109  v /= 100;
110  } while (v);
111  if (p[0] == '0') {
112  // We printed one too many hexits.
113  ++p;
114  }
115  if (add_neg) {
116  *--p = '-';
117  }
118  size_ = storage_ + sizeof(storage_) - p;
119  start_ = p;
120  }
121 
122  // Print the unsigned integer as hex using lowercase.
123  // Supports unsigned integral types and uint128.
124  template <typename T>
125  void PrintAsHexLower(T v) {
126  static_assert(!IsSigned<T>::value, "");
127  char *p = storage_ + sizeof(storage_);
128 
129  do {
130  p -= 2;
131  constexpr const char* table = numbers_internal::kHexTable;
132  std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
133  if (sizeof(T) == 1) break;
134  v >>= 8;
135  } while (v);
136  if (p[0] == '0') {
137  // We printed one too many digits.
138  ++p;
139  }
140  start_ = p;
141  size_ = storage_ + sizeof(storage_) - p;
142  }
143 
144  // Print the unsigned integer as hex using uppercase.
145  // Supports unsigned integral types and uint128.
146  template <typename T>
147  void PrintAsHexUpper(T v) {
148  static_assert(!IsSigned<T>::value, "");
149  char *p = storage_ + sizeof(storage_);
150 
151  // kHexTable is only lowercase, so do it manually for uppercase.
152  do {
153  *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
154  v >>= 4;
155  } while (v);
156  start_ = p;
157  size_ = storage_ + sizeof(storage_) - p;
158  }
159 
160  // The printed value including the '-' sign if available.
161  // For inputs of value `0`, this will return "0"
162  string_view with_neg_and_zero() const { return {start_, size_}; }
163 
164  // The printed value not including the '-' sign.
165  // For inputs of value `0`, this will return "".
166  string_view without_neg_or_zero() const {
167  static_assert('-' < '0', "The check below verifies both.");
168  size_t advance = start_[0] <= '0' ? 1 : 0;
169  return {start_ + advance, size_ - advance};
170  }
171 
172  bool is_negative() const { return start_[0] == '-'; }
173 
174  private:
175  const char *start_;
176  size_t size_;
177  // Max size: 128 bit value as octal -> 43 digits, plus sign char
178  char storage_[128 / 3 + 1 + 1];
179 };
180 
181 // Note: 'o' conversions do not have a base indicator, it's just that
182 // the '#' flag is specified to modify the precision for 'o' conversions.
183 string_view BaseIndicator(const IntDigits &as_digits,
184  const FormatConversionSpecImpl conv) {
185  // always show 0x for %p.
186  bool alt = conv.has_alt_flag() ||
187  conv.conversion_char() == FormatConversionCharInternal::p;
188  bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
189  conv.conversion_char() == FormatConversionCharInternal::X ||
190  conv.conversion_char() == FormatConversionCharInternal::p);
191  // From the POSIX description of '#' flag:
192  // "For x or X conversion specifiers, a non-zero result shall have
193  // 0x (or 0X) prefixed to it."
194  if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
195  return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
196  : "0x";
197  }
198  return {};
199 }
200 
201 string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
202  if (conv.conversion_char() == FormatConversionCharInternal::d ||
203  conv.conversion_char() == FormatConversionCharInternal::i) {
204  if (neg) return "-";
205  if (conv.has_show_pos_flag()) return "+";
206  if (conv.has_sign_col_flag()) return " ";
207  }
208  return {};
209 }
210 
211 bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
212  FormatSinkImpl *sink) {
213  size_t fill = 0;
214  if (conv.width() >= 0) fill = conv.width();
215  ReducePadding(1, &fill);
216  if (!conv.has_left_flag()) sink->Append(fill, ' ');
217  sink->Append(1, v);
218  if (conv.has_left_flag()) sink->Append(fill, ' ');
219  return true;
220 }
221 
222 bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
223  const FormatConversionSpecImpl conv,
224  FormatSinkImpl *sink) {
225  // Print as a sequence of Substrings:
226  // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
227  size_t fill = 0;
228  if (conv.width() >= 0) fill = conv.width();
229 
230  string_view formatted = as_digits.without_neg_or_zero();
231  ReducePadding(formatted, &fill);
232 
233  string_view sign = SignColumn(as_digits.is_negative(), conv);
234  ReducePadding(sign, &fill);
235 
236  string_view base_indicator = BaseIndicator(as_digits, conv);
237  ReducePadding(base_indicator, &fill);
238 
239  int precision = conv.precision();
240  bool precision_specified = precision >= 0;
241  if (!precision_specified)
242  precision = 1;
243 
244  if (conv.has_alt_flag() &&
245  conv.conversion_char() == FormatConversionCharInternal::o) {
246  // From POSIX description of the '#' (alt) flag:
247  // "For o conversion, it increases the precision (if necessary) to
248  // force the first digit of the result to be zero."
249  if (formatted.empty() || *formatted.begin() != '0') {
250  int needed = static_cast<int>(formatted.size()) + 1;
251  precision = std::max(precision, needed);
252  }
253  }
254 
255  size_t num_zeroes = Excess(formatted.size(), precision);
256  ReducePadding(num_zeroes, &fill);
257 
258  size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
259  size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
260 
261  // From POSIX description of the '0' (zero) flag:
262  // "For d, i, o, u, x, and X conversion specifiers, if a precision
263  // is specified, the '0' flag is ignored."
264  if (!precision_specified && conv.has_zero_flag()) {
265  num_zeroes += num_left_spaces;
266  num_left_spaces = 0;
267  }
268 
269  sink->Append(num_left_spaces, ' ');
270  sink->Append(sign);
271  sink->Append(base_indicator);
272  sink->Append(num_zeroes, '0');
273  sink->Append(formatted);
274  sink->Append(num_right_spaces, ' ');
275  return true;
276 }
277 
278 template <typename T>
279 bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
280  FormatSinkImpl *sink) {
281  using U = typename MakeUnsigned<T>::type;
282  IntDigits as_digits;
283 
284  // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
285  // it to complain about a switch/case type mismatch, even though both are
286  // FormatConverionChar. Likely this is because at this point
287  // FormatConversionChar is declared, but not defined.
288  switch (static_cast<uint8_t>(conv.conversion_char())) {
289  case static_cast<uint8_t>(FormatConversionCharInternal::c):
290  return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
291 
292  case static_cast<uint8_t>(FormatConversionCharInternal::o):
293  as_digits.PrintAsOct(static_cast<U>(v));
294  break;
295 
296  case static_cast<uint8_t>(FormatConversionCharInternal::x):
297  as_digits.PrintAsHexLower(static_cast<U>(v));
298  break;
299  case static_cast<uint8_t>(FormatConversionCharInternal::X):
300  as_digits.PrintAsHexUpper(static_cast<U>(v));
301  break;
302 
303  case static_cast<uint8_t>(FormatConversionCharInternal::u):
304  as_digits.PrintAsDec(static_cast<U>(v));
305  break;
306 
307  case static_cast<uint8_t>(FormatConversionCharInternal::d):
308  case static_cast<uint8_t>(FormatConversionCharInternal::i):
309  as_digits.PrintAsDec(v);
310  break;
311 
312  case static_cast<uint8_t>(FormatConversionCharInternal::a):
313  case static_cast<uint8_t>(FormatConversionCharInternal::e):
314  case static_cast<uint8_t>(FormatConversionCharInternal::f):
315  case static_cast<uint8_t>(FormatConversionCharInternal::g):
316  case static_cast<uint8_t>(FormatConversionCharInternal::A):
317  case static_cast<uint8_t>(FormatConversionCharInternal::E):
318  case static_cast<uint8_t>(FormatConversionCharInternal::F):
319  case static_cast<uint8_t>(FormatConversionCharInternal::G):
320  return ConvertFloatImpl(static_cast<double>(v), conv, sink);
321 
322  default:
323  ABSL_ASSUME(false);
324  }
325 
326  if (conv.is_basic()) {
327  sink->Append(as_digits.with_neg_and_zero());
328  return true;
329  }
330  return ConvertIntImplInnerSlow(as_digits, conv, sink);
331 }
332 
333 template <typename T>
334 bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
335  FormatSinkImpl *sink) {
338 }
339 
340 inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
341  FormatSinkImpl *sink) {
342  if (conv.is_basic()) {
343  sink->Append(v);
344  return true;
345  }
346  return sink->PutPaddedString(v, conv.width(), conv.precision(),
347  conv.has_left_flag());
348 }
349 
350 } // namespace
351 
352 // ==================== Strings ====================
355  FormatSinkImpl *sink) {
356  return {ConvertStringArg(v, conv, sink)};
357 }
358 
361  FormatSinkImpl *sink) {
362  return {ConvertStringArg(v, conv, sink)};
363 }
364 
365 ArgConvertResult<FormatConversionCharSetUnion(
366  FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
368  FormatSinkImpl *sink) {
369  if (conv.conversion_char() == FormatConversionCharInternal::p)
370  return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
371  size_t len;
372  if (v == nullptr) {
373  len = 0;
374  } else if (conv.precision() < 0) {
375  len = std::strlen(v);
376  } else {
377  // If precision is set, we look for the NUL-terminator on the valid range.
378  len = std::find(v, v + conv.precision(), '\0') - v;
379  }
380  return {ConvertStringArg(string_view(v, len), conv, sink)};
381 }
382 
383 // ==================== Raw pointers ====================
386  if (!v.value) {
387  sink->Append("(nil)");
388  return {true};
389  }
390  IntDigits as_digits;
391  as_digits.PrintAsHexLower(v.value);
392  return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
393 }
394 
395 // ==================== Floats ====================
398  FormatSinkImpl *sink) {
399  return {ConvertFloatArg(v, conv, sink)};
400 }
403  FormatSinkImpl *sink) {
404  return {ConvertFloatArg(v, conv, sink)};
405 }
408  FormatSinkImpl *sink) {
409  return {ConvertFloatArg(v, conv, sink)};
410 }
411 
412 // ==================== Chars ====================
415  FormatSinkImpl *sink) {
416  return {ConvertIntArg(v, conv, sink)};
417 }
420  FormatSinkImpl *sink) {
421  return {ConvertIntArg(v, conv, sink)};
422 }
425  FormatSinkImpl *sink) {
426  return {ConvertIntArg(v, conv, sink)};
427 }
428 
429 // ==================== Ints ====================
432  FormatSinkImpl *sink) {
433  return {ConvertIntArg(v, conv, sink)};
434 }
435 IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
437  FormatSinkImpl *sink) {
438  return {ConvertIntArg(v, conv, sink)};
439 }
442  FormatSinkImpl *sink) {
443  return {ConvertIntArg(v, conv, sink)};
444 }
447  FormatSinkImpl *sink) {
448  return {ConvertIntArg(v, conv, sink)};
449 }
452  FormatSinkImpl *sink) {
453  return {ConvertIntArg(v, conv, sink)};
454 }
455 IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
457  FormatSinkImpl *sink) {
458  return {ConvertIntArg(v, conv, sink)};
459 }
462  FormatSinkImpl *sink) {
463  return {ConvertIntArg(v, conv, sink)};
464 }
465 IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
467  FormatSinkImpl *sink) {
468  return {ConvertIntArg(v, conv, sink)};
469 }
472  FormatSinkImpl *sink) {
473  return {ConvertIntArg(v, conv, sink)};
474 }
477  FormatSinkImpl *sink) {
478  return {ConvertIntArg(v, conv, sink)};
479 }
480 
482 
483 
484 
485 } // namespace str_format_internal
486 
488 } // namespace absl
precision
int precision
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:448
absl::numbers_internal::PutTwoDigits
void PutTwoDigits(size_t i, char *buf)
Definition: abseil-cpp/absl/strings/numbers.h:137
find
static void ** find(grpc_chttp2_stream_map *map, uint32_t key)
Definition: stream_map.cc:99
absl::str_format_internal::FormatConversionSpecImpl::has_zero_flag
bool has_zero_flag() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:286
capacity
uint16_t capacity
Definition: protobuf/src/google/protobuf/descriptor.cc:948
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::str_format_internal::ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_()
absl::str_format_internal::FormatConversionSpecImpl::conversion_char
FormatConversionChar conversion_char() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:288
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::str_format_internal::FormatSinkImpl::Append
void Append(size_t n, char c)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:78
absl::FormatConversionChar::s
@ s
absl::str_format_internal::ArgConvertResult::value
bool value
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:100
xds_manager.p
p
Definition: xds_manager.py:60
absl::str_format_internal::VoidPtr
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:89
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
start_
const char * start_
Definition: abseil-cpp/absl/strings/internal/str_format/arg.cc:175
absl::str_format_internal::Excess
size_t Excess(size_t used, size_t capacity)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:439
T
#define T(upbtypeconst, upbtype, ctype, default_value)
absl::str_format_internal::ConvertFloatImpl
bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink)
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1400
absl::str_format_internal::FormatConversionCharIsFloat
bool FormatConversionCharIsFloat(FormatConversionChar c)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:232
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::str_format_internal::FormatConversionSpecImpl::has_left_flag
bool has_left_flag() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:278
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
absl::int128
Definition: abseil-cpp/absl/numeric/int128.h:338
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
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::FormatConversionSpecImpl::has_show_pos_flag
bool has_show_pos_flag() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:279
absl::str_format_internal::FormatConversionSpecImpl::has_alt_flag
bool has_alt_flag() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:285
absl::str_format_internal::ArgConvertResult
Definition: abseil-cpp/absl/strings/internal/str_format/arg.h:99
absl::string_view::begin
constexpr const_iterator begin() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:220
advance
static void advance(upb_pbdecoder *d, size_t len)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:6553
absl::str_format_internal::FormatSinkImpl
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:67
absl::str_format_internal::FormatConversionSpecImpl::has_sign_col_flag
bool has_sign_col_flag() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:282
absl::str_format_internal::FormatConversionSpecImpl::width
int width() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:297
absl::str_format_internal::FormatConversionSpecImpl::precision
int precision() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:300
absl::str_format_internal::FormatSinkImpl::PutPaddedString
bool PutPaddedString(string_view v, int width, int precision, bool left)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.cc:58
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
storage_
char storage_[128/3+1+1]
Definition: abseil-cpp/absl/strings/internal/str_format/arg.cc:178
value
const char * value
Definition: hpack_parser_table.cc:165
absl::chars_format::hex
@ hex
ABSL_ASSUME
#define ABSL_ASSUME(cond)
Definition: abseil-cpp/absl/base/optimization.h:209
absl::str_format_internal::FormatConversionSpecImpl
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:274
sink
FormatSinkImpl * sink
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:450
string_view
absl::string_view string_view
Definition: attr.cc:22
fill
int fill
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:47
absl::numbers_internal::kHexTable
ABSL_CONST_INIT const ABSL_DLL char kHexTable[513]
Definition: abseil-cpp/absl/strings/numbers.cc:1030
table
uint8_t table[256]
Definition: hpack_parser.cc:456
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
absl::numbers_internal::FastIntToBuffer
char * FastIntToBuffer(int32_t, char *)
Definition: abseil-cpp/absl/strings/numbers.cc:217
absl::str_format_internal::FormatConvertImpl
StringConvertResult FormatConvertImpl(const std::string &v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink)
Definition: abseil-cpp/absl/strings/internal/str_format/arg.cc:353
str_format_internal
absl::str_format_internal::FormatConversionCharSetUnion
constexpr FormatConversionCharSet FormatConversionCharSetUnion(FormatConversionCharSet a)
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:339
absl::str_format_internal::FormatConversionSpecImpl::is_basic
bool is_basic() const
Definition: abseil-cpp/absl/strings/internal/str_format/extension.h:277
absl::uint128
Definition: abseil-cpp/absl/numeric/int128.h:104
size_
size_t size_
Definition: abseil-cpp/absl/strings/internal/str_format/arg.cc:176


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