Skip to content

[libc][search] implement posix lfind function #114692

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

Merged
merged 12 commits into from
Nov 11, 2024
Merged
3 changes: 3 additions & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno

# search.h entrypoints
libc.src.search.lfind

# setjmp.h entrypoints
libc.src.setjmp.longjmp
libc.src.setjmp.setjmp
Expand Down
3 changes: 3 additions & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno

# search.h entrypoints
libc.src.search.lfind

# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
Expand Down
3 changes: 3 additions & 0 deletions libc/config/darwin/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno

# search.h entrypoints
libc.src.search.lfind

# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
Expand Down
3 changes: 3 additions & 0 deletions libc/config/darwin/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper

# search.h entrypoints
libc.src.search.lfind

# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bzero
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
libc.src.search.lfind
libc.src.search.remque

# threads.h entrypoints
Expand Down
3 changes: 3 additions & 0 deletions libc/config/linux/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno

# search.h entrypoints
libc.src.search.lfind

# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
libc.src.search.lfind
libc.src.search.remque

# threads.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
libc.src.search.lfind
libc.src.search.remque

# threads.h entrypoints
Expand Down
3 changes: 3 additions & 0 deletions libc/config/windows/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper

# search.h entrypoints
libc.src.search.lfind

# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/libc_search.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ hcreate |check|
hdestroy |check|
hsearch |check|
insque |check|
lfind
lfind |check|
lsearch
remque |check|
tdelete
Expand Down
10 changes: 10 additions & 0 deletions libc/newhdrgen/yaml/search.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,13 @@ functions:
return_type: void
arguments:
- type: void *
- name: lfind
standards:
- POSIX
return_type: void *
arguments:
- type: void *
- type: void *
- type: size_t *
- type: size_t
- type: int(*compar)(const void *, const void *)
11 changes: 11 additions & 0 deletions libc/spec/posix.td
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,17 @@ def POSIX : StandardSpec<"POSIX"> {
ArgSpec<VoidPtr>
]
>,
FunctionSpec<
"lfind",
RetValSpec<VoidPtr>,
[
ArgSpec<VoidPtr>,
ArgSpec<VoidPtr>,
ArgSpec<SizeTPtr>,
ArgSpec<SizeTType>,
// TODO: Unsure how to specify int(*compar)(void *, void *)
]
>
]
>;

Expand Down
11 changes: 11 additions & 0 deletions libc/src/search/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,14 @@ add_entrypoint_object(
libc.include.search
libc.src.__support.intrusive_list
)

add_entrypoint_object(
lfind
SRCS
lfind.cpp
HDRS
lfind.h
DEPENDS
libc.include.search
libc.src.__support.CPP.cstddef
)
29 changes: 29 additions & 0 deletions libc/src/search/lfind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/search/lfind.h"
#include "src/__support/CPP/cstddef.h" // cpp::byte
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, lfind,
(void *key, void *base, size_t *nmemb, size_t size,
int (*compar)(void *, void *))) {
cpp::byte *next = reinterpret_cast<cpp::byte *>(base);
cpp::byte *end = next + (*nmemb * size);
while (next < end) {
if (compar(key, next) == 0) {
return next;
}
next += size;
}
return nullptr;
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/search/lfind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_SEARCH_LFIND_H
#define LLVM_LIBC_SRC_SEARCH_LFIND_H

#include "src/__support/macros/config.h"
#include <search.h> // size_t

namespace LIBC_NAMESPACE_DECL {
void *lfind(void *key, void *base, size_t *nmemb, size_t size,
int (*compar)(void *, void *));
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_SEARCH_LFIND_H
10 changes: 10 additions & 0 deletions libc/test/src/search/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,13 @@ add_libc_unittest(
libc.src.search.insque
libc.src.search.remque
)

add_libc_unittest(
lfind_test
SUITE
libc_search_unittests
SRCS
lfind_test.cpp
DEPENDS
libc.src.search.lfind
)
46 changes: 46 additions & 0 deletions libc/test/src/search/lfind_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===-- Unittests for lfind -----------------------------------------------===//
//
// 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/lfind.h"
#include "test/UnitTest/Test.h"

int compar(void *a, void *b) {
return *reinterpret_cast<int *>(a) - *reinterpret_cast<int *>(b);
}

TEST(LlvmLibcLfindTest, SearchHead) {
int list[3] = {1, 2, 3};
size_t len = 3;
int key = 1;
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
ASSERT_TRUE(ret == &list[0]);
}

TEST(LlvmLibcLfindTest, SearchMiddle) {
int list[3] = {1, 2, 3};
size_t len = 3;
int key = 2;
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
ASSERT_TRUE(ret == &list[1]);
}

TEST(LlvmLibcLfindTest, SearchTail) {
int list[3] = {1, 2, 3};
size_t len = 3;
int key = 3;
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
ASSERT_TRUE(ret == &list[2]);
}

TEST(LlvmLibcLfindTest, SearchNonExistent) {
int list[3] = {1, 2, 3};
size_t len = 3;
int key = 5;
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
ASSERT_TRUE(ret == nullptr);
}
Loading