466 } |
466 } |
467 } |
467 } |
468 return matches_exactly_one; |
468 return matches_exactly_one; |
469 } |
469 } |
470 |
470 |
471 static int matches_tags_none(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
471 static int matches_tagfilter(UcxList *dav_tags, SyncTagFilter *tagfilter); |
472 UCX_FOREACH(e, tags) { |
472 |
473 if (ucx_list_contains(dav_tags, e->data, |
473 static int matches_subfilters_and(UcxList *dav_tags, SyncTagFilter *filter) { |
474 (cmp_func) compare_tagname, &ignorecase)) { |
474 int ret = 1; |
475 return 0; |
475 for (size_t i = 0 ; i < filter->subfilter_count ; i++) { |
476 } |
476 ret &= matches_tagfilter(dav_tags, filter->subfilters[i]); |
477 } |
477 } |
478 return 1; |
478 return ret; |
479 } |
479 } |
480 |
480 |
481 static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) { |
481 static int matches_subfilters_or(UcxList *dav_tags, SyncTagFilter *filter) { |
|
482 int ret = 0; |
|
483 for (size_t i = 0 ; i < filter->subfilter_count ; i++) { |
|
484 ret |= matches_tagfilter(dav_tags, filter->subfilters[i]); |
|
485 } |
|
486 return ret; |
|
487 } |
|
488 |
|
489 static int matches_subfilters_one(UcxList *dav_tags, SyncTagFilter *filter) { |
|
490 int one = 0; |
|
491 for (size_t i = 0 ; i < filter->subfilter_count ; i++) { |
|
492 if (matches_tagfilter(dav_tags, filter->subfilters[i])) { |
|
493 if (one) { |
|
494 return 0; |
|
495 } else { |
|
496 one = 1; |
|
497 } |
|
498 } |
|
499 } |
|
500 return one; |
|
501 } |
|
502 |
|
503 static int matches_tagfilter(UcxList *dav_tags, SyncTagFilter *tagfilter) { |
482 |
504 |
483 if (tagfilter->subfilter_count > 0) { |
505 if (tagfilter->subfilter_count > 0) { |
484 int ret = 1; |
506 switch (tagfilter->mode) { |
485 for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) { |
507 case DAV_SYNC_TAGFILTER_OR: |
486 ret &= matches_tags(dav_tags, tagfilter->subfilters[i]); |
508 return matches_subfilters_or(dav_tags, tagfilter); |
487 } |
509 case DAV_SYNC_TAGFILTER_AND: |
488 return ret; |
510 return matches_subfilters_and(dav_tags, tagfilter); |
|
511 case DAV_SYNC_TAGFILTER_NONE: |
|
512 return !matches_subfilters_or(dav_tags, tagfilter); |
|
513 case DAV_SYNC_TAGFILTER_ONE: |
|
514 return matches_subfilters_one(dav_tags, tagfilter); |
|
515 default: |
|
516 abort(); |
|
517 } |
489 } else { |
518 } else { |
490 int ignorecase = 0; // TODO: maybe add support later |
519 int ignorecase = 0; // TODO: maybe add support later |
491 switch (tagfilter->mode) { |
520 switch (tagfilter->mode) { |
492 case DAV_SYNC_TAGFILTER_OR: |
521 case DAV_SYNC_TAGFILTER_OR: |
493 return matches_tags_or(dav_tags, tagfilter->tags, ignorecase); |
522 return matches_tags_or(dav_tags, tagfilter->tags, ignorecase); |
494 case DAV_SYNC_TAGFILTER_AND: |
523 case DAV_SYNC_TAGFILTER_AND: |
495 return matches_tags_and(dav_tags, tagfilter->tags, ignorecase); |
524 return matches_tags_and(dav_tags, tagfilter->tags, ignorecase); |
496 case DAV_SYNC_TAGFILTER_NONE: |
525 case DAV_SYNC_TAGFILTER_NONE: |
497 return matches_tags_none(dav_tags, tagfilter->tags, ignorecase); |
526 return !matches_tags_or(dav_tags, tagfilter->tags, ignorecase); |
498 case DAV_SYNC_TAGFILTER_ONE: |
527 case DAV_SYNC_TAGFILTER_ONE: |
499 return matches_tags_one(dav_tags, tagfilter->tags, ignorecase); |
528 return matches_tags_one(dav_tags, tagfilter->tags, ignorecase); |
500 default: |
529 default: |
501 abort(); |
530 abort(); |
502 } |
531 } |
509 } |
538 } |
510 |
539 |
511 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
540 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
512 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
541 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
513 |
542 |
514 int ret = matches_tags(res_tags, tagfilter); |
543 int ret = matches_tagfilter(res_tags, tagfilter); |
515 |
544 |
516 ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); |
545 ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); |
517 ucx_list_free(res_tags); |
546 ucx_list_free(res_tags); |
518 |
547 |
519 return ret; |
548 return ret; |