From 1e91f68be8cfd8f960e7494d553f4bd953e19eb1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Jul 2015 17:01:44 +0200 Subject: 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. --- src/NetworkManagerUtils.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/NetworkManagerUtils.h | 1 + src/tests/test-general.c | 16 +++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 24a6f952cb..4ca8bc89b6 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1419,6 +1419,85 @@ nm_match_spec_split (const char *value) 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 * nm_utils_get_shared_wifi_permission (NMConnection *connection) { diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 4c4f55b96e..d9adfc0975 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -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_interface_name (const GSList *specs, const char *interface_name); 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); diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 3397dd9715..eda7a1f892 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -674,13 +674,27 @@ static void test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches) { const char *m; - GSList *specs, *specs_reverse = NULL; + GSList *specs, *specs_reverse = NULL, *specs_resplit, *specs_i, *specs_j; guint i; + gs_free char *specs_joined = NULL; g_assert (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 * matches are inclusive -- except "except:" which always wins. */ specs_reverse = g_slist_reverse (g_slist_copy (specs)); -- cgit v1.2.1