summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Tsige Solomon <tsige@google.com>2023-06-21 08:52:53 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-06-21 08:53:52 -0700
commit34eb767645347f100bdd66fc1e35eee96e357961 (patch)
tree5257457b09e5c1533b41e9607fdefd20ef158eae
parent166d71d18f01aa73fd35aae611692320952a75b5 (diff)
Support for int128 to string type conversion.
PiperOrigin-RevId: 542269673 Change-Id: Ib6f7e9a57f83d73dd6fb9c45fc9f85ff0fdd75fe
-rw-r--r--absl/numeric/BUILD.bazel1
-rw-r--r--absl/numeric/CMakeLists.txt1
-rw-r--r--absl/numeric/int128.cc12
-rw-r--r--absl/numeric/int128.h17
-rw-r--r--absl/numeric/int128_stream_test.cc7
5 files changed, 38 insertions, 0 deletions
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 <cstring>
#include <iosfwd>
#include <limits>
+#include <string>
#include <utility>
#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 <typename Sink>
+ 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 <typename Sink>
+ 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 <string>
#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);