diff -r fe855ce911f9 -r 26998dc980f9 dav/sync.c --- a/dav/sync.c Wed May 30 12:10:58 2018 +0200 +++ b/dav/sync.c Wed May 30 16:06:03 2018 +0200 @@ -255,31 +255,74 @@ return 1; } -static int matches_tags(UcxList *resource_tags, SyncTagFilter *tagfilter) { - if(!resource_tags) { - return 0; +static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) { + UCX_FOREACH(e, tags) { + if (!ucx_list_contains(dav_tags, e->data, + (cmp_func) compare_tagname, &ignorecase)) { + return 0; + } } - - UcxMap *res_tagmap = ucx_map_new(32); - UCX_FOREACH(elm, resource_tags) { - DavTag *t = elm->data; - // the value actually doesn't matter - ucx_map_cstr_put(res_tagmap, t->name, t); + return 1; +} + +static int matches_tags_or(UcxList *dav_tags, UcxList *tags, int ignorecase) { + UCX_FOREACH(e, tags) { + if (ucx_list_contains(dav_tags, e->data, + (cmp_func) compare_tagname, &ignorecase)) { + return 1; + } } - - int ret = 1; - - // TODO: replace FOREACH with new tag expression evaluation - UCX_FOREACH(elm, tagfilter->tags) { - DavTag *matches_tag = elm->data; - if(!ucx_map_cstr_get(res_tagmap, matches_tag->name)) { - ret = 0; - break; + return 0; +} + +static int matches_tags_one(UcxList *dav_tags, UcxList *tags, int ignorecase) { + int matches_exactly_one = 0; + UCX_FOREACH(e, tags) { + if (ucx_list_contains(dav_tags, e->data, + (cmp_func) compare_tagname, &ignorecase)) { + if (matches_exactly_one) { + return 0; + } else { + matches_exactly_one = 1; + } } } - - ucx_map_free(res_tagmap); - return ret; + return matches_exactly_one; +} + +static int matches_tags_none(UcxList *dav_tags, UcxList *tags, int ignorecase) { + UCX_FOREACH(e, tags) { + if (ucx_list_contains(dav_tags, e->data, + (cmp_func) compare_tagname, &ignorecase)) { + return 0; + } + } + return 1; +} + +static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) { + + if (tagfilter->subfilter_count > 0) { + int ret = 1; + for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) { + ret &= matches_tags(dav_tags, &(tagfilter->subfilters[i])); + } + return ret; + } else { + int ignorecase = 0; // TODO: maybe add support later + switch (tagfilter->mode) { + case DAV_SYNC_TAGFILTER_OR: + return matches_tags_or(dav_tags, tagfilter->tags, ignorecase); + case DAV_SYNC_TAGFILTER_AND: + return matches_tags_and(dav_tags, tagfilter->tags, ignorecase); + case DAV_SYNC_TAGFILTER_NONE: + return matches_tags_none(dav_tags, tagfilter->tags, ignorecase); + case DAV_SYNC_TAGFILTER_ONE: + return matches_tags_one(dav_tags, tagfilter->tags, ignorecase); + default: + abort(); + } + } } static int res_matches_tags(DavResource *res, SyncTagFilter *tagfilter) { @@ -291,8 +334,10 @@ UcxList *res_tags = parse_dav_xml_taglist(tagsprop); int ret = matches_tags(res_tags, tagfilter); - // TODO: free list content + + ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); ucx_list_free(res_tags); + return ret; } @@ -474,8 +519,10 @@ continue; } - + // TODO: remove this fake and let the cmd parser store the filter SyncTagFilter tagfilter; + tagfilter.mode = DAV_SYNC_TAGFILTER_AND; + tagfilter.subfilter_count = 0; tagfilter.tags = NULL; char *tags_str = cmd_getoption(a, "tags"); if(tags_str) {