diff options
author | sribee8 <sriya.pratipati@gmail.com> | 2025-06-27 09:51:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-27 16:51:37 +0000 |
commit | ac7e3910350aed59495883d4193275106047645f (patch) | |
tree | f9b889a74e92c4f42cb7ba7923faa280ba32cf37 | |
parent | af2bf2e544b5c2a8a3cc4fd2acab2cc83107af66 (diff) | |
download | llvm-ac7e3910350aed59495883d4193275106047645f.zip llvm-ac7e3910350aed59495883d4193275106047645f.tar.gz llvm-ac7e3910350aed59495883d4193275106047645f.tar.bz2 |
[libc] Implemented wcsnlen (#145610)
Implemented wcsnlen and tests for the function.
---------
Co-authored-by: Sriya Pratipati <sriyap@google.com>
-rw-r--r-- | libc/config/linux/x86_64/entrypoints.txt | 1 | ||||
-rw-r--r-- | libc/include/wchar.yaml | 7 | ||||
-rw-r--r-- | libc/src/wchar/CMakeLists.txt | 11 | ||||
-rw-r--r-- | libc/src/wchar/wcsnlen.cpp | 25 | ||||
-rw-r--r-- | libc/src/wchar/wcsnlen.h | 22 | ||||
-rw-r--r-- | libc/test/src/wchar/CMakeLists.txt | 12 | ||||
-rw-r--r-- | libc/test/src/wchar/wcsnlen_test.cpp | 54 |
7 files changed, 132 insertions, 0 deletions
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 6b3fc94..7a954a4 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 # wchar.h entrypoints libc.src.wchar.btowc libc.src.wchar.wcslen + libc.src.wchar.wcsnlen libc.src.wchar.wctob libc.src.wchar.wmemmove libc.src.wchar.wmemset diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index 3972968..9e862ff 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -17,6 +17,13 @@ functions: return_type: size_t arguments: - type: const wchar_t * + - name: wcsnlen + standards: + - stdc + return_type: size_t + arguments: + - type: const wchar_t * + - type: size_t - name: wctob standards: - stdc diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index 1666410..867aab6 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -11,6 +11,17 @@ add_entrypoint_object( ) add_entrypoint_object( + wcsnlen + SRCS + wcsnlen.cpp + HDRS + wcsnlen.h + DEPENDS + libc.hdr.types.size_t + libc.hdr.types.wchar_t +) + +add_entrypoint_object( wctob SRCS wctob.cpp diff --git a/libc/src/wchar/wcsnlen.cpp b/libc/src/wchar/wcsnlen.cpp new file mode 100644 index 0000000..4613006 --- /dev/null +++ b/libc/src/wchar/wcsnlen.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of wcsnlen -----------------------------------------===// +// +// 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/wcsnlen.h" + +#include "hdr/types/size_t.h" +#include "hdr/types/wchar_t.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(size_t, wcsnlen, (const wchar_t *src, size_t maxlen)) { + size_t i = 0; + for (; i < maxlen && src[i]; ++i) + ; + return i; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcsnlen.h b/libc/src/wchar/wcsnlen.h new file mode 100644 index 0000000..5a4c92d --- /dev/null +++ b/libc/src/wchar/wcsnlen.h @@ -0,0 +1,22 @@ +//===-- Implementation header for wcsnlen ---------------------------------===// +// +// 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_WCSNLEN_H +#define LLVM_LIBC_SRC_WCHAR_WCSNLEN_H + +#include "hdr/types/size_t.h" +#include "hdr/types/wchar_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +size_t wcsnlen(const wchar_t *src, size_t maxlen); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCSNLEN_H diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt index bf16fdd..02949c6 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -13,6 +13,18 @@ add_libc_test( ) add_libc_test( + wcsnlen_test + SUITE + libc_wchar_unittests + SRCS + wcsnlen_test.cpp + DEPENDS + libc.hdr.types.size_t + libc.hdr.types.wchar_t + libc.src.wchar.wcsnlen +) + +add_libc_test( btowc_test SUITE libc_wchar_unittests diff --git a/libc/test/src/wchar/wcsnlen_test.cpp b/libc/test/src/wchar/wcsnlen_test.cpp new file mode 100644 index 0000000..efb7198 --- /dev/null +++ b/libc/test/src/wchar/wcsnlen_test.cpp @@ -0,0 +1,54 @@ +//===-- Unittests for wcsnlen ---------------------------------------------===// +// +// 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/size_t.h" +#include "hdr/types/wchar_t.h" +#include "src/wchar/wcsnlen.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcWCSNLenTest, EmptyString) { + ASSERT_EQ(static_cast<size_t>(0), LIBC_NAMESPACE::wcsnlen(L"", 0)); + // If N is greater than string length, this should still return 0. + ASSERT_EQ(static_cast<size_t>(0), LIBC_NAMESPACE::wcsnlen(L"", 1)); +} + +TEST(LlvmLibcWCSNLenTest, OneCharacterString) { + const wchar_t *src = L"A"; + ASSERT_EQ(static_cast<size_t>(1), LIBC_NAMESPACE::wcsnlen(src, 1)); + // If N is 0, this should return 0. + ASSERT_EQ(static_cast<size_t>(0), LIBC_NAMESPACE::wcsnlen(src, 0)); + // If N is greater than string length, this should still return 1. + ASSERT_EQ(static_cast<size_t>(1), LIBC_NAMESPACE::wcsnlen(src, 3)); +} + +TEST(LlvmLibcWCSNLenTest, ManyCharacterString) { + const wchar_t *src = L"123456789"; + ASSERT_EQ(static_cast<size_t>(9), LIBC_NAMESPACE::wcsnlen(src, 9)); + // If N is 0, this should return 0. + ASSERT_EQ(static_cast<size_t>(0), LIBC_NAMESPACE::wcsnlen(src, 0)); + // If N is smaller than the string length, it should return N. + ASSERT_EQ(static_cast<size_t>(3), LIBC_NAMESPACE::wcsnlen(src, 3)); + // If N is greater than string length, this should still return 9. + ASSERT_EQ(static_cast<size_t>(9), LIBC_NAMESPACE::wcsnlen(src, 42)); +} + +TEST(LlvmLibcWCSNLenTest, IgnoreCharactersAfterNullTerminator) { + const wchar_t src[5] = {L'a', L'b', L'c', L'\0', L'd'}; + ASSERT_EQ(static_cast<size_t>(3), LIBC_NAMESPACE::wcsnlen(src, 3)); + // This should only read up to the null terminator. + ASSERT_EQ(static_cast<size_t>(3), LIBC_NAMESPACE::wcsnlen(src, 4)); + ASSERT_EQ(static_cast<size_t>(3), LIBC_NAMESPACE::wcsnlen(src, 5)); +} + +TEST(LlvmLibcWCSNLenTest, NoNullTerminator) { + const wchar_t src[4] = {L'a', L'b', L'c', L'd'}; + // Should return 4 + ASSERT_EQ(static_cast<size_t>(4), LIBC_NAMESPACE::wcsnlen(src, 4)); + // Should return 2 since N is smaller than string length + ASSERT_EQ(static_cast<size_t>(2), LIBC_NAMESPACE::wcsnlen(src, 2)); +} |