arg.h 20 KB

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