Skip to content

Commit d5436b0

Browse files
sribee8Sriya Pratipati
andauthored
[libc] wcslcat implementation (#146588)
implemented wcslcat and tests. --------- Co-authored-by: Sriya Pratipati <sriyap@google.com>
1 parent ac4a38e commit d5436b0

File tree

9 files changed

+175
-0
lines changed

9 files changed

+175
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ set(TARGET_LIBC_ENTRYPOINTS
384384
libc.src.wchar.wcscat
385385
libc.src.wchar.wcsstr
386386
libc.src.wchar.wcsncat
387+
libc.src.wchar.wcslcat
387388
libc.src.wchar.wcscpy
388389
libc.src.wchar.wcslcpy
389390
libc.src.wchar.wmemchr

libc/include/wchar.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ functions:
166166
arguments:
167167
- type: wchar_t *__restrict
168168
- type: const wchar_t *__restrict
169+
- name: wcslcat
170+
standards:
171+
- stdc
172+
return_type: size_t
173+
arguments:
174+
- type: wchar_t *__restrict
175+
- type: const wchar_t *__restrict
176+
- type: size_t
169177
- name: wcsstr
170178
standards:
171179
- stdc

libc/src/wchar/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,18 @@ add_entrypoint_object(
307307
libc.src.string.string_utils
308308
)
309309

310+
add_entrypoint_object(
311+
wcslcat
312+
SRCS
313+
wcslcat.cpp
314+
HDRS
315+
wcslcat.h
316+
DEPENDS
317+
libc.hdr.types.size_t
318+
libc.hdr.wchar_macros
319+
libc.src.string.string_utils
320+
)
321+
310322
add_entrypoint_object(
311323
wmemchr
312324
SRCS

libc/src/wchar/wcslcat.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- Implementation of wcslcat -----------------------------------------===//
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/wcslcat.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(size_t, wcslcat,
20+
(wchar_t *__restrict dst, const wchar_t *__restrict src,
21+
size_t dstsize)) {
22+
const size_t dstlen = internal::string_length(dst);
23+
const size_t srclen = internal::string_length(src);
24+
int limit = static_cast<int>(dstsize - dstlen - 1);
25+
size_t returnval = (dstsize < dstlen ? dstsize : dstlen) + srclen;
26+
if (limit < 0)
27+
return returnval;
28+
int i = 0;
29+
for (; i < limit && src[i] != L'\0'; ++i) {
30+
dst[dstlen + i] = src[i];
31+
}
32+
33+
// appending null terminator if there is room
34+
if (dstlen + i < dstlen + dstsize)
35+
dst[dstlen + i] = L'\0';
36+
return returnval;
37+
}
38+
39+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wcslcat.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Implementation header for wcslcat ---------------------------------===//
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_WCSLCAT_H
10+
#define LLVM_LIBC_SRC_WCHAR_WCSLCAT_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+
size_t wcslcat(wchar_t *__restrict dst, const wchar_t *__restrict src,
19+
size_t dstsize);
20+
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SRC_WCHAR_WCSLCAT_H

libc/test/src/wchar/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,17 @@ add_libc_test(
283283
libc.src.wchar.wcsncat
284284
)
285285

286+
add_libc_test(
287+
wcslcat_test
288+
SUITE
289+
libc_wchar_unittests
290+
SRCS
291+
wcslcat_test.cpp
292+
DEPENDS
293+
libc.src.wchar.wcslcat
294+
libc.hdr.types.size_t
295+
)
296+
286297
add_libc_test(
287298
wcscpy_test
288299
SUITE

libc/test/src/wchar/wcslcat_test.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===-- Unittests for wcslcat ---------------------------------------------===//
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/size_t.h"
10+
#include "hdr/types/wchar_t.h"
11+
#include "src/wchar/wcslcat.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
TEST(LlvmLibcWCSLCatTest, TooBig) {
15+
const wchar_t *src = L"cd";
16+
wchar_t dst[4]{L"ab"};
17+
size_t res = LIBC_NAMESPACE::wcslcat(dst, src, 3);
18+
ASSERT_TRUE(dst[0] == L'a');
19+
ASSERT_TRUE(dst[1] == L'b');
20+
ASSERT_TRUE(dst[2] == L'\0');
21+
// Should still return src length + dst length
22+
ASSERT_EQ(res, size_t(4));
23+
// Not enough space to copy d
24+
res = LIBC_NAMESPACE::wcslcat(dst, src, 4);
25+
ASSERT_TRUE(dst[0] == L'a');
26+
ASSERT_TRUE(dst[1] == L'b');
27+
ASSERT_TRUE(dst[2] == L'c');
28+
ASSERT_TRUE(dst[3] == L'\0');
29+
ASSERT_EQ(res, size_t(4));
30+
}
31+
32+
TEST(LlvmLibcWCSLCatTest, Smaller) {
33+
const wchar_t *src = L"cd";
34+
wchar_t dst[7]{L"ab"};
35+
size_t res = LIBC_NAMESPACE::wcslcat(dst, src, 7);
36+
ASSERT_TRUE(dst[0] == L'a');
37+
ASSERT_TRUE(dst[1] == L'b');
38+
ASSERT_TRUE(dst[2] == L'c');
39+
ASSERT_TRUE(dst[3] == L'd');
40+
ASSERT_TRUE(dst[4] == L'\0');
41+
ASSERT_EQ(res, size_t(4));
42+
}
43+
44+
TEST(LlvmLibcWCSLCatTest, SmallerNoOverwriteAfter0) {
45+
const wchar_t *src = L"cd";
46+
wchar_t dst[8]{L"ab\0\0efg"};
47+
size_t res = LIBC_NAMESPACE::wcslcat(dst, src, 8);
48+
ASSERT_TRUE(dst[0] == L'a');
49+
ASSERT_TRUE(dst[1] == L'b');
50+
ASSERT_TRUE(dst[2] == L'c');
51+
ASSERT_TRUE(dst[3] == L'd');
52+
ASSERT_TRUE(dst[4] == L'\0');
53+
ASSERT_TRUE(dst[5] == L'f');
54+
ASSERT_TRUE(dst[6] == L'g');
55+
ASSERT_TRUE(dst[7] == L'\0');
56+
ASSERT_EQ(res, size_t(4));
57+
}

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5829,6 +5829,19 @@ libc_function(
58295829
],
58305830
)
58315831

5832+
libc_function(
5833+
name = "wcslcat",
5834+
srcs = ["src/wchar/wcslcat.cpp"],
5835+
hdrs = ["src/wchar/wcslcat.h"],
5836+
deps = [
5837+
":__support_common",
5838+
":__support_macros_config",
5839+
":string_utils",
5840+
":types_size_t",
5841+
":types_wchar_t",
5842+
],
5843+
)
5844+
58325845
libc_function(
58335846
name = "wcslcpy",
58345847
srcs = ["src/wchar/wcslcpy.cpp"],

utils/bazel/llvm-project-overlay/libc/test/src/wchar/BUILD.bazel

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ libc_test(
8383
],
8484
)
8585

86+
87+
libc_test(
88+
name = "wcslcat_test",
89+
srcs = ["wcslcat_test.cpp"],
90+
deps = [
91+
"//libc:types_size_t",
92+
"//libc:types_wchar_t",
93+
"//libc:wcslcat",
94+
],
95+
)
96+
8697
libc_test(
8798
name = "wcslcpy_test",
8899
srcs = ["wcslcpy_test.cpp"],

0 commit comments

Comments
 (0)