<p>Neels Hofmeyr has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13061">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_string_ringbuffer and osmo_static_string() API<br><br>Change-Id: I48f8951de4d209d4cd3ca1aa9ce6137918913125<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, 639 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/61/13061/1</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 16159d3..efc9bcc 100644</span><br><span>--- a/include/osmocom/core/utils.h</span><br><span>+++ b/include/osmocom/core/utils.h</span><br><span>@@ -230,4 +230,33 @@</span><br><span> #define OSMO_STRBUF_PRINTF(STRBUF, fmt, args...) \</span><br><span>    OSMO_STRBUF_APPEND(STRBUF, snprintf, fmt, ##args)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! State for managing a ringbuffer of static strings. See osmo_static_string(). */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_string_ringbuffer {</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! Start of the usable memory. */</span><br><span style="color: hsl(120, 100%, 40%);">+    char *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! Size of the usable memory. */</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t buf_size;</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Pointer to after the last used static string. */</span><br><span style="color: hsl(120, 100%, 40%);">+  char *next;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! Most recent usages, for sanity checking. If not NULL, should point to an array of char*[recent_len]. */</span><br><span style="color: hsl(120, 100%, 40%);">+   char **recent;</span><br><span style="color: hsl(120, 100%, 40%);">+        /*! Number of recent usages that is considered as still in use. */</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t recent_len;</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%);">+char *osmo_string_ringbuffer_get(struct osmo_string_ringbuffer *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_string_ringbuffer_avail(struct osmo_string_ringbuffer *buf);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_string_ringbuffer_clear(struct osmo_string_ringbuffer *buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_static_string(size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Useful to pass osmo_static_string() and size arguments without repeating the size.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *     printf("%s\n", osmo_hexdump_buf(OSMO_STATIC_STRING(my_data_len*2), my_data, my_data_len, NULL, false));</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define OSMO_STATIC_STRING(SIZE) osmo_static_string(SIZE), (SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct osmo_string_ringbuffer osmo_static_string_buf_default;</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct osmo_string_ringbuffer *osmo_static_string_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! @} */</span><br><span>diff --git a/src/utils.c b/src/utils.c</span><br><span>index 2d5bcb0..12189b6 100644</span><br><span>--- a/src/utils.c</span><br><span>+++ b/src/utils.c</span><br><span>@@ -826,4 +826,160 @@</span><br><span>        return (sum * 9) % 10 + '0';</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return section from a string ringbuffer that is currently considered unused.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] buf  osmo_string_ringbuffer instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bufsize  The amount of bytes that should be available, caller needs to include terminating nul.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Pointer to string buffer, or NULL if there is not enough unused memory available in osmo_static_string_buf.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_string_ringbuffer_get(struct osmo_string_ringbuffer *buf, size_t bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *ret;</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!bufsize || !buf)</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%);">+        if (bufsize > buf->buf_size)</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%);">+        ret = buf->next;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ret < buf->buf</span><br><span style="color: hsl(120, 100%, 40%);">+          || ret + bufsize > buf->buf + buf->buf_size)</span><br><span style="color: hsl(120, 100%, 40%);">+             ret = buf->buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (buf->recent) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ret <= buf->recent[0]</span><br><span style="color: hsl(120, 100%, 40%);">+                   && bufsize > buf->recent[0] - ret)</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%);">+                /* Record used chunk in list of recent buffers */</span><br><span style="color: hsl(120, 100%, 40%);">+             for (i = 0; i < buf->recent_len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (!buf->recent[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                               break;</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 (i < buf->recent_len)</span><br><span style="color: hsl(120, 100%, 40%);">+                        buf->recent[i] = ret;</span><br><span style="color: hsl(120, 100%, 40%);">+              else {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (buf->recent_len > 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                                memmove(&buf->recent[0], &buf->recent[1], (buf->recent_len - 1) *</span><br><span style="color: hsl(120, 100%, 40%);">+                                    sizeof(buf->recent[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+                   buf->recent[buf->recent_len - 1] = ret;</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%);">+   buf->next = ret + bufsize;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return ret;</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%);">+/*! Reset string ringbuffer to make all of its space available.</span><br><span style="color: hsl(120, 100%, 40%);">+ * This can be useful to mark a buffer as unused, e.g. to recover from a full buffer, or before and after the caller</span><br><span style="color: hsl(120, 100%, 40%);">+ * would like to allocate an unusually large buffer. All previously allocated pointers gotten by</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_string_ringbuffer_get() for this ring buffer must no longer be used. */</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_string_ringbuffer_clear(struct osmo_string_ringbuffer *buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (buf->recent && buf->recent_len)</span><br><span style="color: hsl(120, 100%, 40%);">+             memset(buf->recent, 0, buf->recent_len * sizeof(buf->recent[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+    buf->next = NULL;</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%);">+/*! Return the largest amount of bytes that could be allocated at this point in time.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] buf  osmo_string_ringbuffer instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Size of largest continuous chunk of bytes available.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t osmo_string_ringbuffer_avail(struct osmo_string_ringbuffer *buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      char *pos = buf->next;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (pos < buf->buf || pos > buf->buf + buf->buf_size)</span><br><span style="color: hsl(120, 100%, 40%);">+          pos = buf->buf;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (buf->recent && buf->recent[0]) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (pos <= buf->recent[0])</span><br><span style="color: hsl(120, 100%, 40%);">+                      return buf->recent[0] - pos;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             return OSMO_MAX(buf->buf_size - (pos - buf->buf),</span><br><span style="color: hsl(120, 100%, 40%);">+                               buf->recent[0] - buf->buf);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return buf->buf_size - (pos - buf->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%);">+/*! Re-use static string ring buffer not before five osmo_static_string() calls have occured. */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *default_string_buf_recent[5] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Currently, the largest requested size within libosmocore is 4100 bytes (msgb_hexdump()), allow for enough space so</span><br><span style="color: hsl(120, 100%, 40%);">+ * that it can be called any number of times in a row without hitting the recent[] check. To guarantee N untouched</span><br><span style="color: hsl(120, 100%, 40%);">+ * previous buffers, there has to be space for N+1 buffers. However, a fragmented offset may lead to needing N+2. */</span><br><span style="color: hsl(120, 100%, 40%);">+static char default_string_buf_storage[4100 * (ARRAY_SIZE(default_string_buf_recent) + 2)];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_string_ringbuffer osmo_static_string_buf_default = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .buf = default_string_buf_storage,</span><br><span style="color: hsl(120, 100%, 40%);">+    .buf_size = sizeof(default_string_buf_storage),</span><br><span style="color: hsl(120, 100%, 40%);">+       .recent = default_string_buf_recent,</span><br><span style="color: hsl(120, 100%, 40%);">+  .recent_len = ARRAY_SIZE(default_string_buf_recent),</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_string_ringbuffer *osmo_static_string_buf = &osmo_static_string_buf_default;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return a static string buffer that can hold the given string length plus an additional nul character, or abort the</span><br><span style="color: hsl(120, 100%, 40%);">+ * program if no buffer is available.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The idea is to provide distinct string buffers for various osmo_xxx_name() API implementations, so that the same</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_xxx_name() function can be used multiple times in the same print format arguments.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use osmo_static_string_buf, which can be redirected by the caller to a larger buffer, if required.  By default,</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_static_string_buf points at osmo_static_string_buf_default, so that no initialization is necessary by the</span><br><span style="color: hsl(120, 100%, 40%);">+ * caller.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is the responsibility of the caller to ensure that enough string buffer space is available. If insufficient space</span><br><span style="color: hsl(120, 100%, 40%);">+ * is detected, abort the program using OSMO_ASSERT(false).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Insufficient space is detected by considering the last N allocations as still used. Depending on the amount of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ * reserved each time, there can in practice be many more than N allocations without overlapping. If, for example,</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_static_string_buf is configured to guarantee 5 allocations of 4100 bytes each without overlaps, that would also</span><br><span style="color: hsl(120, 100%, 40%);">+ * allow for 50 non-overlapping allocations of 410 bytes each. Hence this mechanism merely ensures basic sanity, so that</span><br><span style="color: hsl(120, 100%, 40%);">+ * the caller can at all times be sure that at least 5 concurrent allocations will succeed, and will receive a program</span><br><span style="color: hsl(120, 100%, 40%);">+ * error otherwise.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param bufsize  The amount of bytes that should be available, caller needs to include terminating nul.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Pointer to string buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_static_string(size_t bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      char *ret = osmo_string_ringbuffer_get(osmo_static_string_buf, bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* If we're going to assert because of no more static strings being available, print out a status to stderr</span><br><span style="color: hsl(120, 100%, 40%);">+        * first. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ret) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int i;</span><br><span style="color: hsl(120, 100%, 40%);">+                fprintf(stderr, "\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "*** Static ringbuffer full:\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                     "  avail = %zu\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "  requested %zu\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                 "  size = %zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_string_ringbuffer_avail(osmo_static_string_buf),</span><br><span style="color: hsl(120, 100%, 40%);">+                 bufsize,</span><br><span style="color: hsl(120, 100%, 40%);">+                      osmo_static_string_buf->buf_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PRINT_IDX(val, label_fmt, label_args...) \</span><br><span style="color: hsl(120, 100%, 40%);">+           if (osmo_static_string_buf->val >= osmo_static_string_buf->buf \</span><br><span style="color: hsl(120, 100%, 40%);">+                 && osmo_static_string_buf->val <= (osmo_static_string_buf->buf + osmo_static_string_buf->buf_size)) \</span><br><span style="color: hsl(120, 100%, 40%);">+                 fprintf(stderr, "  [%zu] " label_fmt "\n", \</span><br><span style="color: hsl(120, 100%, 40%);">+                              osmo_static_string_buf->val - osmo_static_string_buf->buf, ## label_args); \</span><br><span style="color: hsl(120, 100%, 40%);">+            else \</span><br><span style="color: hsl(120, 100%, 40%);">+                        fprintf(stderr, "  " label_fmt " out of bounds\n", ## label_args);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              PRINT_IDX(next, "next");</span><br><span style="color: hsl(120, 100%, 40%);">+            if (osmo_static_string_buf->recent) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      for (i = 0; i < osmo_static_string_buf->recent_len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (!osmo_static_string_buf->recent[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                                    continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             PRINT_IDX(recent[i], "recent[%d]", i);</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%);">+#undef PRINT_IDX</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(ret);</span><br><span style="color: hsl(120, 100%, 40%);">+     return ret;</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/tests/utils/utils_test.c b/tests/utils/utils_test.c</span><br><span>index d592fe0..73589d6 100644</span><br><span>--- a/tests/utils/utils_test.c</span><br><span>+++ b/tests/utils/utils_test.c</span><br><span>@@ -1022,6 +1022,115 @@</span><br><span>         printf("(need %d chars, had size=63) %s\n", rc, buf);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void string_ringbuf_test_print_pos(struct osmo_string_ringbuffer *b, char *pos, const char* label)</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%);">+        const char *marker = "^";</span><br><span style="color: hsl(120, 100%, 40%);">+   if (pos < b->buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+             pos = b->buf;</span><br><span style="color: hsl(120, 100%, 40%);">+              marker = "<-";</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (pos > b->buf + b->buf_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+            pos = b->buf + b->buf_size + 5;</span><br><span style="color: hsl(120, 100%, 40%);">+         marker = "->";</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < (pos - b->buf); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            printf(" ");</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("       " "%s%s\n", marker, label);</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%);">+void string_ringbuf_test_get(struct osmo_string_ringbuffer *b, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *ret = osmo_string_ringbuffer_get(b, len);</span><br><span style="color: hsl(120, 100%, 40%);">+       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        static char marker = 'a';</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("osmo_string_ringbuffer_get(%2zu) -> ", len);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ret)</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("NULL");</span><br><span style="color: hsl(120, 100%, 40%);">+     else {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("buf[%zu]", ret - b->buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                for (i = 0; i < len; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+                  ret[i] = marker;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</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%);">+     printf("buf = [");</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < b->buf_size; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("%c", b->buf[i]? : '_');</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("]\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      string_ringbuf_test_print_pos(b, b->next, "next");</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = b->recent_len-1; i >= 0; i--)</span><br><span style="color: hsl(120, 100%, 40%);">+          string_ringbuf_test_print_pos(b, b->recent[i], "recent");</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("avail = %zu\n", osmo_string_ringbuffer_avail(b));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ marker++;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (marker > 'z')</span><br><span style="color: hsl(120, 100%, 40%);">+          marker = 'a';</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%);">+void string_ringbuf_test()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     char buf[23] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+    char *recent[3] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_string_ringbuffer _b = {</span><br><span style="color: hsl(120, 100%, 40%);">+          .buf = buf,</span><br><span style="color: hsl(120, 100%, 40%);">+           .buf_size = sizeof(buf),</span><br><span style="color: hsl(120, 100%, 40%);">+              .recent = recent,</span><br><span style="color: hsl(120, 100%, 40%);">+             .recent_len = ARRAY_SIZE(recent),</span><br><span style="color: hsl(120, 100%, 40%);">+     };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_string_ringbuffer *b = &_b;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CLEAR \</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(buf, 0, sizeof(buf)); \</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_string_ringbuffer_clear(b);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("\n\n%s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("\n*** Test continuous small buffers\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 26; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           string_ringbuf_test_get(b, i&1? 5 : 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("\n*** Test exact use\n");</span><br><span style="color: hsl(120, 100%, 40%);">+   CLEAR</span><br><span style="color: hsl(120, 100%, 40%);">+ string_ringbuf_test_get(b, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\n*** Test deadlock\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    CLEAR</span><br><span style="color: hsl(120, 100%, 40%);">+ string_ringbuf_test_get(b, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\n*** Test deadlock (2)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        CLEAR</span><br><span style="color: hsl(120, 100%, 40%);">+ string_ringbuf_test_get(b, 23);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_test_get(b, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\n*** Test bounds checking: available size\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     CLEAR</span><br><span style="color: hsl(120, 100%, 40%);">+ string_ringbuf_test_get(b, 30);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       string_ringbuf_test_get(b, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\nTest bounds checking: invalid args\n");</span><br><span style="color: hsl(120, 100%, 40%);">+   string_ringbuf_test_get(b, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(osmo_string_ringbuffer_get(NULL, 10) == NULL);</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>@@ -1040,5 +1149,6 @@</span><br><span>  osmo_sockaddr_to_str_and_uint_test();</span><br><span>        osmo_str_tolowupper_test();</span><br><span>  strbuf_test();</span><br><span style="color: hsl(120, 100%, 40%);">+        string_ringbuf_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 1215ddd..48574cb 100644</span><br><span>--- a/tests/utils/utils_test.ok</span><br><span>+++ b/tests/utils/utils_test.ok</span><br><span>@@ -342,3 +342,347 @@</span><br><span> (need 134 chars)</span><br><span> T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off! -- T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off! -- T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off!</span><br><span> (need 134 chars, had size=63) T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off! -- T minus 10 9 8 7</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%);">+string_ringbuf_test</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+*** Test continuous small buffers</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaa____________________]</span><br><span style="color: hsl(120, 100%, 40%);">+          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 20</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[3]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaabbbbb_______________]</span><br><span style="color: hsl(120, 100%, 40%);">+               ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 15</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[8]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaabbbbbccc____________]</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^next</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 12</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[11]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaabbbbbcccddddd_______]</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 7</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[16]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaabbbbbcccdddddeee____]</span><br><span style="color: hsl(120, 100%, 40%);">+                          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [fffffbbbcccdddddeee____]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 6</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[5]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [fffffgggcccdddddeee____]</span><br><span style="color: hsl(120, 100%, 40%);">+               ^next</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[8]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [fffffggghhhhhdddeee____]</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^next</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 10</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[13]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [fffffggghhhhhiiieee____]</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 7</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[16]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [fffffggghhhhhiiijjjjj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [kkkffggghhhhhiiijjjjj__]</span><br><span style="color: hsl(120, 100%, 40%);">+          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 10</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[3]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [kkklllllhhhhhiiijjjjj__]</span><br><span style="color: hsl(120, 100%, 40%);">+               ^next</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[8]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [kkklllllmmmhhiiijjjjj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^next</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 12</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[11]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [kkklllllmmmnnnnnjjjjj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 7</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[16]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [kkklllllmmmnnnnnooojj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [ppppplllmmmnnnnnooojj__]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 6</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[5]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [pppppqqqmmmnnnnnooojj__]</span><br><span style="color: hsl(120, 100%, 40%);">+               ^next</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[8]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [pppppqqqrrrrrnnnooojj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^next</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 10</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[13]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [pppppqqqrrrrrsssooojj__]</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 7</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[16]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [pppppqqqrrrrrsssttttt__]</span><br><span style="color: hsl(120, 100%, 40%);">+                            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [uuuppqqqrrrrrsssttttt__]</span><br><span style="color: hsl(120, 100%, 40%);">+          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                    ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 10</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[3]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [uuuvvvvvrrrrrsssttttt__]</span><br><span style="color: hsl(120, 100%, 40%);">+               ^next</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[8]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [uuuvvvvvwwwrrsssttttt__]</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^next</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 12</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[11]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [uuuvvvvvwwwxxxxxttttt__]</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+          ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 7</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[16]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [uuuvvvvvwwwxxxxxyyytt__]</span><br><span style="color: hsl(120, 100%, 40%);">+                          ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+               ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 8</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [zzzzzvvvwwwxxxxxyyytt__]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                  ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+*** Test exact use</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaaaa__________________]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 18</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[5]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaaaabbbbb_____________]</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 13</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(10) -> buf[10]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaaaabbbbbcccccccccc___]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[20]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [aaaaabbbbbccccccccccddd]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 5</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [eeeeebbbbbccccccccccddd]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 5</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[5]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [eeeeefffffccccccccccddd]</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^next</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 10</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(10) -> buf[10]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [eeeeefffffggggggggggddd]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[20]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [eeeeefffffgggggggggghhh]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 5</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+*** Test deadlock</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 5) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [iiiii__________________]</span><br><span style="color: hsl(120, 100%, 40%);">+            ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 18</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(15) -> buf[5]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [iiiiijjjjjjjjjjjjjjj___]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 3) -> buf[20]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [iiiiijjjjjjjjjjjjjjjkkk]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 1) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [iiiiijjjjjjjjjjjjjjjkkk]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 1) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [iiiiijjjjjjjjjjjjjjjkkk]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+            ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+*** Test deadlock (2)</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(23) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [nnnnnnnnnnnnnnnnnnnnnnn]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 1) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [nnnnnnnnnnnnnnnnnnnnnnn]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 1) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [nnnnnnnnnnnnnnnnnnnnnnn]</span><br><span style="color: hsl(120, 100%, 40%);">+                              ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+*** Test bounds checking: available size</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(30) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [_______________________]</span><br><span style="color: hsl(120, 100%, 40%);">+       <-next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 23</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(10) -> buf[0]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [rrrrrrrrrr_____________]</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 13</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get(10) -> buf[10]</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [rrrrrrrrrrssssssssss___]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 4) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [rrrrrrrrrrssssssssss___]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Test bounds checking: invalid args</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_string_ringbuffer_get( 0) -> NULL</span><br><span style="color: hsl(120, 100%, 40%);">+buf = [rrrrrrrrrrssssssssss___]</span><br><span style="color: hsl(120, 100%, 40%);">+                           ^next</span><br><span style="color: hsl(120, 100%, 40%);">+       <-recent</span><br><span style="color: hsl(120, 100%, 40%);">+                 ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+       ^recent</span><br><span style="color: hsl(120, 100%, 40%);">+avail = 3</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13061">change 13061</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/13061"/><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: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I48f8951de4d209d4cd3ca1aa9ce6137918913125 </div>
<div style="display:none"> Gerrit-Change-Number: 13061 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>