From 34eb767645347f100bdd66fc1e35eee96e357961 Mon Sep 17 00:00:00 2001 From: Tsige Solomon Date: Wed, 21 Jun 2023 08:52:53 -0700 Subject: Support for int128 to string type conversion. PiperOrigin-RevId: 542269673 Change-Id: Ib6f7e9a57f83d73dd6fb9c45fc9f85ff0fdd75fe --- absl/numeric/BUILD.bazel | 1 + absl/numeric/CMakeLists.txt | 1 + absl/numeric/int128.cc | 12 ++++++++++++ absl/numeric/int128.h | 17 +++++++++++++++++ absl/numeric/int128_stream_test.cc | 7 +++++++ 5 files changed, 38 insertions(+) diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel index ec0b8701..c5aaf72b 100644 --- a/absl/numeric/BUILD.bazel +++ b/absl/numeric/BUILD.bazel @@ -97,6 +97,7 @@ cc_test( "//absl/base", "//absl/hash:hash_testing", "//absl/meta:type_traits", + "//absl/strings", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt index 384c0fc0..7181b91a 100644 --- a/absl/numeric/CMakeLists.txt +++ b/absl/numeric/CMakeLists.txt @@ -72,6 +72,7 @@ absl_cc_test( absl::base absl::hash_testing absl::type_traits + absl::strings GTest::gmock_main ) diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 6ffe43d5..daa32b51 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -202,6 +202,10 @@ std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { } // namespace +std::string uint128::ToString() const { + return Uint128ToFormattedString(*this, std::ios_base::dec); +} + std::ostream& operator<<(std::ostream& os, uint128 v) { std::ios_base::fmtflags flags = os.flags(); std::string rep = Uint128ToFormattedString(v, flags); @@ -285,6 +289,14 @@ int128 operator%(int128 lhs, int128 rhs) { } #endif // ABSL_HAVE_INTRINSIC_INT128 +std::string int128::ToString() const { + std::string rep; + if (Int128High64(*this) < 0) rep = "-"; + rep.append(Uint128ToFormattedString(UnsignedAbsoluteValue(*this), + std::ios_base::dec)); + return rep; +} + std::ostream& operator<<(std::ostream& os, int128 v) { std::ios_base::fmtflags flags = os.flags(); std::string rep; diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index aa0f86f7..7530a793 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "absl/base/config.h" @@ -217,9 +218,17 @@ class return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); } + // Support for absl::StrCat() etc. + template + friend void AbslStringify(Sink& sink, uint128 v) { + sink.Append(v.ToString()); + } + private: constexpr uint128(uint64_t high, uint64_t low); + std::string ToString() const; + // TODO(strel) Update implementation to use __int128 once all users of // uint128 are fixed to not depend on alignof(uint128) == 8. Also add // alignas(16) to class definition to keep alignment consistent across @@ -454,9 +463,17 @@ class int128 { return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); } + // Support for absl::StrCat() etc. + template + friend void AbslStringify(Sink& sink, int128 v) { + sink.Append(v.ToString()); + } + private: constexpr int128(int64_t high, uint64_t low); + std::string ToString() const; + #if defined(ABSL_HAVE_INTRINSIC_INT128) __int128 v_; #else // ABSL_HAVE_INTRINSIC_INT128 diff --git a/absl/numeric/int128_stream_test.cc b/absl/numeric/int128_stream_test.cc index 81d2adee..bd937847 100644 --- a/absl/numeric/int128_stream_test.cc +++ b/absl/numeric/int128_stream_test.cc @@ -18,6 +18,7 @@ #include #include "gtest/gtest.h" +#include "absl/strings/str_cat.h" namespace { @@ -87,6 +88,9 @@ constexpr std::ios::fmtflags kBase = std::ios::showbase; constexpr std::ios::fmtflags kPos = std::ios::showpos; void CheckUint128Case(const Uint128TestCase& test_case) { + if (test_case.flags == kDec && test_case.width == 0) { + EXPECT_EQ(absl::StrCat(test_case.value), test_case.expected); + } std::ostringstream os; os.flags(test_case.flags); os.width(test_case.width); @@ -155,6 +159,9 @@ struct Int128TestCase { }; void CheckInt128Case(const Int128TestCase& test_case) { + if (test_case.flags == kDec && test_case.width == 0) { + EXPECT_EQ(absl::StrCat(test_case.value), test_case.expected); + } std::ostringstream os; os.flags(test_case.flags); os.width(test_case.width); -- cgit v1.2.3