summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luarest/lmtziplib.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luarest/lmtziplib.c')
-rw-r--r--source/luametatex/source/luarest/lmtziplib.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/source/luametatex/source/luarest/lmtziplib.c b/source/luametatex/source/luarest/lmtziplib.c
new file mode 100644
index 000000000..099f99830
--- /dev/null
+++ b/source/luametatex/source/luarest/lmtziplib.c
@@ -0,0 +1,206 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+# define ZLIB_CONST 1
+
+# include "luametatex.h"
+
+/*tex
+
+ This is a rather minimalistic interface to zlib. We can wrap around it and need some specific
+ file overhead anyway. Also, we never needed all that stream stuff.
+
+*/
+
+# define ziplib_in_char_ptr const unsigned char *
+# define ziplib_out_char_ptr unsigned char *
+
+# define ziplib_buffer_size 16*1024
+
+static int ziplib_aux_compress(
+ lua_State *L,
+ const char *data,
+ int size,
+ int level,
+ int method,
+ int window,
+ int memory,
+ int strategy,
+ int buffersize
+)
+{
+ int state;
+ z_stream zipstream;
+ zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */
+ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */
+ zipstream.next_out = Z_NULL;
+ zipstream.avail_out = 0;
+ zipstream.next_in = Z_NULL;
+ zipstream.avail_in = 0;
+ state = deflateInit2(&zipstream, level, method, window, memory, strategy);
+ if (state == Z_OK) {
+ luaL_Buffer buffer;
+ luaL_buffinit(L, &buffer);
+ zipstream.next_in = (ziplib_in_char_ptr) data;
+ zipstream.avail_in = size;
+ while (1) {
+ zipstream.next_out = (ziplib_out_char_ptr) luaL_prepbuffsize(&buffer, buffersize);
+ zipstream.avail_out = buffersize;
+ state = deflate(&zipstream, Z_FINISH);
+ if (state != Z_OK && state != Z_STREAM_END) {
+ lua_pushnil(L);
+ break;
+ } else {
+ luaL_addsize(&buffer, buffersize - zipstream.avail_out);
+ if (zipstream.avail_out != 0) {
+ luaL_pushresult(&buffer);
+ break;
+ }
+ }
+ }
+ deflateEnd(&zipstream);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int ziplib_compress(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ int size = (int) lua_rawlen(L, 1);
+ int level = lmt_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
+ int method = lmt_optinteger(L, 3, Z_DEFLATED);
+ int window = lmt_optinteger(L, 4, 15);
+ int memory = lmt_optinteger(L, 5, 8);
+ int strategy = lmt_optinteger(L, 6, Z_DEFAULT_STRATEGY);
+ return ziplib_aux_compress(L, data, size, level, method, window, memory, strategy, ziplib_buffer_size);
+}
+
+static int ziplib_compresssize(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ int size = (int) lua_rawlen(L, 1);
+ int level = lmt_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
+ int buffersize = lmt_optinteger(L, 3, ziplib_buffer_size);
+ int window = lmt_optinteger(L, 4, 15); /* like decompresssize */
+ return ziplib_aux_compress(L, data, size, level, Z_DEFLATED, window, 8, Z_DEFAULT_STRATEGY, buffersize);
+}
+
+static int ziplib_decompress(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ int size = (int) lua_rawlen(L, 1);
+ int window = lmt_optinteger(L, 2, 15);
+ int state;
+ z_stream zipstream;
+ zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */
+ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */
+ zipstream.next_out = Z_NULL;
+ zipstream.avail_out = 0;
+ zipstream.next_in = Z_NULL;
+ zipstream.avail_in = 0;
+ state = inflateInit2(&zipstream, window);
+ if (state == Z_OK) {
+ luaL_Buffer buffer;
+ luaL_buffinit(L, &buffer);
+ zipstream.next_in = (ziplib_in_char_ptr) data;
+ zipstream.avail_in = size;
+ while (1) {
+ zipstream.next_out = (ziplib_out_char_ptr) luaL_prepbuffsize(&buffer, ziplib_buffer_size);
+ zipstream.avail_out = ziplib_buffer_size;
+ state = inflate(&zipstream, Z_NO_FLUSH);
+ luaL_addsize(&buffer, ziplib_buffer_size - zipstream.avail_out);
+ if (state == Z_STREAM_END) {
+ luaL_pushresult(&buffer);
+ break;
+ } else if (state != Z_OK) {
+ lua_pushnil(L);
+ break;
+ } else if (zipstream.avail_out == 0) {
+ continue;
+ } else if (zipstream.avail_in == 0) {
+ luaL_pushresult(&buffer);
+ break;
+ }
+ }
+ inflateEnd(&zipstream);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int ziplib_decompresssize(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ int size = (int) lua_rawlen(L, 1);
+ int targetsize = lmt_tointeger(L, 2);
+ int window = lmt_optinteger(L, 3, 15);
+ int state;
+ z_stream zipstream;
+ zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */
+ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */
+ zipstream.next_out = Z_NULL;
+ zipstream.avail_out = 0;
+ zipstream.next_in = Z_NULL;
+ zipstream.avail_in = 0;
+ state = inflateInit2(&zipstream, window);
+ if (state == Z_OK) {
+ luaL_Buffer buffer;
+ zipstream.next_in = (ziplib_in_char_ptr) data;
+ zipstream.avail_in = size;
+ zipstream.next_out = (ziplib_out_char_ptr) luaL_buffinitsize(L, &buffer, (lua_Integer) targetsize + 100);
+ zipstream.avail_out = targetsize + 100;
+ state = inflate(&zipstream, Z_NO_FLUSH); /* maybe Z_FINISH buffer large enough */
+ if (state != Z_OK && state != Z_STREAM_END) {
+ lua_pushnil(L);
+ } else if (zipstream.avail_in == 0) {
+ luaL_pushresultsize(&buffer, targetsize);
+ } else {
+ lua_pushnil(L);
+ }
+ inflateEnd(&zipstream);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int ziplib_adler32(lua_State *L)
+{
+ int checksum = lmt_optinteger(L, 2, 0);
+ size_t buffersize = 0;
+ const char *buffer = lua_tolstring(L, 1, &buffersize);
+ checksum = adler32(checksum, (ziplib_in_char_ptr) buffer, (unsigned int) buffersize);
+ lua_pushinteger(L, checksum);
+ return 1;
+}
+
+static int ziplib_crc32(lua_State *L)
+{
+ int checksum = lmt_optinteger(L, 2, 0);
+ size_t buffersize = 0;
+ const char *buffer = lua_tolstring(L, 1, &buffersize);
+ checksum = crc32(checksum, (ziplib_in_char_ptr) buffer, (unsigned int) buffersize);
+ lua_pushinteger(L, checksum);
+ return 1;
+}
+
+static struct luaL_Reg ziplib_function_list[] = {
+ { "compress", ziplib_compress },
+ { "compresssize", ziplib_compresssize },
+ { "decompress", ziplib_decompress },
+ { "decompresssize", ziplib_decompresssize },
+ { "adler32", ziplib_adler32 },
+ { "crc32", ziplib_crc32 },
+ { NULL, NULL },
+};
+
+int luaopen_xzip(lua_State *L) {
+ lua_newtable(L);
+ luaL_setfuncs(L, ziplib_function_list, 0);
+ return 1;
+}
+