shared: add "strip" argument to _nm_utils_unescape_spaces()

It's usually not necessary, because _nm_utils_unescape_spaces()
gets called after nm_utils_strsplit_set(), which already removes
the non-escaped spaces.

Still, for completeness, this should be here. Also, because with
this the function is useful for individual options (not delimiter
separate list values), to support automatically dropping leading or
trailing whitespace, but also support escaping them.
This commit is contained in:
Thomas Haller 2019-03-19 13:52:52 +01:00
parent b91f21aa23
commit e3fa570c1b
5 changed files with 87 additions and 22 deletions

View file

@ -3229,7 +3229,7 @@ _set_fcn_match_interface_name (ARGS_SET_FCN)
if (strv) {
for (i = 0; strv[i]; i++) {
nm_setting_match_add_interface_name (NM_SETTING_MATCH (setting),
_nm_utils_unescape_spaces ((char *) strv[i]));
_nm_utils_unescape_spaces ((char *) strv[i], TRUE));
}
}
return TRUE;

View file

@ -7733,24 +7733,73 @@ test_nm_utils_escape_spaces (void)
g_free (to_free);
}
static void
_do_test_unescape_spaces (const char *in, const char *out)
{
nm_auto_free_gstring GString *str_out = g_string_new (NULL);
nm_auto_free_gstring GString *str_in = g_string_new (NULL);
guint i;
for (i = 0; i < 10; i++) {
g_string_set_size (str_in, 0);
g_string_append (str_in, in);
if (i == 0)
g_assert_cmpstr (_nm_utils_unescape_spaces (str_in->str, FALSE), ==, out);
else if (i == 1)
g_assert_cmpstr (_nm_utils_unescape_spaces (str_in->str, TRUE), ==, out);
else {
bool do_strip = nmtst_get_rand_bool ();
guint n = nmtst_get_rand_int () % 20;
guint j;
g_string_set_size (str_out, 0);
if (!do_strip)
g_string_append (str_out, out);
for (j = 0; j < n; j++) {
gboolean append = nmtst_get_rand_bool ();
char ch = nmtst_rand_select (' ', '\t');
if (append && out[strlen (out) - 1] == '\\')
append = FALSE;
g_string_insert_c (str_in, append ? -1 : 0, ch);
if (!do_strip)
g_string_insert_c (str_out, append ? -1 : 0, ch);
}
if (do_strip)
g_assert_cmpstr (_nm_utils_unescape_spaces (str_in->str, TRUE), ==, out);
else
g_assert_cmpstr (_nm_utils_unescape_spaces (str_in->str, FALSE), ==, str_out->str);
}
}
}
static void
test_nm_utils_unescape_spaces (void)
{
#define CHECK_STR(in, out) \
G_STMT_START { \
gs_free char *str = g_strdup (in); \
\
g_assert_cmpstr (_nm_utils_unescape_spaces (str), ==, out); \
} G_STMT_END
CHECK_STR ("\\a", "\\a");
CHECK_STR ("foobar", "foobar");
CHECK_STR ("foo bar", "foo bar");
CHECK_STR ("foo\\ bar", "foo bar");
CHECK_STR ("foo\\", "foo\\");
CHECK_STR ("\\\\\t", "\\\t");
#undef CHECK_STR
_do_test_unescape_spaces ("", "");
_do_test_unescape_spaces ("\\", "\\");
_do_test_unescape_spaces ("\\ ", " ");
_do_test_unescape_spaces ("\\\t", "\t");
_do_test_unescape_spaces ("a", "a");
_do_test_unescape_spaces ("\\a", "\\a");
_do_test_unescape_spaces ("foobar", "foobar");
_do_test_unescape_spaces ("foo bar", "foo bar");
_do_test_unescape_spaces ("foo\\ bar", "foo bar");
_do_test_unescape_spaces ("foo\\", "foo\\");
_do_test_unescape_spaces ("\\\\", "\\\\");
_do_test_unescape_spaces ("foo bar", "foo bar");
_do_test_unescape_spaces ("\\ foo bar", " foo bar");
_do_test_unescape_spaces ("\\ foo bar\\ ", " foo bar ");
_do_test_unescape_spaces ("\\\tfoo bar\\\t", "\tfoo bar\t");
_do_test_unescape_spaces ("\\\tfoo bar \\\t", "\tfoo bar \t");
_do_test_unescape_spaces ("\\\t", "\t");
_do_test_unescape_spaces ("\\\t \\ ", "\t ");
}
/*****************************************************************************/

View file

@ -2458,20 +2458,36 @@ _nm_utils_escape_spaces (const char *str, char **to_free)
}
char *
_nm_utils_unescape_spaces (char *str)
_nm_utils_unescape_spaces (char *str, gboolean do_strip)
{
guint i, j = 0;
gsize i = 0;
gsize j = 0;
gsize preserve_space_at = 0;
if (!str)
return NULL;
for (i = 0; str[i]; i++) {
if (str[i] == '\\' && IS_SPACE (str[i+1]))
if (do_strip) {
while (str[i] && IS_SPACE (str[i]))
i++;
}
for (; str[i]; i++) {
if ( str[i] == '\\'
&& IS_SPACE (str[i+1])) {
preserve_space_at = j;
i++;
}
str[j++] = str[i];
}
str[j] = '\0';
if (do_strip && j > 0) {
while ( --j > preserve_space_at
&& IS_SPACE (str[j]))
str[j] = '\0';
}
return str;
}

View file

@ -1085,7 +1085,7 @@ void _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...);
/*****************************************************************************/
const char *_nm_utils_escape_spaces (const char *str, char **to_free);
char *_nm_utils_unescape_spaces (char *str);
char *_nm_utils_unescape_spaces (char *str, gboolean do_strip);
/*****************************************************************************/

View file

@ -1449,7 +1449,7 @@ make_match_setting (shvarFile *ifcfg)
if (!s_match)
s_match = (NMSettingMatch *) nm_setting_match_new ();
nm_setting_match_add_interface_name (s_match,
_nm_utils_unescape_spaces ((char *) strv[i]));
_nm_utils_unescape_spaces ((char *) strv[i], TRUE));
}
}