return 0;
}
+/* Matches if all items from selection string list match. */
+static int _cmp_field_string_list_all(const struct str_list_sort_value *val,
+ const struct selection_str_list *sel)
+{
+ struct dm_str_list *sel_item;
+ unsigned int i = 1;
+
+ /* if item count differs, it's clear the lists do not match */
+ if (val->items[0].len != dm_list_size(sel->list))
+ return 0;
+
+ /* both lists are sorted so they either match 1:1 or not */
+ dm_list_iterate_items(sel_item, sel->list) {
+ if (strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len))
+ return 0;
+ i++;
+ }
+
+ return 1;
+}
+
+/* Matches if any item from selection string list matches. */
+static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
+ const struct selection_str_list *sel)
+{
+ struct dm_str_list *sel_item;
+ unsigned int i;
+
+ /* if value has no items and selection has at least one, it's clear there's no match */
+ if ((val->items[0].len == 0) && dm_list_size(sel->list))
+ return 0;
+
+ dm_list_iterate_items(sel_item, sel->list) {
+ /*
+ * TODO: Optimize this so we don't need to compare the whole lists' content.
+ * Make use of the fact that the lists are sorted!
+ */
+ for (i = 1; i <= val->items[0].len; i++) {
+ if (!strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int _cmp_field_string_list(const char *field_id,
+ const struct str_list_sort_value *value,
+ const struct selection_str_list *selection, uint32_t flags)
+{
+ int r;
+
+ switch (selection->type & SEL_MASK) {
+ case SEL_AND:
+ r = _cmp_field_string_list_all(value, selection);
+ break;
+ case SEL_OR:
+ r = _cmp_field_string_list_any(value, selection);
+ break;
+ default:
+ log_error(INTERNAL_ERROR "_cmp_field_string_list: unsupported string "
+ "list type found, expecting either AND or OR list for "
+ "selection field %s", field_id);
+ return 0;
+ }
+
+ return flags & FLD_CMP_NOT ? !r : r;
+}
+
static int _cmp_field_regex(const char *s, struct dm_regex *r, uint32_t flags)
{
int match = dm_regex_match(r, s) >= 0;
case DM_REPORT_FIELD_TYPE_STRING:
r = _cmp_field_string(field_id, (const char *) f->sort_value, fs->v.s, fs->flags);
break;
+ case DM_REPORT_FIELD_TYPE_STRING_LIST:
+ r = _cmp_field_string_list(field_id, (const struct str_list_sort_value *) f->sort_value,
+ fs->v.l, fs->flags);
+ break;
default:
log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id);
}