summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/tagtree.c134
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/common/bsearch.c49
-rw-r--r--firmware/include/bsearch.h28
4 files changed, 147 insertions, 65 deletions
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 @@
29#include <stdio.h> 29#include <stdio.h>
30#include <stdlib.h> 30#include <stdlib.h>
31#include "string-extra.h" 31#include "string-extra.h"
32#include "bsearch.h"
32#include "config.h" 33#include "config.h"
33#include "system.h" 34#include "system.h"
34#include "kernel.h" 35#include "kernel.h"
@@ -160,6 +161,13 @@ struct match
160 int symbol; 161 int symbol;
161}; 162};
162 163
164static int compare_match(const void* _key, const void* _elem)
165{
166 const char* key = _key;
167 const struct match *elem = _elem;
168 return strcasecmp(key, elem->str);
169}
170
163/* Statusbar text of the current view. */ 171/* Statusbar text of the current view. */
164static char current_title[MAX_TAGS][128]; 172static char current_title[MAX_TAGS][128];
165 173
@@ -221,42 +229,42 @@ static int get_token_str(char *buf, int size)
221static int get_tag(int *tag) 229static int get_tag(int *tag)
222{ 230{
223 static const struct match get_tag_match[] = 231 static const struct match get_tag_match[] =
224 { 232 { /* sorted by ascii (case insensitive) for bsearch */
225 {"album", tag_album}, 233 { "%format", var_format },
226 {"artist", tag_artist}, 234 { "%include", var_include },
227 {"bitrate", tag_bitrate}, 235 { "%limit", var_limit },
228 {"composer", tag_composer}, 236 {"%menu_start",var_menu_start},
229 {"comment", tag_comment}, 237 {"%root_menu",var_rootmenu},
230 {"albumartist", tag_albumartist}, 238 { "%sort", var_sorttype },
231 {"ensemble", tag_albumartist}, 239 { "%strip", var_strip },
232 {"grouping", tag_grouping}, 240 {"->",menu_next},
233 {"genre", tag_genre}, 241 { "==>", menu_load },
234 {"length", tag_length}, 242 { "album", tag_album },
235 {"Lm", tag_virt_length_min}, 243 { "albumartist", tag_albumartist },
236 {"Ls", tag_virt_length_sec}, 244 { "artist", tag_artist },
237 {"Pm", tag_virt_playtime_min}, 245 { "autoscore", tag_virt_autoscore },
238 {"Ps", tag_virt_playtime_sec}, 246 { "bitrate", tag_bitrate },
239 {"title", tag_title}, 247 { "comment", tag_comment },
240 {"filename", tag_filename}, 248 { "commitid", tag_commitid },
241 {"tracknum", tag_tracknumber}, 249 { "composer", tag_composer },
242 {"discnum", tag_discnumber}, 250 { "discnum", tag_discnumber },
243 {"year", tag_year}, 251 { "ensemble", tag_albumartist },
244 {"playcount", tag_playcount}, 252 { "entryage", tag_virt_entryage },
245 {"rating", tag_rating}, 253 { "filename", tag_filename },
246 {"lastplayed", tag_lastplayed}, 254 { "genre", tag_genre },
247 {"lastoffset", tag_lastoffset}, 255 { "grouping", tag_grouping },
248 {"commitid", tag_commitid}, 256 { "lastoffset", tag_lastoffset },
249 {"entryage", tag_virt_entryage}, 257 { "lastplayed", tag_lastplayed },
250 {"autoscore", tag_virt_autoscore}, 258 { "length", tag_length },
251 {"%sort", var_sorttype}, 259 { "Lm", tag_virt_length_min },
252 {"%limit", var_limit}, 260 { "Ls", tag_virt_length_sec },
253 {"%strip", var_strip}, 261 { "playcount", tag_playcount },
254 {"%menu_start", var_menu_start}, 262 { "Pm", tag_virt_playtime_min },
255 {"%include", var_include}, 263 { "Ps", tag_virt_playtime_sec },
256 {"%root_menu", var_rootmenu}, 264 { "rating", tag_rating },
257 {"%format", var_format}, 265 { "title", tag_title },
258 {"->", menu_next}, 266 { "tracknum", tag_tracknumber },
259 {"==>", menu_load} 267 { "year", tag_year },
260 }; 268 };
261 char buf[128]; 269 char buf[128];
262 unsigned int i; 270 unsigned int i;
@@ -277,15 +285,13 @@ static int get_tag(int *tag)
277 } 285 }
278 buf[i] = '\0'; 286 buf[i] = '\0';
279 287
280 for (i = 0; i < ARRAYLEN(get_tag_match); i++) 288 struct match *elem = bsearch(buf, get_tag_match, ARRAYLEN(get_tag_match),
289 sizeof(struct match), compare_match);
290 if (elem)
281 { 291 {
282 if (!strcasecmp(buf, get_tag_match[i].str)) 292 *tag = elem->symbol;
283 { 293 return 1;
284 *tag = get_tag_match[i].symbol;
285 return 1;
286 }
287 } 294 }
288
289 logf("NO MATCH: %s\n", buf); 295 logf("NO MATCH: %s\n", buf);
290 if (buf[0] == '?') 296 if (buf[0] == '?')
291 return 0; 297 return 0;
@@ -296,21 +302,21 @@ static int get_tag(int *tag)
296static int get_clause(int *condition) 302static int get_clause(int *condition)
297{ 303{
298 static const struct match get_clause_match[] = 304 static const struct match get_clause_match[] =
299 { 305 { /* sorted by ascii (case insensitive) for bsearch */
300 {"=", clause_is}, 306 { "!$", clause_not_ends_with },
301 {"==", clause_is}, 307 { "!=", clause_is_not },
302 {"!=", clause_is_not}, 308 { "!^", clause_not_begins_with },
303 {">", clause_gt}, 309 { "!~", clause_not_contains },
304 {">=", clause_gteq}, 310 { "$", clause_ends_with },
305 {"<", clause_lt}, 311 { "<", clause_lt },
306 {"<=", clause_lteq}, 312 { "<=", clause_lteq },
307 {"~", clause_contains}, 313 { "=", clause_is },
308 {"!~", clause_not_contains}, 314 { "==", clause_is },
309 {"^", clause_begins_with}, 315 { ">", clause_gt },
310 {"!^", clause_not_begins_with}, 316 { ">=", clause_gteq },
311 {"$", clause_ends_with}, 317 { "@", clause_oneof },
312 {"!$", clause_not_ends_with}, 318 { "^", clause_begins_with },
313 {"@", clause_oneof} 319 { "~", clause_contains },
314 }; 320 };
315 321
316 char buf[4]; 322 char buf[4];
@@ -332,15 +338,13 @@ static int get_clause(int *condition)
332 } 338 }
333 buf[i] = '\0'; 339 buf[i] = '\0';
334 340
335 for (i = 0; i < ARRAYLEN(get_clause_match); i++) 341 struct match *elem = bsearch(buf, get_clause_match, ARRAYLEN(get_clause_match),
342 sizeof(struct match), compare_match);
343 if (elem)
336 { 344 {
337 if (!strcasecmp(buf, get_clause_match[i].str)) 345 *condition = elem->symbol;
338 { 346 return 1;
339 *condition = get_clause_match[i].symbol;
340 return 1;
341 }
342 } 347 }
343
344 return 0; 348 return 0;
345} 349}
346 350
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 4aef86f002..dd3e028e30 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -105,6 +105,7 @@ libc/mktime.c
105 105
106/* Common */ 106/* Common */
107common/version.c 107common/version.c
108common/bsearch.c
108common/config.c 109common/config.c
109common/crc32.c 110common/crc32.c
110#ifdef MI4_FORMAT 111#ifdef MI4_FORMAT
diff --git a/firmware/common/bsearch.c b/firmware/common/bsearch.c
new file mode 100644
index 0000000000..cbfec3578a
--- /dev/null
+++ b/firmware/common/bsearch.c
@@ -0,0 +1,49 @@
1/* Copyright (C) 1991,92,97,2000,02 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19#include <stdlib.h>
20
21
22/* Perform a binary search for KEY in BASE which has NMEMB elements
23 of SIZE bytes each. The comparisons are done by (*COMPAR)(). */
24void *
25bsearch (const void *key, const void *base, size_t nmemb, size_t size,
26 int (*compar) (const void *, const void *))
27{
28 size_t l, u, idx;
29 const void *p;
30 int comparison;
31
32 l = 0;
33 u = nmemb;
34 while (l < u)
35 {
36 idx = (l + u) / 2;
37 p = (void *) (((const char *) base) + (idx * size));
38 comparison = (*compar) (key, p);
39 if (comparison < 0)
40 u = idx;
41 else if (comparison > 0)
42 l = idx + 1;
43 else
44 return (void *) p;
45 }
46
47 return NULL;
48}
49/* libc_hidden_def (bsearch) */
diff --git a/firmware/include/bsearch.h b/firmware/include/bsearch.h
new file mode 100644
index 0000000000..e113676a06
--- /dev/null
+++ b/firmware/include/bsearch.h
@@ -0,0 +1,28 @@
1/* Copyright (C) 1991,92,97,2000,02 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19#ifndef __BSEARCH_H__
20#define __BSEARCH_H__
21
22/* Perform a binary search for KEY in BASE which has NMEMB elements
23 of SIZE bytes each. The comparisons are done by (*COMPAR)(). */
24void *
25bsearch (const void *key, const void *base, size_t nmemb, size_t size,
26 int (*compar) (const void *, const void *));
27
28#endif