|
@@ -247,7 +247,11 @@ bool FileAccessCompressed::eof_reached() const {
|
|
|
}
|
|
|
|
|
|
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
|
|
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
|
|
+ if (p_length == 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ERR_FAIL_NULL_V(p_dst, -1);
|
|
|
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
|
|
|
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
|
|
|
|
|
@@ -256,29 +260,38 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- for (uint64_t i = 0; i < p_length; i++) {
|
|
|
- p_dst[i] = read_ptr[read_pos];
|
|
|
- read_pos++;
|
|
|
- if (read_pos >= read_block_size) {
|
|
|
- read_block++;
|
|
|
+ uint64_t dst_idx = 0;
|
|
|
+ while (true) {
|
|
|
+ // Copy over as much of our current block as possible.
|
|
|
+ const uint32_t copied_bytes_count = MIN(p_length - dst_idx, read_block_size - read_pos);
|
|
|
+ memcpy(p_dst + dst_idx, read_ptr + read_pos, copied_bytes_count);
|
|
|
+ dst_idx += copied_bytes_count;
|
|
|
+ read_pos += copied_bytes_count;
|
|
|
+
|
|
|
+ if (dst_idx == p_length) {
|
|
|
+ // We're done! We read back all that was requested.
|
|
|
+ return p_length;
|
|
|
+ }
|
|
|
|
|
|
- if (read_block < read_block_count) {
|
|
|
- //read another block of compressed data
|
|
|
- f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
|
|
- int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
|
|
- ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt.");
|
|
|
- read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
|
|
- read_pos = 0;
|
|
|
-
|
|
|
- } else {
|
|
|
- read_block--;
|
|
|
- at_end = true;
|
|
|
- if (i + 1 < p_length) {
|
|
|
- read_eof = true;
|
|
|
- }
|
|
|
- return i + 1;
|
|
|
+ // We're not done yet; try reading the next block.
|
|
|
+ read_block++;
|
|
|
+
|
|
|
+ if (read_block >= read_block_count) {
|
|
|
+ // We're done! We read back the whole file.
|
|
|
+ read_block--;
|
|
|
+ at_end = true;
|
|
|
+ if (dst_idx + 1 < p_length) {
|
|
|
+ read_eof = true;
|
|
|
}
|
|
|
+ return dst_idx + 1;
|
|
|
}
|
|
|
+
|
|
|
+ // Read the next block of compressed data.
|
|
|
+ f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
|
|
+ int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
|
|
+ ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt.");
|
|
|
+ read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
|
|
+ read_pos = 0;
|
|
|
}
|
|
|
|
|
|
return p_length;
|