Neels Hofmeyr has uploaded this change for review. ( 
https://gerrit.osmocom.org/13594


Change subject: tweak OSMO_STRBUF_APPEND(), add OSMO_STRBUF_APPEND_NOLEN()
......................................................................

tweak OSMO_STRBUF_APPEND(), add OSMO_STRBUF_APPEND_NOLEN()

In OSMO_STRBUF_APPEND, use local variable names that are less likely to shadow
other local variables: prefix with _sb_.

In OSMO_STRBUF_APPEND, add a check to add to .pos only if it is not NULL.

Add OSMO_STRBUF_APPEND_NOLEN(), which works for function signatures that don't
return a length. This is useful for any osmo_*_buf() string writing functions,
so that these write directly to the strbuf.

Change-Id: I108cadf72deb3a3bcab9a07e50572d9da1ab0359
---
M include/osmocom/core/utils.h
M tests/utils/utils_test.c
M tests/utils/utils_test.ok
3 files changed, 53 insertions(+), 7 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/94/13594/1

diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index e19649a..0daad76 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -199,14 +199,14 @@
 #define OSMO_STRBUF_APPEND(STRBUF, func, args...) do { \
                if (!(STRBUF).pos) \
                        (STRBUF).pos = (STRBUF).buf; \
-               size_t remain = (STRBUF).buf ? (STRBUF).len - ((STRBUF).pos - 
(STRBUF).buf) : 0; \
-               int l = func((STRBUF).pos, remain, ##args); \
-               if (l < 0 || l > remain) \
+               size_t _sb_remain = (STRBUF).buf ? (STRBUF).len - ((STRBUF).pos 
- (STRBUF).buf) : 0; \
+               int _sb_l = func((STRBUF).pos, _sb_remain, ##args); \
+               if (_sb_l < 0 || _sb_l > _sb_remain) \
                        (STRBUF).pos = (STRBUF).buf + (STRBUF).len; \
-               else \
-                       (STRBUF).pos += l; \
-               if (l > 0) \
-                       (STRBUF).chars_needed += l; \
+               else if ((STRBUF).pos) \
+                       (STRBUF).pos += _sb_l; \
+               if (_sb_l > 0) \
+                       (STRBUF).chars_needed += _sb_l; \
        } while(0)

 /*! Shortcut for OSMO_STRBUF_APPEND() invocation using snprintf().
@@ -231,6 +231,29 @@
 #define OSMO_STRBUF_PRINTF(STRBUF, fmt, args...) \
        OSMO_STRBUF_APPEND(STRBUF, snprintf, fmt, ##args)

+/*! Like OSMO_STRBUF_APPEND(), but for function signatures that return the 
char* buffer instead of a length.
+ * When using this function, the final STRBUF.chars_needed may not reflect the 
actual number of characters needed, since
+ * that number cannot be obtained from this kind of function signature.
+ * \param[inout] STRBUF  A struct osmo_strbuf instance.
+ * \param[in] func  A function with a signature of char *func(char *dst, 
size_t dst_len [, args]) where
+ *                  the returned string is always written to dst.
+ * \param[in] args  Arguments passed to func, if any.
+ */
+#define OSMO_STRBUF_APPEND_NOLEN(STRBUF, func, args...) do { \
+               if (!(STRBUF).pos) \
+                       (STRBUF).pos = (STRBUF).buf; \
+               size_t _sb_remain = (STRBUF).buf ? (STRBUF).len - ((STRBUF).pos 
- (STRBUF).buf) : 0; \
+               if (_sb_remain) { \
+                       func((STRBUF).pos, _sb_remain, ##args); \
+               } \
+               size_t _sb_l = (STRBUF).pos ? strnlen((STRBUF).pos, _sb_remain) 
: 0; \
+               if (_sb_l > _sb_remain) \
+                       (STRBUF).pos = (STRBUF).buf + (STRBUF).len; \
+               else if ((STRBUF).pos) \
+                       (STRBUF).pos += _sb_l; \
+               (STRBUF).chars_needed += _sb_l; \
+       } while(0)
+
 bool osmo_str_startswith(const char *str, const char *startswith_str);

 /*! @} */
diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c
index 211b4d1..223f67d 100644
--- a/tests/utils/utils_test.c
+++ b/tests/utils/utils_test.c
@@ -1014,6 +1014,23 @@
        printf("(need %d chars, had size=63) %s\n", rc, buf);
 }

+void strbuf_test_nolen()
+{
+       char buf[20];
+       struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) };
+       uint8_t ubits[] = {0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0};
+       printf("\n%s\n", __func__);
+
+       OSMO_STRBUF_APPEND_NOLEN(sb, osmo_ubit_dump_buf, ubits, sizeof(ubits));
+       printf("%zu: %s (need=%zu)\n", sb.len, buf, sb.chars_needed);
+       OSMO_STRBUF_APPEND_NOLEN(sb, osmo_ubit_dump_buf, ubits, sizeof(ubits));
+       printf("more: %s (need=%zu)\n", buf, sb.chars_needed);
+
+       sb = (struct osmo_strbuf){ .buf = buf, .len = 10 };
+       OSMO_STRBUF_APPEND_NOLEN(sb, osmo_ubit_dump_buf, ubits, sizeof(ubits));
+       printf("%zu: %s (need=%zu)\n", sb.len, buf, sb.chars_needed);
+}
+
 static void startswith_test_str(const char *str, const char *startswith_str, 
bool expect_rc)
 {
        bool rc = osmo_str_startswith(str, startswith_str);
@@ -1059,6 +1076,7 @@
        osmo_sockaddr_to_str_and_uint_test();
        osmo_str_tolowupper_test();
        strbuf_test();
+       strbuf_test_nolen();
        startswith_test();
        return 0;
 }
diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok
index 5783eb1..587c6f0 100644
--- a/tests/utils/utils_test.ok
+++ b/tests/utils/utils_test.ok
@@ -341,6 +341,11 @@
 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!
 (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

+strbuf_test_nolen
+20: 0001011100101010 (need=16)
+more: 0001011100101010000 (need=19)
+10: 000101110 (need=9)
+
 startswith_test()
 osmo_str_startswith(NULL, NULL) == true
 osmo_str_startswith("", NULL) == true

-- 
To view, visit https://gerrit.osmocom.org/13594
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I108cadf72deb3a3bcab9a07e50572d9da1ab0359
Gerrit-Change-Number: 13594
Gerrit-PatchSet: 1
Gerrit-Owner: Neels Hofmeyr <nhofm...@sysmocom.de>

Reply via email to