diff options
-rw-r--r-- | mpq-file.c | 87 |
1 files changed, 48 insertions, 39 deletions
@@ -153,56 +153,65 @@ static int cache_sector(struct mpq_file_t * mpq_f, int sector) { } /* - * The read function will call itself recursively, in order to split the calls across the sectors. + * The read function will iterate several times, in order to split the calls across the sectors. */ uint32_t mpqlib_read(struct mpq_file_t * mpq_f, void * _buffer, uint32_t size) { - char * buffer = (char *) _buffer; - int sector_begin, sector_end; - uint32_t cl_size; - uint32_t offset_begin, offset_end; + int return_size = 0; + + while (1) { + char * buffer = (char *) _buffer; + int sector_begin, sector_end; + uint32_t cl_size; + uint32_t offset_begin, offset_end; - uint32_t first_sector_begins; + uint32_t first_sector_begins; uint32_t last_sector_ends; __mpqlib_errno = MPQLIB_ERROR_NO_ERROR; - /* Computing various cursors and stuff. */ - if ((size + mpq_f->cursor) >= mpq_f->file_size) - size = mpq_f->file_size - mpq_f->cursor; + /* Computing various cursors and stuff. */ + if ((size + mpq_f->cursor) >= mpq_f->file_size) + size = mpq_f->file_size - mpq_f->cursor; - offset_begin = mpq_f->cursor; - sector_begin = offset_begin / mpq_f->sector_size; - first_sector_begins = offset_begin % mpq_f->sector_size; - - offset_end = size + mpq_f->cursor; - sector_end = offset_end / mpq_f->sector_size; - last_sector_ends = offset_end % mpq_f->sector_size; - - if (!(offset_end % mpq_f->sector_size)) { - sector_end--; - last_sector_ends = mpq_f->sector_size; - } - - /* Let's ask for the first sector */ - if (!cache_sector(mpq_f, sector_begin)) { - __mpqlib_errno = MPQLIB_ERROR_COMPRESSION; - return 0; - } - - /* If we've hit the end sector, let's just copy that over and exit. */ - if (sector_begin == sector_end) { - memcpy(buffer, mpq_f->buffer + first_sector_begins, size); - mpq_f->cursor += size; - return size; + offset_begin = mpq_f->cursor; + sector_begin = offset_begin / mpq_f->sector_size; + first_sector_begins = offset_begin % mpq_f->sector_size; + + offset_end = size + mpq_f->cursor; + sector_end = offset_end / mpq_f->sector_size; + last_sector_ends = offset_end % mpq_f->sector_size; + + if (!(offset_end % mpq_f->sector_size)) { + sector_end--; + last_sector_ends = mpq_f->sector_size; + } + + /* Let's ask for the first sector */ + if (!cache_sector(mpq_f, sector_begin)) { + __mpqlib_errno = MPQLIB_ERROR_COMPRESSION; + return 0; + } + + /* If we've hit the end sector, let's just copy that over and exit. */ + if (sector_begin == sector_end) { + memcpy(buffer, mpq_f->buffer + first_sector_begins, size); + mpq_f->cursor += size; + return_size = size; + break; + } + + /* Else, let's compute the cluster size, copy that chunk, and reiterate. */ + cl_size = mpq_f->sector_size - first_sector_begins; + memcpy(buffer, mpq_f->buffer + first_sector_begins, cl_size); + mpq_f->cursor += cl_size; + + return_size += cl_size; + _buffer = buffer + cl_size; + size = size - cl_size; } - /* Else, let's compute the cluster size, copy that chunk, and recurse. */ - cl_size = mpq_f->sector_size - first_sector_begins; - memcpy(buffer, mpq_f->buffer + first_sector_begins, cl_size); - mpq_f->cursor += cl_size; - - return mpqlib_read(mpq_f, buffer + cl_size, size - cl_size) + cl_size; + return return_size; } uint32_t mpqlib_seek(struct mpq_file_t * mpq_f, int32_t offset, enum mpqlib_file_seek_t wheel) { |