diff --git a/apps/tagcache.c b/apps/tagcache.c index b74933dbcd..9d59a5283d 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -239,9 +239,11 @@ static const char * const tag_type_str[] = { [clause_ends_with] = "clause_ends_with", [clause_not_ends_with] = "clause_not_ends_with", [clause_oneof] = "clause_oneof", + [clause_contains_oneof] = "clause_contains_oneof", [clause_begins_oneof] = "clause_begins_oneof", [clause_ends_oneof] = "clause_ends_oneof", [clause_not_oneof] = "clause_not_oneof", + [clause_not_contains_oneof] = "clause_not_contains_oneof", [clause_not_begins_oneof] = "clause_not_begins_oneof", [clause_not_ends_oneof] = "clause_not_ends_oneof", [clause_logical_or] = "clause_logical_or" @@ -1397,6 +1399,28 @@ inline static bool str_begins_ends_oneof(const char *str, const char *list, bool return false; } +inline static bool str_contains_oneof(const char *str, char *list) +{ + logf_clauses("%s %s %s", str, __func__, list); + const char *sep; + int l, len = strlen(str); + + while (*list) + { + sep = strchr(list, '|'); + l = sep ? (intptr_t)sep - (intptr_t)list : (int)strlen(list); + list[l] = '\0'; + if (l <= len && strcasestr(str, list) != NULL) { + if (sep) list[l] = '|'; + return true; + } + if (sep) list[l] = '|'; + list += sep ? l + 1 : l; + } + + return false; +} + static bool check_against_clause(long numeric, const char *str, const struct tagcache_search_clause *clause) { @@ -1462,6 +1486,10 @@ static bool check_against_clause(long numeric, const char *str, case clause_not_begins_oneof: return !str_begins_ends_oneof(str, clause->str, clause->type == clause_not_begins_oneof); + case clause_contains_oneof: + return str_contains_oneof(str, clause->str); + case clause_not_contains_oneof: + return !str_contains_oneof(str, clause->str); default: logf("Incorrect tag: %d", clause->type); } diff --git a/apps/tagcache.h b/apps/tagcache.h index 5c510e02e6..4604fab1d7 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -72,10 +72,9 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, clause_lt, clause_lteq, clause_contains, clause_not_contains, - clause_begins_with, clause_not_begins_with, clause_ends_with, - clause_not_ends_with, clause_oneof, - clause_begins_oneof, clause_ends_oneof, clause_not_oneof, - clause_not_begins_oneof, clause_not_ends_oneof, + clause_begins_with, clause_not_begins_with, clause_ends_with, clause_not_ends_with, + clause_oneof, clause_begins_oneof, clause_ends_oneof, clause_contains_oneof, + clause_not_oneof, clause_not_begins_oneof, clause_not_ends_oneof, clause_not_contains_oneof, clause_logical_or }; struct tagcache_stat { diff --git a/apps/tagtree.c b/apps/tagtree.c index 75752e20a9..67ff646205 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -481,9 +481,11 @@ static int get_clause(int *condition) CLAUSE('!', '^', clause_not_begins_with), CLAUSE('$', ' ', clause_ends_with), CLAUSE('!', '$', clause_not_ends_with), + CLAUSE('@', '~', clause_contains_oneof), CLAUSE('@', '^', clause_begins_oneof), CLAUSE('@', '$', clause_ends_oneof), CLAUSE('@', ' ', clause_oneof), + CLAUSE('*', '~', clause_not_contains_oneof), CLAUSE('*', '^', clause_not_begins_oneof), CLAUSE('*', '$', clause_not_ends_oneof), CLAUSE('!', '@', clause_not_oneof),