Przeglądaj źródła

Optimize `FileAccessCompressed::get_buffer` by using `memcpy`.

Lukas Tenbrink 5 miesięcy temu
rodzic
commit
b67e213b16
1 zmienionych plików z 34 dodań i 21 usunięć
  1. 34 21
      core/io/file_access_compressed.cpp

+ 34 - 21
core/io/file_access_compressed.cpp

@@ -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;