ref: 9a77e91ba8d54b9e2d0cca801d8995a266374112
dir: /src/helpers/riff.c/
#include "dumb.h" #include "internal/riff.h" #include <stdlib.h> struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper ) { unsigned stream_size; struct riff * stream; if ( size < 8 ) return 0; if ( dumbfile_seek(f, offset, DFS_SEEK_SET) ) return 0; if ( dumbfile_mgetl(f) != DUMB_ID('R','I','F','F') ) return 0; stream_size = (int) dumbfile_igetl(f); if ( stream_size + 8 > size ) return 0; if ( stream_size < 4 ) return 0; stream = (struct riff *) malloc( sizeof( struct riff ) ); if ( ! stream ) return 0; stream->type = (int) dumbfile_mgetl(f); stream->chunk_count = 0; stream->chunks = 0; stream_size -= 4; while ( stream_size && !dumbfile_error(f) ) { struct riff_chunk * chunk; if ( stream_size < 8 ) break; stream->chunks = ( struct riff_chunk * ) realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) ); if ( ! stream->chunks ) break; chunk = stream->chunks + stream->chunk_count; chunk->type = (int) dumbfile_mgetl(f); chunk->size = (int) dumbfile_igetl(f); chunk->offset = dumbfile_pos(f); stream_size -= 8; if ( stream_size < chunk->size ) break; if ( chunk->type == DUMB_ID('R','I','F','F') ) { chunk->nested = riff_parse( f, chunk->offset - 8, chunk->size + 8, proper ); if ( ! chunk->nested ) break; } else { chunk->nested = 0; } dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET); stream_size -= chunk->size; if ( proper && ( chunk->size & 1 ) ) { dumbfile_skip(f, 1); -- stream_size; } ++stream->chunk_count; } if ( stream_size ) { riff_free( stream ); stream = 0; } return stream; } void riff_free( struct riff * stream ) { if ( stream ) { if ( stream->chunks ) { unsigned i; for ( i = 0; i < stream->chunk_count; ++i ) { struct riff_chunk * chunk = stream->chunks + i; if ( chunk->nested ) riff_free( chunk->nested ); } free( stream->chunks ); } free( stream ); } }