about summary refs log tree commit diff
path: root/absl/strings/numbers.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/numbers.cc')
-rw-r--r--absl/strings/numbers.cc52
1 files changed, 50 insertions, 2 deletions
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index caab463161eb..a0e5a7fd4e7d 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -30,6 +30,7 @@
 #include <memory>
 #include <utility>
 
+#include "absl/base/attributes.h"
 #include "absl/base/internal/bits.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/strings/ascii.h"
@@ -719,8 +720,8 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
 // commonly used bases.
 template <typename IntType>
 struct LookupTables {
-  static const IntType kVmaxOverBase[];
-  static const IntType kVminOverBase[];
+  ABSL_CONST_INIT static const IntType kVmaxOverBase[];
+  ABSL_CONST_INIT static const IntType kVminOverBase[];
 };
 
 // An array initializer macro for X/base where base in [0, 36].
@@ -735,6 +736,49 @@ struct LookupTables {
         X / 35, X / 36,                                                   \
   }
 
+// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
+// array to avoid a static initializer.
+template <>
+const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
+    0,
+    0,
+    MakeUint128(9223372036854775807u, 18446744073709551615u),
+    MakeUint128(6148914691236517205u, 6148914691236517205u),
+    MakeUint128(4611686018427387903u, 18446744073709551615u),
+    MakeUint128(3689348814741910323u, 3689348814741910323u),
+    MakeUint128(3074457345618258602u, 12297829382473034410u),
+    MakeUint128(2635249153387078802u, 5270498306774157604u),
+    MakeUint128(2305843009213693951u, 18446744073709551615u),
+    MakeUint128(2049638230412172401u, 14347467612885206812u),
+    MakeUint128(1844674407370955161u, 11068046444225730969u),
+    MakeUint128(1676976733973595601u, 8384883669867978007u),
+    MakeUint128(1537228672809129301u, 6148914691236517205u),
+    MakeUint128(1418980313362273201u, 4256940940086819603u),
+    MakeUint128(1317624576693539401u, 2635249153387078802u),
+    MakeUint128(1229782938247303441u, 1229782938247303441u),
+    MakeUint128(1152921504606846975u, 18446744073709551615u),
+    MakeUint128(1085102592571150095u, 1085102592571150095u),
+    MakeUint128(1024819115206086200u, 16397105843297379214u),
+    MakeUint128(970881267037344821u, 16504981539634861972u),
+    MakeUint128(922337203685477580u, 14757395258967641292u),
+    MakeUint128(878416384462359600u, 14054662151397753612u),
+    MakeUint128(838488366986797800u, 13415813871788764811u),
+    MakeUint128(802032351030850070u, 4812194106185100421u),
+    MakeUint128(768614336404564650u, 12297829382473034410u),
+    MakeUint128(737869762948382064u, 11805916207174113034u),
+    MakeUint128(709490156681136600u, 11351842506898185609u),
+    MakeUint128(683212743470724133u, 17080318586768103348u),
+    MakeUint128(658812288346769700u, 10540996613548315209u),
+    MakeUint128(636094623231363848u, 15266270957552732371u),
+    MakeUint128(614891469123651720u, 9838263505978427528u),
+    MakeUint128(595056260442243600u, 9520900167075897608u),
+    MakeUint128(576460752303423487u, 18446744073709551615u),
+    MakeUint128(558992244657865200u, 8943875914525843207u),
+    MakeUint128(542551296285575047u, 9765923333140350855u),
+    MakeUint128(527049830677415760u, 8432797290838652167u),
+    MakeUint128(512409557603043100u, 8198552921648689607u),
+};
+
 template <typename IntType>
 const IntType LookupTables<IntType>::kVmaxOverBase[] =
     X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -754,6 +798,8 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
   assert(base >= 0);
   assert(vmax >= static_cast<IntType>(base));
   const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
+  assert(base < 2 ||
+         std::numeric_limits<IntType>::max() / base == vmax_over_base);
   const char* start = text.data();
   const char* end = start + text.size();
   // loop over digits
@@ -787,6 +833,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base,
   assert(vmin < 0);
   assert(vmin <= 0 - base);
   IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
+  assert(base < 2 ||
+         std::numeric_limits<IntType>::min() / base == vmin_over_base);
   // 2003 c++ standard [expr.mul]
   // "... the sign of the remainder is implementation-defined."
   // Although (vmin/base)*base + vmin%base is always vmin.