diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-10-15 11:01:18 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-10-15 11:01:18 +0000 |
commit | b89b5ba2ee31bd351710670cf5ecc5aa8beb95f3 (patch) | |
tree | 67fa9676aed7cfca7048bc40e60f71e87007149f /apps/tagcache.c | |
parent | a7acf1351f3088c0d509e87d84db95d38fed788c (diff) | |
download | rockbox-b89b5ba2ee31bd351710670cf5ecc5aa8beb95f3.tar.gz rockbox-b89b5ba2ee31bd351710670cf5ecc5aa8beb95f3.zip |
(1) New syntax to support conditional formatting.
(2) Reduced tagnavi memory consumption.
(3) There was a bug that splash screen counter was counting down when
inserting tracks next. But in fact that might be preferred, so always
count down after successful tagcache query.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11223 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r-- | apps/tagcache.c | 355 |
1 files changed, 197 insertions, 158 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index ca2421171b..38537b5ceb 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -538,6 +538,96 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx) | |||
538 | return true; | 538 | return true; |
539 | } | 539 | } |
540 | 540 | ||
541 | static bool open_files(struct tagcache_search *tcs, int tag) | ||
542 | { | ||
543 | if (tcs->idxfd[tag] < 0) | ||
544 | { | ||
545 | char fn[MAX_PATH]; | ||
546 | |||
547 | snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag); | ||
548 | tcs->idxfd[tag] = open(fn, O_RDONLY); | ||
549 | } | ||
550 | |||
551 | if (tcs->idxfd[tag] < 0) | ||
552 | { | ||
553 | logf("File not open!"); | ||
554 | return false; | ||
555 | } | ||
556 | |||
557 | return true; | ||
558 | } | ||
559 | |||
560 | static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, | ||
561 | int tag, char *buf, long size) | ||
562 | { | ||
563 | struct tagfile_entry tfe; | ||
564 | long seek; | ||
565 | |||
566 | *buf = '\0'; | ||
567 | |||
568 | if (tagcache_is_numeric_tag(tag)) | ||
569 | return false; | ||
570 | |||
571 | seek = idx->tag_seek[tag]; | ||
572 | if (seek < 0) | ||
573 | { | ||
574 | logf("Retrieve failed"); | ||
575 | return false; | ||
576 | } | ||
577 | |||
578 | #ifdef HAVE_TC_RAMCACHE | ||
579 | if (tcs->ramsearch) | ||
580 | { | ||
581 | struct tagfile_entry *ep; | ||
582 | |||
583 | # ifdef HAVE_DIRCACHE | ||
584 | if (tag == tag_filename && idx->flag & FLAG_DIRCACHE) | ||
585 | { | ||
586 | dircache_copy_path((struct dircache_entry *)seek, | ||
587 | buf, size); | ||
588 | return true; | ||
589 | } | ||
590 | else | ||
591 | # endif | ||
592 | if (tag != tag_filename) | ||
593 | { | ||
594 | ep = (struct tagfile_entry *)&hdr->tags[tag][seek]; | ||
595 | strncpy(buf, ep->tag_data, size-1); | ||
596 | |||
597 | return true; | ||
598 | } | ||
599 | } | ||
600 | #endif | ||
601 | |||
602 | if (!open_files(tcs, tag)) | ||
603 | return false; | ||
604 | |||
605 | lseek(tcs->idxfd[tag], seek, SEEK_SET); | ||
606 | if (read(tcs->idxfd[tag], &tfe, sizeof(struct tagfile_entry)) != | ||
607 | sizeof(struct tagfile_entry)) | ||
608 | { | ||
609 | logf("read error #5"); | ||
610 | return false; | ||
611 | } | ||
612 | |||
613 | if (tfe.tag_length >= size) | ||
614 | { | ||
615 | logf("too small buffer"); | ||
616 | return false; | ||
617 | } | ||
618 | |||
619 | if (read(tcs->idxfd[tag], buf, tfe.tag_length) != | ||
620 | tfe.tag_length) | ||
621 | { | ||
622 | logf("read error #6"); | ||
623 | return false; | ||
624 | } | ||
625 | |||
626 | buf[tfe.tag_length] = '\0'; | ||
627 | |||
628 | return true; | ||
629 | } | ||
630 | |||
541 | static long check_virtual_tags(int tag, const struct index_entry *idx) | 631 | static long check_virtual_tags(int tag, const struct index_entry *idx) |
542 | { | 632 | { |
543 | long data = 0; | 633 | long data = 0; |
@@ -671,6 +761,96 @@ static bool check_against_clause(long numeric, const char *str, | |||
671 | return false; | 761 | return false; |
672 | } | 762 | } |
673 | 763 | ||
764 | bool check_clauses(struct tagcache_search *tcs, | ||
765 | struct index_entry *idx, | ||
766 | struct tagcache_search_clause **clause, int count) | ||
767 | { | ||
768 | int i; | ||
769 | |||
770 | #ifdef HAVE_TC_RAMCACHE | ||
771 | if (tcs->ramsearch) | ||
772 | { | ||
773 | /* Go through all conditional clauses. */ | ||
774 | for (i = 0; i < count; i++) | ||
775 | { | ||
776 | struct tagfile_entry *tfe; | ||
777 | int seek; | ||
778 | char buf[256]; | ||
779 | char *str = NULL; | ||
780 | |||
781 | seek = check_virtual_tags(clause[i]->tag, idx); | ||
782 | |||
783 | if (!tagcache_is_numeric_tag(clause[i]->tag)) | ||
784 | { | ||
785 | if (clause[i]->tag == tag_filename) | ||
786 | { | ||
787 | retrieve(tcs, idx, tag_filename, buf, sizeof buf); | ||
788 | str = buf; | ||
789 | } | ||
790 | else | ||
791 | { | ||
792 | tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek]; | ||
793 | str = tfe->tag_data; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | if (!check_against_clause(seek, str, clause[i])) | ||
798 | return false; | ||
799 | } | ||
800 | } | ||
801 | else | ||
802 | #endif | ||
803 | { | ||
804 | /* Check for conditions. */ | ||
805 | for (i = 0; i < count; i++) | ||
806 | { | ||
807 | struct tagfile_entry tfe; | ||
808 | int seek; | ||
809 | char str[256]; | ||
810 | |||
811 | seek = check_virtual_tags(clause[i]->tag, idx); | ||
812 | |||
813 | memset(str, 0, sizeof str); | ||
814 | if (!tagcache_is_numeric_tag(clause[i]->tag)) | ||
815 | { | ||
816 | int fd = tcs->idxfd[clause[i]->tag]; | ||
817 | lseek(fd, seek, SEEK_SET); | ||
818 | read(fd, &tfe, sizeof(struct tagfile_entry)); | ||
819 | if (tfe.tag_length >= (int)sizeof(str)) | ||
820 | { | ||
821 | logf("Too long tag read!"); | ||
822 | break ; | ||
823 | } | ||
824 | |||
825 | read(fd, str, tfe.tag_length); | ||
826 | |||
827 | /* Check if entry has been deleted. */ | ||
828 | if (str[0] == '\0') | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | if (!check_against_clause(seek, str, clause[i])) | ||
833 | return false; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | return true; | ||
838 | } | ||
839 | |||
840 | bool tagcache_check_clauses(struct tagcache_search *tcs, | ||
841 | struct tagcache_search_clause **clause, int count) | ||
842 | { | ||
843 | struct index_entry idx; | ||
844 | |||
845 | if (count == 0) | ||
846 | return true; | ||
847 | |||
848 | if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true)) | ||
849 | return false; | ||
850 | |||
851 | return check_clauses(tcs, &idx, clause, count); | ||
852 | } | ||
853 | |||
674 | static bool add_uniqbuf(struct tagcache_search *tcs, long id) | 854 | static bool add_uniqbuf(struct tagcache_search *tcs, long id) |
675 | { | 855 | { |
676 | int i; | 856 | int i; |
@@ -713,18 +893,18 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
713 | 893 | ||
714 | for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) | 894 | for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) |
715 | { | 895 | { |
896 | struct index_entry *idx = &hdr->indices[i]; | ||
716 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 897 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
717 | break ; | 898 | break ; |
718 | 899 | ||
719 | /* Skip deleted files. */ | 900 | /* Skip deleted files. */ |
720 | if (hdr->indices[i].flag & FLAG_DELETED) | 901 | if (idx->flag & FLAG_DELETED) |
721 | continue; | 902 | continue; |
722 | 903 | ||
723 | /* Go through all filters.. */ | 904 | /* Go through all filters.. */ |
724 | for (j = 0; j < tcs->filter_count; j++) | 905 | for (j = 0; j < tcs->filter_count; j++) |
725 | { | 906 | { |
726 | if (hdr->indices[i].tag_seek[tcs->filter_tag[j]] != | 907 | if (idx->tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j]) |
727 | tcs->filter_seek[j]) | ||
728 | { | 908 | { |
729 | break ; | 909 | break ; |
730 | } | 910 | } |
@@ -733,51 +913,17 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
733 | if (j < tcs->filter_count) | 913 | if (j < tcs->filter_count) |
734 | continue ; | 914 | continue ; |
735 | 915 | ||
736 | /* Go through all conditional clauses. */ | 916 | /* Check for conditions. */ |
737 | for (j = 0; j < tcs->clause_count; j++) | 917 | if (!check_clauses(tcs, idx, tcs->clause, tcs->clause_count)) |
738 | { | 918 | continue; |
739 | struct index_entry *idx = &hdr->indices[i]; | ||
740 | int seek; | ||
741 | char buf[256]; | ||
742 | char *str = NULL; | ||
743 | struct tagfile_entry *entry; | ||
744 | |||
745 | seek = check_virtual_tags(tcs->clause[j]->tag, idx); | ||
746 | |||
747 | if (!tagcache_is_numeric_tag(tcs->clause[j]->tag)) | ||
748 | { | ||
749 | if (tcs->clause[j]->tag == tag_filename) | ||
750 | { | ||
751 | int oldtype = tcs->type; | ||
752 | tcs->type = tag_filename; | ||
753 | tagcache_retrieve(tcs, i, buf, sizeof buf); | ||
754 | tcs->type = oldtype; | ||
755 | str = buf; | ||
756 | } | ||
757 | else | ||
758 | { | ||
759 | entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek]; | ||
760 | str = entry->tag_data; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | |||
765 | if (!check_against_clause(seek, str, tcs->clause[j])) | ||
766 | break ; | ||
767 | } | ||
768 | |||
769 | if (j < tcs->clause_count) | ||
770 | continue ; | ||
771 | 919 | ||
772 | /* Add to the seek list if not already in uniq buffer. */ | 920 | /* Add to the seek list if not already in uniq buffer. */ |
773 | if (!add_uniqbuf(tcs, hdr->indices[i].tag_seek[tcs->type])) | 921 | if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type])) |
774 | continue; | 922 | continue; |
775 | 923 | ||
776 | /* Lets add it. */ | 924 | /* Lets add it. */ |
777 | tcs->seek_list[tcs->seek_list_count] = | 925 | tcs->seek_list[tcs->seek_list_count] = idx->tag_seek[tcs->type]; |
778 | hdr->indices[i].tag_seek[tcs->type]; | 926 | tcs->seek_flags[tcs->seek_list_count] = idx->flag; |
779 | tcs->seek_flags[tcs->seek_list_count] = | ||
780 | hdr->indices[i].flag; | ||
781 | tcs->seek_list_count++; | 927 | tcs->seek_list_count++; |
782 | } | 928 | } |
783 | 929 | ||
@@ -813,39 +959,8 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
813 | continue ; | 959 | continue ; |
814 | 960 | ||
815 | /* Check for conditions. */ | 961 | /* Check for conditions. */ |
816 | for (i = 0; i < tcs->clause_count; i++) | 962 | if (!check_clauses(tcs, &entry, tcs->clause, tcs->clause_count)) |
817 | { | 963 | continue; |
818 | struct tagfile_entry tfe; | ||
819 | int seek; | ||
820 | char str[256]; | ||
821 | |||
822 | seek = check_virtual_tags(tcs->clause[i]->tag, &entry); | ||
823 | |||
824 | memset(str, 0, sizeof str); | ||
825 | if (!tagcache_is_numeric_tag(tcs->clause[i]->tag)) | ||
826 | { | ||
827 | int fd = tcs->idxfd[tcs->clause[i]->tag]; | ||
828 | lseek(fd, seek, SEEK_SET); | ||
829 | read(fd, &tfe, sizeof(struct tagfile_entry)); | ||
830 | if (tfe.tag_length >= (int)sizeof(str)) | ||
831 | { | ||
832 | logf("Too long tag read!"); | ||
833 | break ; | ||
834 | } | ||
835 | |||
836 | read(fd, str, tfe.tag_length); | ||
837 | |||
838 | /* Check if entry has been deleted. */ | ||
839 | if (str[0] == '\0') | ||
840 | break; | ||
841 | } | ||
842 | |||
843 | if (!check_against_clause(seek, str, tcs->clause[i])) | ||
844 | break ; | ||
845 | } | ||
846 | |||
847 | if (i < tcs->clause_count) | ||
848 | continue ; | ||
849 | 964 | ||
850 | /* Add to the seek list if not already in uniq buffer. */ | 965 | /* Add to the seek list if not already in uniq buffer. */ |
851 | if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type])) | 966 | if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type])) |
@@ -1025,25 +1140,6 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, | |||
1025 | return true; | 1140 | return true; |
1026 | } | 1141 | } |
1027 | 1142 | ||
1028 | static bool open_files(struct tagcache_search *tcs) | ||
1029 | { | ||
1030 | if (tcs->idxfd[tcs->type] < 0) | ||
1031 | { | ||
1032 | char fn[MAX_PATH]; | ||
1033 | |||
1034 | snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tcs->type); | ||
1035 | tcs->idxfd[tcs->type] = open(fn, O_RDONLY); | ||
1036 | } | ||
1037 | |||
1038 | if (tcs->idxfd[tcs->type] < 0) | ||
1039 | { | ||
1040 | logf("File not open!"); | ||
1041 | return false; | ||
1042 | } | ||
1043 | |||
1044 | return true; | ||
1045 | } | ||
1046 | |||
1047 | #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ | 1143 | #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ |
1048 | ? (flag & FLAG_DIRCACHE) : 1) | 1144 | ? (flag & FLAG_DIRCACHE) : 1) |
1049 | 1145 | ||
@@ -1085,7 +1181,7 @@ static bool get_next(struct tagcache_search *tcs) | |||
1085 | if ((!tcs->ramsearch || !TAG_FILENAME_RAM(tcs)) | 1181 | if ((!tcs->ramsearch || !TAG_FILENAME_RAM(tcs)) |
1086 | && !tagcache_is_numeric_tag(tcs->type)) | 1182 | && !tagcache_is_numeric_tag(tcs->type)) |
1087 | { | 1183 | { |
1088 | if (!open_files(tcs)) | 1184 | if (!open_files(tcs, tcs->type)) |
1089 | return false; | 1185 | return false; |
1090 | 1186 | ||
1091 | lseek(tcs->idxfd[tcs->type], tcs->seek_list[tcs->seek_list_count], SEEK_SET); | 1187 | lseek(tcs->idxfd[tcs->type], tcs->seek_list[tcs->seek_list_count], SEEK_SET); |
@@ -1144,7 +1240,7 @@ static bool get_next(struct tagcache_search *tcs) | |||
1144 | else | 1240 | else |
1145 | #endif | 1241 | #endif |
1146 | { | 1242 | { |
1147 | if (!open_files(tcs)) | 1243 | if (!open_files(tcs, tcs->type)) |
1148 | return false; | 1244 | return false; |
1149 | 1245 | ||
1150 | tcs->result_seek = lseek(tcs->idxfd[tcs->type], 0, SEEK_CUR); | 1246 | tcs->result_seek = lseek(tcs->idxfd[tcs->type], 0, SEEK_CUR); |
@@ -1193,72 +1289,13 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
1193 | bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | 1289 | bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, |
1194 | char *buf, long size) | 1290 | char *buf, long size) |
1195 | { | 1291 | { |
1196 | struct tagfile_entry tfe; | ||
1197 | struct index_entry idx; | 1292 | struct index_entry idx; |
1198 | long seek; | ||
1199 | 1293 | ||
1200 | *buf = '\0'; | 1294 | *buf = '\0'; |
1201 | if (!get_index(tcs->masterfd, idxid, &idx, true)) | 1295 | if (!get_index(tcs->masterfd, idxid, &idx, true)) |
1202 | return false; | 1296 | return false; |
1203 | 1297 | ||
1204 | seek = idx.tag_seek[tcs->type]; | 1298 | return retrieve(tcs, &idx, tcs->type, buf, size); |
1205 | if (seek < 0) | ||
1206 | { | ||
1207 | logf("Retrieve failed"); | ||
1208 | return false; | ||
1209 | } | ||
1210 | |||
1211 | #ifdef HAVE_TC_RAMCACHE | ||
1212 | if (tcs->ramsearch) | ||
1213 | { | ||
1214 | struct tagfile_entry *ep; | ||
1215 | |||
1216 | # ifdef HAVE_DIRCACHE | ||
1217 | if (tcs->type == tag_filename && hdr->indices[idxid].flag & FLAG_DIRCACHE) | ||
1218 | { | ||
1219 | dircache_copy_path((struct dircache_entry *)seek, | ||
1220 | buf, size); | ||
1221 | return true; | ||
1222 | } | ||
1223 | else | ||
1224 | # endif | ||
1225 | if (tcs->type != tag_filename) | ||
1226 | { | ||
1227 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][seek]; | ||
1228 | strncpy(buf, ep->tag_data, size-1); | ||
1229 | |||
1230 | return true; | ||
1231 | } | ||
1232 | } | ||
1233 | #endif | ||
1234 | |||
1235 | if (!open_files(tcs)) | ||
1236 | return false; | ||
1237 | |||
1238 | lseek(tcs->idxfd[tcs->type], seek, SEEK_SET); | ||
1239 | if (read(tcs->idxfd[tcs->type], &tfe, sizeof(struct tagfile_entry)) != | ||
1240 | sizeof(struct tagfile_entry)) | ||
1241 | { | ||
1242 | logf("read error #5"); | ||
1243 | return false; | ||
1244 | } | ||
1245 | |||
1246 | if (tfe.tag_length >= size) | ||
1247 | { | ||
1248 | logf("too small buffer"); | ||
1249 | return false; | ||
1250 | } | ||
1251 | |||
1252 | if (read(tcs->idxfd[tcs->type], buf, tfe.tag_length) != | ||
1253 | tfe.tag_length) | ||
1254 | { | ||
1255 | logf("read error #6"); | ||
1256 | return false; | ||
1257 | } | ||
1258 | |||
1259 | buf[tfe.tag_length] = '\0'; | ||
1260 | |||
1261 | return true; | ||
1262 | } | 1299 | } |
1263 | 1300 | ||
1264 | #if 0 | 1301 | #if 0 |
@@ -2961,11 +2998,13 @@ static bool delete_entry(long idx_id) | |||
2961 | 2998 | ||
2962 | /* Skip the header block */ | 2999 | /* Skip the header block */ |
2963 | lseek(fd, myidx.tag_seek[tag] + sizeof(struct tagfile_entry), SEEK_SET); | 3000 | lseek(fd, myidx.tag_seek[tag] + sizeof(struct tagfile_entry), SEEK_SET); |
2964 | 3001 | ||
3002 | /* Debug, print 10 first characters of the tag | ||
2965 | read(fd, buf, 10); | 3003 | read(fd, buf, 10); |
2966 | buf[10]='\0'; | 3004 | buf[10]='\0'; |
2967 | logf("TAG:%s", buf); | 3005 | logf("TAG:%s", buf); |
2968 | lseek(fd, -10, SEEK_CUR); | 3006 | lseek(fd, -10, SEEK_CUR); |
3007 | */ | ||
2969 | 3008 | ||
2970 | /* Write first data byte in tag as \0 */ | 3009 | /* Write first data byte in tag as \0 */ |
2971 | write(fd, "", 1); | 3010 | write(fd, "", 1); |