summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luaoptional/lmtlz4.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luaoptional/lmtlz4.c')
-rw-r--r--source/luametatex/source/luaoptional/lmtlz4.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/source/luametatex/source/luaoptional/lmtlz4.c b/source/luametatex/source/luaoptional/lmtlz4.c
new file mode 100644
index 000000000..d54442635
--- /dev/null
+++ b/source/luametatex/source/luaoptional/lmtlz4.c
@@ -0,0 +1,193 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+# include <stdlib.h>
+
+# include "luametatex.h"
+
+# define LZ4F_VERSION 100 /* used to check for an incompatible API breaking change */
+
+typedef struct lz4lib_state_info {
+
+ int initialized;
+ int padding;
+
+ int (*LZ4_compressBound) (int inputSize);
+ int (*LZ4_compress_fast) (const char *src, char *dst, int srcSize, int dstCapacity, int acceleration);
+ int (*LZ4_decompress_safe) (const char *src, char *dst, int compressedSize, int dstCapacity);
+ size_t (*LZ4F_compressFrameBound) (size_t srcSize, void *);
+ size_t (*LZ4F_compressFrame) (void *dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, void *);
+ unsigned (*LZ4F_isError) (int code);
+ int (*LZ4F_createDecompressionContext) (void **dctxPtr, unsigned version);
+ int (*LZ4F_freeDecompressionContext) (void *dctx);
+ size_t (*LZ4F_decompress) (void *dctx, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, void *);
+
+} lz4lib_state_info;
+
+static lz4lib_state_info lz4lib_state = {
+
+ .initialized = 0,
+ .padding = 0,
+
+ .LZ4_compressBound = NULL,
+ .LZ4_compress_fast = NULL,
+ .LZ4_decompress_safe = NULL,
+ .LZ4F_compressFrameBound = NULL,
+ .LZ4F_compressFrame = NULL,
+ .LZ4F_isError = NULL,
+ .LZ4F_createDecompressionContext = NULL,
+ .LZ4F_freeDecompressionContext = NULL,
+ .LZ4F_decompress = NULL,
+
+};
+
+static int lz4lib_compress(lua_State *L)
+{
+ if (lz4lib_state.initialized) {
+ size_t sourcesize = 0;
+ const char *source = luaL_checklstring(L, 1, &sourcesize);
+ lua_Integer acceleration = luaL_optinteger(L, 2, 1);
+ size_t targetsize = lz4lib_state.LZ4_compressBound((int) sourcesize);
+ luaL_Buffer buffer;
+ char *target = luaL_buffinitsize(L, &buffer, targetsize);
+ int result = lz4lib_state.LZ4_compress_fast(source, target, (int) sourcesize, (int) targetsize, (int) acceleration);
+ if (result > 0) {
+ luaL_pushresultsize(&buffer, result);
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ return 1;
+}
+
+/*
+
+ There is no info about the target size so we don't provide a decompress function. Either use
+ the frame variant or save and restore the targetsize,
+
+ static int lz4lib_decompress(lua_State *L)
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+
+*/
+
+static int lz4lib_decompresssize(lua_State *L)
+{
+ if (lz4lib_state.initialized) {
+ size_t sourcesize = 0;
+ size_t targetsize = luaL_checkinteger(L, 2);
+ const char *source = luaL_checklstring(L, 1, &sourcesize);
+ if (source && targetsize > 0) {
+ luaL_Buffer buffer;
+ char *target = luaL_buffinitsize(L, &buffer, targetsize);
+ int result = lz4lib_state.LZ4_decompress_safe(source, target, (int) sourcesize, (int) targetsize);
+ if (result > 0) {
+ luaL_pushresultsize(&buffer, result);
+ } else {
+ lua_pushnil(L);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ return 1;
+}
+
+static int lz4lib_framecompress(lua_State *L)
+{
+ if (lz4lib_state.initialized) {
+ size_t sourcesize = 0;
+ const char *source = luaL_checklstring(L, 1, &sourcesize);
+ luaL_Buffer buffer;
+ size_t targetsize = lz4lib_state.LZ4F_compressFrameBound(sourcesize, NULL);
+ char *target = luaL_buffinitsize(L, &buffer, targetsize);
+ size_t result = lz4lib_state.LZ4F_compressFrame(target, targetsize, source, sourcesize, NULL);
+ luaL_pushresultsize(&buffer, result);
+ }
+ return 1;
+}
+
+static int lz4lib_framedecompress(lua_State *L)
+{
+ if (lz4lib_state.initialized) {
+ size_t sourcesize = 0;
+ const char *source = luaL_checklstring(L, 1, &sourcesize);
+ if (source) {
+ void *context = NULL;
+ int errorcode = lz4lib_state.LZ4F_createDecompressionContext(&context, LZ4F_VERSION);
+ if (lz4lib_state.LZ4F_isError(errorcode)) {
+ lua_pushnil(L);
+ } else {
+ luaL_Buffer buffer;
+ luaL_buffinit(L, &buffer);
+ while (1) {
+ size_t targetsize = 0xFFFF;
+ char *target = luaL_prepbuffsize(&buffer, targetsize);
+ size_t consumed = sourcesize;
+ size_t errorcode = lz4lib_state.LZ4F_decompress(context, target, &targetsize, source, &consumed, NULL);
+ if (lz4lib_state.LZ4F_isError((int) errorcode)) {
+ lua_pushnil(L);
+ break;
+ } else if (targetsize == 0) {
+ luaL_pushresult(&buffer);
+ break;
+ } else {
+ luaL_addsize(&buffer, targetsize);
+ sourcesize -= consumed;
+ source += consumed;
+ }
+ }
+ }
+ if (context) {
+ lz4lib_state.LZ4F_freeDecompressionContext(context);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ return 1;
+}
+
+static int lz4lib_initialize(lua_State *L)
+{
+ if (! lz4lib_state.initialized) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+
+ lmt_library lib = lmt_library_load(filename);
+
+ lz4lib_state.LZ4_compressBound = lmt_library_find(lib, "LZ4_compressBound");
+ lz4lib_state.LZ4_compress_fast = lmt_library_find(lib, "LZ4_compress_fast");
+ lz4lib_state.LZ4_decompress_safe = lmt_library_find(lib, "LZ4_decompress_safe");
+ lz4lib_state.LZ4F_compressFrameBound = lmt_library_find(lib, "LZ4F_compressFrameBound");
+ lz4lib_state.LZ4F_compressFrame = lmt_library_find(lib, "LZ4F_compressFrame");
+ lz4lib_state.LZ4F_isError = lmt_library_find(lib, "LZ4F_isError");
+ lz4lib_state.LZ4F_createDecompressionContext = lmt_library_find(lib, "LZ4F_createDecompressionContext");
+ lz4lib_state.LZ4F_freeDecompressionContext = lmt_library_find(lib, "LZ4F_freeDecompressionContext");
+ lz4lib_state.LZ4F_decompress = lmt_library_find(lib, "LZ4F_decompress");
+
+ lz4lib_state.initialized = lmt_library_okay(lib);
+ }
+ }
+ lua_pushboolean(L, lz4lib_state.initialized);
+ return 1;
+}
+
+static struct luaL_Reg lz4lib_function_list[] = {
+ { "initialize", lz4lib_initialize },
+ { "compress", lz4lib_compress },
+ /* { "decompress", lz4lib_decompress }, */
+ { "decompresssize", lz4lib_decompresssize },
+ { "framecompress", lz4lib_framecompress },
+ { "framedecompress", lz4lib_framedecompress },
+ { NULL, NULL },
+};
+
+int luaopen_lz4(lua_State * L)
+{
+ lmt_library_register(L, "lz4", lz4lib_function_list);
+ return 0;
+}