From 406ed5efac68af31c3cc7a0e7401ebf4dd419804 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Sun, 14 Sep 2014 17:42:08 -0400 Subject: [PATCH] Add compression API --- doc/lua_api.txt | 12 ++++++++++ src/script/lua_api/l_util.cpp | 41 +++++++++++++++++++++++++++++++++++ src/script/lua_api/l_util.h | 6 +++++ src/serialization.cpp | 9 ++++---- src/serialization.h | 4 ++-- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 37477b60a..805b63f6a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1763,6 +1763,18 @@ minetest.deserialize(string) -> table ^ Example: deserialize('return { ["foo"] = "bar" }') -> {foo='bar'} ^ Example: deserialize('print("foo")') -> nil (function call fails) ^ error:[string "print("foo")"]:1: attempt to call global 'print' (a nil value) +minetest.compress(data, method, ...) -> compressed_data +^ Compress a string of data. +^ `method` is a string identifying the compression method to be used. +^ Supported compression methods: +^ Deflate (zlib): "deflate" +^ `...` indicates method-specific arguments. Currently defined arguments are: +^ Deflate: `level` - Compression level, 0-9 or nil. +minetest.decompress(compressed_data, method, ...) -> data +^ Decompress a string of data (using ZLib). +^ See documentation on minetest.compress() for supported compression methods. +^ currently supported. +^ `...` indicates method-specific arguments. Currently, no methods use this. minetest.is_protected(pos, name) -> bool ^ This function should be overridden by protection mods and should be used to check if a player can interact at a position. diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 57db632c9..dda5b5abf 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_converter.h" #include "common/c_content.h" #include "cpp_api/s_async.h" +#include "serialization.h" #include "debug.h" #include "porting.h" #include "log.h" @@ -283,6 +284,40 @@ int ModApiUtil::l_get_builtin_path(lua_State *L) return 1; } +// compress(data, method, level) +int ModApiUtil::l_compress(lua_State *L) +{ + size_t size; + const char *data = luaL_checklstring(L, 1, &size); + + int level = -1; + if (!lua_isnone(L, 3) && !lua_isnil(L, 3)) + level = luaL_checknumber(L, 3); + + std::ostringstream os; + compressZlib(std::string(data, size), os, level); + + std::string out = os.str(); + + lua_pushlstring(L, out.data(), out.size()); + return 1; +} + +// decompress(data, method) +int ModApiUtil::l_decompress(lua_State *L) +{ + size_t size; + const char * data = luaL_checklstring(L, 1, &size); + + std::istringstream is(std::string(data, size)); + std::ostringstream os; + decompressZlib(is, os); + + std::string out = os.str(); + + lua_pushlstring(L, out.data(), out.size()); + return 1; +} void ModApiUtil::Initialize(lua_State *L, int top) { @@ -306,6 +341,9 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(is_yes); API_FCT(get_builtin_path); + + API_FCT(compress); + API_FCT(decompress); } void ModApiUtil::InitializeAsync(AsyncEngine& engine) @@ -325,5 +363,8 @@ void ModApiUtil::InitializeAsync(AsyncEngine& engine) ASYNC_API_FCT(is_yes); ASYNC_API_FCT(get_builtin_path); + + ASYNC_API_FCT(compress); + ASYNC_API_FCT(decompress); } diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index cfdeea1e8..e82432381 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -81,6 +81,12 @@ private: // get_scriptdir() static int l_get_builtin_path(lua_State *L); + // compress(data, method, ...) + static int l_compress(lua_State *L); + + // decompress(data, method, ...) + static int l_decompress(lua_State *L); + public: static void Initialize(lua_State *L, int top); diff --git a/src/serialization.cpp b/src/serialization.cpp index 118bad467..c0fbe10e2 100644 --- a/src/serialization.cpp +++ b/src/serialization.cpp @@ -53,7 +53,7 @@ void zerr(int ret) } } -void compressZlib(SharedBuffer data, std::ostream &os) +void compressZlib(SharedBuffer data, std::ostream &os, int level) { z_stream z; const s32 bufsize = 16384; @@ -65,7 +65,7 @@ void compressZlib(SharedBuffer data, std::ostream &os) z.zfree = Z_NULL; z.opaque = Z_NULL; - ret = deflateInit(&z, -1); + ret = deflateInit(&z, level); if(ret != Z_OK) throw SerializationError("compressZlib: deflateInit failed"); @@ -94,13 +94,12 @@ void compressZlib(SharedBuffer data, std::ostream &os) } deflateEnd(&z); - } -void compressZlib(const std::string &data, std::ostream &os) +void compressZlib(const std::string &data, std::ostream &os, int level) { SharedBuffer databuf((u8*)data.c_str(), data.size()); - compressZlib(databuf, os); + compressZlib(databuf, os, level); } void decompressZlib(std::istream &is, std::ostream &os) diff --git a/src/serialization.h b/src/serialization.h index 86da31486..41a505455 100644 --- a/src/serialization.h +++ b/src/serialization.h @@ -78,8 +78,8 @@ with this program; if not, write to the Free Software Foundation, Inc., Misc. serialization functions */ -void compressZlib(SharedBuffer data, std::ostream &os); -void compressZlib(const std::string &data, std::ostream &os); +void compressZlib(SharedBuffer data, std::ostream &os, int level = -1); +void compressZlib(const std::string &data, std::ostream &os, int level = -1); void decompressZlib(std::istream &is, std::ostream &os); // These choose between zlib and a self-made one according to version