2013-09-28 00:24:23 -03:00
|
|
|
#include "dumb.h"
|
|
|
|
#include "internal/riff.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
struct riff *riff_parse(DUMBFILE *f, long offset, long size, unsigned proper) {
|
|
|
|
unsigned stream_size;
|
|
|
|
struct riff *stream;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
if (size < 8)
|
|
|
|
return 0;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
if (dumbfile_seek(f, offset, DFS_SEEK_SET))
|
|
|
|
return 0;
|
|
|
|
if (dumbfile_mgetl(f) != DUMB_ID('R', 'I', 'F', 'F'))
|
|
|
|
return 0;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
stream_size = (int)dumbfile_igetl(f);
|
|
|
|
if (stream_size + 8 > size)
|
|
|
|
return 0;
|
|
|
|
if (stream_size < 4)
|
|
|
|
return 0;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
stream = (struct riff *)malloc(sizeof(struct riff));
|
|
|
|
if (!stream)
|
|
|
|
return 0;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
stream->type = (int)dumbfile_mgetl(f);
|
|
|
|
stream->chunk_count = 0;
|
|
|
|
stream->chunks = 0;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
stream_size -= 4;
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
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);
|
2013-09-28 00:24:23 -03:00
|
|
|
chunk->offset = dumbfile_pos(f);
|
2017-09-26 20:11:54 -03:00
|
|
|
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 {
|
2013-09-28 00:24:23 -03:00
|
|
|
chunk->nested = 0;
|
2017-09-26 20:11:54 -03:00
|
|
|
}
|
2013-09-28 00:24:23 -03:00
|
|
|
dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
|
2017-09-26 20:11:54 -03:00
|
|
|
stream_size -= chunk->size;
|
|
|
|
if (proper && (chunk->size & 1)) {
|
2013-09-28 00:24:23 -03:00
|
|
|
dumbfile_skip(f, 1);
|
2017-09-26 20:11:54 -03:00
|
|
|
--stream_size;
|
|
|
|
}
|
|
|
|
++stream->chunk_count;
|
|
|
|
}
|
2013-09-28 00:24:23 -03:00
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
if (stream_size) {
|
|
|
|
riff_free(stream);
|
|
|
|
stream = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream;
|
2013-09-28 00:24:23 -03:00
|
|
|
}
|
|
|
|
|
2017-09-26 20:11:54 -03:00
|
|
|
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);
|
|
|
|
}
|
2013-09-28 00:24:23 -03:00
|
|
|
}
|