foobar2000 SDK  2015-08-03
Functions
cue_parser.cpp File Reference

Go to the source code of this file.

Functions

static void g_parse_cue (const char *p_cuesheet, cue_parser_callback &p_callback)
 
static void g_parse_cue_line (const char *p_line, t_size p_line_length, cue_parser_callback &p_callback)
 
static bool is_linebreak (char c)
 
static bool is_numeric (char c)
 
static bool is_spacing (char c)
 
static void validate_file_type (const char *p_type, t_size p_type_length)
 

Function Documentation

static void g_parse_cue ( const char *  p_cuesheet,
cue_parser_callback &  p_callback 
)
static

Definition at line 594 of file cue_parser.cpp.

595 {
596  const char * parseptr = p_cuesheet;
597  t_size lineidx = 1;
598  while(*parseptr)
599  {
600  while(is_spacing(*parseptr)) parseptr++;
601  if (*parseptr)
602  {
603  t_size length = 0;
604  while(parseptr[length] && !is_linebreak(parseptr[length])) length++;
605  if (length > 0) {
606  try {
607  g_parse_cue_line(parseptr,length,p_callback);
608  } catch(exception_cue const & e) {//rethrow with line info
609  pfc::throw_exception_with_message< exception_cue > (PFC_string_formatter() << e.what() << " (line " << (unsigned)lineidx << ")");
610  }
611  }
612  parseptr += length;
613  while(is_linebreak(*parseptr)) {
614  if (*parseptr == '\n') lineidx++;
615  parseptr++;
616  }
617  }
618  }
619 }
static void g_parse_cue_line(const char *p_line, t_size p_line_length, cue_parser_callback &p_callback)
Definition: cue_parser.cpp:380
static bool is_linebreak(char c)
Definition: cue_parser.cpp:15
size_t t_size
Definition: int_types.h:48
static bool is_spacing(char c)
Definition: cue_parser.cpp:10
static void g_parse_cue_line ( const char *  p_line,
t_size  p_line_length,
cue_parser_callback &  p_callback 
)
static

Definition at line 380 of file cue_parser.cpp.

381 {
382  t_size ptr = 0;
383  while(ptr < p_line_length && !is_spacing(p_line[ptr])) ptr++;
384  if (!stricmp_utf8_ex(p_line,ptr,"file",pfc_infinite))
385  {
386  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
387  t_size file_base,file_length, type_base,type_length;
388 
389  if (p_line[ptr] == '\"')
390  {
391  ptr++;
392  file_base = ptr;
393  while(ptr < p_line_length && p_line[ptr] != '\"') ptr++;
394  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid FILE syntax");
395  file_length = ptr - file_base;
396  ptr++;
397  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
398  }
399  else
400  {
401  file_base = ptr;
402  while(ptr < p_line_length && !is_spacing(p_line[ptr])) ptr++;
403  file_length = ptr - file_base;
404  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
405  }
406 
407  type_base = ptr;
408  while(ptr < p_line_length && !is_spacing(p_line[ptr])) ptr++;
409  type_length = ptr - type_base;
410  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
411 
412  if (ptr != p_line_length || file_length == 0 || type_length == 0) pfc::throw_exception_with_message< exception_cue > ("invalid FILE syntax");
413 
414  p_callback.on_file(p_line + file_base, file_length, p_line + type_base, type_length);
415  }
416  else if (!stricmp_utf8_ex(p_line,ptr,"track",pfc_infinite))
417  {
418  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
419 
420  t_size track_base = ptr, track_length;
421  while(ptr < p_line_length && !is_spacing(p_line[ptr]))
422  {
423  if (!is_numeric(p_line[ptr])) pfc::throw_exception_with_message< exception_cue > ("invalid TRACK syntax");
424  ptr++;
425  }
426  track_length = ptr - track_base;
427  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
428 
429  t_size type_base = ptr, type_length;
430  while(ptr < p_line_length && !is_spacing(p_line[ptr])) ptr++;
431  type_length = ptr - type_base;
432 
433  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
434  if (ptr != p_line_length || type_length == 0) pfc::throw_exception_with_message< exception_cue > ("invalid TRACK syntax");
435  unsigned track = pfc::atoui_ex(p_line+track_base,track_length);
436  if (track < 1 || track > 99) pfc::throw_exception_with_message< exception_cue > ("invalid track number");
437 
438  p_callback.on_track(track,p_line + type_base, type_length);
439  }
440  else if (!stricmp_utf8_ex(p_line,ptr,"index",pfc_infinite))
441  {
442  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
443 
444  t_size index_base,index_length, time_base,time_length;
445  index_base = ptr;
446  while(ptr < p_line_length && !is_spacing(p_line[ptr]))
447  {
448  if (!is_numeric(p_line[ptr])) pfc::throw_exception_with_message< exception_cue > ("invalid INDEX syntax" );
449  ptr++;
450  }
451  index_length = ptr - index_base;
452 
453  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
454  time_base = ptr;
455  while(ptr < p_line_length && !is_spacing(p_line[ptr]))
456  {
457  if (!is_numeric(p_line[ptr]) && p_line[ptr] != ':')
458  pfc::throw_exception_with_message< exception_cue > ("invalid INDEX syntax");
459  ptr++;
460  }
461  time_length = ptr - time_base;
462 
463  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
464 
465  if (ptr != p_line_length || index_length == 0 || time_length == 0)
466  pfc::throw_exception_with_message< exception_cue > ("invalid INDEX syntax");
467 
468  unsigned index = pfc::atoui_ex(p_line+index_base,index_length);
469  if (index > 99) pfc::throw_exception_with_message< exception_cue > ("invalid INDEX syntax");
470  unsigned time = cuesheet_parse_index_time_ticks_e(p_line + time_base,time_length);
471 
472  p_callback.on_index(index,time);
473  }
474  else if (!stricmp_utf8_ex(p_line,ptr,"pregap",pfc_infinite))
475  {
476  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
477 
478  t_size time_base, time_length;
479  time_base = ptr;
480  while(ptr < p_line_length && !is_spacing(p_line[ptr]))
481  {
482  if (!is_numeric(p_line[ptr]) && p_line[ptr] != ':')
483  pfc::throw_exception_with_message< exception_cue > ("invalid PREGAP syntax");
484  ptr++;
485  }
486  time_length = ptr - time_base;
487 
488  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
489 
490  if (ptr != p_line_length || time_length == 0)
491  pfc::throw_exception_with_message< exception_cue > ("invalid PREGAP syntax");
492 
493  unsigned time = cuesheet_parse_index_time_ticks_e(p_line + time_base,time_length);
494 
495  p_callback.on_pregap(time);
496  }
497  else if (!stricmp_utf8_ex(p_line,ptr,"title",pfc_infinite))
498  {
499  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
500  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid TITLE syntax");
501  if (p_line[ptr] == '\"')
502  {
503  ptr++;
504  t_size base = ptr;
505  while(ptr < p_line_length && p_line[ptr] != '\"') ptr++;
506  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid TITLE syntax");
507  t_size length = ptr-base;
508  ptr++;
509  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
510  if (ptr != p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid TITLE syntax");
511  p_callback.on_title(p_line+base,length);
512  }
513  else
514  {
515  p_callback.on_title(p_line+ptr,p_line_length-ptr);
516  }
517  }
518  else if (!stricmp_utf8_ex(p_line,ptr,"performer",pfc_infinite))
519  {
520  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
521  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid PERFORMER syntax");
522  if (p_line[ptr] == '\"')
523  {
524  ptr++;
525  t_size base = ptr;
526  while(ptr < p_line_length && p_line[ptr] != '\"') ptr++;
527  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid PERFORMER syntax");
528  t_size length = ptr-base;
529  ptr++;
530  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
531  if (ptr != p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid PERFORMER syntax");
532  p_callback.on_performer(p_line+base,length);
533  }
534  else
535  {
536  p_callback.on_performer(p_line+ptr,p_line_length-ptr);
537  }
538  }
539  else if (!stricmp_utf8_ex(p_line,ptr,"songwriter",pfc_infinite))
540  {
541  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
542  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid SONGWRITER syntax");
543  if (p_line[ptr] == '\"')
544  {
545  ptr++;
546  t_size base = ptr;
547  while(ptr < p_line_length && p_line[ptr] != '\"') ptr++;
548  if (ptr == p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid SONGWRITER syntax");
549  t_size length = ptr-base;
550  ptr++;
551  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
552  if (ptr != p_line_length) pfc::throw_exception_with_message< exception_cue > ("invalid SONGWRITER syntax");
553  p_callback.on_songwriter(p_line+base,length);
554  }
555  else
556  {
557  p_callback.on_songwriter(p_line+ptr,p_line_length-ptr);
558  }
559  }
560  else if (!stricmp_utf8_ex(p_line,ptr,"isrc",pfc_infinite))
561  {
562  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
563  t_size length = p_line_length - ptr;
564  if (length == 0) pfc::throw_exception_with_message< exception_cue > ("invalid ISRC syntax");
565  p_callback.on_isrc(p_line+ptr,length);
566  }
567  else if (!stricmp_utf8_ex(p_line,ptr,"catalog",pfc_infinite))
568  {
569  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
570  t_size length = p_line_length - ptr;
571  if (length == 0) pfc::throw_exception_with_message< exception_cue > ("invalid CATALOG syntax");
572  p_callback.on_catalog(p_line+ptr,length);
573  }
574  else if (!stricmp_utf8_ex(p_line,ptr,"flags",pfc_infinite))
575  {
576  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
577  if (ptr < p_line_length)
578  p_callback.on_flags(p_line + ptr, p_line_length - ptr);
579  }
580  else if (!stricmp_utf8_ex(p_line,ptr,"rem",pfc_infinite))
581  {
582  while(ptr < p_line_length && is_spacing(p_line[ptr])) ptr++;
583  if (ptr < p_line_length)
584  p_callback.on_comment(p_line + ptr, p_line_length - ptr);
585  }
586  else if (!stricmp_utf8_ex(p_line,ptr,"postgap",pfc_infinite)) {
587  pfc::throw_exception_with_message< exception_cue > ("POSTGAP is not supported");
588  } else if (!stricmp_utf8_ex(p_line,ptr,"cdtextfile",pfc_infinite)) {
589  //do nothing
590  }
591  else pfc::throw_exception_with_message< exception_cue > ("unknown cuesheet item");
592 }
int SHARED_EXPORT stricmp_utf8_ex(const char *p1, t_size len1, const char *p2, t_size len2)
size_t t_size
Definition: int_types.h:48
unsigned atoui_ex(const char *p_string, t_size p_string_len)
unsigned cuesheet_parse_index_time_ticks_e(const char *p_string, t_size p_length)
Definition: chapterizer.cpp:48
static bool is_numeric(char c)
Definition: cue_parser.cpp:7
static bool is_spacing(char c)
Definition: cue_parser.cpp:10
static bool is_linebreak ( char  c)
static

Definition at line 15 of file cue_parser.cpp.

16 {
17  return c == '\n' || c == '\r';
18 }
static bool is_numeric ( char  c)
static

Definition at line 7 of file cue_parser.cpp.

7 {return c>='0' && c<='9';}
static bool is_spacing ( char  c)
static

Definition at line 10 of file cue_parser.cpp.

11 {
12  return c == ' ' || c == '\t';
13 }
static void validate_file_type ( const char *  p_type,
t_size  p_type_length 
)
static

Definition at line 20 of file cue_parser.cpp.

20  {
21  if (
22  //standard types
23  stricmp_utf8_ex(p_type,p_type_length,"WAVE",pfc_infinite) != 0 &&
24  stricmp_utf8_ex(p_type,p_type_length,"MP3",pfc_infinite) != 0 &&
25  stricmp_utf8_ex(p_type,p_type_length,"AIFF",pfc_infinite) != 0 &&
26  //common user-entered types
27  stricmp_utf8_ex(p_type,p_type_length,"APE",pfc_infinite) != 0 &&
28  stricmp_utf8_ex(p_type,p_type_length,"FLAC",pfc_infinite) != 0 &&
29  stricmp_utf8_ex(p_type,p_type_length,"WV",pfc_infinite) != 0 &&
30  stricmp_utf8_ex(p_type,p_type_length,"WAVPACK",pfc_infinite) != 0
31  )
32  pfc::throw_exception_with_message< exception_cue >(PFC_string_formatter() << "expected WAVE, MP3 or AIFF, got : \"" << pfc::string_part(p_type,p_type_length) << "\"");
33 }
int SHARED_EXPORT stricmp_utf8_ex(const char *p1, t_size len1, const char *p2, t_size len2)
string_part_ref string_part(const char *ptr, t_size len)
Definition: string_base.h:31