mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 09:46:17 +01:00
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:
parent
60c42f6648
commit
1985d54bb2
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user