Home | History | Annotate | Download | only in libFLAC
      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 */
     60 FLAC_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: */
     64 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917";
     65 #else
     66 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917";
     67 #endif
     68 
     69 FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
     70 FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
     71 FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
     72 
     73 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
     74 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
     75 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
     76 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
     77 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
     78 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
     79 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
     80 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
     81 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
     82 
     83 FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
     84 
     85 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
     86 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
     87 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
     88 
     89 FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
     90 
     91 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
     92 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
     93 
     94 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
     95 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
     96 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
     97 
     98 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
     99 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
    100 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
    101 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
    102 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
    103 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
    104 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
    105 
    106 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
    107 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
    108 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
    109 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
    110 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
    111 
    112 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
    113 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
    114 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
    115 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
    116 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
    117 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
    118 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
    119 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
    120 
    121 FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
    122 FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
    123 FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
    124 
    125 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
    126 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
    127 FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
    128 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
    129 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
    130 FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
    131 FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
    132 FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
    133 FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
    134 FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
    135 
    136 FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
    137 
    138 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
    139 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
    140 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
    141 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
    142 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
    143 
    144 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
    145 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
    146 
    147 FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
    148 	"PARTITIONED_RICE",
    149 	"PARTITIONED_RICE2"
    150 };
    151 
    152 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
    153 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
    154 
    155 FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
    156 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
    157 FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
    158 
    159 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
    160 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
    161 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
    162 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
    163 
    164 FLAC_API const char * const FLAC__SubframeTypeString[] = {
    165 	"CONSTANT",
    166 	"VERBATIM",
    167 	"FIXED",
    168 	"LPC"
    169 };
    170 
    171 FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
    172 	"INDEPENDENT",
    173 	"LEFT_SIDE",
    174 	"RIGHT_SIDE",
    175 	"MID_SIDE"
    176 };
    177 
    178 FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
    179 	"FRAME_NUMBER_TYPE_FRAME_NUMBER",
    180 	"FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
    181 };
    182 
    183 FLAC_API const char * const FLAC__MetadataTypeString[] = {
    184 	"STREAMINFO",
    185 	"PADDING",
    186 	"APPLICATION",
    187 	"SEEKTABLE",
    188 	"VORBIS_COMMENT",
    189 	"CUESHEET",
    190 	"PICTURE"
    191 };
    192 
    193 FLAC_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 
    217 FLAC_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 
    226 FLAC_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 */
    242 FLAC_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() */
    266 static 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 */
    278 FLAC_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  */
    316 static 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 
    357 FLAC_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 
    366 FLAC_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 
    390 FLAC_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 */
    416 FLAC_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 */
    495 FLAC_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  */
    522 unsigned 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 
    532 unsigned 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 
    542 unsigned 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 
    557 void 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 
    566 void 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 
    577 FLAC__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