static void flacdec_read_vorbis_comment(BitstreamReader *comment, unsigned channel_count, int *channel_mask) { struct bs_buffer *line = buf_new(); unsigned line_len; unsigned total_lines; const char mask_prefix[] = "WAVEFORMATEXTENSIBLE_CHANNEL_MASK="; if (!setjmp(*br_try(comment))) { /*skip over vendor string*/ line_len = comment->read(comment, 32); comment->skip_bytes(comment, line_len); /*walk through all entries in the comment*/ for (total_lines = comment->read(comment, 32); total_lines > 0; total_lines--) { const char *s; /*populate entry one character at a time (this avoids allocating a big chunk of space if the length field is something way too large)*/ buf_reset(line); for (line_len = comment->read(comment, 32); line_len > 0; line_len--) { buf_putc( toupper((int)comment->read(comment, 8)), line); } buf_putc(0, line); /*NULL terminator*/ s = (const char *)buf_window_start(line); /*if line starts with mask prefix*/ if (strstr(s, mask_prefix) == s) { /*convert rest of line to base-16 integer*/ unsigned mask = (unsigned)strtoul( s + strlen(mask_prefix), NULL, 16); /*and populate mask field if its number of channel bits matches the stream's channel count*/ if (channel_bits(mask) == channel_count) { *channel_mask = mask; } } } br_etry(comment); } else { /*read error in VORBIS_COMMENT (probably invalid length field somewhere)*/ br_etry(comment); } buf_close(line); }
unsigned buf_read(struct bs_buffer *stream, uint8_t *data, unsigned data_size) { const buf_size_t to_read = MIN(data_size, buf_window_size(stream)); memcpy(data, buf_window_start(stream), to_read); stream->window_start += to_read; return to_read; }
void buf_resize(struct bs_buffer *stream, unsigned additional_bytes) { /*only perform resize if space actually needed*/ if (additional_bytes > buf_unused_size(stream)) { if (stream->window_start > 0) { /*shift window down before extending buffer to add more space*/ if (buf_window_size(stream)) { memmove(stream->data, buf_window_start(stream), buf_window_size(stream)); } stream->window_end -= stream->window_start; stream->window_start = 0; } while (additional_bytes > buf_unused_size(stream)) { stream->data_size *= 2; } stream->data = realloc(stream->data, stream->data_size); } }