[libc-commits] [libc] d00a49f - [libc] Add iswctype and wctype (#191178)
via libc-commits
libc-commits at lists.llvm.org
Fri Apr 17 03:52:25 PDT 2026
Author: Elio
Date: 2026-04-17T11:52:20+01:00
New Revision: d00a49fc3495f260d8b3125b5d9f4e263ac13166
URL: https://github.com/llvm/llvm-project/commit/d00a49fc3495f260d8b3125b5d9f4e263ac13166
DIFF: https://github.com/llvm/llvm-project/commit/d00a49fc3495f260d8b3125b5d9f4e263ac13166.diff
LOG: [libc] Add iswctype and wctype (#191178)
Implement the iswctype and wctype functions from <wctype.h>.
- Add wctype_t type definition.
- Implement wctype to map property strings to classification
descriptors.
- Implement iswctype as a dispatcher over existing wide character
classification functions.
- Add corresponding entrypoints and unit tests.
Refs: https://github.com/llvm/llvm-project/issues/191076
---------
Co-authored-by: Zile Xiong <xiongzile99 at gmail.com>
Added:
libc/hdr/types/wctype_t.h
libc/hdr/wctype_overlay.h
libc/include/llvm-libc-types/wctype_t.h
libc/src/wctype/iswctype.cpp
libc/src/wctype/iswctype.h
libc/src/wctype/wctype.cpp
libc/src/wctype/wctype.h
libc/test/src/wctype/iswctype_test.cpp
libc/test/src/wctype/wctype_test.cpp
Modified:
libc/config/baremetal/arm/entrypoints.txt
libc/config/baremetal/riscv/entrypoints.txt
libc/config/darwin/aarch64/entrypoints.txt
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/arm/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/windows/entrypoints.txt
libc/hdr/types/CMakeLists.txt
libc/include/CMakeLists.txt
libc/include/llvm-libc-types/CMakeLists.txt
libc/include/wctype.yaml
libc/src/__support/wctype_utils.h
libc/src/wctype/CMakeLists.txt
libc/test/src/__support/wctype_utils_test.cpp
libc/test/src/wctype/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 9c0e71b2beec0..41c80efc64227 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -314,6 +314,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
# internal entrypoints
libc.startup.baremetal.init
libc.startup.baremetal.fini
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5c88bc4ae1fb7..88eacfae12969 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -311,6 +311,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
# internal entrypoints
libc.startup.baremetal.init
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index c93ba47a6f2d6..914d2b7918da1 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -114,6 +114,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
)
if(LLVM_LIBC_FULL_BUILD)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 6f7567cf3789f..87bd5461496b3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -386,6 +386,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
# sys/uio.h entrypoints
libc.src.sys.uio.writev
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 167d762f36cb9..8a4d88b5ba98c 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -206,6 +206,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
)
if(LLVM_LIBC_FULL_BUILD)
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 1856d8edba7de..ea117c1d83c24 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -390,6 +390,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
# sys/uio.h entrypoints
libc.src.sys.uio.writev
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index fe5991c695e25..5c69c8808b2c1 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -440,6 +440,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
# sys/uio.h entrypoints
libc.src.sys.uio.writev
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index c6db359933f08..94d1d00e676d9 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -120,6 +120,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wctype.iswxdigit
libc.src.wctype.iswpunct
libc.src.wctype.iswprint
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
)
set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 7e1a8974fa486..7395f70c0d2aa 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -443,6 +443,15 @@ add_proxy_header_library(
libc.include.wchar
)
+
+add_proxy_header_library(
+ wctype_t
+ HDRS
+ wctype_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.wctype_t
+)
+
add_proxy_header_library(
uid_t
HDRS
diff --git a/libc/hdr/types/wctype_t.h b/libc/hdr/types/wctype_t.h
new file mode 100644
index 0000000000000..39f33b87f3e15
--- /dev/null
+++ b/libc/hdr/types/wctype_t.h
@@ -0,0 +1,23 @@
+//===-- Definition of wctype_t.h ------------------------------------------===//
+//
+// 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 LLVM_LIBC_HDR_TYPES_WCTYPE_T_H
+#define LLVM_LIBC_HDR_TYPES_WCTYPE_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/wctype_t.h"
+
+#else // overlay mode
+
+#include "hdr/wctype_overlay.h"
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_WCTYPE_T_H
diff --git a/libc/hdr/wctype_overlay.h b/libc/hdr/wctype_overlay.h
new file mode 100644
index 0000000000000..3ae7fbe24ec8d
--- /dev/null
+++ b/libc/hdr/wctype_overlay.h
@@ -0,0 +1,69 @@
+//===-- Including wctype.h in overlay mode --------------------------------===//
+//
+// 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 LLVM_LIBC_HDR_WCTYPE_OVERLAY_H
+#define LLVM_LIBC_HDR_WCTYPE_OVERLAY_H
+
+#ifdef LIBC_FULL_BUILD
+#error "This header should only be included in overlay mode"
+#endif
+
+// Overlay mode
+
+// glibc <wctype.h> header might provide extern inline definitions for few
+// functions, causing external alias errors. They are guarded by
+// `__USE_EXTERN_INLINES` macro. We temporarily disable `__USE_EXTERN_INLINES`
+// macro by defining `__NO_INLINE__` before including <wctype.h>.
+// And the same with `__USE_FORTIFY_LEVEL`, which will be temporarily disabled
+// with `_FORTIFY_SOURCE`.
+
+#ifdef _FORTIFY_SOURCE
+#define LIBC_OLD_FORTIFY_SOURCE _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+
+#ifndef __NO_INLINE__
+#define __NO_INLINE__ 1
+#define LIBC_SET_NO_INLINE
+#endif
+
+#ifdef __USE_EXTERN_INLINES
+#define LIBC_OLD_USE_EXTERN_INLINES
+#undef __USE_EXTERN_INLINES
+#endif
+
+#ifdef __USE_FORTIFY_LEVEL
+#define LIBC_OLD_USE_FORTIFY_LEVEL __USE_FORTIFY_LEVEL
+#undef __USE_FORTIFY_LEVEL
+#define __USE_FORTIFY_LEVEL 0
+#endif
+
+#include <wctype.h>
+
+#ifdef LIBC_OLD_FORTIFY_SOURCE
+#define _FORTIFY_SOURCE LIBC_OLD_FORTIFY_SOURCE
+#undef LIBC_OLD_FORTIFY_SOURCE
+#endif
+
+#ifdef LIBC_SET_NO_INLINE
+#undef __NO_INLINE__
+#undef LIBC_SET_NO_INLINE
+#endif
+
+#ifdef LIBC_OLD_USE_FORTIFY_LEVEL
+#undef __USE_FORTIFY_LEVEL
+#define __USE_FORTIFY_LEVEL LIBC_OLD_USE_FORTIFY_LEVEL
+#undef LIBC_OLD_USE_FORTIFY_LEVEL
+#endif
+
+#ifdef LIBC_OLD_USE_EXTERN_INLINES
+#define __USE_EXTERN_INLINES
+#undef LIBC_OLD_USE_EXTERN_INLINES
+#endif
+
+#endif // LLVM_LIBC_HDR_WCTYPE_OVERLAY_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index ab1d4967d4183..74d31025f9f4d 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -887,6 +887,7 @@ add_header_macro(
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.wint_t
+ .llvm-libc-types.wctype_t
)
add_header_macro(
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index e40f6e194ab3a..021e0a29555cf 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -191,6 +191,7 @@ add_header(
libc.include.llvm-libc-macros.stdint_macros
)
add_header(wint_t HDR wint_t.h)
+add_header(wctype_t HDR wctype_t.h)
add_header(sa_family_t HDR sa_family_t.h)
add_header(socklen_t HDR socklen_t.h)
add_header(struct_sockaddr_un HDR struct_sockaddr_un.h DEPENDS .sa_family_t)
diff --git a/libc/include/llvm-libc-types/wctype_t.h b/libc/include/llvm-libc-types/wctype_t.h
new file mode 100644
index 0000000000000..47840df02fc46
--- /dev/null
+++ b/libc/include/llvm-libc-types/wctype_t.h
@@ -0,0 +1,14 @@
+//===-- Definition of wctype_t types --------------------------------------===//
+//
+// 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 LLVM_LIBC_TYPES_WCTYPE_T_H
+#define LLVM_LIBC_TYPES_WCTYPE_T_H
+
+typedef unsigned int wctype_t;
+
+#endif // LLVM_LIBC_TYPES_WCTYPE_T_H
diff --git a/libc/include/wctype.yaml b/libc/include/wctype.yaml
index 932ff6ac1b138..a5163ecc2d3f2 100644
--- a/libc/include/wctype.yaml
+++ b/libc/include/wctype.yaml
@@ -1,6 +1,7 @@
header: wctype.h
types:
- type_name: wint_t
+ - type_name: wctype_t
functions:
- name: iswalpha
standards:
@@ -74,3 +75,16 @@ functions:
return_type: int
arguments:
- type: wint_t
+ - name: iswctype
+ standards:
+ - stdc
+ return_type: int
+ arguments:
+ - type: wint_t
+ - type: wctype_t
+ - name: wctype
+ standards:
+ - stdc
+ return_type: wctype_t
+ arguments:
+ - type: const char*
diff --git a/libc/src/__support/wctype_utils.h b/libc/src/__support/wctype_utils.h
index a80c78d54c796..9c66990f8b9d7 100644
--- a/libc/src/__support/wctype_utils.h
+++ b/libc/src/__support/wctype_utils.h
@@ -10,6 +10,9 @@
#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
#include "hdr/types/wchar_t.h"
+#include "hdr/types/wctype_t.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/string_view.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h"
@@ -551,7 +554,6 @@ LIBC_INLINE constexpr bool isprint(wchar_t wch) {
return lookup_properties(wch) & PropertyFlag::PRINT;
#endif
}
-
LIBC_INLINE constexpr bool isxdigit(wchar_t wch) {
// Hexadecimal digits are the same in C.UTF8 as in ASCII
return ascii::isxdigit(wch);
@@ -579,6 +581,85 @@ LIBC_INLINE constexpr bool ispunct(wchar_t wch) {
#endif
}
+struct wctype_mapping {
+ cpp::string_view name;
+ wctype_t desc;
+};
+
+LIBC_INLINE constexpr wctype_t WCTYPE_INVALID = 0;
+LIBC_INLINE constexpr wctype_t WCTYPE_ALNUM = 1;
+LIBC_INLINE constexpr wctype_t WCTYPE_ALPHA = 2;
+LIBC_INLINE constexpr wctype_t WCTYPE_BLANK = 3;
+LIBC_INLINE constexpr wctype_t WCTYPE_CNTRL = 4;
+LIBC_INLINE constexpr wctype_t WCTYPE_DIGIT = 5;
+LIBC_INLINE constexpr wctype_t WCTYPE_GRAPH = 6;
+LIBC_INLINE constexpr wctype_t WCTYPE_LOWER = 7;
+LIBC_INLINE constexpr wctype_t WCTYPE_PRINT = 8;
+LIBC_INLINE constexpr wctype_t WCTYPE_PUNCT = 9;
+LIBC_INLINE constexpr wctype_t WCTYPE_SPACE = 10;
+LIBC_INLINE constexpr wctype_t WCTYPE_UPPER = 11;
+LIBC_INLINE constexpr wctype_t WCTYPE_XDIGIT = 12;
+
+LIBC_INLINE constexpr cpp::array<wctype_mapping, 12> mappings = {{
+ {"alnum", WCTYPE_ALNUM},
+ {"alpha", WCTYPE_ALPHA},
+ {"blank", WCTYPE_BLANK},
+ {"cntrl", WCTYPE_CNTRL},
+ {"digit", WCTYPE_DIGIT},
+ {"graph", WCTYPE_GRAPH},
+ {"lower", WCTYPE_LOWER},
+ {"print", WCTYPE_PRINT},
+ {"punct", WCTYPE_PUNCT},
+ {"space", WCTYPE_SPACE},
+ {"upper", WCTYPE_UPPER},
+ {"xdigit", WCTYPE_XDIGIT},
+}};
+
+LIBC_INLINE constexpr wctype_t wctype(const char *property) {
+ if (!property)
+ return WCTYPE_INVALID;
+
+ cpp::string_view prop(property);
+
+ for (const auto &wc : mappings) {
+ if (wc.name == prop) {
+ return wc.desc;
+ }
+ }
+ return WCTYPE_INVALID;
+}
+
+LIBC_INLINE constexpr int iswctype(wchar_t c, wctype_t desc) {
+ switch (desc) {
+ case WCTYPE_ALNUM:
+ return isalnum(c);
+ case WCTYPE_ALPHA:
+ return isalpha(c);
+ case WCTYPE_BLANK:
+ return isblank(c);
+ case WCTYPE_CNTRL:
+ return iscntrl(c);
+ case WCTYPE_DIGIT:
+ return isdigit(c);
+ case WCTYPE_GRAPH:
+ return isgraph(c);
+ case WCTYPE_LOWER:
+ return islower(c);
+ case WCTYPE_PRINT:
+ return isprint(c);
+ case WCTYPE_PUNCT:
+ return ispunct(c);
+ case WCTYPE_SPACE:
+ return isspace(c);
+ case WCTYPE_UPPER:
+ return isupper(c);
+ case WCTYPE_XDIGIT:
+ return isxdigit(c);
+ default:
+ return 0;
+ }
+}
+
LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) {
#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
return ascii::tolower(wch);
diff --git a/libc/src/wctype/CMakeLists.txt b/libc/src/wctype/CMakeLists.txt
index 07bfed39980c2..57f9e7753a9f5 100644
--- a/libc/src/wctype/CMakeLists.txt
+++ b/libc/src/wctype/CMakeLists.txt
@@ -130,3 +130,24 @@ add_entrypoint_object(
libc.src.__support.wctype_utils
libc.hdr.types.wint_t
)
+
+add_entrypoint_object(
+ iswctype
+ SRCS
+ iswctype.cpp
+ HDRS
+ iswctype.h
+ DEPENDS
+ libc.src.__support.wctype_utils
+ libc.hdr.types.wint_t
+)
+
+add_entrypoint_object(
+ wctype
+ SRCS
+ wctype.cpp
+ HDRS
+ wctype.h
+ DEPENDS
+ libc.src.__support.wctype_utils
+)
diff --git a/libc/src/wctype/iswctype.cpp b/libc/src/wctype/iswctype.cpp
new file mode 100644
index 0000000000000..1604836225fee
--- /dev/null
+++ b/libc/src/wctype/iswctype.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of iswctype ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wctype/iswctype.h"
+#include "src/__support/common.h"
+#include "src/__support/wctype_utils.h"
+
+#include "hdr/types/wctype_t.h"
+#include "hdr/types/wint_t.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, iswctype, (wint_t c, wctype_t desc)) {
+ return internal::iswctype(static_cast<wchar_t>(c), desc);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wctype/iswctype.h b/libc/src/wctype/iswctype.h
new file mode 100644
index 0000000000000..10a0f3e969c8d
--- /dev/null
+++ b/libc/src/wctype/iswctype.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for iswctype ----------------------*- C++ -*-===//
+//
+// 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 LLVM_LIBC_SRC_WCTYPE_ISWCTYPE_H
+#define LLVM_LIBC_SRC_WCTYPE_ISWCTYPE_H
+
+#include "hdr/types/wctype_t.h"
+#include "hdr/types/wint_t.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int iswctype(wint_t c, wctype_t desc);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCTYPE_ISWCTYPE_H
diff --git a/libc/src/wctype/wctype.cpp b/libc/src/wctype/wctype.cpp
new file mode 100644
index 0000000000000..59c28dcf5a437
--- /dev/null
+++ b/libc/src/wctype/wctype.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of wctype ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wctype/wctype.h"
+#include "src/__support/common.h"
+#include "src/__support/wctype_utils.h"
+
+#include "hdr/types/wctype_t.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(wctype_t, wctype, (const char *property)) {
+ return internal::wctype(property);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wctype/wctype.h b/libc/src/wctype/wctype.h
new file mode 100644
index 0000000000000..98300e49f7e03
--- /dev/null
+++ b/libc/src/wctype/wctype.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for iswctype ----------------------*- C++ -*-===//
+//
+// 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 LLVM_LIBC_SRC_WCTYPE_WCTYPE_H
+#define LLVM_LIBC_SRC_WCTYPE_WCTYPE_H
+
+#include "hdr/types/wctype_t.h"
+#include "hdr/types/wint_t.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+wctype_t wctype(const char *property);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCTYPE_WCTYPE_H
diff --git a/libc/test/src/__support/wctype_utils_test.cpp b/libc/test/src/__support/wctype_utils_test.cpp
index 9bc7e818cdbc6..88cd56cc0cae5 100644
--- a/libc/test/src/__support/wctype_utils_test.cpp
+++ b/libc/test/src/__support/wctype_utils_test.cpp
@@ -1,7 +1,15 @@
+//===-- Unittests for wctype utils ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/types/wctype_t.h"
#include "src/__support/macros/config.h"
#include "src/__support/wctype/wctype_classification_utils.h"
#include "test/UnitTest/Test.h"
-
namespace {
namespace ascii_mode {
@@ -9,7 +17,12 @@ namespace ascii_mode {
#define LIBC_CONF_WCTYPE_MODE LIBC_WCTYPE_MODE_ASCII
#undef LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp = ::LIBC_NAMESPACE::cpp;
+} // namespace LIBC_NAMESPACE_DECL
#include "src/__support/wctype_utils.h"
+
} // namespace ascii_mode
namespace utf8_mode {
@@ -19,9 +32,11 @@ namespace utf8_mode {
namespace LIBC_NAMESPACE_DECL {
using ::LIBC_NAMESPACE::lookup_properties;
using ::LIBC_NAMESPACE::PropertyFlag;
+namespace cpp = ::LIBC_NAMESPACE::cpp;
} // namespace LIBC_NAMESPACE_DECL
#undef LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
+
#include "src/__support/wctype_utils.h"
} // namespace utf8_mode
diff --git a/libc/test/src/wctype/CMakeLists.txt b/libc/test/src/wctype/CMakeLists.txt
index a5f85856dfb38..f7cdcc77482e4 100644
--- a/libc/test/src/wctype/CMakeLists.txt
+++ b/libc/test/src/wctype/CMakeLists.txt
@@ -121,3 +121,24 @@ add_libc_test(
DEPENDS
libc.src.wctype.iswprint
)
+
+add_libc_test(
+ iswctype_test
+ SUITE
+ libc_wctype_unittests
+ SRCS
+ iswctype_test.cpp
+ DEPENDS
+ libc.src.wctype.iswctype
+ libc.src.wctype.wctype
+)
+
+add_libc_test(
+ wctype_test
+ SUITE
+ libc_wctype_unittests
+ SRCS
+ wctype_test.cpp
+ DEPENDS
+ libc.src.wctype.wctype
+)
diff --git a/libc/test/src/wctype/iswctype_test.cpp b/libc/test/src/wctype/iswctype_test.cpp
new file mode 100644
index 0000000000000..4aed4d047b619
--- /dev/null
+++ b/libc/test/src/wctype/iswctype_test.cpp
@@ -0,0 +1,181 @@
+//===-- Unittests for iswctype --------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wctype/iswctype.h"
+#include "src/wctype/wctype.h"
+
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibciswctype, Alnum) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("alnum");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'Z', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'5', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'!', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Alpha) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("alpha");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'Z', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'_', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Blank) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("blank");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\t', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\r', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Cntrl) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("cntrl");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\0', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\t', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\r', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(0x1f, desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(0x7f, desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Digit) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("digit");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'0', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'9', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'/', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L':', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Graph) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("graph");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'!', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'~', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\t', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Lower) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("lower");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'z', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'_', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Print) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("print");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'0', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'~', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\t', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'\0', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Punct) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("punct");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'!', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'?', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'_', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'[', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Space) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("space");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L' ', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\t', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\n', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\v', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\f', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'\r', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'!', desc), 0);
+}
+
+TEST(LlvmLibciswctype, Upper) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("upper");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'Z', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'1', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'_', desc), 0);
+}
+
+TEST(LlvmLibciswctype, XDigit) {
+ const wctype_t desc = LIBC_NAMESPACE::wctype("xdigit");
+ ASSERT_NE(desc, static_cast<wctype_t>(0));
+
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'0', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'9', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'a', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'f', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'A', desc), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswctype(L'F', desc), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'g', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'G', desc), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'?', desc), 0);
+}
+
+TEST(LlvmLibciswctype, InvalidDescriptor) {
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'a', 0), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L'0', 0), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswctype(L' ', 0), 0);
+}
diff --git a/libc/test/src/wctype/wctype_test.cpp b/libc/test/src/wctype/wctype_test.cpp
new file mode 100644
index 0000000000000..e4aa1bb6694d6
--- /dev/null
+++ b/libc/test/src/wctype/wctype_test.cpp
@@ -0,0 +1,35 @@
+//===-- Unittests for wctype ----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wctype/wctype.h"
+
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcwctype, ValidPropertiesReturnNonZero) {
+ EXPECT_NE(LIBC_NAMESPACE::wctype("alnum"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("alpha"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("blank"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("cntrl"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("digit"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("graph"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("lower"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("print"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("punct"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("space"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("upper"), static_cast<wctype_t>(0));
+ EXPECT_NE(LIBC_NAMESPACE::wctype("xdigit"), static_cast<wctype_t>(0));
+}
+
+TEST(LlvmLibcwctype, InvalidPropertiesReturnZero) {
+ EXPECT_EQ(LIBC_NAMESPACE::wctype(nullptr), static_cast<wctype_t>(0));
+ EXPECT_EQ(LIBC_NAMESPACE::wctype(""), static_cast<wctype_t>(0));
+ EXPECT_EQ(LIBC_NAMESPACE::wctype("foo"), static_cast<wctype_t>(0));
+ EXPECT_EQ(LIBC_NAMESPACE::wctype("Alpha"), static_cast<wctype_t>(0));
+ EXPECT_EQ(LIBC_NAMESPACE::wctype("xdigit "), static_cast<wctype_t>(0));
+ EXPECT_EQ(LIBC_NAMESPACE::wctype(" alnum"), static_cast<wctype_t>(0));
+}
More information about the libc-commits
mailing list