Commit 90ced91c authored by Josh Coalson's avatar Josh Coalson
Browse files

split metadata.c into metadata_object.c and metadata_iterators.c

parent 089f3be9
......@@ -48,7 +48,8 @@ libFLAC_la_SOURCES = \
lpc.c \
md5.c \
memory.c \
metadata.c \
metadata_iterators.c \
metadata_object.c \
seek_table.c \
seekable_stream_decoder.c \
stream_decoder.c \
......
......@@ -55,7 +55,8 @@ OBJS = $(ASM_OBJS) \
lpc.o \
md5.o \
memory.o \
metadata.o \
metadata_iterators.o \
metadata_object.o \
seek_table.o \
seekable_stream_decoder.o \
stream_decoder.o \
......
......@@ -39,7 +39,8 @@ C_FILES= \
lpc.c \
md5.c \
memory.c \
metadata.c \
metadata_iterators.c \
metadata_object.c \
seek_table.c \
seekable_stream_decoder.c \
stream_decoder.c \
......
......@@ -32,8 +32,9 @@
#endif
#include <sys/stat.h> /* for stat(), maybe chmod() */
#include "private/metadata.h"
#include "FLAC/assert.h"
#include "FLAC/metadata.h"
#include "FLAC/file_decoder.h"
#ifdef max
......@@ -52,9 +53,6 @@
*
***************************************************************************/
/* this one should probably not go in the public interface: */
static void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object);
static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes);
......@@ -1148,7 +1146,7 @@ FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__MetaData_Iterator *iterato
save = iterator->current->prev;
if(replace_with_padding) {
FLAC__metadata_object_delete_data_(iterator->current->data);
FLAC__metadata_object_delete_data(iterator->current->data);
iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
}
else {
......@@ -1203,479 +1201,6 @@ FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__MetaData_Iterator *i
}
/****************************************************************************
*
* Metadata object routines
*
***************************************************************************/
/*@@@@move
will return pointer to new empty object of type 'type', or 0 if malloc failed
type is valid type
*/
FLAC__StreamMetaData *FLAC__metadata_object_new(FLAC__MetaDataType type)
{
FLAC__StreamMetaData *object = malloc(sizeof(FLAC__StreamMetaData));
if(0 != object) {
memset(object, 0, sizeof(FLAC__StreamMetaData));
object->is_last = false;
object->type = type;
switch(type) {
case FLAC__METADATA_TYPE_STREAMINFO:
object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
break;
case FLAC__METADATA_TYPE_PADDING:
break;
case FLAC__METADATA_TYPE_APPLICATION:
object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN + FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
break;
default:
/* double protection: */
FLAC__ASSERT(0);
free(object);
return 0;
}
}
return object;
}
static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
{
if(bytes > 0 && 0 != from) {
if(0 == (*to = malloc(bytes)))
return false;
memcpy(*to, from, bytes);
}
else {
FLAC__ASSERT(0 == from);
FLAC__ASSERT(bytes == 0);
*to = 0;
}
return true;
}
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__ASSERT(from->length > 0);
if(0 == (to->entry = malloc(from->length)))
return false;
memcpy(to->entry, from->entry, from->length);
}
return true;
}
/*@@@@move
return a pointer to a copy of 'object', or 0 if any malloc failed. does a deep copy. user gets ownership of object.
FLAC__ASSERT(0 != object);
*/
FLAC__StreamMetaData *FLAC__metadata_object_copy(const FLAC__StreamMetaData *object)
{
FLAC__StreamMetaData *to;
unsigned i;
FLAC__ASSERT(0 != object);
if(0 != (to = FLAC__metadata_object_new(object->type))) {
to->is_last = object->is_last;
to->type = object->type;
to->length = object->length;
switch(to->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetaData_StreamInfo));
break;
case FLAC__METADATA_TYPE_PADDING:
break;
case FLAC__METADATA_TYPE_APPLICATION:
memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8);
if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) {
FLAC__metadata_object_delete(to);
return 0;
}
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
to->data.seek_table.num_points = object->data.seek_table.num_points;
if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetaData_SeekPoint))) {
FLAC__metadata_object_delete(to);
return 0;
}
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) {
FLAC__metadata_object_delete(to);
return 0;
}
if(object->data.vorbis_comment.num_comments == 0) {
FLAC__ASSERT(0 == object->data.vorbis_comment.comments);
to->data.vorbis_comment.comments = 0;
}
else {
FLAC__ASSERT(0 != object->data.vorbis_comment.comments);
to->data.vorbis_comment.comments = FLAC__metadata_object_vorbiscomment_entry_array_copy(object->data.vorbis_comment.comments);
if(0 == to->data.vorbis_comment.comments) {
FLAC__metadata_object_delete(to);
return 0;
}
}
to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
break;
default:
/* double protection: */
FLAC__ASSERT(0);
free(to);
return 0;
}
}
return to;
}
void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object)
{
unsigned i;
FLAC__ASSERT(0 != object);
switch(object->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
case FLAC__METADATA_TYPE_PADDING:
break;
case FLAC__METADATA_TYPE_APPLICATION:
if(0 != object->data.application.data)
free(object->data.application.data);
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
if(0 != object->data.seek_table.points)
free(object->data.seek_table.points);
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if(0 != object->data.vorbis_comment.vendor_string.entry)
free(object->data.vorbis_comment.vendor_string.entry);
if(0 != object->data.vorbis_comment.comments) {
FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0);
FLAC__metadata_object_vorbiscomment_entry_array_delete(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
}
break;
default:
FLAC__ASSERT(0);
}
}
/*@@@@move
frees 'object'. does a deep delete.
*/
void FLAC__metadata_object_delete(FLAC__StreamMetaData *object)
{
FLAC__metadata_object_delete_data_(object);
free(object);
}
/*@@@@move
sets the application data to 'data'. if 'copy' is true, makes, copy, else takes ownership of pointer. returns false if copy==true and malloc fails.
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
*/
FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetaData *object, FLAC__byte *data, unsigned length, FLAC__bool copy)
{
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
if(0 != object->data.application.data)
free(object->data.application.data);
if(copy) {
if(!copy_bytes_(&object->data.application.data, data, length))
return false;
}
else {
object->data.application.data = data;
}
object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8 + length;
return true;
}
/*@@@@move
creates an array of seekpoints (FLAC__StreamMetaData_SeekPoint). returns pointer to new array, or NULL if malloc fails.
num_points > 0.
*/
FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_new(unsigned num_points)
{
FLAC__StreamMetaData_SeekPoint *object_array;
FLAC__ASSERT(num_points > 0);
object_array = malloc(num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
if(0 != object_array)
memset(object_array, 0, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
return object_array;
}
/*@@@@move
return pointer to copy of seekpoint array, or NULL if malloc fails.
num_points > 0
object_array != NULL
*/
FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_copy(const FLAC__StreamMetaData_SeekPoint *object_array, unsigned num_points)
{
FLAC__StreamMetaData_SeekPoint *return_array;
FLAC__ASSERT(0 != object_array);
FLAC__ASSERT(num_points > 0);
return_array = FLAC__metadata_object_seekpoint_array_new(num_points);
if(0 != return_array)
memcpy(return_array, object_array, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
return return_array;
}
/*@@@@move
frees object array.
object_array != NULL
*/
void FLAC__metadata_object_seekpoint_array_delete(FLAC__StreamMetaData_SeekPoint *object_array)
{
FLAC__ASSERT(0 != object_array);
free(object_array);
}
FLAC__bool FLAC__metadata_object_seekpoint_array_resize(FLAC__StreamMetaData_SeekPoint **object_array, unsigned old_num_points, unsigned new_num_points)
{
FLAC__ASSERT(0 != object_array);
if(0 == *object_array) {
FLAC__ASSERT(old_num_points == 0);
if(0 == new_num_points)
return true;
else
return 0 != (*object_array = FLAC__metadata_object_seekpoint_array_new(new_num_points));
}
else {
const unsigned old_size = old_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
const unsigned new_size = new_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
FLAC__ASSERT(old_num_points > 0);
if(new_size == 0) {
free(*object_array);
*object_array = 0;
}
else if(0 == (*object_array = realloc(*object_array, new_size)))
return false;
if(new_size > old_size)
memset(*object_array + old_num_points, 0, new_size - old_size);
return true;
}
}
FLAC__bool FLAC__metadata_object_seektable_set_points(FLAC__StreamMetaData *object, FLAC__StreamMetaData_SeekPoint *points, unsigned num_points, FLAC__bool copy)
{
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
FLAC__ASSERT((0 != points && num_points > 0) || (0 == points && num_points == 0 && copy == false));
object->data.seek_table.num_points = num_points;
if(0 != object->data.seek_table.points)
FLAC__metadata_object_seekpoint_array_delete(object->data.seek_table.points);
if(copy) {
if(0 == (object->data.seek_table.points = FLAC__metadata_object_seekpoint_array_copy(points, num_points)))
return false;
}
else {
object->data.seek_table.points = points;
}
object->length = num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
return true;
}
FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_vorbiscomment_entry_array_new(unsigned num_comments)
{
FLAC__StreamMetaData_VorbisComment_Entry *object_array;
FLAC__ASSERT(num_comments > 0);
object_array = malloc(num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
if(0 != object_array)
memset(object_array, 0, num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
return object_array;
}
FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_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 = FLAC__metadata_object_vorbiscomment_entry_array_new(num_comments);
if(0 != return_array) {
unsigned i;
/* Need to do this to set the pointers inside the comments to 0.
* In case of an error in the following loop, the object will be
* deleted and we don't want the destructor freeing uninitialized
* pointers.
*/
memset(return_array, 0, num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
for(i = 0; i < num_comments; i++) {
if(!copy_vcentry_(return_array+i, object_array+i)) {
FLAC__metadata_object_vorbiscomment_entry_array_delete(return_array, num_comments);
return 0;
}
}
}
return return_array;
}
void FLAC__metadata_object_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);
}
FLAC__bool FLAC__metadata_object_vorbiscomment_entry_array_resize(FLAC__StreamMetaData_VorbisComment_Entry **object_array, unsigned old_num_comments, unsigned new_num_comments)
{
FLAC__ASSERT(0 != object_array);
if(0 == *object_array) {
FLAC__ASSERT(old_num_comments == 0);
if(0 == new_num_comments)
return true;
else
return 0 != (*object_array = FLAC__metadata_object_vorbiscomment_entry_array_new(new_num_comments));
}
else {
const unsigned old_size = old_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
const unsigned new_size = new_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
FLAC__ASSERT(old_num_comments > 0);
/* if shrinking, free the truncated entries */
if(new_num_comments < old_num_comments) {
unsigned i;
for(i = new_num_comments; i < old_num_comments; i++)
if(0 != (*object_array)[i].entry)
free((*object_array)[i].entry);
}
if(new_size == 0) {
free(*object_array);
*object_array = 0;
}
else if(0 == (*object_array = realloc(*object_array, new_size)))
return false;
/* if growing, zero all the length/pointers of new elements */
if(new_size > old_size)
memset(*object_array + old_num_comments, 0, new_size - old_size);
return true;
}
}
FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetaData *object, FLAC__byte *entry, unsigned length, FLAC__bool copy)
{
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__ASSERT((0 != entry && length > 0) || (0 == entry && length == 0 && copy == false));
if(0 != object->data.vorbis_comment.vendor_string.entry)
free(object->data.vorbis_comment.vendor_string.entry);
object->length -= object->data.vorbis_comment.vendor_string.length;
if(copy) {
if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, entry, length)) {
object->data.vorbis_comment.vendor_string.length = 0;
return false;
}
}
else {
object->data.vorbis_comment.vendor_string.entry = entry;
}
object->data.vorbis_comment.vendor_string.length = length;
object->length += object->data.vorbis_comment.vendor_string.length;
return true;
}
FLAC__bool FLAC__metadata_object_vorbiscomment_set_comments(FLAC__StreamMetaData *object, FLAC__StreamMetaData_VorbisComment_Entry *comments, unsigned num_comments, FLAC__bool copy)
{
unsigned i;
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__ASSERT((0 != comments && num_comments > 0) || (0 == comments && num_comments == 0 && copy == false));
object->data.vorbis_comment.num_comments = num_comments;
if(0 != object->data.vorbis_comment.comments)
FLAC__metadata_object_vorbiscomment_entry_array_delete(object->data.vorbis_comment.comments, num_comments);
if(copy) {
if(0 == (object->data.vorbis_comment.comments = FLAC__metadata_object_vorbiscomment_entry_array_copy(comments, num_comments)))
return false;
}
else {
object->data.vorbis_comment.comments = comments;
}
object->length = num_comments * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
/* calculate the new length */
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;
}
return true;
}
FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetaData *object, unsigned comment_num, FLAC__byte *entry, unsigned length, FLAC__bool copy)
{
}
FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetaData *object, unsigned comment_num, FLAC__byte *entry, unsigned length, FLAC__bool copy)
{
}
FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetaData *object, unsigned comment_num)
{
}
/****************************************************************************
*
* Local function definitions
......
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001,2002 Josh Coalson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#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 = 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 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 = malloc(from->length)))
return false;
memcpy(x, from->entry, from->length);
to->entry = x;
}