fileinfo: Add g_file_attribute_matcher_subtract()

Added as public API so I can write tests, the use case is local.
This commit is contained in:
Benjamin Otte 2011-11-01 20:11:47 +01:00
parent 60c42f6648
commit 1985d54bb2
4 changed files with 85 additions and 2 deletions

View File

@ -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

View File

@ -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,11 +2265,82 @@ 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.

View File

@ -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,

View File

@ -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