diff options
| author | Alex Brachet <abrachet@google.com> | 2022-05-19 21:47:28 +0000 |
|---|---|---|
| committer | Alex Brachet <abrachet@google.com> | 2022-05-19 21:48:39 +0000 |
| commit | b1183305f882f15a368cc33ed9b2f77aedb5b9a6 (patch) | |
| tree | cb777194ee849529bbec278d071c40b1fa257e2b | |
| parent | 027499a82434ea7a784b2e5a0227540f00fbc307 (diff) | |
| download | llvm-b1183305f882f15a368cc33ed9b2f77aedb5b9a6.zip llvm-b1183305f882f15a368cc33ed9b2f77aedb5b9a6.tar.gz llvm-b1183305f882f15a368cc33ed9b2f77aedb5b9a6.tar.bz2 | |
[libc] Add strlcat
Differential Revision: https://reviews.llvm.org/D125978
| -rw-r--r-- | libc/config/darwin/arm/entrypoints.txt | 1 | ||||
| -rw-r--r-- | libc/config/linux/aarch64/entrypoints.txt | 1 | ||||
| -rw-r--r-- | libc/config/linux/x86_64/entrypoints.txt | 1 | ||||
| -rw-r--r-- | libc/config/windows/entrypoints.txt | 1 | ||||
| -rw-r--r-- | libc/spec/bsd_ext.td | 5 | ||||
| -rw-r--r-- | libc/src/string/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | libc/src/string/string_utils.h | 13 | ||||
| -rw-r--r-- | libc/src/string/strlcat.cpp | 27 | ||||
| -rw-r--r-- | libc/src/string/strlcat.h | 20 | ||||
| -rw-r--r-- | libc/src/string/strlcpy.cpp | 11 | ||||
| -rw-r--r-- | libc/test/src/string/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | libc/test/src/string/strlcat_test.cpp | 37 |
12 files changed, 130 insertions, 12 deletions
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt index 568a8fb..a8f882f 100644 --- a/libc/config/darwin/arm/entrypoints.txt +++ b/libc/config/darwin/arm/entrypoints.txt @@ -35,6 +35,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strcmp libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen libc.src.string.strncat diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 31a5969..01b4fac 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -40,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strcmp libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen libc.src.string.strncat diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 783dabf..a0b7a6b5 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -40,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strcmp libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen libc.src.string.strncat diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 0f5b14a..8d7cf67 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -35,6 +35,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strcmp libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen libc.src.string.strncat diff --git a/libc/spec/bsd_ext.td b/libc/spec/bsd_ext.td index 09832f7..577d978 100644 --- a/libc/spec/bsd_ext.td +++ b/libc/spec/bsd_ext.td @@ -6,6 +6,11 @@ def BsdExtensions : StandardSpec<"BSDExtensions"> { [], // Enumerations [ FunctionSpec< + "strlcat", + RetValSpec<SizeTType>, + [ArgSpec<CharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>] + >, + FunctionSpec< "strlcpy", RetValSpec<SizeTType>, [ArgSpec<CharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>] diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index 20b1b4c..68962e2 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -6,6 +6,8 @@ add_header_library( string_utils.h DEPENDS libc.src.__support.CPP.bitset + .memory_utils.memcpy_implementation + .memory_utils.memset_implementation ) add_entrypoint_object( @@ -127,14 +129,23 @@ add_entrypoint_object( ) add_entrypoint_object( + strlcat + SRCS + strlcat.cpp + HDRS + strlcat.h + DEPENDS + .string_utils + libc.include.string +) + +add_entrypoint_object( strlcpy SRCS strlcpy.cpp HDRS strlcpy.h DEPENDS - .memory_utils.memcpy_implementation - .memory_utils.memset_implementation .string_utils libc.include.string ) diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h index 699f65f..3d854d3 100644 --- a/libc/src/string/string_utils.h +++ b/libc/src/string/string_utils.h @@ -11,6 +11,8 @@ #include "src/__support/CPP/Bitset.h" #include "src/__support/common.h" +#include "src/string/memory_utils/memcpy_implementations.h" +#include "src/string/memory_utils/memset_implementations.h" #include <stddef.h> // size_t namespace __llvm_libc { @@ -85,6 +87,17 @@ static inline char *string_token(char *__restrict src, return token; } +static inline size_t strlcpy(char *__restrict dst, const char *__restrict src, + size_t size) { + size_t len = internal::string_length(src); + if (!size) + return len; + size_t n = len < size - 1 ? len : size - 1; + inline_memcpy(dst, src, n); + inline_memset(dst + n, 0, size - n); + return len; +} + } // namespace internal } // namespace __llvm_libc diff --git a/libc/src/string/strlcat.cpp b/libc/src/string/strlcat.cpp new file mode 100644 index 0000000..a718de7 --- /dev/null +++ b/libc/src/string/strlcat.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of strlcat -----------------------------------------===// +// +// 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/strlcat.h" +#include "src/string/string_utils.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(size_t, strlcat, + (char *__restrict dst, const char *__restrict src, + size_t size)) { + char *new_dst = reinterpret_cast<char *>(internal::find_first_character( + reinterpret_cast<unsigned char *>(dst), 0, size)); + if (!new_dst) + return size + internal::string_length(src); + size_t first_len = new_dst - dst; + return first_len + internal::strlcpy(new_dst, src, size - first_len); +} + +} // namespace __llvm_libc diff --git a/libc/src/string/strlcat.h b/libc/src/string/strlcat.h new file mode 100644 index 0000000..7b073c6 --- /dev/null +++ b/libc/src/string/strlcat.h @@ -0,0 +1,20 @@ +//===-- Implementation header for strlcat -----------------------*- 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_STRLCAT_H +#define LLVM_LIBC_SRC_STRING_STRLCAT_H + +#include <string.h> + +namespace __llvm_libc { + +size_t strlcat(char *__restrict dst, const char *__restrict src, size_t size); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_STRLCAT_H diff --git a/libc/src/string/strlcpy.cpp b/libc/src/string/strlcpy.cpp index 3cb3dd1..fa1f102 100644 --- a/libc/src/string/strlcpy.cpp +++ b/libc/src/string/strlcpy.cpp @@ -7,9 +7,6 @@ //===----------------------------------------------------------------------===// #include "src/string/strlcpy.h" -#include "src/string/bzero.h" -#include "src/string/memory_utils/memcpy_implementations.h" -#include "src/string/memory_utils/memset_implementations.h" #include "src/string/string_utils.h" #include "src/__support/common.h" @@ -19,13 +16,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(size_t, strlcpy, (char *__restrict dst, const char *__restrict src, size_t size)) { - size_t len = internal::string_length(src); - if (!size) - return len; - size_t n = len < size - 1 ? len : size - 1; - inline_memcpy(dst, src, n); - inline_memset(dst + n, 0, size - n); - return len; + return internal::strlcpy(dst, src, size); } } // namespace __llvm_libc diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt index 5bdb47a..e60f9ab 100644 --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -124,6 +124,16 @@ add_libc_unittest( ) add_libc_unittest( + strlcat_test + SUITE + libc_string_unittests + SRCS + strlcat_test.cpp + DEPENDS + libc.src.string.strlcat +) + +add_libc_unittest( strlcpy_test SUITE libc_string_unittests diff --git a/libc/test/src/string/strlcat_test.cpp b/libc/test/src/string/strlcat_test.cpp new file mode 100644 index 0000000..66db15e5 --- /dev/null +++ b/libc/test/src/string/strlcat_test.cpp @@ -0,0 +1,37 @@ +//===-- Unittests for strlcat ---------------------------------------------===// +// +// 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/strlcat.h" +#include "utils/UnitTest/Test.h" +#include <stdlib.h> + +TEST(LlvmLibcStrlcatTest, TooBig) { + const char *str = "cd"; + char buf[4]{"ab"}; + EXPECT_EQ(__llvm_libc::strlcat(buf, str, 3), size_t(4)); + EXPECT_STREQ(buf, "ab"); + EXPECT_EQ(__llvm_libc::strlcat(buf, str, 4), size_t(4)); + EXPECT_STREQ(buf, "abc"); +} + +TEST(LlvmLibcStrlcatTest, Smaller) { + const char *str = "cd"; + char buf[7]{"ab"}; + + EXPECT_EQ(__llvm_libc::strlcat(buf, str, 7), size_t(4)); + EXPECT_STREQ(buf, "abcd"); +} + +TEST(LlvmLibcStrlcatTest, No0) { + const char *str = "cd"; + char buf[7]{"ab"}; + EXPECT_EQ(__llvm_libc::strlcat(buf, str, 1), size_t(3)); + EXPECT_STREQ(buf, "ab"); + EXPECT_EQ(__llvm_libc::strlcat(buf, str, 2), size_t(4)); + EXPECT_STREQ(buf, "ab"); +} |
