[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`.
This commit is contained in:
parent
9d4837f47c
commit
396ed9c2a1
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -960,6 +960,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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -885,6 +885,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
|
||||
|
||||
@ -1025,6 +1025,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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -42,7 +42,7 @@ hcreate |check|
|
||||
hdestroy |check|
|
||||
hsearch |check|
|
||||
insque |check|
|
||||
lfind
|
||||
lfind |check|
|
||||
lsearch
|
||||
remque |check|
|
||||
tdelete
|
||||
|
||||
@ -254,6 +254,7 @@ add_header_macro(
|
||||
.llvm-libc-types.ENTRY
|
||||
.llvm-libc-types.struct_hsearch_data
|
||||
.llvm-libc-types.size_t
|
||||
.llvm-libc-types.__lsearchcompare_t
|
||||
)
|
||||
|
||||
add_header_macro(
|
||||
|
||||
@ -3,6 +3,7 @@ add_header(size_t HDR size_t.h)
|
||||
add_header(ssize_t HDR ssize_t.h)
|
||||
add_header(__atfork_callback_t HDR __atfork_callback_t.h)
|
||||
add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
|
||||
add_header(__lsearchcompare_t HDR __lsearchcompare_t.h)
|
||||
add_header(__call_once_func_t HDR __call_once_func_t.h)
|
||||
add_header(__exec_argv_t HDR __exec_argv_t.h)
|
||||
add_header(__exec_envp_t HDR __exec_envp_t.h)
|
||||
|
||||
14
libc/include/llvm-libc-types/__lsearchcompare_t.h
Normal file
14
libc/include/llvm-libc-types/__lsearchcompare_t.h
Normal file
@ -0,0 +1,14 @@
|
||||
//===-- Definition of type __lsearchcompare_t -----------------------------===//
|
||||
//
|
||||
// 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_TYPES___LSEARCHCOMPARE_T_H
|
||||
#define LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
|
||||
|
||||
typedef int (*__lsearchcompare_t)(const void *, const void *);
|
||||
|
||||
#endif // LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
|
||||
@ -4,6 +4,7 @@ types:
|
||||
- type_name: struct_hsearch_data
|
||||
- type_name: ENTRY
|
||||
- type_name: ACTION
|
||||
- type_name: __lsearchcompare_t
|
||||
enums: []
|
||||
objects: []
|
||||
functions:
|
||||
@ -57,3 +58,13 @@ functions:
|
||||
return_type: void
|
||||
arguments:
|
||||
- type: void *
|
||||
- name: lfind
|
||||
standards:
|
||||
- POSIX
|
||||
return_type: void *
|
||||
arguments:
|
||||
- type: const void *
|
||||
- type: const void *
|
||||
- type: size_t *
|
||||
- type: size_t
|
||||
- type: __lsearchcompare_t
|
||||
|
||||
@ -100,6 +100,9 @@ def StructStatvfs : NamedType<"struct statvfs">;
|
||||
def StructStatvfsPtr : PtrType<StructStatvfs>;
|
||||
def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>;
|
||||
|
||||
// The function pointer type for the predicate for lsearch, lfind
|
||||
def LSearchCompareT : NamedType<"__lsearchcompare_t">;
|
||||
|
||||
def POSIX : StandardSpec<"POSIX"> {
|
||||
PtrType CharPtr = PtrType<CharType>;
|
||||
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
|
||||
@ -1618,6 +1621,17 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||
ArgSpec<VoidPtr>
|
||||
]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"lfind",
|
||||
RetValSpec<VoidPtr>,
|
||||
[
|
||||
ArgSpec<ConstVoidPtr>,
|
||||
ArgSpec<ConstVoidPtr>,
|
||||
ArgSpec<SizeTPtr>,
|
||||
ArgSpec<SizeTType>,
|
||||
ArgSpec<LSearchCompareT>
|
||||
]
|
||||
>
|
||||
]
|
||||
>;
|
||||
|
||||
|
||||
@ -98,3 +98,15 @@ 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
|
||||
libc.src.__support.memory_size
|
||||
)
|
||||
|
||||
35
libc/src/search/lfind.cpp
Normal file
35
libc/src/search/lfind.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
//===-- 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"
|
||||
#include "src/__support/memory_size.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
LLVM_LIBC_FUNCTION(void *, lfind,
|
||||
(const void *key, const 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);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
20
libc/src/search/lfind.h
Normal file
20
libc/src/search/lfind.h
Normal file
@ -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 <stddef.h> // size_t
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
void *lfind(const void *key, const void *base, size_t *nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *));
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SEARCH_LFIND_H
|
||||
@ -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
libc/test/src/search/lfind_test.cpp
Normal file
46
libc/test/src/search/lfind_test.cpp
Normal file
@ -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(const void *a, const void *b) {
|
||||
return *reinterpret_cast<const int *>(a) != *reinterpret_cast<const 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…
x
Reference in New Issue
Block a user