diff options
author | Thomas Haller <thaller@redhat.com> | 2020-06-20 12:10:32 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-06-20 19:22:04 +0200 |
commit | 83c79bc7a82ea513574cd08a38115a485921b1fa (patch) | |
tree | 7d27c7eec9ba6e0b7989bd80c67a9d4fd12f514a | |
parent | 8ba4537b24617680b6f0e94d69b0b552a7ee4bd3 (diff) | |
download | NetworkManager-83c79bc7a82ea513574cd08a38115a485921b1fa.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.
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.c | 2 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-str-buf.h | 41 |
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 68e6ee5ba1..cb43182c41 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -4859,6 +4859,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); |