On Tue, Oct 28, 2025 at 5:18 PM Jonathan Wakely <[email protected]> wrote:

> 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.
>
LGTM.

>
>  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>
>
I was wondering why you are changing this, as i have initially missed this
change.

>  #include <stack>
>  #include <stdexcept>
>  #include <string>
> --
> 2.51.0
>
>

Reply via email to