-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libc] Implemented wcsncmp #142429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Implemented wcsncmp #142429
Conversation
@llvm/pr-subscribers-libc Author: Uzair Nawaz (uzairnawaz) ChangesImplemented wcsncmp and added tests Full diff: https://github.com/llvm/llvm-project/pull/142429.diff 7 Files Affected:
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 545b9227349fe..d78fd646d9f5d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -366,6 +366,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wchar.wctob
libc.src.wchar.wmemset
libc.src.wchar.wcschr
+ libc.src.wchar.wcsncmp
libc.src.wchar.wcspbrk
libc.src.wchar.wcsspn
libc.src.wchar.wmemcmp
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index bfd9a10342019..f1a92268b3f72 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -42,6 +42,14 @@ functions:
arguments:
- type: const wchar_t *
- type: wchar_t
+ - name: wcsncmp
+ standards:
+ - stdc
+ return_type: int
+ arguments:
+ - type: const wchar_t *
+ - type: const wchar_t *
+ - type: size_t
- name: wcspbrk
standards:
- stdc
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 9db121762348b..86065791baf98 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -68,6 +68,18 @@ add_entrypoint_object(
libc.src.__support.wctype_utils
)
+add_entrypoint_object(
+ wcsncmp
+ SRCS
+ wcsncmp.cpp
+ HDRS
+ wcsncmp.h
+ DEPENDS
+ libc.hdr.wchar_macros
+ libc.hdr.types.size_t
+ libc.src.__support.wctype_utils
+)
+
add_entrypoint_object(
wcsspn
SRCS
diff --git a/libc/src/wchar/wcsncmp.cpp b/libc/src/wchar/wcsncmp.cpp
new file mode 100644
index 0000000000000..f2e052b3c9fe3
--- /dev/null
+++ b/libc/src/wchar/wcsncmp.cpp
@@ -0,0 +1,37 @@
+//===-- Implementation of wcsncmp -----------------------------------------===//
+//
+// 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/wchar/wcsncmp.h"
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/null_check.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, wcsncmp,
+ (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;
+
+ auto comp = [](wchar_t l, wchar_t r) -> int { return l - r; };
+
+ for (; n > 1; --n, ++left, ++right) {
+ wchar_t lc = *left;
+ if (!comp(lc, '\0') || comp(lc, *right))
+ break;
+ }
+ return comp(*reinterpret_cast<const wchar_t *>(left),
+ *reinterpret_cast<const wchar_t *>(right));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsncmp.h b/libc/src/wchar/wcsncmp.h
new file mode 100644
index 0000000000000..0b4187e730e28
--- /dev/null
+++ b/libc/src/wchar/wcsncmp.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcsncmp ---------------------------------===//
+//
+// 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_WCHAR_WCSNCMP_H
+#define LLVM_LIBC_SRC_WCHAR_WCSNCMP_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int wcsncmp(const wchar_t *left, const wchar_t *right, size_t n);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSNCMP_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 9bc230e0bddf3..41fed323e019e 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -55,6 +55,16 @@ add_libc_test(
libc.src.wchar.wcschr
)
+add_libc_test(
+ wcsncmp_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcsncmp_test.cpp
+ DEPENDS
+ libc.src.wchar.wcsncmp
+)
+
add_libc_test(
wcspbrk_test
SUITE
diff --git a/libc/test/src/wchar/wcsncmp_test.cpp b/libc/test/src/wchar/wcsncmp_test.cpp
new file mode 100644
index 0000000000000..28bbb52648226
--- /dev/null
+++ b/libc/test/src/wchar/wcsncmp_test.cpp
@@ -0,0 +1,169 @@
+//===-- Unittests for wcsncmp ---------------------------------------------===//
+//
+// 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/wchar/wcsncmp.h"
+#include "test/UnitTest/Test.h"
+
+// This group is just copies of the wcscmp tests, since all the same cases still
+// need to be tested.
+
+TEST(LlvmLibcWcsncmpTest, EmptyStringsShouldReturnZeroWithSufficientLength) {
+ const wchar_t *s1 = L"";
+ const wchar_t *s2 = L"";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 1);
+ ASSERT_EQ(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 1);
+ ASSERT_EQ(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest,
+ EmptyStringShouldNotEqualNonEmptyStringWithSufficientLength) {
+ const wchar_t *empty = L"";
+ const wchar_t *s2 = L"abc";
+ int result = LIBC_NAMESPACE::wcsncmp(empty, s2, 3);
+ ASSERT_LT(result, 0);
+
+ // Similar case if empty string is second argument.
+ const wchar_t *s3 = L"123";
+ result = LIBC_NAMESPACE::wcsncmp(s3, empty, 3);
+ ASSERT_GT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, EqualStringsShouldReturnZeroWithSufficientLength) {
+ const wchar_t *s1 = L"abc";
+ const wchar_t *s2 = L"abc";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 3);
+ ASSERT_EQ(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 3);
+ ASSERT_EQ(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest,
+ ShouldReturnResultOfFirstDifferenceWithSufficientLength) {
+ const wchar_t *s1 = L"___B42__";
+ const wchar_t *s2 = L"___C55__";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 8);
+ ASSERT_LT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 8);
+ ASSERT_GT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest,
+ CapitalizedLetterShouldNotBeEqualWithSufficientLength) {
+ const wchar_t *s1 = L"abcd";
+ const wchar_t *s2 = L"abCd";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 4);
+ ASSERT_GT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 4);
+ ASSERT_LT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest,
+ UnequalLengthStringsShouldNotReturnZeroWithSufficientLength) {
+ const wchar_t *s1 = L"abc";
+ const wchar_t *s2 = L"abcd";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 4);
+ ASSERT_LT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 4);
+ ASSERT_GT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, StringArgumentSwapChangesSignWithSufficientLength) {
+ const wchar_t *a = L"a";
+ const wchar_t *b = L"b";
+ int result = LIBC_NAMESPACE::wcsncmp(b, a, 1);
+ ASSERT_GT(result, 0);
+
+ result = LIBC_NAMESPACE::wcsncmp(a, b, 1);
+ ASSERT_LT(result, 0);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+TEST(LlvmLibcWcsncmpTest, NullptrCrash) {
+ // Passing in a nullptr should crash the program.
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcsncmp(L"aaaaaaaaaaaaaa", nullptr, 3); },
+ WITH_SIGNAL(-1));
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcsncmp(nullptr, L"aaaaaaaaaaaaaa", 3); },
+ WITH_SIGNAL(-1));
+}
+#endif // LIBC_HAS_ADDRESS_SANITIZER
+
+// This group is actually testing wcsncmp functionality
+
+TEST(LlvmLibcWcsncmpTest, NonEqualStringsEqualWithLengthZero) {
+ const wchar_t *s1 = L"abc";
+ const wchar_t *s2 = L"def";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 0);
+ ASSERT_EQ(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 0);
+ ASSERT_EQ(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, NonEqualStringsNotEqualWithLengthOne) {
+ const wchar_t *s1 = L"abc";
+ const wchar_t *s2 = L"def";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 1);
+ ASSERT_LT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 1);
+ ASSERT_GT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, NonEqualStringsEqualWithShorterLength) {
+ const wchar_t *s1 = L"___B42__";
+ const wchar_t *s2 = L"___C55__";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 3);
+ ASSERT_EQ(result, 0);
+
+ // This should return 'B' - 'C' = -1.
+ result = LIBC_NAMESPACE::wcsncmp(s1, s2, 4);
+ ASSERT_LT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 3);
+ ASSERT_EQ(result, 0);
+
+ // This should return 'C' - 'B' = 1.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 4);
+ ASSERT_GT(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, StringComparisonEndsOnNullByteEvenWithLongerLength) {
+ const wchar_t *s1 = L"abc\0def";
+ const wchar_t *s2 = L"abc\0abc";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 7);
+ ASSERT_EQ(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 7);
+ ASSERT_EQ(result, 0);
+}
+
+TEST(LlvmLibcWcsncmpTest, Case) {
+ const wchar_t *s1 = L"aB";
+ const wchar_t *s2 = L"ab";
+ int result = LIBC_NAMESPACE::wcsncmp(s1, s2, 2);
+ ASSERT_LT(result, 0);
+
+ // Verify operands reversed.
+ result = LIBC_NAMESPACE::wcsncmp(s2, s1, 2);
+ ASSERT_GT(result, 0);
+}
|
libc/src/wchar/CMakeLists.txt
Outdated
DEPENDS | ||
libc.hdr.wchar_macros | ||
libc.hdr.types.size_t | ||
libc.src.__support.wctype_utils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix: wctype_utils isn't used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Implemented wcsncmp and added tests
Implemented wcsncmp and added tests