summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheloha <>2021-12-08 22:06:28 +0000
committercheloha <>2021-12-08 22:06:28 +0000
commit5165d5492b21787880fe5f1c83625ebf368f5859 (patch)
tree7062715ee531af2299c0238b27065eab446cf820
parentbc0dd110f81e03683e891dc84e5f213eb81e1750 (diff)
downloadopenbsd-5165d5492b21787880fe5f1c83625ebf368f5859.tar.gz
openbsd-5165d5492b21787880fe5f1c83625ebf368f5859.tar.bz2
openbsd-5165d5492b21787880fe5f1c83625ebf368f5859.zip
lsearch(3): reimplement using lfind(3)
lsearch(3) is really just lfind(3) with an additional branch to append the key if lfind(3) fails. If we get rid of the underlying linear_base() function and move the search portion into lfind(3) and the key-copying portion into lsearch(3) we get smaller and simpler code. Misc. notes: - We do not need to keep the historical comment about errno. lsearch(3) is pure computation and does not set errno. That's really all you need to know. The specification reserves no errors, either. - We are using lfind(3) internally now, so it switches from PROTO_DEPRECATED to PROTO_NORMAL in hidden/search.h and needs DEF_WEAK in stdlib/lsearch.c. With advice from guenther@ on symbol housekeeping in libc. Thread: https://marc.info/?l=openbsd-tech&m=163885187632449&w=2 ok millert@
-rw-r--r--src/lib/libc/stdlib/lsearch.c45
1 files changed, 13 insertions, 32 deletions
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
index 93e200e1bd..95ebf49b81 100644
--- a/src/lib/libc/stdlib/lsearch.c
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: lsearch.c,v 1.6 2021/12/07 04:01:45 cheloha Exp $ */ 1/* $OpenBSD: lsearch.c,v 1.7 2021/12/08 22:06:28 cheloha Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1989, 1993 4 * Copyright (c) 1989, 1993
@@ -37,53 +37,34 @@
37#include <search.h> 37#include <search.h>
38 38
39typedef int (*cmp_fn_t)(const void *, const void *); 39typedef int (*cmp_fn_t)(const void *, const void *);
40static void *linear_base(const void *, const void *, size_t *, size_t,
41 cmp_fn_t, int);
42 40
43void * 41void *
44lsearch(const void *key, void *base, size_t *nelp, size_t width, 42lsearch(const void *key, void *base, size_t *nelp, size_t width,
45 cmp_fn_t compar) 43 cmp_fn_t compar)
46{ 44{
45 void *element = lfind(key, base, nelp, width, compar);
47 46
48 return(linear_base(key, base, nelp, width, compar, 1)); 47 /*
48 * Use memmove(3) to ensure the key is copied cleanly into the
49 * array, even if the key overlaps with the end of the array.
50 */
51 if (element == NULL) {
52 element = memmove((char *)base + *nelp * width, key, width);
53 *nelp += 1;
54 }
55 return element;
49} 56}
50 57
51void * 58void *
52lfind(const void *key, const void *base, size_t *nelp, size_t width, 59lfind(const void *key, const void *base, size_t *nelp, size_t width,
53 cmp_fn_t compar) 60 cmp_fn_t compar)
54{ 61{
55 return(linear_base(key, base, nelp, width, compar, 0));
56}
57
58static void *
59linear_base(const void *key, const void *base, size_t *nelp, size_t width,
60 cmp_fn_t compar, int add_flag)
61{
62 const char *element, *end; 62 const char *element, *end;
63 63
64 end = (const char *)base + *nelp * width; 64 end = (const char *)base + *nelp * width;
65 for (element = base; element < end; element += width) 65 for (element = base; element < end; element += width)
66 if (!compar(key, element)) /* key found */ 66 if (!compar(key, element)) /* key found */
67 return((void *)element); 67 return((void *)element);
68 68 return NULL;
69 if (!add_flag) /* key not found */
70 return(NULL);
71
72 /*
73 * The UNIX System User's Manual, 1986 edition claims that
74 * a NULL pointer is returned by lsearch with errno set
75 * appropriately, if there is not enough room in the table
76 * to add a new item. This can't be done as none of these
77 * routines have any method of determining the size of the
78 * table. This comment isn't in the 1986-87 System V
79 * manual.
80 */
81 ++*nelp;
82
83 /*
84 * Use memmove(3) to ensure the key is copied cleanly into the
85 * array, even if the key overlaps with the end of the array.
86 */
87 memmove((void *)end, key, width);
88 return((void *)end);
89} 69}
70DEF_WEAK(lfind);