Skip to content

Commit d4791f5

Browse files
sribee8Sriya Pratipati
andauthored
[libc] wcsspn implementation (#142034)
Implemented wcsspn as well as tests for the function. --------- Co-authored-by: Sriya Pratipati <[email protected]>
1 parent 03d1f3d commit d4791f5

File tree

7 files changed

+172
-0
lines changed

7 files changed

+172
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ set(TARGET_LIBC_ENTRYPOINTS
366366
libc.src.wchar.wctob
367367
libc.src.wchar.wmemset
368368
libc.src.wchar.wcschr
369+
libc.src.wchar.wcsspn
369370
libc.src.wchar.wmemcmp
370371

371372
# sys/uio.h entrypoints

libc/include/wchar.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ functions:
4242
arguments:
4343
- type: const wchar_t *
4444
- type: wchar_t
45+
- name: wcsspn
46+
standards:
47+
- stdc
48+
return_type: size_t
49+
arguments:
50+
- type: const wchar_t *
51+
- type: const wchar_t *
4552
- name: wmemcmp
4653
standards:
4754
- stdc

libc/src/wchar/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ add_entrypoint_object(
5757
libc.src.__support.wctype_utils
5858
)
5959

60+
add_entrypoint_object(
61+
wcsspn
62+
SRCS
63+
wcsspn.cpp
64+
HDRS
65+
wcsspn.h
66+
DEPENDS
67+
libc.hdr.wchar_macros
68+
libc.hdr.types.size_t
69+
libc.src.__support.wctype_utils
70+
)
71+
6072
add_entrypoint_object(
6173
wmemcmp
6274
SRCS

libc/src/wchar/wcsspn.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- Implementation of wcsspn ------------------------------------------===//
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/wcsspn.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+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
bool check(wchar_t c, const wchar_t *s2) {
19+
for (int n = 0; s2[n]; ++n) {
20+
if (s2[n] == c)
21+
return true;
22+
}
23+
return false;
24+
}
25+
LLVM_LIBC_FUNCTION(size_t, wcsspn, (const wchar_t *s1, const wchar_t *s2)) {
26+
size_t i = 0;
27+
for (; s1[i]; ++i) {
28+
if (!check(s1[i], s2))
29+
return i;
30+
}
31+
return i;
32+
}
33+
34+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wcsspn.h

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

libc/test/src/wchar/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ add_libc_test(
5555
libc.src.wchar.wcschr
5656
)
5757

58+
add_libc_test(
59+
wcsspn_test
60+
SUITE
61+
libc_wchar_unittests
62+
SRCS
63+
wcsspn_test.cpp
64+
DEPENDS
65+
libc.src.wchar.wcsspn
66+
)
67+
5868
add_libc_test(
5969
wmemcmp_test
6070
SUITE

libc/test/src/wchar/wcsspn_test.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===-- Unittests for wcsspn ----------------------------------------------===//
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/wcsspn.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
TEST(LlvmLibcWCSSpnTest, EmptyStringShouldReturnZeroLengthSpan) {
15+
// The search should not include the null terminator.
16+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"", L""), size_t{0});
17+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"_", L""), size_t{0});
18+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"", L"_"), size_t{0});
19+
}
20+
21+
TEST(LlvmLibcWCSSpnTest, ShouldNotSpanAnythingAfterNullTerminator) {
22+
const wchar_t src[4] = {'a', 'b', '\0', 'c'};
23+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"ab"), size_t{2});
24+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"c"), size_t{0});
25+
26+
// Same goes for the segment to be searched for.
27+
const wchar_t segment[4] = {'1', '2', '\0', '3'};
28+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"123", segment), size_t{2});
29+
}
30+
31+
TEST(LlvmLibcWCSSpnTest, SpanEachIndividualCharacter) {
32+
const wchar_t *src = L"12345";
33+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"1"), size_t{1});
34+
// Since '1' is not within the segment, the span
35+
// size should remain zero.
36+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"2"), size_t{0});
37+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"3"), size_t{0});
38+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"4"), size_t{0});
39+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"5"), size_t{0});
40+
}
41+
42+
TEST(LlvmLibcWCSSpnTest, UnmatchedCharacterShouldNotBeCountedInSpan) {
43+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"a", L"b"), size_t{0});
44+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"abcdef", L"1"), size_t{0});
45+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"123", L"4"), size_t{0});
46+
}
47+
48+
TEST(LlvmLibcWCSSpnTest, SequentialCharactersShouldSpan) {
49+
const wchar_t *src = L"abcde";
50+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"a"), size_t{1});
51+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"ab"), size_t{2});
52+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"abc"), size_t{3});
53+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"abcd"), size_t{4});
54+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"abcde"), size_t{5});
55+
// Same thing for when the roles are reversed.
56+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"abcde", src), size_t{5});
57+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"abcd", src), size_t{4});
58+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"abc", src), size_t{3});
59+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"ab", src), size_t{2});
60+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"a", src), size_t{1});
61+
}
62+
63+
TEST(LlvmLibcWCSSpnTest, NonSequentialCharactersShouldNotSpan) {
64+
const wchar_t *src = L"123456789";
65+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"_1_abc_2_def_3_"), size_t{3});
66+
// Only spans 4 since '5' is not within the span.
67+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(src, L"67__34abc12"), size_t{4});
68+
}
69+
70+
TEST(LlvmLibcWCSSpnTest, ReverseCharacters) {
71+
// Since these are still sequential, this should span.
72+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"12345", L"54321"), size_t{5});
73+
// Does not span any since '1' is not within the span.
74+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"12345", L"432"), size_t{0});
75+
// Only spans 1 since '2' is not within the span.
76+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"12345", L"51"), size_t{1});
77+
}
78+
79+
TEST(LlvmLibcWCSSpnTest, DuplicatedCharactersToBeSearchedForShouldStillMatch) {
80+
// Only a single character, so only spans 1.
81+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"a", L"aa"), size_t{1});
82+
// This should count once for each 'a' in the source string.
83+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"aa", L"aa"), size_t{2});
84+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"aaa", L"aa"), size_t{3});
85+
EXPECT_EQ(LIBC_NAMESPACE::wcsspn(L"aaaa", L"aa"), size_t{4});
86+
}

0 commit comments

Comments
 (0)