mirror of https://gerrit.osmocom.org/libosmocore
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
This commit is contained in:
parent
ff65d24ec4
commit
06356fd9c3
|
@ -139,6 +139,7 @@ uint64_t osmo_decode_big_endian(const uint8_t *data, size_t data_len);
|
|||
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);
|
||||
|
|
22
src/utils.c
22
src/utils.c
|
@ -525,6 +525,28 @@ size_t osmo_strlcpy(char *dst, const char *src, size_t siz)
|
|||
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.
|
||||
|
|
|
@ -1191,6 +1191,39 @@ static void osmo_print_n_test(void)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ int main(int argc, char **argv)
|
|||
startswith_test();
|
||||
name_c_impl_test();
|
||||
osmo_print_n_test();
|
||||
osmo_strnchr_test();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -403,3 +403,11 @@ NULL token_len=10 buf_size=1 -> token="" rc=0
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue