From: Caslyn Tonelli Date: Mon, 3 Apr 2023 21:56:49 +0000 (+0000) Subject: [libc] Add strxfrm Implementation X-Git-Tag: upstream/17.0.6~12372 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a1e4f1d006a5a669aaa874b8d36f58d9b086620f;p=platform%2Fupstream%2Fllvm.git [libc] Add strxfrm Implementation Introduce `strxfrm` and unit tests. The current implementation is introduced without locale support. The simplified function performs a `memcpy` if the `n` value is large enough to store the source len + '\0', otherwise `dest` is unmodified. Ticket: https://fxbug.dev/124217 Differential Revision: https://reviews.llvm.org/D147478 --- diff --git a/libc/config/linux/riscv64/entrypoints.txt b/libc/config/linux/riscv64/entrypoints.txt index 9daf4ed..cd41bae 100644 --- a/libc/config/linux/riscv64/entrypoints.txt +++ b/libc/config/linux/riscv64/entrypoints.txt @@ -72,6 +72,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index b74bc66..0b024b1 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -72,6 +72,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index 07c3b80..ee43c93 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -385,6 +385,17 @@ add_entrypoint_object( .string_utils ) +add_entrypoint_object( + strxfrm + SRCS + strxfrm.cpp + HDRS + strxfrm.h + DEPENDS + .string_utils + .memory_utils.memcpy_implementation +) + # Helper to define a function with multiple implementations # - Computes flags to satisfy required/rejected features and arch, # - Declares an entry point, diff --git a/libc/src/string/strxfrm.cpp b/libc/src/string/strxfrm.cpp new file mode 100644 index 0000000..5ee96d4 --- /dev/null +++ b/libc/src/string/strxfrm.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of strxfrm -----------------------------------------===// +// +// 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/string/strxfrm.h" +#include "src/string/memory_utils/memcpy_implementations.h" +#include "src/string/string_utils.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Add support for locales. +LLVM_LIBC_FUNCTION(size_t, strxfrm, + (char *__restrict dest, const char *__restrict src, + size_t n)) { + size_t len = internal::string_length(src); + if (n > len) + inline_memcpy(dest, src, len + 1); + return len; +} + +} // namespace __llvm_libc diff --git a/libc/src/string/strxfrm.h b/libc/src/string/strxfrm.h new file mode 100644 index 0000000..1ca1e73 --- /dev/null +++ b/libc/src/string/strxfrm.h @@ -0,0 +1,19 @@ +//===-- Implementation header for strxfrm -----------------------*- C++ -*-===// +// +// 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_STRING_STRXFRM_H +#define LLVM_LIBC_SRC_STRING_STRXFRM_H + +#include // For size_t +namespace __llvm_libc { + +size_t strxfrm(char *__restrict dest, const char *__restrict src, size_t n); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_STRXFRM_H diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt index 5d9be5e..9d5933e 100644 --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -368,6 +368,16 @@ add_libc_unittest( libc.src.string.strtok_r ) +add_libc_unittest( + strxfrm_test + SUITE + libc_string_unittests + SRCS + strxfrm_test.cpp + DEPENDS + libc.src.string.strxfrm +) + # Tests all implementations that can run on the target CPU. function(add_libc_multi_impl_test name) get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations) diff --git a/libc/test/src/string/strxfrm_test.cpp b/libc/test/src/string/strxfrm_test.cpp new file mode 100644 index 0000000..0512556 --- /dev/null +++ b/libc/test/src/string/strxfrm_test.cpp @@ -0,0 +1,45 @@ +//===-- Unittests for strxfrm ---------------------------------------------===// +// +// 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/string/strxfrm.h" +#include "test/UnitTest/Test.h" + +#include "src/string/string_utils.h" + +// TODO: Add more comprehensive tests once locale support is added. + +TEST(LlvmLibcStrxfrmTest, SimpleTestSufficientlySizedN) { + const char *src = "abc"; + const size_t n = 5; + + char dest[n]; + size_t result = __llvm_libc::strxfrm(dest, src, n); + ASSERT_EQ(result, __llvm_libc::internal::string_length(src)); + ASSERT_STREQ(dest, src); +} + +TEST(LlvmLibcStrxfrmTest, SimpleTestExactSizedN) { + const char *src = "abc"; + const size_t n = 4; + + char dest[n]; + size_t result = __llvm_libc::strxfrm(dest, src, n); + ASSERT_EQ(result, __llvm_libc::internal::string_length(src)); + ASSERT_STREQ(dest, src); +} + +TEST(LlvmLibcStrxfrmTest, SimpleTestInsufficientlySizedN) { + const char *src = "abc"; + const size_t n = 3; + + // Verify strxfrm does not modify dest if src len >= n + char dest[n] = {'x', 'x', '\0'}; + size_t result = __llvm_libc::strxfrm(dest, src, n); + ASSERT_GE(result, n); + ASSERT_STREQ(dest, "xx"); +}