mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 18:16:42 +00:00
[libc] Implement search/lsearch
(#131431)
ref: - https://man7.org/linux/man-pages/man3/lsearch.3.html - https://pubs.opengroup.org/onlinepubs/009696699/functions/lsearch.html
This commit is contained in:
parent
9ed772cecc
commit
af7c8c475a
@ -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
|
||||
|
@ -943,6 +943,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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.
|
||||
|
39
libc/src/search/lsearch.cpp
Normal file
39
libc/src/search/lsearch.cpp
Normal file
@ -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
|
20
libc/src/search/lsearch.h
Normal file
20
libc/src/search/lsearch.h
Normal file
@ -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
|
@ -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
|
||||
)
|
||||
|
66
libc/test/src/search/lsearch_test.cpp
Normal file
66
libc/test/src/search/lsearch_test.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
//===-- 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);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcLsearchTest, SearchExceptional) {
|
||||
int list[3] = {1, 2, 3};
|
||||
size_t len = 3;
|
||||
size_t max_len = ~0;
|
||||
int key = 3;
|
||||
|
||||
ASSERT_EQ(LIBC_NAMESPACE::lsearch(nullptr, list, &len, sizeof(int), compar),
|
||||
nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, nullptr, &len, sizeof(int), compar),
|
||||
nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, nullptr, sizeof(int), compar),
|
||||
nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, &max_len, sizeof(int), compar),
|
||||
nullptr);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), nullptr),
|
||||
nullptr);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user