From 7efa6e7da0d3071be785b6206d9b2121405c0b01 Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Wed, 20 Nov 2002 06:35:42 +0000 Subject: [PATCH] beginnings of cuesheet file parser --- src/share/grabbag/cuesheet.c | 153 +++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/src/share/grabbag/cuesheet.c b/src/share/grabbag/cuesheet.c index 69ebdc50..83bccace 100644 --- a/src/share/grabbag/cuesheet.c +++ b/src/share/grabbag/cuesheet.c @@ -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; +}