diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/lsearch.c | 45 |
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 | ||
39 | typedef int (*cmp_fn_t)(const void *, const void *); | 39 | typedef int (*cmp_fn_t)(const void *, const void *); |
40 | static void *linear_base(const void *, const void *, size_t *, size_t, | ||
41 | cmp_fn_t, int); | ||
42 | 40 | ||
43 | void * | 41 | void * |
44 | lsearch(const void *key, void *base, size_t *nelp, size_t width, | 42 | lsearch(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 | ||
51 | void * | 58 | void * |
52 | lfind(const void *key, const void *base, size_t *nelp, size_t width, | 59 | lfind(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 | |||
58 | static void * | ||
59 | linear_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 | } |
70 | DEF_WEAK(lfind); | ||