<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10830">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_str_tolower() and _toupper() with test<br><br>We already have osmo_str2lower() and osmo_str2upper(), but these lack:<br>* proper destination buffer bounds checking,<br>* ability to call directly as printf() argument.<br><br>Deprecate osmo_str2upper() and osmo_str2lower() because of missing bounds<br>checking.<br><br>Introduce osmo_str_tolower_buf(), osmo_str_toupper_buf() to provide<br>bounds-safe conversion, also able to safely convert a buffer in-place.<br><br>Introduce osmo_str_tolower(), osmo_str_toupper() that call the above _buf()<br>equivalents using a static buffer[128] and returning the resulting string<br>directly, convenient for direct printing. Possibly truncated but always safe.<br><br>Add unit tests to utils_test.c.<br><br>Replace all libosmocore uses of now deprecated osmo_str2lower().<br><br>Naming: the ctype.h API is called tolower() and toupper(), so just prepend<br>'osmo_str_' and don't separate 'to_lower'.<br><br>Change-Id: Ib0ee1206b9f31d7ba25c31f8008119ac55440797<br>---<br>M include/osmocom/core/utils.h<br>M src/utils.c<br>M src/vty/logging_vty.c<br>M tests/utils/utils_test.c<br>M tests/utils/utils_test.ok<br>5 files changed, 333 insertions(+), 9 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 976d4a8..0b54c88 100644</span><br><span>--- a/include/osmocom/core/utils.h</span><br><span>+++ b/include/osmocom/core/utils.h</span><br><span>@@ -7,6 +7,7 @@</span><br><span> #include <osmocom/core/backtrace.h></span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/panic.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/defs.h></span><br><span> </span><br><span> /*! \defgroup utils General-purpose utility functions</span><br><span>  *  @{</span><br><span>@@ -57,8 +58,18 @@</span><br><span> </span><br><span> #define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1] __attribute__((__unused__));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void osmo_str2lower(char *out, const char *in);</span><br><span style="color: hsl(0, 100%, 40%);">-void osmo_str2upper(char *out, const char *in);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_str2lower(char *out, const char *in)</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_DEPRECATED("Use osmo_str_tolower() or osmo_str_tolower_buf() instead,"</span><br><span style="color: hsl(120, 100%, 40%);">+                 " to properly check target memory bounds");</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_str2upper(char *out, const char *in)</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_DEPRECATED("Use osmo_str_toupper() or osmo_str_toupper_buf() instead,"</span><br><span style="color: hsl(120, 100%, 40%);">+                 " to properly check target memory bounds");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_str_tolower(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_str_toupper(const char *src);</span><br><span> </span><br><span> #define OSMO_SNPRINTF_RET(ret, rem, offset, len)               \</span><br><span> do {                                                               \</span><br><span>diff --git a/src/utils.c b/src/utils.c</span><br><span>index 3f40f2e..e6adcf8 100644</span><br><span>--- a/src/utils.c</span><br><span>+++ b/src/utils.c</span><br><span>@@ -638,4 +638,90 @@</span><br><span>    return g0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Convert a string to lowercase, while checking buffer size boundaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters</span><br><span style="color: hsl(120, 100%, 40%);">+ * length as well as nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note: similar osmo_str2lower(), but safe to use for src strings of arbitrary length.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] dest  Target buffer to write lowercase string.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dest_len  Maximum buffer size of dest (e.g. sizeof(dest)).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] src  String to convert to lowercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (dest == src) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (dest_len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             dest[dest_len - 1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = strlen(dest);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (dest_len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return strlen(src);</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = osmo_strlcpy(dest, src, dest_len);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     for (; *dest; dest++)</span><br><span style="color: hsl(120, 100%, 40%);">+         *dest = tolower(*dest);</span><br><span style="color: hsl(120, 100%, 40%);">+       return rc;</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%);">+/*! Convert a string to lowercase, using a static buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The resulting string may be truncated if the internally used static buffer is shorter than src.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a</span><br><span style="color: hsl(120, 100%, 40%);">+ * terminating nul.</span><br><span style="color: hsl(120, 100%, 40%);">+ * See also osmo_str_tolower_buf().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  String to convert to lowercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Resulting lowercase string in a static buffer, always nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_str_tolower(const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      static char buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_tolower_buf(buf, sizeof(buf), src);</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</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%);">+/*! Convert a string to uppercase, while checking buffer size boundaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters</span><br><span style="color: hsl(120, 100%, 40%);">+ * length as well as nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note: similar osmo_str2upper(), but safe to use for src strings of arbitrary length.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] dest  Target buffer to write uppercase string.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dest_len  Maximum buffer size of dest (e.g. sizeof(dest)).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] src  String to convert to uppercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      size_t rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (dest == src) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (dest_len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             dest[dest_len - 1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = strlen(dest);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (dest_len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return strlen(src);</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = osmo_strlcpy(dest, src, dest_len);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     for (; *dest; dest++)</span><br><span style="color: hsl(120, 100%, 40%);">+         *dest = toupper(*dest);</span><br><span style="color: hsl(120, 100%, 40%);">+       return rc;</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%);">+/*! Convert a string to uppercase, using a static buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The resulting string may be truncated if the internally used static buffer is shorter than src.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a</span><br><span style="color: hsl(120, 100%, 40%);">+ * terminating nul.</span><br><span style="color: hsl(120, 100%, 40%);">+ * See also osmo_str_toupper_buf().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  String to convert to uppercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Resulting uppercase string in a static buffer, always nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_str_toupper(const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      static char buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_toupper_buf(buf, sizeof(buf), src);</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! @} */</span><br><span>diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c</span><br><span>index 8c8a332..7d97bb1 100644</span><br><span>--- a/src/vty/logging_vty.c</span><br><span>+++ b/src/vty/logging_vty.c</span><br><span>@@ -754,7 +754,6 @@</span><br><span> static int config_write_log_single(struct vty *vty, struct log_target *tgt)</span><br><span> {</span><br><span>     int i;</span><br><span style="color: hsl(0, 100%, 40%);">-  char level_lower[32];</span><br><span> </span><br><span>    switch (tgt->type) {</span><br><span>      case LOG_TGT_TYPE_VTY:</span><br><span>@@ -806,21 +805,19 @@</span><br><span>               VTY_NEWLINE);</span><br><span> </span><br><span>    /* stupid old osmo logging API uses uppercase strings... */</span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_str2lower(level_lower, log_level_str(tgt->loglevel));</span><br><span style="color: hsl(0, 100%, 40%);">-   vty_out(vty, "  logging level all %s%s", level_lower, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "  logging level all %s%s", osmo_str_tolower(log_level_str(tgt->loglevel)),</span><br><span style="color: hsl(120, 100%, 40%);">+         VTY_NEWLINE);</span><br><span> </span><br><span>    for (i = 0; i < osmo_log_info->num_cat; i++) {</span><br><span>                 const struct log_category *cat = &tgt->categories[i];</span><br><span style="color: hsl(0, 100%, 40%);">-            char cat_lower[32];</span><br><span> </span><br><span>              /* skip empty entries in the array */</span><br><span>                if (!osmo_log_info->cat[i].name)</span><br><span>                  continue;</span><br><span> </span><br><span>                /* stupid old osmo logging API uses uppercase strings... */</span><br><span style="color: hsl(0, 100%, 40%);">-             osmo_str2lower(cat_lower, osmo_log_info->cat[i].name+1);</span><br><span style="color: hsl(0, 100%, 40%);">-             osmo_str2lower(level_lower, log_level_str(cat->loglevel));</span><br><span style="color: hsl(0, 100%, 40%);">-           vty_out(vty, "  logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               vty_out(vty, "  logging level %s", osmo_str_tolower(osmo_log_info->cat[i].name+1));</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty, " %s%s", osmo_str_tolower(log_level_str(cat->loglevel)), VTY_NEWLINE);</span><br><span>     }</span><br><span> </span><br><span>        return 1;</span><br><span>diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c</span><br><span>index 2f1e87d..2bb1f9c 100644</span><br><span>--- a/tests/utils/utils_test.c</span><br><span>+++ b/tests/utils/utils_test.c</span><br><span>@@ -616,6 +616,189 @@</span><br><span>       }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_str_tolowupper_test_data {</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *in;</span><br><span style="color: hsl(120, 100%, 40%);">+       bool use_static_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t buflen;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *expect_lower;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *expect_upper;</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t expect_rc;</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t expect_rc_inplace;</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%);">+struct osmo_str_tolowupper_test_data osmo_str_tolowupper_tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .use_static_buf = true,</span><br><span style="color: hsl(120, 100%, 40%);">+               .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+               .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</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%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .buflen = 99,</span><br><span style="color: hsl(120, 100%, 40%);">+         .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+               .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+               .expect_rc = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc_inplace = 62,</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%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .buflen = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_lower = "Unset",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_upper = "Unset",</span><br><span style="color: hsl(120, 100%, 40%);">+            .expect_rc = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc_inplace = 0,</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%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .buflen = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_lower = "",</span><br><span style="color: hsl(120, 100%, 40%);">+         .expect_upper = "",</span><br><span style="color: hsl(120, 100%, 40%);">+         .expect_rc = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc_inplace = 0,</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%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .buflen = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+          .expect_lower = "a",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_upper = "A",</span><br><span style="color: hsl(120, 100%, 40%);">+                .expect_rc = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc_inplace = 1,</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%);">+             .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",</span><br><span style="color: hsl(120, 100%, 40%);">+         .buflen = 28,</span><br><span style="color: hsl(120, 100%, 40%);">+         .expect_lower = "abcdefghijklmnopqrstuvwxyza",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZA",</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+              .expect_rc_inplace = 27,</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_str_tolowupper_test()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        char buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+        bool ok = true;</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("\n%s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < ARRAY_SIZE(osmo_str_tolowupper_tests); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct osmo_str_tolowupper_test_data *d = &osmo_str_tolowupper_tests[i];</span><br><span style="color: hsl(120, 100%, 40%);">+          size_t rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *res;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* tolower */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (d->use_static_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   res = osmo_str_tolower(d->in);</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("osmo_str_tolower(%s)\n", osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("               = %s\n", osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_ASSERT(sizeof(buf) >= d->buflen);</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_strlcpy(buf, "Unset", sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+                    rc = osmo_str_tolower_buf(buf, d->buflen, d->in);</span><br><span style="color: hsl(120, 100%, 40%);">+                       res = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf("osmo_str_tolower_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("                   = %zu, %s\n", rc, osmo_quote_str(res, -1));</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%);">+           if (strcmp(res, d->expect_lower)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                             "       got %s\n", i, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("  expected %s\n", osmo_quote_str(d->expect_lower, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                  ok = false;</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%);">+           if (!d->use_static_buf && d->expect_rc != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                             "       got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                     ok = false;</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%);">+           /* tolower, in-place */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!d->use_static_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_strlcpy(buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  d->buflen ? d->in : "Unset",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+                    rc = osmo_str_tolower_buf(buf, d->buflen, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                    res = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf("osmo_str_tolower_buf(%zu, %s, in-place)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        d->buflen, osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("                   = %zu, %s\n", rc, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (strcmp(res, d->expect_lower)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "       got %s\n", i, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                              printf("  expected %s\n", osmo_quote_str(d->expect_lower, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                          ok = false;</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%);">+                   if (d->expect_rc_inplace != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "       got rc=%zu, expected rc=%zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     i, rc, d->expect_rc_inplace);</span><br><span style="color: hsl(120, 100%, 40%);">+                               ok = false;</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 style="color: hsl(120, 100%, 40%);">+           /* toupper */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (d->use_static_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   res = osmo_str_toupper(d->in);</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("osmo_str_toupper(%s)\n", osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("               = %s\n", osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_ASSERT(sizeof(buf) >= d->buflen);</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_strlcpy(buf, "Unset", sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+                    rc = osmo_str_toupper_buf(buf, d->buflen, d->in);</span><br><span style="color: hsl(120, 100%, 40%);">+                       res = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf("osmo_str_toupper_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("                   = %zu, %s\n", rc, osmo_quote_str(res, -1));</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%);">+           if (strcmp(res, d->expect_upper)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                             "       got %s\n", i, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("  expected %s\n", osmo_quote_str(d->expect_upper, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                  ok = false;</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%);">+           if (!d->use_static_buf && d->expect_rc != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                             "       got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                     ok = false;</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%);">+           /* toupper, in-place */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!d->use_static_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_strlcpy(buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  d->buflen ? d->in : "Unset",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+                    rc = osmo_str_toupper_buf(buf, d->buflen, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                    res = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+                    printf("osmo_str_toupper_buf(%zu, %s, in-place)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        d->buflen, osmo_quote_str(d->in, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("                   = %zu, %s\n", rc, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (strcmp(res, d->expect_upper)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "       got %s\n", i, osmo_quote_str(res, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                              printf("  expected %s\n", osmo_quote_str(d->expect_upper, -1));</span><br><span style="color: hsl(120, 100%, 40%);">+                          ok = false;</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%);">+                   if (d->expect_rc_inplace != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "       got rc=%zu, expected rc=%zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     i, rc, d->expect_rc_inplace);</span><br><span style="color: hsl(120, 100%, 40%);">+                               ok = false;</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(ok);</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>@@ -631,5 +814,6 @@</span><br><span>    str_quote_test();</span><br><span>    isqrt_test();</span><br><span>        osmo_sockaddr_to_str_and_uint_test();</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_tolowupper_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 abc7317..3ea8ec6 100644</span><br><span>--- a/tests/utils/utils_test.ok</span><br><span>+++ b/tests/utils/utils_test.ok</span><br><span>@@ -153,3 +153,49 @@</span><br><span> [5] 234.23.42.123:1234 (omit addr) addr_len=0 --> :1234 rc=0</span><br><span> [6] 234.23.42.123:1234 addr_len=0 --> :1234 rc=13</span><br><span> [7] 234.23.42.123:1234 (omit addr) (omit port) addr_len=0 --> :0 rc=0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolowupper_test</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+               = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+               = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "Unset"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 0, "Unset"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "Unset"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 0, "Unset"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, ""</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 0, ""</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, ""</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 0, ""</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "a"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 1, "a"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "A"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 1, "A"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "abcdefghijklmnopqrstuvwxyza"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_tolower_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 27, "abcdefghijklmnopqrstuvwxyza"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()")</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZA"</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_str_toupper_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place)</span><br><span style="color: hsl(120, 100%, 40%);">+                   = 27, "ABCDEFGHIJKLMNOPQRSTUVWXYZA"</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10830">change 10830</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/10830"/><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-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ib0ee1206b9f31d7ba25c31f8008119ac55440797 </div>
<div style="display:none"> Gerrit-Change-Number: 10830 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>