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