From 0fdb865eb1578690850211315dd8887d9d688b9f Mon Sep 17 00:00:00 2001 From: Sriya Pratipati Date: Sat, 31 May 2025 00:15:05 +0000 Subject: [PATCH 1/3] [libc] wcscat implementation Implemented wcscat and tests. --- libc/config/linux/x86_64/entrypoints.txt | 1 + libc/include/wchar.yaml | 7 ++++ libc/src/wchar/CMakeLists.txt | 12 ++++++ libc/src/wchar/wcscat.cpp | 29 +++++++++++++++ libc/src/wchar/wcscat.h | 21 +++++++++++ libc/test/src/wchar/CMakeLists.txt | 10 +++++ libc/test/src/wchar/wcscat_test.cpp | 47 ++++++++++++++++++++++++ 7 files changed, 127 insertions(+) create mode 100644 libc/src/wchar/wcscat.cpp create mode 100644 libc/src/wchar/wcscat.h create mode 100644 libc/test/src/wchar/wcscat_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 7ddeb4d31b466..cb84ba9888bc9 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -370,6 +370,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcsspn libc.src.wchar.wmemcmp libc.src.wchar.wmemcpy + libc.src.wchar.wcscat # sys/uio.h entrypoints libc.src.sys.uio.writev diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index bfd9a10342019..28ca540ad75bc 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -72,3 +72,10 @@ functions: - type: __restrict wchar_t * - type: const __restrict wchar_t * - type: size_t + - name: wcscat + standards: + - stdc + return_type: wchar_t * + arguments: + - type: __restrict wchar_t * + - type: const __restrict wchar_t * diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index 9db121762348b..616ccdbc130d5 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -104,3 +104,15 @@ add_entrypoint_object( libc.hdr.wchar_macros libc.src.__support.wctype_utils ) + +add_entrypoint_object( + wcscat + SRCS + wcscat.cpp + HDRS + wcscat.h + DEPENDS + libc.hdr.types.size_t + libc.hdr.wchar_macros + libc.src.string.string_utils +) diff --git a/libc/src/wchar/wcscat.cpp b/libc/src/wchar/wcscat.cpp new file mode 100644 index 0000000000000..efdc5012701ff --- /dev/null +++ b/libc/src/wchar/wcscat.cpp @@ -0,0 +1,29 @@ +//===-- Implementation of wcscat ------------------------------------------===// +// +// 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/wcscat.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(wchar_t *, wcscat, + (wchar_t *__restrict s1, const wchar_t *__restrict s2)) { + size_t size_1 = internal::string_length(s1); + size_t size_2 = internal::string_length(s2); + for (size_t i = 0; i <= size_2; i++) { + s1[size_1 + i] = s2[i]; + } + return s1; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcscat.h b/libc/src/wchar/wcscat.h new file mode 100644 index 0000000000000..b0b4455983b4e --- /dev/null +++ b/libc/src/wchar/wcscat.h @@ -0,0 +1,21 @@ +//===-- Implementation header for wcscat ----------------------------------===// +// +// 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_WCSCAT_H +#define LLVM_LIBC_SRC_WCHAR_WCSCAT_H + +#include "hdr/types/wchar_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +wchar_t *wcscat(wchar_t *__restrict s1, const wchar_t *__restrict s2); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCSCAT_H diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt index 9bc230e0bddf3..a7c922cd3e8cf 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -94,3 +94,13 @@ add_libc_test( DEPENDS libc.src.wchar.wmemcpy ) + +add_libc_test( + wcscat_test + SUITE + libc_wchar_unittests + SRCS + wcscat_test.cpp + DEPENDS + libc.src.wchar.wcscat +) diff --git a/libc/test/src/wchar/wcscat_test.cpp b/libc/test/src/wchar/wcscat_test.cpp new file mode 100644 index 0000000000000..e91f79613ca9c --- /dev/null +++ b/libc/test/src/wchar/wcscat_test.cpp @@ -0,0 +1,47 @@ +//===-- Unittests for wcscat ---------------------------------------------===// +// +// 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/wcscat.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcWCSCatTest, EmptyDest) { + // Dest should be fully replaced with src. + wchar_t dest[4] = {L'\0'}; + const wchar_t *src = L"abc"; + LIBC_NAMESPACE::wcscat(dest, src); + ASSERT_TRUE(dest[0] == L'a'); + ASSERT_TRUE(dest[1] == L'b'); + ASSERT_TRUE(dest[2] == L'c'); + ASSERT_TRUE(dest[3] == L'\0'); +} + +TEST(LlvmLibcWCSCatTest, NonEmptyDest) { + // Src should be appended on to dest. + wchar_t dest[7] = {L'x', L'y', L'z', L'\0'}; + const wchar_t *src = L"abc"; + LIBC_NAMESPACE::wcscat(dest, src); + ASSERT_TRUE(dest[0] == L'x'); + ASSERT_TRUE(dest[1] == L'y'); + ASSERT_TRUE(dest[2] == L'z'); + ASSERT_TRUE(dest[3] == L'a'); + ASSERT_TRUE(dest[4] == L'b'); + ASSERT_TRUE(dest[5] == L'c'); + ASSERT_TRUE(dest[6] == L'\0'); +} + +TEST(LlvmLibcWCSCatTest, EmptySrc) { + // Dest should remain intact. + wchar_t dest[4] = {L'x', L'y', L'z', L'\0'}; + const wchar_t *src = L""; + LIBC_NAMESPACE::wcscat(dest, src); + ASSERT_TRUE(dest[0] == L'x'); + ASSERT_TRUE(dest[1] == L'y'); + ASSERT_TRUE(dest[2] == L'z'); + ASSERT_TRUE(dest[3] == L'\0'); +} From 530268ce420d2396d8c914e7e4742832eba71a7b Mon Sep 17 00:00:00 2001 From: Sriya Pratipati Date: Mon, 2 Jun 2025 19:14:27 +0000 Subject: [PATCH 2/3] Cleaned up code. --- libc/src/wchar/wcscat.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libc/src/wchar/wcscat.cpp b/libc/src/wchar/wcscat.cpp index efdc5012701ff..6ad27a54d5ad5 100644 --- a/libc/src/wchar/wcscat.cpp +++ b/libc/src/wchar/wcscat.cpp @@ -19,10 +19,11 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(wchar_t *, wcscat, (wchar_t *__restrict s1, const wchar_t *__restrict s2)) { size_t size_1 = internal::string_length(s1); - size_t size_2 = internal::string_length(s2); - for (size_t i = 0; i <= size_2; i++) { + size_t i = 0; + for (; s2[i] != L'\0'; i++) { s1[size_1 + i] = s2[i]; } + s1[size_1 + i] = L'\0'; return s1; } From 826e8bfb1f1b76def0ffb17c329bab63de048b92 Mon Sep 17 00:00:00 2001 From: Sriya Pratipati Date: Mon, 2 Jun 2025 19:15:43 +0000 Subject: [PATCH 3/3] Cleaned up code --- libc/src/wchar/wcscat.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libc/src/wchar/wcscat.cpp b/libc/src/wchar/wcscat.cpp index 6ad27a54d5ad5..50d90c0941c75 100644 --- a/libc/src/wchar/wcscat.cpp +++ b/libc/src/wchar/wcscat.cpp @@ -20,9 +20,8 @@ LLVM_LIBC_FUNCTION(wchar_t *, wcscat, (wchar_t *__restrict s1, const wchar_t *__restrict s2)) { size_t size_1 = internal::string_length(s1); size_t i = 0; - for (; s2[i] != L'\0'; i++) { + for (; s2[i] != L'\0'; i++) s1[size_1 + i] = s2[i]; - } s1[size_1 + i] = L'\0'; return s1; }