mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
tagnavi.config: Add a logical-OR operator ("|") for tagnavi conditionals.
Logical-AND ("&") always takes precedence over logical-OR. (Parentheses are not supported.) Fight binsize increase by storing some common expressions in local variables. This avoids repeated reevaluations involving memory accesses. check_clauses: Fail clause (return false) in case of errors (tag too long, DB entry deleted). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29851 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
8cb4b36ee3
commit
6a24a7a903
3 changed files with 78 additions and 51 deletions
103
apps/tagcache.c
103
apps/tagcache.c
|
@ -984,74 +984,86 @@ static bool check_against_clause(long numeric, const char *str,
|
||||||
|
|
||||||
static bool check_clauses(struct tagcache_search *tcs,
|
static bool check_clauses(struct tagcache_search *tcs,
|
||||||
struct index_entry *idx,
|
struct index_entry *idx,
|
||||||
struct tagcache_search_clause **clause, int count)
|
struct tagcache_search_clause **clauses, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef HAVE_TC_RAMCACHE
|
/* Go through all conditional clauses. */
|
||||||
if (tcs->ramsearch)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
/* Go through all conditional clauses. */
|
int seek;
|
||||||
for (i = 0; i < count; i++)
|
char buf[256];
|
||||||
|
char *str;
|
||||||
|
struct tagcache_search_clause *clause = clauses[i];
|
||||||
|
|
||||||
|
if (clause->type == clause_logical_or)
|
||||||
|
break; /* all conditions before logical-or satisfied --
|
||||||
|
stop processing clauses */
|
||||||
|
|
||||||
|
#ifdef HAVE_TC_RAMCACHE
|
||||||
|
str = NULL;
|
||||||
|
|
||||||
|
if (tcs->ramsearch)
|
||||||
{
|
{
|
||||||
struct tagfile_entry *tfe;
|
struct tagfile_entry *tfe;
|
||||||
int seek;
|
|
||||||
char buf[256];
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx);
|
seek = check_virtual_tags(clause->tag, tcs->idx_id, idx);
|
||||||
|
|
||||||
if (!TAGCACHE_IS_NUMERIC(clause[i]->tag))
|
if (!TAGCACHE_IS_NUMERIC(clause->tag))
|
||||||
{
|
{
|
||||||
if (clause[i]->tag == tag_filename)
|
if (clause->tag == tag_filename)
|
||||||
{
|
{
|
||||||
retrieve(tcs, idx, tag_filename, buf, sizeof buf);
|
retrieve(tcs, idx, tag_filename, buf, sizeof buf);
|
||||||
str = buf;
|
str = buf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek];
|
tfe = (struct tagfile_entry *)&hdr->tags[clause->tag][seek];
|
||||||
str = tfe->tag_data;
|
str = tfe->tag_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_against_clause(seek, str, clause[i]))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
/* Check for conditions. */
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
struct tagfile_entry tfe;
|
struct tagfile_entry tfe;
|
||||||
int seek;
|
str = buf;
|
||||||
char str[256];
|
|
||||||
|
|
||||||
seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx);
|
seek = check_virtual_tags(clause->tag, tcs->idx_id, idx);
|
||||||
|
|
||||||
memset(str, 0, sizeof str);
|
memset(buf, 0, sizeof buf);
|
||||||
if (!TAGCACHE_IS_NUMERIC(clause[i]->tag))
|
if (!TAGCACHE_IS_NUMERIC(clause->tag))
|
||||||
{
|
{
|
||||||
int fd = tcs->idxfd[clause[i]->tag];
|
int fd = tcs->idxfd[clause->tag];
|
||||||
lseek(fd, seek, SEEK_SET);
|
lseek(fd, seek, SEEK_SET);
|
||||||
ecread_tagfile_entry(fd, &tfe);
|
ecread_tagfile_entry(fd, &tfe);
|
||||||
if (tfe.tag_length >= (int)sizeof(str))
|
if (tfe.tag_length >= (int)sizeof(buf))
|
||||||
{
|
{
|
||||||
logf("Too long tag read!");
|
logf("Too long tag read!");
|
||||||
break ;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
read(fd, str, tfe.tag_length);
|
read(fd, str, tfe.tag_length);
|
||||||
|
|
||||||
/* Check if entry has been deleted. */
|
/* Check if entry has been deleted. */
|
||||||
if (str[0] == '\0')
|
if (str[0] == '\0')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!check_against_clause(seek, str, clause))
|
||||||
|
{
|
||||||
|
/* Clause failed -- try finding a logical-or clause */
|
||||||
|
while (++i < count)
|
||||||
|
{
|
||||||
|
if (clauses[i]->type == clause_logical_or)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_against_clause(seek, str, clause[i]))
|
if (i < count) /* Found logical-or? */
|
||||||
return false;
|
continue; /* Check clauses after logical-or */
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,21 +1381,24 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there is already a similar filter in present (filters are
|
if (clause->type != clause_logical_or)
|
||||||
* much faster than clauses).
|
|
||||||
*/
|
|
||||||
for (i = 0; i < tcs->filter_count; i++)
|
|
||||||
{
|
{
|
||||||
if (tcs->filter_tag[i] == clause->tag)
|
/* Check if there is already a similar filter in present (filters are
|
||||||
return true;
|
* much faster than clauses).
|
||||||
}
|
*/
|
||||||
|
for (i = 0; i < tcs->filter_count; i++)
|
||||||
if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
|
{
|
||||||
{
|
if (tcs->filter_tag[i] == clause->tag)
|
||||||
char buf[MAX_PATH];
|
return true;
|
||||||
|
}
|
||||||
snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);
|
|
||||||
tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
|
if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
|
||||||
|
{
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);
|
||||||
|
tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcs->clause[tcs->clause_count] = clause;
|
tcs->clause[tcs->clause_count] = clause;
|
||||||
|
|
|
@ -120,7 +120,7 @@ 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,
|
enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq,
|
||||||
clause_lt, clause_lteq, clause_contains, clause_not_contains,
|
clause_lt, clause_lteq, clause_contains, clause_not_contains,
|
||||||
clause_begins_with, clause_not_begins_with, clause_ends_with,
|
clause_begins_with, clause_not_begins_with, clause_ends_with,
|
||||||
clause_not_ends_with, clause_oneof };
|
clause_not_ends_with, clause_oneof, clause_logical_or };
|
||||||
|
|
||||||
struct tagcache_stat {
|
struct tagcache_stat {
|
||||||
bool initialized; /* Is tagcache currently busy? */
|
bool initialized; /* Is tagcache currently busy? */
|
||||||
|
|
|
@ -461,16 +461,18 @@ static int add_format(const char *buf)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
struct tagcache_search_clause *newclause;
|
||||||
|
|
||||||
if (clause_count >= TAGCACHE_MAX_CLAUSES)
|
if (clause_count >= TAGCACHE_MAX_CLAUSES)
|
||||||
{
|
{
|
||||||
logf("too many clauses");
|
logf("too many clauses");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
formats[format_count]->clause[clause_count] =
|
newclause = buffer_alloc(sizeof(struct tagcache_search_clause));
|
||||||
buffer_alloc(sizeof(struct tagcache_search_clause));
|
|
||||||
|
|
||||||
if (!read_clause(formats[format_count]->clause[clause_count]))
|
formats[format_count]->clause[clause_count] = newclause;
|
||||||
|
if (!read_clause(newclause))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
clause_count++;
|
clause_count++;
|
||||||
|
@ -486,6 +488,7 @@ static int add_format(const char *buf)
|
||||||
|
|
||||||
static int get_condition(struct search_instruction *inst)
|
static int get_condition(struct search_instruction *inst)
|
||||||
{
|
{
|
||||||
|
struct tagcache_search_clause *new_clause;
|
||||||
int clause_count;
|
int clause_count;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
|
@ -530,10 +533,15 @@ static int get_condition(struct search_instruction *inst)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst->clause[inst->tagorder_count][clause_count] =
|
new_clause = buffer_alloc(sizeof(struct tagcache_search_clause));
|
||||||
buffer_alloc(sizeof(struct tagcache_search_clause));
|
inst->clause[inst->tagorder_count][clause_count] = new_clause;
|
||||||
|
|
||||||
if (!read_clause(inst->clause[inst->tagorder_count][clause_count]))
|
if (*strp == '|')
|
||||||
|
{
|
||||||
|
strp++;
|
||||||
|
new_clause->type = clause_logical_or;
|
||||||
|
}
|
||||||
|
else if (!read_clause(new_clause))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
inst->clause_count[inst->tagorder_count]++;
|
inst->clause_count[inst->tagorder_count]++;
|
||||||
|
@ -1502,6 +1510,10 @@ int tagtree_enter(struct tree_context* c)
|
||||||
for (j = 0; j < csi->clause_count[i]; j++)
|
for (j = 0; j < csi->clause_count[i]; j++)
|
||||||
{
|
{
|
||||||
char* searchstring;
|
char* searchstring;
|
||||||
|
|
||||||
|
if (csi->clause[i][j]->type == clause_logical_or)
|
||||||
|
continue;
|
||||||
|
|
||||||
source = csi->clause[i][j]->source;
|
source = csi->clause[i][j]->source;
|
||||||
|
|
||||||
if (source == source_constant)
|
if (source == source_constant)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue