Skip to content

Commit ab22f65

Browse files
[libc] implement strings/str{n}casecmp_l (#130407)
ref: https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcasecmp_l.html This patch introduces the `strcasecmp_l` function. At present, the locale parameter is ignored, making it a stub implementation. This is consistent with how other locale-related functions, such as `islower_l`, are treated in our codebase as well as in [musl](https://github.com/bminor/musl/blob/master/src/string/strcasecmp.c) and [bionic](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/strings_l.cpp). --------- Co-authored-by: Michael Jones <[email protected]>
1 parent c127618 commit ab22f65

File tree

11 files changed

+217
-0
lines changed

11 files changed

+217
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,10 @@ if(LLVM_LIBC_FULL_BUILD)
911911
# sched.h entrypoints
912912
libc.src.sched.__sched_getcpucount
913913

914+
# strings.h entrypoints
915+
libc.src.strings.strcasecmp_l
916+
libc.src.strings.strncasecmp_l
917+
914918
# setjmp.h entrypoints
915919
libc.src.setjmp.longjmp
916920
libc.src.setjmp.setjmp

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,10 @@ if(LLVM_LIBC_FULL_BUILD)
938938
libc.src.string.strcoll_l
939939
libc.src.string.strxfrm_l
940940

941+
# strings.h entrypoints
942+
libc.src.strings.strcasecmp_l
943+
libc.src.strings.strncasecmp_l
944+
941945
# assert.h entrypoints
942946
libc.src.assert.__assert_fail
943947

libc/include/strings.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ header_template: strings.h.def
33
macros: []
44
types:
55
- type_name: size_t
6+
- type_name: locale_t
67
enums: []
78
objects: []
89
functions:
@@ -68,6 +69,14 @@ functions:
6869
arguments:
6970
- type: const char *
7071
- type: const char *
72+
- name: strcasecmp_l
73+
standards:
74+
- BSDExtensions
75+
return_type: int
76+
arguments:
77+
- type: const char *
78+
- type: const char *
79+
- type: locale_t
7180
- name: strncasecmp
7281
standards:
7382
- BSDExtensions
@@ -76,3 +85,12 @@ functions:
7685
- type: const char *
7786
- type: const char *
7887
- type: size_t
88+
- name: strncasecmp_l
89+
standards:
90+
- BSDExtensions
91+
return_type: int
92+
arguments:
93+
- type: const char *
94+
- type: const char *
95+
- type: size_t
96+
- type: locale_t

libc/src/strings/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ add_entrypoint_object(
115115
libc.src.string.memory_utils.inline_strcmp
116116
)
117117

118+
add_entrypoint_object(
119+
strcasecmp_l
120+
SRCS
121+
strcasecmp_l.cpp
122+
HDRS
123+
strcasecmp_l.h
124+
DEPENDS
125+
libc.hdr.types.locale_t
126+
libc.src.__support.ctype_utils
127+
libc.src.string.memory_utils.inline_strcmp
128+
)
129+
118130
add_entrypoint_object(
119131
strncasecmp
120132
SRCS
@@ -125,3 +137,15 @@ add_entrypoint_object(
125137
libc.src.__support.ctype_utils
126138
libc.src.string.memory_utils.inline_strcmp
127139
)
140+
141+
add_entrypoint_object(
142+
strncasecmp_l
143+
SRCS
144+
strncasecmp_l.cpp
145+
HDRS
146+
strncasecmp_l.h
147+
DEPENDS
148+
libc.hdr.types.locale_t
149+
libc.src.__support.ctype_utils
150+
libc.src.string.memory_utils.inline_strcmp
151+
)

libc/src/strings/strcasecmp_l.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Implementation of strcasecmp_l ------------------------------------===//
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/strings/strcasecmp_l.h"
10+
11+
#include "src/__support/common.h"
12+
#include "src/__support/ctype_utils.h"
13+
#include "src/__support/macros/config.h"
14+
#include "src/string/memory_utils/inline_strcmp.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
LLVM_LIBC_FUNCTION(int, strcasecmp_l,
19+
(const char *left, const char *right, locale_t)) {
20+
auto case_cmp = [](char a, char b) {
21+
return LIBC_NAMESPACE::internal::tolower(a) -
22+
LIBC_NAMESPACE::internal::tolower(b);
23+
};
24+
return inline_strcmp(left, right, case_cmp);
25+
}
26+
27+
} // namespace LIBC_NAMESPACE_DECL

libc/src/strings/strcasecmp_l.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for strcasecmp_l ------------------*- C++ -*-===//
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_STRINGS_STRCASECMP_L_H
10+
#define LLVM_LIBC_SRC_STRINGS_STRCASECMP_L_H
11+
12+
#include "hdr/types/locale_t.h"
13+
#include "src/__support/macros/config.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
int strcasecmp_l(const char *left, const char *right, locale_t locale);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_STRINGS_STRCASECMP_L_H

libc/src/strings/strncasecmp_l.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Implementation of strncasecmp_l -----------------------------------===//
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/strings/strncasecmp_l.h"
10+
11+
#include "src/__support/common.h"
12+
#include "src/__support/ctype_utils.h"
13+
#include "src/__support/macros/config.h"
14+
#include "src/string/memory_utils/inline_strcmp.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
LLVM_LIBC_FUNCTION(int, strncasecmp_l,
19+
(const char *left, const char *right, size_t n, locale_t)) {
20+
auto case_cmp = [](char a, char b) {
21+
return LIBC_NAMESPACE::internal::tolower(a) -
22+
LIBC_NAMESPACE::internal::tolower(b);
23+
};
24+
return inline_strncmp(left, right, n, case_cmp);
25+
}
26+
27+
} // namespace LIBC_NAMESPACE_DECL

libc/src/strings/strncasecmp_l.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Implementation header for strncasecmp_l -----------------*- C++ -*-===//
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_STRINGS_STRNCASECMP_L_H
10+
#define LLVM_LIBC_SRC_STRINGS_STRNCASECMP_L_H
11+
12+
#include "hdr/types/locale_t.h"
13+
#include "src/__support/macros/config.h"
14+
#include <stddef.h>
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
int strncasecmp_l(const char *left, const char *right, size_t n,
19+
locale_t locale);
20+
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SRC_STRINGS_STRNCASECMP_L_H

libc/test/src/strings/CMakeLists.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ add_libc_test(
7474
libc.src.strings.strcasecmp
7575
)
7676

77+
add_libc_test(
78+
strcasecmp_l_test
79+
SUITE
80+
libc-strings-tests
81+
SRCS
82+
strcasecmp_l_test.cpp
83+
DEPENDS
84+
libc.hdr.locale_macros
85+
libc.src.locale.freelocale
86+
libc.src.locale.newlocale
87+
libc.src.strings.strcasecmp_l
88+
)
89+
7790
add_libc_test(
7891
strncasecmp_test
7992
SUITE
@@ -84,5 +97,18 @@ add_libc_test(
8497
libc.src.strings.strncasecmp
8598
)
8699

100+
add_libc_test(
101+
strncasecmp_l_test
102+
SUITE
103+
libc-strings-tests
104+
SRCS
105+
strncasecmp_l_test.cpp
106+
DEPENDS
107+
libc.hdr.locale_macros
108+
libc.src.locale.freelocale
109+
libc.src.locale.newlocale
110+
libc.src.strings.strncasecmp_l
111+
)
112+
87113
add_libc_multi_impl_test(bcmp libc-strings-tests SRCS bcmp_test.cpp)
88114
add_libc_multi_impl_test(bzero libc-strings-tests SRCS bzero_test.cpp)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Unittests for strcasecmp_l ----------------------------------------===//
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/locale_macros.h"
10+
#include "src/locale/freelocale.h"
11+
#include "src/locale/newlocale.h"
12+
#include "src/strings/strcasecmp_l.h"
13+
#include "test/UnitTest/Test.h"
14+
15+
TEST(LlvmLibcStrCaseCmpLTest, Case) {
16+
locale_t locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr);
17+
ASSERT_EQ(LIBC_NAMESPACE::strcasecmp_l("hello", "HELLO", locale), 0);
18+
ASSERT_LT(LIBC_NAMESPACE::strcasecmp_l("hello1", "hello2", locale), 0);
19+
ASSERT_GT(LIBC_NAMESPACE::strcasecmp_l("hello2", "hello1", locale), 0);
20+
LIBC_NAMESPACE::freelocale(locale);
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Unittests for strncasecmp_l ---------------------------------------===//
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/locale_macros.h"
10+
#include "src/locale/freelocale.h"
11+
#include "src/locale/newlocale.h"
12+
#include "src/strings/strncasecmp_l.h"
13+
#include "test/UnitTest/Test.h"
14+
15+
TEST(LlvmLibcStrNCaseCmpLTest, Case) {
16+
locale_t locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr);
17+
ASSERT_EQ(LIBC_NAMESPACE::strncasecmp_l("hello", "HELLO", 3, locale), 0);
18+
ASSERT_EQ(LIBC_NAMESPACE::strncasecmp_l("abcXX", "ABCYY", 3, locale), 0);
19+
ASSERT_LT(LIBC_NAMESPACE::strncasecmp_l("hello1", "hello2", 6, locale), 0);
20+
ASSERT_GT(LIBC_NAMESPACE::strncasecmp_l("hello2", "hello1", 6, locale), 0);
21+
LIBC_NAMESPACE::freelocale(locale);
22+
}

0 commit comments

Comments
 (0)