diff options
Diffstat (limited to 'vendor/lua-zlib')
-rw-r--r-- | vendor/lua-zlib/.gitattributes | 1 | ||||
-rw-r--r-- | vendor/lua-zlib/README | 163 | ||||
-rw-r--r-- | vendor/lua-zlib/lua-zlib-1.1-0.rockspec | 42 | ||||
-rw-r--r-- | vendor/lua-zlib/lua_zlib.c | 1295 |
4 files changed, 1501 insertions, 0 deletions
diff --git a/vendor/lua-zlib/.gitattributes b/vendor/lua-zlib/.gitattributes new file mode 100644 index 00000000..54be6288 --- /dev/null +++ b/vendor/lua-zlib/.gitattributes | |||
@@ -0,0 +1 @@ | |||
lua_zlib.c export-subst ident | |||
diff --git a/vendor/lua-zlib/README b/vendor/lua-zlib/README new file mode 100644 index 00000000..c438ee05 --- /dev/null +++ b/vendor/lua-zlib/README | |||
@@ -0,0 +1,163 @@ | |||
1 | ********************************************************************** | ||
2 | * Author : Brian Maher <maherb at brimworks dot com> | ||
3 | * Library : lua_zlib - Lua 5.1 interface to zlib | ||
4 | * | ||
5 | * The MIT License | ||
6 | * | ||
7 | * Copyright (c) 2009 Brian Maher | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
10 | * of this software and associated documentation files (the "Software"), to deal | ||
11 | * in the Software without restriction, including without limitation the rights | ||
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
13 | * copies of the Software, and to permit persons to whom the Software is | ||
14 | * furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice shall be included in | ||
17 | * all copies or substantial portions of the Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
25 | * THE SOFTWARE. | ||
26 | ********************************************************************** | ||
27 | |||
28 | To use this library, you need zlib, get it here: | ||
29 | http://www.gzip.org/zlib/ | ||
30 | |||
31 | To build this library, you can use CMake and get it here: | ||
32 | http://www.cmake.org/cmake/resources/software.html | ||
33 | |||
34 | ...or you can use GNU Make. | ||
35 | make <platform> | ||
36 | |||
37 | Loading the library: | ||
38 | |||
39 | If you built the library as a loadable package | ||
40 | [local] zlib = require 'zlib' | ||
41 | |||
42 | If you compiled the package statically into your application, call | ||
43 | the function "luaopen_zlib(L)". It will create a table with the zlib | ||
44 | functions and leave it on the stack. | ||
45 | |||
46 | -- zlib functions -- | ||
47 | |||
48 | int major, int minor, int patch = zlib.version() | ||
49 | |||
50 | returns numeric zlib version for the major, minor, and patch | ||
51 | levels of the version dynamically linked in. | ||
52 | |||
53 | function stream = zlib.deflate([ int compression_level ], [ int window_size ]) | ||
54 | |||
55 | If no compression_level is provided uses Z_DEFAULT_COMPRESSION (6), | ||
56 | compression level is a number from 1-9 where zlib.BEST_SPEED is 1 | ||
57 | and zlib.BEST_COMPRESSION is 9. | ||
58 | |||
59 | Returns a "stream" function that compresses (or deflates) all | ||
60 | strings passed in. Specifically, use it as such: | ||
61 | |||
62 | string deflated, bool eof, int bytes_in, int bytes_out = | ||
63 | stream(string input [, 'sync' | 'full' | 'finish']) | ||
64 | |||
65 | Takes input and deflates and returns a portion of it, | ||
66 | optionally forcing a flush. | ||
67 | |||
68 | A 'sync' flush will force all pending output to be flushed to | ||
69 | the return value and the output is aligned on a byte boundary, | ||
70 | so that the decompressor can get all input data available so | ||
71 | far. Flushing may degrade compression for some compression | ||
72 | algorithms and so it should be used only when necessary. | ||
73 | |||
74 | A 'full' flush will flush all output as with 'sync', and the | ||
75 | compression state is reset so that decompression can restart | ||
76 | from this point if previous compressed data has been damaged | ||
77 | or if random access is desired. Using Z_FULL_FLUSH too often | ||
78 | can seriously degrade the compression. | ||
79 | |||
80 | A 'finish' flush will force all pending output to be processed | ||
81 | and results in the stream become unusable. Any future | ||
82 | attempts to print anything other than the empty string will | ||
83 | result in an error that begins with IllegalState. | ||
84 | |||
85 | The eof result is true if 'finish' was specified, otherwise | ||
86 | it is false. | ||
87 | |||
88 | The bytes_in is how many bytes of input have been passed to | ||
89 | stream, and bytes_out is the number of bytes returned in | ||
90 | deflated string chunks. | ||
91 | |||
92 | function stream = zlib.inflate([int windowBits]) | ||
93 | |||
94 | Returns a "stream" function that decompresses (or inflates) all | ||
95 | strings passed in. Optionally specify a windowBits argument | ||
96 | that is passed to inflateInit2(), see zlib.h for details about | ||
97 | this argument. By default, gzip header detection is done, and | ||
98 | the max window size is used. | ||
99 | |||
100 | The "stream" function should be used as such: | ||
101 | |||
102 | string inflated, bool eof, int bytes_in, int bytes_out = | ||
103 | stream(string input) | ||
104 | |||
105 | Takes input and inflates and returns a portion of it. If it | ||
106 | detects the end of a deflation stream, then total will be the | ||
107 | total number of bytes read from input and all future calls to | ||
108 | stream() with a non empty string will result in an error that | ||
109 | begins with IllegalState. | ||
110 | |||
111 | No flush options are provided since the maximal amount of | ||
112 | input is always processed. | ||
113 | |||
114 | eof will be true when the input string is determined to be at | ||
115 | the "end of the file". | ||
116 | |||
117 | The bytes_in is how many bytes of input have been passed to | ||
118 | stream, and bytes_out is the number of bytes returned in | ||
119 | inflated string chunks. | ||
120 | |||
121 | |||
122 | function compute_checksum = zlib.adler32() | ||
123 | function compute_checksum = zlib.crc32() | ||
124 | |||
125 | Create a new checksum computation function using either the | ||
126 | adler32 or crc32 algorithms. This resulting function should be | ||
127 | used as such: | ||
128 | |||
129 | int checksum = compute_checksum(string input | | ||
130 | function compute_checksum) | ||
131 | |||
132 | The compute_checksum function takes as input either a string | ||
133 | that is logically getting appended to or another | ||
134 | compute_checksum function that is logically getting appended. | ||
135 | The result is the updated checksum. | ||
136 | |||
137 | For example, these uses will all result in the same checksum: | ||
138 | |||
139 | -- All in one call: | ||
140 | local csum = zlib.crc32()("one two") | ||
141 | |||
142 | -- Multiple calls: | ||
143 | local compute = zlib.crc32() | ||
144 | compute("one") | ||
145 | assert(csum == compute(" two")) | ||
146 | |||
147 | -- Multiple compute_checksums joined: | ||
148 | local compute1, compute2 = zlib.crc32(), zlib.crc32() | ||
149 | compute1("one") | ||
150 | compute2(" two") | ||
151 | assert(csum == compute1(compute2)) | ||
152 | |||
153 | NOTE: This library ships with an "lzlib" compatibility shim. However, the | ||
154 | following things are not compatible: | ||
155 | |||
156 | * zlib.version() in lzlib returns a string, but this library returns a | ||
157 | numeric tuple (see above). | ||
158 | |||
159 | * zlib.{adler,crc}32() in lzlib returns the {adler,crc}32 initial value, | ||
160 | however if this value is used with calls to adler32 it works in | ||
161 | compatibility mode. | ||
162 | |||
163 | To use this shim add the -DLZLIB_COMPAT compiler flag. \ No newline at end of file | ||
diff --git a/vendor/lua-zlib/lua-zlib-1.1-0.rockspec b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec new file mode 100644 index 00000000..7927d6ce --- /dev/null +++ b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec | |||
@@ -0,0 +1,42 @@ | |||
1 | package = "lua-zlib" | ||
2 | version = "1.2-0" | ||
3 | source = { | ||
4 | url = "git://github.com/brimworks/lua-zlib.git", | ||
5 | tag = "v1.2", | ||
6 | } | ||
7 | description = { | ||
8 | summary = "Simple streaming interface to zlib for Lua.", | ||
9 | detailed = [[ | ||
10 | Simple streaming interface to zlib for Lua. | ||
11 | Consists of two functions: inflate and deflate. | ||
12 | Both functions return "stream functions" (takes a buffer of input and returns a buffer of output). | ||
13 | This project is hosted on github. | ||
14 | ]], | ||
15 | homepage = "https://github.com/brimworks/lua-zlib", | ||
16 | license = "MIT" | ||
17 | } | ||
18 | dependencies = { | ||
19 | "lua >= 5.1, <= 5.3" | ||
20 | } | ||
21 | external_dependencies = { | ||
22 | ZLIB = { | ||
23 | header = "zlib.h" | ||
24 | } | ||
25 | } | ||
26 | |||
27 | build = { | ||
28 | type = "builtin", | ||
29 | modules = { | ||
30 | zlib = { | ||
31 | sources = { "lua_zlib.c" }, | ||
32 | libraries = { "z" }, | ||
33 | defines = { "LZLIB_COMPAT" }, | ||
34 | incdirs = { "$(ZLIB_INCDIR)" }, | ||
35 | } | ||
36 | }, | ||
37 | platforms = { | ||
38 | windows = { modules = { zlib = { libraries = { | ||
39 | "$(ZLIB_LIBDIR)/zlib" -- Must full path to `"zlib"`, or else will cause the `LINK : fatal error LNK1149` | ||
40 | } } } } | ||
41 | } | ||
42 | } | ||
diff --git a/vendor/lua-zlib/lua_zlib.c b/vendor/lua-zlib/lua_zlib.c new file mode 100644 index 00000000..da57e91a --- /dev/null +++ b/vendor/lua-zlib/lua_zlib.c | |||
@@ -0,0 +1,1295 @@ | |||
1 | #include <ctype.h> | ||
2 | #include <lauxlib.h> | ||
3 | #include <lua.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <zlib.h> | ||
7 | |||
8 | /* | ||
9 | * ** compatibility with Lua 5.2 | ||
10 | * */ | ||
11 | #if (LUA_VERSION_NUM >= 502) | ||
12 | #undef luaL_register | ||
13 | #define luaL_register(L,n,f) \ | ||
14 | { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); } | ||
15 | |||
16 | #endif | ||
17 | |||
18 | #if (LUA_VERSION_NUM >= 503) | ||
19 | #undef luaL_optint | ||
20 | #define luaL_optint(L,n,d) ((int)luaL_optinteger(L,(n),(d))) | ||
21 | #endif | ||
22 | |||
23 | #ifdef LZLIB_COMPAT | ||
24 | /**************** lzlib compatibilty **********************************/ | ||
25 | /* Taken from https://raw.githubusercontent.com/LuaDist/lzlib/93b88e931ffa7cd0a52a972b6b26d37628f479f3/lzlib.c */ | ||
26 | |||
27 | /************************************************************************ | ||
28 | * Author : Tiago Dionizio <tiago.dionizio@gmail.com> * | ||
29 | * Library : lzlib - Lua 5 interface to access zlib library functions * | ||
30 | * * | ||
31 | * Permission is hereby granted, free of charge, to any person obtaining * | ||
32 | * a copy of this software and associated documentation files (the * | ||
33 | * "Software"), to deal in the Software without restriction, including * | ||
34 | * without limitation the rights to use, copy, modify, merge, publish, * | ||
35 | * distribute, sublicense, and/or sell copies of the Software, and to * | ||
36 | * permit persons to whom the Software is furnished to do so, subject to * | ||
37 | * the following conditions: * | ||
38 | * * | ||
39 | * The above copyright notice and this permission notice shall be * | ||
40 | * included in all copies or substantial portions of the Software. * | ||
41 | * * | ||
42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * | ||
43 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * | ||
44 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* | ||
45 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * | ||
46 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * | ||
47 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * | ||
48 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * | ||
49 | ************************************************************************/ | ||
50 | |||
51 | |||
52 | /* | ||
53 | ** ========================================================================= | ||
54 | ** compile time options wich determine available functionality | ||
55 | ** ========================================================================= | ||
56 | */ | ||
57 | |||
58 | /* TODO | ||
59 | |||
60 | - also call flush on table/userdata when flush function is detected | ||
61 | - remove io_cb check inflate_block if condition | ||
62 | - only set eos when ZSTREAM_END is reached | ||
63 | - check for stream errors to close stream when really needed | ||
64 | |||
65 | */ | ||
66 | |||
67 | |||
68 | /* | ||
69 | ** ========================================================================= | ||
70 | ** zlib stream metamethods | ||
71 | ** ========================================================================= | ||
72 | */ | ||
73 | #define ZSTREAMMETA "zlib:zstream" | ||
74 | |||
75 | #define LZ_ANY -1 | ||
76 | #define LZ_NONE 0 | ||
77 | #define LZ_DEFLATE 1 | ||
78 | #define LZ_INFLATE 2 | ||
79 | |||
80 | #if 0 | ||
81 | #define LZ_BUFFER_SIZE LUAL_BUFFERSIZE | ||
82 | #else | ||
83 | #define LZ_BUFFER_SIZE 8192 | ||
84 | #endif | ||
85 | |||
86 | typedef struct { | ||
87 | /* zlib structures */ | ||
88 | z_stream zstream; | ||
89 | /* stream state. LZ_DEFLATE | LZ_INFLATE */ | ||
90 | int state; | ||
91 | int error; | ||
92 | int peek; | ||
93 | int eos; | ||
94 | /* user callback source for reading/writing */ | ||
95 | int io_cb; | ||
96 | /* input buffer */ | ||
97 | int i_buffer_ref; | ||
98 | size_t i_buffer_pos; | ||
99 | size_t i_buffer_len; | ||
100 | const char *i_buffer; | ||
101 | /* output buffer */ | ||
102 | size_t o_buffer_len; | ||
103 | size_t o_buffer_max; | ||
104 | char o_buffer[LZ_BUFFER_SIZE]; | ||
105 | /* dictionary */ | ||
106 | const Bytef *dictionary; | ||
107 | size_t dictionary_len; | ||
108 | } lz_stream; | ||
109 | |||
110 | |||
111 | /* forward declarations */ | ||
112 | static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush); | ||
113 | |||
114 | |||
115 | static lz_stream *lzstream_new(lua_State *L, int src) { | ||
116 | lz_stream *s = (lz_stream*)lua_newuserdata(L, sizeof(lz_stream)); | ||
117 | |||
118 | luaL_getmetatable(L, ZSTREAMMETA); | ||
119 | lua_setmetatable(L, -2); /* set metatable */ | ||
120 | |||
121 | s->state = LZ_NONE; | ||
122 | s->error = Z_OK; | ||
123 | s->eos = 0; | ||
124 | s->io_cb = LUA_REFNIL; | ||
125 | |||
126 | s->i_buffer = NULL; | ||
127 | s->i_buffer_ref = LUA_REFNIL; | ||
128 | s->i_buffer_pos = 0; | ||
129 | s->i_buffer_len = 0; | ||
130 | |||
131 | s->peek = 0; | ||
132 | s->o_buffer_len = 0; | ||
133 | s->o_buffer_max = sizeof(s->o_buffer) / sizeof(s->o_buffer[0]); | ||
134 | |||
135 | s->zstream.zalloc = Z_NULL; | ||
136 | s->zstream.zfree = Z_NULL; | ||
137 | |||
138 | /* prepare source */ | ||
139 | if (lua_isstring(L, src)) { | ||
140 | lua_pushvalue(L, src); | ||
141 | s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
142 | s->i_buffer = lua_tolstring(L, src, &s->i_buffer_len); | ||
143 | } else { | ||
144 | /* table | function | userdata */ | ||
145 | lua_pushvalue(L, src); | ||
146 | s->io_cb = luaL_ref(L, LUA_REGISTRYINDEX); | ||
147 | } | ||
148 | return s; | ||
149 | } | ||
150 | |||
151 | static void lzstream_cleanup(lua_State *L, lz_stream *s) { | ||
152 | if (s && s->state != LZ_NONE) { | ||
153 | if (s->state == LZ_INFLATE) { | ||
154 | inflateEnd(&s->zstream); | ||
155 | } | ||
156 | if (s->state == LZ_DEFLATE) { | ||
157 | deflateEnd(&s->zstream); | ||
158 | } | ||
159 | |||
160 | luaL_unref(L, LUA_REGISTRYINDEX, s->io_cb); | ||
161 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
162 | s->state = LZ_NONE; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /* ====================================================================== */ | ||
167 | |||
168 | static lz_stream *lzstream_get(lua_State *L, int index) { | ||
169 | lz_stream *s = (lz_stream*)luaL_checkudata(L, index, ZSTREAMMETA); | ||
170 | if (s == NULL) luaL_argerror(L, index, "bad zlib stream"); | ||
171 | return s; | ||
172 | } | ||
173 | |||
174 | static lz_stream *lzstream_check(lua_State *L, int index, int state) { | ||
175 | lz_stream *s = lzstream_get(L, index); | ||
176 | if ((state != LZ_ANY && s->state != state) || s->state == LZ_NONE) { | ||
177 | luaL_argerror(L, index, "attempt to use invalid zlib stream"); | ||
178 | } | ||
179 | return s; | ||
180 | } | ||
181 | |||
182 | /* ====================================================================== */ | ||
183 | |||
184 | static int lzstream_tostring(lua_State *L) { | ||
185 | lz_stream *s = (lz_stream*)luaL_checkudata(L, 1, ZSTREAMMETA); | ||
186 | if (s == NULL) luaL_argerror(L, 1, "bad zlib stream"); | ||
187 | |||
188 | if (s->state == LZ_NONE) { | ||
189 | lua_pushstring(L, "zlib stream (closed)"); | ||
190 | } else if (s->state == LZ_DEFLATE) { | ||
191 | lua_pushfstring(L, "zlib deflate stream (%p)", (void*)s); | ||
192 | } else if (s->state == LZ_INFLATE) { | ||
193 | lua_pushfstring(L, "zlib inflate stream (%p)", (void*)s); | ||
194 | } else { | ||
195 | lua_pushfstring(L, "%p", (void*)s); | ||
196 | } | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | |||
201 | /* ====================================================================== */ | ||
202 | |||
203 | static int lzstream_gc(lua_State *L) { | ||
204 | lz_stream *s = lzstream_get(L, 1); | ||
205 | lzstream_cleanup(L, s); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* ====================================================================== */ | ||
210 | |||
211 | static int lzstream_close(lua_State *L) { | ||
212 | lz_stream *s = lzstream_get(L, 1); | ||
213 | |||
214 | if (s->state == LZ_DEFLATE) { | ||
215 | lua_settop(L, 0); | ||
216 | lua_pushliteral(L, ""); | ||
217 | return lzstream_docompress(L, s, 1, 1, Z_FINISH); | ||
218 | } | ||
219 | |||
220 | lzstream_cleanup(L, s); | ||
221 | lua_pushboolean(L, 1); | ||
222 | return 1; | ||
223 | } | ||
224 | |||
225 | /* ====================================================================== */ | ||
226 | |||
227 | static int lzstream_adler(lua_State *L) { | ||
228 | lz_stream *s = lzstream_check(L, 1, LZ_ANY); | ||
229 | lua_pushnumber(L, s->zstream.adler); | ||
230 | return 1; | ||
231 | } | ||
232 | |||
233 | /* ====================================================================== */ | ||
234 | |||
235 | /* | ||
236 | zlib.deflate( | ||
237 | sink: function | { write: function [, close: function, flush: function] }, | ||
238 | compression level, [Z_DEFAILT_COMPRESSION] | ||
239 | method, [Z_DEFLATED] | ||
240 | windowBits, [15] | ||
241 | memLevel, [8] | ||
242 | strategy, [Z_DEFAULT_STRATEGY] | ||
243 | dictionary: [""] | ||
244 | ) | ||
245 | */ | ||
246 | static int lzlib_deflate(lua_State *L) { | ||
247 | int level, method, windowBits, memLevel, strategy; | ||
248 | lz_stream *s; | ||
249 | const char *dictionary; | ||
250 | size_t dictionary_len; | ||
251 | |||
252 | if (lua_istable(L, 1) || lua_isuserdata(L, 1)) { | ||
253 | /* is there a :write function? */ | ||
254 | lua_getfield(L, 1, "write"); | ||
255 | if (!lua_isfunction(L, -1)) { | ||
256 | luaL_argerror(L, 1, "output parameter does not provide :write function"); | ||
257 | } | ||
258 | lua_pop(L, 1); | ||
259 | } | ||
260 | else if (!lua_isfunction(L, 1)) { | ||
261 | luaL_argerror(L, 1, "output parameter must be a function, table or userdata value"); | ||
262 | } | ||
263 | |||
264 | level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION); | ||
265 | method = (int) luaL_optinteger(L, 3, Z_DEFLATED); | ||
266 | windowBits = (int) luaL_optinteger(L, 4, 15); | ||
267 | memLevel = (int) luaL_optinteger(L, 5, 8); | ||
268 | strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY); | ||
269 | dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len); | ||
270 | |||
271 | s = lzstream_new(L, 1); | ||
272 | |||
273 | if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) { | ||
274 | lua_pushliteral(L, "call to deflateInit2 failed"); | ||
275 | lua_error(L); | ||
276 | } | ||
277 | |||
278 | if (dictionary) { | ||
279 | if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) { | ||
280 | lua_pushliteral(L, "call to deflateSetDictionnary failed"); | ||
281 | lua_error(L); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | s->state = LZ_DEFLATE; | ||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | zlib.inflate( | ||
291 | source: string | function | { read: function, close: function }, | ||
292 | windowBits: number, [15] | ||
293 | dictionary: [""] | ||
294 | ) | ||
295 | */ | ||
296 | static int lzlib_inflate(lua_State *L) | ||
297 | { | ||
298 | int windowBits; | ||
299 | lz_stream *s; | ||
300 | int have_peek = 0; | ||
301 | const char *dictionary; | ||
302 | size_t dictionary_len; | ||
303 | |||
304 | if (lua_istable(L, 1) || lua_isuserdata(L, 1)) { | ||
305 | /* is there a :read function? */ | ||
306 | lua_getfield(L, 1, "read"); | ||
307 | if (!lua_isfunction(L, -1)) { | ||
308 | luaL_argerror(L, 1, "input parameter does not provide :read function"); | ||
309 | } | ||
310 | lua_pop(L, 1); | ||
311 | /* check for peek function */ | ||
312 | lua_getfield(L, 1, "peek"); | ||
313 | have_peek = lua_isfunction(L, -1); | ||
314 | lua_pop(L, 1); | ||
315 | } | ||
316 | else if (!lua_isstring(L, 1) && !lua_isfunction(L, 1)) { | ||
317 | luaL_argerror(L, 1, "input parameter must be a string, function, table or userdata value"); | ||
318 | } | ||
319 | |||
320 | windowBits = (int) luaL_optinteger(L, 2, 15); | ||
321 | dictionary = luaL_optlstring(L, 3, NULL, &dictionary_len); | ||
322 | |||
323 | s = lzstream_new(L, 1); | ||
324 | |||
325 | if (windowBits > 0 && windowBits < 16) { | ||
326 | windowBits |= 32; | ||
327 | } | ||
328 | |||
329 | if (inflateInit2(&s->zstream, windowBits) != Z_OK) { | ||
330 | lua_pushliteral(L, "call to inflateInit2 failed"); | ||
331 | lua_error(L); | ||
332 | } | ||
333 | |||
334 | if (dictionary) { | ||
335 | s->dictionary = (const Bytef *) dictionary; | ||
336 | s->dictionary_len = dictionary_len; | ||
337 | } | ||
338 | |||
339 | s->peek = have_peek; | ||
340 | s->state = LZ_INFLATE; | ||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | /* ====================================================================== */ | ||
345 | |||
346 | static int lz_pushresult (lua_State *L, lz_stream *s) { | ||
347 | if (s->error == Z_OK) { | ||
348 | lua_pushboolean(L, 1); | ||
349 | return 1; | ||
350 | } else { | ||
351 | lua_pushnil(L); | ||
352 | lua_pushstring(L, zError(s->error)); | ||
353 | lua_pushinteger(L, s->error); | ||
354 | return 3; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | Get block to process: | ||
360 | - top of stack gets | ||
361 | */ | ||
362 | static const char* lzstream_fetch_block(lua_State *L, lz_stream *s, int hint) { | ||
363 | if (s->i_buffer_pos >= s->i_buffer_len) { | ||
364 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
365 | s->i_buffer_ref = LUA_NOREF; | ||
366 | s->i_buffer = NULL; | ||
367 | |||
368 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
369 | if (!lua_isnil(L, -1)) { | ||
370 | if (lua_isfunction(L, -1)) { | ||
371 | lua_pushinteger(L, hint); | ||
372 | lua_call(L, 1, 1); | ||
373 | } else { | ||
374 | lua_getfield(L, -1, (s->peek ? "peek" : "read")); | ||
375 | lua_insert(L, -2); | ||
376 | lua_pushinteger(L, hint); | ||
377 | lua_call(L, 2, 1); | ||
378 | } | ||
379 | |||
380 | if (lua_isstring(L, -1)) { | ||
381 | s->i_buffer_pos = 0; | ||
382 | s->i_buffer = lua_tolstring(L, -1, &s->i_buffer_len); | ||
383 | if (s->i_buffer_len > 0) { | ||
384 | s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
385 | } else { | ||
386 | lua_pop(L, 1); | ||
387 | } | ||
388 | } else if (lua_isnil(L, -1)) { | ||
389 | lua_pop(L, 1); | ||
390 | } else { | ||
391 | lua_pushliteral(L, "deflate callback must return string or nil"); | ||
392 | lua_error(L); | ||
393 | } | ||
394 | } else { | ||
395 | lua_pop(L, 1); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | return s->i_buffer; | ||
400 | } | ||
401 | |||
402 | static int lzstream_inflate_block(lua_State *L, lz_stream *s) { | ||
403 | if (lzstream_fetch_block(L, s, LZ_BUFFER_SIZE) || !s->eos) { | ||
404 | int r; | ||
405 | |||
406 | if (s->i_buffer_len == s->i_buffer_pos) { | ||
407 | s->zstream.next_in = NULL; | ||
408 | s->zstream.avail_in = 0; | ||
409 | } else { | ||
410 | s->zstream.next_in = (unsigned char*)(s->i_buffer + s->i_buffer_pos); | ||
411 | s->zstream.avail_in = s->i_buffer_len - s->i_buffer_pos; | ||
412 | } | ||
413 | |||
414 | s->zstream.next_out = (unsigned char*)s->o_buffer + s->o_buffer_len; | ||
415 | s->zstream.avail_out = s->o_buffer_max - s->o_buffer_len; | ||
416 | |||
417 | /* munch some more */ | ||
418 | r = inflate(&s->zstream, Z_SYNC_FLUSH); | ||
419 | |||
420 | if (r == Z_NEED_DICT) { | ||
421 | if (s->dictionary == NULL) { | ||
422 | lua_pushliteral(L, "no inflate dictionary provided"); | ||
423 | lua_error(L); | ||
424 | } | ||
425 | |||
426 | if (inflateSetDictionary(&s->zstream, s->dictionary, s->dictionary_len) != Z_OK) { | ||
427 | lua_pushliteral(L, "call to inflateSetDictionnary failed"); | ||
428 | lua_error(L); | ||
429 | } | ||
430 | |||
431 | r = inflate(&s->zstream, Z_SYNC_FLUSH); | ||
432 | } | ||
433 | |||
434 | if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) { | ||
435 | lzstream_cleanup(L, s); | ||
436 | s->error = r; | ||
437 | #if 1 | ||
438 | lua_pushfstring(L, "failed to decompress [%d]", r); | ||
439 | lua_error(L); | ||
440 | #endif | ||
441 | } | ||
442 | |||
443 | if (r == Z_STREAM_END) { | ||
444 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
445 | s->i_buffer_ref = LUA_NOREF; | ||
446 | s->i_buffer = NULL; | ||
447 | |||
448 | s->eos = 1; | ||
449 | } | ||
450 | |||
451 | /* number of processed bytes */ | ||
452 | if (s->peek) { | ||
453 | size_t processed = s->i_buffer_len - s->i_buffer_pos - s->zstream.avail_in; | ||
454 | |||
455 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
456 | lua_getfield(L, -1, "read"); | ||
457 | lua_insert(L, -2); | ||
458 | lua_pushinteger(L, processed); | ||
459 | lua_call(L, 2, 0); | ||
460 | } | ||
461 | |||
462 | s->i_buffer_pos = s->i_buffer_len - s->zstream.avail_in; | ||
463 | s->o_buffer_len = s->o_buffer_max - s->zstream.avail_out; | ||
464 | } | ||
465 | |||
466 | return s->o_buffer_len; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | ** Remove n bytes from the output buffer. | ||
471 | */ | ||
472 | static void lzstream_remove(lz_stream *s, size_t n) { | ||
473 | memmove(s->o_buffer, s->o_buffer + n, s->o_buffer_len - n); | ||
474 | s->o_buffer_len -= n; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | ** Copy at most n bytes to buffer b and remove them from the | ||
479 | ** output stream buffer. | ||
480 | */ | ||
481 | static int lzstream_flush_buffer(lua_State *L, lz_stream *s, size_t n, luaL_Buffer *b) { | ||
482 | /* check output */ | ||
483 | if (n > s->o_buffer_len) { | ||
484 | n = s->o_buffer_len; | ||
485 | } | ||
486 | |||
487 | if (n > 0) { | ||
488 | lua_pushlstring(L, s->o_buffer, n); | ||
489 | luaL_addvalue(b); | ||
490 | |||
491 | lzstream_remove(s, n); | ||
492 | } | ||
493 | |||
494 | return n; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | z:read( | ||
499 | {number | '*l' | '*a'}* | ||
500 | ) | ||
501 | */ | ||
502 | static int lz_test_eof(lua_State *L, lz_stream *s) { | ||
503 | lua_pushlstring(L, NULL, 0); | ||
504 | if (s->o_buffer_len > 0) { | ||
505 | return 1; | ||
506 | } else if (s->eos) { | ||
507 | return 0; | ||
508 | } else { | ||
509 | return lzstream_inflate_block(L, s); | ||
510 | } | ||
511 | } | ||
512 | |||
513 | static int lz_read_line(lua_State *L, lz_stream *s) { | ||
514 | luaL_Buffer b; | ||
515 | size_t l = 0, n; | ||
516 | |||
517 | luaL_buffinit(L, &b); | ||
518 | |||
519 | if (s->o_buffer_len > 0 || !s->eos) do { | ||
520 | char *p = s->o_buffer; | ||
521 | size_t len = s->o_buffer_len; | ||
522 | |||
523 | /* find newline in output buffer */ | ||
524 | for (n = 0; n < len; ++n, ++p) { | ||
525 | if (*p == '\n' || *p == '\r') { | ||
526 | int eat_nl = *p == '\r'; | ||
527 | luaL_addlstring(&b, s->o_buffer, n); | ||
528 | lzstream_remove(s, n+1); | ||
529 | l += n; | ||
530 | |||
531 | if (eat_nl && lzstream_inflate_block(L, s)) { | ||
532 | if (s->o_buffer_len > 0 && *s->o_buffer == '\n') { | ||
533 | lzstream_remove(s, 1); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | luaL_pushresult(&b); | ||
538 | return 1; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | if (len > 0) { | ||
543 | luaL_addlstring(&b, s->o_buffer, len); | ||
544 | lzstream_remove(s, len); | ||
545 | l += len; | ||
546 | } | ||
547 | } while (lzstream_inflate_block(L, s)); | ||
548 | |||
549 | luaL_pushresult(&b); | ||
550 | return l > 0 || !s->eos || s->o_buffer_len > 0; | ||
551 | } | ||
552 | |||
553 | |||
554 | static int lz_read_chars(lua_State *L, lz_stream *s, size_t n) { | ||
555 | size_t len; | ||
556 | luaL_Buffer b; | ||
557 | luaL_buffinit(L, &b); | ||
558 | |||
559 | if (s->o_buffer_len > 0 || !s->eos) do { | ||
560 | size_t rlen = lzstream_flush_buffer(L, s, n, &b); | ||
561 | n -= rlen; | ||
562 | } while (n > 0 && lzstream_inflate_block(L, s)); | ||
563 | |||
564 | luaL_pushresult(&b); | ||
565 | lua_tolstring(L, -1, &len); | ||
566 | return n == 0 || len > 0; | ||
567 | } | ||
568 | |||
569 | static int lzstream_decompress(lua_State *L) { | ||
570 | lz_stream *s = lzstream_check(L, 1, LZ_INFLATE); | ||
571 | int nargs = lua_gettop(L) - 1; | ||
572 | int success; | ||
573 | int n; | ||
574 | if (nargs == 0) { /* no arguments? */ | ||
575 | success = lz_read_line(L, s); | ||
576 | n = 3; /* to return 1 result */ | ||
577 | } | ||
578 | else { /* ensure stack space for all results and for auxlib's buffer */ | ||
579 | luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); | ||
580 | success = 1; | ||
581 | for (n = 2; nargs-- && success; n++) { | ||
582 | if (lua_type(L, n) == LUA_TNUMBER) { | ||
583 | size_t l = (size_t)lua_tointeger(L, n); | ||
584 | success = (l == 0) ? lz_test_eof(L, s) : lz_read_chars(L, s, l); | ||
585 | } | ||
586 | else { | ||
587 | const char *p = lua_tostring(L, n); | ||
588 | luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); | ||
589 | switch (p[1]) { | ||
590 | case 'l': /* line */ | ||
591 | success = lz_read_line(L, s); | ||
592 | break; | ||
593 | case 'a': /* file */ | ||
594 | lz_read_chars(L, s, ~((size_t)0)); /* read MAX_SIZE_T chars */ | ||
595 | success = 1; /* always success */ | ||
596 | break; | ||
597 | default: | ||
598 | return luaL_argerror(L, n, "invalid format"); | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | if (s->error != Z_OK) { | ||
604 | return lz_pushresult(L, s); | ||
605 | } | ||
606 | if (!success) { | ||
607 | lua_pop(L, 1); /* remove last result */ | ||
608 | lua_pushnil(L); /* push nil instead */ | ||
609 | } | ||
610 | return n - 2; | ||
611 | } | ||
612 | |||
613 | |||
614 | static int lzstream_readline(lua_State *L) { | ||
615 | lz_stream *s; | ||
616 | int sucess; | ||
617 | |||
618 | s = lzstream_check(L, lua_upvalueindex(1), LZ_INFLATE); | ||
619 | sucess = lz_read_line(L, s); | ||
620 | |||
621 | if (s->error != Z_OK) { | ||
622 | return lz_pushresult(L, s); | ||
623 | } | ||
624 | |||
625 | if (sucess) { | ||
626 | return 1; | ||
627 | } else { | ||
628 | /* EOF */ | ||
629 | return 0; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static int lzstream_lines(lua_State *L) { | ||
634 | lzstream_check(L, 1, LZ_INFLATE); | ||
635 | lua_settop(L, 1); | ||
636 | lua_pushcclosure(L, lzstream_readline, 1); | ||
637 | return 1; | ||
638 | } | ||
639 | |||
640 | /* ====================================================================== */ | ||
641 | |||
642 | static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush) { | ||
643 | int r, arg; | ||
644 | int self = 0; | ||
645 | size_t b_size = s->o_buffer_max; | ||
646 | unsigned char *b = (unsigned char *)s->o_buffer; | ||
647 | |||
648 | /* number of processed bytes */ | ||
649 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
650 | if (!lua_isfunction(L, -1)) { | ||
651 | self = 1; | ||
652 | lua_getfield(L, -1, "write"); | ||
653 | } | ||
654 | |||
655 | for (arg = from; arg <= to; arg++) { | ||
656 | s->zstream.next_in = (unsigned char*)luaL_checklstring(L, arg, (size_t*)&s->zstream.avail_in); | ||
657 | |||
658 | do { | ||
659 | s->zstream.next_out = b; | ||
660 | s->zstream.avail_out = b_size; | ||
661 | |||
662 | /* bake some more */ | ||
663 | r = deflate(&s->zstream, flush); | ||
664 | if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) { | ||
665 | lzstream_cleanup(L, s); | ||
666 | lua_pushboolean(L, 0); | ||
667 | lua_pushfstring(L, "failed to compress [%d]", r); | ||
668 | return 2; | ||
669 | } | ||
670 | |||
671 | if (s->zstream.avail_out != b_size) { | ||
672 | /* write output */ | ||
673 | lua_pushvalue(L, -1); /* function */ | ||
674 | if (self) lua_pushvalue(L, -3); /* self */ | ||
675 | lua_pushlstring(L, (char*)b, b_size - s->zstream.avail_out); /* data */ | ||
676 | lua_call(L, (self ? 2 : 1), 0); | ||
677 | } | ||
678 | |||
679 | if (r == Z_STREAM_END) { | ||
680 | lzstream_cleanup(L, s); | ||
681 | break; | ||
682 | } | ||
683 | |||
684 | /* process all input */ | ||
685 | } while (s->zstream.avail_in > 0 || s->zstream.avail_out == 0); | ||
686 | } | ||
687 | |||
688 | lua_pushboolean(L, 1); | ||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | static int lzstream_compress(lua_State *L) { | ||
693 | lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE); | ||
694 | return lzstream_docompress(L, s, 2, lua_gettop(L), Z_NO_FLUSH); | ||
695 | } | ||
696 | |||
697 | |||
698 | /* ====================================================================== */ | ||
699 | |||
700 | static int lzstream_flush(lua_State *L) { | ||
701 | static int flush_values[] = { Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH }; | ||
702 | static const char *const flush_opts[] = { "sync", "full", "finish" }; | ||
703 | |||
704 | lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE); | ||
705 | int flush = luaL_checkoption(L, 2, flush_opts[0], flush_opts); | ||
706 | |||
707 | lua_settop(L, 0); | ||
708 | lua_pushliteral(L, ""); | ||
709 | return lzstream_docompress(L, s, 1, 1, flush_values[flush]); | ||
710 | } | ||
711 | |||
712 | /* ====================================================================== */ | ||
713 | |||
714 | static int lzlib_compress(lua_State *L) { | ||
715 | size_t avail_in; | ||
716 | const char *next_in = luaL_checklstring(L, 1, &avail_in); | ||
717 | int level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION); | ||
718 | int method = (int) luaL_optinteger(L, 3, Z_DEFLATED); | ||
719 | int windowBits = (int) luaL_optinteger(L, 4, 15); | ||
720 | int memLevel = (int) luaL_optinteger(L, 5, 8); | ||
721 | int strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY); | ||
722 | |||
723 | int ret; | ||
724 | luaL_Buffer b; | ||
725 | z_stream zs; | ||
726 | |||
727 | luaL_buffinit(L, &b); | ||
728 | |||
729 | zs.zalloc = Z_NULL; | ||
730 | zs.zfree = Z_NULL; | ||
731 | |||
732 | zs.next_out = Z_NULL; | ||
733 | zs.avail_out = 0; | ||
734 | zs.next_in = Z_NULL; | ||
735 | zs.avail_in = 0; | ||
736 | |||
737 | ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy); | ||
738 | |||
739 | if (ret != Z_OK) | ||
740 | { | ||
741 | lua_pushnil(L); | ||
742 | lua_pushnumber(L, ret); | ||
743 | return 2; | ||
744 | } | ||
745 | |||
746 | zs.next_in = (unsigned char*)next_in; | ||
747 | zs.avail_in = avail_in; | ||
748 | |||
749 | for(;;) | ||
750 | { | ||
751 | zs.next_out = (unsigned char*)luaL_prepbuffer(&b); | ||
752 | zs.avail_out = LUAL_BUFFERSIZE; | ||
753 | |||
754 | /* munch some more */ | ||
755 | ret = deflate(&zs, Z_FINISH); | ||
756 | |||
757 | /* push gathered data */ | ||
758 | luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out); | ||
759 | |||
760 | /* done processing? */ | ||
761 | if (ret == Z_STREAM_END) | ||
762 | break; | ||
763 | |||
764 | /* error condition? */ | ||
765 | if (ret != Z_OK) | ||
766 | break; | ||
767 | } | ||
768 | |||
769 | /* cleanup */ | ||
770 | deflateEnd(&zs); | ||
771 | |||
772 | luaL_pushresult(&b); | ||
773 | lua_pushnumber(L, ret); | ||
774 | return 2; | ||
775 | } | ||
776 | |||
777 | /* ====================================================================== */ | ||
778 | |||
779 | static int lzlib_decompress(lua_State *L) | ||
780 | { | ||
781 | size_t avail_in; | ||
782 | const char *next_in = luaL_checklstring(L, 1, &avail_in); | ||
783 | int windowBits = (int) luaL_optinteger(L, 2, 15); | ||
784 | |||
785 | int ret; | ||
786 | luaL_Buffer b; | ||
787 | z_stream zs; | ||
788 | |||
789 | luaL_buffinit(L, &b); | ||
790 | |||
791 | zs.zalloc = Z_NULL; | ||
792 | zs.zfree = Z_NULL; | ||
793 | |||
794 | zs.next_out = Z_NULL; | ||
795 | zs.avail_out = 0; | ||
796 | zs.next_in = Z_NULL; | ||
797 | zs.avail_in = 0; | ||
798 | |||
799 | ret = inflateInit2(&zs, windowBits); | ||
800 | |||
801 | if (ret != Z_OK) { | ||
802 | lua_pushliteral(L, "failed to initialize zstream structures"); | ||
803 | lua_error(L); | ||
804 | } | ||
805 | |||
806 | zs.next_in = (unsigned char*)next_in; | ||
807 | zs.avail_in = avail_in; | ||
808 | |||
809 | for (;;) { | ||
810 | zs.next_out = (unsigned char*)luaL_prepbuffer(&b); | ||
811 | zs.avail_out = LUAL_BUFFERSIZE; | ||
812 | |||
813 | /* bake some more */ | ||
814 | ret = inflate(&zs, Z_FINISH); | ||
815 | |||
816 | /* push gathered data */ | ||
817 | luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out); | ||
818 | |||
819 | /* done processing? */ | ||
820 | if (ret == Z_STREAM_END) | ||
821 | break; | ||
822 | |||
823 | if (ret != Z_OK && ret != Z_BUF_ERROR) { | ||
824 | /* cleanup */ | ||
825 | inflateEnd(&zs); | ||
826 | |||
827 | lua_pushliteral(L, "failed to process zlib stream"); | ||
828 | lua_error(L); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | /* cleanup */ | ||
833 | inflateEnd(&zs); | ||
834 | |||
835 | luaL_pushresult(&b); | ||
836 | return 1; | ||
837 | } | ||
838 | |||
839 | #endif | ||
840 | /**********************************************************************/ | ||
841 | |||
842 | #define DEF_MEM_LEVEL 8 | ||
843 | |||
844 | typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len); | ||
845 | typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2); | ||
846 | |||
847 | |||
848 | static int lz_deflate(lua_State *L); | ||
849 | static int lz_deflate_delete(lua_State *L); | ||
850 | static int lz_inflate_delete(lua_State *L); | ||
851 | static int lz_inflate(lua_State *L); | ||
852 | static int lz_checksum(lua_State *L); | ||
853 | static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine); | ||
854 | static int lz_adler32(lua_State *L); | ||
855 | static int lz_crc32(lua_State *L); | ||
856 | |||
857 | static int lz_version(lua_State *L) { | ||
858 | const char* version = zlibVersion(); | ||
859 | int count = strlen(version) + 1; | ||
860 | char* cur = (char*)memcpy(lua_newuserdata(L, count), | ||
861 | version, count); | ||
862 | |||
863 | count = 0; | ||
864 | while ( *cur ) { | ||
865 | char* begin = cur; | ||
866 | /* Find all digits: */ | ||
867 | while ( isdigit(*cur) ) cur++; | ||
868 | if ( begin != cur ) { | ||
869 | int is_end = *cur == '\0'; | ||
870 | *cur = '\0'; | ||
871 | lua_pushnumber(L, atoi(begin)); | ||
872 | count++; | ||
873 | if ( is_end ) break; | ||
874 | cur++; | ||
875 | } | ||
876 | while ( *cur && ! isdigit(*cur) ) cur++; | ||
877 | } | ||
878 | |||
879 | return count; | ||
880 | } | ||
881 | |||
882 | static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) { | ||
883 | /* Both of these are "normal" return codes: */ | ||
884 | if ( result == Z_OK || result == Z_STREAM_END ) return result; | ||
885 | switch ( result ) { | ||
886 | case Z_NEED_DICT: | ||
887 | lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d", | ||
888 | stream->msg, file, line); | ||
889 | break; | ||
890 | case Z_STREAM_ERROR: | ||
891 | lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d", | ||
892 | stream->msg, file, line); | ||
893 | break; | ||
894 | case Z_DATA_ERROR: | ||
895 | lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d", | ||
896 | file, line); | ||
897 | break; | ||
898 | case Z_MEM_ERROR: | ||
899 | lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d", | ||
900 | stream->msg, file, line); | ||
901 | break; | ||
902 | case Z_BUF_ERROR: | ||
903 | lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d", | ||
904 | stream->msg, file, line); | ||
905 | break; | ||
906 | case Z_VERSION_ERROR: | ||
907 | lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d", | ||
908 | ZLIB_VERSION, zlibVersion(), stream->msg, file, line); | ||
909 | break; | ||
910 | default: | ||
911 | lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d", | ||
912 | result, stream->msg, file, line); | ||
913 | } | ||
914 | lua_error(L); | ||
915 | return result; | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * @upvalue z_stream - Memory for the z_stream. | ||
920 | * @upvalue remainder - Any remainder from the last deflate call. | ||
921 | * | ||
922 | * @param string - "print" to deflate stream. | ||
923 | * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH. | ||
924 | * | ||
925 | * if no params, terminates the stream (as if we got empty string and Z_FINISH). | ||
926 | */ | ||
927 | static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) { | ||
928 | int flush = Z_NO_FLUSH, result; | ||
929 | z_stream* stream; | ||
930 | luaL_Buffer buff; | ||
931 | size_t avail_in; | ||
932 | |||
933 | if ( filter == deflate ) { | ||
934 | const char *const opts[] = { "none", "sync", "full", "finish", NULL }; | ||
935 | flush = luaL_checkoption(L, 2, opts[0], opts); | ||
936 | if ( flush ) flush++; | ||
937 | /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */ | ||
938 | |||
939 | /* No arguments or nil, we are terminating the stream: */ | ||
940 | if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) { | ||
941 | flush = Z_FINISH; | ||
942 | } | ||
943 | } | ||
944 | |||
945 | stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1)); | ||
946 | if ( stream == NULL ) { | ||
947 | if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) { | ||
948 | lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name); | ||
949 | lua_error(L); | ||
950 | } | ||
951 | lua_pushstring(L, ""); | ||
952 | lua_pushboolean(L, 1); | ||
953 | return 2; /* Ignore duplicate calls to "close". */ | ||
954 | } | ||
955 | |||
956 | luaL_buffinit(L, &buff); | ||
957 | |||
958 | if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1); | ||
959 | |||
960 | if ( lua_isstring(L, lua_upvalueindex(2)) ) { | ||
961 | lua_pushvalue(L, lua_upvalueindex(2)); | ||
962 | if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) { | ||
963 | lua_concat(L, 2); | ||
964 | } | ||
965 | } | ||
966 | |||
967 | /* Do the actual deflate'ing: */ | ||
968 | if (lua_gettop(L) > 0) { | ||
969 | stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in); | ||
970 | } else { | ||
971 | stream->next_in = NULL; | ||
972 | avail_in = 0; | ||
973 | } | ||
974 | stream->avail_in = avail_in; | ||
975 | |||
976 | if ( ! stream->avail_in && ! flush ) { | ||
977 | /* Passed empty string, make it a noop instead of erroring out. */ | ||
978 | lua_pushstring(L, ""); | ||
979 | lua_pushboolean(L, 0); | ||
980 | lua_pushinteger(L, stream->total_in); | ||
981 | lua_pushinteger(L, stream->total_out); | ||
982 | return 4; | ||
983 | } | ||
984 | |||
985 | do { | ||
986 | stream->next_out = (unsigned char*)luaL_prepbuffer(&buff); | ||
987 | stream->avail_out = LUAL_BUFFERSIZE; | ||
988 | result = filter(stream, flush); | ||
989 | if ( Z_BUF_ERROR != result ) { | ||
990 | /* Ignore Z_BUF_ERROR since that just indicates that we | ||
991 | * need a larger buffer in order to proceed. Thanks to | ||
992 | * Tobias Markmann for finding this bug! | ||
993 | */ | ||
994 | lz_assert(L, result, stream, __FILE__, __LINE__); | ||
995 | } | ||
996 | luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out); | ||
997 | } while ( stream->avail_out == 0 ); | ||
998 | |||
999 | /* Need to do this before we alter the stack: */ | ||
1000 | luaL_pushresult(&buff); | ||
1001 | |||
1002 | /* Save remainder in lua_upvalueindex(2): */ | ||
1003 | if ( NULL != stream->next_in ) { | ||
1004 | lua_pushlstring(L, (char*)stream->next_in, stream->avail_in); | ||
1005 | lua_replace(L, lua_upvalueindex(2)); | ||
1006 | } | ||
1007 | |||
1008 | /* "close" the stream/remove finalizer: */ | ||
1009 | if ( result == Z_STREAM_END ) { | ||
1010 | /* Clear-out the metatable so end is not called twice: */ | ||
1011 | lua_pushnil(L); | ||
1012 | lua_setmetatable(L, lua_upvalueindex(1)); | ||
1013 | |||
1014 | /* nil the upvalue: */ | ||
1015 | lua_pushnil(L); | ||
1016 | lua_replace(L, lua_upvalueindex(1)); | ||
1017 | |||
1018 | /* Close the stream: */ | ||
1019 | lz_assert(L, end(stream), stream, __FILE__, __LINE__); | ||
1020 | |||
1021 | lua_pushboolean(L, 1); | ||
1022 | } else { | ||
1023 | lua_pushboolean(L, 0); | ||
1024 | } | ||
1025 | lua_pushinteger(L, stream->total_in); | ||
1026 | lua_pushinteger(L, stream->total_out); | ||
1027 | return 4; | ||
1028 | } | ||
1029 | |||
1030 | static void lz_create_deflate_mt(lua_State *L) { | ||
1031 | luaL_newmetatable(L, "lz.deflate.meta"); /* {} */ | ||
1032 | |||
1033 | lua_pushcfunction(L, lz_deflate_delete); | ||
1034 | lua_setfield(L, -2, "__gc"); | ||
1035 | |||
1036 | lua_pop(L, 1); /* <empty> */ | ||
1037 | } | ||
1038 | |||
1039 | static int lz_deflate_new(lua_State *L) { | ||
1040 | int level; | ||
1041 | int window_size; | ||
1042 | int result; | ||
1043 | |||
1044 | #ifdef LZLIB_COMPAT | ||
1045 | if ( lua_istable(L, 1) || lua_isuserdata(L, 1) || lua_isfunction(L, 1) ) { | ||
1046 | return lzlib_deflate(L); | ||
1047 | } | ||
1048 | #endif | ||
1049 | |||
1050 | level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION); | ||
1051 | window_size = luaL_optint(L, 2, MAX_WBITS); | ||
1052 | |||
1053 | /* Allocate the stream: */ | ||
1054 | z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); | ||
1055 | |||
1056 | stream->zalloc = Z_NULL; | ||
1057 | stream->zfree = Z_NULL; | ||
1058 | |||
1059 | result = deflateInit2(stream, level, Z_DEFLATED, window_size, | ||
1060 | DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); | ||
1061 | |||
1062 | lz_assert(L, result, stream, __FILE__, __LINE__); | ||
1063 | |||
1064 | /* Don't allow destructor to execute unless deflateInit2 was successful: */ | ||
1065 | luaL_getmetatable(L, "lz.deflate.meta"); | ||
1066 | lua_setmetatable(L, -2); | ||
1067 | |||
1068 | lua_pushnil(L); | ||
1069 | lua_pushcclosure(L, lz_deflate, 2); | ||
1070 | return 1; | ||
1071 | } | ||
1072 | |||
1073 | static int lz_deflate(lua_State *L) { | ||
1074 | return lz_filter_impl(L, deflate, deflateEnd, "deflate"); | ||
1075 | } | ||
1076 | |||
1077 | static int lz_deflate_delete(lua_State *L) { | ||
1078 | z_stream* stream = (z_stream*)lua_touserdata(L, 1); | ||
1079 | |||
1080 | /* Ignore errors. */ | ||
1081 | deflateEnd(stream); | ||
1082 | |||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | static void lz_create_inflate_mt(lua_State *L) { | ||
1088 | luaL_newmetatable(L, "lz.inflate.meta"); /* {} */ | ||
1089 | |||
1090 | lua_pushcfunction(L, lz_inflate_delete); | ||
1091 | lua_setfield(L, -2, "__gc"); | ||
1092 | |||
1093 | lua_pop(L, 1); /* <empty> */ | ||
1094 | } | ||
1095 | |||
1096 | static int lz_inflate_new(lua_State *L) { | ||
1097 | /* Allocate the stream */ | ||
1098 | z_stream* stream; | ||
1099 | |||
1100 | #ifdef LZLIB_COMPAT | ||
1101 | int type = lua_type(L, 1); | ||
1102 | if ( type == LUA_TTABLE || type == LUA_TUSERDATA || type == LUA_TFUNCTION || type == LUA_TSTRING ) { | ||
1103 | return lzlib_inflate(L); | ||
1104 | } | ||
1105 | #endif | ||
1106 | |||
1107 | stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); | ||
1108 | |||
1109 | /* By default, we will do gzip header detection w/ max window size */ | ||
1110 | int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32; | ||
1111 | |||
1112 | stream->zalloc = Z_NULL; | ||
1113 | stream->zfree = Z_NULL; | ||
1114 | stream->next_in = Z_NULL; | ||
1115 | stream->avail_in = 0; | ||
1116 | |||
1117 | lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__); | ||
1118 | |||
1119 | /* Don't allow destructor to execute unless deflateInit was successful: */ | ||
1120 | luaL_getmetatable(L, "lz.inflate.meta"); | ||
1121 | lua_setmetatable(L, -2); | ||
1122 | |||
1123 | lua_pushnil(L); | ||
1124 | lua_pushcclosure(L, lz_inflate, 2); | ||
1125 | return 1; | ||
1126 | } | ||
1127 | |||
1128 | static int lz_inflate(lua_State *L) { | ||
1129 | return lz_filter_impl(L, inflate, inflateEnd, "inflate"); | ||
1130 | } | ||
1131 | |||
1132 | static int lz_inflate_delete(lua_State *L) { | ||
1133 | z_stream* stream = (z_stream*)lua_touserdata(L, 1); | ||
1134 | |||
1135 | /* Ignore errors: */ | ||
1136 | inflateEnd(stream); | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static int lz_checksum(lua_State *L) { | ||
1142 | if ( lua_gettop(L) <= 0 ) { | ||
1143 | lua_pushvalue(L, lua_upvalueindex(3)); | ||
1144 | lua_pushvalue(L, lua_upvalueindex(4)); | ||
1145 | } else if ( lua_isfunction(L, 1) ) { | ||
1146 | checksum_combine_t combine = (checksum_combine_t) | ||
1147 | lua_touserdata(L, lua_upvalueindex(2)); | ||
1148 | |||
1149 | lua_pushvalue(L, 1); | ||
1150 | lua_call(L, 0, 2); | ||
1151 | if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) { | ||
1152 | luaL_argerror(L, 1, "expected function to return two numbers"); | ||
1153 | } | ||
1154 | |||
1155 | /* Calculate and replace the checksum */ | ||
1156 | lua_pushnumber(L, | ||
1157 | combine((uLong)lua_tonumber(L, lua_upvalueindex(3)), | ||
1158 | (uLong)lua_tonumber(L, -2), | ||
1159 | (z_off_t)lua_tonumber(L, -1))); | ||
1160 | lua_pushvalue(L, -1); | ||
1161 | lua_replace(L, lua_upvalueindex(3)); | ||
1162 | |||
1163 | /* Calculate and replace the length */ | ||
1164 | lua_pushnumber(L, | ||
1165 | lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2)); | ||
1166 | lua_pushvalue(L, -1); | ||
1167 | lua_replace(L, lua_upvalueindex(4)); | ||
1168 | } else { | ||
1169 | const Bytef* str; | ||
1170 | size_t len; | ||
1171 | |||
1172 | checksum_t checksum = (checksum_t) | ||
1173 | lua_touserdata(L, lua_upvalueindex(1)); | ||
1174 | str = (const Bytef*)luaL_checklstring(L, 1, &len); | ||
1175 | |||
1176 | /* Calculate and replace the checksum */ | ||
1177 | lua_pushnumber(L, | ||
1178 | checksum((uLong)lua_tonumber(L, lua_upvalueindex(3)), | ||
1179 | str, | ||
1180 | len)); | ||
1181 | lua_pushvalue(L, -1); | ||
1182 | lua_replace(L, lua_upvalueindex(3)); | ||
1183 | |||
1184 | /* Calculate and replace the length */ | ||
1185 | lua_pushnumber(L, | ||
1186 | lua_tonumber(L, lua_upvalueindex(4)) + len); | ||
1187 | lua_pushvalue(L, -1); | ||
1188 | lua_replace(L, lua_upvalueindex(4)); | ||
1189 | } | ||
1190 | return 2; | ||
1191 | } | ||
1192 | |||
1193 | static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) { | ||
1194 | lua_pushlightuserdata(L, checksum); | ||
1195 | lua_pushlightuserdata(L, combine); | ||
1196 | lua_pushnumber(L, checksum(0L, Z_NULL, 0)); | ||
1197 | lua_pushnumber(L, 0); | ||
1198 | lua_pushcclosure(L, lz_checksum, 4); | ||
1199 | return 1; | ||
1200 | } | ||
1201 | |||
1202 | static int lz_adler32(lua_State *L) { | ||
1203 | #ifdef LZLIB_COMPAT | ||
1204 | /* lzlib compat*/ | ||
1205 | if ( lua_gettop(L) != 0 ) { | ||
1206 | size_t len; | ||
1207 | int adler; | ||
1208 | const unsigned char* buf; | ||
1209 | if ( lua_isfunction(L, 1) ) { | ||
1210 | adler = adler32(0L, Z_NULL, 0); | ||
1211 | } else { | ||
1212 | adler = (int)luaL_checkinteger(L, 1); | ||
1213 | } | ||
1214 | buf = (unsigned char*)luaL_checklstring(L, 2, &len); | ||
1215 | lua_pushnumber(L, adler32(adler, buf, len)); | ||
1216 | return 1; | ||
1217 | } | ||
1218 | #endif | ||
1219 | return lz_checksum_new(L, adler32, adler32_combine); | ||
1220 | } | ||
1221 | |||
1222 | static int lz_crc32(lua_State *L) { | ||
1223 | #ifdef LZLIB_COMPAT | ||
1224 | /* lzlib compat*/ | ||
1225 | if ( lua_gettop(L) != 0 ) { | ||
1226 | size_t len; | ||
1227 | int crc; | ||
1228 | const unsigned char* buf; | ||
1229 | if ( lua_isfunction(L, 1) ) { | ||
1230 | crc = crc32(0L, Z_NULL, 0); | ||
1231 | } else { | ||
1232 | crc = (int)luaL_checkinteger(L, 1); | ||
1233 | } | ||
1234 | buf = (unsigned char*)luaL_checklstring(L, 2, &len); | ||
1235 | lua_pushnumber(L, crc32(crc, buf, len)); | ||
1236 | return 1; | ||
1237 | } | ||
1238 | #endif | ||
1239 | return lz_checksum_new(L, crc32, crc32_combine); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | static const luaL_Reg zlib_functions[] = { | ||
1244 | { "deflate", lz_deflate_new }, | ||
1245 | { "inflate", lz_inflate_new }, | ||
1246 | { "adler32", lz_adler32 }, | ||
1247 | { "crc32", lz_crc32 }, | ||
1248 | #ifdef LZLIB_COMPAT | ||
1249 | { "compress", lzlib_compress }, | ||
1250 | { "decompress", lzlib_decompress }, | ||
1251 | #endif | ||
1252 | { "version", lz_version }, | ||
1253 | { NULL, NULL } | ||
1254 | }; | ||
1255 | |||
1256 | #define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3)) | ||
1257 | #define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3)) | ||
1258 | |||
1259 | LUALIB_API int luaopen_zlib(lua_State * const L) { | ||
1260 | lz_create_deflate_mt(L); | ||
1261 | lz_create_inflate_mt(L); | ||
1262 | |||
1263 | luaL_register(L, "zlib", zlib_functions); | ||
1264 | |||
1265 | SETINT("BEST_SPEED", Z_BEST_SPEED); | ||
1266 | SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION); | ||
1267 | |||
1268 | SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2016 Brian Maher"); | ||
1269 | SETLITERAL("_DESCRIPTION", "Simple streaming interface to the zlib library"); | ||
1270 | SETLITERAL("_VERSION", "lua-zlib $Id$ $Format:%d$"); | ||
1271 | |||
1272 | /* Expose this to lua so we can do a test: */ | ||
1273 | SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE); | ||
1274 | |||
1275 | /* lzlib compatibility */ | ||
1276 | #ifdef LZLIB_COMPAT | ||
1277 | SETINT("NO_COMPRESSION", Z_NO_COMPRESSION); | ||
1278 | SETINT("DEFAULT_COMPRESSION", Z_DEFAULT_COMPRESSION); | ||
1279 | SETINT("FILTERED", Z_FILTERED); | ||
1280 | SETINT("HUFFMAN_ONLY", Z_HUFFMAN_ONLY); | ||
1281 | SETINT("RLE", Z_RLE); | ||
1282 | SETINT("FIXED", Z_FIXED); | ||
1283 | SETINT("DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY); | ||
1284 | SETINT("MINIMUM_MEMLEVEL", 1); | ||
1285 | SETINT("MAXIMUM_MEMLEVEL", 9); | ||
1286 | SETINT("DEFAULT_MEMLEVEL", 8); | ||
1287 | SETINT("DEFAULT_WINDOWBITS", 15); | ||
1288 | SETINT("MINIMUM_WINDOWBITS", 8); | ||
1289 | SETINT("MAXIMUM_WINDOWBITS", 15); | ||
1290 | SETINT("GZIP_WINDOWBITS", 16); | ||
1291 | SETINT("RAW_WINDOWBITS", -1); | ||
1292 | #endif | ||
1293 | |||
1294 | return 1; | ||
1295 | } | ||