<p>neels <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/16166">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: add osmo_strnchr()<br><br>When finding a char in a string, I want to be able to limit the search area by<br>size, not only by nul terminator.<br><br>Change-Id: I48f8ace9f51f8a06796648883afcabe3b4e8b537<br>---<br>M include/osmocom/core/utils.h<br>M src/utils.c<br>M tests/utils/utils_test.c<br>M tests/utils/utils_test.ok<br>4 files changed, 65 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h</span><br><span>index 86d45bc..1abbe98 100644</span><br><span>--- a/include/osmocom/core/utils.h</span><br><span>+++ b/include/osmocom/core/utils.h</span><br><span>@@ -139,6 +139,7 @@</span><br><span> uint8_t *osmo_encode_big_endian(uint64_t value, size_t data_len);</span><br><span> </span><br><span> size_t osmo_strlcpy(char *dst, const char *src, size_t siz);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_strnchr(const char *str, size_t str_size, char c);</span><br><span> </span><br><span> bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,</span><br><span>                     bool require_even);</span><br><span>diff --git a/src/utils.c b/src/utils.c</span><br><span>index 4378431..c3e3efb 100644</span><br><span>--- a/src/utils.c</span><br><span>+++ b/src/utils.c</span><br><span>@@ -525,6 +525,28 @@</span><br><span>      return ret;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find first occurence of a char in a size limited string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Like strchr() but with a buffer size limit.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  String buffer to examine.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str_size  sizeof(str).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] c  Character to look for.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Pointer to the matched char, or NULL if not found.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_strnchr(const char *str, size_t str_size, char c)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *end = str + str_size;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *pos;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  for (pos = str; pos < end; pos++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (c == *pos)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return pos;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!*pos)</span><br><span style="color: hsl(120, 100%, 40%);">+                    return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Validate that a given string is a hex string within given size limits.</span><br><span>  * Note that each hex digit amounts to a nibble, so if checking for a hex</span><br><span>  * string to result in N bytes, pass amount of digits as 2*N.</span><br><span>diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c</span><br><span>index 69510af..a79b8ed 100644</span><br><span>--- a/tests/utils/utils_test.c</span><br><span>+++ b/tests/utils/utils_test.c</span><br><span>@@ -1191,6 +1191,39 @@</span><br><span>  }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_strnchr_test(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct test {</span><br><span style="color: hsl(120, 100%, 40%);">+         const char *haystack;</span><br><span style="color: hsl(120, 100%, 40%);">+         size_t haystack_len;</span><br><span style="color: hsl(120, 100%, 40%);">+          const char *needle;</span><br><span style="color: hsl(120, 100%, 40%);">+           int expect_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct test tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               { "foo=bar", 8, "=", 3 },</span><br><span style="color: hsl(120, 100%, 40%);">+         { "foo=bar", 4, "=", 3 },</span><br><span style="color: hsl(120, 100%, 40%);">+         { "foo=bar", 3, "=", -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+                { "foo=bar", 0, "=", -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+                { "foo\0=bar", 9, "=", -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+              { "foo\0=bar", 9, "\0", 3 },</span><br><span style="color: hsl(120, 100%, 40%);">+      };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct test *t;</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("\n%s()\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+       for (t = tests; t - tests < ARRAY_SIZE(tests); t++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              const char *r = osmo_strnchr(t->haystack, t->haystack_len, t->needle[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+            int offset = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (r)</span><br><span style="color: hsl(120, 100%, 40%);">+                        offset = r - t->haystack;</span><br><span style="color: hsl(120, 100%, 40%);">+          printf("osmo_strnchr(%s, %zu, ",</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_quote_str(t->haystack, -1), t->haystack_len);</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("'%s') -> %d",</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_escape_str(t->needle, 1), offset);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (offset != t->expect_offset)</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf(" ERROR expected %d", t->expect_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+          printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>       static const struct log_info log_info = {};</span><br><span>@@ -1213,5 +1246,6 @@</span><br><span>  startswith_test();</span><br><span>   name_c_impl_test();</span><br><span>  osmo_print_n_test();</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_strnchr_test();</span><br><span>         return 0;</span><br><span> }</span><br><span>diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok</span><br><span>index d5cf491..89e0fed 100644</span><br><span>--- a/tests/utils/utils_test.ok</span><br><span>+++ b/tests/utils/utils_test.ok</span><br><span>@@ -403,3 +403,11 @@</span><br><span> NULL token_len=10 buf_size=0 -> token="unchanged" rc=0</span><br><span> "" token_len=10 buf_size=0 -> token="unchanged" rc=0</span><br><span> "foo=bar" token_len=0 buf_size=0 -> token="unchanged" rc=0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr_test()</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo=bar", 8, '=') -> 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo=bar", 4, '=') -> 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo=bar", 3, '=') -> -1</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo=bar", 0, '=') -> -1</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo", 9, '=') -> -1</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_strnchr("foo", 9, '\0') -> 3</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/16166">change 16166</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/16166"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I48f8ace9f51f8a06796648883afcabe3b4e8b537 </div>
<div style="display:none"> Gerrit-Change-Number: 16166 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>