summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-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)
217 return errno ? -1 : num_read; 217 return errno ? -1 : num_read;
218} 218}
219 219
220/* Performance optimized version of the previous function. */
221int fast_readline(int fd, char *buf, int buf_size, void *parameters,
222 int (*callback)(int n, const char *buf, void *parameters))
223{
224 char *p, *next;
225 int rc, pos = 0;
226 int count = 0;
227
228 while ( 1 )
229 {
230 next = NULL;
231
232 rc = read(fd, &buf[pos], buf_size - pos - 1);
233 if (rc >= 0)
234 buf[pos+rc] = '\0';
235
236 if ( (p = strchr(buf, '\r')) != NULL)
237 {
238 *p = '\0';
239 next = ++p;
240 }
241 else
242 p = buf;
243
244 if ( (p = strchr(p, '\n')) != NULL)
245 {
246 *p = '\0';
247 next = ++p;
248 }
249
250 rc = callback(count, buf, parameters);
251 if (rc < 0)
252 return rc;
253
254 count++;
255 if (next)
256 {
257 pos = buf_size - ((long)next - (long)buf) - 1;
258 memmove(buf, next, pos);
259 }
260 else
261 break ;
262 }
263
264 return 0;
265}
266
220#ifdef HAVE_LCD_BITMAP 267#ifdef HAVE_LCD_BITMAP
221 268
222#if LCD_DEPTH == 16 269#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,
42 * stored in buffer. 42 * stored in buffer.
43 */ 43 */
44int read_line(int fd, char* buffer, int buffer_size); 44int read_line(int fd, char* buffer, int buffer_size);
45int fast_readline(int fd, char *buf, int buf_size, void *parameters,
46 int (*callback)(int n, const char *buf, void *parameters));
45 47
46#ifdef HAVE_LCD_BITMAP 48#ifdef HAVE_LCD_BITMAP
47/* Save a .BMP file containing the current screen contents. */ 49/* 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 @@
72#include "atoi.h" 72#include "atoi.h"
73#include "crc32.h" 73#include "crc32.h"
74#include "eeprom_settings.h" 74#include "eeprom_settings.h"
75#include "misc.h"
75 76
76/* Tag Cache thread. */ 77/* Tag Cache thread. */
77static struct event_queue tagcache_queue; 78static struct event_queue tagcache_queue;
@@ -2687,40 +2688,42 @@ static bool read_tag(char *dest, long size,
2687 return false; 2688 return false;
2688} 2689}
2689 2690
2690static bool parse_changelog_line(int masterfd, const char *buf) 2691static int parse_changelog_line(int line_n, const char *buf, void *parameters)
2691{ 2692{
2692 struct index_entry idx; 2693 struct index_entry idx;
2693 char tag_data[MAX_PATH]; 2694 char tag_data[MAX_PATH];
2694 int idx_id; 2695 int idx_id;
2696 int masterfd = (int)parameters;
2695 const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; 2697 const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed };
2696 int i; 2698 int i;
2699 (void)line_n;
2697 2700
2698 if (*buf == '#') 2701 if (*buf == '#')
2699 return true; 2702 return 0;
2700 2703
2701 if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) 2704 if (!read_tag(tag_data, sizeof tag_data, buf, "filename"))
2702 { 2705 {
2703 logf("filename missing"); 2706 logf("filename missing");
2704 logf("-> %s", buf); 2707 logf("-> %s", buf);
2705 return false; 2708 return -1;
2706 } 2709 }
2707 2710
2708 idx_id = find_index(tag_data); 2711 idx_id = find_index(tag_data);
2709 if (idx_id < 0) 2712 if (idx_id < 0)
2710 { 2713 {
2711 logf("entry not found"); 2714 logf("entry not found");
2712 return false; 2715 return -2;
2713 } 2716 }
2714 2717
2715 if (!get_index(masterfd, idx_id, &idx, false)) 2718 if (!get_index(masterfd, idx_id, &idx, false))
2716 { 2719 {
2717 logf("failed to retrieve index entry"); 2720 logf("failed to retrieve index entry");
2718 return false; 2721 return -3;
2719 } 2722 }
2720 2723
2721 /* Stop if tag has already been modified. */ 2724 /* Stop if tag has already been modified. */
2722 if (idx.flag & FLAG_DIRTYNUM) 2725 if (idx.flag & FLAG_DIRTYNUM)
2723 return false; 2726 return -4;
2724 2727
2725 logf("import: %s", tag_data); 2728 logf("import: %s", tag_data);
2726 2729
@@ -2745,7 +2748,7 @@ static bool parse_changelog_line(int masterfd, const char *buf)
2745 current_serial = data; 2748 current_serial = data;
2746 } 2749 }
2747 2750
2748 return write_index(masterfd, idx_id, &idx); 2751 return write_index(masterfd, idx_id, &idx) ? 0 : -5;
2749} 2752}
2750 2753
2751bool tagcache_import_changelog(void) 2754bool tagcache_import_changelog(void)
@@ -2754,7 +2757,6 @@ bool tagcache_import_changelog(void)
2754 struct tagcache_header tch; 2757 struct tagcache_header tch;
2755 int clfd, masterfd; 2758 int clfd, masterfd;
2756 char buf[2048]; 2759 char buf[2048];
2757 int pos = 0;
2758 2760
2759 if (!stat.ready) 2761 if (!stat.ready)
2760 return false; 2762 return false;
@@ -2779,41 +2781,8 @@ bool tagcache_import_changelog(void)
2779 2781
2780 filenametag_fd = open_tag_fd(&tch, tag_filename, false); 2782 filenametag_fd = open_tag_fd(&tch, tag_filename, false);
2781 2783
2782 /* Fast readline */ 2784 fast_readline(filenametag_fd, buf, sizeof buf, (void *)masterfd,
2783 while ( 1 ) 2785 parse_changelog_line);
2784 {
2785 char *p;
2786 char *next = NULL;
2787 int rc;
2788
2789 rc = read(clfd, &buf[pos], sizeof(buf)-pos-1);
2790 if (rc >= 0)
2791 buf[pos+rc] = '\0';
2792
2793 if ( (p = strchr(buf, '\r')) != NULL)
2794 {
2795 *p = '\0';
2796 next = ++p;
2797 }
2798 else
2799 p = buf;
2800
2801 if ( (p = strchr(p, '\n')) != NULL)
2802 {
2803 *p = '\0';
2804 next = ++p;
2805 }
2806
2807 parse_changelog_line(masterfd, buf);
2808
2809 if (next)
2810 {
2811 pos = sizeof(buf) - ((long)next - (long)buf) - 1;
2812 memmove(buf, next, pos);
2813 }
2814 else
2815 break ;
2816 }
2817 2786
2818 close(clfd); 2787 close(clfd);
2819 close(masterfd); 2788 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 @@
42#include "atoi.h" 42#include "atoi.h"
43#include "playback.h" 43#include "playback.h"
44#include "yesno.h" 44#include "yesno.h"
45#include "misc.h"
45 46
46#define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" 47#define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config"
47 48
@@ -678,157 +679,162 @@ bool tagtree_import(void)
678 return false; 679 return false;
679} 680}
680 681
681static bool parse_menu(const char *filename) 682static bool parse_menu(const char *filename);
683
684int parse_line(int n, const char *buf, void *parameters)
682{ 685{
683 int fd;
684 char buf[256];
685 char data[256]; 686 char data[256];
686 int variable; 687 int variable;
687 int rc; 688 static bool read_menu;
688 bool first = true;
689 bool read_menu = false;
690 int i; 689 int i;
691
692 if (menu_count >= TAGMENU_MAX_MENUS)
693 {
694 logf("max menucount reached");
695 return false;
696 }
697 690
698 fd = open(filename, O_RDONLY); 691 (void)parameters;
699 if (fd < 0)
700 {
701 logf("Search instruction file not found.");
702 return false;
703 }
704 692
705 /* Now read file for real, parsing into si */ 693 /* First line, do initialisation. */
706 while ( 1 ) 694 if (n == 0)
707 { 695 {
708 rc = read_line(fd, buf, sizeof(buf)-1); 696 if (strcasecmp(TAGNAVI_VERSION, buf))
709 if (rc <= 0)
710 break;
711
712 if (first)
713 { 697 {
714 if (strcasecmp(TAGNAVI_VERSION, buf)) 698 logf("Version mismatch");
715 { 699 return -1;
716 logf("Version mismatch");
717 break;
718 }
719 first = false;
720 } 700 }
721 701
722 if (buf[0] == '#') 702 read_menu = false;
723 continue; 703 }
724 704
725 if (buf[0] == '\0') 705 if (buf[0] == '#')
706 return 0;
707
708 if (buf[0] == '\0')
709 {
710 if (read_menu)
726 { 711 {
727 if (read_menu) 712 /* End the menu */
728 { 713 menu_count++;
729 /* End the menu */ 714 read_menu = false;
730 menu_count++;
731 read_menu = false;
732 }
733 continue;
734 } 715 }
716 return 0;
717 }
718
719 if (!read_menu)
720 {
721 strp = buf;
722 if (get_tag(&variable) <= 0)
723 return 0;
735 724
736 if (!read_menu) 725 switch (variable)
737 { 726 {
738 strp = buf; 727 case var_format:
739 if (get_tag(&variable) <= 0) 728 if (add_format(strp) < 0)
740 continue; 729 {
730 logf("Format add fail: %s", data);
731 }
732 break;
733
734 case var_include:
735 if (get_token_str(data, sizeof(data)) < 0)
736 {
737 logf("%include empty");
738 return false;
739 }
741 740
742 switch (variable) 741 if (!parse_menu(data))
743 { 742 {
744 case var_format: 743 logf("Load menu fail: %s", data);
745 if (add_format(strp) < 0) 744 }
746 { 745 break;
747 logf("Format add fail: %s", data);
748 }
749 break;
750 746
751 case var_include: 747 case var_menu_start:
752 if (get_token_str(data, sizeof(data)) < 0) 748 if (menu_count >= TAGMENU_MAX_MENUS)
753 { 749 {
754 logf("%include empty"); 750 logf("max menucount reached");
755 return false; 751 return false;
756 } 752 }
757 753
758 if (!parse_menu(data)) 754 menus[menu_count] = buffer_alloc(sizeof(struct root_menu));
759 { 755 menu = menus[menu_count];
760 logf("Load menu fail: %s", data); 756 memset(menu, 0, sizeof(struct root_menu));
761 } 757 if (get_token_str(menu->id, sizeof(menu->id)) < 0)
762 break; 758 {
759 logf("%menu_start id empty");
760 return false;
761 }
762 if (get_token_str(menu->title, sizeof(menu->title)) < 0)
763 {
764 logf("%menu_start title empty");
765 return false;
766 }
767 menu->itemcount = 0;
768 read_menu = true;
769 break;
763 770
764 case var_menu_start: 771 case var_rootmenu:
765 if (menu_count >= TAGMENU_MAX_MENUS) 772 /* Only set root menu once. */
766 { 773 if (root_menu)
767 logf("max menucount reached");
768 return false;
769 }
770
771 menus[menu_count] = buffer_alloc(sizeof(struct root_menu));
772 menu = menus[menu_count];
773 memset(menu, 0, sizeof(struct root_menu));
774 if (get_token_str(menu->id, sizeof(menu->id)) < 0)
775 {
776 logf("%menu_start id empty");
777 return false;
778 }
779 if (get_token_str(menu->title, sizeof(menu->title)) < 0)
780 {
781 logf("%menu_start title empty");
782 return false;
783 }
784 menu->itemcount = 0;
785 read_menu = true;
786 break; 774 break;
787 775
788 case var_rootmenu: 776 if (get_token_str(data, sizeof(data)) < 0)
789 /* Only set root menu once. */ 777 {
790 if (root_menu) 778 logf("%root_menu empty");
791 break; 779 return false;
792 780 }
793 if (get_token_str(data, sizeof(data)) < 0)
794 {
795 logf("%root_menu empty");
796 return false;
797 }
798 781
799 for (i = 0; i < menu_count; i++) 782 for (i = 0; i < menu_count; i++)
783 {
784 if (!strcasecmp(menus[i]->id, data))
800 { 785 {
801 if (!strcasecmp(menus[i]->id, data)) 786 root_menu = i;
802 {
803 root_menu = i;
804 }
805 } 787 }
806 break; 788 }
807 } 789 break;
808
809 continue;
810 }
811
812 if (menu->itemcount >= TAGMENU_MAX_ITEMS)
813 {
814 logf("max itemcount reached");
815 continue;
816 }
817
818 /* Allocate */
819 if (menu->items[menu->itemcount] == NULL)
820 {
821 menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry));
822 memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry));
823 menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction));
824 } 790 }
825 791
826 memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); 792 return 0;
827 if (!parse_search(menu->items[menu->itemcount], buf))
828 continue;
829
830 menu->itemcount++;
831 } 793 }
794
795 if (menu->itemcount >= TAGMENU_MAX_ITEMS)
796 {
797 logf("max itemcount reached");
798 return 0;
799 }
800
801 /* Allocate */
802 if (menu->items[menu->itemcount] == NULL)
803 {
804 menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry));
805 memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry));
806 menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction));
807 }
808
809 memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction));
810 if (!parse_search(menu->items[menu->itemcount], buf))
811 return 0;
812
813 menu->itemcount++;
814
815 return 0;
816}
817
818static bool parse_menu(const char *filename)
819{
820 int fd;
821 char buf[256];
822
823 if (menu_count >= TAGMENU_MAX_MENUS)
824 {
825 logf("max menucount reached");
826 return false;
827 }
828
829 fd = open(filename, O_RDONLY);
830 if (fd < 0)
831 {
832 logf("Search instruction file not found.");
833 return false;
834 }
835
836 /* Now read file for real, parsing into si */
837 fast_readline(fd, buf, sizeof buf, NULL, parse_line);
832 close(fd); 838 close(fd);
833 839
834 return true; 840 return true;