summaryrefslogtreecommitdiff
path: root/absl/strings/internal/str_format/arg.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-12-04 11:01:12 -0800
committerGravatar Ashley Hedberg <ahedberg@google.com>2018-12-04 16:54:40 -0500
commitfcb104594b0bb4b8ac306cb2f55ecdad40974683 (patch)
treed2d79d246c6a894ca6716f47c15ebb7b8796b36a /absl/strings/internal/str_format/arg.h
parent6c7de165d1c82684359ccb630bb5f83263fa5ebc (diff)
Creation of LTS branch "lts_2018_12_18"20181200
- 44b0fafc62d9b8f192e8180cbe9c4b806b339d57 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 926bfeb9fff223429c12224b7514243886323e8d Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 13327debebc5c2d1d4991b69fe50450e340e50e4 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 3088e76c597e068479e82508b1770a7ad0c806b6 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f6ae816808cd913e0e2b3e2af14f328fa1071af0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - a06c4a1d9093137b7217a5aaba8920d62e835dc0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 7b46e1d31a6b08b1c6da2a13e7b151a20446fa07 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 070f6e47b33a2909d039e620c873204f78809492 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 7990fd459e9339467814ddb95000c87cb1e4d945 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f95179062eb65ce40895cc76f1398cce25394369 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - cc8dcd307b76a575d2e3e0958a4fe4c7193c2f68 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - a705aa78dc76fc5c79d501e61dcc077eca68a8a4 Merge pull request #194 from Mizux/windows by Xiaoyi Zhang <zhangxy988@gmail.com> - a4c3ffff11eec0ee45742f915c255e9f870b7e0f Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 01174578651b73021d9b8c3820f6fea707dacdf0 Merge pull request #201 from ccawley2011/fix-byteswap by Matt Calabrese <38107210+mattcalabrese-google@users.noreply.github.com> - f86f9413856b65afdd61fea938d684b8ab73115a Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 94c298e2a0ae409e283cab96c954a685bd865a70 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 0884a6a04e4497d11b1b398cc0e422b118bf977a Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - c16d5557cd05119b5b7b1318ef778ebe3195b4a1 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 45221ccc4ed643e4209b0cc5798e97203f108fa8 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 2019e17a520575ab365b2b5134d71068182c70b8 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 5b70a8910b2e6fb0ce5193a41873139a126d2f7f Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - a00bdd176d66ef0b417d9576052a19091fbdf891 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f340f773edab951656b19b6f1a77c964a78ec4c2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 445998d7ac4e5d3c50411d377e3b50e960d2d6c2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - e821380d69a549dc64900693942789d21aa4df5e Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f21d187b80e3b7f08fb279775ea9c8b48c636030 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 5441bbe1db5d0f2ca24b5b60166367b0966790af Fix code snippet in comment (#174) by Loo Rong Jie <loorongjie@gmail.com> - 5aae0cffae8ffaacab965756169b34e511b353df Fix CMake build (#173) by Stephan Dollberg <stephan.dollberg@gmail.com> - 48cd2c3f351ff188bc85684b84a91b6e6d17d896 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - e291c279e458761e77a69b09b129d3d1e81f1e80 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - e01d95528ea2137a4a27a88d1f57c6cb260aafed Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 8ff1374008259719b54a8cb128ef951c02da164c Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 02451914b9ad5320f81f56a89f3eef1f8683227c Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 921fd5cf02ec0d665439a790148d59faa7d4a72c Merge pull request #166 from rongjiecomputer/cmake-test by Gennadiy Civil <gennadiycivil@users.noreply.github.com> - fb462224c058487763f263b7995d70efd0242c17 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - c075ad321696fa5072e097f0a51e4fe76a6fe13e Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 0f4bc966754ec6cd28d5f03467d56f1efdc598e3 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 6c7e5ffc43decd92f7bdfc510ad8a245a20b6dea Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - d6df769173bf0263489f98874b93034db0e479a2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 28080f5f050c9530aa9f2b39c60d8217038d64ff Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 9c987f429bba32fb4446280fd3b91e2472d71d4d Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 5e7d459eeca7bc53deab0ee9634601386b53d7c0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - bed5bd6e185c7e0311f3a1f2dab4c96083dac636 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - fefc83638fb69395d259ed245699310610429064 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - d8cfe9f2a77fbee02c09642491e62a3f3677e0f6 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - ad5c960b2eb914881d1ceba0e996a0a8f3f6ca59 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 86f0fe93ad9d6d033a319476736a3256369c1f75 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f0f15c2778b0e4959244dd25e63f445a455870f5 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 29ff6d4860070bf8fcbd39c8805d0c32d56628a3 Removed "warning treated as error" flag from MSVC (#153) by vocaviking <vocaviking@users.noreply.github.com> - 083d04dd4a62ebbf037079b06e49b323c5e1192a Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - bea85b52733022294eef108a2e42d77b616ddca2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 8f96be6ca60d967bd4b37f93d0a03bcff4145200 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 92e07e5590752d6b8e67f7f2f86c6286561e8cea Merge pull request #152 from clnperez/fix-multi-defines-p... by Derek Mauro <761129+derekmauro@users.noreply.github.com> - 2125e6444a9de9e41f21ecdc674dd7d8759c149d Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 9acad869d21731f5bc50430a33fe61cc0ffcbb0b Merge pull request #150 from OlafvdSpek/patch-2 by Jonathan Cohen <cohenjon@google.com> - c2e00d341913bf03b4597ade5b056042e23e8c58 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 9e060686d1c325f34f9806b45fe77bafeed00aee Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 7aa411ceafc1272a28579cca739a97a2fb79055a Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 2c5af55ed34850d8b7dd46177c8ca53fdfda920e Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 44aa275286baf97fc13529aca547a88b180beb08 Merge pull request #143 from rongjiecomputer/kernel by Xiaoyi Zhang <zhangxy988@gmail.com> - 42f22a28401c952f1fc5942231c7fdac80811bf5 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - b973bc53ef366f0253b85eeed9a79b241884a843 Merge pull request #139 from siepkes/smartos-support by ahedberg <ahedberg@google.com> - e0def7473e52336f58759e11db4cd9467e5e0356 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - f826f1d489b61b64df1d94afbe5981841a82e5fa Merge pull request #138 from edbaunton/remove-deprecated-... by ahedberg <ahedberg@google.com> - 7b50a4a94b0c7df68b3a854c850b551aaef0a8b4 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - a5030ca5125b9d557ecfeea8acc8b1a8e49f6d27 Merge pull request #144 from rongjiecomputer/winsock2 by Xiaoyi Zhang <zhangxy988@gmail.com> - 02687955b7ca8fc02ada9b14bc247deeb108d341 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 8f612ebb152fb7e05643a2bcf78cb89a8c0641ad Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 134496a31d8b324f762de3bee9a002658c984456 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - ba8d6cf07766263723e86736f20a51c1c9c67b19 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - be1e84b988fceabcea4fc9e93f899539f0c81901 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 16ac2ec2e38cdf47f9330a312e319d57da659c10 Merge pull request #134 from rongjiecomputer/cmake by Alex Strelnikov <strel@google.com> - 7efd8dc0f1075356e9c7caa950afd1ecf854e8b9 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 87a4c07856e7dc69958019d47b2f02ae47746ec0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> - 4491d606df34c44efda47b6d17b605262f17e182 Export of internal Abseil changes. by Abseil Team <absl-team@google.com> GitOrigin-RevId: 44b0fafc62d9b8f192e8180cbe9c4b806b339d57 Change-Id: I2c427b5b41b2d34101922048b00f3d9dafcb498d
Diffstat (limited to 'absl/strings/internal/str_format/arg.h')
-rw-r--r--absl/strings/internal/str_format/arg.h422
1 files changed, 422 insertions, 0 deletions
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
new file mode 100644
index 00000000..0af4c839
--- /dev/null
+++ b/absl/strings/internal/str_format/arg.h
@@ -0,0 +1,422 @@
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
+
+#include <string.h>
+#include <wchar.h>
+
+#include <cstdio>
+#include <iomanip>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/port.h"
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/int128.h"
+#include "absl/strings/internal/str_format/extension.h"
+#include "absl/strings/string_view.h"
+
+class Cord;
+class CordReader;
+
+namespace absl {
+inline namespace lts_2018_12_18 {
+
+class FormatCountCapture;
+class FormatSink;
+
+namespace str_format_internal {
+
+template <typename T, typename = void>
+struct HasUserDefinedConvert : std::false_type {};
+
+template <typename T>
+struct HasUserDefinedConvert<
+ T, void_t<decltype(AbslFormatConvert(
+ std::declval<const T&>(), std::declval<ConversionSpec>(),
+ std::declval<FormatSink*>()))>> : std::true_type {};
+template <typename T>
+class StreamedWrapper;
+
+// If 'v' can be converted (in the printf sense) according to 'conv',
+// then convert it, appending to `sink` and return `true`.
+// Otherwise fail and return `false`.
+// Raw pointers.
+struct VoidPtr {
+ VoidPtr() = default;
+ template <typename T,
+ decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
+ VoidPtr(T* ptr) // NOLINT
+ : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
+ uintptr_t value;
+};
+ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+
+// Strings.
+ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+template <class AbslCord,
+ typename std::enable_if<
+ std::is_same<AbslCord, ::Cord>::value>::type* = nullptr,
+ class AbslCordReader = ::CordReader>
+ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
+ if (conv.conv().id() != ConversionChar::s) return {false};
+
+ bool is_left = conv.flags().left;
+ size_t space_remaining = 0;
+
+ int width = conv.width();
+ if (width >= 0) space_remaining = width;
+
+ size_t to_write = value.size();
+
+ int precision = conv.precision();
+ if (precision >= 0)
+ to_write = std::min(to_write, static_cast<size_t>(precision));
+
+ space_remaining = Excess(to_write, space_remaining);
+
+ if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
+
+ string_view piece;
+ for (AbslCordReader reader(value);
+ to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
+ if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
+ sink->Append(piece);
+ }
+
+ if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
+ return {true};
+}
+
+using IntegralConvertResult =
+ ConvertResult<Conv::c | Conv::numeric | Conv::star>;
+using FloatingConvertResult = ConvertResult<Conv::floating>;
+
+// Floats.
+FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+
+// Chars.
+IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+
+// Ints.
+IntegralConvertResult FormatConvertImpl(short v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(long v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
+ ConversionSpec conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
+ FormatSinkImpl* sink);
+template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
+IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
+ FormatSinkImpl* sink) {
+ return FormatConvertImpl(static_cast<int>(v), conv, sink);
+}
+
+// We provide this function to help the checker, but it is never defined.
+// FormatArgImpl will use the underlying Convert functions instead.
+template <typename T>
+typename std::enable_if<std::is_enum<T>::value &&
+ !HasUserDefinedConvert<T>::value,
+ IntegralConvertResult>::type
+FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
+
+template <typename T>
+ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
+ ConversionSpec conv,
+ FormatSinkImpl* out) {
+ std::ostringstream oss;
+ oss << v.v_;
+ if (!oss) return {false};
+ return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
+}
+
+// Use templates and dependent types to delay evaluation of the function
+// until after FormatCountCapture is fully defined.
+struct FormatCountCaptureHelper {
+ template <class T = int>
+ static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
+ const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
+
+ if (conv.conv().id() != str_format_internal::ConversionChar::n)
+ return {false};
+ *v2.p_ = static_cast<int>(sink->size());
+ return {true};
+ }
+};
+
+template <class T = int>
+ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
+ return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
+}
+
+// Helper friend struct to hide implementation details from the public API of
+// FormatArgImpl.
+struct FormatArgImplFriend {
+ template <typename Arg>
+ static bool ToInt(Arg arg, int* out) {
+ // A value initialized ConversionSpec has a `none` conv, which tells the
+ // dispatcher to run the `int` conversion.
+ return arg.dispatcher_(arg.data_, {}, out);
+ }
+
+ template <typename Arg>
+ static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
+ FormatSinkImpl* out) {
+ return arg.dispatcher_(arg.data_, conv, out);
+ }
+
+ template <typename Arg>
+ static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
+ return arg.dispatcher_;
+ }
+};
+
+// A type-erased handle to a format argument.
+class FormatArgImpl {
+ private:
+ enum { kInlinedSpace = 8 };
+
+ using VoidPtr = str_format_internal::VoidPtr;
+
+ union Data {
+ const void* ptr;
+ const volatile void* volatile_ptr;
+ char buf[kInlinedSpace];
+ };
+
+ using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
+
+ template <typename T>
+ struct store_by_value
+ : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
+ (std::is_integral<T>::value ||
+ std::is_floating_point<T>::value ||
+ std::is_pointer<T>::value ||
+ std::is_same<VoidPtr, T>::value)> {};
+
+ enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
+ template <typename T>
+ struct storage_policy
+ : std::integral_constant<StoragePolicy,
+ (std::is_volatile<T>::value
+ ? ByVolatilePointer
+ : (store_by_value<T>::value ? ByValue
+ : ByPointer))> {
+ };
+
+ // To reduce the number of vtables we will decay values before hand.
+ // Anything with a user-defined Convert will get its own vtable.
+ // For everything else:
+ // - Decay char* and char arrays into `const char*`
+ // - Decay any other pointer to `const void*`
+ // - Decay all enums to their underlying type.
+ // - Decay function pointers to void*.
+ template <typename T, typename = void>
+ struct DecayType {
+ static constexpr bool kHasUserDefined =
+ str_format_internal::HasUserDefinedConvert<T>::value;
+ using type = typename std::conditional<
+ !kHasUserDefined && std::is_convertible<T, const char*>::value,
+ const char*,
+ typename std::conditional<!kHasUserDefined &&
+ std::is_convertible<T, VoidPtr>::value,
+ VoidPtr, const T&>::type>::type;
+ };
+ template <typename T>
+ struct DecayType<T,
+ typename std::enable_if<
+ !str_format_internal::HasUserDefinedConvert<T>::value &&
+ std::is_enum<T>::value>::type> {
+ using type = typename std::underlying_type<T>::type;
+ };
+
+ public:
+ template <typename T>
+ explicit FormatArgImpl(const T& value) {
+ using D = typename DecayType<T>::type;
+ static_assert(
+ std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
+ "Decayed types must be stored by value");
+ Init(static_cast<D>(value));
+ }
+
+ private:
+ friend struct str_format_internal::FormatArgImplFriend;
+ template <typename T, StoragePolicy = storage_policy<T>::value>
+ struct Manager;
+
+ template <typename T>
+ struct Manager<T, ByPointer> {
+ static Data SetValue(const T& value) {
+ Data data;
+ data.ptr = &value;
+ return data;
+ }
+
+ static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
+ };
+
+ template <typename T>
+ struct Manager<T, ByVolatilePointer> {
+ static Data SetValue(const T& value) {
+ Data data;
+ data.volatile_ptr = &value;
+ return data;
+ }
+
+ static const T& Value(Data arg) {
+ return *static_cast<const T*>(arg.volatile_ptr);
+ }
+ };
+
+ template <typename T>
+ struct Manager<T, ByValue> {
+ static Data SetValue(const T& value) {
+ Data data;
+ memcpy(data.buf, &value, sizeof(value));
+ return data;
+ }
+
+ static T Value(Data arg) {
+ T value;
+ memcpy(&value, arg.buf, sizeof(T));
+ return value;
+ }
+ };
+
+ template <typename T>
+ void Init(const T& value) {
+ data_ = Manager<T>::SetValue(value);
+ dispatcher_ = &Dispatch<T>;
+ }
+
+ template <typename T>
+ static int ToIntVal(const T& val) {
+ using CommonType = typename std::conditional<std::is_signed<T>::value,
+ int64_t, uint64_t>::type;
+ if (static_cast<CommonType>(val) >
+ static_cast<CommonType>((std::numeric_limits<int>::max)())) {
+ return (std::numeric_limits<int>::max)();
+ } else if (std::is_signed<T>::value &&
+ static_cast<CommonType>(val) <
+ static_cast<CommonType>((std::numeric_limits<int>::min)())) {
+ return (std::numeric_limits<int>::min)();
+ }
+ return static_cast<int>(val);
+ }
+
+ template <typename T>
+ static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
+ std::false_type) {
+ *out = ToIntVal(Manager<T>::Value(arg));
+ return true;
+ }
+
+ template <typename T>
+ static bool ToInt(Data arg, int* out, std::false_type,
+ std::true_type /* is_enum */) {
+ *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
+ Manager<T>::Value(arg)));
+ return true;
+ }
+
+ template <typename T>
+ static bool ToInt(Data, int*, std::false_type, std::false_type) {
+ return false;
+ }
+
+ template <typename T>
+ static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
+ // A `none` conv indicates that we want the `int` conversion.
+ if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
+ return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
+ std::is_enum<T>());
+ }
+
+ return str_format_internal::FormatConvertImpl(
+ Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
+ .value;
+ }
+
+ Data data_;
+ Dispatcher dispatcher_;
+};
+
+#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
+ E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
+
+#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
+
+ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
+
+} // namespace str_format_internal
+} // inline namespace lts_2018_12_18
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_