diff options
author | Thomas Haller <thaller@redhat.com> | 2019-06-27 10:33:14 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-06-28 16:48:17 +0200 |
commit | b4fe51b5faa259f971a9e3d23cfba844526f6c13 (patch) | |
tree | a3f9585af32801ee92d41cf48b4dd3c57ae149ea | |
parent | 1d2df314cc9cbe242b3b1533777b834c6418408d (diff) | |
download | NetworkManager-b4fe51b5faa259f971a9e3d23cfba844526f6c13.tar.gz |
shared: add nm_utils_strv_dup() util
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.c | 56 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.h | 2 |
2 files changed, 58 insertions, 0 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index 472a4c484f..7362dfc930 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -2345,6 +2345,62 @@ nm_utils_strv_make_deep_copied_n (const char **strv, gsize len) return (char **) strv; } +/** + * @strv: the strv array to copy. It may be %NULL if @len + * is negative or zero (in which case %NULL will be returned). + * @len: the length of strings in @str. If negative, strv is assumed + * to be a NULL terminated array. + * + * Like g_strdupv(), with two differences: + * + * - accepts a @len parameter for non-null terminated strv array. + * + * - this never returns an empty strv array, but always %NULL if + * there are no strings. + * + * Note that if @len is non-negative, then it still must not + * contain any %NULL pointers within the first @len elements. + * Otherwise you would leak elements if you try to free the + * array with g_strfreev(). Allowing that would be error prone. + * + * Returns: (transfer full): a clone of the strv array. Always + * %NULL terminated. + */ +char ** +nm_utils_strv_dup (gpointer strv, gssize len) +{ + gsize i, l; + char **v; + const char *const *const src = strv; + + if (len < 0) + l = NM_PTRARRAY_LEN (src); + else + l = len; + if (l == 0) { + /* this function never returns an empty strv array. If you + * need that, handle it yourself. */ + return NULL; + } + + v = g_new (char *, l + 1); + for (i = 0; i < l; i++) { + + if (G_UNLIKELY (!src[i])) { + /* NULL strings are not allowed. Clear the remainder of the array + * and return it (with assertion failure). */ + l++; + for (; i < l; i++) + v[i] = NULL; + g_return_val_if_reached (v); + } + + v[i] = g_strdup (src[i]); + } + v[l] = NULL; + return v; +} + /*****************************************************************************/ gssize diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index e65d1be683..7de6c06208 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -979,6 +979,8 @@ nm_utils_strv_make_deep_copied_nonnull (const char **strv) return nm_utils_strv_make_deep_copied (strv) ?: g_new0 (char *, 1); } +char **nm_utils_strv_dup (gpointer strv, gssize len); + /*****************************************************************************/ GSList *nm_utils_g_slist_find_str (const GSList *list, |