aboutsummaryrefslogtreecommitdiff
path: root/vendor/lua-zlib
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/lua-zlib')
-rw-r--r--vendor/lua-zlib/.gitattributes1
-rw-r--r--vendor/lua-zlib/README163
-rw-r--r--vendor/lua-zlib/lua-zlib-1.1-0.rockspec42
-rw-r--r--vendor/lua-zlib/lua_zlib.c1295
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
28To use this library, you need zlib, get it here:
29 http://www.gzip.org/zlib/
30
31To 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
37Loading 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
48int 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
53function 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
92function 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
122function compute_checksum = zlib.adler32()
123function 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
153NOTE: This library ships with an "lzlib" compatibility shim. However, the
154following 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
163To 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 @@
1package = "lua-zlib"
2version = "1.2-0"
3source = {
4 url = "git://github.com/brimworks/lua-zlib.git",
5 tag = "v1.2",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, <= 5.3"
20}
21external_dependencies = {
22 ZLIB = {
23 header = "zlib.h"
24 }
25}
26
27build = {
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
86typedef 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 */
112static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush);
113
114
115static 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
151static 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
168static 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
174static 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
184static 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
203static 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
211static 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
227static 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*/
246static 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*/
296static 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
346static 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*/
362static 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
402static 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*/
472static 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*/
481static 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*/
502static 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
513static 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
554static 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
569static 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
614static 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
633static 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
642static 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
692static 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
700static 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
714static 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
779static 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
844typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len);
845typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2);
846
847
848static int lz_deflate(lua_State *L);
849static int lz_deflate_delete(lua_State *L);
850static int lz_inflate_delete(lua_State *L);
851static int lz_inflate(lua_State *L);
852static int lz_checksum(lua_State *L);
853static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine);
854static int lz_adler32(lua_State *L);
855static int lz_crc32(lua_State *L);
856
857static 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
882static 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 */
927static 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
1030static 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
1039static 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
1073static int lz_deflate(lua_State *L) {
1074 return lz_filter_impl(L, deflate, deflateEnd, "deflate");
1075}
1076
1077static 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
1087static 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
1096static 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
1128static int lz_inflate(lua_State *L) {
1129 return lz_filter_impl(L, inflate, inflateEnd, "inflate");
1130}
1131
1132static 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
1141static 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
1193static 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
1202static 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
1222static 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
1243static 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
1259LUALIB_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}