diff options
Diffstat (limited to 'src/lib/libc')
| -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); | ||
