about summary refs log tree commit diff
path: root/shared/nm-glib-aux/nm-str-buf.h
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2021-01-11 18:07:03 +0100
committerSebastien Bacher <seb128@ubuntu.com>2021-01-11 18:15:57 +0100
commit2567f558da3eb9911678227d4aeb15162e707d89 (patch)
tree13c80b0e091c8ba585b14b966cda998f95f1936d /shared/nm-glib-aux/nm-str-buf.h
parent02d99ffd62ede29cffcb45fcbe33d044b7406d3a (diff)
parentf54032b30e1ddd84f10a339e0caf493772e049a7 (diff)
Merge branch 'debian/master' into ubuntu/master
Diffstat (limited to 'shared/nm-glib-aux/nm-str-buf.h')
-rw-r--r--shared/nm-glib-aux/nm-str-buf.h442
1 files changed, 259 insertions, 183 deletions
diff --git a/shared/nm-glib-aux/nm-str-buf.h b/shared/nm-glib-aux/nm-str-buf.h
index da082abe..062630a5 100644
--- a/shared/nm-glib-aux/nm-str-buf.h
+++ b/shared/nm-glib-aux/nm-str-buf.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: LGPL-2.1+
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #ifndef __NM_STR_BUF_H__
 #define __NM_STR_BUF_H__
@@ -11,72 +11,65 @@
 /* NMStrBuf is not unlike GString. The main difference is that it can use
  * nm_explicit_bzero() when growing the buffer. */
 typedef struct _NMStrBuf {
-
-	char *_priv_str;
-
-	/* The unions only exist because we allow/encourage read-only access
-	 * to the "len" and "allocated" fields, but modifying the fields is
-	 * only allowed to the NMStrBuf implementation itself. */
-	union {
-		/*const*/ gsize len;
-		gsize _priv_len;
-	};
-	union {
-		/*const*/ gsize allocated;
-		gsize _priv_allocated;
-	};
-
-	bool _priv_do_bzero_mem;
+    char *_priv_str;
+
+    /* The unions only exist because we allow/encourage read-only access
+     * to the "len" and "allocated" fields, but modifying the fields is
+     * only allowed to the NMStrBuf implementation itself. */
+    union {
+        /*const*/ gsize len;
+        gsize           _priv_len;
+    };
+    union {
+        /*const*/ gsize allocated;
+        gsize           _priv_allocated;
+    };
+
+    bool _priv_do_bzero_mem;
 } NMStrBuf;
 
 /*****************************************************************************/
 
 static inline void
-_nm_str_buf_assert (NMStrBuf *strbuf)
+_nm_str_buf_assert(NMStrBuf *strbuf)
 {
-	nm_assert (strbuf);
-	nm_assert ((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0));
-	nm_assert (strbuf->_priv_len <= strbuf->_priv_allocated);
+    nm_assert(strbuf);
+    nm_assert((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0));
+    nm_assert(strbuf->_priv_len <= strbuf->_priv_allocated);
 }
 
 static inline NMStrBuf
-NM_STR_BUF_INIT (gsize allocated, gboolean do_bzero_mem)
+NM_STR_BUF_INIT(gsize allocated, gboolean do_bzero_mem)
 {
-	NMStrBuf strbuf = {
-		._priv_str          = allocated ? g_malloc (allocated) : NULL,
-		._priv_allocated    = allocated,
-		._priv_len          = 0,
-		._priv_do_bzero_mem = do_bzero_mem,
-	};
-
-	return strbuf;
+    NMStrBuf strbuf = {
+        ._priv_str          = allocated ? g_malloc(allocated) : NULL,
+        ._priv_allocated    = allocated,
+        ._priv_len          = 0,
+        ._priv_do_bzero_mem = do_bzero_mem,
+    };
+
+    return strbuf;
 }
 
 static inline void
-nm_str_buf_init (NMStrBuf *strbuf,
-                 gsize len,
-                 bool do_bzero_mem)
+nm_str_buf_init(NMStrBuf *strbuf, gsize len, bool do_bzero_mem)
 {
-	nm_assert (strbuf);
-	*strbuf = NM_STR_BUF_INIT (len, do_bzero_mem);
-	_nm_str_buf_assert (strbuf);
+    nm_assert(strbuf);
+    *strbuf = NM_STR_BUF_INIT(len, do_bzero_mem);
+    _nm_str_buf_assert(strbuf);
 }
 
-void _nm_str_buf_ensure_size (NMStrBuf *strbuf,
-                              gsize new_size,
-                              gboolean reserve_exact);
+void _nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact);
 
 static inline void
-nm_str_buf_maybe_expand (NMStrBuf *strbuf,
-                         gsize reserve,
-                         gboolean reserve_exact)
+nm_str_buf_maybe_expand(NMStrBuf *strbuf, gsize reserve, gboolean reserve_exact)
 {
-	_nm_str_buf_assert (strbuf);
-	nm_assert (strbuf->_priv_len < G_MAXSIZE - reserve);
+    _nm_str_buf_assert(strbuf);
+    nm_assert(strbuf->_priv_len < G_MAXSIZE - reserve);
 
-	/* @reserve is the extra space that we require. */
-	if (G_UNLIKELY (reserve > strbuf->_priv_allocated - strbuf->_priv_len))
-		_nm_str_buf_ensure_size (strbuf, strbuf->_priv_len + reserve, reserve_exact);
+    /* @reserve is the extra space that we require. */
+    if (G_UNLIKELY(reserve > strbuf->_priv_allocated - strbuf->_priv_len))
+        _nm_str_buf_ensure_size(strbuf, strbuf->_priv_len + reserve, reserve_exact);
 }
 
 /*****************************************************************************/
@@ -85,9 +78,9 @@ nm_str_buf_maybe_expand (NMStrBuf *strbuf,
  * nm_str_buf_set_size:
  * @strbuf: the initialized #NMStrBuf
  * @new_len: the new length
- * @honor_do_bzero_mem: if %TRUE, the shrinked memory will be cleared, if
+ * @honor_do_bzero_mem: if %TRUE, the shrunk memory will be cleared, if
  *   do_bzero_mem is set. This should be usually set to %TRUE, unless
- *   you know that the shrinked memory does not contain data that requires to be
+ *   you know that the shrunk memory does not contain data that requires to be
  *   cleared. When growing the size, this value has no effect.
  * @reserve_exact: when growing the buffer, reserve the exact amount of bytes.
  *   If %FALSE, the buffer may allocate more memory than requested to grow
@@ -103,162 +96,229 @@ nm_str_buf_maybe_expand (NMStrBuf *strbuf,
  * pre-existing, grown buffer).
  */
 static inline void
-nm_str_buf_set_size (NMStrBuf *strbuf,
-                     gsize new_len,
-                     gboolean honor_do_bzero_mem,
-                     gboolean reserve_exact)
+nm_str_buf_set_size(NMStrBuf *strbuf,
+                    gsize     new_len,
+                    gboolean  honor_do_bzero_mem,
+                    gboolean  reserve_exact)
 {
-	_nm_str_buf_assert (strbuf);
-
-	if (new_len < strbuf->_priv_len) {
-		if (   honor_do_bzero_mem
-		    && strbuf->_priv_do_bzero_mem) {
-			/* we only clear the memory that we wrote to. */
-			nm_explicit_bzero (&strbuf->_priv_str[new_len], strbuf->_priv_len - new_len);
-		}
-	} else if (new_len > strbuf->_priv_len) {
-		nm_str_buf_maybe_expand (strbuf,
-		                         new_len - strbuf->_priv_len + (reserve_exact ? 0u : 1u),
-		                         reserve_exact);
-	} else
-		return;
-
-	strbuf->_priv_len = new_len;
+    _nm_str_buf_assert(strbuf);
+
+    if (new_len < strbuf->_priv_len) {
+        if (honor_do_bzero_mem && strbuf->_priv_do_bzero_mem) {
+            /* we only clear the memory that we wrote to. */
+            nm_explicit_bzero(&strbuf->_priv_str[new_len], strbuf->_priv_len - new_len);
+        }
+    } else if (new_len > strbuf->_priv_len) {
+        nm_str_buf_maybe_expand(strbuf,
+                                new_len - strbuf->_priv_len + (reserve_exact ? 0u : 1u),
+                                reserve_exact);
+    } else
+        return;
+
+    strbuf->_priv_len = new_len;
 }
 
 /*****************************************************************************/
 
 static inline void
-nm_str_buf_erase (NMStrBuf *strbuf,
-                  gsize pos,
-                  gssize len,
-                  gboolean honor_do_bzero_mem)
+nm_str_buf_erase(NMStrBuf *strbuf, gsize pos, gssize len, gboolean honor_do_bzero_mem)
 {
-	gsize new_len;
+    gsize new_len;
 
-	_nm_str_buf_assert (strbuf);
+    _nm_str_buf_assert(strbuf);
 
-	nm_assert (pos <= strbuf->_priv_len);
+    nm_assert(pos <= strbuf->_priv_len);
 
-	if (len == 0)
-		return;
+    if (len == 0)
+        return;
 
-	if (len < 0) {
-		/* truncate the string before pos */
-		nm_assert (len == -1);
-		new_len = pos;
-	} else {
-		gsize l = len;
+    if (len < 0) {
+        /* truncate the string before pos */
+        nm_assert(len == -1);
+        new_len = pos;
+    } else {
+        gsize l = len;
 
-		nm_assert (l <= strbuf->_priv_len - pos);
+        nm_assert(l <= strbuf->_priv_len - pos);
 
-		new_len = strbuf->_priv_len - l;
-		if (pos + l < strbuf->_priv_len) {
-			memmove (&strbuf->_priv_str[pos],
-			         &strbuf->_priv_str[pos + l],
-			         strbuf->_priv_len - (pos + l));
-		}
-	}
+        new_len = strbuf->_priv_len - l;
+        if (pos + l < strbuf->_priv_len) {
+            memmove(&strbuf->_priv_str[pos],
+                    &strbuf->_priv_str[pos + l],
+                    strbuf->_priv_len - (pos + l));
+        }
+    }
 
-	nm_assert (new_len <= strbuf->_priv_len);
-	nm_str_buf_set_size (strbuf, new_len, honor_do_bzero_mem, TRUE);
+    nm_assert(new_len <= strbuf->_priv_len);
+    nm_str_buf_set_size(strbuf, new_len, honor_do_bzero_mem, TRUE);
 }
 
 /*****************************************************************************/
 
 static inline void
-nm_str_buf_append_c_repeated (NMStrBuf *strbuf,
-                              char ch,
-                              guint len)
+nm_str_buf_append_c_repeated(NMStrBuf *strbuf, char ch, guint len)
+{
+    if (len > 0) {
+        nm_str_buf_maybe_expand(strbuf, len + 1, FALSE);
+        do {
+            strbuf->_priv_str[strbuf->_priv_len++] = ch;
+        } while (--len > 0);
+    }
+}
+
+static inline void
+nm_str_buf_append_c(NMStrBuf *strbuf, char ch)
 {
-	if (len > 0) {
-		nm_str_buf_maybe_expand (strbuf, len + 1, FALSE);
-		do {
-			strbuf->_priv_str[strbuf->_priv_len++] = ch;
-		} while (--len > 0);
-	}
+    nm_str_buf_maybe_expand(strbuf, 2, FALSE);
+    strbuf->_priv_str[strbuf->_priv_len++] = ch;
 }
 
 static inline void
-nm_str_buf_append_c (NMStrBuf *strbuf,
-                     char ch)
+nm_str_buf_append_c2(NMStrBuf *strbuf, char ch0, char ch1)
 {
-	nm_str_buf_maybe_expand (strbuf, 2, FALSE);
-	strbuf->_priv_str[strbuf->_priv_len++] = ch;
+    nm_str_buf_maybe_expand(strbuf, 3, FALSE);
+    strbuf->_priv_str[strbuf->_priv_len++] = ch0;
+    strbuf->_priv_str[strbuf->_priv_len++] = ch1;
 }
 
 static inline void
-nm_str_buf_append_c2 (NMStrBuf *strbuf,
-                      char ch0,
-                      char ch1)
+nm_str_buf_append_c4(NMStrBuf *strbuf, char ch0, char ch1, char ch2, char ch3)
 {
-	nm_str_buf_maybe_expand (strbuf, 3, FALSE);
-	strbuf->_priv_str[strbuf->_priv_len++] = ch0;
-	strbuf->_priv_str[strbuf->_priv_len++] = ch1;
+    nm_str_buf_maybe_expand(strbuf, 5, FALSE);
+    strbuf->_priv_str[strbuf->_priv_len++] = ch0;
+    strbuf->_priv_str[strbuf->_priv_len++] = ch1;
+    strbuf->_priv_str[strbuf->_priv_len++] = ch2;
+    strbuf->_priv_str[strbuf->_priv_len++] = ch3;
 }
 
 static inline void
-nm_str_buf_append_c4 (NMStrBuf *strbuf,
-                      char ch0,
-                      char ch1,
-                      char ch2,
-                      char ch3)
+nm_str_buf_append_c_hex(NMStrBuf *strbuf, char ch, gboolean upper_case)
 {
-	nm_str_buf_maybe_expand (strbuf, 5, FALSE);
-	strbuf->_priv_str[strbuf->_priv_len++] = ch0;
-	strbuf->_priv_str[strbuf->_priv_len++] = ch1;
-	strbuf->_priv_str[strbuf->_priv_len++] = ch2;
-	strbuf->_priv_str[strbuf->_priv_len++] = ch3;
+    nm_str_buf_maybe_expand(strbuf, 3, FALSE);
+    strbuf->_priv_str[strbuf->_priv_len++] = nm_hexchar(((guchar) ch) >> 4, upper_case);
+    strbuf->_priv_str[strbuf->_priv_len++] = nm_hexchar((guchar) ch, upper_case);
 }
 
 static inline void
-nm_str_buf_append_len (NMStrBuf *strbuf,
-                       const char *str,
-                       gsize len)
+nm_str_buf_append_len(NMStrBuf *strbuf, const char *str, gsize len)
 {
-	_nm_str_buf_assert (strbuf);
+    _nm_str_buf_assert(strbuf);
 
-	if (len > 0) {
-		nm_str_buf_maybe_expand (strbuf, len + 1, FALSE);
-		memcpy (&strbuf->_priv_str[strbuf->_priv_len], str, len);
-		strbuf->_priv_len += len;
-	}
+    if (len > 0) {
+        nm_str_buf_maybe_expand(strbuf, len + 1, FALSE);
+        memcpy(&strbuf->_priv_str[strbuf->_priv_len], str, len);
+        strbuf->_priv_len += len;
+    }
+}
+
+static inline char *
+nm_str_buf_append_len0(NMStrBuf *strbuf, const char *str, gsize len)
+{
+    _nm_str_buf_assert(strbuf);
+
+    /* this is basically like nm_str_buf_append_len() and
+     * nm_str_buf_get_str() in one. */
+
+    nm_str_buf_maybe_expand(strbuf, len + 1u, FALSE);
+    if (len > 0) {
+        memcpy(&strbuf->_priv_str[strbuf->_priv_len], str, len);
+        strbuf->_priv_len += len;
+    }
+    strbuf->_priv_str[strbuf->_priv_len] = '\0';
+    return strbuf->_priv_str;
 }
 
 static inline void
-nm_str_buf_append (NMStrBuf *strbuf,
-                   const char *str)
+nm_str_buf_append(NMStrBuf *strbuf, const char *str)
 {
-	nm_assert (str);
+    nm_assert(str);
 
-	nm_str_buf_append_len (strbuf, str, strlen (str));
+    nm_str_buf_append_len(strbuf, str, strlen(str));
 }
 
-void nm_str_buf_append_printf (NMStrBuf *strbuf,
-                               const char *format,
-                               ...) _nm_printf (2, 3);
+static inline char *
+nm_str_buf_append0(NMStrBuf *strbuf, const char *str)
+{
+    nm_assert(str);
+
+    return nm_str_buf_append_len0(strbuf, str, strlen(str));
+}
+
+void nm_str_buf_append_printf(NMStrBuf *strbuf, const char *format, ...) _nm_printf(2, 3);
 
 static inline void
-nm_str_buf_ensure_trailing_c (NMStrBuf *strbuf, char ch)
+nm_str_buf_ensure_trailing_c(NMStrBuf *strbuf, char ch)
 {
-	_nm_str_buf_assert (strbuf);
+    _nm_str_buf_assert(strbuf);
 
-	if (   strbuf->_priv_len == 0
-	    || strbuf->_priv_str[strbuf->_priv_len - 1] != ch)
-		nm_str_buf_append_c (strbuf, ch);
+    if (strbuf->_priv_len == 0 || strbuf->_priv_str[strbuf->_priv_len - 1] != ch)
+        nm_str_buf_append_c(strbuf, ch);
+}
+
+static inline NMStrBuf *
+nm_str_buf_append_required_delimiter(NMStrBuf *strbuf, char delimiter)
+{
+    _nm_str_buf_assert(strbuf);
+
+    /* appends the @delimiter if it is required (that is, if the
+     * string is not empty). */
+    if (strbuf->len > 0)
+        nm_str_buf_append_c(strbuf, delimiter);
+    return strbuf;
+}
+
+static inline void
+nm_str_buf_reset(NMStrBuf *strbuf, const char *str)
+{
+    _nm_str_buf_assert(strbuf);
+
+    if (strbuf->_priv_len > 0) {
+        if (strbuf->_priv_do_bzero_mem) {
+            /* we only clear the memory that we wrote to. */
+            nm_explicit_bzero(strbuf->_priv_str, strbuf->_priv_len);
+        }
+        strbuf->_priv_len = 0;
+    }
+
+    if (str)
+        nm_str_buf_append(strbuf, str);
+}
+
+/*****************************************************************************/
+
+/* Calls nm_utils_escaped_tokens_escape() on @str and appends the
+ * result to @strbuf. */
+static inline void
+nm_utils_escaped_tokens_escape_strbuf(const char *str, const char *delimiters, NMStrBuf *strbuf)
+{
+    gs_free char *str_to_free = NULL;
+
+    nm_assert(str);
+
+    nm_str_buf_append(strbuf, nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free));
+}
+
+/* Calls nm_utils_escaped_tokens_escape_unnecessary() on @str and appends the
+ * string to @strbuf. */
+static inline void
+nm_utils_escaped_tokens_escape_strbuf_assert(const char *str,
+                                             const char *delimiters,
+                                             NMStrBuf *  strbuf)
+{
+    nm_str_buf_append(strbuf, nm_utils_escaped_tokens_escape_unnecessary(str, delimiters));
 }
 
 /*****************************************************************************/
 
 static inline gboolean
-nm_str_buf_is_initalized (NMStrBuf *strbuf)
+nm_str_buf_is_initalized(NMStrBuf *strbuf)
 {
-	nm_assert (strbuf);
+    nm_assert(strbuf);
 #if NM_MORE_ASSERTS
-	if (strbuf->_priv_str)
-		_nm_str_buf_assert (strbuf);
+    if (strbuf->_priv_str)
+        _nm_str_buf_assert(strbuf);
 #endif
-	return !!strbuf->_priv_str;
+    return !!strbuf->_priv_str;
 }
 
 /**
@@ -282,23 +342,23 @@ nm_str_buf_is_initalized (NMStrBuf *strbuf)
  *   If currently no buffer is allocated, this will return %NULL.
  */
 static inline char *
-nm_str_buf_get_str (NMStrBuf *strbuf)
+nm_str_buf_get_str(NMStrBuf *strbuf)
 {
-	_nm_str_buf_assert (strbuf);
+    _nm_str_buf_assert(strbuf);
 
-	if (!strbuf->_priv_str)
-		return NULL;
+    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;
+    nm_str_buf_maybe_expand(strbuf, 1, FALSE);
+    strbuf->_priv_str[strbuf->_priv_len] = '\0';
+    return strbuf->_priv_str;
 }
 
 static inline char *
-nm_str_buf_get_str_unsafe (NMStrBuf *strbuf)
+nm_str_buf_get_str_unsafe(NMStrBuf *strbuf)
 {
-	_nm_str_buf_assert (strbuf);
-	return strbuf->_priv_str;
+    _nm_str_buf_assert(strbuf);
+    return strbuf->_priv_str;
 }
 
 /**
@@ -314,22 +374,38 @@ nm_str_buf_get_str_unsafe (NMStrBuf *strbuf)
  *   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_finalize(NMStrBuf *strbuf, gsize *out_len)
 {
-	_nm_str_buf_assert (strbuf);
+    _nm_str_buf_assert(strbuf);
+
+    NM_SET_OUT(out_len, strbuf->_priv_len);
 
-	NM_SET_OUT (out_len, strbuf->_priv_len);
+    if (!strbuf->_priv_str)
+        return NULL;
 
-	if (!strbuf->_priv_str)
-		return NULL;
+    nm_str_buf_maybe_expand(strbuf, 1, TRUE);
+    strbuf->_priv_str[strbuf->_priv_len] = '\0';
 
-	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);
+}
 
-	/* 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);
+static inline GBytes *
+nm_str_buf_finalize_to_gbytes(NMStrBuf *strbuf)
+{
+    char *s;
+    gsize l;
+
+    /* this always returns a non-NULL, newly allocated GBytes instance.
+     * The data buffer always has an additional NUL character after
+     * the data, and the data is allocated with malloc.
+     *
+     * That means, the caller who takes ownership of the GBytes can
+     * safely modify the content of the buffer (including the additional
+     * NUL sentinel). */
+    s = nm_str_buf_finalize(strbuf, &l);
+    return g_bytes_new_take(s ?: g_new0(char, 1), l);
 }
 
 /**
@@ -341,21 +417,21 @@ nm_str_buf_finalize (NMStrBuf *strbuf,
  * with nm_str_buf_init().
  */
 static inline void
-nm_str_buf_destroy (NMStrBuf *strbuf)
+nm_str_buf_destroy(NMStrBuf *strbuf)
 {
-	if (!strbuf->_priv_str)
-		return;
-	_nm_str_buf_assert (strbuf);
-	if (strbuf->_priv_do_bzero_mem)
-		nm_explicit_bzero (strbuf->_priv_str, strbuf->_priv_len);
-	g_free (strbuf->_priv_str);
-
-	/* the buffer is in invalid state afterwards, however, we clear it
-	 * so far, that nm_auto_str_buf is happy when calling
-	 * nm_str_buf_destroy() again.  */
-	strbuf->_priv_str = NULL;
+    if (!strbuf->_priv_str)
+        return;
+    _nm_str_buf_assert(strbuf);
+    if (strbuf->_priv_do_bzero_mem)
+        nm_explicit_bzero(strbuf->_priv_str, strbuf->_priv_len);
+    g_free(strbuf->_priv_str);
+
+    /* the buffer is in invalid state afterwards, however, we clear it
+     * so far, that nm_auto_str_buf is happy when calling
+     * nm_str_buf_destroy() again.  */
+    strbuf->_priv_str = NULL;
 }
 
-#define nm_auto_str_buf    nm_auto (nm_str_buf_destroy)
+#define nm_auto_str_buf nm_auto(nm_str_buf_destroy)
 
 #endif /* __NM_STR_BUF_H__ */