Skip to content

Commit 396ed9c

Browse files
authoredNov 11, 2024··
[libc][search] implement posix lfind function (#114692)
# Changes - Implement the POSIX [`lfind`](https://man7.org/linux/man-pages/man3/lsearch.3.html) function. - Put a checkmark in the [posix support table docs](https://libc.llvm.org/libc_search.html) next to `lfind`.
1 parent 9d4837f commit 396ed9c

File tree

20 files changed

+186
-1
lines changed

20 files changed

+186
-1
lines changed
 

‎libc/config/baremetal/arm/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
2626
# errno.h entrypoints
2727
libc.src.errno.errno
2828

29+
# search.h entrypoints
30+
libc.src.search.lfind
31+
2932
# setjmp.h entrypoints
3033
libc.src.setjmp.longjmp
3134
libc.src.setjmp.setjmp

‎libc/config/baremetal/riscv/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
2626
# errno.h entrypoints
2727
libc.src.errno.errno
2828

29+
# search.h entrypoints
30+
libc.src.search.lfind
31+
2932
# string.h entrypoints
3033
libc.src.string.bcmp
3134
libc.src.string.bcopy

‎libc/config/darwin/arm/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
2020
# errno.h entrypoints
2121
libc.src.errno.errno
2222

23+
# search.h entrypoints
24+
libc.src.search.lfind
25+
2326
# string.h entrypoints
2427
libc.src.string.bcmp
2528
libc.src.string.bcopy

‎libc/config/darwin/x86_64/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
1717
libc.src.ctype.tolower
1818
libc.src.ctype.toupper
1919

20+
# search.h entrypoints
21+
libc.src.search.lfind
22+
2023
# string.h entrypoints
2124
libc.src.string.bcmp
2225
libc.src.string.bzero

‎libc/config/linux/aarch64/entrypoints.txt

+1
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ if(LLVM_LIBC_FULL_BUILD)
960960
libc.src.search.hsearch
961961
libc.src.search.hsearch_r
962962
libc.src.search.insque
963+
libc.src.search.lfind
963964
libc.src.search.remque
964965

965966
# threads.h entrypoints

‎libc/config/linux/arm/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
2020
# errno.h entrypoints
2121
libc.src.errno.errno
2222

23+
# search.h entrypoints
24+
libc.src.search.lfind
25+
2326
# string.h entrypoints
2427
libc.src.string.bcmp
2528
libc.src.string.bcopy

‎libc/config/linux/riscv/entrypoints.txt

+1
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ if(LLVM_LIBC_FULL_BUILD)
885885
libc.src.search.hsearch
886886
libc.src.search.hsearch_r
887887
libc.src.search.insque
888+
libc.src.search.lfind
888889
libc.src.search.remque
889890

890891
# threads.h entrypoints

‎libc/config/linux/x86_64/entrypoints.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,7 @@ if(LLVM_LIBC_FULL_BUILD)
10251025
libc.src.search.hsearch
10261026
libc.src.search.hsearch_r
10271027
libc.src.search.insque
1028+
libc.src.search.lfind
10281029
libc.src.search.remque
10291030

10301031
# threads.h entrypoints

‎libc/config/windows/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
1717
libc.src.ctype.tolower
1818
libc.src.ctype.toupper
1919

20+
# search.h entrypoints
21+
libc.src.search.lfind
22+
2023
# string.h entrypoints
2124
libc.src.string.bcmp
2225
libc.src.string.bcopy

‎libc/docs/libc_search.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ hcreate |check|
4242
hdestroy |check|
4343
hsearch |check|
4444
insque |check|
45-
lfind
45+
lfind |check|
4646
lsearch
4747
remque |check|
4848
tdelete

‎libc/include/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ add_header_macro(
254254
.llvm-libc-types.ENTRY
255255
.llvm-libc-types.struct_hsearch_data
256256
.llvm-libc-types.size_t
257+
.llvm-libc-types.__lsearchcompare_t
257258
)
258259

259260
add_header_macro(

‎libc/include/llvm-libc-types/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_header(size_t HDR size_t.h)
33
add_header(ssize_t HDR ssize_t.h)
44
add_header(__atfork_callback_t HDR __atfork_callback_t.h)
55
add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
6+
add_header(__lsearchcompare_t HDR __lsearchcompare_t.h)
67
add_header(__call_once_func_t HDR __call_once_func_t.h)
78
add_header(__exec_argv_t HDR __exec_argv_t.h)
89
add_header(__exec_envp_t HDR __exec_envp_t.h)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===-- Definition of type __lsearchcompare_t -----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
10+
#define LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
11+
12+
typedef int (*__lsearchcompare_t)(const void *, const void *);
13+
14+
#endif // LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H

‎libc/newhdrgen/yaml/search.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ types:
44
- type_name: struct_hsearch_data
55
- type_name: ENTRY
66
- type_name: ACTION
7+
- type_name: __lsearchcompare_t
78
enums: []
89
objects: []
910
functions:
@@ -57,3 +58,13 @@ functions:
5758
return_type: void
5859
arguments:
5960
- type: void *
61+
- name: lfind
62+
standards:
63+
- POSIX
64+
return_type: void *
65+
arguments:
66+
- type: const void *
67+
- type: const void *
68+
- type: size_t *
69+
- type: size_t
70+
- type: __lsearchcompare_t

‎libc/spec/posix.td

+14
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ def StructStatvfs : NamedType<"struct statvfs">;
100100
def StructStatvfsPtr : PtrType<StructStatvfs>;
101101
def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>;
102102

103+
// The function pointer type for the predicate for lsearch, lfind
104+
def LSearchCompareT : NamedType<"__lsearchcompare_t">;
105+
103106
def POSIX : StandardSpec<"POSIX"> {
104107
PtrType CharPtr = PtrType<CharType>;
105108
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -1618,6 +1621,17 @@ def POSIX : StandardSpec<"POSIX"> {
16181621
ArgSpec<VoidPtr>
16191622
]
16201623
>,
1624+
FunctionSpec<
1625+
"lfind",
1626+
RetValSpec<VoidPtr>,
1627+
[
1628+
ArgSpec<ConstVoidPtr>,
1629+
ArgSpec<ConstVoidPtr>,
1630+
ArgSpec<SizeTPtr>,
1631+
ArgSpec<SizeTType>,
1632+
ArgSpec<LSearchCompareT>
1633+
]
1634+
>
16211635
]
16221636
>;
16231637

‎libc/src/search/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,15 @@ add_entrypoint_object(
9898
libc.include.search
9999
libc.src.__support.intrusive_list
100100
)
101+
102+
add_entrypoint_object(
103+
lfind
104+
SRCS
105+
lfind.cpp
106+
HDRS
107+
lfind.h
108+
DEPENDS
109+
libc.include.search
110+
libc.src.__support.CPP.cstddef
111+
libc.src.__support.memory_size
112+
)

‎libc/src/search/lfind.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===-- Implementation of lfind -------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/search/lfind.h"
10+
#include "src/__support/CPP/cstddef.h" // cpp::byte
11+
#include "src/__support/common.h"
12+
#include "src/__support/macros/config.h"
13+
#include "src/__support/memory_size.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
LLVM_LIBC_FUNCTION(void *, lfind,
17+
(const void *key, const void *base, size_t *nmemb,
18+
size_t size, int (*compar)(const void *, const void *))) {
19+
if (key == nullptr || base == nullptr || nmemb == nullptr ||
20+
compar == nullptr)
21+
return nullptr;
22+
23+
size_t byte_len = 0;
24+
if (internal::mul_overflow(*nmemb, size, &byte_len))
25+
return nullptr;
26+
27+
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
28+
const cpp::byte *end = next + byte_len;
29+
for (; next < end; next += size)
30+
if (compar(key, next) == 0)
31+
return const_cast<cpp::byte *>(next);
32+
return nullptr;
33+
}
34+
35+
} // namespace LIBC_NAMESPACE_DECL

‎libc/src/search/lfind.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for lfind -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SEARCH_LFIND_H
10+
#define LLVM_LIBC_SRC_SEARCH_LFIND_H
11+
12+
#include "src/__support/macros/config.h"
13+
#include <stddef.h> // size_t
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
void *lfind(const void *key, const void *base, size_t *nmemb, size_t size,
17+
int (*compar)(const void *, const void *));
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_SEARCH_LFIND_H

‎libc/test/src/search/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,13 @@ add_libc_unittest(
2525
libc.src.search.insque
2626
libc.src.search.remque
2727
)
28+
29+
add_libc_unittest(
30+
lfind_test
31+
SUITE
32+
libc_search_unittests
33+
SRCS
34+
lfind_test.cpp
35+
DEPENDS
36+
libc.src.search.lfind
37+
)

‎libc/test/src/search/lfind_test.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===-- Unittests for lfind -----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/search/lfind.h"
10+
#include "test/UnitTest/Test.h"
11+
12+
int compar(const void *a, const void *b) {
13+
return *reinterpret_cast<const int *>(a) != *reinterpret_cast<const int *>(b);
14+
}
15+
16+
TEST(LlvmLibcLfindTest, SearchHead) {
17+
int list[3] = {1, 2, 3};
18+
size_t len = 3;
19+
int key = 1;
20+
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
21+
ASSERT_TRUE(ret == &list[0]);
22+
}
23+
24+
TEST(LlvmLibcLfindTest, SearchMiddle) {
25+
int list[3] = {1, 2, 3};
26+
size_t len = 3;
27+
int key = 2;
28+
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
29+
ASSERT_TRUE(ret == &list[1]);
30+
}
31+
32+
TEST(LlvmLibcLfindTest, SearchTail) {
33+
int list[3] = {1, 2, 3};
34+
size_t len = 3;
35+
int key = 3;
36+
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
37+
ASSERT_TRUE(ret == &list[2]);
38+
}
39+
40+
TEST(LlvmLibcLfindTest, SearchNonExistent) {
41+
int list[3] = {1, 2, 3};
42+
size_t len = 3;
43+
int key = 5;
44+
void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
45+
ASSERT_TRUE(ret == nullptr);
46+
}

0 commit comments

Comments
 (0)
Please sign in to comment.