diff --git a/doc/ru/scripting/builtins/libcompression.md b/doc/ru/scripting/builtins/libcompression.md new file mode 100644 index 00000000..276fbd29 --- /dev/null +++ b/doc/ru/scripting/builtins/libcompression.md @@ -0,0 +1,25 @@ +# Библиотека *compression* + +Библиотека функций для работы сжатия/разжатия массивов байт + +```lua +-- Сжимает массив байт. +compression.encode( + -- Массив байт + data: array of integers, + -- Алгоритм сжатия (поддерживается только gzip) + [опционально] algorithm="gzip", + -- Вернуть результат в table? + [опционально] usetable=false +) -> array of integers + +-- Разжимает массив байт. +compression.decode( + -- Массив байт + data: array of integers, + -- Алгоритм разжатия (поддерживается только gzip) + [опционально] algorithm="gzip", + -- Вернуть результат в table? + [опционально] usetable=false +) -> array of integers +``` \ No newline at end of file diff --git a/doc/ru/scripting/builtins/libfile.md b/doc/ru/scripting/builtins/libfile.md index e06e420c..4afbe23c 100644 --- a/doc/ru/scripting/builtins/libfile.md +++ b/doc/ru/scripting/builtins/libfile.md @@ -205,4 +205,4 @@ file.open_named_pipe(имя: str, режим: str) -> io_stream `/tmp/` или `\\\\.\\pipe\\` добавлять не нужно - движок делает это автоматически. -Доступные режимы такие же, как и в `file.open`, за исключением `+` \ No newline at end of file +Доступные режимы такие же, как и в `file.open`, за исключением `+` diff --git a/src/logic/scripting/lua/libs/api_lua.hpp b/src/logic/scripting/lua/libs/api_lua.hpp index 6c24d9d4..e304d6dc 100644 --- a/src/logic/scripting/lua/libs/api_lua.hpp +++ b/src/logic/scripting/lua/libs/api_lua.hpp @@ -43,6 +43,7 @@ extern const luaL_Reg playerlib[]; extern const luaL_Reg posteffectslib[]; // gfx.posteffects extern const luaL_Reg quatlib[]; extern const luaL_Reg randomlib[]; +extern const luaL_Reg compressionlib[]; extern const luaL_Reg text3dlib[]; // gfx.text3d extern const luaL_Reg timelib[]; extern const luaL_Reg tomllib[]; diff --git a/src/logic/scripting/lua/libs/libcompression.cpp b/src/logic/scripting/lua/libs/libcompression.cpp new file mode 100644 index 00000000..c212f42e --- /dev/null +++ b/src/logic/scripting/lua/libs/libcompression.cpp @@ -0,0 +1,84 @@ +#include "api_lua.hpp" +#include "coders/gzip.hpp" +#include "../lua_engine.hpp" + +static int l_encode(lua::State* L) { + char argc = lua::gettop(L); + std::vector compressedBytes; + + std::string algo = "gzip"; + if (argc >= 2) { + if (!lua::isstring(L, 2)) { + throw std::runtime_error("compression algorithm must be a string"); + } + algo = lua::require_lstring(L, 2); + } + + if (algo == "gzip") { + auto str = lua::bytearray_as_string(L, 1); + compressedBytes = gzip::compress( + reinterpret_cast(str.data()), + str.size() + ); + } else { + throw std::runtime_error("unsupported compression algorithm"); + } + + if (argc < 3 || !lua::toboolean(L, 3)) { + lua::create_bytearray(L, std::move(compressedBytes)); + } else { + size_t length = compressedBytes.size(); + lua::createtable(L, length, 0); + int newTable = lua::gettop(L); + for (size_t i = 0; i < length; i++) { + lua::pushinteger(L, compressedBytes.data()[i]); + lua::rawseti(L, i + 1, newTable); + } + } + + return 1; +} + +static int l_decode(lua::State* L) { + char argc = lua::gettop(L); + std::vector decompressedBytes; + + std::string algo = "gzip"; + if (argc >= 2) { + if (!lua::isstring(L, 2)) { + throw std::runtime_error("compression algorithm must be a string"); + } + algo = lua::require_lstring(L, 2); + } + + if (algo == "gzip") { + auto str = lua::bytearray_as_string(L, 1); + decompressedBytes = gzip::decompress( + reinterpret_cast(str.data()), + str.size() + ); + } else { + throw std::runtime_error("unsupported compression algorithm"); + } + + if (argc < 3 || !lua::toboolean(L, 3)) { + lua::create_bytearray(L, std::move(decompressedBytes)); + } else { + size_t length = decompressedBytes.size(); + lua::createtable(L, length, 0); + int newTable = lua::gettop(L); + for (size_t i = 0; i < length; i++) { + lua::pushinteger(L, decompressedBytes.data()[i]); + lua::rawseti(L, i + 1, newTable); + } + } + + return 1; +} + +const luaL_Reg compressionlib[] = { + {"encode", lua::wrap}, + {"decode", lua::wrap}, + {NULL, NULL} +}; + diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index f5cb2bfc..dae5e6d2 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -188,34 +188,6 @@ static int l_list(lua::State* L) { return 1; } -static int l_gzip_compress(lua::State* L) { - std::vector bytes; - - lua::read_bytes_from_table(L, 1, bytes); - auto compressed_bytes = gzip::compress(bytes.data(), bytes.size()); - int newTable = lua::gettop(L); - - for (size_t i = 0; i < compressed_bytes.size(); i++) { - lua::pushinteger(L, compressed_bytes.data()[i]); - lua::rawseti(L, i + 1, newTable); - } - return 1; -} - -static int l_gzip_decompress(lua::State* L) { - std::vector bytes; - - lua::read_bytes_from_table(L, 1, bytes); - auto decompressed_bytes = gzip::decompress(bytes.data(), bytes.size()); - int newTable = lua::gettop(L); - - for (size_t i = 0; i < decompressed_bytes.size(); i++) { - lua::pushinteger(L, decompressed_bytes.data()[i]); - lua::rawseti(L, i + 1, newTable); - } - return 1; -} - static int l_read_combined_list(lua::State* L) { std::string path = lua::require_string(L, 1); if (path.find(':') != std::string::npos) { @@ -419,8 +391,6 @@ const luaL_Reg filelib[] = { {"resolve", lua::wrap}, {"write_bytes", lua::wrap}, {"write", lua::wrap}, - {"gzip_compress", lua::wrap}, - {"gzip_decompress", lua::wrap}, {"read_combined_list", lua::wrap}, {"read_combined_object", lua::wrap}, {"is_writeable", lua::wrap}, @@ -436,3 +406,4 @@ const luaL_Reg filelib[] = { {"__close_all_descriptors", lua::wrap}, {NULL, NULL} }; + diff --git a/src/logic/scripting/lua/lua_engine.cpp b/src/logic/scripting/lua/lua_engine.cpp index 6ffa9057..665a9adf 100644 --- a/src/logic/scripting/lua/lua_engine.cpp +++ b/src/logic/scripting/lua/lua_engine.cpp @@ -52,6 +52,7 @@ static void create_libs(State* L, StateType stateType) { openlib(L, "pack", packlib); openlib(L, "quat", quatlib); openlib(L, "random", randomlib); + openlib(L, "compression", compressionlib); openlib(L, "toml", tomllib); openlib(L, "utf8", utf8lib); openlib(L, "vec2", vec2lib);