📄 metadata_object.c
字号:
/* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Xiph.org Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include <stdlib.h>#include <string.h>#include "private/metadata.h"#include "FLAC/assert.h"/**************************************************************************** * * Local routines * ***************************************************************************/static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes){ if(bytes > 0 && 0 != from) { FLAC__byte *x; if(0 == (x = (FLAC__byte*)malloc(bytes))) return false; memcpy(x, from, bytes); *to = x; } else { FLAC__ASSERT(0 == from); FLAC__ASSERT(bytes == 0); *to = 0; } return true;}static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length){ FLAC__byte *x = (FLAC__byte*)realloc(*entry, length+1); if(0 != x) { x[length] = '\0'; *entry = x; return true; } else return false;}static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from){ to->length = from->length; if(0 == from->entry) { FLAC__ASSERT(from->length == 0); to->entry = 0; } else { FLAC__byte *x; FLAC__ASSERT(from->length > 0); if(0 == (x = (FLAC__byte*)malloc(from->length+1))) return false; memcpy(x, from->entry, from->length); x[from->length] = '\0'; to->entry = x; } return true;}static FLAC__bool copy_track_(FLAC__StreamMetadata_CueSheet_Track *to, const FLAC__StreamMetadata_CueSheet_Track *from){ memcpy(to, from, sizeof(FLAC__StreamMetadata_CueSheet_Track)); if(0 == from->indices) { FLAC__ASSERT(from->num_indices == 0); } else { FLAC__StreamMetadata_CueSheet_Index *x; FLAC__ASSERT(from->num_indices > 0); if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)malloc(from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index)))) return false; memcpy(x, from->indices, from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index)); to->indices = x; } return true;}static void seektable_calculate_length_(FLAC__StreamMetadata *object){ FLAC__ASSERT(0 != object); FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); object->length = object->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;}static FLAC__StreamMetadata_SeekPoint *seekpoint_array_new_(unsigned num_points){ FLAC__StreamMetadata_SeekPoint *object_array; FLAC__ASSERT(num_points > 0); object_array = (FLAC__StreamMetadata_SeekPoint*)malloc(num_points * sizeof(FLAC__StreamMetadata_SeekPoint)); if(0 != object_array) { unsigned i; for(i = 0; i < num_points; i++) { object_array[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; object_array[i].stream_offset = 0; object_array[i].frame_samples = 0; } } return object_array;}static void vorbiscomment_calculate_length_(FLAC__StreamMetadata *object){ unsigned i; FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN) / 8; object->length += object->data.vorbis_comment.vendor_string.length; object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8; for(i = 0; i < object->data.vorbis_comment.num_comments; i++) { object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8); object->length += object->data.vorbis_comment.comments[i].length; }}static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_new_(unsigned num_comments){ FLAC__ASSERT(num_comments > 0); return (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry));}static void vorbiscomment_entry_array_delete_(FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments){ unsigned i; FLAC__ASSERT(0 != object_array && num_comments > 0); for(i = 0; i < num_comments; i++) if(0 != object_array[i].entry) free(object_array[i].entry); if(0 != object_array) free(object_array);}static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_copy_(const FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments){ FLAC__StreamMetadata_VorbisComment_Entry *return_array; FLAC__ASSERT(0 != object_array); FLAC__ASSERT(num_comments > 0); return_array = vorbiscomment_entry_array_new_(num_comments); if(0 != return_array) { unsigned i; for(i = 0; i < num_comments; i++) { if(!copy_vcentry_(return_array+i, object_array+i)) { vorbiscomment_entry_array_delete_(return_array, num_comments); return 0; } } } return return_array;}static FLAC__bool vorbiscomment_set_entry_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry *dest, const FLAC__StreamMetadata_VorbisComment_Entry *src, FLAC__bool copy){ FLAC__byte *save; FLAC__ASSERT(0 != object); FLAC__ASSERT(0 != dest); FLAC__ASSERT(0 != src); FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__ASSERT((0 != src->entry && src->length > 0) || (0 == src->entry && src->length == 0)); save = dest->entry; if(0 != src->entry && src->length > 0) { if(copy) { /* do the copy first so that if we fail we leave the dest object untouched */ if(!copy_vcentry_(dest, src)) return false; } else { /* we have to make sure that the string we're taking over is null-terminated */ /* * Stripping the const from src->entry is OK since we're taking * ownership of the pointer. This is a hack around a deficiency * in the API where the same function is used for 'copy' and * 'own', but the source entry is a const pointer. If we were * precise, the 'own' flavor would be a separate function with a * non-const source pointer. But it's not, so we hack away. */ if(!ensure_null_terminated_((FLAC__byte**)(&src->entry), src->length)) return false; *dest = *src; } } else { /* the src is null */ *dest = *src; } if(0 != save) free(save); vorbiscomment_calculate_length_(object); return true;}static int vorbiscomment_find_entry_from_(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name, unsigned field_name_length){ unsigned i; FLAC__ASSERT(0 != object); FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__ASSERT(0 != field_name); for(i = offset; i < object->data.vorbis_comment.num_comments; i++) { if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) return (int)i; } return -1;}static void cuesheet_calculate_length_(FLAC__StreamMetadata *object){ unsigned i; FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); object->length = ( FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN + FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN + FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN ) / 8; object->length += object->data.cue_sheet.num_tracks * ( FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN ) / 8; for(i = 0; i < object->data.cue_sheet.num_tracks; i++) { object->length += object->data.cue_sheet.tracks[i].num_indices * ( FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN + FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN + FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN ) / 8; }}static FLAC__StreamMetadata_CueSheet_Index *cuesheet_track_index_array_new_(unsigned num_indices){ FLAC__ASSERT(num_indices > 0); return (FLAC__StreamMetadata_CueSheet_Index*)calloc(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index));}static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_new_(unsigned num_tracks){ FLAC__ASSERT(num_tracks > 0); return (FLAC__StreamMetadata_CueSheet_Track*)calloc(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));}static void cuesheet_track_array_delete_(FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks){ unsigned i; FLAC__ASSERT(0 != object_array && num_tracks > 0); for(i = 0; i < num_tracks; i++) { if(0 != object_array[i].indices) { FLAC__ASSERT(object_array[i].num_indices > 0); free(object_array[i].indices); } } if(0 != object_array) free(object_array);}static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_copy_(const FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks){ FLAC__StreamMetadata_CueSheet_Track *return_array; FLAC__ASSERT(0 != object_array); FLAC__ASSERT(num_tracks > 0); return_array = cuesheet_track_array_new_(num_tracks); if(0 != return_array) { unsigned i; for(i = 0; i < num_tracks; i++) { if(!copy_track_(return_array+i, object_array+i)) { cuesheet_track_array_delete_(return_array, num_tracks); return 0; } } } return return_array;}static FLAC__bool cuesheet_set_track_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_CueSheet_Track *dest, const FLAC__StreamMetadata_CueSheet_Track *src, FLAC__bool copy){ FLAC__StreamMetadata_CueSheet_Index *save; FLAC__ASSERT(0 != object); FLAC__ASSERT(0 != dest); FLAC__ASSERT(0 != src); FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); FLAC__ASSERT((0 != src->indices && src->num_indices > 0) || (0 == src->indices && src->num_indices == 0)); save = dest->indices; /* do the copy first so that if we fail we leave the object untouched */ if(copy) { if(!copy_track_(dest, src)) return false; } else { *dest = *src; } if(0 != save) free(save);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -