arg.h
Go to the documentation of this file.
00001 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
00002 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
00003 
00004 #include <string.h>
00005 #include <wchar.h>
00006 
00007 #include <cstdio>
00008 #include <iomanip>
00009 #include <limits>
00010 #include <memory>
00011 #include <sstream>
00012 #include <string>
00013 #include <type_traits>
00014 
00015 #include "absl/base/port.h"
00016 #include "absl/meta/type_traits.h"
00017 #include "absl/numeric/int128.h"
00018 #include "absl/strings/internal/str_format/extension.h"
00019 #include "absl/strings/string_view.h"
00020 
00021 class Cord;
00022 class CordReader;
00023 
00024 namespace absl {
00025 
00026 class FormatCountCapture;
00027 class FormatSink;
00028 
00029 namespace str_format_internal {
00030 
00031 template <typename T, typename = void>
00032 struct HasUserDefinedConvert : std::false_type {};
00033 
00034 template <typename T>
00035 struct HasUserDefinedConvert<
00036     T, void_t<decltype(AbslFormatConvert(
00037            std::declval<const T&>(), std::declval<ConversionSpec>(),
00038            std::declval<FormatSink*>()))>> : std::true_type {};
00039 
00040 template <typename T>
00041 class StreamedWrapper;
00042 
00043 // If 'v' can be converted (in the printf sense) according to 'conv',
00044 // then convert it, appending to `sink` and return `true`.
00045 // Otherwise fail and return `false`.
00046 
00047 // Raw pointers.
00048 struct VoidPtr {
00049   VoidPtr() = default;
00050   template <typename T,
00051             decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
00052   VoidPtr(T* ptr)  // NOLINT
00053       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
00054   uintptr_t value;
00055 };
00056 ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
00057                                          FormatSinkImpl* sink);
00058 
00059 // Strings.
00060 ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
00061                                          ConversionSpec conv,
00062                                          FormatSinkImpl* sink);
00063 ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
00064                                          FormatSinkImpl* sink);
00065 ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
00066                                                    ConversionSpec conv,
00067                                                    FormatSinkImpl* sink);
00068 template <class AbslCord,
00069           typename std::enable_if<
00070               std::is_same<AbslCord, ::Cord>::value>::type* = nullptr,
00071           class AbslCordReader = ::CordReader>
00072 ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
00073                                          ConversionSpec conv,
00074                                          FormatSinkImpl* sink) {
00075   if (conv.conv().id() != ConversionChar::s) return {false};
00076 
00077   bool is_left = conv.flags().left;
00078   size_t space_remaining = 0;
00079 
00080   int width = conv.width();
00081   if (width >= 0) space_remaining = width;
00082 
00083   size_t to_write = value.size();
00084 
00085   int precision = conv.precision();
00086   if (precision >= 0)
00087     to_write = (std::min)(to_write, static_cast<size_t>(precision));
00088 
00089   space_remaining = Excess(to_write, space_remaining);
00090 
00091   if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
00092 
00093   string_view piece;
00094   for (AbslCordReader reader(value);
00095        to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
00096     if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
00097     sink->Append(piece);
00098   }
00099 
00100   if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
00101   return {true};
00102 }
00103 
00104 using IntegralConvertResult =
00105     ConvertResult<Conv::c | Conv::numeric | Conv::star>;
00106 using FloatingConvertResult = ConvertResult<Conv::floating>;
00107 
00108 // Floats.
00109 FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
00110                                         FormatSinkImpl* sink);
00111 FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
00112                                         FormatSinkImpl* sink);
00113 FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
00114                                         FormatSinkImpl* sink);
00115 
00116 // Chars.
00117 IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
00118                                         FormatSinkImpl* sink);
00119 IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
00120                                         FormatSinkImpl* sink);
00121 IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
00122                                         FormatSinkImpl* sink);
00123 
00124 // Ints.
00125 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
00126                                         ConversionSpec conv,
00127                                         FormatSinkImpl* sink);
00128 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
00129                                         ConversionSpec conv,
00130                                         FormatSinkImpl* sink);
00131 IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
00132                                         FormatSinkImpl* sink);
00133 IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
00134                                         FormatSinkImpl* sink);
00135 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
00136                                         ConversionSpec conv,
00137                                         FormatSinkImpl* sink);
00138 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
00139                                         ConversionSpec conv,
00140                                         FormatSinkImpl* sink);
00141 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
00142                                         ConversionSpec conv,
00143                                         FormatSinkImpl* sink);
00144 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
00145                                         ConversionSpec conv,
00146                                         FormatSinkImpl* sink);
00147 IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
00148                                         FormatSinkImpl* sink);
00149 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
00150 IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
00151                                         FormatSinkImpl* sink) {
00152   return FormatConvertImpl(static_cast<int>(v), conv, sink);
00153 }
00154 
00155 // We provide this function to help the checker, but it is never defined.
00156 // FormatArgImpl will use the underlying Convert functions instead.
00157 template <typename T>
00158 typename std::enable_if<std::is_enum<T>::value &&
00159                             !HasUserDefinedConvert<T>::value,
00160                         IntegralConvertResult>::type
00161 FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
00162 
00163 template <typename T>
00164 ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
00165                                          ConversionSpec conv,
00166                                          FormatSinkImpl* out) {
00167   std::ostringstream oss;
00168   oss << v.v_;
00169   if (!oss) return {false};
00170   return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
00171 }
00172 
00173 // Use templates and dependent types to delay evaluation of the function
00174 // until after FormatCountCapture is fully defined.
00175 struct FormatCountCaptureHelper {
00176   template <class T = int>
00177   static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
00178                                               ConversionSpec conv,
00179                                               FormatSinkImpl* sink) {
00180     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
00181 
00182     if (conv.conv().id() != str_format_internal::ConversionChar::n)
00183       return {false};
00184     *v2.p_ = static_cast<int>(sink->size());
00185     return {true};
00186   }
00187 };
00188 
00189 template <class T = int>
00190 ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
00191                                          ConversionSpec conv,
00192                                          FormatSinkImpl* sink) {
00193   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
00194 }
00195 
00196 // Helper friend struct to hide implementation details from the public API of
00197 // FormatArgImpl.
00198 struct FormatArgImplFriend {
00199   template <typename Arg>
00200   static bool ToInt(Arg arg, int* out) {
00201     // A value initialized ConversionSpec has a `none` conv, which tells the
00202     // dispatcher to run the `int` conversion.
00203     return arg.dispatcher_(arg.data_, {}, out);
00204   }
00205 
00206   template <typename Arg>
00207   static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
00208                       FormatSinkImpl* out) {
00209     return arg.dispatcher_(arg.data_, conv, out);
00210   }
00211 
00212   template <typename Arg>
00213   static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
00214     return arg.dispatcher_;
00215   }
00216 };
00217 
00218 // A type-erased handle to a format argument.
00219 class FormatArgImpl {
00220  private:
00221   enum { kInlinedSpace = 8 };
00222 
00223   using VoidPtr = str_format_internal::VoidPtr;
00224 
00225   union Data {
00226     const void* ptr;
00227     const volatile void* volatile_ptr;
00228     char buf[kInlinedSpace];
00229   };
00230 
00231   using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
00232 
00233   template <typename T>
00234   struct store_by_value
00235       : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
00236                                          (std::is_integral<T>::value ||
00237                                           std::is_floating_point<T>::value ||
00238                                           std::is_pointer<T>::value ||
00239                                           std::is_same<VoidPtr, T>::value)> {};
00240 
00241   enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
00242   template <typename T>
00243   struct storage_policy
00244       : std::integral_constant<StoragePolicy,
00245                                (std::is_volatile<T>::value
00246                                     ? ByVolatilePointer
00247                                     : (store_by_value<T>::value ? ByValue
00248                                                                 : ByPointer))> {
00249   };
00250 
00251   // To reduce the number of vtables we will decay values before hand.
00252   // Anything with a user-defined Convert will get its own vtable.
00253   // For everything else:
00254   //   - Decay char* and char arrays into `const char*`
00255   //   - Decay any other pointer to `const void*`
00256   //   - Decay all enums to their underlying type.
00257   //   - Decay function pointers to void*.
00258   template <typename T, typename = void>
00259   struct DecayType {
00260     static constexpr bool kHasUserDefined =
00261         str_format_internal::HasUserDefinedConvert<T>::value;
00262     using type = typename std::conditional<
00263         !kHasUserDefined && std::is_convertible<T, const char*>::value,
00264         const char*,
00265         typename std::conditional<!kHasUserDefined &&
00266                                       std::is_convertible<T, VoidPtr>::value,
00267                                   VoidPtr, const T&>::type>::type;
00268   };
00269   template <typename T>
00270   struct DecayType<T,
00271                    typename std::enable_if<
00272                        !str_format_internal::HasUserDefinedConvert<T>::value &&
00273                        std::is_enum<T>::value>::type> {
00274     using type = typename std::underlying_type<T>::type;
00275   };
00276 
00277  public:
00278   template <typename T>
00279   explicit FormatArgImpl(const T& value) {
00280     using D = typename DecayType<T>::type;
00281     static_assert(
00282         std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
00283         "Decayed types must be stored by value");
00284     Init(static_cast<D>(value));
00285   }
00286 
00287  private:
00288   friend struct str_format_internal::FormatArgImplFriend;
00289   template <typename T, StoragePolicy = storage_policy<T>::value>
00290   struct Manager;
00291 
00292   template <typename T>
00293   struct Manager<T, ByPointer> {
00294     static Data SetValue(const T& value) {
00295       Data data;
00296       data.ptr = std::addressof(value);
00297       return data;
00298     }
00299 
00300     static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
00301   };
00302 
00303   template <typename T>
00304   struct Manager<T, ByVolatilePointer> {
00305     static Data SetValue(const T& value) {
00306       Data data;
00307       data.volatile_ptr = &value;
00308       return data;
00309     }
00310 
00311     static const T& Value(Data arg) {
00312       return *static_cast<const T*>(arg.volatile_ptr);
00313     }
00314   };
00315 
00316   template <typename T>
00317   struct Manager<T, ByValue> {
00318     static Data SetValue(const T& value) {
00319       Data data;
00320       memcpy(data.buf, &value, sizeof(value));
00321       return data;
00322     }
00323 
00324     static T Value(Data arg) {
00325       T value;
00326       memcpy(&value, arg.buf, sizeof(T));
00327       return value;
00328     }
00329   };
00330 
00331   template <typename T>
00332   void Init(const T& value) {
00333     data_ = Manager<T>::SetValue(value);
00334     dispatcher_ = &Dispatch<T>;
00335   }
00336 
00337   template <typename T>
00338   static int ToIntVal(const T& val) {
00339     using CommonType = typename std::conditional<std::is_signed<T>::value,
00340                                                  int64_t, uint64_t>::type;
00341     if (static_cast<CommonType>(val) >
00342         static_cast<CommonType>((std::numeric_limits<int>::max)())) {
00343       return (std::numeric_limits<int>::max)();
00344     } else if (std::is_signed<T>::value &&
00345                static_cast<CommonType>(val) <
00346                    static_cast<CommonType>((std::numeric_limits<int>::min)())) {
00347       return (std::numeric_limits<int>::min)();
00348     }
00349     return static_cast<int>(val);
00350   }
00351 
00352   template <typename T>
00353   static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
00354                     std::false_type) {
00355     *out = ToIntVal(Manager<T>::Value(arg));
00356     return true;
00357   }
00358 
00359   template <typename T>
00360   static bool ToInt(Data arg, int* out, std::false_type,
00361                     std::true_type /* is_enum */) {
00362     *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
00363         Manager<T>::Value(arg)));
00364     return true;
00365   }
00366 
00367   template <typename T>
00368   static bool ToInt(Data, int*, std::false_type, std::false_type) {
00369     return false;
00370   }
00371 
00372   template <typename T>
00373   static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
00374     // A `none` conv indicates that we want the `int` conversion.
00375     if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
00376       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
00377                       std::is_enum<T>());
00378     }
00379 
00380     return str_format_internal::FormatConvertImpl(
00381                Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
00382         .value;
00383   }
00384 
00385   Data data_;
00386   Dispatcher dispatcher_;
00387 };
00388 
00389 #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
00390   E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
00391 
00392 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)                   \
00393   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
00394                                              __VA_ARGS__);                     \
00395   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \
00396   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \
00397   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \
00398   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \
00399   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
00400   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \
00401                                              __VA_ARGS__);                     \
00402   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \
00403   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \
00404   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \
00405   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \
00406                                              __VA_ARGS__);                     \
00407   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \
00408                                              __VA_ARGS__);                     \
00409   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
00410                                              __VA_ARGS__);                     \
00411   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
00412   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
00413   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
00414   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
00415   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
00416   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
00417   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
00418 
00419 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
00420 
00421 }  // namespace str_format_internal
00422 }  // namespace absl
00423 
00424 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14