Skip to content

Commit

Permalink
add MiniZip Module
Browse files Browse the repository at this point in the history
  • Loading branch information
illlustr committed Feb 5, 2025
1 parent 868bd17 commit 1c26a14
Show file tree
Hide file tree
Showing 10 changed files with 575 additions and 0 deletions.
9 changes: 9 additions & 0 deletions modules/zip/SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python

Import('env')
Import('env_modules')

env_zip = env_modules.Clone()

# Module files
env_zip.add_source_files(env.modules_sources, "*.cpp")
14 changes: 14 additions & 0 deletions modules/zip/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
def can_build(env, platform):
return True

def configure(env):
pass

def get_doc_classes():
return [
"ZipReader",
"ZipPacker",
]

def get_doc_path():
return "doc_classes"
74 changes: 74 additions & 0 deletions modules/zip/doc_classes/ZIPPacker.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ZIPPacker" inherits="Reference" category="Core" version="3.2">
<brief_description>
Class for creating zip archives
</brief_description>
<description>
ZIPPacker provides a way to create zip archives.
</description>
<tutorials>
</tutorials>
<methods>
<method name="open">
<return type="int" enum="Error">
</return>
<argument index="0" name="path" type="String">
</argument>
<argument index="1" name="append" type="int" enum="ZIPPacker.ZipAppend" default="0">
</argument>
<description>
Opens a zip file to start writing. What happens if the file already exists is determined by [code]append[/code].
</description>
</method>
<method name="start_file">
<return type="int" enum="Error">
</return>
<argument index="0" name="path" type="String">
</argument>
<description>
Starts a new file in the zip archive. Subsequent calls to [method write_file] will write to this file.
If the file at the given path already exists, a duplicate entry will be created.
</description>
</method>
<method name="write_file">
<return type="int" enum="Error">
</return>
<argument index="0" name="data" type="PoolByteArray">
</argument>
<description>
Writes data to a file in the archive. Which file is written to is determined by the latest call to [method start_file].
If the file has already been written to, the data will be appended.
</description>
</method>
<method name="close_file">
<return type="int" enum="Error">
</return>
<description>
Closes the file that was opened with [method start_file].
</description>
</method>
<method name="close">
<return type="int" enum="Error">
</return>
<description>
Closes the zip file and flushes the data to the disk.
</description>
</method>
</methods>
<members>
</members>
<signals>
</signals>
<constants>
<constant name="APPEND_CREATE" value="0" enum="ZipAppend">
The file will be created if it does not exist, or overwritten if it does exist.
</constant>
<constant name="APPEND_CREATEAFTER" value="1" enum="ZipAppend">
The zip file will be appended to the data in the file, if the file already exists.
</constant>
<constant name="APPEND_ADDINZIP" value="2" enum="ZipAppend">
Files will be added to the existing zip file.
Note: Files in the archive cannot be overwritten in this mode. If you write to a file that already exists in the archive, a duplicate entry will be created instead.
</constant>
</constants>
</class>
55 changes: 55 additions & 0 deletions modules/zip/doc_classes/ZIPReader.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ZIPReader" inherits="Reference" category="Core" version="3.2">
<brief_description>
Class for reading zip archives
</brief_description>
<description>
ZIPReader provides a way to open zip archives and read the files inside.
</description>
<tutorials>
</tutorials>
<methods>
<method name="open">
<return type="int" enum="Error">
</return>
<argument index="0" name="path" type="String">
</argument>
<description>
Opens a zip file for reading. If a file was already open, it will be closed.
</description>
</method>
<method name="get_files">
<return type="PoolStringArray">
</return>
<description>
Returns the list of file paths in the archive. All paths are relative to the root of the archive.
For example, if you have an archive containg a folder, "foo", which contains a file, "bar.txt", the list will contain one item: "foo/bar.txt".
</description>
</method>
<method name="read_file">
<return type="PoolByteArray">
</return>
<argument index="0" name="path" type="String">
</argument>
<argument index="1" name="case_sensitive" type="bool" default="true">
</argument>
<description>
Returns the contents of a file in the archive as a [PoolByteArray]. If you need the contents as a string, use [method PoolByteArray.get_string_from_utf8].
If there is a problem reading the file (such as the file doesn't exist), an empty PoolByteArray will be returned and an error will be logged to the console.
</description>
</method>
<method name="close">
<return type="int" enum="Error">
</return>
<description>
Closes the file. Subsequent operations other than [method open] will fail after this is called.
</description>
</method>
</methods>
<members>
</members>
<signals>
</signals>
<constants>
</constants>
</class>
42 changes: 42 additions & 0 deletions modules/zip/register_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**************************************************************************/
/* register_types.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "register_types.h"

#include "zip_packer.h"
#include "zip_reader.h"

void register_zip_types() {
ClassDB::register_class<ZIPReader>();
ClassDB::register_class<ZIPPacker>();
}

void unregister_zip_types() {
}
32 changes: 32 additions & 0 deletions modules/zip/register_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**************************************************************************/
/* register_types.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

void register_zip_types();
void unregister_zip_types();
105 changes: 105 additions & 0 deletions modules/zip/zip_packer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/**************************************************************************/
/* zip_packer.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "core/io/zip_io.h"

#include "zip_packer.h"

Error ZIPPacker::open(String path, ZipAppend append) {
if (f) {
close();
}

zlib_filefunc_def io = zipio_create_io_from_file(&f);
zf = zipOpen2(path.utf8().get_data(), append, NULL, &io);
return zf != NULL ? OK : FAILED;
}

Error ZIPPacker::close() {
ERR_FAIL_COND_V_MSG(!f, FAILED, "ZIPPacker cannot be closed because it is not open.");

return zipClose(zf, NULL) == ZIP_OK ? OK : FAILED;
}

Error ZIPPacker::start_file(String path) {
ERR_FAIL_COND_V_MSG(!f, FAILED, "ZIPPacker must be opened before use.");

zip_fileinfo zipfi;

OS::Time time = OS::get_singleton()->get_time();
OS::Date date = OS::get_singleton()->get_date();

zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
zipfi.tmz_date.tm_min = time.min;
zipfi.tmz_date.tm_mon = date.month - 1;
zipfi.tmz_date.tm_sec = time.sec;
zipfi.tmz_date.tm_year = date.year;
zipfi.dosDate = 0;
zipfi.external_fa = 0;
zipfi.internal_fa = 0;

int ret = zipOpenNewFileInZip(zf, path.utf8().get_data(), &zipfi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
return ret == ZIP_OK ? OK : FAILED;
}

Error ZIPPacker::write_file(Vector<uint8_t> data) {
ERR_FAIL_COND_V_MSG(!f, FAILED, "ZIPPacker must be opened before use.");

return zipWriteInFileInZip(zf, data.ptr(), data.size()) == ZIP_OK ? OK : FAILED;
}

Error ZIPPacker::close_file() {
ERR_FAIL_COND_V_MSG(!f, FAILED, "ZIPPacker must be opened before use.");

return zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED;
}

void ZIPPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path", "append"), &ZIPPacker::open, DEFVAL(Variant(APPEND_CREATE)));
ClassDB::bind_method(D_METHOD("start_file", "path"), &ZIPPacker::start_file);
ClassDB::bind_method(D_METHOD("write_file", "data"), &ZIPPacker::write_file);
ClassDB::bind_method(D_METHOD("close_file"), &ZIPPacker::close_file);
ClassDB::bind_method(D_METHOD("close"), &ZIPPacker::close);

BIND_ENUM_CONSTANT(APPEND_CREATE);
BIND_ENUM_CONSTANT(APPEND_CREATEAFTER);
BIND_ENUM_CONSTANT(APPEND_ADDINZIP);
}

ZIPPacker::ZIPPacker() {
f = NULL;
}

ZIPPacker::~ZIPPacker() {
if (f) {
close();
}
}
Loading

0 comments on commit 1c26a14

Please sign in to comment.