metadata_object.c
来自「这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔」· C语言 代码 · 共 1,474 行 · 第 1/4 页
C
1,474 行
/* 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 + =
减小字号Ctrl + -
显示快捷键?