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 namespace absl {
22 ABSL_NAMESPACE_BEGIN
23 
24 class Cord;
25 class FormatCountCapture;
26 class FormatSink;
27 
28 template <absl::FormatConversionCharSet C>
29 struct FormatConvertResult;
30 class FormatConversionSpec;
31 
32 namespace str_format_internal {
33 
34 template <typename T, typename = void>
35 struct HasUserDefinedConvert : std::false_type {};
36 
37 template <typename T>
38 struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
39                                     std::declval<const T&>(),
40                                     std::declval<const FormatConversionSpec&>(),
41                                     std::declval<FormatSink*>()))>>
42     : std::true_type {};
43 
44 void AbslFormatConvert();  // Stops the lexical name lookup
45 template <typename T>
46 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
47                        FormatSinkImpl* sink)
48     -> decltype(AbslFormatConvert(v,
49                                   std::declval<const FormatConversionSpec&>(),
50                                   std::declval<FormatSink*>())) {
51   using FormatConversionSpecT =
52       absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
53   using FormatSinkT =
54       absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
55   auto fcs = conv.Wrap<FormatConversionSpecT>();
56   auto fs = sink->Wrap<FormatSinkT>();
57   return AbslFormatConvert(v, fcs, &fs);
58 }
59 
60 template <typename T>
61 class StreamedWrapper;
62 
63 // If 'v' can be converted (in the printf sense) according to 'conv',
64 // then convert it, appending to `sink` and return `true`.
65 // Otherwise fail and return `false`.
66 
67 // AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
68 // as an extension mechanism. These FormatConvertImpl functions are the default
69 // implementations.
70 // The ADL search is augmented via the 'Sink*' parameter, which also
71 // serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
72 // functions in the namespaces associated with 'v'.
73 
74 // Raw pointers.
75 struct VoidPtr {
76   VoidPtr() = default;
77   template <typename T,
78             decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
79   VoidPtr(T* ptr)  // NOLINT
80       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
81   uintptr_t value;
82 };
83 
84 template <FormatConversionCharSet C>
85 struct ArgConvertResult {
86   bool value;
87 };
88 
89 template <FormatConversionCharSet C>
90 constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
91   return C;
92 }
93 
94 template <FormatConversionCharSet C>
95 constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
96   return C;
97 }
98 
99 using StringConvertResult =
100     ArgConvertResult<FormatConversionCharSetInternal::s>;
101 ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
102     VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
103 
104 // Strings.
105 StringConvertResult FormatConvertImpl(const std::string& v,
106                                       FormatConversionSpecImpl conv,
107                                       FormatSinkImpl* sink);
108 StringConvertResult FormatConvertImpl(string_view v,
109                                       FormatConversionSpecImpl conv,
110                                       FormatSinkImpl* sink);
111 ArgConvertResult<FormatConversionCharSetUnion(
112     FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
113 FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
114                   FormatSinkImpl* sink);
115 
116 template <class AbslCord, typename std::enable_if<std::is_same<
117                               AbslCord, absl::Cord>::value>::type* = nullptr>
118 StringConvertResult FormatConvertImpl(const AbslCord& value,
119                                       FormatConversionSpecImpl conv,
120                                       FormatSinkImpl* sink) {
121   bool is_left = conv.has_left_flag();
122   size_t space_remaining = 0;
123 
124   int width = conv.width();
125   if (width >= 0) space_remaining = width;
126 
127   size_t to_write = value.size();
128 
129   int precision = conv.precision();
130   if (precision >= 0)
131     to_write = (std::min)(to_write, static_cast<size_t>(precision));
132 
133   space_remaining = Excess(to_write, space_remaining);
134 
135   if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
136 
137   for (string_view piece : value.Chunks()) {
138     if (piece.size() > to_write) {
139       piece.remove_suffix(piece.size() - to_write);
140       to_write = 0;
141     } else {
142       to_write -= piece.size();
143     }
144     sink->Append(piece);
145     if (to_write == 0) {
146       break;
147     }
148   }
149 
150   if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
151   return {true};
152 }
153 
154 using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
155     FormatConversionCharSetInternal::c,
156     FormatConversionCharSetInternal::kNumeric,
157     FormatConversionCharSetInternal::kStar)>;
158 using FloatingConvertResult =
159     ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
160 
161 // Floats.
162 FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
163                                         FormatSinkImpl* sink);
164 FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
165                                         FormatSinkImpl* sink);
166 FloatingConvertResult FormatConvertImpl(long double v,
167                                         FormatConversionSpecImpl conv,
168                                         FormatSinkImpl* sink);
169 
170 // Chars.
171 IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
172                                         FormatSinkImpl* sink);
173 IntegralConvertResult FormatConvertImpl(signed char v,
174                                         FormatConversionSpecImpl conv,
175                                         FormatSinkImpl* sink);
176 IntegralConvertResult FormatConvertImpl(unsigned char v,
177                                         FormatConversionSpecImpl conv,
178                                         FormatSinkImpl* sink);
179 
180 // Ints.
181 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
182                                         FormatConversionSpecImpl conv,
183                                         FormatSinkImpl* sink);
184 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
185                                         FormatConversionSpecImpl conv,
186                                         FormatSinkImpl* sink);
187 IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
188                                         FormatSinkImpl* sink);
189 IntegralConvertResult FormatConvertImpl(unsigned v,
190                                         FormatConversionSpecImpl conv,
191                                         FormatSinkImpl* sink);
192 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
193                                         FormatConversionSpecImpl conv,
194                                         FormatSinkImpl* sink);
195 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
196                                         FormatConversionSpecImpl conv,
197                                         FormatSinkImpl* sink);
198 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
199                                         FormatConversionSpecImpl conv,
200                                         FormatSinkImpl* sink);
201 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
202                                         FormatConversionSpecImpl conv,
203                                         FormatSinkImpl* sink);
204 IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
205                                         FormatSinkImpl* sink);
206 IntegralConvertResult FormatConvertImpl(uint128 v,
207                                         FormatConversionSpecImpl conv,
208                                         FormatSinkImpl* sink);
209 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
210 IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
211                                         FormatSinkImpl* sink) {
212   return FormatConvertImpl(static_cast<int>(v), conv, sink);
213 }
214 
215 // We provide this function to help the checker, but it is never defined.
216 // FormatArgImpl will use the underlying Convert functions instead.
217 template <typename T>
218 typename std::enable_if<std::is_enum<T>::value &&
219                             !HasUserDefinedConvert<T>::value,
220                         IntegralConvertResult>::type
221 FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
222 
223 template <typename T>
224 StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
225                                       FormatConversionSpecImpl conv,
226                                       FormatSinkImpl* out) {
227   std::ostringstream oss;
228   oss << v.v_;
229   if (!oss) return {false};
230   return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
231 }
232 
233 // Use templates and dependent types to delay evaluation of the function
234 // until after FormatCountCapture is fully defined.
235 struct FormatCountCaptureHelper {
236   template <class T = int>
237   static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
238       const FormatCountCapture& v, FormatConversionSpecImpl conv,
239       FormatSinkImpl* sink) {
240     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
241 
242     if (conv.conversion_char() !=
243         str_format_internal::FormatConversionCharInternal::n) {
244       return {false};
245     }
246     *v2.p_ = static_cast<int>(sink->size());
247     return {true};
248   }
249 };
250 
251 template <class T = int>
252 ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
253     const FormatCountCapture& v, FormatConversionSpecImpl conv,
254     FormatSinkImpl* sink) {
255   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
256 }
257 
258 // Helper friend struct to hide implementation details from the public API of
259 // FormatArgImpl.
260 struct FormatArgImplFriend {
261   template <typename Arg>
262   static bool ToInt(Arg arg, int* out) {
263     // A value initialized FormatConversionSpecImpl has a `none` conv, which
264     // tells the dispatcher to run the `int` conversion.
265     return arg.dispatcher_(arg.data_, {}, out);
266   }
267 
268   template <typename Arg>
269   static bool Convert(Arg arg, FormatConversionSpecImpl conv,
270                       FormatSinkImpl* out) {
271     return arg.dispatcher_(arg.data_, conv, out);
272   }
273 
274   template <typename Arg>
275   static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
276     return arg.dispatcher_;
277   }
278 };
279 
280 template <typename Arg>
281 constexpr FormatConversionCharSet ArgumentToConv() {
282   return absl::str_format_internal::ExtractCharSet(
283       decltype(str_format_internal::FormatConvertImpl(
284           std::declval<const Arg&>(),
285           std::declval<const FormatConversionSpecImpl&>(),
286           std::declval<FormatSinkImpl*>())){});
287 }
288 
289 // A type-erased handle to a format argument.
290 class FormatArgImpl {
291  private:
292   enum { kInlinedSpace = 8 };
293 
294   using VoidPtr = str_format_internal::VoidPtr;
295 
296   union Data {
297     const void* ptr;
298     const volatile void* volatile_ptr;
299     char buf[kInlinedSpace];
300   };
301 
302   using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
303 
304   template <typename T>
305   struct store_by_value
306       : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
307                                          (std::is_integral<T>::value ||
308                                           std::is_floating_point<T>::value ||
309                                           std::is_pointer<T>::value ||
310                                           std::is_same<VoidPtr, T>::value)> {};
311 
312   enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
313   template <typename T>
314   struct storage_policy
315       : std::integral_constant<StoragePolicy,
316                                (std::is_volatile<T>::value
317                                     ? ByVolatilePointer
318                                     : (store_by_value<T>::value ? ByValue
319                                                                 : ByPointer))> {
320   };
321 
322   // To reduce the number of vtables we will decay values before hand.
323   // Anything with a user-defined Convert will get its own vtable.
324   // For everything else:
325   //   - Decay char* and char arrays into `const char*`
326   //   - Decay any other pointer to `const void*`
327   //   - Decay all enums to their underlying type.
328   //   - Decay function pointers to void*.
329   template <typename T, typename = void>
330   struct DecayType {
331     static constexpr bool kHasUserDefined =
332         str_format_internal::HasUserDefinedConvert<T>::value;
333     using type = typename std::conditional<
334         !kHasUserDefined && std::is_convertible<T, const char*>::value,
335         const char*,
336         typename std::conditional<!kHasUserDefined &&
337                                       std::is_convertible<T, VoidPtr>::value,
338                                   VoidPtr, const T&>::type>::type;
339   };
340   template <typename T>
341   struct DecayType<T,
342                    typename std::enable_if<
343                        !str_format_internal::HasUserDefinedConvert<T>::value &&
344                        std::is_enum<T>::value>::type> {
345     using type = typename std::underlying_type<T>::type;
346   };
347 
348  public:
349   template <typename T>
350   explicit FormatArgImpl(const T& value) {
351     using D = typename DecayType<T>::type;
352     static_assert(
353         std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
354         "Decayed types must be stored by value");
355     Init(static_cast<D>(value));
356   }
357 
358  private:
359   friend struct str_format_internal::FormatArgImplFriend;
360   template <typename T, StoragePolicy = storage_policy<T>::value>
361   struct Manager;
362 
363   template <typename T>
364   struct Manager<T, ByPointer> {
365     static Data SetValue(const T& value) {
366       Data data;
367       data.ptr = std::addressof(value);
368       return data;
369     }
370 
371     static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
372   };
373 
374   template <typename T>
375   struct Manager<T, ByVolatilePointer> {
376     static Data SetValue(const T& value) {
377       Data data;
378       data.volatile_ptr = &value;
379       return data;
380     }
381 
382     static const T& Value(Data arg) {
383       return *static_cast<const T*>(arg.volatile_ptr);
384     }
385   };
386 
387   template <typename T>
388   struct Manager<T, ByValue> {
389     static Data SetValue(const T& value) {
390       Data data;
391       memcpy(data.buf, &value, sizeof(value));
392       return data;
393     }
394 
395     static T Value(Data arg) {
396       T value;
397       memcpy(&value, arg.buf, sizeof(T));
398       return value;
399     }
400   };
401 
402   template <typename T>
403   void Init(const T& value) {
404     data_ = Manager<T>::SetValue(value);
405     dispatcher_ = &Dispatch<T>;
406   }
407 
408   template <typename T>
409   static int ToIntVal(const T& val) {
410     using CommonType = typename std::conditional<std::is_signed<T>::value,
411                                                  int64_t, uint64_t>::type;
412     if (static_cast<CommonType>(val) >
413         static_cast<CommonType>((std::numeric_limits<int>::max)())) {
414       return (std::numeric_limits<int>::max)();
415     } else if (std::is_signed<T>::value &&
416                static_cast<CommonType>(val) <
417                    static_cast<CommonType>((std::numeric_limits<int>::min)())) {
418       return (std::numeric_limits<int>::min)();
419     }
420     return static_cast<int>(val);
421   }
422 
423   template <typename T>
424   static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
425                     std::false_type) {
426     *out = ToIntVal(Manager<T>::Value(arg));
427     return true;
428   }
429 
430   template <typename T>
431   static bool ToInt(Data arg, int* out, std::false_type,
432                     std::true_type /* is_enum */) {
433     *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
434         Manager<T>::Value(arg)));
435     return true;
436   }
437 
438   template <typename T>
439   static bool ToInt(Data, int*, std::false_type, std::false_type) {
440     return false;
441   }
442 
443   template <typename T>
444   static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
445     // A `none` conv indicates that we want the `int` conversion.
446     if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
447                            FormatConversionCharInternal::kNone)) {
448       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
449                       std::is_enum<T>());
450     }
451     if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
452                                      spec.conversion_char()))) {
453       return false;
454     }
455     return str_format_internal::FormatConvertImpl(
456                Manager<T>::Value(arg), spec,
457                static_cast<FormatSinkImpl*>(out))
458         .value;
459   }
460 
461   Data data_;
462   Dispatcher dispatcher_;
463 };
464 
465 #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E)                     \
466   E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
467                                              void*)
468 
469 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)                   \
470   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
471                                              __VA_ARGS__);                     \
472   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \
473   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \
474   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \
475   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \
476   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
477   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \
478                                              __VA_ARGS__);                     \
479   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \
480   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \
481   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \
482   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \
483                                              __VA_ARGS__);                     \
484   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \
485                                              __VA_ARGS__);                     \
486   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
487                                              __VA_ARGS__);                     \
488   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__);             \
489   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
490   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
491   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
492   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
493   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
494   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
495   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
496 
497 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
498 
499 
500 }  // namespace str_format_internal
501 ABSL_NAMESPACE_END
502 }  // namespace absl
503 
504 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
505