From 74ab227b58ee3eae152c1142eb9144ee5332a7d9 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Mon, 18 Jul 2011 18:55:20 +0000 Subject: Introduce bsearch() and use it in tagtree.c. bsearch() is a general purpose binary search function for arrays. It's supposedly faster than looping over arrays. The array needs to be sorted in ascending order under the provided comparison function. If the key and array element are of the same kind, then the same compare function can be used for qsort() and bsearch(). Code taken from glibc. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30155 a1c6a512-1295-4272-9138-f99709370657 --- apps/tagtree.c | 134 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 65 deletions(-) (limited to 'apps/tagtree.c') diff --git a/apps/tagtree.c b/apps/tagtree.c index 3df8d9db2b..1bdc0550a6 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -29,6 +29,7 @@ #include #include #include "string-extra.h" +#include "bsearch.h" #include "config.h" #include "system.h" #include "kernel.h" @@ -160,6 +161,13 @@ struct match int symbol; }; +static int compare_match(const void* _key, const void* _elem) +{ + const char* key = _key; + const struct match *elem = _elem; + return strcasecmp(key, elem->str); +} + /* Statusbar text of the current view. */ static char current_title[MAX_TAGS][128]; @@ -221,42 +229,42 @@ static int get_token_str(char *buf, int size) static int get_tag(int *tag) { static const struct match get_tag_match[] = - { - {"album", tag_album}, - {"artist", tag_artist}, - {"bitrate", tag_bitrate}, - {"composer", tag_composer}, - {"comment", tag_comment}, - {"albumartist", tag_albumartist}, - {"ensemble", tag_albumartist}, - {"grouping", tag_grouping}, - {"genre", tag_genre}, - {"length", tag_length}, - {"Lm", tag_virt_length_min}, - {"Ls", tag_virt_length_sec}, - {"Pm", tag_virt_playtime_min}, - {"Ps", tag_virt_playtime_sec}, - {"title", tag_title}, - {"filename", tag_filename}, - {"tracknum", tag_tracknumber}, - {"discnum", tag_discnumber}, - {"year", tag_year}, - {"playcount", tag_playcount}, - {"rating", tag_rating}, - {"lastplayed", tag_lastplayed}, - {"lastoffset", tag_lastoffset}, - {"commitid", tag_commitid}, - {"entryage", tag_virt_entryage}, - {"autoscore", tag_virt_autoscore}, - {"%sort", var_sorttype}, - {"%limit", var_limit}, - {"%strip", var_strip}, - {"%menu_start", var_menu_start}, - {"%include", var_include}, - {"%root_menu", var_rootmenu}, - {"%format", var_format}, - {"->", menu_next}, - {"==>", menu_load} + { /* sorted by ascii (case insensitive) for bsearch */ + { "%format", var_format }, + { "%include", var_include }, + { "%limit", var_limit }, + {"%menu_start",var_menu_start}, + {"%root_menu",var_rootmenu}, + { "%sort", var_sorttype }, + { "%strip", var_strip }, + {"->",menu_next}, + { "==>", menu_load }, + { "album", tag_album }, + { "albumartist", tag_albumartist }, + { "artist", tag_artist }, + { "autoscore", tag_virt_autoscore }, + { "bitrate", tag_bitrate }, + { "comment", tag_comment }, + { "commitid", tag_commitid }, + { "composer", tag_composer }, + { "discnum", tag_discnumber }, + { "ensemble", tag_albumartist }, + { "entryage", tag_virt_entryage }, + { "filename", tag_filename }, + { "genre", tag_genre }, + { "grouping", tag_grouping }, + { "lastoffset", tag_lastoffset }, + { "lastplayed", tag_lastplayed }, + { "length", tag_length }, + { "Lm", tag_virt_length_min }, + { "Ls", tag_virt_length_sec }, + { "playcount", tag_playcount }, + { "Pm", tag_virt_playtime_min }, + { "Ps", tag_virt_playtime_sec }, + { "rating", tag_rating }, + { "title", tag_title }, + { "tracknum", tag_tracknumber }, + { "year", tag_year }, }; char buf[128]; unsigned int i; @@ -277,15 +285,13 @@ static int get_tag(int *tag) } buf[i] = '\0'; - for (i = 0; i < ARRAYLEN(get_tag_match); i++) + struct match *elem = bsearch(buf, get_tag_match, ARRAYLEN(get_tag_match), + sizeof(struct match), compare_match); + if (elem) { - if (!strcasecmp(buf, get_tag_match[i].str)) - { - *tag = get_tag_match[i].symbol; - return 1; - } + *tag = elem->symbol; + return 1; } - logf("NO MATCH: %s\n", buf); if (buf[0] == '?') return 0; @@ -296,21 +302,21 @@ static int get_tag(int *tag) static int get_clause(int *condition) { static const struct match get_clause_match[] = - { - {"=", clause_is}, - {"==", 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} + { /* sorted by ascii (case insensitive) for bsearch */ + { "!$", clause_not_ends_with }, + { "!=", clause_is_not }, + { "!^", clause_not_begins_with }, + { "!~", clause_not_contains }, + { "$", clause_ends_with }, + { "<", clause_lt }, + { "<=", clause_lteq }, + { "=", clause_is }, + { "==", clause_is }, + { ">", clause_gt }, + { ">=", clause_gteq }, + { "@", clause_oneof }, + { "^", clause_begins_with }, + { "~", clause_contains }, }; char buf[4]; @@ -332,15 +338,13 @@ static int get_clause(int *condition) } buf[i] = '\0'; - for (i = 0; i < ARRAYLEN(get_clause_match); i++) + struct match *elem = bsearch(buf, get_clause_match, ARRAYLEN(get_clause_match), + sizeof(struct match), compare_match); + if (elem) { - if (!strcasecmp(buf, get_clause_match[i].str)) - { - *condition = get_clause_match[i].symbol; - return 1; - } + *condition = elem->symbol; + return 1; } - return 0; } -- cgit v1.2.3