ref: ef707958359b91d9cc34a29f4f5328a069a4c1ce
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); } }