diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index a30ffbe0b2b91..f87e212eecbab 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -374,6 +374,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wmemcmp libc.src.wchar.wmempcpy libc.src.wchar.wmemcpy + libc.src.wchar.wcscat libc.src.wchar.wcsstr libc.src.wchar.wcsncat libc.src.wchar.wcscpy diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index 29a989fddb592..a44a352e4753a 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -102,6 +102,13 @@ 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 * - name: wcsstr standards: - stdc diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index be62495bf8a0f..95246ad777697 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -137,6 +137,18 @@ add_entrypoint_object( 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 +) + add_entrypoint_object( wcsstr SRCS diff --git a/libc/src/wchar/wcscat.cpp b/libc/src/wchar/wcscat.cpp new file mode 100644 index 0000000000000..50d90c0941c75 --- /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 i = 0; + for (; s2[i] != L'\0'; i++) + s1[size_1 + i] = s2[i]; + s1[size_1 + i] = L'\0'; + 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 38ff8b8720504..859d33a22617f 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -135,6 +135,16 @@ add_libc_test( libc.src.wchar.wmemcpy ) +add_libc_test( + wcscat_test + SUITE + libc_wchar_unittests + SRCS + wcscat_test.cpp + DEPENDS + libc.src.wchar.wcscat +) + add_libc_test( wcsstr_test SUITE 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'); +}