summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hohmuth <sideral@rockbox.org>2011-05-10 10:25:41 +0000
committerMichael Hohmuth <sideral@rockbox.org>2011-05-10 10:25:41 +0000
commit6a24a7a90363bfbf4c5a0be0585da425506adfab (patch)
treef03b057c7e83f4924e084c2843d42ccedb0939ea
parent8cb4b36ee3513e9c26e16e3d9cf8a788e1809602 (diff)
downloadrockbox-6a24a7a90363bfbf4c5a0be0585da425506adfab.tar.gz
rockbox-6a24a7a90363bfbf4c5a0be0585da425506adfab.zip
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
-rw-r--r--apps/tagcache.c103
-rw-r--r--apps/tagcache.h2
-rw-r--r--apps/tagtree.c24
3 files changed, 78 insertions, 51 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 75191d678e..7555781cbe 100644
--- a/apps/tagcache.c
+++ b/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,
struct index_entry *idx,
- struct tagcache_search_clause **clause, int count)
+ struct tagcache_search_clause **clauses, int count)
{
int i;
-#ifdef HAVE_TC_RAMCACHE
- if (tcs->ramsearch)
+ /* Go through all conditional clauses. */
+ for (i = 0; i < count; i++)
{
- /* Go through all conditional clauses. */
- for (i = 0; i < count; i++)
+ int seek;
+ 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;
- 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);
str = buf;
}
else
{
- tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek];
+ tfe = (struct tagfile_entry *)&hdr->tags[clause->tag][seek];
str = tfe->tag_data;
}
}
-
- if (!check_against_clause(seek, str, clause[i]))
- return false;
}
- }
- else
+ else
#endif
- {
- /* Check for conditions. */
- for (i = 0; i < count; i++)
{
struct tagfile_entry tfe;
- int seek;
- char str[256];
+ str = buf;
- 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);
- if (!TAGCACHE_IS_NUMERIC(clause[i]->tag))
+ memset(buf, 0, sizeof buf);
+ if (!TAGCACHE_IS_NUMERIC(clause->tag))
{
- int fd = tcs->idxfd[clause[i]->tag];
+ int fd = tcs->idxfd[clause->tag];
lseek(fd, seek, SEEK_SET);
ecread_tagfile_entry(fd, &tfe);
- if (tfe.tag_length >= (int)sizeof(str))
+ if (tfe.tag_length >= (int)sizeof(buf))
{
logf("Too long tag read!");
- break ;
+ return false;
}
read(fd, str, tfe.tag_length);
/* Check if entry has been deleted. */
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;
}
- if (!check_against_clause(seek, str, clause[i]))
- return false;
+ if (i < count) /* Found logical-or? */
+ continue; /* Check clauses after logical-or */
+
+ return false;
}
}
@@ -1369,21 +1381,24 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
return false;
}
- /* Check if there is already a similar filter in present (filters are
- * much faster than clauses).
- */
- for (i = 0; i < tcs->filter_count; i++)
- {
- if (tcs->filter_tag[i] == clause->tag)
- return true;
- }
-
- if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
+ if (clause->type != clause_logical_or)
{
- char buf[MAX_PATH];
-
- snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);
- tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
+ /* Check if there is already a similar filter in present (filters are
+ * much faster than clauses).
+ */
+ for (i = 0; i < tcs->filter_count; i++)
+ {
+ if (tcs->filter_tag[i] == clause->tag)
+ return true;
+ }
+
+ 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;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 59f8b8bc9a..7351998c0a 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -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,
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_not_ends_with, clause_oneof, clause_logical_or };
struct tagcache_stat {
bool initialized; /* Is tagcache currently busy? */
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 2a2e2b805b..e7f703154c 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -461,16 +461,18 @@ static int add_format(const char *buf)
while (1)
{
+ struct tagcache_search_clause *newclause;
+
if (clause_count >= TAGCACHE_MAX_CLAUSES)
{
logf("too many clauses");
break;
}
- formats[format_count]->clause[clause_count] =
- buffer_alloc(sizeof(struct tagcache_search_clause));
+ newclause = 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;
clause_count++;
@@ -486,6 +488,7 @@ static int add_format(const char *buf)
static int get_condition(struct search_instruction *inst)
{
+ struct tagcache_search_clause *new_clause;
int clause_count;
char buf[128];
@@ -530,10 +533,15 @@ static int get_condition(struct search_instruction *inst)
return false;
}
- inst->clause[inst->tagorder_count][clause_count] =
- buffer_alloc(sizeof(struct tagcache_search_clause));
+ new_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;
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++)
{
char* searchstring;
+
+ if (csi->clause[i][j]->type == clause_logical_or)
+ continue;
+
source = csi->clause[i][j]->source;
if (source == source_constant)