8000 lua-zlib/lua_zlib.c at master · hishamhm/lua-zlib · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
1295 lines (1066 loc) · 37.8 KB

lua_zlib.c

File metadata and controls

1295 lines (1066 loc) · 37.8 KB
for(;;)
{
zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
zs.avail_out = LUAL_BUFFERSIZE;
/* munch some more */
ret = deflate(&zs, Z_FINISH);
/* push gathered data */
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
/* done processing? */
if (ret == Z_STREAM_END)
break;
/* error condition? */
if (ret != Z_OK)
break;
}
/* cleanup */
deflateEnd(&zs);
luaL_pushresult(&b);
lua_pushnumber(L, ret);
return 2;
}
/* ====================================================================== */
static int lzlib_decompress(lua_State *L)
{
size_t avail_in;
const char *next_in = luaL_checklstring(L, 1, &avail_in);
int windowBits = (int) luaL_optinteger(L, 2, 15);
int ret;
luaL_Buffer b;
z_stream zs;
luaL_buffinit(L, &b);
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.next_out = Z_NULL;
zs.avail_out = 0;
zs.next_in = Z_NULL;
zs.avail_in = 0;
ret = inflateInit2(&zs, windowBits);
if (ret != Z_OK) {
lua_pushliteral(L, "failed to initialize zstream structures");
lua_error(L);
}
zs.next_in = (unsigned char*)next_in;
zs.avail_in = avail_in;
for (;;) {
zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
zs.avail_out = LUAL_BUFFERSIZE;
/* bake some more */
ret = inflate(&zs, Z_FINISH);
/* push gathered data */
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
/* done processing? */
if (ret == Z_STREAM_END)
break;
if (ret != Z_OK && ret != Z_BUF_ERROR) {
/* cleanup */
inflateEnd(&zs);
lua_pushliteral(L, "failed to process zlib stream");
lua_error(L);
}
}
/* cleanup */
inflateEnd(&zs);
luaL_pushresult(&b);
return 1;
}
#endif
/**********************************************************************/
#define DEF_MEM_LEVEL 8
typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len);
typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2);
static int lz_deflate(lua_State *L);
static int lz_deflate_delete(lua_State *L);
static int lz_inflate_delete(lua_State *L);
static int lz_inflate(lua_State *L);
static int lz_checksum(lua_State *L);
static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine);
static int lz_adler32(lua_State *L);
static int lz_crc32(lua_State *L);
static int lz_version(lua_State *L) {
const char* version = zlibVersion();
int count = strlen(version) + 1;
char* cur = (char*)memcpy(lua_newuserdata(L, count),
version, count);
count = 0;
while ( *cur ) {
char* begin = cur;
/* Find all digits: */
while ( isdigit(*cur) ) cur++;
if ( begin != cur ) {
int is_end = *cur == '\0';
*cur = '\0';
lua_pushnumber(L, atoi(begin));
count++;
if ( is_end ) break;
cur++;
}
while ( *cur && ! isdigit(*cur) ) cur++;
}
return count;
}
static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) {
/* Both of these are "normal" return codes: */
if ( result == Z_OK || result == Z_STREAM_END ) return result;
switch ( result ) {
case Z_NEED_DICT:
lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d",
stream->msg, file, line);
break;
case Z_STREAM_ERROR:
lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d",
stream->msg, file, line);
break;
case Z_DATA_ERROR:
lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d",
file, line);
break;
case Z_MEM_ERROR:
lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d",
stream->msg, file, line);
break;
case Z_BUF_ERROR:
lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d",
stream->msg, file, line);
break;
case Z_VERSION_ERROR:
lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d",
ZLIB_VERSION, zlibVersion(), stream->msg, file, line);
break;
default:
lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d",
result, stream->msg, file, line);
}
lua_error(L);
return result;
}
/**
* @upvalue z_stream - Memory for the z_stream.
* @upvalue remainder - Any remainder from the last deflate call.
*
* @param string - "print" to deflate stream.
* @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH.
*
* if no params, terminates the stream (as if we got empty string and Z_FINISH).
*/
static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) {
int flush = Z_NO_FLUSH, result;
z_stream* stream;
luaL_Buffer buff;
size_t avail_in;
if ( filter == deflate ) {
const char *const opts[] = { "none", "sync", "full", "finish", NULL };
flush = luaL_checkoption(L, 2, opts[0], opts);
if ( flush ) flush++;
/* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */
/* No arguments or nil, we are terminating the stream: */
if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
flush = Z_FINISH;
}
}
stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
if ( stream == NULL ) {
if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
lua_error(L);
}
lua_pushstring(L, "");
lua_pushboolean(L, 1);
return 2; /* Ignore duplicate calls to "close". */
}
luaL_buffinit(L, &buff);
if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);
if ( lua_isstring(L, lua_upvalueindex(2)) ) {
lua_pushvalue(L, lua_upvalueindex(2));
if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
lua_concat(L, 2);
}
}
/* Do the actual deflate'ing: */
if (lua_gettop(L) > 0) {
stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in);
} else {
stream->next_in = NULL;
avail_in = 0;
}
stream->avail_in = avail_in;
if ( ! stream->avail_in && ! flush ) {
/* Passed empty string, make it a noop instead of erroring out. */
lua_pushstring(L, "");
lua_pushboolean(L, 0);
lua_pushinteger(L, stream->total_in);
lua_pushinteger(L, stream->total_out);
return 4;
}
do {
stream->next_out = (unsigned char*)luaL_prepbuffer(&buff);
stream->avail_out = LUAL_BUFFERSIZE;
result = filter(stream, flush);
if ( Z_BUF_ERROR != result ) {
/* Ignore Z_BUF_ERROR since that just indicates that we
* need a larger buffer in order to proceed. Thanks to
* Tobias Markmann for finding this bug!
*/
lz_assert(L, result, stream, __FILE__, __LINE__);
}
luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
} while ( stream->avail_out == 0 );
/* Need to do this before we alter the stack: */
luaL_pushresult(&buff);
0