summaryrefslogtreecommitdiff
path: root/absl/strings/internal/str_format/arg.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-09-15 14:29:39 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-09-15 14:30:34 -0700
commitab2e2c4f6062999afaf960759dfccb77f350c702 (patch)
treea09ca81723521190744e2ec917a9f697cd08254b /absl/strings/internal/str_format/arg.cc
parentd423ac0ef052bd7b6fc53fd1a026a44e1713d993 (diff)
Adds support for "%v" in absl::StrFormat and related functions for numeric types, including integer and floating point values. Users may now specify %v and have the format specifier deduced. Integer values will print according to %d specifications, unsigned values will use %u, and floating point values will use %g. Note that %v does not work for `char` due to ambiguity regarding the intended output. Please continue to use %c for `char`.
PiperOrigin-RevId: 474658166 Change-Id: Iecae39263e368b27232db440535f2bf7da8d863c
Diffstat (limited to 'absl/strings/internal/str_format/arg.cc')
-rw-r--r--absl/strings/internal/str_format/arg.cc49
1 files changed, 36 insertions, 13 deletions
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index 007e8e83..b0e06bfb 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -278,12 +278,33 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
return true;
}
+template <typename T,
+ typename std::enable_if<(std::is_integral<T>::value &&
+ std::is_signed<T>::value) ||
+ std::is_same<T, int128>::value,
+ int>::type = 0>
+constexpr auto ConvertV(T) {
+ return FormatConversionCharInternal::d;
+}
+
+template <typename T,
+ typename std::enable_if<(std::is_integral<T>::value &&
+ std::is_unsigned<T>::value) ||
+ std::is_same<T, uint128>::value,
+ int>::type = 0>
+constexpr auto ConvertV(T) {
+ return FormatConversionCharInternal::u;
+}
+
template <typename T>
-bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
using U = typename MakeUnsigned<T>::type;
IntDigits as_digits;
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ conv.set_conversion_char(ConvertV(T{}));
+ }
+
// This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
// it to complain about a switch/case type mismatch, even though both are
// FormatConverionChar. Likely this is because at this point
@@ -334,8 +355,11 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
}
template <typename T>
-bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertFloatArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ conv.set_conversion_char(FormatConversionCharInternal::g);
+ }
+
return FormatConversionCharIsFloat(conv.conversion_char()) &&
ConvertFloatImpl(v, conv, sink);
}
@@ -413,19 +437,18 @@ FloatingConvertResult FormatConvertImpl(long double v,
}
// ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(char v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(signed char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(signed char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(unsigned char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(unsigned char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}