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