-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libc] Implemented wcsrchr #142436
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 wcsrchr #142436
Conversation
@llvm/pr-subscribers-libc Author: Uzair Nawaz (uzairnawaz) ChangesImplemented wcsrchr and added tests Full diff: https://github.com/llvm/llvm-project/pull/142436.diff 7 Files Affected:
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 545b9227349fe..e6cbfe0257a3e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -367,6 +367,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wchar.wmemset
libc.src.wchar.wcschr
libc.src.wchar.wcspbrk
+ libc.src.wchar.wcsrchr
libc.src.wchar.wcsspn
libc.src.wchar.wmemcmp
libc.src.wchar.wmemcpy
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index bfd9a10342019..39732feb62fcd 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -49,6 +49,13 @@ functions:
arguments:
- type: const wchar_t *
- type: const wchar_t *
+ - name: wcsrchr
+ standards:
+ - stdc
+ return_type: const wchar_t *
+ arguments:
+ - type: const wchar_t *
+ - type: wchar_t
- name: wcsspn
standards:
- stdc
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 9db121762348b..dd597550e06d8 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -68,6 +68,17 @@ add_entrypoint_object(
libc.src.__support.wctype_utils
)
+add_entrypoint_object(
+ wcsrchr
+ SRCS
+ wcsrchr.cpp
+ HDRS
+ wcsrchr.h
+ DEPENDS
+ libc.hdr.wchar_macros
+ libc.src.__support.wctype_utils
+)
+
add_entrypoint_object(
wcsspn
SRCS
diff --git a/libc/src/wchar/wcsrchr.cpp b/libc/src/wchar/wcsrchr.cpp
new file mode 100644
index 0000000000000..bb4e373bb1ce1
--- /dev/null
+++ b/libc/src/wchar/wcsrchr.cpp
@@ -0,0 +1,31 @@
+//===-- Implementation of wcsrchr -----------------------------------------===//
+//
+// 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/wcsrchr.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"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(const wchar_t *, wcsrchr, (const wchar_t *s, wchar_t c)) {
+ LIBC_CRASH_ON_NULLPTR(s);
+
+ const wchar_t *last_occurrence = nullptr;
+ while (true) {
+ if (*s == c)
+ last_occurrence = s;
+ if (*s == L'\0')
+ return last_occurrence;
+ ++s;
+ }
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsrchr.h b/libc/src/wchar/wcsrchr.h
new file mode 100644
index 0000000000000..5e9d8c3c2db92
--- /dev/null
+++ b/libc/src/wchar/wcsrchr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for wcsrchr ---------------------------------===//
+//
+// 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_WCSRCHR_H
+#define LLVM_LIBC_SRC_WCHAR_WCSRCHR_H
+
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+const wchar_t *wcsrchr(const wchar_t *s, wchar_t c);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSRCHR_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 9bc230e0bddf3..6a212a620f853 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -65,6 +65,16 @@ add_libc_test(
libc.src.wchar.wcspbrk
)
+add_libc_test(
+ wcsrchr_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcsrchr_test.cpp
+ DEPENDS
+ libc.src.wchar.wcsrchr
+)
+
add_libc_test(
wcsspn_test
SUITE
diff --git a/libc/test/src/wchar/wcsrchr_test.cpp b/libc/test/src/wchar/wcsrchr_test.cpp
new file mode 100644
index 0000000000000..707dfb6756ee9
--- /dev/null
+++ b/libc/test/src/wchar/wcsrchr_test.cpp
@@ -0,0 +1,68 @@
+//===-- Unittests for wcsrchr ---------------------------------------------===//
+//
+// 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/wchar_t.h"
+#include "src/wchar/wcsrchr.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWCSRChrTest, FindsFirstCharacter) {
+ // Should return pointer to original string since 'a' is the first character.
+ const wchar_t *src = L"abcde";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'a'), src);
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsMiddleCharacter) {
+ // Should return pointer to 'c'.
+ const wchar_t *src = L"abcde";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'c'), (src + 2));
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsLastCharacterThatIsNotNullTerminator) {
+ // Should return pointer to 'e'.
+ const wchar_t *src = L"abcde";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'e'), (src + 4));
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsNullTerminator) {
+ // Should return pointer to null terminator.
+ const wchar_t *src = L"abcde";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'\0'), (src + 5));
+}
+
+TEST(LlvmLibcWCSRChrTest, CharacterNotWithinStringShouldReturnNullptr) {
+ // Since 'z' is not within the string, should return nullptr.
+ const wchar_t *src = L"abcde";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'z'), nullptr);
+}
+
+TEST(LlvmLibcWCSRChrTest, ShouldFindLastOfDuplicates) {
+ // Should return pointer to the last '1'.
+ const wchar_t *src = L"abc1def1ghi";
+ ASSERT_EQ((int)(LIBC_NAMESPACE::wcsrchr(src, L'1') - src), 7);
+
+ // Should return pointer to the last 'X'
+ const wchar_t *dups = L"XXXXX";
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(dups, L'X'), dups + 4);
+}
+
+TEST(LlvmLibcWCSRChrTest, EmptyStringShouldOnlyMatchNullTerminator) {
+ // Null terminator should match
+ const wchar_t *src = L"";
+ ASSERT_EQ(src, LIBC_NAMESPACE::wcsrchr(src, L'\0'));
+ // All other characters should not match
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'Z'), nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'3'), nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'*'), nullptr);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+TEST(LlvmLibcWCSRChrTest, NullptrCrash) {
+ // Passing in a nullptr should crash the program.
+ EXPECT_DEATH([] { LIBC_NAMESPACE::wcsrchr(nullptr, L'a'); }, WITH_SIGNAL(-1));
+}
+#endif // LIBC_HAS_ADDRESS_SANITIZER
|
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.
just a build fix, otherwise LGTM
libc/src/wchar/CMakeLists.txt
Outdated
wcsrchr.h | ||
DEPENDS | ||
libc.hdr.wchar_macros | ||
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.
don't need wctype_utils
please add "fixes #124347" to the description |
fixes llvm#124347 Implemented wcsrchr and added tests
fixes #124347
Implemented wcsrchr and added tests