Skip to content

Commit bc5e5c0

Browse files
sribee8Sriya Pratipati
andauthored
[libc] wcpncpy implementation (#145430)
Implemented wcpncpy and tests. --------- Co-authored-by: Sriya Pratipati <[email protected]>
1 parent 10d46cf commit bc5e5c0

File tree

7 files changed

+174
-0
lines changed

7 files changed

+174
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ set(TARGET_LIBC_ENTRYPOINTS
385385
libc.src.wchar.wcscpy
386386
libc.src.wchar.wmemchr
387387
libc.src.wchar.wcpcpy
388+
libc.src.wchar.wcpncpy
388389

389390
# sys/uio.h entrypoints
390391
libc.src.sys.uio.writev

libc/include/wchar.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,11 @@ functions:
189189
arguments:
190190
- type: wchar_t *__restrict
191191
- type: const wchar_t *__restrict
192+
- name: wcpncpy
193+
standards:
194+
- stdc
195+
return_type: wchar_t *
196+
arguments:
197+
- type: wchar_t *__restrict
198+
- type: const wchar_t *__restrict
199+
- type: size_t

libc/src/wchar/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ add_entrypoint_object(
104104
libc.src.string.string_utils
105105
)
106106

107+
add_entrypoint_object(
108+
wcpncpy
109+
SRCS
110+
wcpncpy.cpp
111+
HDRS
112+
wcpncpy.h
113+
DEPENDS
114+
libc.hdr.types.size_t
115+
libc.hdr.wchar_macros
116+
libc.src.__support.macros.null_check
117+
)
118+
107119
add_entrypoint_object(
108120
wcschr
109121
SRCS

libc/src/wchar/wcpncpy.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===-- Implementation of wcpncpy -----------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/wchar/wcpncpy.h"
10+
11+
#include "hdr/types/size_t.h"
12+
#include "hdr/types/wchar_t.h"
13+
#include "src/__support/common.h"
14+
#include "src/__support/macros/config.h"
15+
#include "src/__support/macros/null_check.h"
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
LLVM_LIBC_FUNCTION(wchar_t *, wcpncpy,
20+
(wchar_t *__restrict s1, const wchar_t *__restrict s2,
21+
size_t n)) {
22+
if (n) {
23+
LIBC_CRASH_ON_NULLPTR(s1);
24+
LIBC_CRASH_ON_NULLPTR(s2);
25+
}
26+
size_t i;
27+
// Copy up until \0 is found.
28+
for (i = 0; i < n && s2[i] != '\0'; ++i)
29+
s1[i] = s2[i];
30+
// When n>strlen(src), n-strlen(src) \0 are appended.
31+
for (; i < n; ++i)
32+
s1[i] = L'\0';
33+
return s1 + i;
34+
}
35+
36+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wcpncpy.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Implementation header for wcpncpy ---------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_WCHAR_WCPNCPY_H
10+
#define LLVM_LIBC_SRC_WCHAR_WCPNCPY_H
11+
12+
#include "hdr/types/size_t.h"
13+
#include "hdr/types/wchar_t.h"
14+
#include "src/__support/macros/config.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
wchar_t *wcpncpy(wchar_t *__restrict ws1, const wchar_t *__restrict ws2,
19+
size_t n);
20+
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SRC_WCHAR_WCPNsCPY_H

libc/test/src/wchar/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,13 @@ add_libc_test(
255255
DEPENDS
256256
libc.src.wchar.wcpcpy
257257
)
258+
259+
add_libc_test(
260+
wcpncpy_test
261+
SUITE
262+
libc_wchar_unittests
263+
SRCS
264+
wcpncpy_test.cpp
265+
DEPENDS
266+
libc.src.wchar.wcpncpy
267+
)

libc/test/src/wchar/wcpncpy_test.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===-- Unittests for wcpncpy --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "hdr/types/wchar_t.h"
10+
#include "src/wchar/wcpncpy.h"
11+
#include "test/UnitTest/Test.h"
12+
13+
TEST(LlvmLibcWCPNCpyTest, EmptySrc) {
14+
// Empty src should lead to empty destination.
15+
wchar_t dest[4] = {L'a', L'b', L'c', L'\0'};
16+
const wchar_t *src = L"";
17+
LIBC_NAMESPACE::wcpncpy(dest, src, 3);
18+
ASSERT_TRUE(dest[0] == src[0]);
19+
ASSERT_TRUE(dest[0] == L'\0');
20+
// Rest should also be padded with L'\0'
21+
ASSERT_TRUE(dest[1] == L'\0');
22+
ASSERT_TRUE(dest[2] == L'\0');
23+
}
24+
25+
TEST(LlvmLibcWCPNCpyTest, Untouched) {
26+
wchar_t dest[] = {L'a', L'b'};
27+
const wchar_t src[] = {L'x', L'\0'};
28+
LIBC_NAMESPACE::wcpncpy(dest, src, 0);
29+
ASSERT_TRUE(dest[0] == L'a');
30+
ASSERT_TRUE(dest[1] == L'b');
31+
}
32+
33+
TEST(LlvmLibcWCPNCpyTest, CopyOne) {
34+
wchar_t dest[] = {L'a', L'b'};
35+
const wchar_t src[] = {L'x', L'y'};
36+
wchar_t *res = LIBC_NAMESPACE::wcpncpy(dest, src, 1);
37+
ASSERT_TRUE(dest[0] == L'x');
38+
ASSERT_TRUE(dest[1] == L'b');
39+
ASSERT_EQ(dest + 1, res);
40+
}
41+
42+
TEST(LlvmLibcWCPNCpyTest, CopyNull) {
43+
wchar_t dest[] = {L'a', L'b'};
44+
const wchar_t src[] = {L'\0', L'y'};
45+
wchar_t *res = LIBC_NAMESPACE::wcpncpy(dest, src, 1);
46+
ASSERT_TRUE(dest[0] == L'\0');
47+
ASSERT_TRUE(dest[1] == L'b');
48+
ASSERT_EQ(dest + 1, res);
49+
}
50+
51+
TEST(LlvmLibcWCPNCpyTest, CopyPastSrc) {
52+
wchar_t dest[] = {L'a', L'b'};
53+
const wchar_t src[] = {L'\0', L'y'};
54+
wchar_t *res = LIBC_NAMESPACE::wcpncpy(dest, src, 2);
55+
ASSERT_TRUE(dest[0] == L'\0');
56+
ASSERT_TRUE(dest[1] == L'\0');
57+
ASSERT_EQ(dest + 2, res);
58+
}
59+
60+
TEST(LlvmLibcWCPNCpyTest, CopyTwoNoNull) {
61+
wchar_t dest[] = {L'a', L'b'};
62+
const wchar_t src[] = {L'x', L'y'};
63+
wchar_t *res = LIBC_NAMESPACE::wcpncpy(dest, src, 2);
64+
ASSERT_TRUE(dest[0] == L'x');
65+
ASSERT_TRUE(dest[1] == L'y');
66+
ASSERT_EQ(dest + 2, res);
67+
}
68+
69+
TEST(LlvmLibcWCPNCpyTest, CopyTwoWithNull) {
70+
wchar_t dest[] = {L'a', L'b'};
71+
const wchar_t src[] = {L'x', L'\0'};
72+
wchar_t *res = LIBC_NAMESPACE::wcpncpy(dest, src, 2);
73+
ASSERT_TRUE(dest[0] == L'x');
74+
ASSERT_TRUE(dest[1] == L'\0');
75+
ASSERT_EQ(dest + 2, res);
76+
}
77+
78+
#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
79+
TEST(LlvmLibcWCPNCpyTest, NullptrCrash) {
80+
// Passing in a nullptr should crash the program.
81+
EXPECT_DEATH([] { LIBC_NAMESPACE::wcpncpy(nullptr, nullptr, 1); },
82+
WITH_SIGNAL(-1));
83+
}
84+
#endif // LIBC_HAS_ADDRESS_SANITIZER

0 commit comments

Comments
 (0)