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 83c79bc7a8)
(cherry picked from commit 5216e5c012)
This commit is contained in:
Thomas Haller 2020-06-20 12:10:32 +02:00
parent 1ea72435da
commit 4086261a9f
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
2 changed files with 28 additions and 15 deletions

View file

@ -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,

View file

@ -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);