[PATCH] libstdc++: Simplify std::regex_traits::value

Jonathan Wakely jwakely@redhat.com
Tue Oct 28 16:11:32 GMT 2025


We don't need to use an istringstream to convert a hex digit to its
numerical value.

libstdc++-v3/ChangeLog:

	* include/bits/regex.tcc (regex_traits::value): Implement
	without using istringstream.
	* include/std/regex: Do not include <sstream>.
---

Tested x86_64-linux.

This changes what we do for radix != 8 && radix != 16 but that's fine,
because it's undefined to use an arbitrary radix anyway. The standard
says:

Preconditions: The value of radix is 8, 10, or 16.

 libstdc++-v3/include/bits/regex.tcc | 49 ++++++++++++++++++++++++-----
 libstdc++-v3/include/std/regex      |  1 -
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index b94fe4490f7c..a0edf272717e 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -331,20 +331,53 @@ namespace __detail
 	    && __c == __fctyp.widen('_'));
     }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
   template<typename _Ch_type>
     int
     regex_traits<_Ch_type>::
     value(_Ch_type __ch, int __radix) const
     {
-      std::basic_istringstream<char_type> __is(string_type(1, __ch));
-      long __v;
-      if (__radix == 8)
-	__is >> std::oct;
-      else if (__radix == 16)
-	__is >> std::hex;
-      __is >> __v;
-      return __is.fail() ? -1 : __v;
+      if constexpr (sizeof(_Ch_type) > 1)
+	{
+	  const auto& __ctyp = std::use_facet<ctype<_Ch_type>>(_M_locale);
+	  const char __c = __ctyp.narrow(__ch, '\0');
+	  return regex_traits<char>{}.value(__c, __radix);
+	}
+      else
+	{
+	  const char __c = static_cast<char>(__ch);
+	  const char __max_digit = __radix == 8 ? '7' : '9';
+	  if ('0' <= __ch && __ch <= __max_digit)
+	    return __ch - '0';
+	  if (__radix < 16)
+	    return -1;
+	  switch (__ch)
+	  {
+	    case 'a':
+	    case 'A':
+	      return 10;
+	    case 'b':
+	    case 'B':
+	      return 11;
+	    case 'c':
+	    case 'C':
+	      return 12;
+	    case 'd':
+	    case 'D':
+	      return 13;
+	    case 'e':
+	    case 'E':
+	      return 14;
+	    case 'f':
+	    case 'F':
+	      return 15;
+	    default:
+	      return -1;
+	    }
+	}
     }
+#pragma GCC diagnostic pop
 
   template<typename _Bi_iter, typename _Alloc>
   template<typename _Out_iter>
diff --git a/libstdc++-v3/include/std/regex b/libstdc++-v3/include/std/regex
index 022306621cba..9121d267a793 100644
--- a/libstdc++-v3/include/std/regex
+++ b/libstdc++-v3/include/std/regex
@@ -41,7 +41,6 @@
 
 #include <bitset>
 #include <locale>
-#include <sstream>
 #include <stack>
 #include <stdexcept>
 #include <string>
-- 
2.51.0



More information about the Libstdc++ mailing list