mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-12 07:23:24 -05:00
Add Timo's match patch
This commit is contained in:
parent
9ebe74c9fd
commit
cde5f4c917
@ -28,13 +28,15 @@
|
|||||||
# Date (date)
|
# Date (date)
|
||||||
#
|
#
|
||||||
# Valid operators include:
|
# Valid operators include:
|
||||||
# is, includes (string)
|
# is, includes (string), matches (string)
|
||||||
# >, <, <=, >=, = (int)
|
# >, <, <=, >=, = (int)
|
||||||
# after, before (date)
|
# after, before (date)
|
||||||
#
|
#
|
||||||
# the "is" operator must exactly match the tag,
|
# the "is" operator must exactly match the tag, while
|
||||||
# while the "includes" operator matches a substring.
|
# the "includes" operator matches a substring and
|
||||||
# Both matches are case-insensitive
|
# "matches" operator makes trivial wildcard match using
|
||||||
|
# "?" and "*" as wildcards for any character and any
|
||||||
|
# string accordingly. All matches are case-insensitive.
|
||||||
#
|
#
|
||||||
# Valid operands include:
|
# Valid operands include:
|
||||||
# "string value" (string)
|
# "string value" (string)
|
||||||
|
@ -81,6 +81,7 @@ after { yylval.ival=AFTER; return(AFTER); }
|
|||||||
|
|
||||||
is { yylval.ival=IS; return(IS); }
|
is { yylval.ival=IS; return(IS); }
|
||||||
includes { yylval.ival=INCLUDES; return(INCLUDES); }
|
includes { yylval.ival=INCLUDES; return(INCLUDES); }
|
||||||
|
matches { yylval.ival=INCLUDES; return(MATCHES); }
|
||||||
= { yylval.ival=EQUALS; return(EQUALS); }
|
= { yylval.ival=EQUALS; return(EQUALS); }
|
||||||
|
|
||||||
or |
|
or |
|
||||||
|
@ -72,6 +72,7 @@ int pl_number=2;
|
|||||||
%token <ival> GREATEREQUAL
|
%token <ival> GREATEREQUAL
|
||||||
%token <ival> IS
|
%token <ival> IS
|
||||||
%token <ival> INCLUDES
|
%token <ival> INCLUDES
|
||||||
|
%token <ival> MATCHES
|
||||||
|
|
||||||
%token <ival> OR
|
%token <ival> OR
|
||||||
%token <ival> AND
|
%token <ival> AND
|
||||||
@ -168,6 +169,7 @@ strtag: ARTIST
|
|||||||
|
|
||||||
strbool: IS { $$=$1; }
|
strbool: IS { $$=$1; }
|
||||||
| INCLUDES { $$=$1; }
|
| INCLUDES { $$=$1; }
|
||||||
|
| MATCHES { $$=$1; }
|
||||||
| NOT strbool { $$=$2 | 0x80000000; }
|
| NOT strbool { $$=$2 | 0x80000000; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -48,6 +48,48 @@ int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode);
|
|||||||
|
|
||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
|
|
||||||
|
#define MATCH_WILD_CHR '?'
|
||||||
|
#define MATCH_WILD_STR '*'
|
||||||
|
#define MATCH_CHAR_EQ(m, c, case_sensitive) \
|
||||||
|
(((m) == (c)) || \
|
||||||
|
((! case_sensitive) && \
|
||||||
|
((isalpha((m)) ? toupper((m)) : (m)) == \
|
||||||
|
(isalpha((c)) ? toupper((c)) : (c)))))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* match
|
||||||
|
*
|
||||||
|
* Trivial pattern matcher.
|
||||||
|
* - '*' matches to any (sub)string
|
||||||
|
* - '?' matches to any character
|
||||||
|
* Returs non-zero on match.
|
||||||
|
*/
|
||||||
|
static int match(char *mask, char *str, int case_sensitive)
|
||||||
|
{
|
||||||
|
unsigned char *s, *m;
|
||||||
|
|
||||||
|
m = (unsigned char *)mask;
|
||||||
|
s = (unsigned char *)str;
|
||||||
|
while (*m != '\0') {
|
||||||
|
if ((! MATCH_CHAR_EQ(*m, *s, case_sensitive)) &&
|
||||||
|
(*m != MATCH_WILD_CHR) && (*m != MATCH_WILD_STR)) {
|
||||||
|
return 0;
|
||||||
|
} else if (*m == MATCH_WILD_STR) {
|
||||||
|
m++;
|
||||||
|
while (*s) {
|
||||||
|
if (match((char *)m, (char *)s, case_sensitive))
|
||||||
|
return 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return ((!(*m != '\0')) ? 1 : 0);
|
||||||
|
} else {
|
||||||
|
s++;
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ((!(*s != '\0')) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pl_dump
|
* pl_dump
|
||||||
*
|
*
|
||||||
@ -150,6 +192,9 @@ void pl_dump_node(PL_NODE *pnode, int indent) {
|
|||||||
case INCLUDES:
|
case INCLUDES:
|
||||||
printf("%s",not? "DOES NOT INCLUDE " : "INCLUDES ");
|
printf("%s",not? "DOES NOT INCLUDE " : "INCLUDES ");
|
||||||
break;
|
break;
|
||||||
|
case MATCHES:
|
||||||
|
printf("%s",not? "DOES NOT MATCH " : "MATCHES ");
|
||||||
|
break;
|
||||||
case EQUALS:
|
case EQUALS:
|
||||||
printf("EQUALS ");
|
printf("EQUALS ");
|
||||||
break;
|
break;
|
||||||
@ -355,6 +400,10 @@ int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
|||||||
r_arg=(int)strcasestr(cval,pnode->arg2.cval);
|
r_arg=(int)strcasestr(cval,pnode->arg2.cval);
|
||||||
retval = not ? !r_arg : r_arg;
|
retval = not ? !r_arg : r_arg;
|
||||||
break;
|
break;
|
||||||
|
case MATCHES:
|
||||||
|
r_arg = match(pnode->arg2.cval, cval, 0);
|
||||||
|
retval = not ? r_arg : !r_arg;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user