1
/************************************************************************
2
* Author : Tiago Dionizio (tngd@mega.ist.utl.pt) *
3
* Library : lzlib - Lua 5 interface to access zlib library functions *
5
* Permission is hereby granted, free of charge, to any person obtaining *
6
* a copy of this software and associated documentation files (the *
7
* "Software"), to deal in the Software without restriction, including *
8
* without limitation the rights to use, copy, modify, merge, publish, *
9
* distribute, sublicense, and/or sell copies of the Software, and to *
10
* permit persons to whom the Software is furnished to do so, subject to *
11
* the following conditions: *
13
* The above copyright notice and this permission notice shall be *
14
* included in all copies or substantial portions of the Software. *
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
17
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
19
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
20
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
21
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
22
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23
************************************************************************/
25
/************************************************************************
26
$Id: lzlib.c,v 1.3 2004/07/22 19:10:47 tngd Exp $
28
************************************************************************/
39
** =========================================================================
40
** compile time options wich determine available functionality
41
** =========================================================================
46
** =========================================================================
47
** zlib stream metamethods
48
** =========================================================================
50
#define ZSTREAMMETA "zlib:zstream"
52
#define LZANY (void*)-1
53
#define LZNONE (void*)0
54
#define LZDEFLATE (void*)1
55
#define LZINFLATE (void*)2
57
static z_stream *lzstream_new(lua_State *L)
59
z_stream *s = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
61
luaL_getmetatable(L, ZSTREAMMETA);
62
lua_setmetatable(L, -2); /* set metatable */
77
static void lzstream_cleanup(lua_State *L, z_stream *s)
79
if (s && s->opaque != LZNONE)
81
if (s->opaque == LZINFLATE)
83
if (s->opaque == LZDEFLATE)
89
/* ====================================================================== */
91
static z_stream *lzstream_get(lua_State *L, int index)
93
z_stream *s = (z_stream*)luaL_checkudata(L, index, ZSTREAMMETA);
94
if (s == NULL) luaL_argerror(L, index, "bad zlib stream");
98
static z_stream *lzstream_check(lua_State *L, int index, void *state)
100
z_stream *s = lzstream_get(L, index);
101
if ((state != LZANY && s->opaque != state) || s->opaque == LZNONE)
102
luaL_argerror(L, index, "attempt to use invalid zlib stream");
106
/* ====================================================================== */
108
static int lzstream_tostring(lua_State *L)
111
z_stream *s = (z_stream*)luaL_checkudata(L, 1, ZSTREAMMETA);
112
if (s == NULL) luaL_argerror(L, 1, "bad zlib stream");
114
if (s->opaque == LZNONE)
115
strncpy(buf, "zlib stream (closed)", 100);
116
else if (s->opaque == LZDEFLATE)
117
snprintf(buf, 100, "zlib deflate stream (%p)", s);
118
else if (s->opaque == LZINFLATE)
119
snprintf(buf, 100, "zlib inflate stream (%p)", s);
121
snprintf(buf, 100, "%p", s);
123
lua_pushstring(L, buf);
127
/* ====================================================================== */
129
static int lzstream_gc(lua_State *L)
131
z_stream *s = lzstream_get(L, 1);
132
lzstream_cleanup(L, s);
136
/* ====================================================================== */
138
static int lzstream_close(lua_State *L)
140
z_stream *s = lzstream_check(L, 1, LZANY);
141
lzstream_cleanup(L, s);
145
/* ====================================================================== */
147
static int lzstream_adler(lua_State *L)
149
z_stream *s = lzstream_check(L, 1, LZANY);
150
lua_pushnumber(L, s->adler);
154
/* ====================================================================== */
156
static int lzlib_deflate(lua_State *L)
158
int level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
159
int method = luaL_optint(L, 2, Z_DEFLATED);
160
int windowBits = luaL_optint(L, 3, 15);
161
int memLevel = luaL_optint(L, 4, 8);
162
int strategy = luaL_optint(L, 5, Z_DEFAULT_STRATEGY);
164
z_stream *s = lzstream_new(L);
166
if (deflateInit2(s, level, method, windowBits, memLevel, strategy) != Z_OK)
168
lua_pushliteral(L, "failed to start decompressing");
171
s->opaque = LZDEFLATE;
175
/* ====================================================================== */
177
static int lzlib_inflate(lua_State *L)
179
int windowBits = luaL_optint(L, 1, 15);
181
z_stream *s = lzstream_new(L);
183
if (inflateInit2(s, windowBits) != Z_OK)
185
lua_pushliteral(L, "failed to start compressing");
189
s->opaque = LZINFLATE;
193
/* ====================================================================== */
195
static int lzstream_decompress(lua_State *L)
197
z_stream *s = lzstream_check(L, 1, LZINFLATE);
198
s->next_in = (char*)luaL_checkstring(L, 2);
199
s->avail_in = lua_strlen(L, 2);
203
luaL_buffinit(L, &b);
207
s->next_out = luaL_prepbuffer(&b);
208
s->avail_out = LUAL_BUFFERSIZE;
210
/* munch some more */
211
r = inflate(s, Z_SYNC_FLUSH);
212
if (r != Z_OK && r != Z_STREAM_END) {
213
lua_pushfstring(L, "failed to decompress [%d]", r);
217
/* push gathered data */
218
luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
220
/* until we have free space in the output buffer - meaning we are done */
221
} while (s->avail_in > 0 || s->avail_out == 0);
223
/* send gathered data if any */
229
/* ====================================================================== */
231
static int lzstream_compress(lua_State *L)
233
z_stream *s = lzstream_check(L, 1, LZDEFLATE);
234
s->next_in = (char*)luaL_checkstring(L, 2);
235
s->avail_in = lua_strlen(L, 2);
239
luaL_buffinit(L, &b);
243
s->next_out = luaL_prepbuffer(&b);
244
s->avail_out = LUAL_BUFFERSIZE;
247
if ((r = deflate(s, Z_NO_FLUSH)) != Z_OK)
249
lua_pushfstring(L, "failed to compress [%d]", r);
253
/* push gathered data */
254
luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
256
/* until we have free space in the output buffer - meaning we are done */
257
} while (s->avail_out == 0);
259
/* send gathered data if any */
265
/* ====================================================================== */
267
static int lzstream_flush(lua_State *L)
269
z_stream *s = lzstream_check(L, 1, LZANY);
271
if (s->opaque == LZINFLATE) {
272
lua_pushliteral(L, "");
282
luaL_buffinit(L, &b);
285
s->next_out = luaL_prepbuffer(&b);
286
s->avail_out = LUAL_BUFFERSIZE;
288
r = deflate(s, Z_FINISH);
290
if (r != Z_OK && r != Z_STREAM_END) {
291
lua_pushfstring(L, "failed to flush [%d]", r);
295
/* push gathered data */
296
luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
297
} while (r != Z_STREAM_END);
299
/* send gathered data if any */
305
/* ====================================================================== */
307
static int lzstream_reset(lua_State *L)
309
z_stream *s = lzstream_check(L, 1, LZANY);
311
if (s->state == LZDEFLATE)
312
lua_pushnumber(L, deflateReset(s));
313
else if (s->opaque == LZINFLATE)
314
lua_pushnumber(L, inflateReset(s));
317
lua_pushliteral(L, "invalid zlib stream state");
326
** =========================================================================
328
** =========================================================================
331
static int lzlib_version(lua_State *L)
333
lua_pushstring(L, zlibVersion());
337
/* ====================================================================== */
338
static int lzlib_adler32(lua_State *L)
340
if (lua_gettop(L) == 0)
342
/* adler32 initial value */
343
lua_pushnumber(L, adler32(0L, Z_NULL, 0));
347
/* update adler32 checksum */
348
int adler = luaL_checkint(L, 1);
349
const char* buf = luaL_checkstring(L, 2);
350
int len = lua_strlen(L, 2);
352
lua_pushnumber(L, adler32(adler, buf, len));
357
/* ====================================================================== */
358
static int lzlib_crc32(lua_State *L)
360
if (lua_gettop(L) == 0)
362
/* crc32 initial value */
363
lua_pushnumber(L, crc32(0L, Z_NULL, 0));
367
/* update crc32 checksum */
368
int crc = luaL_checkint(L, 1);
369
const char* buf = luaL_checkstring(L, 2);
370
int len = lua_strlen(L, 2);
372
lua_pushnumber(L, crc32(crc, buf, len));
377
/* ====================================================================== */
380
static int lzlib_compress(lua_State *L)
382
const char *next_in = luaL_checkstring(L, 1);
383
int avail_in = lua_strlen(L, 1);
384
int level = luaL_optint(L, 2, Z_DEFAULT_COMPRESSION);
385
int method = luaL_optint(L, 3, Z_DEFLATED);
386
int windowBits = luaL_optint(L, 4, 15);
387
int memLevel = luaL_optint(L, 5, 8);
388
int strategy = luaL_optint(L, 6, Z_DEFAULT_STRATEGY);
392
luaL_buffinit(L, &b);
399
zs.next_out = Z_NULL;
404
ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy);
409
lua_pushnumber(L, ret);
413
zs.next_in = (char*)next_in;
414
zs.avail_in = avail_in;
418
zs.next_out = luaL_prepbuffer(&b);
419
zs.avail_out = LUAL_BUFFERSIZE;
421
/* munch some more */
422
ret = deflate(&zs, Z_FINISH);
424
/* push gathered data */
425
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
427
/* done processing? */
428
if (ret == Z_STREAM_END)
431
/* error condition? */
440
lua_pushnumber(L, ret);
444
/* ====================================================================== */
446
static int lzlib_decompress(lua_State *L)
448
const char *next_in = luaL_checkstring(L, 1);
449
int avail_in = lua_strlen(L, 1);
450
int windowBits = luaL_optint(L, 2, 15);
454
luaL_buffinit(L, &b);
461
zs.next_out = Z_NULL;
466
ret = inflateInit2(&zs, windowBits);
471
lua_pushnumber(L, ret);
475
zs.next_in = (char*)next_in;
476
zs.avail_in = avail_in;
480
zs.next_out = luaL_prepbuffer(&b);
481
zs.avail_out = LUAL_BUFFERSIZE;
484
ret = inflate(&zs, Z_FINISH);
486
/* push gathered data */
487
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
489
/* need dictionary? - no dictionary support here, so just quit */
490
if (ret == Z_NEED_DICT)
493
/* done processing? */
494
if (ret == Z_STREAM_END)
497
/* error condition? */
498
if (ret != Z_BUF_ERROR)
506
lua_pushnumber(L, ret);
512
** =========================================================================
513
** Register functions
514
** =========================================================================
518
LUALIB_API int luaopen_zlib(lua_State *L)
520
const luaL_reg zstreamm[] =
522
{"reset", lzstream_reset },
524
{"compress", lzstream_compress },
525
{"decompress", lzstream_decompress },
526
{"flush", lzstream_flush },
527
{"close", lzstream_close },
529
{"adler", lzstream_adler },
531
{"__tostring", lzstream_tostring },
532
{"__gc", lzstream_gc },
536
const luaL_reg zlib[] =
538
{"version", lzlib_version },
539
{"adler32", lzlib_adler32 },
540
{"crc32", lzlib_crc32 },
542
{"compressobj", lzlib_deflate },
543
{"decompressobj", lzlib_inflate },
545
{"compress", lzlib_compress },
546
{"decompress", lzlib_decompress },
551
/* ====================================================================== */
553
/* make sure header and library version are consistent */
554
const char* version = zlibVersion();
555
if (strncmp(version, ZLIB_VERSION, 5))
557
lua_pushfstring(L, "zlib library version does not match - header: %s, library: %s", ZLIB_VERSION, version);
561
/* create new metatable for zlib compression structures */
562
luaL_newmetatable(L, ZSTREAMMETA);
563
lua_pushliteral(L, "__index");
564
lua_pushvalue(L, -2); /* push metatable */
565
lua_rawset(L, -3); /* metatable.__index = metatable */
570
luaL_openlib(L, NULL, zstreamm, 0);
572
lua_pop(L, 1); /* remove metatable from stack */
578
luaL_openlib(L, NULL, zlib, 0);