beginnings of cuesheet file parser
authorJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 20 Nov 2002 06:35:42 +0000 (06:35 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 20 Nov 2002 06:35:42 +0000 (06:35 +0000)
src/share/grabbag/cuesheet.c

index 69ebdc5..83bccac 100644 (file)
@@ -35,3 +35,156 @@ GRABBAG_API void grabbag__cuesheet_frame_to_msf(unsigned frame, unsigned *minute
        frame /= 60;
        *minutes = frame;
 }
+
+/* since we only care about values >= 0 or error, returns < 0 for any illegal int, else value */
+static int local__parse_int_(const char *s)
+{
+       int ret = 0;
+       char c;
+
+       if(*s == '\0')
+               return -1;
+
+       while('\0' != (c = *s++))
+               if(c >= '0' && c <= '9')
+                       ret = ret * 10 + (c - '0');
+               else
+                       return -1;
+
+       return ret;
+}
+
+static char *local__get_field_(char **s)
+{
+       char *p;
+
+       FLAC__ASSERT(0 != s);
+
+       if(0 == *s)
+               return 0;
+
+       /* skip leading whitespace */
+       while(**s && 0 != strchr(" \t\r\n", **s))
+               (*s)++;
+
+       if(**s == 0)
+               *s = 0;
+
+       p = *s;
+
+       if(p) {
+               while(**s && 0 == strchr(" \t\r\n", **s))
+                       (*s)++;
+               if(**s)
+                       **s = '\0';
+               else
+                       *s = 0;
+       }
+
+       return p;
+}
+
+static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, FLAC__bool check_cd_da_subset)
+{
+#if defined _MSC_VER || defined __MINGW32__
+#define FLAC__STRCASECMP stricmp
+#else
+#define FLAC__STRCASECMP strcasecmp
+#endif
+       char buffer[4096], *line, *field;
+       unsigned linelen;
+       int in_track = -1, in_index = -1;
+
+       while(0 != fgets(buffer, sizeof(buffer), file)) {
+               *last_line_read++;
+               line = buffer;
+
+               linelen = strlen(line);
+               if(line[linelen-1] != '\n') {
+                       *error_message = "line too long";
+                       return false;
+               }
+
+               if(0 != (field = local__get_field_(&line))) {
+                       if(0 == FLAC__STRCASECMP(field, "CATALOG")) {
+                               /*@@@@ error if already encountered CATALOG */
+                               /*@@@@ check_cd_da_subset: 13 digits ['0'..'9'] */
+                       }
+                       else if(0 == FLAC__STRCASECMP(field, "FLAGS")) {
+                               /*@@@@ error if already encountered FLAGS in this track */
+                               if(in_track < 0) {
+                                       /*@@@@*/
+                               }
+                               if(in_index >= 0) {
+                                       /*@@@@*/
+                               }
+                               /*@@@@ search for PRE flag only */
+                       }
+                       else if(0 == FLAC__STRCASECMP(field, "INDEX")) {
+                               if(in_track < 0) {
+                                       *error_message = "found INDEX before any TRACK";
+                                       return false;
+                               }
+                               /*@@@@ check_cd_da_subset: 0..99 */
+                               /*@@@@ check_cd_da_subset: first index of first track is 00:00:00 */
+                               /*@@@@ check first is 0 or 1 */
+                               /*@@@@ check sequential */
+                               /*@@@@ parse msf (or sample offset if !check_cd_da_subset)
+                       }
+                       else if(0 == FLAC__STRCASECMP(field, "ISRC")) {
+                               /*@@@@ error if already encountered ISRC in this track */
+                               if(in_track < 0) {
+                                       /*@@@@*/
+                               }
+                               if(in_index >= 0) {
+                                       /*@@@@*/
+                               }
+                       }
+                       else if(0 == FLAC__STRCASECMP(field, "TRACK")) {
+                               if(0 == (field = local__get_field_(&line))) {
+                                       *error_message = "TRACK is missing track number";
+                                       return false;
+                               }
+                               in_track = local__parse_int_(field);
+                               in_index = -1;
+                               if(in_track <= 0) {
+                                       *error_message = "TRACK has invalid track number";
+                                       return false;
+                               }
+                               /*@@@@ check_cd_da_subset: 1..99 */
+                               /*@@@@ check_cd_da_subset: sequential */
+                       }
+               }
+       }
+
+       if(!feof(file)) {
+               *error_message = "read error";
+               return false;
+       }
+       return true;
+#undef FLAC__STRCASECMP
+}
+
+GRABBAG_API FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool check_cd_da_subset)
+{
+       FLAC__StreamMetadata *cuesheet;
+
+       FLAC__ASSERT(0 != file);
+       FLAC__ASSERT(0 != error_message);
+       FLAC__ASSERT(0 != last_line_read);
+
+       *last_line_read = 0;
+       cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);
+
+       if(0 == cuesheet) {
+               *error_message = "memory allocation error";
+               return 0;
+       }
+
+       if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, check_cd_da_subset)) {
+               FLAC__metadata_object_delete(cuesheet);
+               return 0;
+       }
+
+       return cuesheet;
+}