Skip to content

Commit af7c8c4

Browse files
authored
1 parent 9ed772c commit af7c8c4

File tree

10 files changed

+162
-1
lines changed

10 files changed

+162
-1
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,7 @@ if(LLVM_LIBC_FULL_BUILD)
999999
libc.src.search.hsearch_r
10001000
libc.src.search.insque
10011001
libc.src.search.lfind
1002+
libc.src.search.lsearch
10021003
libc.src.search.remque
10031004

10041005
# threads.h entrypoints

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ if(LLVM_LIBC_FULL_BUILD)
943943
libc.src.search.hsearch_r
944944
libc.src.search.insque
945945
libc.src.search.lfind
946+
libc.src.search.lsearch
946947
libc.src.search.remque
947948

948949
# threads.h entrypoints

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ if(LLVM_LIBC_FULL_BUILD)
11131113
libc.src.search.hsearch_r
11141114
libc.src.search.insque
11151115
libc.src.search.lfind
1116+
libc.src.search.lsearch
11161117
libc.src.search.remque
11171118

11181119
# threads.h entrypoints

libc/include/search.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,13 @@ functions:
6969
- type: size_t *
7070
- type: size_t
7171
- type: __lsearchcompare_t
72+
- name: lsearch
73+
standards:
74+
- POSIX
75+
return_type: void *
76+
arguments:
77+
- type: const void *
78+
- type: void *
79+
- type: size_t *
80+
- type: size_t
81+
- type: __lsearchcompare_t

libc/src/search/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,16 @@ add_entrypoint_object(
110110
libc.src.__support.CPP.cstddef
111111
libc.src.__support.memory_size
112112
)
113+
114+
add_entrypoint_object(
115+
lsearch
116+
SRCS
117+
lsearch.cpp
118+
HDRS
119+
lsearch.h
120+
DEPENDS
121+
libc.include.search
122+
libc.src.__support.CPP.cstddef
123+
libc.src.__support.memory_size
124+
libc.src.string.memory_utils.inline_memcpy
125+
)

libc/src/search/lfind.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===-- Implementation of lfind -------------------------------*- C++ -*-===//
1+
//===-- Implementation of lfind ---------------------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.

libc/src/search/lsearch.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- Implementation of lsearch -------------------------------*- 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/lsearch.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+
#include "src/string/memory_utils/inline_memcpy.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
LLVM_LIBC_FUNCTION(void *, lsearch,
18+
(const void *key, void *base, size_t *nmemb, size_t size,
19+
int (*compar)(const void *, const void *))) {
20+
if (key == nullptr || base == nullptr || nmemb == nullptr ||
21+
compar == nullptr)
22+
return nullptr;
23+
24+
size_t byte_len = 0;
25+
if (internal::mul_overflow(*nmemb, size, &byte_len))
26+
return nullptr;
27+
28+
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
29+
const cpp::byte *end = next + byte_len;
30+
for (; next < end; next += size)
31+
if (compar(key, next) == 0)
32+
return const_cast<cpp::byte *>(next);
33+
34+
*nmemb += 1;
35+
inline_memcpy(const_cast<cpp::byte *>(end), key, size);
36+
return const_cast<cpp::byte *>(end);
37+
}
38+
39+
} // namespace LIBC_NAMESPACE_DECL

libc/src/search/lsearch.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for lsearch -----------------------*- 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_LSEARCH_H
10+
#define LLVM_LIBC_SRC_SEARCH_LSEARCH_H
11+
12+
#include "src/__support/macros/config.h"
13+
#include <stddef.h> // size_t
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
void *lsearch(const void *key, 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_LSEARCH_H

libc/test/src/search/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@ add_libc_unittest(
3535
DEPENDS
3636
libc.src.search.lfind
3737
)
38+
39+
add_libc_unittest(
40+
lsearch_test
41+
SUITE
42+
libc_search_unittests
43+
SRCS
44+
lsearch_test.cpp
45+
DEPENDS
46+
libc.src.search.lsearch
47+
)

libc/test/src/search/lsearch_test.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- Unittests for lsearch ---------------------------------------------===//
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/lsearch.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(LlvmLibcLsearchTest, SearchHead) {
17+
int list[3] = {1, 2, 3};
18+
size_t len = 3;
19+
int key = 1;
20+
void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
21+
ASSERT_TRUE(ret == &list[0]);
22+
}
23+
24+
TEST(LlvmLibcLsearchTest, SearchMiddle) {
25+
int list[3] = {1, 2, 3};
26+
size_t len = 3;
27+
int key = 2;
28+
void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
29+
ASSERT_TRUE(ret == &list[1]);
30+
}
31+
32+
TEST(LlvmLibcLsearchTest, SearchTail) {
33+
int list[3] = {1, 2, 3};
34+
size_t len = 3;
35+
int key = 3;
36+
void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
37+
ASSERT_TRUE(ret == &list[2]);
38+
}
39+
40+
TEST(LlvmLibcLsearchTest, SearchNonExistent) {
41+
int list[4] = {1, 2, 3, 0};
42+
size_t len = 3;
43+
int key = 4;
44+
void *ret = LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), compar);
45+
ASSERT_TRUE(ret == &list[3]);
46+
ASSERT_EQ(key, list[3]);
47+
ASSERT_EQ(len, 4UL);
48+
}
49+
50+
TEST(LlvmLibcLsearchTest, SearchExceptional) {
51+
int list[3] = {1, 2, 3};
52+
size_t len = 3;
53+
size_t max_len = ~0;
54+
int key = 3;
55+
56+
ASSERT_EQ(LIBC_NAMESPACE::lsearch(nullptr, list, &len, sizeof(int), compar),
57+
nullptr);
58+
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, nullptr, &len, sizeof(int), compar),
59+
nullptr);
60+
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, nullptr, sizeof(int), compar),
61+
nullptr);
62+
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, &max_len, sizeof(int), compar),
63+
nullptr);
64+
ASSERT_EQ(LIBC_NAMESPACE::lsearch(&key, list, &len, sizeof(int), nullptr),
65+
nullptr);
66+
}

0 commit comments

Comments
 (0)