Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:23

0001 // Copyright 2020 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
0016 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
0017 
0018 #include <string.h>
0019 #include <wchar.h>
0020 
0021 #include <algorithm>
0022 #include <cstddef>
0023 #include <cstdint>
0024 #include <cstdio>
0025 #include <limits>
0026 #include <memory>
0027 #include <sstream>
0028 #include <string>
0029 #include <type_traits>
0030 #include <utility>
0031 
0032 #include "absl/base/config.h"
0033 #include "absl/base/optimization.h"
0034 #include "absl/meta/type_traits.h"
0035 #include "absl/numeric/int128.h"
0036 #include "absl/strings/has_absl_stringify.h"
0037 #include "absl/strings/internal/str_format/extension.h"
0038 #include "absl/strings/string_view.h"
0039 
0040 #if defined(ABSL_HAVE_STD_STRING_VIEW)
0041 #include <string_view>
0042 #endif
0043 
0044 namespace absl {
0045 ABSL_NAMESPACE_BEGIN
0046 
0047 class Cord;
0048 class FormatCountCapture;
0049 class FormatSink;
0050 
0051 template <absl::FormatConversionCharSet C>
0052 struct FormatConvertResult;
0053 class FormatConversionSpec;
0054 
0055 namespace str_format_internal {
0056 
0057 template <FormatConversionCharSet C>
0058 struct ArgConvertResult {
0059   bool value;
0060 };
0061 
0062 using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
0063     FormatConversionCharSetInternal::c,
0064     FormatConversionCharSetInternal::kNumeric,
0065     FormatConversionCharSetInternal::kStar,
0066     FormatConversionCharSetInternal::v)>;
0067 using FloatingConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
0068     FormatConversionCharSetInternal::kFloating,
0069     FormatConversionCharSetInternal::v)>;
0070 using CharConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
0071     FormatConversionCharSetInternal::c,
0072     FormatConversionCharSetInternal::kNumeric,
0073     FormatConversionCharSetInternal::kStar)>;
0074 
0075 template <typename T, typename = void>
0076 struct HasUserDefinedConvert : std::false_type {};
0077 
0078 template <typename T>
0079 struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
0080                                     std::declval<const T&>(),
0081                                     std::declval<const FormatConversionSpec&>(),
0082                                     std::declval<FormatSink*>()))>>
0083     : std::true_type {};
0084 
0085 // These declarations prevent ADL lookup from continuing in absl namespaces,
0086 // we are deliberately using these as ADL hooks and want them to consider
0087 // non-absl namespaces only.
0088 void AbslFormatConvert();
0089 void AbslStringify();
0090 
0091 template <typename T>
0092 bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
0093 
0094 // Forward declarations of internal `ConvertIntArg` function template
0095 // instantiations are here to avoid including the template body in the headers
0096 // and instantiating it in large numbers of translation units. Explicit
0097 // instantiations can be found in "absl/strings/internal/str_format/arg.cc"
0098 extern template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,
0099                                          FormatSinkImpl* sink);
0100 extern template bool ConvertIntArg<signed char>(signed char v,
0101                                                 FormatConversionSpecImpl conv,
0102                                                 FormatSinkImpl* sink);
0103 extern template bool ConvertIntArg<unsigned char>(unsigned char v,
0104                                                   FormatConversionSpecImpl conv,
0105                                                   FormatSinkImpl* sink);
0106 extern template bool ConvertIntArg<wchar_t>(wchar_t v,
0107                                             FormatConversionSpecImpl conv,
0108                                             FormatSinkImpl* sink);
0109 extern template bool ConvertIntArg<short>(short v,  // NOLINT
0110                                           FormatConversionSpecImpl conv,
0111                                           FormatSinkImpl* sink);
0112 extern template bool ConvertIntArg<unsigned short>(   // NOLINT
0113     unsigned short v, FormatConversionSpecImpl conv,  // NOLINT
0114     FormatSinkImpl* sink);
0115 extern template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,
0116                                         FormatSinkImpl* sink);
0117 extern template bool ConvertIntArg<unsigned int>(unsigned int v,
0118                                                  FormatConversionSpecImpl conv,
0119                                                  FormatSinkImpl* sink);
0120 extern template bool ConvertIntArg<long>(                           // NOLINT
0121     long v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);   // NOLINT
0122 extern template bool ConvertIntArg<unsigned long>(unsigned long v,  // NOLINT
0123                                                   FormatConversionSpecImpl conv,
0124                                                   FormatSinkImpl* sink);
0125 extern template bool ConvertIntArg<long long>(long long v,  // NOLINT
0126                                               FormatConversionSpecImpl conv,
0127                                               FormatSinkImpl* sink);
0128 extern template bool ConvertIntArg<unsigned long long>(   // NOLINT
0129     unsigned long long v, FormatConversionSpecImpl conv,  // NOLINT
0130     FormatSinkImpl* sink);
0131 
0132 template <typename T>
0133 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
0134                        FormatSinkImpl* sink)
0135     -> decltype(AbslFormatConvert(v,
0136                                   std::declval<const FormatConversionSpec&>(),
0137                                   std::declval<FormatSink*>())) {
0138   using FormatConversionSpecT =
0139       absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
0140   using FormatSinkT =
0141       absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
0142   auto fcs = conv.Wrap<FormatConversionSpecT>();
0143   auto fs = sink->Wrap<FormatSinkT>();
0144   return AbslFormatConvert(v, fcs, &fs);
0145 }
0146 
0147 template <typename T>
0148 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
0149                        FormatSinkImpl* sink)
0150     -> std::enable_if_t<std::is_enum<T>::value &&
0151                             std::is_void<decltype(AbslStringify(
0152                                 std::declval<FormatSink&>(), v))>::value,
0153                         IntegralConvertResult> {
0154   if (conv.conversion_char() == FormatConversionCharInternal::v) {
0155     using FormatSinkT =
0156         absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
0157     auto fs = sink->Wrap<FormatSinkT>();
0158     AbslStringify(fs, v);
0159     return {true};
0160   } else {
0161     return {ConvertIntArg(
0162         static_cast<typename std::underlying_type<T>::type>(v), conv, sink)};
0163   }
0164 }
0165 
0166 template <typename T>
0167 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
0168                        FormatSinkImpl* sink)
0169     -> std::enable_if_t<!std::is_enum<T>::value &&
0170                             !std::is_same<T, absl::Cord>::value &&
0171                             std::is_void<decltype(AbslStringify(
0172                                 std::declval<FormatSink&>(), v))>::value,
0173                         ArgConvertResult<FormatConversionCharSetInternal::v>> {
0174   using FormatSinkT =
0175       absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
0176   auto fs = sink->Wrap<FormatSinkT>();
0177   AbslStringify(fs, v);
0178   return {true};
0179 }
0180 
0181 template <typename T>
0182 class StreamedWrapper;
0183 
0184 // If 'v' can be converted (in the printf sense) according to 'conv',
0185 // then convert it, appending to `sink` and return `true`.
0186 // Otherwise fail and return `false`.
0187 
0188 // AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
0189 // as an extension mechanism. These FormatConvertImpl functions are the default
0190 // implementations.
0191 // The ADL search is augmented via the 'Sink*' parameter, which also
0192 // serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
0193 // functions in the namespaces associated with 'v'.
0194 
0195 // Raw pointers.
0196 struct VoidPtr {
0197   VoidPtr() = default;
0198   template <typename T,
0199             decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
0200   VoidPtr(T* ptr)  // NOLINT
0201       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
0202   uintptr_t value;
0203 };
0204 
0205 template <FormatConversionCharSet C>
0206 constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
0207   return C;
0208 }
0209 
0210 template <FormatConversionCharSet C>
0211 constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
0212   return C;
0213 }
0214 
0215 ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
0216     VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
0217 
0218 // Strings.
0219 using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
0220     FormatConversionCharSetInternal::s,
0221     FormatConversionCharSetInternal::v)>;
0222 StringConvertResult FormatConvertImpl(const std::string& v,
0223                                       FormatConversionSpecImpl conv,
0224                                       FormatSinkImpl* sink);
0225 StringConvertResult FormatConvertImpl(const std::wstring& v,
0226                                       FormatConversionSpecImpl conv,
0227                                       FormatSinkImpl* sink);
0228 StringConvertResult FormatConvertImpl(string_view v,
0229                                       FormatConversionSpecImpl conv,
0230                                       FormatSinkImpl* sink);
0231 #if defined(ABSL_HAVE_STD_STRING_VIEW)
0232 StringConvertResult FormatConvertImpl(std::wstring_view v,
0233                                       FormatConversionSpecImpl conv,
0234                                       FormatSinkImpl* sink);
0235 #if !defined(ABSL_USES_STD_STRING_VIEW)
0236 inline StringConvertResult FormatConvertImpl(std::string_view v,
0237                                              FormatConversionSpecImpl conv,
0238                                              FormatSinkImpl* sink) {
0239   return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);
0240 }
0241 #endif  // !ABSL_USES_STD_STRING_VIEW
0242 #endif  // ABSL_HAVE_STD_STRING_VIEW
0243 
0244 using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
0245     FormatConversionCharSetInternal::s,
0246     FormatConversionCharSetInternal::p)>;
0247 StringPtrConvertResult FormatConvertImpl(const char* v,
0248                                          FormatConversionSpecImpl conv,
0249                                          FormatSinkImpl* sink);
0250 StringPtrConvertResult FormatConvertImpl(const wchar_t* v,
0251                                          FormatConversionSpecImpl conv,
0252                                          FormatSinkImpl* sink);
0253 // This overload is needed to disambiguate, since `nullptr` could match either
0254 // of the other overloads equally well.
0255 StringPtrConvertResult FormatConvertImpl(std::nullptr_t,
0256                                          FormatConversionSpecImpl conv,
0257                                          FormatSinkImpl* sink);
0258 
0259 template <class AbslCord, typename std::enable_if<std::is_same<
0260                               AbslCord, absl::Cord>::value>::type* = nullptr>
0261 StringConvertResult FormatConvertImpl(const AbslCord& value,
0262                                       FormatConversionSpecImpl conv,
0263                                       FormatSinkImpl* sink) {
0264   bool is_left = conv.has_left_flag();
0265   size_t space_remaining = 0;
0266 
0267   int width = conv.width();
0268   if (width >= 0) space_remaining = static_cast<size_t>(width);
0269 
0270   size_t to_write = value.size();
0271 
0272   int precision = conv.precision();
0273   if (precision >= 0)
0274     to_write = (std::min)(to_write, static_cast<size_t>(precision));
0275 
0276   space_remaining = Excess(to_write, space_remaining);
0277 
0278   if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
0279 
0280   for (string_view piece : value.Chunks()) {
0281     if (piece.size() > to_write) {
0282       piece.remove_suffix(piece.size() - to_write);
0283       to_write = 0;
0284     } else {
0285       to_write -= piece.size();
0286     }
0287     sink->Append(piece);
0288     if (to_write == 0) {
0289       break;
0290     }
0291   }
0292 
0293   if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
0294   return {true};
0295 }
0296 
0297 bool ConvertBoolArg(bool v, FormatSinkImpl* sink);
0298 
0299 // Floats.
0300 FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
0301                                         FormatSinkImpl* sink);
0302 FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
0303                                         FormatSinkImpl* sink);
0304 FloatingConvertResult FormatConvertImpl(long double v,
0305                                         FormatConversionSpecImpl conv,
0306                                         FormatSinkImpl* sink);
0307 
0308 // Chars.
0309 CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
0310                                     FormatSinkImpl* sink);
0311 CharConvertResult FormatConvertImpl(wchar_t v,
0312                                     FormatConversionSpecImpl conv,
0313                                     FormatSinkImpl* sink);
0314 
0315 // Ints.
0316 IntegralConvertResult FormatConvertImpl(signed char v,
0317                                         FormatConversionSpecImpl conv,
0318                                         FormatSinkImpl* sink);
0319 IntegralConvertResult FormatConvertImpl(unsigned char v,
0320                                         FormatConversionSpecImpl conv,
0321                                         FormatSinkImpl* sink);
0322 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
0323                                         FormatConversionSpecImpl conv,
0324                                         FormatSinkImpl* sink);
0325 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
0326                                         FormatConversionSpecImpl conv,
0327                                         FormatSinkImpl* sink);
0328 IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
0329                                         FormatSinkImpl* sink);
0330 IntegralConvertResult FormatConvertImpl(unsigned v,
0331                                         FormatConversionSpecImpl conv,
0332                                         FormatSinkImpl* sink);
0333 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
0334                                         FormatConversionSpecImpl conv,
0335                                         FormatSinkImpl* sink);
0336 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
0337                                         FormatConversionSpecImpl conv,
0338                                         FormatSinkImpl* sink);
0339 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
0340                                         FormatConversionSpecImpl conv,
0341                                         FormatSinkImpl* sink);
0342 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
0343                                         FormatConversionSpecImpl conv,
0344                                         FormatSinkImpl* sink);
0345 IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
0346                                         FormatSinkImpl* sink);
0347 IntegralConvertResult FormatConvertImpl(uint128 v,
0348                                         FormatConversionSpecImpl conv,
0349                                         FormatSinkImpl* sink);
0350 
0351 // This function needs to be a template due to ambiguity regarding type
0352 // conversions.
0353 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
0354 IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
0355                                         FormatSinkImpl* sink) {
0356   if (conv.conversion_char() == FormatConversionCharInternal::v) {
0357     return {ConvertBoolArg(v, sink)};
0358   }
0359 
0360   return FormatConvertImpl(static_cast<int>(v), conv, sink);
0361 }
0362 
0363 // We provide this function to help the checker, but it is never defined.
0364 // FormatArgImpl will use the underlying Convert functions instead.
0365 template <typename T>
0366 typename std::enable_if<std::is_enum<T>::value &&
0367                             !HasUserDefinedConvert<T>::value &&
0368                             !HasAbslStringify<T>::value,
0369                         IntegralConvertResult>::type
0370 FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
0371 
0372 template <typename T>
0373 StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
0374                                       FormatConversionSpecImpl conv,
0375                                       FormatSinkImpl* out) {
0376   std::ostringstream oss;
0377   oss << v.v_;
0378   if (!oss) return {false};
0379   return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
0380 }
0381 
0382 // Use templates and dependent types to delay evaluation of the function
0383 // until after FormatCountCapture is fully defined.
0384 struct FormatCountCaptureHelper {
0385   template <class T = int>
0386   static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
0387       const FormatCountCapture& v, FormatConversionSpecImpl conv,
0388       FormatSinkImpl* sink) {
0389     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
0390 
0391     if (conv.conversion_char() !=
0392         str_format_internal::FormatConversionCharInternal::n) {
0393       return {false};
0394     }
0395     *v2.p_ = static_cast<int>(sink->size());
0396     return {true};
0397   }
0398 };
0399 
0400 template <class T = int>
0401 ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
0402     const FormatCountCapture& v, FormatConversionSpecImpl conv,
0403     FormatSinkImpl* sink) {
0404   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
0405 }
0406 
0407 // Helper friend struct to hide implementation details from the public API of
0408 // FormatArgImpl.
0409 struct FormatArgImplFriend {
0410   template <typename Arg>
0411   static bool ToInt(Arg arg, int* out) {
0412     // A value initialized FormatConversionSpecImpl has a `none` conv, which
0413     // tells the dispatcher to run the `int` conversion.
0414     return arg.dispatcher_(arg.data_, {}, out);
0415   }
0416 
0417   template <typename Arg>
0418   static bool Convert(Arg arg, FormatConversionSpecImpl conv,
0419                       FormatSinkImpl* out) {
0420     return arg.dispatcher_(arg.data_, conv, out);
0421   }
0422 
0423   template <typename Arg>
0424   static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
0425     return arg.dispatcher_;
0426   }
0427 };
0428 
0429 template <typename Arg>
0430 constexpr FormatConversionCharSet ArgumentToConv() {
0431   using ConvResult = decltype(str_format_internal::FormatConvertImpl(
0432       std::declval<const Arg&>(),
0433       std::declval<const FormatConversionSpecImpl&>(),
0434       std::declval<FormatSinkImpl*>()));
0435   return absl::str_format_internal::ExtractCharSet(ConvResult{});
0436 }
0437 
0438 // A type-erased handle to a format argument.
0439 class FormatArgImpl {
0440  private:
0441   enum { kInlinedSpace = 8 };
0442 
0443   using VoidPtr = str_format_internal::VoidPtr;
0444 
0445   union Data {
0446     const void* ptr;
0447     const volatile void* volatile_ptr;
0448     char buf[kInlinedSpace];
0449   };
0450 
0451   using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
0452 
0453   template <typename T>
0454   struct store_by_value
0455       : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
0456                                          (std::is_integral<T>::value ||
0457                                           std::is_floating_point<T>::value ||
0458                                           std::is_pointer<T>::value ||
0459                                           std::is_same<VoidPtr, T>::value)> {};
0460 
0461   enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
0462   template <typename T>
0463   struct storage_policy
0464       : std::integral_constant<StoragePolicy,
0465                                (std::is_volatile<T>::value
0466                                     ? ByVolatilePointer
0467                                     : (store_by_value<T>::value ? ByValue
0468                                                                 : ByPointer))> {
0469   };
0470 
0471   // To reduce the number of vtables we will decay values before hand.
0472   // Anything with a user-defined Convert will get its own vtable.
0473   // For everything else:
0474   //   - Decay char* and char arrays into `const char*`
0475   //   - Decay wchar_t* and wchar_t arrays into `const wchar_t*`
0476   //   - Decay any other pointer to `const void*`
0477   //   - Decay all enums to the integral promotion of their underlying type.
0478   //   - Decay function pointers to void*.
0479   template <typename T, typename = void>
0480   struct DecayType {
0481     static constexpr bool kHasUserDefined =
0482         str_format_internal::HasUserDefinedConvert<T>::value ||
0483         HasAbslStringify<T>::value;
0484     using type = typename std::conditional<
0485         !kHasUserDefined && std::is_convertible<T, const char*>::value,
0486         const char*,
0487         typename std::conditional<
0488             !kHasUserDefined && std::is_convertible<T, const wchar_t*>::value,
0489             const wchar_t*,
0490             typename std::conditional<
0491                 !kHasUserDefined && std::is_convertible<T, VoidPtr>::value,
0492                 VoidPtr,
0493                 const T&>::type>::type>::type;
0494   };
0495   template <typename T>
0496   struct DecayType<
0497       T, typename std::enable_if<
0498              !str_format_internal::HasUserDefinedConvert<T>::value &&
0499              !HasAbslStringify<T>::value && std::is_enum<T>::value>::type> {
0500     using type = decltype(+typename std::underlying_type<T>::type());
0501   };
0502 
0503  public:
0504   template <typename T>
0505   explicit FormatArgImpl(const T& value) {
0506     using D = typename DecayType<T>::type;
0507     static_assert(
0508         std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
0509         "Decayed types must be stored by value");
0510     Init(static_cast<D>(value));
0511   }
0512 
0513  private:
0514   friend struct str_format_internal::FormatArgImplFriend;
0515   template <typename T, StoragePolicy = storage_policy<T>::value>
0516   struct Manager;
0517 
0518   template <typename T>
0519   struct Manager<T, ByPointer> {
0520     static Data SetValue(const T& value) {
0521       Data data;
0522       data.ptr = std::addressof(value);
0523       return data;
0524     }
0525 
0526     static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
0527   };
0528 
0529   template <typename T>
0530   struct Manager<T, ByVolatilePointer> {
0531     static Data SetValue(const T& value) {
0532       Data data;
0533       data.volatile_ptr = &value;
0534       return data;
0535     }
0536 
0537     static const T& Value(Data arg) {
0538       return *static_cast<const T*>(arg.volatile_ptr);
0539     }
0540   };
0541 
0542   template <typename T>
0543   struct Manager<T, ByValue> {
0544     static Data SetValue(const T& value) {
0545       Data data;
0546       memcpy(data.buf, &value, sizeof(value));
0547       return data;
0548     }
0549 
0550     static T Value(Data arg) {
0551       T value;
0552       memcpy(&value, arg.buf, sizeof(T));
0553       return value;
0554     }
0555   };
0556 
0557   template <typename T>
0558   void Init(const T& value) {
0559     data_ = Manager<T>::SetValue(value);
0560     dispatcher_ = &Dispatch<T>;
0561   }
0562 
0563   template <typename T>
0564   static int ToIntVal(const T& val) {
0565     using CommonType = typename std::conditional<std::is_signed<T>::value,
0566                                                  int64_t, uint64_t>::type;
0567     if (static_cast<CommonType>(val) >
0568         static_cast<CommonType>((std::numeric_limits<int>::max)())) {
0569       return (std::numeric_limits<int>::max)();
0570     } else if (std::is_signed<T>::value &&
0571                static_cast<CommonType>(val) <
0572                    static_cast<CommonType>((std::numeric_limits<int>::min)())) {
0573       return (std::numeric_limits<int>::min)();
0574     }
0575     return static_cast<int>(val);
0576   }
0577 
0578   template <typename T>
0579   static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
0580                     std::false_type) {
0581     *out = ToIntVal(Manager<T>::Value(arg));
0582     return true;
0583   }
0584 
0585   template <typename T>
0586   static bool ToInt(Data arg, int* out, std::false_type,
0587                     std::true_type /* is_enum */) {
0588     *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
0589         Manager<T>::Value(arg)));
0590     return true;
0591   }
0592 
0593   template <typename T>
0594   static bool ToInt(Data, int*, std::false_type, std::false_type) {
0595     return false;
0596   }
0597 
0598   template <typename T>
0599   static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
0600     // A `none` conv indicates that we want the `int` conversion.
0601     if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
0602                            FormatConversionCharInternal::kNone)) {
0603       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
0604                       std::is_enum<T>());
0605     }
0606     if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
0607                                      spec.conversion_char()))) {
0608       return false;
0609     }
0610     return str_format_internal::FormatConvertImpl(
0611                Manager<T>::Value(arg), spec,
0612                static_cast<FormatSinkImpl*>(out))
0613         .value;
0614   }
0615 
0616   Data data_;
0617   Dispatcher dispatcher_;
0618 };
0619 
0620 #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E)                     \
0621   E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
0622                                              void*)
0623 
0624 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(...)   \
0625   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
0626                                              __VA_ARGS__);                     \
0627   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \
0628   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \
0629   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \
0630   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \
0631   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
0632   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \
0633                                              __VA_ARGS__);                     \
0634   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \
0635   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \
0636   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \
0637   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \
0638                                              __VA_ARGS__);                     \
0639   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \
0640                                              __VA_ARGS__);                     \
0641   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
0642                                              __VA_ARGS__);                     \
0643   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__);             \
0644   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
0645   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
0646   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
0647   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
0648   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
0649   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
0650   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__);        \
0651   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__);     \
0652   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__)
0653 
0654 #if defined(ABSL_HAVE_STD_STRING_VIEW)
0655 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)       \
0656   ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \
0657       __VA_ARGS__);                                                \
0658   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__)
0659 #else
0660 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
0661   ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(__VA_ARGS__)
0662 #endif
0663 
0664 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
0665 
0666 
0667 }  // namespace str_format_internal
0668 ABSL_NAMESPACE_END
0669 }  // namespace absl
0670 
0671 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_