[libcxx-commits] [libcxx] [libc++] Move the ctype_base implementation to the locale base API (PR #224251)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 17 03:00:24 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/224251
`ctype_base` consists mostly of libc-specific configuration. Moving it to a base class in the locale base API significantly simplifies things.
>From 534effab0e37cc58850cfa2fed9de064331d567c Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 11 Sep 2026 12:56:22 +0200
Subject: [PATCH] [libc++] Move the ctype_base implementation to the locale
base API
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__locale_dir/ctype_base.h | 146 +-----------------
libcxx/include/__locale_dir/locale_base_api.h | 70 ++++++++-
libcxx/include/__locale_dir/support/aix.h | 26 +++-
.../include/__locale_dir/support/bsd_like.h | 48 +++++-
.../__locale_dir/support/default/rune_table.h | 139 +++++++++++++++++
libcxx/include/__locale_dir/support/fuchsia.h | 3 +-
libcxx/include/__locale_dir/support/linux.h | 36 ++++-
.../include/__locale_dir/support/llvm_libc.h | 3 +-
libcxx/include/__locale_dir/support/newlib.h | 35 ++++-
libcxx/include/__locale_dir/support/openbsd.h | 3 +-
libcxx/include/__locale_dir/support/windows.h | 28 +++-
libcxx/include/module.modulemap.in | 1 +
libcxx/src/locale.cpp | 120 +-------------
14 files changed, 376 insertions(+), 283 deletions(-)
create mode 100644 libcxx/include/__locale_dir/support/default/rune_table.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 99c3bd8b72aa8..21f0109b80e52 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -558,6 +558,7 @@ set(files
__locale_dir/support/apple.h
__locale_dir/support/bsd_like.h
__locale_dir/support/default/get_c_locale.h
+ __locale_dir/support/default/rune_table.h
__locale_dir/support/freebsd.h
__locale_dir/support/fuchsia.h
__locale_dir/support/linux.h
diff --git a/libcxx/include/__locale_dir/ctype_base.h b/libcxx/include/__locale_dir/ctype_base.h
index 63eaa3c86b0ab..3817ff614ef77 100644
--- a/libcxx/include/__locale_dir/ctype_base.h
+++ b/libcxx/include/__locale_dir/ctype_base.h
@@ -26,152 +26,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
-class _LIBCPP_EXPORTED_FROM_ABI ctype_base {
+class _LIBCPP_EXPORTED_FROM_ABI ctype_base : public __locale::__ctype_base {
public:
-# if _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
- typedef unsigned long mask;
- static const mask space = 1 << 0;
- static const mask print = 1 << 1;
- static const mask cntrl = 1 << 2;
- static const mask upper = 1 << 3;
- static const mask lower = 1 << 4;
- static const mask alpha = 1 << 5;
- static const mask digit = 1 << 6;
- static const mask punct = 1 << 7;
- static const mask xdigit = 1 << 8;
- static const mask blank = 1 << 9;
-# if defined(__BIONIC__)
- // Historically this was a part of regex_traits rather than ctype_base. The
- // historical value of the constant is preserved for ABI compatibility.
- static const mask __regex_word = 0x8000;
-# else
- static const mask __regex_word = 1 << 10;
-# endif // defined(__BIONIC__)
-# elif defined(__GLIBC__)
- typedef unsigned short mask;
- _LIBCPP_DIAGNOSTIC_PUSH
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmodules-ambiguous-internal-linkage")
- static const mask space = _ISspace;
- static const mask print = _ISprint;
- static const mask cntrl = _IScntrl;
- static const mask upper = _ISupper;
- static const mask lower = _ISlower;
- static const mask alpha = _ISalpha;
- static const mask digit = _ISdigit;
- static const mask punct = _ISpunct;
- static const mask xdigit = _ISxdigit;
- static const mask blank = _ISblank;
- _LIBCPP_DIAGNOSTIC_POP
-# if defined(__mips__) || defined(_LIBCPP_BIG_ENDIAN)
- static const mask __regex_word = static_cast<mask>(_ISbit(15));
-# else
- static const mask __regex_word = 0x80;
-# endif
-# elif defined(_WIN32)
- typedef unsigned short mask;
- static const mask space = _SPACE;
- static const mask print = _BLANK | _PUNCT | _ALPHA | _DIGIT;
- static const mask cntrl = _CONTROL;
- static const mask upper = _UPPER;
- static const mask lower = _LOWER;
- static const mask alpha = _ALPHA;
- static const mask digit = _DIGIT;
- static const mask punct = _PUNCT;
- static const mask xdigit = _HEX;
- static const mask blank = _BLANK;
- static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
-# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
-# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-# elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
-# ifdef __APPLE__
- typedef uint32_t mask;
-# elif defined(__FreeBSD__)
- typedef unsigned long mask;
-# elif defined(__NetBSD__)
- typedef unsigned short mask;
-# endif
- static const mask space = _CTYPE_S;
- static const mask print = _CTYPE_R;
- static const mask cntrl = _CTYPE_C;
- static const mask upper = _CTYPE_U;
- static const mask lower = _CTYPE_L;
- static const mask alpha = _CTYPE_A;
- static const mask digit = _CTYPE_D;
- static const mask punct = _CTYPE_P;
- static const mask xdigit = _CTYPE_X;
-
-# if defined(__NetBSD__)
- static const mask blank = _CTYPE_BL;
- // NetBSD defines classes up to 0x2000
- // see sys/ctype_bits.h, _CTYPE_Q
- static const mask __regex_word = 0x8000;
-# else
- static const mask blank = _CTYPE_B;
- static const mask __regex_word = 0x80;
-# endif
-# elif defined(_AIX)
- typedef unsigned int mask;
- static const mask space = _ISSPACE;
- static const mask print = _ISPRINT;
- static const mask cntrl = _ISCNTRL;
- static const mask upper = _ISUPPER;
- static const mask lower = _ISLOWER;
- static const mask alpha = _ISALPHA;
- static const mask digit = _ISDIGIT;
- static const mask punct = _ISPUNCT;
- static const mask xdigit = _ISXDIGIT;
- static const mask blank = _ISBLANK;
- static const mask __regex_word = 0x8000;
-# elif _LIBCPP_LIBC_NEWLIB
- // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
- typedef char mask;
- // In case char is signed, static_cast is needed to avoid warning on
- // positive value becomming negative.
- static const mask space = static_cast<mask>(_S);
- static const mask print = static_cast<mask>(_P | _U | _L | _N | _B);
- static const mask cntrl = static_cast<mask>(_C);
- static const mask upper = static_cast<mask>(_U);
- static const mask lower = static_cast<mask>(_L);
- static const mask alpha = static_cast<mask>(_U | _L);
- static const mask digit = static_cast<mask>(_N);
- static const mask punct = static_cast<mask>(_P);
- static const mask xdigit = static_cast<mask>(_X | _N);
- static const mask blank = static_cast<mask>(_B);
- // mask is already fully saturated, use a different type in regex_type_traits.
- static const unsigned short __regex_word = 0x100;
-# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
-# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
-# elif defined(__MVS__)
-# if defined(__NATIVE_ASCII_F)
- typedef unsigned int mask;
- static const mask space = _ISSPACE_A;
- static const mask print = _ISPRINT_A;
- static const mask cntrl = _ISCNTRL_A;
- static const mask upper = _ISUPPER_A;
- static const mask lower = _ISLOWER_A;
- static const mask alpha = _ISALPHA_A;
- static const mask digit = _ISDIGIT_A;
- static const mask punct = _ISPUNCT_A;
- static const mask xdigit = _ISXDIGIT_A;
- static const mask blank = _ISBLANK_A;
-# else
- typedef unsigned short mask;
- static const mask space = __ISSPACE;
- static const mask print = __ISPRINT;
- static const mask cntrl = __ISCNTRL;
- static const mask upper = __ISUPPER;
- static const mask lower = __ISLOWER;
- static const mask alpha = __ISALPHA;
- static const mask digit = __ISDIGIT;
- static const mask punct = __ISPUNCT;
- static const mask xdigit = __ISXDIGIT;
- static const mask blank = __ISBLANK;
-# endif
- static const mask __regex_word = 0x8000;
-# else
-# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
-# endif
static const mask alnum = alpha | digit;
static const mask graph = alnum | punct;
diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index 14ff9d8a45b56..c86832e562ac1 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -50,6 +50,29 @@
// #define _LIBCPP_ALL_MASK /* implementation-defined */
// #define _LIBCPP_LC_ALL /* implementation-defined */
//
+//
+// ctype masks
+// -----------
+//
+// // required by the headers
+// struct __ctype_base { // may be an alias instead
+// using mask = /* implementation-defined */
+//
+// static const mask space = /* implementation-defined */
+// static const mask print = /* implementation-defined */
+// static const mask cntrl = /* implementation-defined */
+// static const mask upper = /* implementation-defined */
+// static const mask lower = /* implementation-defined */
+// static const mask alpha = /* implementation-defined */
+// static const mask digit = /* implementation-defined */
+// static const mask punct = /* implementation-defined */
+// static const mask xdigit = /* implementation-defined */
+// static const mask blank = /* implementation-defined */
+// static const mask __regex_word = /* implementation-defined */
+// };
+//
+// const mask* __classic_table() noexcept;
+//
// Strtonum functions
// ------------------
// namespace __locale {
@@ -105,8 +128,6 @@
//
// const char* __get_locale_encoding(__locale_t);
//
-// #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE /* 0 or 1 depending on whether a rune table has to be provided */
-//
// }
#if _LIBCPP_HAS_LOCALIZATION
@@ -182,6 +203,51 @@ inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__
inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
# endif // _LIBCPP_BUILDING_LIBRARY
+//
+// ctype masks
+//
+
+struct __ctype_base {
+# if defined(__NATIVE_ASCII_F)
+ using mask = unsigned int;
+
+ static const mask space = _ISSPACE_A;
+ static const mask print = _ISPRINT_A;
+ static const mask cntrl = _ISCNTRL_A;
+ static const mask upper = _ISUPPER_A;
+ static const mask lower = _ISLOWER_A;
+ static const mask alpha = _ISALPHA_A;
+ static const mask digit = _ISDIGIT_A;
+ static const mask punct = _ISPUNCT_A;
+ static const mask xdigit = _ISXDIGIT_A;
+ static const mask blank = _ISBLANK_A;
+# else
+ using mask = unsigned short;
+
+ static const mask space = __ISSPACE;
+ static const mask print = __ISPRINT;
+ static const mask cntrl = __ISCNTRL;
+ static const mask upper = __ISUPPER;
+ static const mask lower = __ISLOWER;
+ static const mask alpha = __ISALPHA;
+ static const mask digit = __ISDIGIT;
+ static const mask punct = __ISPUNCT;
+ static const mask xdigit = __ISXDIGIT;
+ static const mask blank = __ISBLANK;
+# endif
+ static const mask __regex_word = 0x8000;
+};
+
+# ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() noexcept {
+# if defined(__NATIVE_ASCII_F)
+ return const_cast<const ctype<char>::mask*>(__OBJ_DATA(__lc_ctype_a)->mask);
+# else
+ return const_cast<const ctype<char>::mask*>(__ctypec);
+# endif
+}
+# endif
+
//
// Strtonum functions
//
diff --git a/libcxx/include/__locale_dir/support/aix.h b/libcxx/include/__locale_dir/support/aix.h
index d5c2b395b1a37..98fd82dce3edf 100644
--- a/libcxx/include/__locale_dir/support/aix.h
+++ b/libcxx/include/__locale_dir/support/aix.h
@@ -86,6 +86,30 @@ inline _LIBCPP_HIDE_FROM_ABI const char* __get_locale_encoding(__locale_t __loc)
}
#endif // _LIBCPP_BUILDING_LIBRARY
+//
+// ctype masks
+//
+
+struct __ctype_base {
+ using mask = unsigned int;
+
+ static const mask space = _ISSPACE;
+ static const mask print = _ISPRINT;
+ static const mask cntrl = _ISCNTRL;
+ static const mask upper = _ISUPPER;
+ static const mask lower = _ISLOWER;
+ static const mask alpha = _ISALPHA;
+ static const mask digit = _ISDIGIT;
+ static const mask punct = _ISPUNCT;
+ static const mask xdigit = _ISXDIGIT;
+ static const mask blank = _ISBLANK;
+ static const mask __regex_word = 0x8000;
+};
+
+#ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() _NOEXCEPT { return (const unsigned int*)__lc_ctype_ptr->obj->mask; }
+#endif
+
// The following structure is a quick-and-dirty workaround for routines that AIX
// does not provide in the "_l" (locale-aware) variants.
struct __setAndRestore {
@@ -298,8 +322,6 @@ _LIBCPP_DIAGNOSTIC_POP
} // namespace __locale
_LIBCPP_END_NAMESPACE_STD
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
-
#include <__locale_dir/support/default/get_c_locale.h>
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_AIX_H
diff --git a/libcxx/include/__locale_dir/support/bsd_like.h b/libcxx/include/__locale_dir/support/bsd_like.h
index ebe3f726e34ff..a6e9a73cf060c 100644
--- a/libcxx/include/__locale_dir/support/bsd_like.h
+++ b/libcxx/include/__locale_dir/support/bsd_like.h
@@ -75,6 +75,52 @@ inline __locale_t __get_c_locale() {
#endif
}
+//
+// ctype masks
+//
+
+struct __ctype_base {
+#ifdef __APPLE__
+ using mask = uint32_t;
+#elif defined(__FreeBSD__)
+ using mask = unsigned long;
+#elif defined(__NetBSD__)
+ using mask = unsigned short;
+#else
+# error "BSD-like platforms have to update this list."
+#endif
+ static const mask space = _CTYPE_S;
+ static const mask print = _CTYPE_R;
+ static const mask cntrl = _CTYPE_C;
+ static const mask upper = _CTYPE_U;
+ static const mask lower = _CTYPE_L;
+ static const mask alpha = _CTYPE_A;
+ static const mask digit = _CTYPE_D;
+ static const mask punct = _CTYPE_P;
+ static const mask xdigit = _CTYPE_X;
+
+#if defined(__NetBSD__)
+ static const mask blank = _CTYPE_BL;
+ // NetBSD defines classes up to 0x2000
+ // see sys/ctype_bits.h, _CTYPE_Q
+ static const mask __regex_word = 0x8000;
+#else
+ static const mask blank = _CTYPE_B;
+ static const mask __regex_word = 0x80;
+#endif
+};
+
+#ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() noexcept {
+# if defined(__APPLE__) || defined(__FreeBSD__)
+ return _DefaultRuneLocale.__runetype;
+# elif defined(__NetBSD__)
+ return _C_ctype_tab_ + 1;
+# else
+# error "BSD-like platforms have to update this list."
+# endif
+}
+#endif
//
// Strtonum functions
//
@@ -223,6 +269,4 @@ _LIBCPP_DIAGNOSTIC_POP
} // namespace __locale
_LIBCPP_END_NAMESPACE_STD
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
-
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_BSD_LIKE_H
diff --git a/libcxx/include/__locale_dir/support/default/rune_table.h b/libcxx/include/__locale_dir/support/default/rune_table.h
new file mode 100644
index 0000000000000..4df184f126bda
--- /dev/null
+++ b/libcxx/include/__locale_dir/support/default/rune_table.h
@@ -0,0 +1,139 @@
+//===-----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_DEFAULT_RUNE_TABLE_H
+#define _LIBCPP___LOCALE_DIR_SUPPORT_DEFAULT_RUNE_TABLE_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace __locale {
+struct __ctype_base {
+ typedef unsigned long mask;
+ static const mask space = 1 << 0;
+ static const mask print = 1 << 1;
+ static const mask cntrl = 1 << 2;
+ static const mask upper = 1 << 3;
+ static const mask lower = 1 << 4;
+ static const mask alpha = 1 << 5;
+ static const mask digit = 1 << 6;
+ static const mask punct = 1 << 7;
+ static const mask xdigit = 1 << 8;
+ static const mask blank = 1 << 9;
+#if defined(__BIONIC__)
+ // Historically this was a part of regex_traits rather than ctype_base. The
+ // historical value of the constant is preserved for ABI compatibility.
+ static const mask __regex_word = 0x8000;
+#else
+ static const mask __regex_word = 1 << 10;
+#endif // defined(__BIONIC__)
+};
+
+#ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() noexcept {
+ constexpr auto space = __ctype_base::space;
+ constexpr auto print = __ctype_base::print;
+ constexpr auto cntrl = __ctype_base::cntrl;
+ constexpr auto upper = __ctype_base::upper;
+ constexpr auto lower = __ctype_base::lower;
+ constexpr auto alpha = __ctype_base::alpha;
+ constexpr auto digit = __ctype_base::digit;
+ constexpr auto punct = __ctype_base::punct;
+ constexpr auto xdigit = __ctype_base::xdigit;
+ constexpr auto blank = __ctype_base::blank;
+
+ // clang-format off
+ static constexpr const __ctype_base::mask __table[256] = {
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl | space | blank,
+ cntrl | space, cntrl | space,
+ cntrl | space, cntrl | space,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ cntrl, cntrl,
+ space | blank | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ digit | print | xdigit, digit | print | xdigit,
+ digit | print | xdigit, digit | print | xdigit,
+ digit | print | xdigit, digit | print | xdigit,
+ digit | print | xdigit, digit | print | xdigit,
+ digit | print | xdigit, digit | print | xdigit,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, upper | xdigit | print | alpha,
+ upper | xdigit | print | alpha, upper | xdigit | print | alpha,
+ upper | xdigit | print | alpha, upper | xdigit | print | alpha,
+ upper | xdigit | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, upper | print | alpha,
+ upper | print | alpha, punct | print,
+ punct | print, punct | print,
+ punct | print, punct | print,
+ punct | print, lower | xdigit | print | alpha,
+ lower | xdigit | print | alpha, lower | xdigit | print | alpha,
+ lower | xdigit | print | alpha, lower | xdigit | print | alpha,
+ lower | xdigit | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, lower | print | alpha,
+ lower | print | alpha, punct | print,
+ punct | print, punct | print,
+ punct | print, cntrl,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ // clang-format on
+ return __table;
+}
+#endif
+
+} // namespace __locale
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___LOCALE_DIR_SUPPORT_DEFAULT_RUNE_TABLE_H
diff --git a/libcxx/include/__locale_dir/support/fuchsia.h b/libcxx/include/__locale_dir/support/fuchsia.h
index 0b4c268108032..c3f155d8840d5 100644
--- a/libcxx/include/__locale_dir/support/fuchsia.h
+++ b/libcxx/include/__locale_dir/support/fuchsia.h
@@ -153,9 +153,8 @@ _LIBCPP_DIAGNOSTIC_POP
_LIBCPP_END_NAMESPACE_STD
#include <__locale_dir/support/default/get_c_locale.h>
+#include <__locale_dir/support/default/rune_table.h>
#include <__locale_dir/support/no_locale/characters.h>
#include <__locale_dir/support/no_locale/strtonum.h>
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
-
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_FUCHSIA_H
diff --git a/libcxx/include/__locale_dir/support/linux.h b/libcxx/include/__locale_dir/support/linux.h
index 8d20bbe9180c4..048f5655dabe7 100644
--- a/libcxx/include/__locale_dir/support/linux.h
+++ b/libcxx/include/__locale_dir/support/linux.h
@@ -82,6 +82,38 @@ inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) {
}
#endif // _LIBCPP_BUILDING_LIBRARY
+//
+// ctype masks
+//
+
+#if !(defined(__BIONIC__) || _LIBCPP_HAS_MUSL_LIBC)
+struct __ctype_base {
+ using mask = unsigned short;
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmodules-ambiguous-internal-linkage")
+ static const mask space = _ISspace;
+ static const mask print = _ISprint;
+ static const mask cntrl = _IScntrl;
+ static const mask upper = _ISupper;
+ static const mask lower = _ISlower;
+ static const mask alpha = _ISalpha;
+ static const mask digit = _ISdigit;
+ static const mask punct = _ISpunct;
+ static const mask xdigit = _ISxdigit;
+ static const mask blank = _ISblank;
+ _LIBCPP_DIAGNOSTIC_POP
+# if defined(__mips__) || defined(_LIBCPP_BIG_ENDIAN)
+ static const mask __regex_word = static_cast<mask>(_ISbit(15));
+# else
+ static const mask __regex_word = 0x80;
+# endif
+};
+
+__locale_t __get_c_locale();
+
+inline const __ctype_base::mask* __classic_table() noexcept { return __get_c_locale()->__ctype_b; }
+#endif
+
//
// Strtonum functions
//
@@ -253,9 +285,7 @@ inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
_LIBCPP_END_NAMESPACE_STD
#if defined(__BIONIC__) || _LIBCPP_HAS_MUSL_LIBC
-# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
-#else
-# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
+# include <__locale_dir/support/default/rune_table.h>
#endif
#include <__locale_dir/support/default/get_c_locale.h>
diff --git a/libcxx/include/__locale_dir/support/llvm_libc.h b/libcxx/include/__locale_dir/support/llvm_libc.h
index 6f3662ae99dae..fced448ce8741 100644
--- a/libcxx/include/__locale_dir/support/llvm_libc.h
+++ b/libcxx/include/__locale_dir/support/llvm_libc.h
@@ -55,11 +55,10 @@ inline _LIBCPP_HIDE_FROM_ABI const char* __get_locale_encoding(__locale_t) { ret
_LIBCPP_END_NAMESPACE_STD
#include <__locale_dir/support/default/get_c_locale.h>
+#include <__locale_dir/support/default/rune_table.h>
#include <__locale_dir/support/no_locale/characters.h>
#include <__locale_dir/support/no_locale/conversions.h>
#include <__locale_dir/support/no_locale/formatting.h>
#include <__locale_dir/support/no_locale/strtonum.h>
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
-
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_LLVM_LIBC_H
diff --git a/libcxx/include/__locale_dir/support/newlib.h b/libcxx/include/__locale_dir/support/newlib.h
index daf60e8a48ea2..646a750666e3b 100644
--- a/libcxx/include/__locale_dir/support/newlib.h
+++ b/libcxx/include/__locale_dir/support/newlib.h
@@ -83,6 +83,39 @@ inline _LIBCPP_HIDE_FROM_ABI const char* __get_locale_encoding(__locale_t __loc)
}
#endif // _LIBCPP_BUILDING_LIBRARY
+//
+// ctype masks
+//
+
+struct __ctype_base {
+ // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
+ typedef char mask;
+ // In case char is signed, static_cast is needed to avoid warning on
+ // positive value becomming negative.
+ static const mask space = static_cast<mask>(_S);
+ static const mask print = static_cast<mask>(_P | _U | _L | _N | _B);
+ static const mask cntrl = static_cast<mask>(_C);
+ static const mask upper = static_cast<mask>(_U);
+ static const mask lower = static_cast<mask>(_L);
+ static const mask alpha = static_cast<mask>(_U | _L);
+ static const mask digit = static_cast<mask>(_N);
+ static const mask punct = static_cast<mask>(_P);
+ static const mask xdigit = static_cast<mask>(_X | _N);
+ static const mask blank = static_cast<mask>(_B);
+ // mask is already fully saturated, use a different type in regex_type_traits.
+ static const unsigned short __regex_word = 0x100;
+#define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
+#define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
+#define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
+};
+
+#ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() noexcept {
+ // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
+ return _ctype_ + 1;
+}
+#endif
+
//
// Strtonum functions
//
@@ -245,8 +278,6 @@ inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
} // namespace __locale
_LIBCPP_END_NAMESPACE_STD
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
-
#include <__locale_dir/support/default/get_c_locale.h>
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_NEWLIB_H
diff --git a/libcxx/include/__locale_dir/support/openbsd.h b/libcxx/include/__locale_dir/support/openbsd.h
index 85f008f8a17f0..1a80d635e12ea 100644
--- a/libcxx/include/__locale_dir/support/openbsd.h
+++ b/libcxx/include/__locale_dir/support/openbsd.h
@@ -226,8 +226,7 @@ _LIBCPP_DIAGNOSTIC_POP
} // namespace __locale
_LIBCPP_END_NAMESPACE_STD
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
-
#include <__locale_dir/support/default/get_c_locale.h>
+#include <__locale_dir/support/default/rune_table.h>
#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_OPENBSD_H
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index 5f35d089ac1fc..cab5e0c6b96f9 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -167,6 +167,32 @@ _LIBCPP_EXPORTED_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc);
_LIBCPP_EXPORTED_FROM_ABI const char* __get_locale_encoding(__locale_t __loc);
#endif // _LIBCPP_BUILDING_LIBRARY
+//
+// ctype masks
+//
+
+struct __ctype_base {
+ using mask = unsigned short;
+
+ static const mask space = _SPACE;
+ static const mask print = _BLANK | _PUNCT | _ALPHA | _DIGIT;
+ static const mask cntrl = _CONTROL;
+ static const mask upper = _UPPER;
+ static const mask lower = _LOWER;
+ static const mask alpha = _ALPHA;
+ static const mask digit = _DIGIT;
+ static const mask punct = _PUNCT;
+ static const mask xdigit = _HEX;
+ static const mask blank = _BLANK;
+ static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
+#define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
+#define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
+};
+
+#ifdef _LIBCPP_BUILDING_LIBRARY
+inline const __ctype_base::mask* __classic_table() noexcept { return __pctype_func(); }
+#endif
+
//
// Strtonum functions
//
@@ -309,8 +335,6 @@ struct __locale_guard {
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
_LIBCPP_END_NAMESPACE_STD
-#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
-
#include <__locale_dir/support/default/get_c_locale.h>
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_WINDOWS_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 3e2b446780a43..8e676604b5800 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1628,6 +1628,7 @@ module std {
textual header "__locale_dir/support/apple.h"
textual header "__locale_dir/support/bsd_like.h"
textual header "__locale_dir/support/default/get_c_locale.h"
+ textual header "__locale_dir/support/default/rune_table.h"
textual header "__locale_dir/support/freebsd.h"
textual header "__locale_dir/support/fuchsia.h"
textual header "__locale_dir/support/linux.h"
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index 058bc0ec6f901..9060938a06e68 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -810,125 +810,7 @@ const char* ctype<char>::do_narrow(const char_type* low, const char_type* high,
return low;
}
-#if defined(__EMSCRIPTEN__)
-extern "C" const unsigned short** __ctype_b_loc();
-extern "C" const int** __ctype_tolower_loc();
-extern "C" const int** __ctype_toupper_loc();
-#endif
-
-#if _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
-const ctype<char>::mask* ctype<char>::classic_table() noexcept {
- // clang-format off
- static constexpr const ctype<char>::mask builtin_table[table_size] = {
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl | space | blank,
- cntrl | space, cntrl | space,
- cntrl | space, cntrl | space,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- cntrl, cntrl,
- space | blank | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- digit | print | xdigit, digit | print | xdigit,
- digit | print | xdigit, digit | print | xdigit,
- digit | print | xdigit, digit | print | xdigit,
- digit | print | xdigit, digit | print | xdigit,
- digit | print | xdigit, digit | print | xdigit,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, upper | xdigit | print | alpha,
- upper | xdigit | print | alpha, upper | xdigit | print | alpha,
- upper | xdigit | print | alpha, upper | xdigit | print | alpha,
- upper | xdigit | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, upper | print | alpha,
- upper | print | alpha, punct | print,
- punct | print, punct | print,
- punct | print, punct | print,
- punct | print, lower | xdigit | print | alpha,
- lower | xdigit | print | alpha, lower | xdigit | print | alpha,
- lower | xdigit | print | alpha, lower | xdigit | print | alpha,
- lower | xdigit | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, lower | print | alpha,
- lower | print | alpha, punct | print,
- punct | print, punct | print,
- punct | print, cntrl,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- // clang-format on
- return builtin_table;
-}
-#else
-const ctype<char>::mask* ctype<char>::classic_table() noexcept {
-# if defined(__APPLE__) || defined(__FreeBSD__)
- return _DefaultRuneLocale.__runetype;
-# elif defined(__NetBSD__)
- return _C_ctype_tab_ + 1;
-# elif defined(__GLIBC__)
- return __locale::__get_c_locale()->__ctype_b;
-# elif defined(_WIN32)
- return __pctype_func();
-# elif defined(__EMSCRIPTEN__)
- return *__ctype_b_loc();
-# elif _LIBCPP_LIBC_NEWLIB
- // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
- return _ctype_ + 1;
-# elif defined(_AIX)
- return (const unsigned int*)__lc_ctype_ptr->obj->mask;
-# elif defined(__MVS__)
-# if defined(__NATIVE_ASCII_F)
- return const_cast<const ctype<char>::mask*>(__OBJ_DATA(__lc_ctype_a)->mask);
-# else
- return const_cast<const ctype<char>::mask*>(__ctypec);
-# endif
-# else
- // Platform not supported: abort so the person doing the port knows what to
- // fix
-# warning ctype<char>::classic_table() is not implemented
- printf("ctype<char>::classic_table() is not implemented\n");
- abort();
- return nullptr;
-# endif
-}
-#endif
+const ctype<char>::mask* ctype<char>::classic_table() noexcept { return __classic_table(); }
// template <> class ctype_byname<char>
More information about the libcxx-commits
mailing list