summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-06-20 12:10:32 +0200
committerThomas Haller <thaller@redhat.com>2020-12-08 15:20:16 +0100
commit4086261a9fc45c7a7e90da3d4600271b5c0a9616 (patch)
tree961c7eebf146cf6f1ce62f6973520239b43c364e
parent1ea72435dae474b768752cb1d57e7112bd04b664 (diff)
downloadNetworkManager-4086261a9fc45c7a7e90da3d4600271b5c0a9616.tar.gz
shared: allow empty NMStrBuf buffers with un-allocated memory
Previously, for simplicity, NMStrBuf did not support buffers without any data allocated. However, supporting that has very little overhead/complexity, so do it. Now you can initialize buffers to have no data allocated, and when appending data, it will automatically grow. (cherry picked from commit 83c79bc7a82ea513574cd08a38115a485921b1fa) (cherry picked from commit 5216e5c012475a65699ab98a38cbf7358196b914)
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c2
-rw-r--r--shared/nm-glib-aux/nm-str-buf.h41
2 files changed, 28 insertions, 15 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index 2b7387ba9a..16ead4dfa6 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -4800,6 +4800,8 @@ nm_str_buf_append_printf (NMStrBuf *strbuf,
available = strbuf->_priv_allocated - strbuf->_priv_len;
+ nm_assert (available < G_MAXULONG);
+
va_start (args, format);
l = g_vsnprintf (&strbuf->_priv_str[strbuf->_priv_len],
available,
diff --git a/shared/nm-glib-aux/nm-str-buf.h b/shared/nm-glib-aux/nm-str-buf.h
index 8c73bfaf3d..7121ba609a 100644
--- a/shared/nm-glib-aux/nm-str-buf.h
+++ b/shared/nm-glib-aux/nm-str-buf.h
@@ -35,24 +35,25 @@ static inline void
_nm_str_buf_assert (NMStrBuf *strbuf)
{
nm_assert (strbuf);
- nm_assert (strbuf->_priv_str);
- nm_assert (strbuf->_priv_allocated > 0);
+ nm_assert ((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0));
nm_assert (strbuf->_priv_len <= strbuf->_priv_allocated);
}
+#define NM_STR_BUF_INIT(len, do_bzero_mem) \
+ ((NMStrBuf) { \
+ ._priv_str = (len) ? g_malloc (len) : NULL, \
+ ._priv_allocated = (len), \
+ ._priv_len = 0, \
+ ._priv_do_bzero_mem = (do_bzero_mem), \
+ })
+
static inline void
nm_str_buf_init (NMStrBuf *strbuf,
gsize len,
bool do_bzero_mem)
{
nm_assert (strbuf);
- nm_assert (len > 0);
-
- strbuf->_priv_str = g_malloc (len);
- strbuf->_priv_allocated = len;
- strbuf->_priv_len = 0;
- strbuf->_priv_do_bzero_mem = do_bzero_mem;
-
+ *strbuf = NM_STR_BUF_INIT (len, do_bzero_mem);
_nm_str_buf_assert (strbuf);
}
@@ -66,9 +67,6 @@ nm_str_buf_maybe_expand (NMStrBuf *strbuf,
gboolean reserve_exact)
{
_nm_str_buf_assert (strbuf);
-
- /* currently we always require to reserve a non-zero number of bytes. */
- nm_assert (reserve > 0);
nm_assert (strbuf->_priv_len < G_MAXSIZE - reserve);
/* @reserve is the extra space that we require. */
@@ -263,10 +261,16 @@ nm_str_buf_is_initalized (NMStrBuf *strbuf)
* is of length "strbuf->len", which may be larger if the
* returned string contains NUL characters (binary). The terminating
* NUL character is always present after "strbuf->len" characters.
+ * If currently no buffer is allocated, this will return %NULL.
*/
static inline const char *
nm_str_buf_get_str (NMStrBuf *strbuf)
{
+ _nm_str_buf_assert (strbuf);
+
+ if (!strbuf->_priv_str)
+ return NULL;
+
nm_str_buf_maybe_expand (strbuf, 1, FALSE);
strbuf->_priv_str[strbuf->_priv_len] = '\0';
return strbuf->_priv_str;
@@ -288,16 +292,23 @@ nm_str_buf_get_str_unsafe (NMStrBuf *strbuf)
* Returns: (transfer full): the string of the buffer
* which must be freed by the caller. The @strbuf
* is afterwards in undefined state, though it can be
- * reused after nm_str_buf_init(). */
+ * reused after nm_str_buf_init().
+ * Note that if no string is allocated yet (after nm_str_buf_init() with
+ * length zero), this will return %NULL. */
static inline char *
nm_str_buf_finalize (NMStrBuf *strbuf,
gsize *out_len)
{
- nm_str_buf_maybe_expand (strbuf, 1, TRUE);
- strbuf->_priv_str[strbuf->_priv_len] = '\0';
+ _nm_str_buf_assert (strbuf);
NM_SET_OUT (out_len, strbuf->_priv_len);
+ if (!strbuf->_priv_str)
+ return NULL;
+
+ nm_str_buf_maybe_expand (strbuf, 1, TRUE);
+ strbuf->_priv_str[strbuf->_priv_len] = '\0';
+
/* the buffer is in invalid state afterwards, however, we clear it
* so far, that nm_auto_str_buf and nm_str_buf_destroy() is happy. */
return g_steal_pointer (&strbuf->_priv_str);