Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions libmpq/mpq.c
Original file line number Diff line number Diff line change
Expand Up @@ -897,25 +897,38 @@ int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uin
block_offset = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].offset + (((long long)mpq_archive->mpq_block_ex[mpq_archive->mpq_map[file_number].block_table_indices].offset_high) << 32) + mpq_archive->mpq_file[file_number]->packed_offset[block_number];
in_size = mpq_archive->mpq_file[file_number]->packed_offset[block_number + 1] - mpq_archive->mpq_file[file_number]->packed_offset[block_number];

/* get implosion status. */
libmpq__file_imploded(mpq_archive, file_number, &imploded);

/* get compression status. */
libmpq__file_compressed(mpq_archive, file_number, &compressed);

/* check if we can avoid allocating a temporary buffer. */
const uint8_t use_in_buf_as_out = in_size <= out_size && (!compressed || in_size == out_size) && !imploded;

/* seek in file. */
if (fseeko(mpq_archive->fp, block_offset + mpq_archive->archive_offset, SEEK_SET) < 0) {

/* something with seek in file failed. */
return LIBMPQ_ERROR_SEEK;
}

/* allocate memory for the read buffer. */
if ((in_buf = calloc(1, in_size)) == NULL) {
if (use_in_buf_as_out) {
in_buf = out_buf;
} else {
/* allocate memory for the read buffer. */
if ((in_buf = calloc(1, in_size)) == NULL) {

/* memory allocation problem. */
return LIBMPQ_ERROR_MALLOC;
/* memory allocation problem. */
return LIBMPQ_ERROR_MALLOC;
}
}

/* read block from file. */
if (fread(in_buf, 1, in_size, mpq_archive->fp) != in_size) {

/* free buffers. */
free(in_buf);
if (!use_in_buf_as_out) free(in_buf);

/* something on reading block failed. */
return LIBMPQ_ERROR_READ;
Expand All @@ -941,26 +954,20 @@ int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uin
}
}

/* get compression status. */
libmpq__file_compressed(mpq_archive, file_number, &compressed);

/* check if file is compressed. */
if (compressed) {

/* decompress block. */
if ((tb = libmpq__decompress_block(in_buf, in_size, out_buf, out_size, LIBMPQ_FLAG_COMPRESS_MULTI)) < 0) {

/* free temporary buffer. */
free(in_buf);
if (!use_in_buf_as_out) free(in_buf);

/* something on decompressing block failed. */
return LIBMPQ_ERROR_UNPACK;
}
}

/* get implosion status. */
libmpq__file_imploded(mpq_archive, file_number, &imploded);

/* check if file is imploded. */
if (imploded) {

Expand Down Expand Up @@ -991,15 +998,15 @@ int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uin
if ((tb = libmpq__decompress_block(in_buf, in_size, out_buf, out_size, LIBMPQ_FLAG_COMPRESS_NONE)) < 0) {

/* free temporary buffer. */
free(in_buf);
if (!use_in_buf_as_out) free(in_buf);

/* something on decompressing block failed. */
return LIBMPQ_ERROR_UNPACK;
}
}

/* free read buffer. */
free(in_buf);
if (!use_in_buf_as_out) free(in_buf);

/* check for null pointer. */
if (transferred != NULL) {
Expand Down