Skip to content

Commit 9422abf

Browse files
sribee8Sriya Pratipati
andauthored
[libc] wcsncat implementation (#142431)
Implemented wcsncat and tests. --------- Co-authored-by: Sriya Pratipati <[email protected]>
1 parent dabe983 commit 9422abf

File tree

7 files changed

+167
-0
lines changed

7 files changed

+167
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ set(TARGET_LIBC_ENTRYPOINTS
373373
libc.src.wchar.wmemcmp
374374
libc.src.wchar.wmempcpy
375375
libc.src.wchar.wmemcpy
376+
libc.src.wchar.wcsncat
376377
libc.src.wchar.wcscpy
377378

378379
# sys/uio.h entrypoints

libc/include/wchar.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ functions:
9494
- type: __restrict wchar_t *
9595
- type: const __restrict wchar_t *
9696
- type: size_t
97+
- name: wcsncat
98+
standards:
99+
- stdc
100+
return_type: wchar_t *
101+
arguments:
102+
- type: __restrict wchar_t *
103+
- type: const __restrict wchar_t *
104+
- type: size_t
97105
- name: wcscpy
98106
standards:
99107
- stdc

libc/src/wchar/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ add_entrypoint_object(
125125
libc.src.__support.wctype_utils
126126
)
127127

128+
add_entrypoint_object(
129+
wcsncat
130+
SRCS
131+
wcsncat.cpp
132+
HDRS
133+
wcsncat.h
134+
DEPENDS
135+
libc.hdr.types.size_t
136+
libc.hdr.wchar_macros
137+
libc.src.string.string_utils
138+
)
139+
128140
add_entrypoint_object(
129141
wmempcpy
130142
SRCS

libc/src/wchar/wcsncat.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===-- Implementation of wcsncat -----------------------------------------===//
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/wcsncat.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/string/string_utils.h"
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
LLVM_LIBC_FUNCTION(wchar_t *, wcsncat,
20+
(wchar_t *__restrict s1, const wchar_t *__restrict s2,
21+
size_t n)) {
22+
size_t size = internal::string_length(s1);
23+
size_t i = 0;
24+
for (; s2[i] && i < n; ++i)
25+
s1[size + i] = s2[i];
26+
// Appending null character to the end of the result.
27+
s1[size + i] = L'\0';
28+
return s1;
29+
}
30+
31+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wcsncat.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Implementation header for wcsncat ---------------------------------===//
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_WCSNCAT_H
10+
#define LLVM_LIBC_SRC_WCHAR_WCSNCAT_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 *wcsncat(wchar_t *__restrict s1, const wchar_t *__restrict s2,
19+
size_t n);
20+
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SRC_WCHAR_WCSNCAT_H

libc/test/src/wchar/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ add_libc_test(
125125
libc.src.wchar.wmemcpy
126126
)
127127

128+
add_libc_test(
129+
wcsncat_test
130+
SUITE
131+
libc_wchar_unittests
132+
SRCS
133+
wcsncat_test.cpp
134+
DEPENDS
135+
libc.src.wchar.wcsncat
136+
)
137+
128138
add_libc_test(
129139
wcscpy_test
130140
SUITE

libc/test/src/wchar/wcsncat_test.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===-- Unittests for wcscat ---------------------------------------------===//
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/wcsncat.h"
11+
#include "test/UnitTest/Test.h"
12+
13+
TEST(LlvmLibcWCSNCatTest, EmptyDest) {
14+
wchar_t dest[4] = {L'\0'};
15+
const wchar_t *src = L"abc";
16+
17+
// Start by copying nothing
18+
LIBC_NAMESPACE::wcsncat(dest, src, 0);
19+
ASSERT_TRUE(dest[0] == L'\0');
20+
21+
// Copying part of it.
22+
LIBC_NAMESPACE::wcsncat(dest, src, 1);
23+
ASSERT_TRUE(dest[0] == L'a');
24+
ASSERT_TRUE(dest[1] == L'\0');
25+
26+
// Resetting for the last test.
27+
dest[0] = '\0';
28+
29+
// Copying all of it.
30+
LIBC_NAMESPACE::wcsncat(dest, src, 3);
31+
ASSERT_TRUE(dest[0] == L'a');
32+
ASSERT_TRUE(dest[1] == L'b');
33+
ASSERT_TRUE(dest[2] == L'c');
34+
ASSERT_TRUE(dest[3] == L'\0');
35+
}
36+
37+
TEST(LlvmLibcWCSNCatTest, NonEmptyDest) {
38+
wchar_t dest[7] = {L'x', L'y', L'z', L'\0'};
39+
const wchar_t *src = L"abc";
40+
41+
// Adding on only part of the string
42+
LIBC_NAMESPACE::wcsncat(dest, src, 1);
43+
ASSERT_TRUE(dest[0] == L'x');
44+
ASSERT_TRUE(dest[1] == L'y');
45+
ASSERT_TRUE(dest[2] == L'z');
46+
ASSERT_TRUE(dest[3] == L'a');
47+
ASSERT_TRUE(dest[4] == L'\0');
48+
49+
// Copying more without resetting
50+
LIBC_NAMESPACE::wcsncat(dest, src, 2);
51+
ASSERT_TRUE(dest[0] == L'x');
52+
ASSERT_TRUE(dest[1] == L'y');
53+
ASSERT_TRUE(dest[2] == L'z');
54+
ASSERT_TRUE(dest[3] == L'a');
55+
ASSERT_TRUE(dest[4] == L'a');
56+
ASSERT_TRUE(dest[5] == L'b');
57+
ASSERT_TRUE(dest[6] == L'\0');
58+
59+
// Setting end marker to make sure it overwrites properly.
60+
dest[3] = L'\0';
61+
62+
// Copying all of it.
63+
LIBC_NAMESPACE::wcsncat(dest, src, 3);
64+
ASSERT_TRUE(dest[0] == L'x');
65+
ASSERT_TRUE(dest[1] == L'y');
66+
ASSERT_TRUE(dest[2] == L'z');
67+
ASSERT_TRUE(dest[3] == L'a');
68+
ASSERT_TRUE(dest[4] == L'b');
69+
ASSERT_TRUE(dest[5] == L'c');
70+
ASSERT_TRUE(dest[6] == L'\0');
71+
72+
// Check that copying still works when count > src length.
73+
dest[0] = L'\0';
74+
// And that it doesn't write beyond what is necessary.
75+
dest[4] = L'Z';
76+
LIBC_NAMESPACE::wcsncat(dest, src, 4);
77+
ASSERT_TRUE(dest[0] == L'a');
78+
ASSERT_TRUE(dest[1] == L'b');
79+
ASSERT_TRUE(dest[2] == L'c');
80+
ASSERT_TRUE(dest[3] == L'\0');
81+
ASSERT_TRUE(dest[4] == L'Z');
82+
}

0 commit comments

Comments
 (0)