A set of windows utf8 patches fromJanne Hyvärinen <cse@sci.fi>.
[platform/upstream/flac.git] / src / libFLAC / format.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009  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 "share/compat.h"
42 #include "private/format.h"
43 #include "private/macros.h"
44
45 /* VERSION should come from configure */
46 FLAC_API const char *FLAC__VERSION_STRING = VERSION;
47
48 #if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__
49 /* yet one more hack because of MSVC6: */
50 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917";
51 #else
52 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917";
53 #endif
54
55 FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
56 FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
57 FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
58
59 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
60 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
61 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
62 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
63 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
64 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
65 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
66 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
67 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
68
69 FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
70
71 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
72 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
73 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
74
75 FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
76
77 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
78 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
79
80 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
81 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
82 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
83
84 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
85 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
86 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
87 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
88 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
89 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
90 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
91
92 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
93 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
94 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
95 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
96 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
97
98 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
99 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
100 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
101 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
102 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
103 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
104 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
105 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
106
107 FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
108 FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
109 FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
110
111 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
112 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
113 FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
114 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
115 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
116 FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
117 FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
118 FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
119 FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
120 FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
121
122 FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
123
124 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
125 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
126 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
127 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
128 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
129
130 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
131 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
132
133 FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
134         "PARTITIONED_RICE",
135         "PARTITIONED_RICE2"
136 };
137
138 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
139 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
140
141 FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
142 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
143 FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
144
145 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
146 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
147 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
148 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
149
150 FLAC_API const char * const FLAC__SubframeTypeString[] = {
151         "CONSTANT",
152         "VERBATIM",
153         "FIXED",
154         "LPC"
155 };
156
157 FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
158         "INDEPENDENT",
159         "LEFT_SIDE",
160         "RIGHT_SIDE",
161         "MID_SIDE"
162 };
163
164 FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
165         "FRAME_NUMBER_TYPE_FRAME_NUMBER",
166         "FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
167 };
168
169 FLAC_API const char * const FLAC__MetadataTypeString[] = {
170         "STREAMINFO",
171         "PADDING",
172         "APPLICATION",
173         "SEEKTABLE",
174         "VORBIS_COMMENT",
175         "CUESHEET",
176         "PICTURE"
177 };
178
179 FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
180         "Other",
181         "32x32 pixels 'file icon' (PNG only)",
182         "Other file icon",
183         "Cover (front)",
184         "Cover (back)",
185         "Leaflet page",
186         "Media (e.g. label side of CD)",
187         "Lead artist/lead performer/soloist",
188         "Artist/performer",
189         "Conductor",
190         "Band/Orchestra",
191         "Composer",
192         "Lyricist/text writer",
193         "Recording Location",
194         "During recording",
195         "During performance",
196         "Movie/video screen capture",
197         "A bright coloured fish",
198         "Illustration",
199         "Band/artist logotype",
200         "Publisher/Studio logotype"
201 };
202
203 FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
204 {
205         if(sample_rate == 0 || sample_rate > FLAC__MAX_SAMPLE_RATE) {
206                 return false;
207         }
208         else
209                 return true;
210 }
211
212 FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned sample_rate)
213 {
214         if(blocksize > 16384)
215                 return false;
216         else if(sample_rate <= 48000 && blocksize > 4608)
217                 return false;
218         else
219                 return true;
220 }
221
222 FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate)
223 {
224         if(
225                 !FLAC__format_sample_rate_is_valid(sample_rate) ||
226                 (
227                         sample_rate >= (1u << 16) &&
228                         !(sample_rate % 1000 == 0 || sample_rate % 10 == 0)
229                 )
230         ) {
231                 return false;
232         }
233         else
234                 return true;
235 }
236
237 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
238 FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table)
239 {
240         unsigned i;
241         FLAC__uint64 prev_sample_number = 0;
242         FLAC__bool got_prev = false;
243
244         FLAC__ASSERT(0 != seek_table);
245
246         for(i = 0; i < seek_table->num_points; i++) {
247                 if(got_prev) {
248                         if(
249                                 seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
250                                 seek_table->points[i].sample_number <= prev_sample_number
251                         )
252                                 return false;
253                 }
254                 prev_sample_number = seek_table->points[i].sample_number;
255                 got_prev = true;
256         }
257
258         return true;
259 }
260
261 /* used as the sort predicate for qsort() */
262 static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r)
263 {
264         /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */
265         if(l->sample_number == r->sample_number)
266                 return 0;
267         else if(l->sample_number < r->sample_number)
268                 return -1;
269         else
270                 return 1;
271 }
272
273 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
274 FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
275 {
276         unsigned i, j;
277         FLAC__bool first;
278
279         FLAC__ASSERT(0 != seek_table);
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  */
312 static 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
353 FLAC_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
362 FLAC_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
386 FLAC_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 */
412 FLAC_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 */
491 FLAC_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  */
518 unsigned 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
528 unsigned 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
538 unsigned 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
553 void 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
562 void 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
573 FLAC__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 = realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
581                         return false;
582                 if(0 == (object->raw_bits = 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 }