Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / third_party / abseil-cpp / absl / strings / internal / str_format / arg.h
1 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
2 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
3
4 #include <string.h>
5 #include <wchar.h>
6
7 #include <cstdio>
8 #include <iomanip>
9 #include <limits>
10 #include <memory>
11 #include <sstream>
12 #include <string>
13 #include <type_traits>
14
15 #include "absl/base/port.h"
16 #include "absl/meta/type_traits.h"
17 #include "absl/numeric/int128.h"
18 #include "absl/strings/internal/str_format/extension.h"
19 #include "absl/strings/string_view.h"
20
21 class Cord;
22 class CordReader;
23
24 namespace absl {
25
26 class FormatCountCapture;
27 class FormatSink;
28
29 namespace str_format_internal {
30
31 template <typename T, typename = void>
32 struct HasUserDefinedConvert : std::false_type {};
33
34 template <typename T>
35 struct HasUserDefinedConvert<
36     T, void_t<decltype(AbslFormatConvert(
37            std::declval<const T&>(), std::declval<ConversionSpec>(),
38            std::declval<FormatSink*>()))>> : std::true_type {};
39
40 template <typename T>
41 class StreamedWrapper;
42
43 // If 'v' can be converted (in the printf sense) according to 'conv',
44 // then convert it, appending to `sink` and return `true`.
45 // Otherwise fail and return `false`.
46
47 // Raw pointers.
48 struct VoidPtr {
49   VoidPtr() = default;
50   template <typename T,
51             decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
52   VoidPtr(T* ptr)  // NOLINT
53       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
54   uintptr_t value;
55 };
56 ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
57                                          FormatSinkImpl* sink);
58
59 // Strings.
60 ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
61                                          ConversionSpec conv,
62                                          FormatSinkImpl* sink);
63 ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
64                                          FormatSinkImpl* sink);
65 ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
66                                                    ConversionSpec conv,
67                                                    FormatSinkImpl* sink);
68 template <class AbslCord,
69           typename std::enable_if<
70               std::is_same<AbslCord, ::Cord>::value>::type* = nullptr,
71           class AbslCordReader = ::CordReader>
72 ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
73                                          ConversionSpec conv,
74                                          FormatSinkImpl* sink) {
75   if (conv.conv().id() != ConversionChar::s) return {false};
76
77   bool is_left = conv.flags().left;
78   size_t space_remaining = 0;
79
80   int width = conv.width();
81   if (width >= 0) space_remaining = width;
82
83   size_t to_write = value.size();
84
85   int precision = conv.precision();
86   if (precision >= 0)
87     to_write = (std::min)(to_write, static_cast<size_t>(precision));
88
89   space_remaining = Excess(to_write, space_remaining);
90
91   if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
92
93   string_view piece;
94   for (AbslCordReader reader(value);
95        to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
96     if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
97     sink->Append(piece);
98   }
99
100   if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
101   return {true};
102 }
103
104 using IntegralConvertResult =
105     ConvertResult<Conv::c | Conv::numeric | Conv::star>;
106 using FloatingConvertResult = ConvertResult<Conv::floating>;
107
108 // Floats.
109 FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
110                                         FormatSinkImpl* sink);
111 FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
112                                         FormatSinkImpl* sink);
113 FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
114                                         FormatSinkImpl* sink);
115
116 // Chars.
117 IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
118                                         FormatSinkImpl* sink);
119 IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
120                                         FormatSinkImpl* sink);
121 IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
122                                         FormatSinkImpl* sink);
123
124 // Ints.
125 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
126                                         ConversionSpec conv,
127                                         FormatSinkImpl* sink);
128 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
129                                         ConversionSpec conv,
130                                         FormatSinkImpl* sink);
131 IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
132                                         FormatSinkImpl* sink);
133 IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
134                                         FormatSinkImpl* sink);
135 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
136                                         ConversionSpec conv,
137                                         FormatSinkImpl* sink);
138 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
139                                         ConversionSpec conv,
140                                         FormatSinkImpl* sink);
141 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
142                                         ConversionSpec conv,
143                                         FormatSinkImpl* sink);
144 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
145                                         ConversionSpec conv,
146                                         FormatSinkImpl* sink);
147 IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
148                                         FormatSinkImpl* sink);
149 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
150 IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
151                                         FormatSinkImpl* sink) {
152   return FormatConvertImpl(static_cast<int>(v), conv, sink);
153 }
154
155 // We provide this function to help the checker, but it is never defined.
156 // FormatArgImpl will use the underlying Convert functions instead.
157 template <typename T>
158 typename std::enable_if<std::is_enum<T>::value &&
159                             !HasUserDefinedConvert<T>::value,
160                         IntegralConvertResult>::type
161 FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
162
163 template <typename T>
164 ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
165                                          ConversionSpec conv,
166                                          FormatSinkImpl* out) {
167   std::ostringstream oss;
168   oss << v.v_;
169   if (!oss) return {false};
170   return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
171 }
172
173 // Use templates and dependent types to delay evaluation of the function
174 // until after FormatCountCapture is fully defined.
175 struct FormatCountCaptureHelper {
176   template <class T = int>
177   static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
178                                               ConversionSpec conv,
179                                               FormatSinkImpl* sink) {
180     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
181
182     if (conv.conv().id() != str_format_internal::ConversionChar::n)
183       return {false};
184     *v2.p_ = static_cast<int>(sink->size());
185     return {true};
186   }
187 };
188
189 template <class T = int>
190 ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
191                                          ConversionSpec conv,
192                                          FormatSinkImpl* sink) {
193   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
194 }
195
196 // Helper friend struct to hide implementation details from the public API of
197 // FormatArgImpl.
198 struct FormatArgImplFriend {
199   template <typename Arg>
200   static bool ToInt(Arg arg, int* out) {
201     // A value initialized ConversionSpec has a `none` conv, which tells the
202     // dispatcher to run the `int` conversion.
203     return arg.dispatcher_(arg.data_, {}, out);
204   }
205
206   template <typename Arg>
207   static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
208                       FormatSinkImpl* out) {
209     return arg.dispatcher_(arg.data_, conv, out);
210   }
211
212   template <typename Arg>
213   static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
214     return arg.dispatcher_;
215   }
216 };
217
218 // A type-erased handle to a format argument.
219 class FormatArgImpl {
220  private:
221   enum { kInlinedSpace = 8 };
222
223   using VoidPtr = str_format_internal::VoidPtr;
224
225   union Data {
226     const void* ptr;
227     const volatile void* volatile_ptr;
228     char buf[kInlinedSpace];
229   };
230
231   using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
232
233   template <typename T>
234   struct store_by_value
235       : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
236                                          (std::is_integral<T>::value ||
237                                           std::is_floating_point<T>::value ||
238                                           std::is_pointer<T>::value ||
239                                           std::is_same<VoidPtr, T>::value)> {};
240
241   enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
242   template <typename T>
243   struct storage_policy
244       : std::integral_constant<StoragePolicy,
245                                (std::is_volatile<T>::value
246                                     ? ByVolatilePointer
247                                     : (store_by_value<T>::value ? ByValue
248                                                                 : ByPointer))> {
249   };
250
251   // To reduce the number of vtables we will decay values before hand.
252   // Anything with a user-defined Convert will get its own vtable.
253   // For everything else:
254   //   - Decay char* and char arrays into `const char*`
255   //   - Decay any other pointer to `const void*`
256   //   - Decay all enums to their underlying type.
257   //   - Decay function pointers to void*.
258   template <typename T, typename = void>
259   struct DecayType {
260     static constexpr bool kHasUserDefined =
261         str_format_internal::HasUserDefinedConvert<T>::value;
262     using type = typename std::conditional<
263         !kHasUserDefined && std::is_convertible<T, const char*>::value,
264         const char*,
265         typename std::conditional<!kHasUserDefined &&
266                                       std::is_convertible<T, VoidPtr>::value,
267                                   VoidPtr, const T&>::type>::type;
268   };
269   template <typename T>
270   struct DecayType<T,
271                    typename std::enable_if<
272                        !str_format_internal::HasUserDefinedConvert<T>::value &&
273                        std::is_enum<T>::value>::type> {
274     using type = typename std::underlying_type<T>::type;
275   };
276
277  public:
278   template <typename T>
279   explicit FormatArgImpl(const T& value) {
280     using D = typename DecayType<T>::type;
281     static_assert(
282         std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
283         "Decayed types must be stored by value");
284     Init(static_cast<D>(value));
285   }
286
287  private:
288   friend struct str_format_internal::FormatArgImplFriend;
289   template <typename T, StoragePolicy = storage_policy<T>::value>
290   struct Manager;
291
292   template <typename T>
293   struct Manager<T, ByPointer> {
294     static Data SetValue(const T& value) {
295       Data data;
296       data.ptr = std::addressof(value);
297       return data;
298     }
299
300     static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
301   };
302
303   template <typename T>
304   struct Manager<T, ByVolatilePointer> {
305     static Data SetValue(const T& value) {
306       Data data;
307       data.volatile_ptr = &value;
308       return data;
309     }
310
311     static const T& Value(Data arg) {
312       return *static_cast<const T*>(arg.volatile_ptr);
313     }
314   };
315
316   template <typename T>
317   struct Manager<T, ByValue> {
318     static Data SetValue(const T& value) {
319       Data data;
320       memcpy(data.buf, &value, sizeof(value));
321       return data;
322     }
323
324     static T Value(Data arg) {
325       T value;
326       memcpy(&value, arg.buf, sizeof(T));
327       return value;
328     }
329   };
330
331   template <typename T>
332   void Init(const T& value) {
333     data_ = Manager<T>::SetValue(value);
334     dispatcher_ = &Dispatch<T>;
335   }
336
337   template <typename T>
338   static int ToIntVal(const T& val) {
339     using CommonType = typename std::conditional<std::is_signed<T>::value,
340                                                  int64_t, uint64_t>::type;
341     if (static_cast<CommonType>(val) >
342         static_cast<CommonType>((std::numeric_limits<int>::max)())) {
343       return (std::numeric_limits<int>::max)();
344     } else if (std::is_signed<T>::value &&
345                static_cast<CommonType>(val) <
346                    static_cast<CommonType>((std::numeric_limits<int>::min)())) {
347       return (std::numeric_limits<int>::min)();
348     }
349     return static_cast<int>(val);
350   }
351
352   template <typename T>
353   static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
354                     std::false_type) {
355     *out = ToIntVal(Manager<T>::Value(arg));
356     return true;
357   }
358
359   template <typename T>
360   static bool ToInt(Data arg, int* out, std::false_type,
361                     std::true_type /* is_enum */) {
362     *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
363         Manager<T>::Value(arg)));
364     return true;
365   }
366
367   template <typename T>
368   static bool ToInt(Data, int*, std::false_type, std::false_type) {
369     return false;
370   }
371
372   template <typename T>
373   static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
374     // A `none` conv indicates that we want the `int` conversion.
375     if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
376       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
377                       std::is_enum<T>());
378     }
379
380     return str_format_internal::FormatConvertImpl(
381                Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
382         .value;
383   }
384
385   Data data_;
386   Dispatcher dispatcher_;
387 };
388
389 #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
390   E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
391
392 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)                   \
393   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
394                                              __VA_ARGS__);                     \
395   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \
396   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \
397   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \
398   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \
399   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
400   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \
401                                              __VA_ARGS__);                     \
402   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \
403   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \
404   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \
405   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \
406                                              __VA_ARGS__);                     \
407   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \
408                                              __VA_ARGS__);                     \
409   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
410                                              __VA_ARGS__);                     \
411   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
412   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
413   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
414   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
415   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
416   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
417   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
418
419 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
420
421 }  // namespace str_format_internal
422 }  // namespace absl
423
424 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_