shared: add nm_utils_strv_dup_packed() util
This commit is contained in:
@@ -3422,6 +3422,74 @@ _nm_utils_strv_dup (const char *const*strv,
|
||||
return v;
|
||||
}
|
||||
|
||||
const char **
|
||||
_nm_utils_strv_dup_packed (const char *const*strv,
|
||||
gssize len)
|
||||
|
||||
{
|
||||
const char **result;
|
||||
gsize mem_len;
|
||||
gsize pre_len;
|
||||
gsize len2;
|
||||
char *sbuf;
|
||||
gsize i;
|
||||
|
||||
nm_assert (len >= -1);
|
||||
|
||||
mem_len = 0;
|
||||
if (G_LIKELY (len < 0)) {
|
||||
if ( !strv
|
||||
|| !strv[0]) {
|
||||
/* This function never returns an empty strv array. If you need that, handle it
|
||||
* yourself. */
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; strv[i]; i++)
|
||||
mem_len += strlen (strv[i]);
|
||||
len2 = i;
|
||||
} else {
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
len2 = len;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (G_LIKELY (strv[i]))
|
||||
mem_len += strlen (strv[i]);
|
||||
}
|
||||
}
|
||||
mem_len += len2;
|
||||
|
||||
pre_len = sizeof (const char *) * (len2 + 1u);
|
||||
|
||||
result = g_malloc (pre_len + mem_len);
|
||||
sbuf = &(((char *) result)[pre_len]);
|
||||
for (i = 0; i < len2; i++) {
|
||||
gsize l;
|
||||
|
||||
if (G_UNLIKELY (!strv[i])) {
|
||||
/* Technically there is no problem with accepting NULL strings. But that
|
||||
* does not really result in a strv array, and likely this only happens due
|
||||
* to a bug. We want to catch such bugs by asserting.
|
||||
*
|
||||
* We clear the remainder of the buffer and fail with an assertion. */
|
||||
len2++;
|
||||
for (; i < len2; i++)
|
||||
result[i] = NULL;
|
||||
g_return_val_if_reached (result);;
|
||||
}
|
||||
|
||||
result[i] = sbuf;
|
||||
|
||||
l = strlen (strv[i]) + 1u;
|
||||
memcpy (sbuf, strv[i], l);
|
||||
sbuf += l;
|
||||
}
|
||||
result[i] = NULL;
|
||||
nm_assert (i == len2);
|
||||
nm_assert (sbuf == (&((const char *) result)[pre_len]) + mem_len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gssize
|
||||
|
@@ -1533,6 +1533,11 @@ char **_nm_utils_strv_dup (const char *const*strv,
|
||||
|
||||
#define nm_utils_strv_dup(strv, len, deep_copied) _nm_utils_strv_dup (NM_CAST_STRV_CC (strv), (len), (deep_copied))
|
||||
|
||||
const char **_nm_utils_strv_dup_packed (const char *const*strv,
|
||||
gssize len);
|
||||
|
||||
#define nm_utils_strv_dup_packed(strv, len) _nm_utils_strv_dup_packed (NM_CAST_STRV_CC (strv), (len))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GSList *nm_utils_g_slist_find_str (const GSList *list,
|
||||
|
@@ -941,6 +941,51 @@ test_is_specific_hostname (void)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_strv_dup_packed (void)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *src = NULL;
|
||||
int i_run;
|
||||
|
||||
|
||||
src = g_ptr_array_new_with_free_func (g_free);
|
||||
|
||||
for (i_run = 0; i_run < 500; i_run++) {
|
||||
const int strv_len = nmtst_get_rand_word_length (NULL);
|
||||
gs_free const char **strv_cpy = NULL;
|
||||
const char *const*strv_src;
|
||||
int i, j;
|
||||
|
||||
g_ptr_array_set_size (src, 0);
|
||||
for (i = 0; i < strv_len; i++) {
|
||||
const int word_len = nmtst_get_rand_word_length (NULL);
|
||||
NMStrBuf sbuf = NM_STR_BUF_INIT (0, nmtst_get_rand_bool ());
|
||||
|
||||
for (j = 0; j < word_len; j++)
|
||||
nm_str_buf_append_c (&sbuf, 'a' + (nmtst_get_rand_uint32 () % 20));
|
||||
|
||||
g_ptr_array_add (src, nm_str_buf_finalize (&sbuf, NULL) ?: g_new0 (char, 1));
|
||||
}
|
||||
g_ptr_array_add (src, NULL);
|
||||
|
||||
strv_src = (const char *const*) src->pdata;
|
||||
g_assert (strv_src);
|
||||
g_assert (NM_PTRARRAY_LEN (strv_src) == strv_len);
|
||||
|
||||
strv_cpy = nm_utils_strv_dup_packed (strv_src,
|
||||
nmtst_get_rand_bool () ? (gssize) strv_len : (gssize) -1);
|
||||
if (strv_len == 0)
|
||||
g_assert (!strv_cpy);
|
||||
else
|
||||
g_assert (strv_cpy);
|
||||
g_assert (NM_PTRARRAY_LEN (strv_cpy) == strv_len);
|
||||
if (strv_cpy)
|
||||
g_assert (_nm_utils_strv_equal ((char **) strv_cpy, (char **) strv_src));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
@@ -965,6 +1010,7 @@ int main (int argc, char **argv)
|
||||
g_test_add_func ("/general/test_nm_utils_parse_next_line", test_nm_utils_parse_next_line);
|
||||
g_test_add_func ("/general/test_in_strset_ascii_case", test_in_strset_ascii_case);
|
||||
g_test_add_func ("/general/test_is_specific_hostname", test_is_specific_hostname);
|
||||
g_test_add_func ("/general/test_strv_dup_packed", test_strv_dup_packed);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user