neels has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/16166 )
Change subject: utils: add osmo_strnchr() ...................................................................... utils: add osmo_strnchr() When finding a char in a string, I want to be able to limit the search area by size, not only by nul terminator. Change-Id: I48f8ace9f51f8a06796648883afcabe3b4e8b537 --- M include/osmocom/core/utils.h M src/utils.c M tests/utils/utils_test.c M tests/utils/utils_test.ok 4 files changed, 65 insertions(+), 0 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, approved diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 86d45bc..1abbe98 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -139,6 +139,7 @@ uint8_t *osmo_encode_big_endian(uint64_t value, size_t data_len); size_t osmo_strlcpy(char *dst, const char *src, size_t siz); +const char *osmo_strnchr(const char *str, size_t str_size, char c); bool osmo_is_hexstr(const char *str, int min_digits, int max_digits, bool require_even); diff --git a/src/utils.c b/src/utils.c index 4378431..c3e3efb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -525,6 +525,28 @@ return ret; } +/*! Find first occurence of a char in a size limited string. + * Like strchr() but with a buffer size limit. + * \param[in] str String buffer to examine. + * \param[in] str_size sizeof(str). + * \param[in] c Character to look for. + * \return Pointer to the matched char, or NULL if not found. + */ +const char *osmo_strnchr(const char *str, size_t str_size, char c) +{ + const char *end = str + str_size; + const char *pos; + if (!str) + return NULL; + for (pos = str; pos < end; pos++) { + if (c == *pos) + return pos; + if (!*pos) + return NULL; + } + return NULL; +} + /*! Validate that a given string is a hex string within given size limits. * Note that each hex digit amounts to a nibble, so if checking for a hex * string to result in N bytes, pass amount of digits as 2*N. diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index 69510af..a79b8ed 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -1191,6 +1191,39 @@ } } +static void osmo_strnchr_test(void) +{ + struct test { + const char *haystack; + size_t haystack_len; + const char *needle; + int expect_offset; + }; + struct test tests[] = { + { "foo=bar", 8, "=", 3 }, + { "foo=bar", 4, "=", 3 }, + { "foo=bar", 3, "=", -1 }, + { "foo=bar", 0, "=", -1 }, + { "foo\0=bar", 9, "=", -1 }, + { "foo\0=bar", 9, "\0", 3 }, + }; + struct test *t; + printf("\n%s()\n", __func__); + for (t = tests; t - tests < ARRAY_SIZE(tests); t++) { + const char *r = osmo_strnchr(t->haystack, t->haystack_len, t->needle[0]); + int offset = -1; + if (r) + offset = r - t->haystack; + printf("osmo_strnchr(%s, %zu, ", + osmo_quote_str(t->haystack, -1), t->haystack_len); + printf("'%s') -> %d", + osmo_escape_str(t->needle, 1), offset); + if (offset != t->expect_offset) + printf(" ERROR expected %d", t->expect_offset); + printf("\n"); + } +} + int main(int argc, char **argv) { static const struct log_info log_info = {}; @@ -1213,5 +1246,6 @@ startswith_test(); name_c_impl_test(); osmo_print_n_test(); + osmo_strnchr_test(); return 0; } diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index d5cf491..89e0fed 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -403,3 +403,11 @@ NULL token_len=10 buf_size=0 -> token="unchanged" rc=0 "" token_len=10 buf_size=0 -> token="unchanged" rc=0 "foo=bar" token_len=0 buf_size=0 -> token="unchanged" rc=0 + +osmo_strnchr_test() +osmo_strnchr("foo=bar", 8, '=') -> 3 +osmo_strnchr("foo=bar", 4, '=') -> 3 +osmo_strnchr("foo=bar", 3, '=') -> -1 +osmo_strnchr("foo=bar", 0, '=') -> -1 +osmo_strnchr("foo", 9, '=') -> -1 +osmo_strnchr("foo", 9, '\0') -> 3 -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/16166 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I48f8ace9f51f8a06796648883afcabe3b4e8b537 Gerrit-Change-Number: 16166 Gerrit-PatchSet: 3 Gerrit-Owner: neels <nhofm...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: neels <nhofm...@sysmocom.de> Gerrit-MessageType: merged