From a1ac7434534240f9ce88054028a77466c6e61c7c Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sat, 21 Oct 2006 20:37:33 +0000 Subject: [PATCH] Implement fast_readline as a function and use it for tagtree also. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11301 a1c6a512-1295-4272-9138-f99709370657 --- apps/misc.c | 47 +++++++++ apps/misc.h | 2 + apps/tagcache.c | 55 +++------- apps/tagtree.c | 270 +++++++++++++++++++++++++----------------------- 4 files changed, 199 insertions(+), 175 deletions(-) diff --git a/apps/misc.c b/apps/misc.c index 4be9e43fd9..0936e85569 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -217,6 +217,53 @@ int read_line(int fd, char* buffer, int buffer_size) return errno ? -1 : num_read; } +/* Performance optimized version of the previous function. */ +int fast_readline(int fd, char *buf, int buf_size, void *parameters, + int (*callback)(int n, const char *buf, void *parameters)) +{ + char *p, *next; + int rc, pos = 0; + int count = 0; + + while ( 1 ) + { + next = NULL; + + rc = read(fd, &buf[pos], buf_size - pos - 1); + if (rc >= 0) + buf[pos+rc] = '\0'; + + if ( (p = strchr(buf, '\r')) != NULL) + { + *p = '\0'; + next = ++p; + } + else + p = buf; + + if ( (p = strchr(p, '\n')) != NULL) + { + *p = '\0'; + next = ++p; + } + + rc = callback(count, buf, parameters); + if (rc < 0) + return rc; + + count++; + if (next) + { + pos = buf_size - ((long)next - (long)buf) - 1; + memmove(buf, next, pos); + } + else + break ; + } + + return 0; +} + #ifdef HAVE_LCD_BITMAP #if LCD_DEPTH == 16 diff --git a/apps/misc.h b/apps/misc.h index c5a89901ee..1bc9a23447 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -42,6 +42,8 @@ char *create_datetime_filename(char *buffer, const char *path, * stored in buffer. */ int read_line(int fd, char* buffer, int buffer_size); +int fast_readline(int fd, char *buf, int buf_size, void *parameters, + int (*callback)(int n, const char *buf, void *parameters)); #ifdef HAVE_LCD_BITMAP /* Save a .BMP file containing the current screen contents. */ diff --git a/apps/tagcache.c b/apps/tagcache.c index 38537b5ceb..bf20927d95 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -72,6 +72,7 @@ #include "atoi.h" #include "crc32.h" #include "eeprom_settings.h" +#include "misc.h" /* Tag Cache thread. */ static struct event_queue tagcache_queue; @@ -2687,40 +2688,42 @@ static bool read_tag(char *dest, long size, return false; } -static bool parse_changelog_line(int masterfd, const char *buf) +static int parse_changelog_line(int line_n, const char *buf, void *parameters) { struct index_entry idx; char tag_data[MAX_PATH]; int idx_id; + int masterfd = (int)parameters; const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; int i; + (void)line_n; if (*buf == '#') - return true; + return 0; if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) { logf("filename missing"); logf("-> %s", buf); - return false; + return -1; } idx_id = find_index(tag_data); if (idx_id < 0) { logf("entry not found"); - return false; + return -2; } if (!get_index(masterfd, idx_id, &idx, false)) { logf("failed to retrieve index entry"); - return false; + return -3; } /* Stop if tag has already been modified. */ if (idx.flag & FLAG_DIRTYNUM) - return false; + return -4; logf("import: %s", tag_data); @@ -2745,7 +2748,7 @@ static bool parse_changelog_line(int masterfd, const char *buf) current_serial = data; } - return write_index(masterfd, idx_id, &idx); + return write_index(masterfd, idx_id, &idx) ? 0 : -5; } bool tagcache_import_changelog(void) @@ -2754,7 +2757,6 @@ bool tagcache_import_changelog(void) struct tagcache_header tch; int clfd, masterfd; char buf[2048]; - int pos = 0; if (!stat.ready) return false; @@ -2779,41 +2781,8 @@ bool tagcache_import_changelog(void) filenametag_fd = open_tag_fd(&tch, tag_filename, false); - /* Fast readline */ - while ( 1 ) - { - char *p; - char *next = NULL; - int rc; - - rc = read(clfd, &buf[pos], sizeof(buf)-pos-1); - if (rc >= 0) - buf[pos+rc] = '\0'; - - if ( (p = strchr(buf, '\r')) != NULL) - { - *p = '\0'; - next = ++p; - } - else - p = buf; - - if ( (p = strchr(p, '\n')) != NULL) - { - *p = '\0'; - next = ++p; - } - - parse_changelog_line(masterfd, buf); - - if (next) - { - pos = sizeof(buf) - ((long)next - (long)buf) - 1; - memmove(buf, next, pos); - } - else - break ; - } + fast_readline(filenametag_fd, buf, sizeof buf, (void *)masterfd, + parse_changelog_line); close(clfd); close(masterfd); diff --git a/apps/tagtree.c b/apps/tagtree.c index 97339fa13a..082e10d7d9 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -42,6 +42,7 @@ #include "atoi.h" #include "playback.h" #include "yesno.h" +#include "misc.h" #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" @@ -678,16 +679,146 @@ bool tagtree_import(void) return false; } +static bool parse_menu(const char *filename); + +int parse_line(int n, const char *buf, void *parameters) +{ + char data[256]; + int variable; + static bool read_menu; + int i; + + (void)parameters; + + /* First line, do initialisation. */ + if (n == 0) + { + if (strcasecmp(TAGNAVI_VERSION, buf)) + { + logf("Version mismatch"); + return -1; + } + + read_menu = false; + } + + if (buf[0] == '#') + return 0; + + if (buf[0] == '\0') + { + if (read_menu) + { + /* End the menu */ + menu_count++; + read_menu = false; + } + return 0; + } + + if (!read_menu) + { + strp = buf; + if (get_tag(&variable) <= 0) + return 0; + + switch (variable) + { + case var_format: + if (add_format(strp) < 0) + { + logf("Format add fail: %s", data); + } + break; + + case var_include: + if (get_token_str(data, sizeof(data)) < 0) + { + logf("%include empty"); + return false; + } + + if (!parse_menu(data)) + { + logf("Load menu fail: %s", data); + } + break; + + case var_menu_start: + if (menu_count >= TAGMENU_MAX_MENUS) + { + logf("max menucount reached"); + return false; + } + + menus[menu_count] = buffer_alloc(sizeof(struct root_menu)); + menu = menus[menu_count]; + memset(menu, 0, sizeof(struct root_menu)); + if (get_token_str(menu->id, sizeof(menu->id)) < 0) + { + logf("%menu_start id empty"); + return false; + } + if (get_token_str(menu->title, sizeof(menu->title)) < 0) + { + logf("%menu_start title empty"); + return false; + } + menu->itemcount = 0; + read_menu = true; + break; + + case var_rootmenu: + /* Only set root menu once. */ + if (root_menu) + break; + + if (get_token_str(data, sizeof(data)) < 0) + { + logf("%root_menu empty"); + return false; + } + + for (i = 0; i < menu_count; i++) + { + if (!strcasecmp(menus[i]->id, data)) + { + root_menu = i; + } + } + break; + } + + return 0; + } + + if (menu->itemcount >= TAGMENU_MAX_ITEMS) + { + logf("max itemcount reached"); + return 0; + } + + /* Allocate */ + if (menu->items[menu->itemcount] == NULL) + { + menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); + memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); + menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); + } + + memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); + if (!parse_search(menu->items[menu->itemcount], buf)) + return 0; + + menu->itemcount++; + + return 0; +} + static bool parse_menu(const char *filename) { int fd; char buf[256]; - char data[256]; - int variable; - int rc; - bool first = true; - bool read_menu = false; - int i; if (menu_count >= TAGMENU_MAX_MENUS) { @@ -703,132 +834,7 @@ static bool parse_menu(const char *filename) } /* Now read file for real, parsing into si */ - while ( 1 ) - { - rc = read_line(fd, buf, sizeof(buf)-1); - if (rc <= 0) - break; - - if (first) - { - if (strcasecmp(TAGNAVI_VERSION, buf)) - { - logf("Version mismatch"); - break; - } - first = false; - } - - if (buf[0] == '#') - continue; - - if (buf[0] == '\0') - { - if (read_menu) - { - /* End the menu */ - menu_count++; - read_menu = false; - } - continue; - } - - if (!read_menu) - { - strp = buf; - if (get_tag(&variable) <= 0) - continue; - - switch (variable) - { - case var_format: - if (add_format(strp) < 0) - { - logf("Format add fail: %s", data); - } - break; - - case var_include: - if (get_token_str(data, sizeof(data)) < 0) - { - logf("%include empty"); - return false; - } - - if (!parse_menu(data)) - { - logf("Load menu fail: %s", data); - } - break; - - case var_menu_start: - if (menu_count >= TAGMENU_MAX_MENUS) - { - logf("max menucount reached"); - return false; - } - - menus[menu_count] = buffer_alloc(sizeof(struct root_menu)); - menu = menus[menu_count]; - memset(menu, 0, sizeof(struct root_menu)); - if (get_token_str(menu->id, sizeof(menu->id)) < 0) - { - logf("%menu_start id empty"); - return false; - } - if (get_token_str(menu->title, sizeof(menu->title)) < 0) - { - logf("%menu_start title empty"); - return false; - } - menu->itemcount = 0; - read_menu = true; - break; - - case var_rootmenu: - /* Only set root menu once. */ - if (root_menu) - break; - - if (get_token_str(data, sizeof(data)) < 0) - { - logf("%root_menu empty"); - return false; - } - - for (i = 0; i < menu_count; i++) - { - if (!strcasecmp(menus[i]->id, data)) - { - root_menu = i; - } - } - break; - } - - continue; - } - - if (menu->itemcount >= TAGMENU_MAX_ITEMS) - { - logf("max itemcount reached"); - continue; - } - - /* Allocate */ - if (menu->items[menu->itemcount] == NULL) - { - menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); - memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); - menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); - } - - memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); - if (!parse_search(menu->items[menu->itemcount], buf)) - continue; - - menu->itemcount++; - } + fast_readline(fd, buf, sizeof buf, NULL, parse_line); close(fd); return true;