Coverage Report

Created: 2026-02-04 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tarantool/third_party/lua-zlib/lua_zlib.c
Line
Count
Source
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
0
static int lz_version(lua_State *L) {
858
0
    const char* version = zlibVersion();
859
0
    int         count   = strlen(version) + 1;
860
0
    char*       cur     = (char*)memcpy(lua_newuserdata(L, count),
861
0
                                        version, count);
862
863
0
    count = 0;
864
0
    while ( *cur ) {
865
0
        char* begin = cur;
866
        /* Find all digits: */
867
0
        while ( isdigit(*cur) ) cur++;
868
0
        if ( begin != cur ) {
869
0
            int is_end = *cur == '\0';
870
0
            *cur = '\0';
871
0
            lua_pushnumber(L, atoi(begin));
872
0
            count++;
873
0
            if ( is_end ) break;
874
0
            cur++;
875
0
        }
876
0
        while ( *cur && ! isdigit(*cur) ) cur++;
877
0
    }
878
879
0
    return count;
880
0
}
881
882
0
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
0
    if ( result == Z_OK || result == Z_STREAM_END ) return result;
885
0
    switch ( result ) {
886
0
    case Z_NEED_DICT:
887
0
        lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d",
888
0
                        stream->msg, file, line);
889
0
        break;
890
0
    case Z_STREAM_ERROR:
891
0
        lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d",
892
0
                        stream->msg, file, line);
893
0
        break;
894
0
    case Z_DATA_ERROR:
895
0
        lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d",
896
0
                        file, line);
897
0
        break;
898
0
    case Z_MEM_ERROR:
899
0
        lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d",
900
0
                        stream->msg, file, line);
901
0
        break;
902
0
    case Z_BUF_ERROR:
903
0
        lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d",
904
0
                        stream->msg, file, line);
905
0
        break;
906
0
    case Z_VERSION_ERROR:
907
0
        lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d",
908
0
                        ZLIB_VERSION,  zlibVersion(), stream->msg, file, line);
909
0
        break;
910
0
    default:
911
0
        lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d",
912
0
                        result, stream->msg, file, line);
913
0
    }
914
0
    lua_error(L);
915
0
    return result;
916
0
}
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
0
static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) {
928
0
    int flush = Z_NO_FLUSH, result;
929
0
    z_stream* stream;
930
0
    luaL_Buffer buff;
931
0
    size_t avail_in;
932
933
0
    if ( filter == deflate ) {
934
0
        const char *const opts[] = { "none", "sync", "full", "finish", NULL };
935
0
        flush = luaL_checkoption(L, 2, opts[0], opts);
936
0
        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
0
        if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
941
0
            flush = Z_FINISH;
942
0
        }
943
0
    }
944
945
0
    stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
946
0
    if ( stream == NULL ) {
947
0
        if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
948
0
            lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
949
0
            lua_error(L);
950
0
        }
951
0
        lua_pushstring(L, "");
952
0
        lua_pushboolean(L, 1);
953
0
        return 2; /* Ignore duplicate calls to "close". */
954
0
    }
955
956
0
    luaL_buffinit(L, &buff);
957
958
0
    if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);
959
960
0
    if ( lua_isstring(L, lua_upvalueindex(2)) ) {
961
0
        lua_pushvalue(L, lua_upvalueindex(2));
962
0
        if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
963
0
            lua_concat(L, 2);
964
0
        }
965
0
    }
966
967
    /*  Do the actual deflate'ing: */
968
0
    if (lua_gettop(L) > 0) {
969
0
        stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in);
970
0
    } else {
971
0
        stream->next_in = NULL;
972
0
        avail_in = 0;
973
0
    }
974
0
    stream->avail_in = avail_in;
975
976
0
    if ( ! stream->avail_in && ! flush ) {
977
        /*  Passed empty string, make it a noop instead of erroring out. */
978
0
        lua_pushstring(L, "");
979
0
        lua_pushboolean(L, 0);
980
0
        lua_pushinteger(L, stream->total_in);
981
0
        lua_pushinteger(L, stream->total_out);
982
0
        return 4;
983
0
    }
984
985
0
    do {
986
0
        stream->next_out  = (unsigned char*)luaL_prepbuffer(&buff);
987
0
        stream->avail_out = LUAL_BUFFERSIZE;
988
0
        result = filter(stream, flush);
989
0
        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
0
            lz_assert(L, result, stream, __FILE__, __LINE__);
995
0
        }
996
0
        luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
997
0
    } while ( stream->avail_out == 0 );
998
999
    /*  Need to do this before we alter the stack: */
1000
0
    luaL_pushresult(&buff);
1001
1002
    /*  Save remainder in lua_upvalueindex(2): */
1003
0
    if ( NULL != stream->next_in ) {
1004
0
        lua_pushlstring(L, (char*)stream->next_in, stream->avail_in);
1005
0
        lua_replace(L, lua_upvalueindex(2));
1006
0
    }
1007
1008
    /*  "close" the stream/remove finalizer: */
1009
0
    if ( result == Z_STREAM_END ) {
1010
        /*  Clear-out the metatable so end is not called twice: */
1011
0
        lua_pushnil(L);
1012
0
        lua_setmetatable(L, lua_upvalueindex(1));
1013
1014
        /*  nil the upvalue: */
1015
0
        lua_pushnil(L);
1016
0
        lua_replace(L, lua_upvalueindex(1));
1017
1018
        /*  Close the stream: */
1019
0
        lz_assert(L, end(stream), stream, __FILE__, __LINE__);
1020
1021
0
        lua_pushboolean(L, 1);
1022
0
    } else {
1023
0
        lua_pushboolean(L, 0);
1024
0
    }
1025
0
    lua_pushinteger(L, stream->total_in);
1026
0
    lua_pushinteger(L, stream->total_out);
1027
0
    return 4;
1028
0
}
1029
1030
0
static void lz_create_deflate_mt(lua_State *L) {
1031
0
    luaL_newmetatable(L, "lz.deflate.meta"); /*  {} */
1032
1033
0
    lua_pushcfunction(L, lz_deflate_delete);
1034
0
    lua_setfield(L, -2, "__gc");
1035
1036
0
    lua_pop(L, 1); /*  <empty> */
1037
0
}
1038
1039
0
static int lz_deflate_new(lua_State *L) {
1040
0
    int level;
1041
0
    int window_size;
1042
0
    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
0
    level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
1051
0
    window_size = luaL_optint(L, 2, MAX_WBITS);
1052
1053
    /*  Allocate the stream: */
1054
0
    z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1055
1056
0
    stream->zalloc = Z_NULL;
1057
0
    stream->zfree  = Z_NULL;
1058
1059
0
    result = deflateInit2(stream, level, Z_DEFLATED, window_size,
1060
0
                              DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
1061
1062
0
    lz_assert(L, result, stream, __FILE__, __LINE__);
1063
1064
    /*  Don't allow destructor to execute unless deflateInit2 was successful: */
1065
0
    luaL_getmetatable(L, "lz.deflate.meta");
1066
0
    lua_setmetatable(L, -2);
1067
1068
0
    lua_pushnil(L);
1069
0
    lua_pushcclosure(L, lz_deflate, 2);
1070
0
    return 1;
1071
0
}
1072
1073
0
static int lz_deflate(lua_State *L) {
1074
0
    return lz_filter_impl(L, deflate, deflateEnd, "deflate");
1075
0
}
1076
1077
0
static int lz_deflate_delete(lua_State *L) {
1078
0
    z_stream* stream  = (z_stream*)lua_touserdata(L, 1);
1079
1080
    /*  Ignore errors. */
1081
0
    deflateEnd(stream);
1082
1083
0
    return 0;
1084
0
}
1085
1086
1087
0
static void lz_create_inflate_mt(lua_State *L) {
1088
0
    luaL_newmetatable(L, "lz.inflate.meta"); /*  {} */
1089
1090
0
    lua_pushcfunction(L, lz_inflate_delete);
1091
0
    lua_setfield(L, -2, "__gc");
1092
1093
0
    lua_pop(L, 1); /*  <empty> */
1094
0
}
1095
1096
0
static int lz_inflate_new(lua_State *L) {
1097
    /* Allocate the stream */
1098
0
    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
0
    stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1108
1109
    /*  By default, we will do gzip header detection w/ max window size */
1110
0
    int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32;
1111
1112
0
    stream->zalloc   = Z_NULL;
1113
0
    stream->zfree    = Z_NULL;
1114
0
    stream->next_in  = Z_NULL;
1115
0
    stream->avail_in = 0;
1116
1117
0
    lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__);
1118
1119
    /*  Don't allow destructor to execute unless deflateInit was successful: */
1120
0
    luaL_getmetatable(L, "lz.inflate.meta");
1121
0
    lua_setmetatable(L, -2);
1122
1123
0
    lua_pushnil(L);
1124
0
    lua_pushcclosure(L, lz_inflate, 2);
1125
0
    return 1;
1126
0
}
1127
1128
0
static int lz_inflate(lua_State *L) {
1129
0
    return lz_filter_impl(L, inflate, inflateEnd, "inflate");
1130
0
}
1131
1132
0
static int lz_inflate_delete(lua_State *L) {
1133
0
    z_stream* stream  = (z_stream*)lua_touserdata(L, 1);
1134
1135
    /*  Ignore errors: */
1136
0
    inflateEnd(stream);
1137
1138
0
    return 0;
1139
0
}
1140
1141
0
static int lz_checksum(lua_State *L) {
1142
0
    if ( lua_gettop(L) <= 0 ) {
1143
0
        lua_pushvalue(L, lua_upvalueindex(3));
1144
0
        lua_pushvalue(L, lua_upvalueindex(4));
1145
0
    } else if ( lua_isfunction(L, 1) ) {
1146
0
        checksum_combine_t combine = (checksum_combine_t)
1147
0
            lua_touserdata(L, lua_upvalueindex(2));
1148
1149
0
        lua_pushvalue(L, 1);
1150
0
        lua_call(L, 0, 2);
1151
0
        if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) {
1152
0
            luaL_argerror(L, 1, "expected function to return two numbers");
1153
0
        }
1154
1155
        /* Calculate and replace the checksum */
1156
0
        lua_pushnumber(L,
1157
0
                       combine((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1158
0
                               (uLong)lua_tonumber(L, -2),
1159
0
                               (z_off_t)lua_tonumber(L, -1)));
1160
0
        lua_pushvalue(L, -1);
1161
0
        lua_replace(L, lua_upvalueindex(3));
1162
1163
        /* Calculate and replace the length */
1164
0
        lua_pushnumber(L,
1165
0
                       lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2));
1166
0
        lua_pushvalue(L, -1);
1167
0
        lua_replace(L, lua_upvalueindex(4));
1168
0
    } else {
1169
0
        const Bytef* str;
1170
0
        size_t       len;
1171
1172
0
        checksum_t checksum = (checksum_t)
1173
0
            lua_touserdata(L, lua_upvalueindex(1));
1174
0
        str = (const Bytef*)luaL_checklstring(L, 1, &len);
1175
 
1176
        /* Calculate and replace the checksum */
1177
0
        lua_pushnumber(L,
1178
0
                       checksum((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1179
0
                                str,
1180
0
                                len));
1181
0
        lua_pushvalue(L, -1);
1182
0
        lua_replace(L, lua_upvalueindex(3));
1183
        
1184
        /* Calculate and replace the length */
1185
0
        lua_pushnumber(L,
1186
0
                       lua_tonumber(L, lua_upvalueindex(4)) + len);
1187
0
        lua_pushvalue(L, -1);
1188
0
        lua_replace(L, lua_upvalueindex(4));
1189
0
    }
1190
0
    return 2;
1191
0
}
1192
1193
0
static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) {
1194
0
    lua_pushlightuserdata(L, checksum);
1195
0
    lua_pushlightuserdata(L, combine);
1196
0
    lua_pushnumber(L, checksum(0L, Z_NULL, 0));
1197
0
    lua_pushnumber(L, 0);
1198
0
    lua_pushcclosure(L, lz_checksum, 4);
1199
0
    return 1;
1200
0
}
1201
1202
0
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
0
    return lz_checksum_new(L, adler32, adler32_combine);
1220
0
}
1221
1222
0
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
0
    return lz_checksum_new(L, crc32, crc32_combine);
1240
0
}
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
0
#define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3))
1257
0
#define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3))
1258
1259
0
LUALIB_API int luaopen_zlib(lua_State * const L) {
1260
0
    lz_create_deflate_mt(L);
1261
0
    lz_create_inflate_mt(L);
1262
1263
0
    luaL_register(L, "zlib", zlib_functions);
1264
1265
0
    SETINT("BEST_SPEED", Z_BEST_SPEED);
1266
0
    SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION);
1267
1268
0
    SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2016 Brian Maher");
1269
0
    SETLITERAL("_DESCRIPTION", "Simple streaming interface to the zlib library");
1270
0
    SETLITERAL("_VERSION", "lua-zlib $Id: 9dc7bcd71c3994bc4c8e9dc86e5beaca440de17f $");
1271
1272
    /* Expose this to lua so we can do a test: */
1273
0
    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
0
    return 1;
1295
0
}