tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

arg.h (27788B)


      1 // Copyright 2020 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
     16 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
     17 
     18 #include <string.h>
     19 #include <wchar.h>
     20 
     21 #include <algorithm>
     22 #include <cstddef>
     23 #include <cstdint>
     24 #include <cstdio>
     25 #include <limits>
     26 #include <memory>
     27 #include <sstream>
     28 #include <string>
     29 #include <type_traits>
     30 #include <utility>
     31 
     32 #include "absl/base/config.h"
     33 #include "absl/base/optimization.h"
     34 #include "absl/meta/type_traits.h"
     35 #include "absl/numeric/int128.h"
     36 #include "absl/strings/has_absl_stringify.h"
     37 #include "absl/strings/internal/str_format/extension.h"
     38 #include "absl/strings/string_view.h"
     39 
     40 #if defined(ABSL_HAVE_STD_STRING_VIEW)
     41 #include <string_view>
     42 #endif
     43 
     44 namespace absl {
     45 ABSL_NAMESPACE_BEGIN
     46 
     47 class Cord;
     48 class FormatCountCapture;
     49 class FormatSink;
     50 
     51 template <absl::FormatConversionCharSet C>
     52 struct FormatConvertResult;
     53 class FormatConversionSpec;
     54 
     55 namespace str_format_internal {
     56 
     57 template <FormatConversionCharSet C>
     58 struct ArgConvertResult {
     59  bool value;
     60 };
     61 
     62 using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
     63    FormatConversionCharSetInternal::c,
     64    FormatConversionCharSetInternal::kNumeric,
     65    FormatConversionCharSetInternal::kStar,
     66    FormatConversionCharSetInternal::v)>;
     67 using FloatingConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
     68    FormatConversionCharSetInternal::kFloating,
     69    FormatConversionCharSetInternal::v)>;
     70 using CharConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
     71    FormatConversionCharSetInternal::c,
     72    FormatConversionCharSetInternal::kNumeric,
     73    FormatConversionCharSetInternal::kStar)>;
     74 
     75 template <typename T, typename = void>
     76 struct HasUserDefinedConvert : std::false_type {};
     77 
     78 template <typename T>
     79 struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
     80                                    std::declval<const T&>(),
     81                                    std::declval<const FormatConversionSpec&>(),
     82                                    std::declval<FormatSink*>()))>>
     83    : std::true_type {};
     84 
     85 // These declarations prevent ADL lookup from continuing in absl namespaces,
     86 // we are deliberately using these as ADL hooks and want them to consider
     87 // non-absl namespaces only.
     88 void AbslFormatConvert();
     89 void AbslStringify();
     90 
     91 template <typename T>
     92 bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
     93 
     94 // Forward declarations of internal `ConvertIntArg` function template
     95 // instantiations are here to avoid including the template body in the headers
     96 // and instantiating it in large numbers of translation units. Explicit
     97 // instantiations can be found in "absl/strings/internal/str_format/arg.cc"
     98 extern template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,
     99                                         FormatSinkImpl* sink);
    100 extern template bool ConvertIntArg<signed char>(signed char v,
    101                                                FormatConversionSpecImpl conv,
    102                                                FormatSinkImpl* sink);
    103 extern template bool ConvertIntArg<unsigned char>(unsigned char v,
    104                                                  FormatConversionSpecImpl conv,
    105                                                  FormatSinkImpl* sink);
    106 extern template bool ConvertIntArg<wchar_t>(wchar_t v,
    107                                            FormatConversionSpecImpl conv,
    108                                            FormatSinkImpl* sink);
    109 extern template bool ConvertIntArg<short>(short v,  // NOLINT
    110                                          FormatConversionSpecImpl conv,
    111                                          FormatSinkImpl* sink);
    112 extern template bool ConvertIntArg<unsigned short>(   // NOLINT
    113    unsigned short v, FormatConversionSpecImpl conv,  // NOLINT
    114    FormatSinkImpl* sink);
    115 extern template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,
    116                                        FormatSinkImpl* sink);
    117 extern template bool ConvertIntArg<unsigned int>(unsigned int v,
    118                                                 FormatConversionSpecImpl conv,
    119                                                 FormatSinkImpl* sink);
    120 extern template bool ConvertIntArg<long>(                           // NOLINT
    121    long v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);   // NOLINT
    122 extern template bool ConvertIntArg<unsigned long>(unsigned long v,  // NOLINT
    123                                                  FormatConversionSpecImpl conv,
    124                                                  FormatSinkImpl* sink);
    125 extern template bool ConvertIntArg<long long>(long long v,  // NOLINT
    126                                              FormatConversionSpecImpl conv,
    127                                              FormatSinkImpl* sink);
    128 extern template bool ConvertIntArg<unsigned long long>(   // NOLINT
    129    unsigned long long v, FormatConversionSpecImpl conv,  // NOLINT
    130    FormatSinkImpl* sink);
    131 
    132 template <typename T>
    133 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
    134                       FormatSinkImpl* sink)
    135    -> decltype(AbslFormatConvert(v,
    136                                  std::declval<const FormatConversionSpec&>(),
    137                                  std::declval<FormatSink*>())) {
    138  using FormatConversionSpecT =
    139      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
    140  using FormatSinkT =
    141      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
    142  auto fcs = conv.Wrap<FormatConversionSpecT>();
    143  auto fs = sink->Wrap<FormatSinkT>();
    144  return AbslFormatConvert(v, fcs, &fs);
    145 }
    146 
    147 template <typename T>
    148 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
    149                       FormatSinkImpl* sink)
    150    -> std::enable_if_t<std::is_enum<T>::value &&
    151                            std::is_void<decltype(AbslStringify(
    152                                std::declval<FormatSink&>(), v))>::value,
    153                        IntegralConvertResult> {
    154  if (conv.conversion_char() == FormatConversionCharInternal::v) {
    155    using FormatSinkT =
    156        absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
    157    auto fs = sink->Wrap<FormatSinkT>();
    158    AbslStringify(fs, v);
    159    return {true};
    160  } else {
    161    return {ConvertIntArg(
    162        static_cast<typename std::underlying_type<T>::type>(v), conv, sink)};
    163  }
    164 }
    165 
    166 template <typename T>
    167 auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
    168                       FormatSinkImpl* sink)
    169    -> std::enable_if_t<!std::is_enum<T>::value &&
    170                            !std::is_same<T, absl::Cord>::value &&
    171                            std::is_void<decltype(AbslStringify(
    172                                std::declval<FormatSink&>(), v))>::value,
    173                        ArgConvertResult<FormatConversionCharSetInternal::v>> {
    174  using FormatSinkT =
    175      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
    176  auto fs = sink->Wrap<FormatSinkT>();
    177  AbslStringify(fs, v);
    178  return {true};
    179 }
    180 
    181 template <typename T>
    182 class StreamedWrapper;
    183 
    184 // If 'v' can be converted (in the printf sense) according to 'conv',
    185 // then convert it, appending to `sink` and return `true`.
    186 // Otherwise fail and return `false`.
    187 
    188 // AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
    189 // as an extension mechanism. These FormatConvertImpl functions are the default
    190 // implementations.
    191 // The ADL search is augmented via the 'Sink*' parameter, which also
    192 // serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
    193 // functions in the namespaces associated with 'v'.
    194 
    195 // Raw pointers.
    196 struct VoidPtr {
    197  VoidPtr() = default;
    198  template <typename T,
    199            decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
    200  VoidPtr(T* ptr)  // NOLINT
    201      : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
    202  uintptr_t value;
    203 };
    204 
    205 template <FormatConversionCharSet C>
    206 constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
    207  return C;
    208 }
    209 
    210 template <FormatConversionCharSet C>
    211 constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
    212  return C;
    213 }
    214 
    215 ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
    216    VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
    217 
    218 // Strings.
    219 using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
    220    FormatConversionCharSetInternal::s,
    221    FormatConversionCharSetInternal::v)>;
    222 StringConvertResult FormatConvertImpl(const std::string& v,
    223                                      FormatConversionSpecImpl conv,
    224                                      FormatSinkImpl* sink);
    225 StringConvertResult FormatConvertImpl(const std::wstring& v,
    226                                      FormatConversionSpecImpl conv,
    227                                      FormatSinkImpl* sink);
    228 StringConvertResult FormatConvertImpl(string_view v,
    229                                      FormatConversionSpecImpl conv,
    230                                      FormatSinkImpl* sink);
    231 #if defined(ABSL_HAVE_STD_STRING_VIEW)
    232 StringConvertResult FormatConvertImpl(std::wstring_view v,
    233                                      FormatConversionSpecImpl conv,
    234                                      FormatSinkImpl* sink);
    235 #if !defined(ABSL_USES_STD_STRING_VIEW)
    236 inline StringConvertResult FormatConvertImpl(std::string_view v,
    237                                             FormatConversionSpecImpl conv,
    238                                             FormatSinkImpl* sink) {
    239  return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);
    240 }
    241 #endif  // !ABSL_USES_STD_STRING_VIEW
    242 #endif  // ABSL_HAVE_STD_STRING_VIEW
    243 
    244 using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
    245    FormatConversionCharSetInternal::s,
    246    FormatConversionCharSetInternal::p)>;
    247 StringPtrConvertResult FormatConvertImpl(const char* v,
    248                                         FormatConversionSpecImpl conv,
    249                                         FormatSinkImpl* sink);
    250 StringPtrConvertResult FormatConvertImpl(const wchar_t* v,
    251                                         FormatConversionSpecImpl conv,
    252                                         FormatSinkImpl* sink);
    253 // This overload is needed to disambiguate, since `nullptr` could match either
    254 // of the other overloads equally well.
    255 StringPtrConvertResult FormatConvertImpl(std::nullptr_t,
    256                                         FormatConversionSpecImpl conv,
    257                                         FormatSinkImpl* sink);
    258 
    259 template <class AbslCord, typename std::enable_if<std::is_same<
    260                              AbslCord, absl::Cord>::value>::type* = nullptr>
    261 StringConvertResult FormatConvertImpl(const AbslCord& value,
    262                                      FormatConversionSpecImpl conv,
    263                                      FormatSinkImpl* sink) {
    264  bool is_left = conv.has_left_flag();
    265  size_t space_remaining = 0;
    266 
    267  int width = conv.width();
    268  if (width >= 0) space_remaining = static_cast<size_t>(width);
    269 
    270  size_t to_write = value.size();
    271 
    272  int precision = conv.precision();
    273  if (precision >= 0)
    274    to_write = (std::min)(to_write, static_cast<size_t>(precision));
    275 
    276  space_remaining = Excess(to_write, space_remaining);
    277 
    278  if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
    279 
    280  for (string_view piece : value.Chunks()) {
    281    if (piece.size() > to_write) {
    282      piece.remove_suffix(piece.size() - to_write);
    283      to_write = 0;
    284    } else {
    285      to_write -= piece.size();
    286    }
    287    sink->Append(piece);
    288    if (to_write == 0) {
    289      break;
    290    }
    291  }
    292 
    293  if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
    294  return {true};
    295 }
    296 
    297 bool ConvertBoolArg(bool v, FormatSinkImpl* sink);
    298 
    299 // Floats.
    300 FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
    301                                        FormatSinkImpl* sink);
    302 FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
    303                                        FormatSinkImpl* sink);
    304 FloatingConvertResult FormatConvertImpl(long double v,
    305                                        FormatConversionSpecImpl conv,
    306                                        FormatSinkImpl* sink);
    307 
    308 // Chars.
    309 CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
    310                                    FormatSinkImpl* sink);
    311 CharConvertResult FormatConvertImpl(wchar_t v,
    312                                    FormatConversionSpecImpl conv,
    313                                    FormatSinkImpl* sink);
    314 
    315 // Ints.
    316 IntegralConvertResult FormatConvertImpl(signed char v,
    317                                        FormatConversionSpecImpl conv,
    318                                        FormatSinkImpl* sink);
    319 IntegralConvertResult FormatConvertImpl(unsigned char v,
    320                                        FormatConversionSpecImpl conv,
    321                                        FormatSinkImpl* sink);
    322 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
    323                                        FormatConversionSpecImpl conv,
    324                                        FormatSinkImpl* sink);
    325 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
    326                                        FormatConversionSpecImpl conv,
    327                                        FormatSinkImpl* sink);
    328 IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
    329                                        FormatSinkImpl* sink);
    330 IntegralConvertResult FormatConvertImpl(unsigned v,
    331                                        FormatConversionSpecImpl conv,
    332                                        FormatSinkImpl* sink);
    333 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
    334                                        FormatConversionSpecImpl conv,
    335                                        FormatSinkImpl* sink);
    336 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
    337                                        FormatConversionSpecImpl conv,
    338                                        FormatSinkImpl* sink);
    339 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
    340                                        FormatConversionSpecImpl conv,
    341                                        FormatSinkImpl* sink);
    342 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
    343                                        FormatConversionSpecImpl conv,
    344                                        FormatSinkImpl* sink);
    345 IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
    346                                        FormatSinkImpl* sink);
    347 IntegralConvertResult FormatConvertImpl(uint128 v,
    348                                        FormatConversionSpecImpl conv,
    349                                        FormatSinkImpl* sink);
    350 
    351 // This function needs to be a template due to ambiguity regarding type
    352 // conversions.
    353 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
    354 IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
    355                                        FormatSinkImpl* sink) {
    356  if (conv.conversion_char() == FormatConversionCharInternal::v) {
    357    return {ConvertBoolArg(v, sink)};
    358  }
    359 
    360  return FormatConvertImpl(static_cast<int>(v), conv, sink);
    361 }
    362 
    363 // We provide this function to help the checker, but it is never defined.
    364 // FormatArgImpl will use the underlying Convert functions instead.
    365 template <typename T>
    366 typename std::enable_if<std::is_enum<T>::value &&
    367                            !HasUserDefinedConvert<T>::value &&
    368                            !HasAbslStringify<T>::value,
    369                        IntegralConvertResult>::type
    370 FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
    371 
    372 template <typename T>
    373 StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
    374                                      FormatConversionSpecImpl conv,
    375                                      FormatSinkImpl* out) {
    376  std::ostringstream oss;
    377  oss << v.v_;
    378  if (!oss) return {false};
    379  return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
    380 }
    381 
    382 // Use templates and dependent types to delay evaluation of the function
    383 // until after FormatCountCapture is fully defined.
    384 struct FormatCountCaptureHelper {
    385  template <class T = int>
    386  static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
    387      const FormatCountCapture& v, FormatConversionSpecImpl conv,
    388      FormatSinkImpl* sink) {
    389    const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
    390 
    391    if (conv.conversion_char() !=
    392        str_format_internal::FormatConversionCharInternal::n) {
    393      return {false};
    394    }
    395    *v2.p_ = static_cast<int>(sink->size());
    396    return {true};
    397  }
    398 };
    399 
    400 template <class T = int>
    401 ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
    402    const FormatCountCapture& v, FormatConversionSpecImpl conv,
    403    FormatSinkImpl* sink) {
    404  return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
    405 }
    406 
    407 // Helper friend struct to hide implementation details from the public API of
    408 // FormatArgImpl.
    409 struct FormatArgImplFriend {
    410  template <typename Arg>
    411  static bool ToInt(Arg arg, int* out) {
    412    // A value initialized FormatConversionSpecImpl has a `none` conv, which
    413    // tells the dispatcher to run the `int` conversion.
    414    return arg.dispatcher_(arg.data_, {}, out);
    415  }
    416 
    417  template <typename Arg>
    418  static bool Convert(Arg arg, FormatConversionSpecImpl conv,
    419                      FormatSinkImpl* out) {
    420    return arg.dispatcher_(arg.data_, conv, out);
    421  }
    422 
    423  template <typename Arg>
    424  static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
    425    return arg.dispatcher_;
    426  }
    427 };
    428 
    429 template <typename Arg>
    430 constexpr FormatConversionCharSet ArgumentToConv() {
    431  using ConvResult = decltype(str_format_internal::FormatConvertImpl(
    432      std::declval<const Arg&>(),
    433      std::declval<const FormatConversionSpecImpl&>(),
    434      std::declval<FormatSinkImpl*>()));
    435  return absl::str_format_internal::ExtractCharSet(ConvResult{});
    436 }
    437 
    438 // A type-erased handle to a format argument.
    439 class FormatArgImpl {
    440 private:
    441  enum { kInlinedSpace = 8 };
    442 
    443  using VoidPtr = str_format_internal::VoidPtr;
    444 
    445  union Data {
    446    const void* ptr;
    447    const volatile void* volatile_ptr;
    448    char buf[kInlinedSpace];
    449  };
    450 
    451  using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
    452 
    453  template <typename T>
    454  struct store_by_value
    455      : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
    456                                         (std::is_integral<T>::value ||
    457                                          std::is_floating_point<T>::value ||
    458                                          std::is_pointer<T>::value ||
    459                                          std::is_same<VoidPtr, T>::value)> {};
    460 
    461  enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
    462  template <typename T>
    463  struct storage_policy
    464      : std::integral_constant<StoragePolicy,
    465                               (std::is_volatile<T>::value
    466                                    ? ByVolatilePointer
    467                                    : (store_by_value<T>::value ? ByValue
    468                                                                : ByPointer))> {
    469  };
    470 
    471  // To reduce the number of vtables we will decay values before hand.
    472  // Anything with a user-defined Convert will get its own vtable.
    473  // For everything else:
    474  //   - Decay char* and char arrays into `const char*`
    475  //   - Decay wchar_t* and wchar_t arrays into `const wchar_t*`
    476  //   - Decay any other pointer to `const void*`
    477  //   - Decay all enums to the integral promotion of their underlying type.
    478  //   - Decay function pointers to void*.
    479  template <typename T, typename = void>
    480  struct DecayType {
    481    static constexpr bool kHasUserDefined =
    482        str_format_internal::HasUserDefinedConvert<T>::value ||
    483        HasAbslStringify<T>::value;
    484    using type = typename std::conditional<
    485        !kHasUserDefined && std::is_convertible<T, const char*>::value,
    486        const char*,
    487        typename std::conditional<
    488            !kHasUserDefined && std::is_convertible<T, const wchar_t*>::value,
    489            const wchar_t*,
    490            typename std::conditional<
    491                !kHasUserDefined && std::is_convertible<T, VoidPtr>::value,
    492                VoidPtr,
    493                const T&>::type>::type>::type;
    494  };
    495  template <typename T>
    496  struct DecayType<
    497      T, typename std::enable_if<
    498             !str_format_internal::HasUserDefinedConvert<T>::value &&
    499             !HasAbslStringify<T>::value && std::is_enum<T>::value>::type> {
    500    using type = decltype(+typename std::underlying_type<T>::type());
    501  };
    502 
    503 public:
    504  template <typename T>
    505  explicit FormatArgImpl(const T& value) {
    506    using D = typename DecayType<T>::type;
    507    static_assert(
    508        std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
    509        "Decayed types must be stored by value");
    510    Init(static_cast<D>(value));
    511  }
    512 
    513 private:
    514  friend struct str_format_internal::FormatArgImplFriend;
    515  template <typename T, StoragePolicy = storage_policy<T>::value>
    516  struct Manager;
    517 
    518  template <typename T>
    519  struct Manager<T, ByPointer> {
    520    static Data SetValue(const T& value) {
    521      Data data;
    522      data.ptr = std::addressof(value);
    523      return data;
    524    }
    525 
    526    static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
    527  };
    528 
    529  template <typename T>
    530  struct Manager<T, ByVolatilePointer> {
    531    static Data SetValue(const T& value) {
    532      Data data;
    533      data.volatile_ptr = &value;
    534      return data;
    535    }
    536 
    537    static const T& Value(Data arg) {
    538      return *static_cast<const T*>(arg.volatile_ptr);
    539    }
    540  };
    541 
    542  template <typename T>
    543  struct Manager<T, ByValue> {
    544    static Data SetValue(const T& value) {
    545      Data data;
    546      memcpy(data.buf, &value, sizeof(value));
    547      return data;
    548    }
    549 
    550    static T Value(Data arg) {
    551      T value;
    552      memcpy(&value, arg.buf, sizeof(T));
    553      return value;
    554    }
    555  };
    556 
    557  template <typename T>
    558  void Init(const T& value) {
    559    data_ = Manager<T>::SetValue(value);
    560    dispatcher_ = &Dispatch<T>;
    561  }
    562 
    563  template <typename T>
    564  static int ToIntVal(const T& val) {
    565    using CommonType = typename std::conditional<std::is_signed<T>::value,
    566                                                 int64_t, uint64_t>::type;
    567    if (static_cast<CommonType>(val) >
    568        static_cast<CommonType>((std::numeric_limits<int>::max)())) {
    569      return (std::numeric_limits<int>::max)();
    570    } else if (std::is_signed<T>::value &&
    571               static_cast<CommonType>(val) <
    572                   static_cast<CommonType>((std::numeric_limits<int>::min)())) {
    573      return (std::numeric_limits<int>::min)();
    574    }
    575    return static_cast<int>(val);
    576  }
    577 
    578  template <typename T>
    579  static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
    580                    std::false_type) {
    581    *out = ToIntVal(Manager<T>::Value(arg));
    582    return true;
    583  }
    584 
    585  template <typename T>
    586  static bool ToInt(Data arg, int* out, std::false_type,
    587                    std::true_type /* is_enum */) {
    588    *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
    589        Manager<T>::Value(arg)));
    590    return true;
    591  }
    592 
    593  template <typename T>
    594  static bool ToInt(Data, int*, std::false_type, std::false_type) {
    595    return false;
    596  }
    597 
    598  template <typename T>
    599  static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
    600    // A `none` conv indicates that we want the `int` conversion.
    601    if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
    602                           FormatConversionCharInternal::kNone)) {
    603      return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
    604                      std::is_enum<T>());
    605    }
    606    if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
    607                                     spec.conversion_char()))) {
    608      return false;
    609    }
    610    return str_format_internal::FormatConvertImpl(
    611               Manager<T>::Value(arg), spec,
    612               static_cast<FormatSinkImpl*>(out))
    613        .value;
    614  }
    615 
    616  Data data_;
    617  Dispatcher dispatcher_;
    618 };
    619 
    620 #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E)                     \
    621  E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
    622                                             void*)
    623 
    624 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(...)   \
    625  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
    626                                             __VA_ARGS__);                     \
    627  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \
    628  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \
    629  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \
    630  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \
    631  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
    632  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \
    633                                             __VA_ARGS__);                     \
    634  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \
    635  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \
    636  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \
    637  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \
    638                                             __VA_ARGS__);                     \
    639  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \
    640                                             __VA_ARGS__);                     \
    641  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
    642                                             __VA_ARGS__);                     \
    643  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__);             \
    644  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
    645  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
    646  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
    647  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
    648  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
    649  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
    650  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__);        \
    651  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__);     \
    652  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__)
    653 
    654 #if defined(ABSL_HAVE_STD_STRING_VIEW)
    655 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)       \
    656  ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \
    657      __VA_ARGS__);                                                \
    658  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__)
    659 #else
    660 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
    661  ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(__VA_ARGS__)
    662 #endif
    663 
    664 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
    665 
    666 
    667 }  // namespace str_format_internal
    668 ABSL_NAMESPACE_END
    669 }  // namespace absl
    670 
    671 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_