arg.h 27 KB

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