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:
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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));
|
||||||
|
Reference in New Issue
Block a user