From bcfa14087391f7e414b9f34bef4f16c146e47020 Mon Sep 17 00:00:00 2001 From: Sriya Pratipati Date: Tue, 1 Jul 2025 16:48:22 +0000 Subject: [PATCH 1/2] [libc] wcslcpy implementation Implemented wcslcpy and tests. --- libc/config/linux/x86_64/entrypoints.txt | 1 + libc/include/wchar.yaml | 8 ++++ libc/src/wchar/CMakeLists.txt | 11 +++++ libc/src/wchar/wcslcpy.cpp | 32 +++++++++++++++ libc/src/wchar/wcslcpy.h | 23 +++++++++++ libc/test/src/wchar/CMakeLists.txt | 11 +++++ libc/test/src/wchar/wcslcpy_test.cpp | 51 ++++++++++++++++++++++++ 7 files changed, 137 insertions(+) create mode 100644 libc/src/wchar/wcslcpy.cpp create mode 100644 libc/src/wchar/wcslcpy.h create mode 100644 libc/test/src/wchar/wcslcpy_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 59c248871f83a..8035b964d1a5d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -385,6 +385,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcsstr libc.src.wchar.wcsncat libc.src.wchar.wcscpy + libc.src.wchar.wcslcpy libc.src.wchar.wmemchr libc.src.wchar.wcpcpy libc.src.wchar.wcpncpy diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index 02e1ba331b7cc..7d17d84d16c11 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -203,6 +203,14 @@ functions: arguments: - type: wchar_t *__restrict - type: const wchar_t *__restrict + - name: wcslcpy + standards: + - stdc + return_type: size_t + arguments: + - type: wchar_t *__restrict + - type: const wchar_t *__restrict + - type: size_t - name: wcstok standards: - stdc diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index f2f4b1d38f0f3..2dc14db998766 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -340,3 +340,14 @@ add_entrypoint_object( libc.hdr.wchar_macros libc.src.string.string_utils ) + +add_entrypoint_object( + wcslcpy + SRCS + wcslcpy.cpp + HDRS + wcslcpy.h + DEPENDS + libc.hdr.types.size_t + libc.hdr.wchar_macros +) diff --git a/libc/src/wchar/wcslcpy.cpp b/libc/src/wchar/wcslcpy.cpp new file mode 100644 index 0000000000000..7239334a07f77 --- /dev/null +++ b/libc/src/wchar/wcslcpy.cpp @@ -0,0 +1,32 @@ +//===-- Implementation of wcslcpy -----------------------------------------===// +// +// 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/wcslcpy.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/string/string_utils.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(size_t, wcslcpy, + (wchar_t *__restrict dst, const wchar_t *__restrict src, + size_t dstsize)) { + size_t len = internal::string_length(src); + if (dstsize == 0) + return len; + size_t i = 0; + for (; i < dstsize - 1 && src[i] != L'\0'; ++i) + dst[i] = src[i]; + dst[i] = L'\0'; + return len; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcslcpy.h b/libc/src/wchar/wcslcpy.h new file mode 100644 index 0000000000000..97b02f616605d --- /dev/null +++ b/libc/src/wchar/wcslcpy.h @@ -0,0 +1,23 @@ +//===-- Implementation header for wcslcpy ---------------------------------===// +// +// 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_WCSLCPY_H +#define LLVM_LIBC_SRC_WCHAR_WCSLCPY_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 wcslcpy(wchar_t *__restrict dst, const wchar_t *__restrict src, + size_t dstsize); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCSLCPY_H diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt index 657343d072158..aea520feee504 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -303,6 +303,17 @@ add_libc_test( libc.src.wchar.wcpcpy ) +add_libc_test( + wcslcpy_test + SUITE + libc_wchar_unittests + SRCS + wcslcpy_test.cpp + DEPENDS + libc.hdr.types.size_t + libc.src.wchar.wcslcpy +) + add_libc_test( wcpncpy_test SUITE diff --git a/libc/test/src/wchar/wcslcpy_test.cpp b/libc/test/src/wchar/wcslcpy_test.cpp new file mode 100644 index 0000000000000..9b14a62293f63 --- /dev/null +++ b/libc/test/src/wchar/wcslcpy_test.cpp @@ -0,0 +1,51 @@ +//===-- Unittests for wcslcpy ---------------------------------------------===// +// +// 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/wcslcpy.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcWCSLCpyTest, BiggerSource) { + const wchar_t *src = L"abcde"; + wchar_t dst[3]; + size_t res = LIBC_NAMESPACE::wcslcpy(dst, src, 3); + ASSERT_TRUE(dst[0] == L'a'); + ASSERT_TRUE(dst[1] == L'b'); + // Should append null terminator + ASSERT_TRUE(dst[2] == L'\0'); + // Should still return length of src + ASSERT_EQ(res, size_t(5)); +} + +TEST(LlvmLibcWCSLCpyTest, CopyZero) { + const wchar_t *src = L"abcde"; + wchar_t dst = L'f'; + // Copying zero should not change destination + size_t res = LIBC_NAMESPACE::wcslcpy(&dst, src, 0); + ASSERT_TRUE(dst == L'f'); + // Should still return length of src + ASSERT_EQ(res, size_t(5)); +} + +TEST(LlvmLibcWCSLCpyTest, SmallerSource) { + const wchar_t *src = L"abc"; + wchar_t dst[7]{L"111111"}; + size_t res = LIBC_NAMESPACE::wcslcpy(dst, src, 7); + ASSERT_TRUE(dst[0] == L'a'); + ASSERT_TRUE(dst[1] == L'b'); + ASSERT_TRUE(dst[2] == L'c'); + // Should append null terminator after copying source + ASSERT_TRUE(dst[3] == L'\0'); + // Should not change following characters + ASSERT_TRUE(dst[4] == L'1'); + ASSERT_TRUE(dst[5] == L'1'); + ASSERT_TRUE(dst[6] == L'\0'); + // Should still return length of src + ASSERT_EQ(res, size_t(3)); +} From ca511e789ed35525699ed61276ea2e664a1e242d Mon Sep 17 00:00:00 2001 From: Sriya Pratipati Date: Tue, 1 Jul 2025 16:54:28 +0000 Subject: [PATCH 2/2] added to bazel files --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 13 +++++++++++++ .../libc/test/src/wchar/BUILD.bazel | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 2484a2f1e2bd7..b073ba9a2e4e1 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -5827,6 +5827,19 @@ libc_function( ], ) +libc_function( + name = "wcslcpy", + srcs = ["src/wchar/wcslcpy.cpp"], + hdrs = ["src/wchar/wcslcpy.h"], + deps = [ + ":__support_common", + ":__support_macros_config", + ":string_utils", + ":types_size_t", + ":types_wchar_t", + ], +) + libc_function( name = "wcslen", srcs = ["src/wchar/wcslen.cpp"], diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/wchar/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/wchar/BUILD.bazel index f94065237ef4f..431a7ecb8bfe8 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/wchar/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/wchar/BUILD.bazel @@ -83,6 +83,16 @@ libc_test( ], ) +libc_test( + name = "wcslcpy_test", + srcs = ["wcslcpy_test.cpp"], + deps = [ + "//libc:types_size_t", + "//libc:types_wchar_t", + "//libc:wcslcpy", + ], +) + libc_test( name = "wcslen_test", srcs = ["wcslen_test.cpp"],