[libc-commits] [libc] e47d10f - [libc] Add wcscasecmp and wcsncasecmp implementations. (#222154)
via libc-commits
libc-commits at lists.llvm.org
Thu Sep 10 11:06:01 PDT 2026
Author: Alex Strelnikov
Date: 2026-09-10T14:05:57-04:00
New Revision: e47d10f55719cb5bc7dac81d49277938813b5ee4
URL: https://github.com/llvm/llvm-project/commit/e47d10f55719cb5bc7dac81d49277938813b5ee4
DIFF: https://github.com/llvm/llvm-project/commit/e47d10f55719cb5bc7dac81d49277938813b5ee4.diff
LOG: [libc] Add wcscasecmp and wcsncasecmp implementations. (#222154)
Add a helper to wctype_utils.h for three-way comparison of individual
`wchar_t`s. As is the case in existing code, `wchar_t` is presumed to be
UTF-32.
Assisted-by: Automated tooling, human reviewed.
Added:
libc/src/wchar/wcscasecmp.cpp
libc/src/wchar/wcscasecmp.h
libc/src/wchar/wcsncasecmp.cpp
libc/src/wchar/wcsncasecmp.h
libc/test/src/wchar/wcscasecmp_test.cpp
libc/test/src/wchar/wcsncasecmp_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/include/wchar.yaml
libc/src/__support/wctype_utils.h
libc/src/wchar/CMakeLists.txt
libc/test/src/__support/wctype_utils_test.cpp
libc/test/src/wchar/CMakeLists.txt
libc/utils/docgen/wchar.yaml
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index f3a5ea588312f..77610d6d06057 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -464,6 +464,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.write
# wchar.h entrypoints
+ libc.src.wchar.wcscasecmp
+ libc.src.wchar.wcsncasecmp
libc.src.wchar.wcslen
libc.src.wchar.wctob
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8a25173e43999..65b820e551be6 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -504,6 +504,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# wchar.h entrypoints
libc.src.wchar.btowc
+ libc.src.wchar.wcscasecmp
+ libc.src.wchar.wcsncasecmp
libc.src.wchar.wcslen
libc.src.wchar.wcsnlen
libc.src.wchar.wctob
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index 1017eb827cf45..2b321f6502ff1 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -117,6 +117,21 @@ functions:
arguments:
- type: const wchar_t *
- type: const wchar_t *
+ - name: wcscasecmp
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: const wchar_t *
+ - type: const wchar_t *
+ - name: wcsncasecmp
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: const wchar_t *
+ - type: const wchar_t *
+ - type: size_t
- name: wcscoll
standards:
- stdc
diff --git a/libc/src/__support/wctype_utils.h b/libc/src/__support/wctype_utils.h
index 4d0ecd2c1c0dc..633c9139f7369 100644
--- a/libc/src/__support/wctype_utils.h
+++ b/libc/src/__support/wctype_utils.h
@@ -10,6 +10,7 @@
#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
#include "hdr/types/wchar_t.h"
+#include "src/__support/CPP/bit.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h"
@@ -796,6 +797,17 @@ is_char_or_wchar(wchar_t ch, [[maybe_unused]] char, wchar_t wc_value) {
return (ch == wc_value);
}
+// Returns a three-way comparison between two wide character code points.
+LIBC_INLINE int threeway_cmp_single(wchar_t left, wchar_t right) {
+ // Valid UTF-32 code points are in [0, 0x10FFFF]. If invalid code points were
+ // treated as UB, the comparison below could done with 32-bit arithmetic.
+ if (left == right)
+ return 0;
+ if (left < right)
+ return -1;
+ return 1;
+}
+
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 722619d652500..938b7ad2e4c73 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -373,6 +373,35 @@ add_entrypoint_object(
libc.hdr.types.size_t
)
+add_entrypoint_object(
+ wcscasecmp
+ SRCS
+ wcscasecmp.cpp
+ HDRS
+ wcscasecmp.h
+ DEPENDS
+ libc.hdr.types.wchar_t
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.null_check
+ libc.src.__support.wctype_utils
+)
+
+add_entrypoint_object(
+ wcsncasecmp
+ SRCS
+ wcsncasecmp.cpp
+ HDRS
+ wcsncasecmp.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.types.wchar_t
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.null_check
+ libc.src.__support.wctype_utils
+)
+
add_entrypoint_object(
wcsspn
SRCS
diff --git a/libc/src/wchar/wcscasecmp.cpp b/libc/src/wchar/wcscasecmp.cpp
new file mode 100644
index 0000000000000..29c938c549a4a
--- /dev/null
+++ b/libc/src/wchar/wcscasecmp.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the wcscasecmp function implementation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcscasecmp.h"
+
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/__support/wctype_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, wcscasecmp,
+ (const wchar_t *left, const wchar_t *right)) {
+ LIBC_CRASH_ON_NULLPTR(left);
+ LIBC_CRASH_ON_NULLPTR(right);
+
+ for (;; ++left, ++right) {
+ wchar_t lc = *left;
+ if (lc == L'\0' || internal::tolower(lc) != internal::tolower(*right))
+ break;
+ }
+ return internal::threeway_cmp_single(internal::tolower(*left),
+ internal::tolower(*right));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcscasecmp.h b/libc/src/wchar/wcscasecmp.h
new file mode 100644
index 0000000000000..51a6f1b415c56
--- /dev/null
+++ b/libc/src/wchar/wcscasecmp.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the wcscasecmp function declaration.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSCASECMP_H
+#define LLVM_LIBC_SRC_WCHAR_WCSCASECMP_H
+
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int wcscasecmp(const wchar_t *left, const wchar_t *right);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSCASECMP_H
diff --git a/libc/src/wchar/wcsncasecmp.cpp b/libc/src/wchar/wcsncasecmp.cpp
new file mode 100644
index 0000000000000..2fc29ff972896
--- /dev/null
+++ b/libc/src/wchar/wcsncasecmp.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the wcsncasecmp function implementation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcsncasecmp.h"
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/__support/wctype_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, wcsncasecmp,
+ (const wchar_t *left, const wchar_t *right, size_t n)) {
+ LIBC_CRASH_ON_NULLPTR(left);
+ LIBC_CRASH_ON_NULLPTR(right);
+
+ if (n == 0)
+ return 0;
+
+ for (; n > 1; --n, ++left, ++right) {
+ wchar_t lc = *left;
+ if (lc == L'\0' || internal::tolower(lc) != internal::tolower(*right))
+ break;
+ }
+ return internal::threeway_cmp_single(internal::tolower(*left),
+ internal::tolower(*right));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsncasecmp.h b/libc/src/wchar/wcsncasecmp.h
new file mode 100644
index 0000000000000..754ac54ec2ae2
--- /dev/null
+++ b/libc/src/wchar/wcsncasecmp.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the wcsncasecmp function declaration.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSNCASECMP_H
+#define LLVM_LIBC_SRC_WCHAR_WCSNCASECMP_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int wcsncasecmp(const wchar_t *left, const wchar_t *right, size_t n);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSNCASECMP_H
diff --git a/libc/test/src/__support/wctype_utils_test.cpp b/libc/test/src/__support/wctype_utils_test.cpp
index b2140ab72a3be..ae4770a7765a2 100644
--- a/libc/test/src/__support/wctype_utils_test.cpp
+++ b/libc/test/src/__support/wctype_utils_test.cpp
@@ -553,4 +553,22 @@ TEST(LlvmLibcWctypeUtilsTest, IsCntrlUtf8) {
}
}
+TEST(LlvmLibcWctypeUtilsTest, ThreewayCmpSingle) {
+ using utf8_mode::LIBC_NAMESPACE::internal::threeway_cmp_single;
+
+ EXPECT_EQ(threeway_cmp_single(L'A', L'A'), 0);
+
+ EXPECT_LT(threeway_cmp_single(wchar_t{67}, wchar_t{120}), 0);
+ EXPECT_GT(threeway_cmp_single(wchar_t{120}, wchar_t{67}), 0);
+
+ EXPECT_LT(threeway_cmp_single(wchar_t{1}, WCHAR_MAX), 0);
+ EXPECT_GT(threeway_cmp_single(WCHAR_MAX, wchar_t{1}), 0);
+
+ EXPECT_LT(threeway_cmp_single(WCHAR_MIN, wchar_t{1}), 0);
+ EXPECT_GT(threeway_cmp_single(wchar_t{1}, WCHAR_MIN), 0);
+
+ EXPECT_LT(threeway_cmp_single(WCHAR_MIN, WCHAR_MAX), 0);
+ EXPECT_GT(threeway_cmp_single(WCHAR_MAX, WCHAR_MIN), 0);
+}
+
} // namespace
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 1183d5c44d685..d511a1f0f4541 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -221,6 +221,28 @@ add_libc_test(
libc.src.wchar.wcsncmp
)
+add_libc_test(
+ wcscasecmp_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcscasecmp_test.cpp
+ DEPENDS
+ libc.src.__support.wctype_utils
+ libc.src.wchar.wcscasecmp
+)
+
+add_libc_test(
+ wcsncasecmp_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcsncasecmp_test.cpp
+ DEPENDS
+ libc.src.__support.wctype_utils
+ libc.src.wchar.wcsncasecmp
+)
+
add_libc_test(
wcscmp_test
SUITE
diff --git a/libc/test/src/wchar/wcscasecmp_test.cpp b/libc/test/src/wchar/wcscasecmp_test.cpp
new file mode 100644
index 0000000000000..0e9af12fc1174
--- /dev/null
+++ b/libc/test/src/wchar/wcscasecmp_test.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains unit tests for wcscasecmp.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/wctype_utils.h"
+#include "src/wchar/wcscasecmp.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWcscasecmpTest, EmptyStrings) {
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"", L""), 0);
+}
+
+TEST(LlvmLibcWcscasecmpTest, EmptyVsNonEmptyStrings) {
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"", L"a"), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"a", L""), 0);
+}
+
+TEST(LlvmLibcWcscasecmpTest, Substrings) {
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"aβc", L"aβ"), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"aβc", L"a"), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"aβc", L""), 0);
+
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"aβ", L"aβc"), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"a", L"aβc"), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"", L"aβc"), 0);
+}
+
+TEST(LlvmLibcWcscasecmpTest, MatchingStringsIgnoreCase) {
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abc", L"abc"), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"Abc", L"abc"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"aBc", L"abc"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abC", L"abc"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"ABC", L"abc"), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abc", L"Abc"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abc", L"aBc"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abc", L"abC"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"abc", L"ABC"), 0);
+
+#if LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"Βγδ", L"βγδ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βΓδ", L"βγδ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βγΔ", L"βγδ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"ΒΓΔ", L"βγδ"), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βγδ", L"Βγδ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βγδ", L"βΓδ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βγδ", L"βγΔ"), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcscasecmp(L"βγδ", L"ΒΓΔ"), 0);
+#endif // LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8
+}
+
+TEST(LlvmLibcWcscasecmpTest, NonMatchingStrings) {
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"Δbc", L"abc"), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"aΔc", L"abc"), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcscasecmp(L"abΔ", L"abc"), 0);
+
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"abc", L"Δbc"), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"abc", L"aΔc"), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcscasecmp(L"abc", L"abΔ"), 0);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS)
+
+TEST(LlvmLibcWcscasecmpTest, CrashOnNullPtr) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcscasecmp(L"hello", nullptr); },
+ WITH_SIGNAL(-1));
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcscasecmp(nullptr, L"hello"); },
+ WITH_SIGNAL(-1));
+}
+
+#endif // LIBC_ADD_NULL_CHECKS
diff --git a/libc/test/src/wchar/wcsncasecmp_test.cpp b/libc/test/src/wchar/wcsncasecmp_test.cpp
new file mode 100644
index 0000000000000..dec2ec8255638
--- /dev/null
+++ b/libc/test/src/wchar/wcsncasecmp_test.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains unit tests for wcsncasecmp.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/limits_macros.h"
+#include "src/__support/wctype_utils.h"
+#include "src/wchar/wcsncasecmp.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWcsncasecmpTest, EmptyStrings) {
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"", L"", 0), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"", L"", INT_MAX), 0);
+}
+
+TEST(LlvmLibcWcsncasecmpTest, EmptyVsNonEmptyStringsUnlimited) {
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"", L"a", INT_MAX), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"a", L"", INT_MAX), 0);
+}
+
+TEST(LlvmLibcWcsncasecmpTest, SubstringsUnlimited) {
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"aβc", L"aβ", INT_MAX), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"aβc", L"a", INT_MAX), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"aβc", L"", INT_MAX), 0);
+
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"aβ", L"aβc", INT_MAX), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"a", L"aβc", INT_MAX), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"", L"aβc", INT_MAX), 0);
+}
+
+TEST(LlvmLibcWcsncasecmpTest, MatchingStringsIgnoreCaseUnlimited) {
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"abc", INT_MAX), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"Abc", L"abc", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"aBc", L"abc", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abC", L"abc", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"ABC", L"abc", INT_MAX), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"Abc", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"aBc", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"abC", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"ABC", INT_MAX), 0);
+
+#if LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"Βγδ", L"βγδ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βΓδ", L"βγδ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγΔ", L"βγδ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"ΒΓΔ", L"βγδ", INT_MAX), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"Βγδ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"βΓδ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"βγΔ", INT_MAX), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"ΒΓΔ", INT_MAX), 0);
+#endif // LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8
+}
+
+TEST(LlvmLibcWcsncasecmpTest, NonMatchingStringsUnlimited) {
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"Δbc", L"abc", INT_MAX), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"aΔc", L"abc", INT_MAX), 0);
+ EXPECT_GT(LIBC_NAMESPACE::wcsncasecmp(L"abΔ", L"abc", INT_MAX), 0);
+
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"Δbc", INT_MAX), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"aΔc", INT_MAX), 0);
+ EXPECT_LT(LIBC_NAMESPACE::wcsncasecmp(L"abc", L"abΔ", INT_MAX), 0);
+}
+
+TEST(LlvmLibcWcsncasecmpTest, CompareAtMostStartingMatch) {
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"", 0), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"", L"def", 0), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"def", 0), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"βde", 1), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::wcsncasecmp(L"βγδ", L"βγd", 2), 0);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS)
+
+TEST(LlvmLibcWcsncasecmpTest, CrashOnNullPtr) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcsncasecmp(L"hello", nullptr, 1); },
+ WITH_SIGNAL(-1));
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcsncasecmp(nullptr, L"hello", 1); },
+ WITH_SIGNAL(-1));
+}
+
+#endif // LIBC_ADD_NULL_CHECKS
diff --git a/libc/utils/docgen/wchar.yaml b/libc/utils/docgen/wchar.yaml
index dcc8963efdd35..85bfbe31085d1 100644
--- a/libc/utils/docgen/wchar.yaml
+++ b/libc/utils/docgen/wchar.yaml
@@ -57,6 +57,10 @@ functions:
c-definition: 7.31.4.6.2
wcscmp:
c-definition: 7.31.4.5.2
+ wcscasecmp:
+ in-latest-posix: ''
+ wcsncasecmp:
+ in-latest-posix: ''
wcscoll:
c-definition: 7.31.4.5.3
wcscpy:
More information about the libc-commits
mailing list