1/* libFLAC - Free Lossless Audio Codec library
2 * Copyright (C) 2000-2009  Josh Coalson
3 * Copyright (C) 2011-2014  Xiph.Org Foundation
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * - Neither the name of the Xiph.org Foundation nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifdef HAVE_CONFIG_H
34#  include <config.h>
35#endif
36
37#include <stdio.h>
38#include <stdlib.h> /* for qsort() */
39#include <string.h> /* for memset() */
40#include "FLAC/assert.h"
41#include "FLAC/format.h"
42#include "share/alloc.h"
43#include "share/compat.h"
44#include "private/format.h"
45#include "private/macros.h"
46
47/* VERSION should come from configure */
48FLAC_API const char *FLAC__VERSION_STRING = VERSION;
49
50FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20141125";
51
52FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
53FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
54FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
55
56FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
57FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
58FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
59FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
60FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
61FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
62FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
63FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
64FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
65
66FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
67
68FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
69FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
70FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
71
72FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
73
74FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
75FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
76
77FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
78FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
79FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
80
81FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
82FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
83FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
84FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
85FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
86FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
87FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
88
89FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
90FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
91FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
92FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
93FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
94
95FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
96FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
97FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
98FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
99FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
100FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
101FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
102FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
103
104FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
105FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
106FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
107
108FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
109FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
110FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
111FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
112FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
113FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
114FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
115FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
116FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
117FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
118
119FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
120
121FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
122FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
123FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
124FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
125FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
126
127FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
128FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
129
130FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
131	"PARTITIONED_RICE",
132	"PARTITIONED_RICE2"
133};
134
135FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
136FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
137
138FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
139FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
140FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
141
142FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
143FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
144FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
145FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
146
147FLAC_API const char * const FLAC__SubframeTypeString[] = {
148	"CONSTANT",
149	"VERBATIM",
150	"FIXED",
151	"LPC"
152};
153
154FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
155	"INDEPENDENT",
156	"LEFT_SIDE",
157	"RIGHT_SIDE",
158	"MID_SIDE"
159};
160
161FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
162	"FRAME_NUMBER_TYPE_FRAME_NUMBER",
163	"FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
164};
165
166FLAC_API const char * const FLAC__MetadataTypeString[] = {
167	"STREAMINFO",
168	"PADDING",
169	"APPLICATION",
170	"SEEKTABLE",
171	"VORBIS_COMMENT",
172	"CUESHEET",
173	"PICTURE"
174};
175
176FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
177	"Other",
178	"32x32 pixels 'file icon' (PNG only)",
179	"Other file icon",
180	"Cover (front)",
181	"Cover (back)",
182	"Leaflet page",
183	"Media (e.g. label side of CD)",
184	"Lead artist/lead performer/soloist",
185	"Artist/performer",
186	"Conductor",
187	"Band/Orchestra",
188	"Composer",
189	"Lyricist/text writer",
190	"Recording Location",
191	"During recording",
192	"During performance",
193	"Movie/video screen capture",
194	"A bright coloured fish",
195	"Illustration",
196	"Band/artist logotype",
197	"Publisher/Studio logotype"
198};
199
200FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
201{
202	if(sample_rate == 0 || sample_rate > FLAC__MAX_SAMPLE_RATE) {
203		return false;
204	}
205	else
206		return true;
207}
208
209FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned sample_rate)
210{
211	if(blocksize > 16384)
212		return false;
213	else if(sample_rate <= 48000 && blocksize > 4608)
214		return false;
215	else
216		return true;
217}
218
219FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate)
220{
221	if(
222		!FLAC__format_sample_rate_is_valid(sample_rate) ||
223		(
224			sample_rate >= (1u << 16) &&
225			!(sample_rate % 1000 == 0 || sample_rate % 10 == 0)
226		)
227	) {
228		return false;
229	}
230	else
231		return true;
232}
233
234/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
235FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table)
236{
237	unsigned i;
238	FLAC__uint64 prev_sample_number = 0;
239	FLAC__bool got_prev = false;
240
241	FLAC__ASSERT(0 != seek_table);
242
243	for(i = 0; i < seek_table->num_points; i++) {
244		if(got_prev) {
245			if(
246				seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
247				seek_table->points[i].sample_number <= prev_sample_number
248			)
249				return false;
250		}
251		prev_sample_number = seek_table->points[i].sample_number;
252		got_prev = true;
253	}
254
255	return true;
256}
257
258/* used as the sort predicate for qsort() */
259static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r)
260{
261	/* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */
262	if(l->sample_number == r->sample_number)
263		return 0;
264	else if(l->sample_number < r->sample_number)
265		return -1;
266	else
267		return 1;
268}
269
270/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
271FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
272{
273	unsigned i, j;
274	FLAC__bool first;
275
276	FLAC__ASSERT(0 != seek_table);
277
278	if (seek_table->num_points == 0)
279		return 0;
280
281	/* sort the seekpoints */
282	qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_);
283
284	/* uniquify the seekpoints */
285	first = true;
286	for(i = j = 0; i < seek_table->num_points; i++) {
287		if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
288			if(!first) {
289				if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number)
290					continue;
291			}
292		}
293		first = false;
294		seek_table->points[j++] = seek_table->points[i];
295	}
296
297	for(i = j; i < seek_table->num_points; i++) {
298		seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
299		seek_table->points[i].stream_offset = 0;
300		seek_table->points[i].frame_samples = 0;
301	}
302
303	return j;
304}
305
306/*
307 * also disallows non-shortest-form encodings, c.f.
308 *   http://www.unicode.org/versions/corrigendum1.html
309 * and a more clear explanation at the end of this section:
310 *   http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
311 */
312static unsigned utf8len_(const FLAC__byte *utf8)
313{
314	FLAC__ASSERT(0 != utf8);
315	if ((utf8[0] & 0x80) == 0) {
316		return 1;
317	}
318	else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) {
319		if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */
320			return 0;
321		return 2;
322	}
323	else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) {
324		if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */
325			return 0;
326		/* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */
327		if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */
328			return 0;
329		if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */
330			return 0;
331		return 3;
332	}
333	else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) {
334		if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */
335			return 0;
336		return 4;
337	}
338	else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) {
339		if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */
340			return 0;
341		return 5;
342	}
343	else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) {
344		if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */
345			return 0;
346		return 6;
347	}
348	else {
349		return 0;
350	}
351}
352
353FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name)
354{
355	char c;
356	for(c = *name; c; c = *(++name))
357		if(c < 0x20 || c == 0x3d || c > 0x7d)
358			return false;
359	return true;
360}
361
362FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length)
363{
364	if(length == (unsigned)(-1)) {
365		while(*value) {
366			unsigned n = utf8len_(value);
367			if(n == 0)
368				return false;
369			value += n;
370		}
371	}
372	else {
373		const FLAC__byte *end = value + length;
374		while(value < end) {
375			unsigned n = utf8len_(value);
376			if(n == 0)
377				return false;
378			value += n;
379		}
380		if(value != end)
381			return false;
382	}
383	return true;
384}
385
386FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length)
387{
388	const FLAC__byte *s, *end;
389
390	for(s = entry, end = s + length; s < end && *s != '='; s++) {
391		if(*s < 0x20 || *s > 0x7D)
392			return false;
393	}
394	if(s == end)
395		return false;
396
397	s++; /* skip '=' */
398
399	while(s < end) {
400		unsigned n = utf8len_(s);
401		if(n == 0)
402			return false;
403		s += n;
404	}
405	if(s != end)
406		return false;
407
408	return true;
409}
410
411/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
412FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation)
413{
414	unsigned i, j;
415
416	if(check_cd_da_subset) {
417		if(cue_sheet->lead_in < 2 * 44100) {
418			if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds";
419			return false;
420		}
421		if(cue_sheet->lead_in % 588 != 0) {
422			if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples";
423			return false;
424		}
425	}
426
427	if(cue_sheet->num_tracks == 0) {
428		if(violation) *violation = "cue sheet must have at least one track (the lead-out)";
429		return false;
430	}
431
432	if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) {
433		if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)";
434		return false;
435	}
436
437	for(i = 0; i < cue_sheet->num_tracks; i++) {
438		if(cue_sheet->tracks[i].number == 0) {
439			if(violation) *violation = "cue sheet may not have a track number 0";
440			return false;
441		}
442
443		if(check_cd_da_subset) {
444			if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) {
445				if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170";
446				return false;
447			}
448		}
449
450		if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) {
451			if(violation) {
452				if(i == cue_sheet->num_tracks-1) /* the lead-out track... */
453					*violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples";
454				else
455					*violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples";
456			}
457			return false;
458		}
459
460		if(i < cue_sheet->num_tracks - 1) {
461			if(cue_sheet->tracks[i].num_indices == 0) {
462				if(violation) *violation = "cue sheet track must have at least one index point";
463				return false;
464			}
465
466			if(cue_sheet->tracks[i].indices[0].number > 1) {
467				if(violation) *violation = "cue sheet track's first index number must be 0 or 1";
468				return false;
469			}
470		}
471
472		for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) {
473			if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) {
474				if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples";
475				return false;
476			}
477
478			if(j > 0) {
479				if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) {
480					if(violation) *violation = "cue sheet track index numbers must increase by 1";
481					return false;
482				}
483			}
484		}
485	}
486
487	return true;
488}
489
490/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
491FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
492{
493	char *p;
494	FLAC__byte *b;
495
496	for(p = picture->mime_type; *p; p++) {
497		if(*p < 0x20 || *p > 0x7e) {
498			if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
499			return false;
500		}
501	}
502
503	for(b = picture->description; *b; ) {
504		unsigned n = utf8len_(b);
505		if(n == 0) {
506			if(violation) *violation = "description string must be valid UTF-8";
507			return false;
508		}
509		b += n;
510	}
511
512	return true;
513}
514
515/*
516 * These routines are private to libFLAC
517 */
518unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order)
519{
520	return
521		FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(
522			FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize),
523			blocksize,
524			predictor_order
525		);
526}
527
528unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize)
529{
530	unsigned max_rice_partition_order = 0;
531	while(!(blocksize & 1)) {
532		max_rice_partition_order++;
533		blocksize >>= 1;
534	}
535	return flac_min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order);
536}
537
538unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order)
539{
540	unsigned max_rice_partition_order = limit;
541
542	while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order)
543		max_rice_partition_order--;
544
545	FLAC__ASSERT(
546		(max_rice_partition_order == 0 && blocksize >= predictor_order) ||
547		(max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order)
548	);
549
550	return max_rice_partition_order;
551}
552
553void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
554{
555	FLAC__ASSERT(0 != object);
556
557	object->parameters = 0;
558	object->raw_bits = 0;
559	object->capacity_by_order = 0;
560}
561
562void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
563{
564	FLAC__ASSERT(0 != object);
565
566	if(0 != object->parameters)
567		free(object->parameters);
568	if(0 != object->raw_bits)
569		free(object->raw_bits);
570	FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object);
571}
572
573FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order)
574{
575	FLAC__ASSERT(0 != object);
576
577	FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits));
578
579	if(object->capacity_by_order < max_partition_order) {
580		if(0 == (object->parameters = safe_realloc_(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
581			return false;
582		if(0 == (object->raw_bits = safe_realloc_(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order))))
583			return false;
584		memset(object->raw_bits, 0, sizeof(unsigned)*(1 << max_partition_order));
585		object->capacity_by_order = max_partition_order;
586	}
587
588	return true;
589}
590