1
4
5# include <stdlib.h>
6
7# include "luametatex.h"
8# include "lmtoptional.h"
9
10
13
14typedef enum {
15 LZMA_RESERVED_ENUM = 0
16} lzma_reserved_enum;
17
18typedef enum {
19 LZMA_OK = 0,
20 LZMA_STREAM_END = 1,
21 LZMA_NO_CHECK = 2,
22 LZMA_UNSUPPORTED_CHECK = 3,
23 LZMA_GET_CHECK = 4,
24 LZMA_MEM_ERROR = 5,
25 LZMA_MEMLIMIT_ERROR = 6,
26 LZMA_FORMAT_ERROR = 7,
27 LZMA_OPTIONS_ERROR = 8,
28 LZMA_DATA_ERROR = 9,
29 LZMA_BUF_ERROR = 10,
30 LZMA_PROG_ERROR = 11,
31} lzma_ret;
32
33typedef enum {
34 LZMA_RUN = 0,
35 LZMA_SYNC_FLUSH = 1,
36 LZMA_FULL_FLUSH = 2,
37 LZMA_FULL_BARRIER = 4,
38 LZMA_FINISH = 3
39} lzma_action;
40
41typedef enum {
42 LZMA_CHECK_NONE = 0,
43 LZMA_CHECK_CRC32 = 1,
44 LZMA_CHECK_CRC64 = 4,
45 LZMA_CHECK_SHA256 = 10
46} lzma_check;
47
48typedef struct lzma_internal_s lzma_internal;
49
50typedef struct {
51 void *(*alloc)(void *opaque, size_t nmemb, size_t size);
52 void (*free )(void *opaque, void *ptr);
53 void *opaque;
54} lzma_allocator;
55
56typedef struct {
57 const uint8_t *next_in;
58 size_t avail_in;
59 uint64_t total_in;
60 uint8_t *next_out;
61 size_t avail_out;
62 uint64_t total_out;
63 const lzma_allocator *allocator;
64 lzma_internal *internal;
65 void *reserved_ptr1;
66 void *reserved_ptr2;
67 void *reserved_ptr3;
68 void *reserved_ptr4;
69 uint64_t reserved_int1;
70 uint64_t reserved_int2;
71 size_t reserved_int3;
72 size_t reserved_int4;
73 lzma_reserved_enum reserved_enum1;
74 lzma_reserved_enum reserved_enum2;
75} lzma_stream;
76
77
78# define LZMA_STREAM_INIT { NULL, 0, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
79
80# define LZMA_TELL_NO_CHECK UINT32_C(0x01)
81# define LZMA_TELL_UNSUPPORTED_CHECK UINT32_C(0x02)
82# define LZMA_TELL_ANY_CHECK UINT32_C(0x04)
83# define LZMA_CONCATENATED UINT32_C(0x08)
84
85typedef struct lzmalib_state_info {
86
87 int initialized;
88 int padding;
89
90 int (*lzma_auto_decoder) (lzma_stream *strm, uint64_t memlimit, uint32_t flags);
91 int (*lzma_easy_encoder) (lzma_stream *strm, uint32_t preset, lzma_check check);
92 int (*lzma_code) (lzma_stream *strm, lzma_action action);
93 int (*lzma_end) (lzma_stream *strm);
94
95} lzmalib_state_info;
96
97static lzmalib_state_info lzmalib_state = {
98
99 .initialized = 0,
100 .padding = 0,
101
102 .lzma_auto_decoder = NULL,
103 .lzma_easy_encoder = NULL,
104 .lzma_code = NULL,
105 .lzma_end = NULL,
106};
107
108
109# define lzma_default_level 6
110# define lzma_default_size 0xFFFF
111
112static int lzmalib_compress(lua_State *L)
113{
114 if (lzmalib_state.initialized) {
115 size_t sourcesize = 0;
116 const char *source = luaL_checklstring(L, 1, &sourcesize);
117 int level = lmt_optinteger(L, 2, lzma_default_level);
118 int targetsize = lmt_optinteger(L, 3, lzma_default_size);
119 if (level < 0 || level > 9) {
120 level = lzma_default_level;
121 }
122 if (source) {
123 lzma_stream strm = LZMA_STREAM_INIT;
124 int errorcode = lzmalib_state.lzma_easy_encoder(&strm, level, LZMA_CHECK_CRC64);
125 if (errorcode == LZMA_OK) {
126 luaL_Buffer buffer;
127 luaL_buffinit(L, &buffer);
128 strm.next_in = (const uint8_t *) source;
129 strm.avail_in = sourcesize;
130 if (targetsize < lzma_default_size) {
131 targetsize = lzma_default_size;
132 }
133 while (1) {
134 char *target = luaL_prepbuffsize(&buffer, targetsize);
135 size_t produced = strm.total_out;
136 strm.next_out = (uint8_t *) target;
137 strm.avail_out = targetsize;
138 errorcode = lzmalib_state.lzma_code(&strm, LZMA_FINISH);
139 produced = strm.total_out - produced;
140 luaL_addsize(&buffer, produced);
141 if (errorcode == LZMA_STREAM_END) {
142 lzmalib_state.lzma_end(&strm);
143 luaL_pushresult(&buffer);
144 return 1;
145 } else if (errorcode != LZMA_OK) {
146 lzmalib_state.lzma_end(&strm);
147 break;
148 }
149 }
150 }
151 }
152 }
153 lua_pushnil(L);
154 return 1;
155}
156
157static int lzmalib_decompress(lua_State *L)
158{
159 if (lzmalib_state.initialized) {
160 size_t sourcesize = 0;
161 const char *source = luaL_checklstring(L, 1, &sourcesize);
162 int targetsize = lmt_optinteger(L, 2, lzma_default_size);
163 if (source) {
164 lzma_stream strm = LZMA_STREAM_INIT;
165 int errorcode = lzmalib_state.lzma_auto_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
166 if (errorcode == LZMA_OK) {
167 luaL_Buffer buffer;
168 luaL_buffinit(L, &buffer);
169 strm.next_in = (const uint8_t *) source;
170 strm.avail_in = sourcesize;
171 if (targetsize < lzma_default_size) {
172 targetsize = lzma_default_size;
173 }
174 while (1) {
175 char *target = luaL_prepbuffsize(&buffer, targetsize);
176 size_t produced = strm.total_out;
177 strm.next_out = (uint8_t *) target;
178 strm.avail_out = targetsize;
179 errorcode = lzmalib_state.lzma_code(&strm, LZMA_RUN);
180 produced = strm.total_out - produced;
181 luaL_addsize(&buffer, produced);
182 if (errorcode == LZMA_STREAM_END || produced == 0) {
183 lzmalib_state.lzma_end(&strm);
184 luaL_pushresult(&buffer);
185 return 1;
186 } else if (errorcode != LZMA_OK) {
187 lzmalib_state.lzma_end(&strm);
188 break;
189 }
190 }
191 }
192 }
193 }
194 lua_pushnil(L);
195 return 1;
196}
197
198static int lzmalib_initialize(lua_State *L)
199{
200 if (! lzmalib_state.initialized) {
201 const char *filename = lua_tostring(L, 1);
202 if (filename) {
203
204 lmt_library lib = lmt_library_load(filename);
205
206 lzmalib_state.lzma_auto_decoder = lmt_library_find(lib, "lzma_auto_decoder");
207 lzmalib_state.lzma_easy_encoder = lmt_library_find(lib, "lzma_easy_encoder");
208 lzmalib_state.lzma_code = lmt_library_find(lib, "lzma_code");
209 lzmalib_state.lzma_end = lmt_library_find(lib, "lzma_end");
210
211 lzmalib_state.initialized = lmt_library_okay(lib);
212 }
213 }
214 lua_pushboolean(L, lzmalib_state.initialized);
215 return 1;
216}
217
218static struct luaL_Reg lzmalib_function_list[] = {
219 { "initialize", lzmalib_initialize },
220 { "compress", lzmalib_compress },
221 { "decompress", lzmalib_decompress },
222 { NULL, NULL },
223};
224
225int luaopen_lzma(lua_State * L)
226{
227 lmt_library_register(L, "lzma", lzmalib_function_list);
228 return 0;
229}
230 |