Change in libosmocore[master]: utils: add osmo_strnchr()

2019-11-24 Thread neels
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 
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge 
Gerrit-Reviewer: neels 
Gerrit-MessageType: merged


Change in libosmocore[master]: utils: add osmo_strnchr()

2019-11-22 Thread laforge
laforge has posted comments on this change. ( 
https://gerrit.osmocom.org/c/libosmocore/+/16166 )

Change subject: utils: add osmo_strnchr()
..


Patch Set 2: Code-Review+2


--
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: 2
Gerrit-Owner: neels 
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge 
Gerrit-Comment-Date: Fri, 22 Nov 2019 12:33:17 +
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment


Change in libosmocore[master]: utils: add osmo_strnchr()

2019-11-21 Thread neels
neels has uploaded this change for review. ( 
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(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/66/16166/1

diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index 4e7037a..01c4de6 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 4e55a89..038288c 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 458458e..e87cb22 100644
--- a/tests/utils/utils_test.c
+++ b/tests/utils/utils_test.c
@@ -1317,6 +1317,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 = {};
@@ -1341,5 +1374,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 bd43365..baa708e 100644
--- a/tests/utils/utils_test.ok
+++ b/tests/utils/utils_test.ok
@@ -475,3 +475,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: 1
Gerrit-Owner: neels 
Gerrit-MessageType: newchange