author | Olivier Brunel
<jjk@jjacky.com> 2023-03-24 13:31:21 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-03-26 14:03:02 UTC |
parent | 4ec170d24cca368e9e2380ed68a6a6c8e714c7cf |
doc/byte_get_match_full.3.md | +72 | -0 |
doc/bytestr.h.0.md | +6 | -0 |
include/limb/bytestr.h | +4 | -0 |
meta/libs/limb | +2 | -0 |
src/byte_get_match.c | +10 | -0 |
src/byte_get_match_full.c | +32 | -0 |
diff --git a/doc/byte_get_match_full.3.md b/doc/byte_get_match_full.3.md new file mode 100644 index 0000000..7db9f43 --- /dev/null +++ b/doc/byte_get_match_full.3.md @@ -0,0 +1,72 @@ +% limb manual +% byte_get_match_full(3) + +# NAME + +byte\_get\_match\_full, byte\_get\_match - find the (partial) match of a given +string in an array + +# SYNOPSIS + + #include <limb/bytestr.h> + +```pre hl +int byte_get_match_full(int *<em>first</em>, const char *<em>str</em>, size_t <em>slen</em>, + const void *<em>list</em>, size_t <em>offset</em>, size_t <em>llen</em>) +int byte_get_match(int *<em>first</em>, const char *<em>str</em>, size_t <em>slen</em>, const char **<em>list</em>) +``` + +# DESCRIPTION + +The `byte_get_match_full`() function looks inside the array `list` for a string +matching `str` of length `slen`. + +Each element of the array `list` must by `llen` bytes long, and must contain, +at byte `offset` (starting from 0), a pointer to a NUL-terminated string to +check against. + +An element is said to match if its `slen` first bytes are the same as those from +`str`. In case of an /exact match/, that is the element's NUL-terminated string +is of length `slen`, the search ends and the function returns. + +If the element's string is longer however, the search continues through the +remaining elements in `list`. No other elements shall match for a success. +Otherwise -1 is returned, and if `first` is not NULL the value it points to is +set to the index of the first-matching element. + +The search goes on until an exact match is found, or an element is found with a +string pointer that is NULL. + +! INFO: +! - Elements in `list` need not to be ordered. +! - `first` is not changed if there are no matches. To distinguish between no +! matches and more than one, it should be initialized to e.g. -1 prior to +! calling `byte_get_match_full`(). + +The `byte_get_match`() function is similar, but simply takes `list` as a NULL +terminated array of NUL-terminated string pointers. + +# RETURN VALUE + +These functions return the index of the matching element in `list`, or -1 if +either no element matched `str`, or more than one did. In the later case, if +`first` was not NULL the value it points to is set to the index of the +first-matching element. + +# EXAMPLE + +Usually you'll probably want to use `byte_get_match`() with a NULL terminated +array of strings. + +An example of use for `byte_get_match_full`() would be when the strings are +members of a structure, e.g: + +```c +struct user { + int id; + const char *name; +} users[]; + +int r = byte_get_match_full(&first, name, strlen(name), users, + offsetof(struct user, name), sizeof(*users)); +``` diff --git a/doc/bytestr.h.0.md b/doc/bytestr.h.0.md index ddb7b2f..ff36a60 100644 --- a/doc/bytestr.h.0.md +++ b/doc/bytestr.h.0.md @@ -21,5 +21,11 @@ This header defines functions to work with byte arrays and/or strings. The following functions are defined : +: [byte_get_match_full](3) +:: Find the (partial) match of a given string in an array + +: [byte_get_match](3) +:: Find the (partial) match of a given string in an array of strings + : [byte_str](3) :: To locate a substring within a string diff --git a/include/limb/bytestr.h b/include/limb/bytestr.h index 3ab983b..bc59b28 100644 --- a/include/limb/bytestr.h +++ b/include/limb/bytestr.h @@ -8,4 +8,8 @@ extern size_t byte_str(const char *haystack, size_t hlen, const char *needle, size_t nlen); +extern int byte_get_match_full(int *first, const char *str, size_t slen, + const void *list_, size_t offset, size_t llen); +extern int byte_get_match(int *first, const char *str, size_t slen, const char **list); + #endif /* LIMB_BYTESTR_H */ diff --git a/meta/libs/limb b/meta/libs/limb index ec05868..6929e1a 100644 --- a/meta/libs/limb +++ b/meta/libs/limb @@ -21,6 +21,8 @@ obj/sacoloff.o obj/saoff2ptr.o obj/sacolptr.o # bytestr.h +obj/byte_get_match_full.o +obj/byte_get_match.o obj/byte_str.o # buffer.h obj/buffer_putescall.o diff --git a/src/byte_get_match.c b/src/byte_get_match.c new file mode 100644 index 0000000..3c3209c --- /dev/null +++ b/src/byte_get_match.c @@ -0,0 +1,10 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include "limb/bytestr.h" + +int +byte_get_match(int *first, const char *str, size_t slen, const char **list) +{ + return byte_get_match_full(first, str, slen, list, 0, sizeof(*list)); +} diff --git a/src/byte_get_match_full.c b/src/byte_get_match_full.c new file mode 100644 index 0000000..049c5eb --- /dev/null +++ b/src/byte_get_match_full.c @@ -0,0 +1,32 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include "limb/bytestr.h" + +int +byte_get_match_full(int *first, const char *str, size_t slen, + const void *list_, size_t offset, size_t llen) +{ + const char *list = list_; + int i, m; + + for (i = 0, m = -1; ; list += llen, ++i) { + const char *el = * (const char **) (list + offset); + if (!el) break; + /* str matches an element */ + if (!strncmp(el, str, slen)) { + /* exact match? */ + if (strlen(el) == slen) return i; + + if (m < 0) { + /* first partial match */ + if (first) *first = i; + m = i; + } else { + /* more than one match */ + return -1; + } + } + } + return m; +}