[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 <michaelrj@google.com>
This commit is contained in:
@@ -911,6 +911,10 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||
# sched.h entrypoints
|
||||
libc.src.sched.__sched_getcpucount
|
||||
|
||||
# strings.h entrypoints
|
||||
libc.src.strings.strcasecmp_l
|
||||
libc.src.strings.strncasecmp_l
|
||||
|
||||
# setjmp.h entrypoints
|
||||
libc.src.setjmp.longjmp
|
||||
libc.src.setjmp.setjmp
|
||||
|
||||
@@ -938,6 +938,10 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||
libc.src.string.strcoll_l
|
||||
libc.src.string.strxfrm_l
|
||||
|
||||
# strings.h entrypoints
|
||||
libc.src.strings.strcasecmp_l
|
||||
libc.src.strings.strncasecmp_l
|
||||
|
||||
# assert.h entrypoints
|
||||
libc.src.assert.__assert_fail
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ header_template: strings.h.def
|
||||
macros: []
|
||||
types:
|
||||
- type_name: size_t
|
||||
- type_name: locale_t
|
||||
enums: []
|
||||
objects: []
|
||||
functions:
|
||||
@@ -68,6 +69,14 @@ functions:
|
||||
arguments:
|
||||
- type: const char *
|
||||
- type: const char *
|
||||
- name: strcasecmp_l
|
||||
standards:
|
||||
- BSDExtensions
|
||||
return_type: int
|
||||
arguments:
|
||||
- type: const char *
|
||||
- type: const char *
|
||||
- type: locale_t
|
||||
- name: strncasecmp
|
||||
standards:
|
||||
- BSDExtensions
|
||||
@@ -76,3 +85,12 @@ functions:
|
||||
- type: const char *
|
||||
- type: const char *
|
||||
- type: size_t
|
||||
- name: strncasecmp_l
|
||||
standards:
|
||||
- BSDExtensions
|
||||
return_type: int
|
||||
arguments:
|
||||
- type: const char *
|
||||
- type: const char *
|
||||
- type: size_t
|
||||
- type: locale_t
|
||||
|
||||
@@ -115,6 +115,18 @@ add_entrypoint_object(
|
||||
libc.src.string.memory_utils.inline_strcmp
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strcasecmp_l
|
||||
SRCS
|
||||
strcasecmp_l.cpp
|
||||
HDRS
|
||||
strcasecmp_l.h
|
||||
DEPENDS
|
||||
libc.hdr.types.locale_t
|
||||
libc.src.__support.ctype_utils
|
||||
libc.src.string.memory_utils.inline_strcmp
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strncasecmp
|
||||
SRCS
|
||||
@@ -125,3 +137,15 @@ add_entrypoint_object(
|
||||
libc.src.__support.ctype_utils
|
||||
libc.src.string.memory_utils.inline_strcmp
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strncasecmp_l
|
||||
SRCS
|
||||
strncasecmp_l.cpp
|
||||
HDRS
|
||||
strncasecmp_l.h
|
||||
DEPENDS
|
||||
libc.hdr.types.locale_t
|
||||
libc.src.__support.ctype_utils
|
||||
libc.src.string.memory_utils.inline_strcmp
|
||||
)
|
||||
|
||||
27
libc/src/strings/strcasecmp_l.cpp
Normal file
27
libc/src/strings/strcasecmp_l.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- Implementation of strcasecmp_l ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/strings/strcasecmp_l.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/ctype_utils.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
#include "src/string/memory_utils/inline_strcmp.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, strcasecmp_l,
|
||||
(const char *left, const char *right, locale_t)) {
|
||||
auto case_cmp = [](char a, char b) {
|
||||
return LIBC_NAMESPACE::internal::tolower(a) -
|
||||
LIBC_NAMESPACE::internal::tolower(b);
|
||||
};
|
||||
return inline_strcmp(left, right, case_cmp);
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
21
libc/src/strings/strcasecmp_l.h
Normal file
21
libc/src/strings/strcasecmp_l.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//===-- Implementation header for strcasecmp_l ------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STRINGS_STRCASECMP_L_H
|
||||
#define LLVM_LIBC_SRC_STRINGS_STRCASECMP_L_H
|
||||
|
||||
#include "hdr/types/locale_t.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
int strcasecmp_l(const char *left, const char *right, locale_t locale);
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRINGS_STRCASECMP_L_H
|
||||
27
libc/src/strings/strncasecmp_l.cpp
Normal file
27
libc/src/strings/strncasecmp_l.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- Implementation of strncasecmp_l -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/strings/strncasecmp_l.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/ctype_utils.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
#include "src/string/memory_utils/inline_strcmp.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, strncasecmp_l,
|
||||
(const char *left, const char *right, size_t n, locale_t)) {
|
||||
auto case_cmp = [](char a, char b) {
|
||||
return LIBC_NAMESPACE::internal::tolower(a) -
|
||||
LIBC_NAMESPACE::internal::tolower(b);
|
||||
};
|
||||
return inline_strncmp(left, right, n, case_cmp);
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
23
libc/src/strings/strncasecmp_l.h
Normal file
23
libc/src/strings/strncasecmp_l.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//===-- Implementation header for strncasecmp_l -----------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STRINGS_STRNCASECMP_L_H
|
||||
#define LLVM_LIBC_SRC_STRINGS_STRNCASECMP_L_H
|
||||
|
||||
#include "hdr/types/locale_t.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
#include <stddef.h>
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
int strncasecmp_l(const char *left, const char *right, size_t n,
|
||||
locale_t locale);
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRINGS_STRNCASECMP_L_H
|
||||
@@ -74,6 +74,19 @@ add_libc_test(
|
||||
libc.src.strings.strcasecmp
|
||||
)
|
||||
|
||||
add_libc_test(
|
||||
strcasecmp_l_test
|
||||
SUITE
|
||||
libc-strings-tests
|
||||
SRCS
|
||||
strcasecmp_l_test.cpp
|
||||
DEPENDS
|
||||
libc.hdr.locale_macros
|
||||
libc.src.locale.freelocale
|
||||
libc.src.locale.newlocale
|
||||
libc.src.strings.strcasecmp_l
|
||||
)
|
||||
|
||||
add_libc_test(
|
||||
strncasecmp_test
|
||||
SUITE
|
||||
@@ -84,5 +97,18 @@ add_libc_test(
|
||||
libc.src.strings.strncasecmp
|
||||
)
|
||||
|
||||
add_libc_test(
|
||||
strncasecmp_l_test
|
||||
SUITE
|
||||
libc-strings-tests
|
||||
SRCS
|
||||
strncasecmp_l_test.cpp
|
||||
DEPENDS
|
||||
libc.hdr.locale_macros
|
||||
libc.src.locale.freelocale
|
||||
libc.src.locale.newlocale
|
||||
libc.src.strings.strncasecmp_l
|
||||
)
|
||||
|
||||
add_libc_multi_impl_test(bcmp libc-strings-tests SRCS bcmp_test.cpp)
|
||||
add_libc_multi_impl_test(bzero libc-strings-tests SRCS bzero_test.cpp)
|
||||
|
||||
21
libc/test/src/strings/strcasecmp_l_test.cpp
Normal file
21
libc/test/src/strings/strcasecmp_l_test.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//===-- Unittests for strcasecmp_l ----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "hdr/locale_macros.h"
|
||||
#include "src/locale/freelocale.h"
|
||||
#include "src/locale/newlocale.h"
|
||||
#include "src/strings/strcasecmp_l.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcStrCaseCmpLTest, Case) {
|
||||
locale_t locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::strcasecmp_l("hello", "HELLO", locale), 0);
|
||||
ASSERT_LT(LIBC_NAMESPACE::strcasecmp_l("hello1", "hello2", locale), 0);
|
||||
ASSERT_GT(LIBC_NAMESPACE::strcasecmp_l("hello2", "hello1", locale), 0);
|
||||
LIBC_NAMESPACE::freelocale(locale);
|
||||
}
|
||||
22
libc/test/src/strings/strncasecmp_l_test.cpp
Normal file
22
libc/test/src/strings/strncasecmp_l_test.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- Unittests for strncasecmp_l ---------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "hdr/locale_macros.h"
|
||||
#include "src/locale/freelocale.h"
|
||||
#include "src/locale/newlocale.h"
|
||||
#include "src/strings/strncasecmp_l.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcStrNCaseCmpLTest, Case) {
|
||||
locale_t locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::strncasecmp_l("hello", "HELLO", 3, locale), 0);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::strncasecmp_l("abcXX", "ABCYY", 3, locale), 0);
|
||||
ASSERT_LT(LIBC_NAMESPACE::strncasecmp_l("hello1", "hello2", 6, locale), 0);
|
||||
ASSERT_GT(LIBC_NAMESPACE::strncasecmp_l("hello2", "hello1", 6, locale), 0);
|
||||
LIBC_NAMESPACE::freelocale(locale);
|
||||
}
|
||||
Reference in New Issue
Block a user