summaryrefslogtreecommitdiffstats
path: root/core/io/zip_io.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/zip_io.cpp')
-rw-r--r--core/io/zip_io.cpp50
1 files changed, 46 insertions, 4 deletions
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index 7f60039578..a0e6bd62de 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -30,6 +30,48 @@
#include "zip_io.h"
+#include "core/templates/local_vector.h"
+
+int godot_unzip_get_current_file_info(unzFile p_zip_file, unz_file_info64 &r_file_info, String &r_filepath) {
+ const uLong short_file_path_buffer_size = 16384ul;
+ char short_file_path_buffer[short_file_path_buffer_size];
+
+ int err = unzGetCurrentFileInfo64(p_zip_file, &r_file_info, short_file_path_buffer, short_file_path_buffer_size, nullptr, 0, nullptr, 0);
+ if (unlikely((err != UNZ_OK) || (r_file_info.size_filename > short_file_path_buffer_size))) {
+ LocalVector<char> long_file_path_buffer;
+ long_file_path_buffer.resize(r_file_info.size_filename);
+
+ err = unzGetCurrentFileInfo64(p_zip_file, &r_file_info, long_file_path_buffer.ptr(), long_file_path_buffer.size(), nullptr, 0, nullptr, 0);
+ if (err != UNZ_OK) {
+ return err;
+ }
+ r_filepath = String::utf8(long_file_path_buffer.ptr(), r_file_info.size_filename);
+ } else {
+ r_filepath = String::utf8(short_file_path_buffer, r_file_info.size_filename);
+ }
+
+ return err;
+}
+
+int godot_unzip_locate_file(unzFile p_zip_file, String p_filepath, bool p_case_sensitive) {
+ int err = unzGoToFirstFile(p_zip_file);
+ while (err == UNZ_OK) {
+ unz_file_info64 current_file_info;
+ String current_filepath;
+ err = godot_unzip_get_current_file_info(p_zip_file, current_file_info, current_filepath);
+ if (err == UNZ_OK) {
+ bool filepaths_are_equal = p_case_sensitive ? (p_filepath == current_filepath) : (p_filepath.nocasecmp_to(current_filepath) == 0);
+ if (filepaths_are_equal) {
+ return UNZ_OK;
+ }
+ err = unzGoToNextFile(p_zip_file);
+ }
+ }
+ return err;
+}
+
+//
+
void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
ERR_FAIL_COND_V(fa == nullptr, nullptr);
@@ -38,17 +80,17 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
fname.parse_utf8(p_fname);
int file_access_mode = 0;
- if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
- file_access_mode |= FileAccess::WRITE;
- }
if (mode & ZLIB_FILEFUNC_MODE_READ) {
file_access_mode |= FileAccess::READ;
}
+ if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
+ file_access_mode |= FileAccess::WRITE;
+ }
if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
file_access_mode |= FileAccess::WRITE_READ;
}
- (*fa) = FileAccess::open(fname, file_access_mode);
+ (*fa) = FileAccess::open(fname, file_access_mode);
if (fa->is_null()) {
return nullptr;
}