core: add nm_match_spec_join() function

We have a special implemenation nm_match_spec_split() to split
a string. We also need the reverse operation to be able to convert
a list of specs to string without loss.
This commit is contained in:
Thomas Haller
2015-07-01 17:01:44 +02:00
parent ed632207cd
commit bd57d76af8
3 changed files with 95 additions and 1 deletions

View File

@@ -1419,6 +1419,85 @@ nm_match_spec_split (const char *value)
return g_slist_reverse (pieces); return g_slist_reverse (pieces);
} }
/**
* nm_match_spec_join:
* @specs: the device specs to join
*
* This is based on g_key_file_parse_string_as_value(), analog to
* nm_match_spec_split() which is based on g_key_file_parse_value_as_string().
*
* Returns: (transfer-full): a joined list of device specs that can be
* split again with nm_match_spec_split(). Note that
* nm_match_spec_split (nm_match_spec_join (specs)) yields the original
* result (which is not true the other way around because there are multiple
* ways to encode the same joined specs string).
*/
char *
nm_match_spec_join (GSList *specs)
{
const char *p;
GString *str;
str = g_string_new ("");
for (; specs; specs = specs->next) {
p = specs->data;
if (!p || !*p)
continue;
if (str->len > 0)
g_string_append_c (str, ',');
/* escape leading whitespace */
switch (*p) {
case ' ':
g_string_append (str, "\\s");
p++;
break;
case '\t':
g_string_append (str, "\\t");
p++;
break;
}
for (; *p; p++) {
switch (*p) {
case '\n':
g_string_append (str, "\\n");
break;
case '\r':
g_string_append (str, "\\r");
break;
case '\\':
g_string_append (str, "\\\\");
break;
case ',':
g_string_append (str, "\\,");
break;
case ';':
g_string_append (str, "\\;");
break;
default:
g_string_append_c (str, *p);
break;
}
}
/* escape trailing whitespaces */
switch (str->str[str->len - 1]) {
case ' ':
g_string_overwrite (str, str->len - 1, "\\s");
break;
case '\t':
g_string_overwrite (str, str->len - 1, "\\t");
break;
}
}
return g_string_free (str, FALSE);
}
const char * const char *
nm_utils_get_shared_wifi_permission (NMConnection *connection) nm_utils_get_shared_wifi_permission (NMConnection *connection)
{ {

View File

@@ -98,6 +98,7 @@ NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwad
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels); NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name); NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
GSList *nm_match_spec_split (const char *value); GSList *nm_match_spec_split (const char *value);
char *nm_match_spec_join (GSList *specs);
const char *nm_utils_get_shared_wifi_permission (NMConnection *connection); const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);

View File

@@ -674,13 +674,27 @@ static void
test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches) test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches)
{ {
const char *m; const char *m;
GSList *specs, *specs_reverse = NULL; GSList *specs, *specs_reverse = NULL, *specs_resplit, *specs_i, *specs_j;
guint i; guint i;
gs_free char *specs_joined = NULL;
g_assert (spec_str); g_assert (spec_str);
specs = nm_match_spec_split (spec_str); specs = nm_match_spec_split (spec_str);
/* assert that split(join(specs)) == specs */
specs_joined = nm_match_spec_join (specs);
specs_resplit = nm_match_spec_split (specs_joined);
specs_i = specs;
specs_j = specs_resplit;
while (specs_i && specs_j && g_strcmp0 (specs_i->data, specs_j->data) == 0) {
specs_i = specs_i->next;
specs_j = specs_j->next;
}
g_assert (!specs_i);
g_assert (!specs_j);
g_slist_free_full (specs_resplit, g_free);
/* also check the matches in the reverse order. They must yield the same result because /* also check the matches in the reverse order. They must yield the same result because
* matches are inclusive -- except "except:" which always wins. */ * matches are inclusive -- except "except:" which always wins. */
specs_reverse = g_slist_reverse (g_slist_copy (specs)); specs_reverse = g_slist_reverse (g_slist_copy (specs));