[glib] fileinfo: Add g_file_attribute_matcher_subtract()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] fileinfo: Add g_file_attribute_matcher_subtract()
- Date: Wed, 16 Nov 2011 16:31:50 +0000 (UTC)
commit 1985d54bb2eee39e88e62d1b749bf85f43a55721
Author: Benjamin Otte <otte redhat com>
Date: Tue Nov 1 20:11:47 2011 +0100
fileinfo: Add g_file_attribute_matcher_subtract()
Added as public API so I can write tests, the use case is local.
docs/reference/gio/gio-sections.txt | 1 +
gio/gfileinfo.c | 83 ++++++++++++++++++++++++++++++++++-
gio/gfileinfo.h | 2 +
gio/gio.symbols | 1 +
4 files changed, 85 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index faa7f98..71572bc 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -365,6 +365,7 @@ g_file_info_set_symlink_target
g_file_info_set_sort_order
g_file_attribute_matcher_new
g_file_attribute_matcher_ref
+g_file_attribute_matcher_subtract
g_file_attribute_matcher_unref
g_file_attribute_matcher_matches
g_file_attribute_matcher_matches_only
diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c
index db4d781..87767bc 100644
--- a/gio/gfileinfo.c
+++ b/gio/gfileinfo.c
@@ -2136,7 +2136,7 @@ sub_matcher_matches (SubMatcher *matcher,
/* Call this function after modifying a matcher.
* It will ensure all the invariants other functions rely on.
*/
-static void
+static GFileAttributeMatcher *
matcher_optimize (GFileAttributeMatcher *matcher)
{
SubMatcher *submatcher, *compare;
@@ -2153,6 +2153,12 @@ matcher_optimize (GFileAttributeMatcher *matcher)
return matcher;
}
+ if (matcher->sub_matchers->len == 0)
+ {
+ g_file_attribute_matcher_unref (matcher);
+ return NULL;
+ }
+
/* sort sub_matchers by id (and then mask), so we can bsearch
* and compare matchers in O(N) instead of O(NÂ) */
g_array_sort (matcher->sub_matchers, compare_sub_matchers);
@@ -2175,6 +2181,8 @@ matcher_optimize (GFileAttributeMatcher *matcher)
}
g_array_set_size (matcher->sub_matchers, j + 1);
+
+ return matcher;
}
/**
@@ -2257,12 +2265,83 @@ g_file_attribute_matcher_new (const char *attributes)
g_strfreev (split);
- matcher_optimize (matcher);
+ matcher = matcher_optimize (matcher);
return matcher;
}
/**
+ * g_file_attribute_matcher_subtract:
+ * @matcher: Matcher to subtract from
+ * @subtract: The matcher to subtract
+ *
+ * Subtracts all attributes of @subtract from @matcher and returns
+ * a matcher that supports those attributes.
+ *
+ * Note that currently it is not possible to remove a single
+ * attribute when the @matcher matches the whole namespace - or remove
+ * a namespace or attribute when the matcher matches everything. This
+ * is a limitation of the current implementation, but may be fixed
+ * in the future.
+ *
+ * Returns: A file attribute matcher matching all attributes of
+ * @matcher that are not matched by @subtract
+ **/
+GFileAttributeMatcher *
+g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
+ GFileAttributeMatcher *subtract)
+{
+ GFileAttributeMatcher *result;
+ guint mi, si;
+ SubMatcher *msub, *ssub;
+
+ if (matcher == NULL)
+ return NULL;
+ if (subtract == NULL)
+ return g_file_attribute_matcher_ref (matcher);
+ if (subtract->all)
+ return NULL;
+ if (matcher->all)
+ return g_file_attribute_matcher_ref (matcher);
+
+ result = g_malloc0 (sizeof (GFileAttributeMatcher));
+ result->ref = 1;
+ result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
+
+ si = 0;
+ g_assert (subtract->sub_matchers->len > 0);
+ ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
+
+ for (mi = 0; mi < matcher->sub_matchers->len; mi++)
+ {
+ msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
+
+retry:
+ if (sub_matcher_matches (ssub, msub))
+ continue;
+
+ si++;
+ if (si >= subtract->sub_matchers->len)
+ break;
+
+ ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
+ if (ssub->id <= msub->id)
+ goto retry;
+
+ g_array_append_val (result->sub_matchers, *msub);
+ }
+
+ if (mi < matcher->sub_matchers->len)
+ g_array_append_vals (result->sub_matchers,
+ &g_array_index (matcher->sub_matchers, SubMatcher, mi),
+ matcher->sub_matchers->len - mi);
+
+ result = matcher_optimize (result);
+
+ return result;
+}
+
+/**
* g_file_attribute_matcher_ref:
* @matcher: a #GFileAttributeMatcher.
*
diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h
index e276518..952dade 100644
--- a/gio/gfileinfo.h
+++ b/gio/gfileinfo.h
@@ -939,6 +939,8 @@ GType g_file_attribute_matcher_get_type (void) G_GNUC_CON
GFileAttributeMatcher *g_file_attribute_matcher_new (const char *attributes);
GFileAttributeMatcher *g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher);
void g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher);
+GFileAttributeMatcher *g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
+ GFileAttributeMatcher *subtract);
gboolean g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
const char *attribute);
gboolean g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 72eaa7d..0cb45bf 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -431,6 +431,7 @@ g_file_info_set_symlink_target
g_file_info_set_sort_order
g_file_attribute_matcher_get_type
g_file_attribute_matcher_new
+g_file_attribute_matcher_subtract
g_file_attribute_matcher_ref
g_file_attribute_matcher_unref
g_file_attribute_matcher_matches
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]