Skip to content

Commit 62af2a5

Browse files
authored
[libc] Implemented wcscmp (llvm#142423)
Implemented wcscmp and added tests
1 parent 14c2fa2 commit 62af2a5

File tree

7 files changed

+177
-0
lines changed

7 files changed

+177
-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.wcscmp
369370
libc.src.wchar.wcspbrk
370371
libc.src.wchar.wcsspn
371372
libc.src.wchar.wmemcmp

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: wcscmp
46+
standards:
47+
- stdc
48+
return_type: int
49+
arguments:
50+
- type: const wchar_t *
51+
- type: const wchar_t *
4552
- name: wcspbrk
4653
standards:
4754
- stdc

libc/src/wchar/CMakeLists.txt

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

60+
add_entrypoint_object(
61+
wcscmp
62+
SRCS
63+
wcscmp.cpp
64+
HDRS
65+
wcscmp.h
66+
DEPENDS
67+
libc.hdr.wchar_macros
68+
)
69+
6070
add_entrypoint_object(
6171
wcspbrk
6272
SRCS

libc/src/wchar/wcscmp.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===-- Implementation of wcscmp ------------------------------------------===//
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/wcscmp.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/null_check.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
LLVM_LIBC_FUNCTION(int, wcscmp, (const wchar_t *left, const wchar_t *right)) {
19+
LIBC_CRASH_ON_NULLPTR(left);
20+
LIBC_CRASH_ON_NULLPTR(right);
21+
22+
auto comp = [](wchar_t l, wchar_t r) -> int { return l - r; };
23+
24+
for (; *left && !comp(*left, *right); ++left, ++right)
25+
;
26+
27+
return comp(*left, *right);
28+
}
29+
30+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wcscmp.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation header for wcscmp ----------------------------------===//
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_WCSCMP_H
10+
#define LLVM_LIBC_SRC_WCHAR_WCSCMP_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+
int wcscmp(const wchar_t *left, const wchar_t *right);
19+
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SRC_WCHAR_WCSCMP_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+
wcscmp_test
60+
SUITE
61+
libc_wchar_unittests
62+
SRCS
63+
wcscmp_test.cpp
64+
DEPENDS
65+
libc.src.wchar.wcscmp
66+
)
67+
5868
add_libc_test(
5969
wcspbrk_test
6070
SUITE

libc/test/src/wchar/wcscmp_test.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===-- Unittests for wcscmp ----------------------------------------------===//
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/wcscmp.h"
10+
#include "test/UnitTest/Test.h"
11+
12+
TEST(LlvmLibcWcscmpTest, EmptyStringsShouldReturnZero) {
13+
const wchar_t *s1 = L"";
14+
const wchar_t *s2 = L"";
15+
int result = LIBC_NAMESPACE::wcscmp(s1, s2);
16+
ASSERT_EQ(result, 0);
17+
18+
// Verify operands reversed.
19+
result = LIBC_NAMESPACE::wcscmp(s2, s1);
20+
ASSERT_EQ(result, 0);
21+
}
22+
23+
TEST(LlvmLibcWcscmpTest, EmptyStringShouldNotEqualNonEmptyString) {
24+
const wchar_t *empty = L"";
25+
const wchar_t *s2 = L"abc";
26+
int result = LIBC_NAMESPACE::wcscmp(empty, s2);
27+
ASSERT_LT(result, 0);
28+
29+
// Similar case if empty string is second argument.
30+
const wchar_t *s3 = L"123";
31+
result = LIBC_NAMESPACE::wcscmp(s3, empty);
32+
ASSERT_GT(result, 0);
33+
}
34+
35+
TEST(LlvmLibcWcscmpTest, EqualStringsShouldReturnZero) {
36+
const wchar_t *s1 = L"abc";
37+
const wchar_t *s2 = L"abc";
38+
int result = LIBC_NAMESPACE::wcscmp(s1, s2);
39+
ASSERT_EQ(result, 0);
40+
41+
// Verify operands reversed.
42+
result = LIBC_NAMESPACE::wcscmp(s2, s1);
43+
ASSERT_EQ(result, 0);
44+
}
45+
46+
TEST(LlvmLibcWcscmpTest, ShouldReturnResultOfFirstDifference) {
47+
const wchar_t *s1 = L"___B42__";
48+
const wchar_t *s2 = L"___C55__";
49+
int result = LIBC_NAMESPACE::wcscmp(s1, s2);
50+
ASSERT_LT(result, 0);
51+
52+
// Verify operands reversed.
53+
result = LIBC_NAMESPACE::wcscmp(s2, s1);
54+
ASSERT_GT(result, 0);
55+
}
56+
57+
TEST(LlvmLibcWcscmpTest, CapitalizedLetterShouldNotBeEqual) {
58+
const wchar_t *s1 = L"abcd";
59+
const wchar_t *s2 = L"abCd";
60+
int result = LIBC_NAMESPACE::wcscmp(s1, s2);
61+
ASSERT_GT(result, 0);
62+
63+
// Verify operands reversed.
64+
result = LIBC_NAMESPACE::wcscmp(s2, s1);
65+
ASSERT_LT(result, 0);
66+
}
67+
68+
TEST(LlvmLibcWcscmpTest, UnequalLengthStringsShouldNotReturnZero) {
69+
const wchar_t *s1 = L"abc";
70+
const wchar_t *s2 = L"abcd";
71+
int result = LIBC_NAMESPACE::wcscmp(s1, s2);
72+
ASSERT_LT(result, 0);
73+
74+
// Verify operands reversed.
75+
result = LIBC_NAMESPACE::wcscmp(s2, s1);
76+
ASSERT_GT(result, 0);
77+
}
78+
79+
TEST(LlvmLibcWcscmpTest, StringArgumentSwapChangesSign) {
80+
const wchar_t *a = L"a";
81+
const wchar_t *b = L"b";
82+
int result = LIBC_NAMESPACE::wcscmp(b, a);
83+
ASSERT_GT(result, 0);
84+
85+
result = LIBC_NAMESPACE::wcscmp(a, b);
86+
ASSERT_LT(result, 0);
87+
}
88+
89+
#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
90+
TEST(LlvmLibcWcscmpTest, NullptrCrash) {
91+
// Passing in a nullptr should crash the program.
92+
EXPECT_DEATH([] { LIBC_NAMESPACE::wcscmp(L"aaaaaaaaaaaaaa", nullptr); },
93+
WITH_SIGNAL(-1));
94+
EXPECT_DEATH([] { LIBC_NAMESPACE::wcscmp(nullptr, L"aaaaaaaaaaaaaa"); },
95+
WITH_SIGNAL(-1));
96+
}
97+
#endif // LIBC_HAS_ADDRESS_SANITIZER

0 commit comments

Comments
 (0)