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
00044
00045
00046
00047
00048 struct VoidPtr {
00049 VoidPtr() = default;
00050 template <typename T,
00051 decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
00052 VoidPtr(T* ptr)
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
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
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
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
00125 IntegralConvertResult FormatConvertImpl(short v,
00126 ConversionSpec conv,
00127 FormatSinkImpl* sink);
00128 IntegralConvertResult FormatConvertImpl(unsigned short v,
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,
00136 ConversionSpec conv,
00137 FormatSinkImpl* sink);
00138 IntegralConvertResult FormatConvertImpl(unsigned long v,
00139 ConversionSpec conv,
00140 FormatSinkImpl* sink);
00141 IntegralConvertResult FormatConvertImpl(long long v,
00142 ConversionSpec conv,
00143 FormatSinkImpl* sink);
00144 IntegralConvertResult FormatConvertImpl(unsigned long long v,
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
00156
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
00174
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
00197
00198 struct FormatArgImplFriend {
00199 template <typename Arg>
00200 static bool ToInt(Arg arg, int* out) {
00201
00202
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
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
00252
00253
00254
00255
00256
00257
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 ,
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 ) {
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
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__); \
00400 ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, \
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__); \
00405 ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, \
00406 __VA_ARGS__); \
00407 ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, \
00408 __VA_ARGS__); \
00409 ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, \
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 }
00422 }
00423
00424 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_