[libc] Add strncat and fix strcat
This adds strncat to llvm libc. In addition, an error was found with strcat and that was fixed. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D111583
This commit is contained in:
parent
63638ed181
commit
9e9803bf82
|
@ -35,6 +35,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.string.strcpy
|
||||
libc.src.string.strcspn
|
||||
libc.src.string.strlen
|
||||
libc.src.string.strncat
|
||||
libc.src.string.strncmp
|
||||
libc.src.string.strncpy
|
||||
libc.src.string.strnlen
|
||||
|
|
|
@ -95,6 +95,17 @@ add_entrypoint_object(
|
|||
libc.include.string
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strncat
|
||||
SRCS
|
||||
strncat.cpp
|
||||
HDRS
|
||||
strncat.h
|
||||
DEPENDS
|
||||
.strncpy
|
||||
.string_utils
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strncmp
|
||||
SRCS
|
||||
|
|
|
@ -16,7 +16,10 @@ namespace __llvm_libc {
|
|||
|
||||
LLVM_LIBC_FUNCTION(char *, strcat,
|
||||
(char *__restrict dest, const char *__restrict src)) {
|
||||
__llvm_libc::strcpy(dest + internal::string_length(dest), src);
|
||||
size_t destLength = internal::string_length(dest);
|
||||
size_t srcLength = internal::string_length(src);
|
||||
__llvm_libc::strcpy(dest + destLength, src);
|
||||
dest[destLength + srcLength] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===-- Implementation of strncat -----------------------------------------===//
|
||||
//
|
||||
// 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/strncat.h"
|
||||
#include "src/string/string_utils.h"
|
||||
#include "src/string/strncpy.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, strncat,
|
||||
(char *__restrict dest, const char *__restrict src,
|
||||
size_t count)) {
|
||||
size_t srcLength = internal::string_length(src);
|
||||
size_t copyAmount = srcLength > count ? count : srcLength;
|
||||
size_t destLength = internal::string_length(dest);
|
||||
__llvm_libc::strncpy(dest + destLength, src, copyAmount);
|
||||
dest[destLength + copyAmount] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for strncat -----------------------*- 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_STRNCAT_H
|
||||
#define LLVM_LIBC_SRC_STRING_STRNCAT_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *strncat(char *__restrict dest, const char *__restrict src, size_t count);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRING_STRNCAT_H
|
|
@ -82,6 +82,16 @@ add_libc_unittest(
|
|||
libc.src.string.strlen
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strncat_test
|
||||
SUITE
|
||||
libc_string_unittests
|
||||
SRCS
|
||||
strncat_test.cpp
|
||||
DEPENDS
|
||||
libc.src.string.strncat
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strncmp_test
|
||||
SUITE
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
//===-- Unittests for strncat ---------------------------------------------===//
|
||||
//
|
||||
// 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/strncat.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcStrNCatTest, EmptyDest) {
|
||||
const char *abc = "abc";
|
||||
char dest[4];
|
||||
|
||||
dest[0] = '\0';
|
||||
|
||||
// Start by copying nothing
|
||||
char *result = __llvm_libc::strncat(dest, abc, 0);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_EQ(dest[0], '\0');
|
||||
|
||||
// Then copy part of it.
|
||||
result = __llvm_libc::strncat(dest, abc, 1);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "a");
|
||||
|
||||
// Reset for the last test.
|
||||
dest[0] = '\0';
|
||||
|
||||
// Then copy all of it.
|
||||
result = __llvm_libc::strncat(dest, abc, 3);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, result);
|
||||
ASSERT_STREQ(dest, abc);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStrNCatTest, NonEmptyDest) {
|
||||
const char *abc = "abc";
|
||||
char dest[7];
|
||||
|
||||
dest[0] = 'x';
|
||||
dest[1] = 'y';
|
||||
dest[2] = 'z';
|
||||
dest[3] = '\0';
|
||||
|
||||
// Copy only part of the string onto the end
|
||||
char *result = __llvm_libc::strncat(dest, abc, 1);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "xyza");
|
||||
|
||||
// Copy a bit more, but without resetting.
|
||||
result = __llvm_libc::strncat(dest, abc, 2);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "xyzaab");
|
||||
|
||||
// Set just the end marker, to make sure it overwrites properly.
|
||||
dest[3] = '\0';
|
||||
|
||||
result = __llvm_libc::strncat(dest, abc, 3);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "xyzabc");
|
||||
|
||||
// Check that copying still works when count > src length
|
||||
dest[0] = '\0';
|
||||
// And that it doesn't write beyond what is necessary.
|
||||
dest[4] = 'Z';
|
||||
result = __llvm_libc::strncat(dest, abc, 4);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "abc");
|
||||
ASSERT_EQ(dest[4], 'Z');
|
||||
|
||||
result = __llvm_libc::strncat(dest, abc, 5);
|
||||
ASSERT_EQ(dest, result);
|
||||
ASSERT_STREQ(dest, "abcabc");
|
||||
}
|
Loading…
Reference in New Issue