Adding support for int128 and uint128 flag types

PiperOrigin-RevId: 537120102
Change-Id: I7952e53aca10319eb433e4c4d60cf3d7fe74d19a
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 627f453..583e6d9 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -99,6 +99,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:log_severity",
+        "//absl/numeric:int128",
         "//absl/strings",
         "//absl/strings:str_format",
         "//absl/types:optional",
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index b9d3b97..6525eb2 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -87,6 +87,7 @@
     absl::config
     absl::core_headers
     absl::log_severity
+    absl::int128
     absl::optional
     absl::strings
     absl::str_format
diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc
index 81f9ceb..cf6312b 100644
--- a/absl/flags/marshalling.cc
+++ b/absl/flags/marshalling.cc
@@ -26,6 +26,7 @@
 #include "absl/base/config.h"
 #include "absl/base/log_severity.h"
 #include "absl/base/macros.h"
+#include "absl/numeric/int128.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/match.h"
 #include "absl/strings/numbers.h"
@@ -125,6 +126,32 @@
   return ParseFlagImpl(text, *dst);
 }
 
+bool AbslParseFlag(absl::string_view text, absl::int128* dst, std::string*) {
+  text = absl::StripAsciiWhitespace(text);
+
+  // check hex
+  int base = NumericBase(text);
+  if (!absl::numbers_internal::safe_strto128_base(text, dst, base)) {
+    return false;
+  }
+
+  return base == 16 ? absl::SimpleHexAtoi(text, dst)
+                    : absl::SimpleAtoi(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, absl::uint128* dst, std::string*) {
+  text = absl::StripAsciiWhitespace(text);
+
+  // check hex
+  int base = NumericBase(text);
+  if (!absl::numbers_internal::safe_strtou128_base(text, dst, base)) {
+    return false;
+  }
+
+  return base == 16 ? absl::SimpleHexAtoi(text, dst)
+                    : absl::SimpleAtoi(text, dst);
+}
+
 // --------------------------------------------------------------------
 // AbslParseFlag for floating point types.
 
diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h
index 325e75e..21d955d 100644
--- a/absl/flags/marshalling.h
+++ b/absl/flags/marshalling.h
@@ -200,6 +200,7 @@
 #define ABSL_FLAGS_MARSHALLING_H_
 
 #include "absl/base/config.h"
+#include "absl/numeric/int128.h"
 
 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
 #include <optional>
@@ -233,6 +234,8 @@
 bool AbslParseFlag(absl::string_view, long long*, std::string*);       // NOLINT
 bool AbslParseFlag(absl::string_view, unsigned long long*,             // NOLINT
                    std::string*);
+bool AbslParseFlag(absl::string_view, absl::int128*, std::string*);    // NOLINT
+bool AbslParseFlag(absl::string_view, absl::uint128*, std::string*);   // NOLINT
 bool AbslParseFlag(absl::string_view, float*, std::string*);
 bool AbslParseFlag(absl::string_view, double*, std::string*);
 bool AbslParseFlag(absl::string_view, std::string*, std::string*);
diff --git a/absl/flags/marshalling_test.cc b/absl/flags/marshalling_test.cc
index 7b6d2ad..d996ca7 100644
--- a/absl/flags/marshalling_test.cc
+++ b/absl/flags/marshalling_test.cc
@@ -455,6 +455,143 @@
 
 // --------------------------------------------------------------------
 
+TEST(MarshallingTest, TestInt128Parsing) {
+  std::string err;
+  absl::int128 value;
+
+  absl::int128 zero = 0;
+  absl::int128 one = 1;
+  absl::int128 neg_one = -1;
+  absl::int128 hundred = 100;
+  absl::int128 hundreds_val = 123;
+  absl::int128 neg_thousands_val = -98765;
+  absl::int128 pos_three = 3;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, zero);
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_EQ(value, neg_one);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, hundreds_val);
+  EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err));
+  EXPECT_EQ(value, neg_thousands_val);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, pos_three);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, hundred);
+
+  absl::int128 sixteen = 16;
+  absl::int128 quintillion_val = 1152827684197027293;
+  absl::int128 quintillion_val2 =
+      absl::MakeInt128(0x000000000000fff, 0xFFFFFFFFFFFFFFF);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("0xFFFAAABBBCCCDDD", &value, &err));
+  EXPECT_EQ(value, quintillion_val);
+  EXPECT_TRUE(absl::ParseFlag("0xFFF0FFFFFFFFFFFFFFF", &value, &err));
+  EXPECT_EQ(value, quintillion_val2);
+
+  // TODO(b/285183223): Add support for parsing negative hex representation
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("16  ", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("  16", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("  0100  ", &value, &err));
+  EXPECT_EQ(value, hundred);
+  EXPECT_TRUE(absl::ParseFlag(" 0x7B    ", &value, &err));
+  EXPECT_EQ(value, hundreds_val);  // =123
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint128Parsing) {
+  std::string err;
+  absl::uint128 value;
+
+  absl::uint128 zero = 0;
+  absl::uint128 one = 1;
+  absl::uint128 hundred = 100;
+  absl::uint128 hundreds_val = 123;
+  absl::uint128 pos_three = 3;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, zero);
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, hundreds_val);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, pos_three);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+  EXPECT_EQ(value, one);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, hundred);
+
+  absl::uint128 sixteen = 16;
+  absl::uint128 quintillion_val = 1152827684197027293;
+  absl::uint128 quintillion_val2 =
+      absl::MakeInt128(0x000000000000fff, 0xFFFFFFFFFFFFFFF);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("0xFFFAAABBBCCCDDD", &value, &err));
+  EXPECT_EQ(value, quintillion_val);
+  EXPECT_TRUE(absl::ParseFlag("0xFFF0FFFFFFFFFFFFFFF", &value, &err));
+  EXPECT_EQ(value, quintillion_val2);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("16  ", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("  16", &value, &err));
+  EXPECT_EQ(value, sixteen);
+  EXPECT_TRUE(absl::ParseFlag("  0100  ", &value, &err));
+  EXPECT_EQ(value, hundred);
+  EXPECT_TRUE(absl::ParseFlag(" 0x7B    ", &value, &err));
+  EXPECT_EQ(value, hundreds_val);  // =123
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
 TEST(MarshallingTest, TestFloatParsing) {
   std::string err;
   float value;