mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 13:12:37 -05:00
tagtree reduce size of get_tag lookup table
this is not a hot path only runs at start-up and tagnav reload so speed is not so much of a concern we can split the data into two separate tables to remove the padding and allow symbols to be stored in uint8 (highest symbol <128) and do strlen at TOU use uint16_t for get_clause() Change-Id: I0f8663d0de9cac102f1d58b43bf200272754c466
This commit is contained in:
parent
bb84e9def5
commit
a29af6e7c6
1 changed files with 69 additions and 72 deletions
139
apps/tagtree.c
139
apps/tagtree.c
|
|
@ -358,69 +358,66 @@ static int get_token_str(char *buf, int size)
|
|||
|
||||
static int get_tag(int *tag)
|
||||
{
|
||||
#define TAG_MATCH(str, tag) {str, sizeof(str) - 1, tag}
|
||||
struct match {const char* str; uint16_t len; uint16_t symbol;};
|
||||
static const struct match get_tag_match[] =
|
||||
#define TAG_TABLE \
|
||||
TAG_MATCH("lm", tag_virt_length_min) \
|
||||
TAG_MATCH("ls", tag_virt_length_sec) \
|
||||
TAG_MATCH("pm", tag_virt_playtime_min) \
|
||||
TAG_MATCH("ps", tag_virt_playtime_sec) \
|
||||
TAG_MATCH("->", menu_next) \
|
||||
TAG_MATCH("~>", menu_shuffle_songs) \
|
||||
TAG_MATCH("==>", menu_load) \
|
||||
TAG_MATCH("year", tag_year) \
|
||||
TAG_MATCH("album", tag_album) \
|
||||
TAG_MATCH("genre", tag_genre) \
|
||||
TAG_MATCH("title", tag_title) \
|
||||
TAG_MATCH("%sort", var_sorttype) \
|
||||
TAG_MATCH("artist", tag_artist) \
|
||||
TAG_MATCH("length", tag_length) \
|
||||
TAG_MATCH("rating", tag_rating) \
|
||||
TAG_MATCH("%limit", var_limit) \
|
||||
TAG_MATCH("%strip", var_strip) \
|
||||
TAG_MATCH("bitrate", tag_bitrate) \
|
||||
TAG_MATCH("comment", tag_comment) \
|
||||
TAG_MATCH("discnum", tag_discnumber) \
|
||||
TAG_MATCH("%format", var_format) \
|
||||
TAG_MATCH("%reload", menu_reload) \
|
||||
TAG_MATCH("filename", tag_filename) \
|
||||
TAG_MATCH("basename", tag_virt_basename) \
|
||||
TAG_MATCH("tracknum", tag_tracknumber) \
|
||||
TAG_MATCH("composer", tag_composer) \
|
||||
TAG_MATCH("ensemble", tag_albumartist) \
|
||||
TAG_MATCH("grouping", tag_grouping) \
|
||||
TAG_MATCH("entryage", tag_virt_entryage) \
|
||||
TAG_MATCH("commitid", tag_commitid) \
|
||||
TAG_MATCH("%include", var_include) \
|
||||
TAG_MATCH("playcount", tag_playcount) \
|
||||
TAG_MATCH("autoscore", tag_virt_autoscore) \
|
||||
TAG_MATCH("lastplayed", tag_lastplayed) \
|
||||
TAG_MATCH("lastoffset", tag_lastoffset) \
|
||||
TAG_MATCH("%root_menu", var_rootmenu) \
|
||||
TAG_MATCH("albumartist", tag_albumartist) \
|
||||
TAG_MATCH("lastelapsed", tag_lastelapsed) \
|
||||
TAG_MATCH("%menu_start", var_menu_start) \
|
||||
TAG_MATCH("%byfirstletter", menu_byfirstletter) \
|
||||
TAG_MATCH("canonicalartist", tag_virt_canonicalartist) \
|
||||
/* END OF TAG_TABLE MACRO */
|
||||
|
||||
/* build two separate arrays tag strings and symbol map*/
|
||||
#define TAG_MATCH(str, tag) str,
|
||||
static const char * const get_tag_match[] =
|
||||
{
|
||||
TAG_MATCH("lm", tag_virt_length_min),
|
||||
TAG_MATCH("ls", tag_virt_length_sec),
|
||||
TAG_MATCH("pm", tag_virt_playtime_min),
|
||||
TAG_MATCH("ps", tag_virt_playtime_sec),
|
||||
TAG_MATCH("->", menu_next),
|
||||
TAG_MATCH("~>", menu_shuffle_songs),
|
||||
|
||||
TAG_MATCH("==>", menu_load),
|
||||
|
||||
TAG_MATCH("year", tag_year),
|
||||
|
||||
TAG_MATCH("album", tag_album),
|
||||
TAG_MATCH("genre", tag_genre),
|
||||
TAG_MATCH("title", tag_title),
|
||||
TAG_MATCH("%sort", var_sorttype),
|
||||
|
||||
TAG_MATCH("artist", tag_artist),
|
||||
TAG_MATCH("length", tag_length),
|
||||
TAG_MATCH("rating", tag_rating),
|
||||
TAG_MATCH("%limit", var_limit),
|
||||
TAG_MATCH("%strip", var_strip),
|
||||
|
||||
TAG_MATCH("bitrate", tag_bitrate),
|
||||
TAG_MATCH("comment", tag_comment),
|
||||
TAG_MATCH("discnum", tag_discnumber),
|
||||
TAG_MATCH("%format", var_format),
|
||||
TAG_MATCH("%reload", menu_reload),
|
||||
|
||||
TAG_MATCH("filename", tag_filename),
|
||||
TAG_MATCH("basename", tag_virt_basename),
|
||||
TAG_MATCH("tracknum", tag_tracknumber),
|
||||
TAG_MATCH("composer", tag_composer),
|
||||
TAG_MATCH("ensemble", tag_albumartist),
|
||||
TAG_MATCH("grouping", tag_grouping),
|
||||
TAG_MATCH("entryage", tag_virt_entryage),
|
||||
TAG_MATCH("commitid", tag_commitid),
|
||||
TAG_MATCH("%include", var_include),
|
||||
|
||||
TAG_MATCH("playcount", tag_playcount),
|
||||
TAG_MATCH("autoscore", tag_virt_autoscore),
|
||||
|
||||
TAG_MATCH("lastplayed", tag_lastplayed),
|
||||
TAG_MATCH("lastoffset", tag_lastoffset),
|
||||
TAG_MATCH("%root_menu", var_rootmenu),
|
||||
|
||||
TAG_MATCH("albumartist", tag_albumartist),
|
||||
TAG_MATCH("lastelapsed", tag_lastelapsed),
|
||||
TAG_MATCH("%menu_start", var_menu_start),
|
||||
|
||||
TAG_MATCH("%byfirstletter", menu_byfirstletter),
|
||||
TAG_MATCH("canonicalartist", tag_virt_canonicalartist),
|
||||
|
||||
TAG_MATCH("", 0) /* sentinel */
|
||||
TAG_TABLE
|
||||
};
|
||||
#undef TAG_MATCH
|
||||
const size_t max_cmd_sz = 32; /* needs to be >= to len of longest tagstr */
|
||||
#define TAG_MATCH(str, tag) tag,
|
||||
static const uint8_t get_tag_symbol[]=
|
||||
{
|
||||
TAG_TABLE
|
||||
};
|
||||
#undef TAG_MATCH
|
||||
|
||||
const char *tagstr;
|
||||
uint16_t tagstr_len;
|
||||
const struct match *match;
|
||||
ptrdiff_t tagstr_len;
|
||||
|
||||
/* Find the start. */
|
||||
while (*strp == ' ' || *strp == '>')
|
||||
|
|
@ -430,24 +427,24 @@ static int get_tag(int *tag)
|
|||
return 0;
|
||||
|
||||
tagstr = strp;
|
||||
for (tagstr_len = 0; tagstr_len < max_cmd_sz; tagstr_len++)
|
||||
while(*strp != '\0' && *strp != ' ') /* walk to the end of the tag */
|
||||
{
|
||||
if (*strp == '\0' || *strp == ' ')
|
||||
break ;
|
||||
strp++;
|
||||
}
|
||||
tagstr_len = strp - tagstr;
|
||||
|
||||
for (match = get_tag_match; match->len != 0; match++)
|
||||
for (size_t i = 0; i < ARRAYLEN(get_tag_match); i++)
|
||||
{
|
||||
if (tagstr_len != match->len)
|
||||
continue;
|
||||
else if (strncasecmp(tagstr, match->str, match->len) == 0)
|
||||
const char *match = get_tag_match[i];
|
||||
if ((ptrdiff_t)strlen(match) == tagstr_len)
|
||||
{
|
||||
*tag = match->symbol;
|
||||
if (strncasecmp(tagstr, match, tagstr_len) == 0)
|
||||
{
|
||||
*tag = get_tag_symbol[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
logf("NO MATCH: %.*s\n", tagstr_len, tagstr);
|
||||
|
||||
return -1;
|
||||
|
|
@ -456,10 +453,10 @@ static int get_tag(int *tag)
|
|||
static int get_clause(int *condition)
|
||||
{
|
||||
/* one or two operator conditionals */
|
||||
#define OPS2VAL(op1, op2) ((int)op1 << 8 | (int)op2)
|
||||
#define OPS2VAL(op1, op2) ((uint16_t)op1 << 8 | (uint16_t)op2)
|
||||
#define CLAUSE(op1, op2, symbol) {OPS2VAL(op1, op2), symbol }
|
||||
|
||||
struct clause_symbol {int value;int symbol;};
|
||||
struct clause_symbol {uint16_t value;uint16_t symbol;};
|
||||
const struct clause_symbol *match;
|
||||
static const struct clause_symbol get_clause_match[] =
|
||||
{
|
||||
|
|
@ -497,7 +494,7 @@ static int get_clause(int *condition)
|
|||
if (op2 == '"') /*allow " to end a single op conditional */
|
||||
op2 = ' ';
|
||||
|
||||
int value = OPS2VAL(op1, op2);
|
||||
uint16_t value = OPS2VAL(op1, op2);
|
||||
|
||||
for (match = get_clause_match; match->value != 0; match++)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue