summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/misc.c47
-rw-r--r--apps/misc.h2
-rw-r--r--apps/tagcache.c55
-rw-r--r--apps/tagtree.c258
4 files changed, 193 insertions, 169 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,157 +679,162 @@ bool tagtree_import(void)
return false;
}
-static bool parse_menu(const char *filename)
+static bool parse_menu(const char *filename);
+
+int parse_line(int n, const char *buf, void *parameters)
{
- int fd;
- char buf[256];
char data[256];
int variable;
- int rc;
- bool first = true;
- bool read_menu = false;
+ static bool read_menu;
int i;
-
- if (menu_count >= TAGMENU_MAX_MENUS)
- {
- logf("max menucount reached");
- return false;
- }
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- {
- logf("Search instruction file not found.");
- return false;
- }
+ (void)parameters;
- /* Now read file for real, parsing into si */
- while ( 1 )
+ /* First line, do initialisation. */
+ if (n == 0)
{
- rc = read_line(fd, buf, sizeof(buf)-1);
- if (rc <= 0)
- break;
-
- if (first)
+ if (strcasecmp(TAGNAVI_VERSION, buf))
{
- if (strcasecmp(TAGNAVI_VERSION, buf))
- {
- logf("Version mismatch");
- break;
- }
- first = false;
+ logf("Version mismatch");
+ return -1;
}
- if (buf[0] == '#')
- continue;
-
- if (buf[0] == '\0')
+ read_menu = false;
+ }
+
+ if (buf[0] == '#')
+ return 0;
+
+ if (buf[0] == '\0')
+ {
+ if (read_menu)
{
- if (read_menu)
- {
- /* End the menu */
- menu_count++;
- read_menu = false;
- }
- continue;
+ /* End the menu */
+ menu_count++;
+ read_menu = false;
}
+ return 0;
+ }
+
+ if (!read_menu)
+ {
+ strp = buf;
+ if (get_tag(&variable) <= 0)
+ return 0;
- if (!read_menu)
+ switch (variable)
{
- strp = buf;
- if (get_tag(&variable) <= 0)
- continue;
+ 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;
+ }
- switch (variable)
- {
- case var_format:
- if (add_format(strp) < 0)
- {
- logf("Format add fail: %s", data);
- }
- break;
+ if (!parse_menu(data))
+ {
+ logf("Load menu 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_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;
+ case var_rootmenu:
+ /* Only set root menu once. */
+ if (root_menu)
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;
- }
+ if (get_token_str(data, sizeof(data)) < 0)
+ {
+ logf("%root_menu empty");
+ return false;
+ }
- for (i = 0; i < menu_count; i++)
+ for (i = 0; i < menu_count; i++)
+ {
+ if (!strcasecmp(menus[i]->id, data))
{
- if (!strcasecmp(menus[i]->id, data))
- {
- root_menu = i;
- }
+ 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));
+ }
+ break;
}
- memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction));
- if (!parse_search(menu->items[menu->itemcount], buf))
- continue;
-
- menu->itemcount++;
+ 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];
+
+ if (menu_count >= TAGMENU_MAX_MENUS)
+ {
+ logf("max menucount reached");
+ return false;
+ }
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ logf("Search instruction file not found.");
+ return false;
+ }
+
+ /* Now read file for real, parsing into si */
+ fast_readline(fd, buf, sizeof buf, NULL, parse_line);
close(fd);
return true;