-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Implement search/lsearch
#131431
[libc] Implement search/lsearch
#131431
Conversation
@llvm/pr-subscribers-libc Author: Connector Switch (c8ef) Changesref:
Full diff: https://github.com/llvm/llvm-project/pull/131431.diff 9 Files Affected:
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index ab1917259519b..c1e688ea7e86b 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -999,6 +999,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch_r
libc.src.search.insque
libc.src.search.lfind
+ libc.src.search.lsearch
libc.src.search.remque
# threads.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a29478898fe70..3cb9ee82752b3 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1113,6 +1113,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch_r
libc.src.search.insque
libc.src.search.lfind
+ libc.src.search.lsearch
libc.src.search.remque
# threads.h entrypoints
diff --git a/libc/include/search.yaml b/libc/include/search.yaml
index b7ce06d48e704..f6f5d6cb062e5 100644
--- a/libc/include/search.yaml
+++ b/libc/include/search.yaml
@@ -69,3 +69,13 @@ functions:
- type: size_t *
- type: size_t
- type: __lsearchcompare_t
+ - name: lsearch
+ standards:
+ - POSIX
+ return_type: void *
+ arguments:
+ - type: const void *
+ - type: void *
+ - type: size_t *
+ - type: size_t
+ - type: __lsearchcompare_t
diff --git a/libc/src/search/CMakeLists.txt b/libc/src/search/CMakeLists.txt
index 497657f40f2f0..d78ea062342a1 100644
--- a/libc/src/search/CMakeLists.txt
+++ b/libc/src/search/CMakeLists.txt
@@ -110,3 +110,16 @@ add_entrypoint_object(
libc.src.__support.CPP.cstddef
libc.src.__support.memory_size
)
+
+add_entrypoint_object(
+ lsearch
+ SRCS
+ lsearch.cpp
+ HDRS
+ lsearch.h
+ DEPENDS
+ libc.include.search
+ libc.src.__support.CPP.cstddef
+ libc.src.__support.memory_size
+ libc.src.string.memory_utils.inline_memcpy
+)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index c8bf07de0b903..b10065aef2a93 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of lfind -------------------------------*- C++ -*-===//
+//===-- Implementation of lfind ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/search/lsearch.cpp b/libc/src/search/lsearch.cpp
new file mode 100644
index 0000000000000..e28dc3488413d
--- /dev/null
+++ b/libc/src/search/lsearch.cpp
@@ -0,0 +1,39 @@
+//===-- Implementation of lsearch -------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/search/lsearch.h"
+#include "src/__support/CPP/cstddef.h" // cpp::byte
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/memory_size.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, lsearch,
+ (const void *key, void *base, size_t *nmemb, size_t size,
+ int (*compar)(const void *, const void *))) {
+ if (key == nullptr || base == nullptr || nmemb == nullptr ||
+ compar == nullptr)
+ return nullptr;
+
+ size_t byte_len = 0;
+ if (internal::mul_overflow(*nmemb, size, &byte_len))
+ return nullptr;
+
+ const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
+ const cpp::byte *end = next + byte_len;
+ for (; next < end; next += size)
+ if (compar(key, next) == 0)
+ return const_cast<cpp::byte *>(next);
+
+ *nmemb += 1;
+ inline_memcpy(const_cast<cpp::byte *>(end), key, size);
+ return const_cast<cpp::byte *>(end);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/search/lsearch.h b/libc/src/search/lsearch.h
new file mode 100644
index 0000000000000..c95e01d396cd0
--- /dev/null
+++ b/libc/src/search/lsearch.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for lsearch -----------------------*- 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_SEARCH_LSEARCH_H
+#define LLVM_LIBC_SRC_SEARCH_LSEARCH_H
+
+#include "src/__support/macros/config.h"
+#include <stddef.h> // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+void *lsearch(const void *key, void *base, size_t *nmemb, size_t size,
+ int (*compar)(const void *, const void *));
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEARCH_LSEARCH_H
diff --git a/libc/test/src/search/CMakeLists.txt b/libc/test/src/search/CMakeLists.txt
index a1f9aac2094c9..9f34d4d3fd259 100644
--- a/libc/test/src/search/CMakeLists.txt
+++ b/libc/test/src/search/CMakeLists.txt
@@ -35,3 +35,13 @@ add_libc_unittest(
DEPENDS
libc.src.search.lfind
)
+
+add_libc_unittest(
+ lsearch_test
+ SUITE
+ libc_search_unittests
+ SRCS
+ lsearch_test.cpp
+ DEPENDS
+ libc.src.search.lsearch
+)
diff --git a/libc/test/src/search/lsearch_test.cpp b/libc/test/src/search/lsearch_test.cpp
new file mode 100644
index 0000000000000..22ac37f18b7bd
--- /dev/null
+++ b/libc/test/src/search/lsearch_test.cpp
@@ -0,0 +1,48 @@
+//===-- Unittests for lsearch ---------------------------------------------===//
+//
+// 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/search/lsearch.h"
+#include "test/UnitTest/Test.h"
+
+int compar(const void *a, const void *b) {
+ return *reinterpret_cast<const int *>(a) != *reinterpret_cast<const int *>(b);
+}
+
+TEST(LlvmLibcLsearchTest, SearchHead) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 1;
+ void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[0]);
+}
+
+TEST(LlvmLibcLsearchTest, SearchMiddle) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 2;
+ void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[1]);
+}
+
+TEST(LlvmLibcLsearchTest, SearchTail) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 3;
+ void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[2]);
+}
+
+TEST(LlvmLibcLsearchTest, SearchNonExistent) {
+ int list[4] = {1, 2, 3, 0};
+ size_t len = 3;
+ int key = 4;
+ void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[3]);
+ ASSERT_EQ(key, list[3]);
+ ASSERT_EQ(len, 4UL);
+}
|
Gentle ping~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also enable it for linux/riscv
? The implementation looks quite generic.
Done. |
Not sure why the checkout failed on Buildkite, it seems unrelated. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/196/builds/6160 Here is the relevant piece of the build log for the reference
|
Looks like size_t isn't equivalent to unsigned long on 32-bit platforms. I'll update this to |
…132028) Fix regression: #131431 (comment)
…2 in test. (#132028) Fix regression: llvm/llvm-project#131431 (comment)
ref: