1
4
5# include <stdlib.h>
6
7# include "luametatex.h"
8# include "lmtoptional.h"
9
10# define LZ4F_VERSION 100
11
12typedef struct lz4lib_state_info {
13
14 int initialized;
15 int padding;
16
17 int (*LZ4_compressBound) (int inputSize);
18 int (*LZ4_compress_fast) (const char *src, char *dst, int srcSize, int dstCapacity, int acceleration);
19 int (*LZ4_decompress_safe) (const char *src, char *dst, int compressedSize, int dstCapacity);
20 size_t (*LZ4F_compressFrameBound) (size_t srcSize, void *);
21 size_t (*LZ4F_compressFrame) (void *dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, void *);
22 unsigned (*LZ4F_isError) (int code);
23 int (*LZ4F_createDecompressionContext) (void **dctxPtr, unsigned version);
24 int (*LZ4F_freeDecompressionContext) (void *dctx);
25 size_t (*LZ4F_decompress) (void *dctx, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, void *);
26
27} lz4lib_state_info;
28
29static lz4lib_state_info lz4lib_state = {
30
31 .initialized = 0,
32 .padding = 0,
33
34 .LZ4_compressBound = NULL,
35 .LZ4_compress_fast = NULL,
36 .LZ4_decompress_safe = NULL,
37 .LZ4F_compressFrameBound = NULL,
38 .LZ4F_compressFrame = NULL,
39 .LZ4F_isError = NULL,
40 .LZ4F_createDecompressionContext = NULL,
41 .LZ4F_freeDecompressionContext = NULL,
42 .LZ4F_decompress = NULL,
43
44};
45
46static int lz4lib_compress(lua_State *L)
47{
48 if (lz4lib_state.initialized) {
49 size_t sourcesize = 0;
50 const char *source = luaL_checklstring(L, 1, &sourcesize);
51 lua_Integer acceleration = luaL_optinteger(L, 2, 1);
52 size_t targetsize = lz4lib_state.LZ4_compressBound((int) sourcesize);
53 luaL_Buffer buffer;
54 char *target = luaL_buffinitsize(L, &buffer, targetsize);
55 int result = lz4lib_state.LZ4_compress_fast(source, target, (int) sourcesize, (int) targetsize, (int) acceleration);
56 if (result > 0) {
57 luaL_pushresultsize(&buffer, result);
58 } else {
59 lua_pushnil(L);
60 }
61 }
62 return 1;
63}
64
65
77
78static int lz4lib_decompresssize(lua_State *L)
79{
80 if (lz4lib_state.initialized) {
81 size_t sourcesize = 0;
82 size_t targetsize = luaL_checkinteger(L, 2);
83 const char *source = luaL_checklstring(L, 1, &sourcesize);
84 if (source && targetsize > 0) {
85 luaL_Buffer buffer;
86 char *target = luaL_buffinitsize(L, &buffer, targetsize);
87 int result = lz4lib_state.LZ4_decompress_safe(source, target, (int) sourcesize, (int) targetsize);
88 if (result > 0) {
89 luaL_pushresultsize(&buffer, result);
90 } else {
91 lua_pushnil(L);
92 }
93 } else {
94 lua_pushnil(L);
95 }
96 }
97 return 1;
98}
99
100static int lz4lib_framecompress(lua_State *L)
101{
102 if (lz4lib_state.initialized) {
103 size_t sourcesize = 0;
104 const char *source = luaL_checklstring(L, 1, &sourcesize);
105 luaL_Buffer buffer;
106 size_t targetsize = lz4lib_state.LZ4F_compressFrameBound(sourcesize, NULL);
107 char *target = luaL_buffinitsize(L, &buffer, targetsize);
108 size_t result = lz4lib_state.LZ4F_compressFrame(target, targetsize, source, sourcesize, NULL);
109 luaL_pushresultsize(&buffer, result);
110 }
111 return 1;
112}
113
114static int lz4lib_framedecompress(lua_State *L)
115{
116 if (lz4lib_state.initialized) {
117 size_t sourcesize = 0;
118 const char *source = luaL_checklstring(L, 1, &sourcesize);
119 if (source) {
120 void *context = NULL;
121 int errorcode = lz4lib_state.LZ4F_createDecompressionContext(&context, LZ4F_VERSION);
122 if (lz4lib_state.LZ4F_isError(errorcode)) {
123 lua_pushnil(L);
124 } else {
125 luaL_Buffer buffer;
126 luaL_buffinit(L, &buffer);
127 while (1) {
128 size_t targetsize = 0xFFFF;
129 char *target = luaL_prepbuffsize(&buffer, targetsize);
130 size_t consumed = sourcesize;
131 size_t errorcode = lz4lib_state.LZ4F_decompress(context, target, &targetsize, source, &consumed, NULL);
132 if (lz4lib_state.LZ4F_isError((int) errorcode)) {
133 lua_pushnil(L);
134 break;
135 } else if (targetsize == 0) {
136 luaL_pushresult(&buffer);
137 break;
138 } else {
139 luaL_addsize(&buffer, targetsize);
140 sourcesize -= consumed;
141 source += consumed;
142 }
143 }
144 }
145 if (context) {
146 lz4lib_state.LZ4F_freeDecompressionContext(context);
147 }
148 } else {
149 lua_pushnil(L);
150 }
151 }
152 return 1;
153}
154
155static int lz4lib_initialize(lua_State *L)
156{
157 if (! lz4lib_state.initialized) {
158 const char *filename = lua_tostring(L, 1);
159 if (filename) {
160
161 lmt_library lib = lmt_library_load(filename);
162
163 lz4lib_state.LZ4_compressBound = lmt_library_find(lib, "LZ4_compressBound");
164 lz4lib_state.LZ4_compress_fast = lmt_library_find(lib, "LZ4_compress_fast");
165 lz4lib_state.LZ4_decompress_safe = lmt_library_find(lib, "LZ4_decompress_safe");
166 lz4lib_state.LZ4F_compressFrameBound = lmt_library_find(lib, "LZ4F_compressFrameBound");
167 lz4lib_state.LZ4F_compressFrame = lmt_library_find(lib, "LZ4F_compressFrame");
168 lz4lib_state.LZ4F_isError = lmt_library_find(lib, "LZ4F_isError");
169 lz4lib_state.LZ4F_createDecompressionContext = lmt_library_find(lib, "LZ4F_createDecompressionContext");
170 lz4lib_state.LZ4F_freeDecompressionContext = lmt_library_find(lib, "LZ4F_freeDecompressionContext");
171 lz4lib_state.LZ4F_decompress = lmt_library_find(lib, "LZ4F_decompress");
172
173 lz4lib_state.initialized = lmt_library_okay(lib);
174 }
175 }
176 lua_pushboolean(L, lz4lib_state.initialized);
177 return 1;
178}
179
180static struct luaL_Reg lz4lib_function_list[] = {
181 { "initialize", lz4lib_initialize },
182 { "compress", lz4lib_compress },
183
184 { "decompresssize", lz4lib_decompresssize },
185 { "framecompress", lz4lib_framecompress },
186 { "framedecompress", lz4lib_framedecompress },
187 { NULL, NULL },
188};
189
190int luaopen_lz4(lua_State * L)
191{
192 lmt_library_register(L, "lz4", lz4lib_function_list);
193 return 0;
194}
195 |