1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Miika Pekkarinen 2006-10-21 20:37:33 +00:00
parent 593b552486
commit a1ac743453
4 changed files with 199 additions and 175 deletions

View file

@ -217,6 +217,53 @@ int read_line(int fd, char* buffer, int buffer_size)
return errno ? -1 : num_read; 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 #ifdef HAVE_LCD_BITMAP
#if LCD_DEPTH == 16 #if LCD_DEPTH == 16

View file

@ -42,6 +42,8 @@ char *create_datetime_filename(char *buffer, const char *path,
* stored in buffer. * stored in buffer.
*/ */
int read_line(int fd, char* buffer, int buffer_size); 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 #ifdef HAVE_LCD_BITMAP
/* Save a .BMP file containing the current screen contents. */ /* Save a .BMP file containing the current screen contents. */

View file

@ -72,6 +72,7 @@
#include "atoi.h" #include "atoi.h"
#include "crc32.h" #include "crc32.h"
#include "eeprom_settings.h" #include "eeprom_settings.h"
#include "misc.h"
/* Tag Cache thread. */ /* Tag Cache thread. */
static struct event_queue tagcache_queue; static struct event_queue tagcache_queue;
@ -2687,40 +2688,42 @@ static bool read_tag(char *dest, long size,
return false; 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; struct index_entry idx;
char tag_data[MAX_PATH]; char tag_data[MAX_PATH];
int idx_id; int idx_id;
int masterfd = (int)parameters;
const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed };
int i; int i;
(void)line_n;
if (*buf == '#') if (*buf == '#')
return true; return 0;
if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) if (!read_tag(tag_data, sizeof tag_data, buf, "filename"))
{ {
logf("filename missing"); logf("filename missing");
logf("-> %s", buf); logf("-> %s", buf);
return false; return -1;
} }
idx_id = find_index(tag_data); idx_id = find_index(tag_data);
if (idx_id < 0) if (idx_id < 0)
{ {
logf("entry not found"); logf("entry not found");
return false; return -2;
} }
if (!get_index(masterfd, idx_id, &idx, false)) if (!get_index(masterfd, idx_id, &idx, false))
{ {
logf("failed to retrieve index entry"); logf("failed to retrieve index entry");
return false; return -3;
} }
/* Stop if tag has already been modified. */ /* Stop if tag has already been modified. */
if (idx.flag & FLAG_DIRTYNUM) if (idx.flag & FLAG_DIRTYNUM)
return false; return -4;
logf("import: %s", tag_data); logf("import: %s", tag_data);
@ -2745,7 +2748,7 @@ static bool parse_changelog_line(int masterfd, const char *buf)
current_serial = data; current_serial = data;
} }
return write_index(masterfd, idx_id, &idx); return write_index(masterfd, idx_id, &idx) ? 0 : -5;
} }
bool tagcache_import_changelog(void) bool tagcache_import_changelog(void)
@ -2754,7 +2757,6 @@ bool tagcache_import_changelog(void)
struct tagcache_header tch; struct tagcache_header tch;
int clfd, masterfd; int clfd, masterfd;
char buf[2048]; char buf[2048];
int pos = 0;
if (!stat.ready) if (!stat.ready)
return false; return false;
@ -2779,41 +2781,8 @@ bool tagcache_import_changelog(void)
filenametag_fd = open_tag_fd(&tch, tag_filename, false); filenametag_fd = open_tag_fd(&tch, tag_filename, false);
/* Fast readline */ fast_readline(filenametag_fd, buf, sizeof buf, (void *)masterfd,
while ( 1 ) parse_changelog_line);
{
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 ;
}
close(clfd); close(clfd);
close(masterfd); close(masterfd);

View file

@ -42,6 +42,7 @@
#include "atoi.h" #include "atoi.h"
#include "playback.h" #include "playback.h"
#include "yesno.h" #include "yesno.h"
#include "misc.h"
#define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config"
@ -678,16 +679,146 @@ bool tagtree_import(void)
return false; 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) static bool parse_menu(const char *filename)
{ {
int fd; int fd;
char buf[256]; 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) 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 */ /* Now read file for real, parsing into si */
while ( 1 ) fast_readline(fd, buf, sizeof buf, NULL, parse_line);
{
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++;
}
close(fd); close(fd);
return true; return true;