summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-07-01 17:01:44 +0200
committerThomas Haller <thaller@redhat.com>2015-07-02 14:21:41 +0200
commit1e91f68be8cfd8f960e7494d553f4bd953e19eb1 (patch)
tree2d89326a810ace96fb7d10ec6146db8c25c2f36e
parentc9d9655db23d74c2e611b194bb78a31049647a7a (diff)
downloadNetworkManager-1e91f68be8cfd8f960e7494d553f4bd953e19eb1.tar.gz
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.
-rw-r--r--src/NetworkManagerUtils.c79
-rw-r--r--src/NetworkManagerUtils.h1
-rw-r--r--src/tests/test-general.c16
3 files changed, 95 insertions, 1 deletions
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));