[libc-commits] [libc] [libc] implement `strings/str{n}casecmp_l` (PR #130407)

Connector Switch via libc-commits libc-commits at lists.llvm.org
Tue Mar 11 07:24:57 PDT 2025


https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/130407

>From d9b1a2c847fa68fd7bfcc1ad64c9d3b2d40cc3e4 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sat, 8 Mar 2025 10:02:15 +0000
Subject: [PATCH 1/3] str{n}case_l

---
 libc/config/linux/aarch64/entrypoints.txt    |  2 ++
 libc/config/linux/x86_64/entrypoints.txt     |  2 ++
 libc/include/strings.yaml                    | 18 +++++++++++++
 libc/src/strings/CMakeLists.txt              | 24 +++++++++++++++++
 libc/src/strings/strcasecmp_l.cpp            | 27 ++++++++++++++++++++
 libc/src/strings/strcasecmp_l.h              | 21 +++++++++++++++
 libc/src/strings/strncasecmp_l.cpp           | 27 ++++++++++++++++++++
 libc/src/strings/strncasecmp_l.h             | 23 +++++++++++++++++
 libc/test/src/strings/CMakeLists.txt         | 24 +++++++++++++++++
 libc/test/src/strings/strcasecmp_l_test.cpp  | 20 +++++++++++++++
 libc/test/src/strings/strncasecmp_l_test.cpp | 21 +++++++++++++++
 11 files changed, 209 insertions(+)
 create mode 100644 libc/src/strings/strcasecmp_l.cpp
 create mode 100644 libc/src/strings/strcasecmp_l.h
 create mode 100644 libc/src/strings/strncasecmp_l.cpp
 create mode 100644 libc/src/strings/strncasecmp_l.h
 create mode 100644 libc/test/src/strings/strcasecmp_l_test.cpp
 create mode 100644 libc/test/src/strings/strncasecmp_l_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index c7beb3ef3fdfc..e31d47a06e016 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -99,7 +99,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp
+    libc.src.strings.strcasecmp_l
     libc.src.strings.strncasecmp
+    libc.src.strings.strncasecmp_l
 
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 12dc87bf945fd..32620d4811007 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -99,7 +99,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp
+    libc.src.strings.strcasecmp_l
     libc.src.strings.strncasecmp
+    libc.src.strings.strncasecmp_l
 
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
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..598eab879f884
--- /dev/null
+++ b/libc/src/strings/strncasecmp_l.h
@@ -0,0 +1,23 @@
+//===-- 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_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
diff --git a/libc/test/src/strings/CMakeLists.txt b/libc/test/src/strings/CMakeLists.txt
index baa22bb449c6c..514c67ca9d21b 100644
--- a/libc/test/src/strings/CMakeLists.txt
+++ b/libc/test/src/strings/CMakeLists.txt
@@ -74,6 +74,18 @@ add_libc_test(
     libc.src.strings.strcasecmp
 )
 
+add_libc_test(
+  strcasecmp_l_test
+  SUITE
+    libc-strings-tests
+  SRCS
+    strcasecmp_l_test.cpp
+  DEPENDS
+    libc.src.locale.freelocale
+    libc.src.locale.newlocale
+    libc.src.strings.strcasecmp_l
+)
+
 add_libc_test(
   strncasecmp_test
   SUITE
@@ -84,5 +96,17 @@ add_libc_test(
     libc.src.strings.strncasecmp
 )
 
+add_libc_test(
+  strncasecmp_l_test
+  SUITE
+    libc-strings-tests
+  SRCS
+    strncasecmp_l_test.cpp
+  DEPENDS
+    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..22ebf1b134f3f
--- /dev/null
+++ b/libc/test/src/strings/strcasecmp_l_test.cpp
@@ -0,0 +1,20 @@
+//===-- 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 "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 = newlocale(LC_ALL, "C", nullptr);
+  ASSERT_EQ(strcasecmp_l("hello", "HELLO", locale), 0);
+  ASSERT_LT(strcasecmp_l("hello1", "hello2", locale), 0);
+  ASSERT_GT(strcasecmp_l("hello2", "hello1", locale), 0);
+  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..08708565c7f61
--- /dev/null
+++ b/libc/test/src/strings/strncasecmp_l_test.cpp
@@ -0,0 +1,21 @@
+//===-- 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 "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 = newlocale(LC_ALL, "C", nullptr);
+  ASSERT_EQ(0, strncasecmp_l("hello", "HELLO", 3, locale));
+  ASSERT_EQ(0, strncasecmp_l("abcXX", "ABCYY", 3, locale));
+  ASSERT_LT(strncasecmp_l("hello1", "hello2", 6, locale), 0);
+  ASSERT_GT(strncasecmp_l("hello2", "hello1", 6, locale), 0);
+  freelocale(locale);
+}

>From e203b5093a422784f817bd5ee202c507e186c82a Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sat, 8 Mar 2025 10:24:10 +0000
Subject: [PATCH 2/3] .

---
 libc/config/linux/aarch64/entrypoints.txt | 6 ++++--
 libc/config/linux/x86_64/entrypoints.txt  | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index e31d47a06e016..ab1917259519b 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -99,9 +99,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp
-    libc.src.strings.strcasecmp_l
     libc.src.strings.strncasecmp
-    libc.src.strings.strncasecmp_l
 
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
@@ -913,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 32620d4811007..a29478898fe70 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -99,9 +99,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp
-    libc.src.strings.strcasecmp_l
     libc.src.strings.strncasecmp
-    libc.src.strings.strncasecmp_l
 
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
@@ -940,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
 

>From 40736e7c14f5fa16a6b7819d34342149de235ed5 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sat, 8 Mar 2025 11:08:56 +0000
Subject: [PATCH 3/3] header

---
 libc/test/src/strings/CMakeLists.txt         |  2 ++
 libc/test/src/strings/strcasecmp_l_test.cpp  | 11 ++++++-----
 libc/test/src/strings/strncasecmp_l_test.cpp | 13 +++++++------
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/libc/test/src/strings/CMakeLists.txt b/libc/test/src/strings/CMakeLists.txt
index 514c67ca9d21b..a1bf5e82d7ea8 100644
--- a/libc/test/src/strings/CMakeLists.txt
+++ b/libc/test/src/strings/CMakeLists.txt
@@ -81,6 +81,7 @@ add_libc_test(
   SRCS
     strcasecmp_l_test.cpp
   DEPENDS
+    libc.include.locale
     libc.src.locale.freelocale
     libc.src.locale.newlocale
     libc.src.strings.strcasecmp_l
@@ -103,6 +104,7 @@ add_libc_test(
   SRCS
     strncasecmp_l_test.cpp
   DEPENDS
+    libc.include.locale
     libc.src.locale.freelocale
     libc.src.locale.newlocale
     libc.src.strings.strncasecmp_l
diff --git a/libc/test/src/strings/strcasecmp_l_test.cpp b/libc/test/src/strings/strcasecmp_l_test.cpp
index 22ebf1b134f3f..8eca6b51d0cee 100644
--- a/libc/test/src/strings/strcasecmp_l_test.cpp
+++ b/libc/test/src/strings/strcasecmp_l_test.cpp
@@ -6,15 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "include/llvm-libc-macros/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 = newlocale(LC_ALL, "C", nullptr);
-  ASSERT_EQ(strcasecmp_l("hello", "HELLO", locale), 0);
-  ASSERT_LT(strcasecmp_l("hello1", "hello2", locale), 0);
-  ASSERT_GT(strcasecmp_l("hello2", "hello1", locale), 0);
-  freelocale(locale);
+  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
index 08708565c7f61..51b9ea4c16cd0 100644
--- a/libc/test/src/strings/strncasecmp_l_test.cpp
+++ b/libc/test/src/strings/strncasecmp_l_test.cpp
@@ -6,16 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "include/llvm-libc-macros/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 = newlocale(LC_ALL, "C", nullptr);
-  ASSERT_EQ(0, strncasecmp_l("hello", "HELLO", 3, locale));
-  ASSERT_EQ(0, strncasecmp_l("abcXX", "ABCYY", 3, locale));
-  ASSERT_LT(strncasecmp_l("hello1", "hello2", 6, locale), 0);
-  ASSERT_GT(strncasecmp_l("hello2", "hello1", 6, locale), 0);
-  freelocale(locale);
+  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);
 }



More information about the libc-commits mailing list