diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index c7beb3ef3fdfc..ab1917259519b 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -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 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 12dc87bf945fd..a29478898fe70 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -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 diff --git a/libc/include/strings.yaml b/libc/include/strings.yaml index 802f6533585f8..855800d9dbc3d 100644 --- a/libc/include/strings.yaml +++ b/libc/include/strings.yaml @@ -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 diff --git a/libc/src/strings/CMakeLists.txt b/libc/src/strings/CMakeLists.txt index 6d86680e8e71f..d312495ae8d91 100644 --- a/libc/src/strings/CMakeLists.txt +++ b/libc/src/strings/CMakeLists.txt @@ -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 +) diff --git a/libc/src/strings/strcasecmp_l.cpp b/libc/src/strings/strcasecmp_l.cpp new file mode 100644 index 0000000000000..95117cb27a564 --- /dev/null +++ b/libc/src/strings/strcasecmp_l.cpp @@ -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 diff --git a/libc/src/strings/strcasecmp_l.h b/libc/src/strings/strcasecmp_l.h new file mode 100644 index 0000000000000..48074460205ce --- /dev/null +++ b/libc/src/strings/strcasecmp_l.h @@ -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 diff --git a/libc/src/strings/strncasecmp_l.cpp b/libc/src/strings/strncasecmp_l.cpp new file mode 100644 index 0000000000000..91ac7e5e89107 --- /dev/null +++ b/libc/src/strings/strncasecmp_l.cpp @@ -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 diff --git a/libc/src/strings/strncasecmp_l.h b/libc/src/strings/strncasecmp_l.h new file mode 100644 index 0000000000000..6c6c7f17b4438 --- /dev/null +++ b/libc/src/strings/strncasecmp_l.h @@ -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 + +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 diff --git a/libc/test/src/strings/CMakeLists.txt b/libc/test/src/strings/CMakeLists.txt index baa22bb449c6c..5f70dc024f6ce 100644 --- a/libc/test/src/strings/CMakeLists.txt +++ b/libc/test/src/strings/CMakeLists.txt @@ -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) diff --git a/libc/test/src/strings/strcasecmp_l_test.cpp b/libc/test/src/strings/strcasecmp_l_test.cpp new file mode 100644 index 0000000000000..33a47b6547d68 --- /dev/null +++ b/libc/test/src/strings/strcasecmp_l_test.cpp @@ -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); +} diff --git a/libc/test/src/strings/strncasecmp_l_test.cpp b/libc/test/src/strings/strncasecmp_l_test.cpp new file mode 100644 index 0000000000000..271f31808c7c3 --- /dev/null +++ b/libc/test/src/strings/strncasecmp_l_test.cpp @@ -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); +}