[libcxx-commits] [libcxx] [libc++] Optimize num_get integral functions (PR #121795)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Feb 26 07:58:04 PST 2025


================
@@ -836,98 +796,137 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed(
   char_type __atoms1[__atoms_size];
   const char_type* __atoms = this->__do_widen(__iob, __atoms1);
   string __grouping        = this->__stage2_int_prep(__iob, __thousands_sep);
-  string __buf;
-  __buf.resize(__buf.capacity());
-  char* __a     = &__buf[0];
-  char* __a_end = __a;
   unsigned __g[__num_get_base::__num_get_buf_sz];
   unsigned* __g_end = __g;
   unsigned __dc     = 0;
-  for (; __b != __e; ++__b) {
-    if (__a_end == __a + __buf.size()) {
-      size_t __tmp = __buf.size();
-      __buf.resize(2 * __buf.size());
-      __buf.resize(__buf.capacity());
-      __a     = &__buf[0];
-      __a_end = __a + __tmp;
+
+  if (__first == __last) {
+    __err |= ios_base::eofbit;
+    return __first;
+  }
+
+  while (!__grouping.empty() && *__first == __thousands_sep) {
+    ++__first;
+    if (__g_end - __g < this->__num_get_buf_sz) {
+      *__g_end++ = __dc;
+      __dc       = 0;
     }
-    if (this->__stage2_int_loop(
-            *__b,
-            __base,
-            __a,
-            __a_end,
-            __dc,
-            __thousands_sep,
-            __grouping,
-            __g,
-            __g_end,
-            const_cast<char_type*>(__atoms)))
-      break;
   }
-  if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
-    *__g_end++ = __dc;
-  // Stage 3
-  __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
-  // Digit grouping checked
-  __check_grouping(__grouping, __g, __g_end, __err);
-  // EOF checked
-  if (__b == __e)
+
+  bool __negate = false;
+  // __c == '+' || __c == '-'
+  if (auto __c = *__first; __c == __atoms[24] || __c == __atoms[25]) {
+    __negate = __c == __atoms[25];
+    ++__first;
+  }
+
+  if (__first == __last) {
     __err |= ios_base::eofbit;
-  return __b;
-}
+    return __first;
+  }
 
-// unsigned
+  bool __parsed_num = false;
 
-template <class _CharT, class _InputIterator>
-template <class _Unsigned>
-_InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned(
-    iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const {
-  // Stage 1
-  int __base = this->__get_base(__iob);
-  // Stage 2
-  char_type __thousands_sep;
-  const int __atoms_size = __num_get_base::__int_chr_cnt;
-  char_type __atoms1[__atoms_size];
-  const char_type* __atoms = this->__do_widen(__iob, __atoms1);
-  string __grouping        = this->__stage2_int_prep(__iob, __thousands_sep);
-  string __buf;
-  __buf.resize(__buf.capacity());
-  char* __a     = &__buf[0];
-  char* __a_end = __a;
-  unsigned __g[__num_get_base::__num_get_buf_sz];
-  unsigned* __g_end = __g;
-  unsigned __dc     = 0;
-  for (; __b != __e; ++__b) {
-    if (__a_end == __a + __buf.size()) {
-      size_t __tmp = __buf.size();
-      __buf.resize(2 * __buf.size());
-      __buf.resize(__buf.capacity());
-      __a     = &__buf[0];
-      __a_end = __a + __tmp;
+  // If we don't have a pre-set base, figure it out
+  if (__base == 0) {
+    auto __c = *__first;
+    // __c == '0'
+    if (__c == __atoms[0]) {
+      ++__first;
+      if (__first == __last) {
+        __err |= ios_base::eofbit;
+        return __first;
+      }
+      // __c2 == 'x' || __c2 == 'X'
+      if (auto __c2 = *__first; __c2 == __atoms[22] || __c2 == __atoms[23]) {
+        __base = 16;
+        ++__first;
+      } else {
+        __base = 8;
+      }
+    } else {
+      __base = 10;
     }
-    if (this->__stage2_int_loop(
----------------
ldionne wrote:

`__stage2_int_loop` is part of the ABI but it's otherwise not used anymore. So we should add a deprecation attribute like we do [here](https://github.com/llvm/llvm-project/blob/main/libcxx/include/locale#L404) for `__stage2_int_prep`, and move the definition of the function to `src/` with a comment about it being pure ABI backwards compatibility.

https://github.com/llvm/llvm-project/pull/121795


More information about the libcxx-commits mailing list