Permalink
Browse files

zlib binding added, with stream interface

  • Loading branch information...
1 parent cbec0fe commit ef58a0d21bf7f07f0d7f1071c1a343c6129aa032 @dvv dvv committed Mar 14, 2012
Showing with 341 additions and 1 deletion.
  1. +12 −1 Makefile
  2. +2 −0 lib/luvit/luvit.lua
  3. +61 −0 lib/luvit/zlib.lua
  4. +156 −0 src/luv_zlib.c
  5. +28 −0 src/luv_zlib.h
  6. +7 −0 src/luvit_init.c
  7. BIN tests/fixtures/test.gz
  8. +75 −0 tests/test-zlib.lua
View
@@ -7,6 +7,7 @@ UVDIR=deps/uv
UV_VERSION=$(shell git --git-dir ${UVDIR}/.git describe --all --long | cut -f 3 -d -)
HTTPDIR=deps/http-parser
HTTP_VERSION=$(shell git --git-dir ${HTTPDIR}/.git describe --tags)
+ZLIBDIR=deps/zlib
SSLDIR=deps/openssl
BUILDDIR=build
@@ -54,6 +55,7 @@ else
CFLAGS+=-I${SSLDIR}/openssl/include
LDFLAGS+=${SSLDIR}/libopenssl.a
endif
+LDFLAGS+=${ZLIBDIR}/libz.a
LDFLAGS+=-Wall -lm -ldl -lpthread
ifeq (${OS_NAME},Linux)
@@ -109,11 +111,13 @@ LUVLIBS=${BUILDDIR}/utils.o \
${BUILDDIR}/lenv.o \
${BUILDDIR}/lyajl.o \
${BUILDDIR}/los.o \
+ ${BUILDDIR}/luv_zlib.o \
${BUILDDIR}/lhttp_parser.o
DEPS=${LUADIR}/src/libluajit.a \
${YAJLDIR}/yajl.a \
${UVDIR}/uv.a \
+ ${ZLIBDIR}/libz.a \
${HTTPDIR}/http_parser.o
ifeq (${USE_SYSTEM_SSL},0)
@@ -152,6 +156,13 @@ ${HTTPDIR}/Makefile:
${HTTPDIR}/http_parser.o: ${HTTPDIR}/Makefile
$(MAKE) -C ${HTTPDIR} http_parser.o
+${ZLIBDIR}/Makefile:
+ git submodule update --init ${ZLIBDIR}
+
+${ZLIBDIR}/libz.a: ${ZLIBDIR}/Makefile
+ ( cd ${ZLIBDIR} ; ./configure )
+ $(MAKE) -C ${ZLIBDIR}
+
${SSLDIR}/Makefile.openssl:
git submodule update --init ${SSLDIR}
@@ -161,7 +172,7 @@ ${SSLDIR}/libopenssl.a: ${SSLDIR}/Makefile.openssl
${BUILDDIR}/%.o: src/%.c ${DEPS}
mkdir -p ${BUILDDIR}
$(CC) ${CFLAGS} --std=c89 -D_GNU_SOURCE -g -Wall -Werror -c $< -o $@ \
- -I${HTTPDIR} -I${UVDIR}/include -I${LUADIR}/src -I${YAJLDIR}/src/api -I${YAJLDIR}/src \
+ -I${HTTPDIR} -I${UVDIR}/include -I${LUADIR}/src -I${YAJLDIR}/src/api -I${YAJLDIR}/src -I${ZLIBDIR} \
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \
-DUSE_SYSTEM_SSL=${USE_SYSTEM_SSL} \
-DHTTP_VERSION=\"${HTTP_VERSION}\" \
View
@@ -65,6 +65,7 @@ process.versions = {
uv = native.VERSION_MAJOR .. "." .. native.VERSION_MINOR .. "-" .. UV_VERSION,
luajit = LUAJIT_VERSION,
yajl = YAJL_VERSION,
+ zlib = ZLIB_VERSION,
http_parser = HTTP_VERSION,
openssl = OPENSSL_VERSION,
}
@@ -73,6 +74,7 @@ _G.YAJL_VERSION = nil
_G.LUAJIT_VERSION = nil
_G.UV_VERSION = nil
_G.HTTP_VERSION = nil
+_G.ZLIB_VERSION = nil
_G.OPENSSL_VERSION = nil
-- Add a way to exit programs cleanly
View
@@ -0,0 +1,61 @@
+--[[
+
+Copyright 2012 The Luvit Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS-IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+--]]
+
+local binding = require('zlib_native')
+
+--
+-- generic zlib stream
+--
+
+local Zlib = require('core').iStream:extend()
+
+function Zlib:initialize(what, ...)
+ self.zlib = binding.new(what, ...)
+end
+
+function Zlib:write(chunk, flag)
+ if not flag then
+ flag = chunk == nil and 'finish' or nil
+ end
+ local text, err = self.zlib:write(chunk, flag)
+ if not text then
+ self:emit('error', err)
+ else
+ if #text > 0 then
+ self:emit('data', text)
+ end
+ self:emit('drain')
+ end
+end
+
+function Zlib:done()
+ self.zlib = nil
+ self:emit('end')
+end
+
+function Zlib:close()
+ self.zlib = nil
+end
+
+--
+-- module
+--
+
+return {
+ Zlib = Zlib,
+}
View
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012 The Luvit Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "zlib.h"
+
+#include <lauxlib.h>
+#include <lua.h>
+
+typedef struct {
+ z_stream stream;
+ int (*filter)(z_stream *, int);
+ int (*end)(z_stream *);
+} z_t;
+
+static const char *methods[] = {
+ "inflate", "deflate", NULL
+};
+
+static const char *flush_opts[] = {
+ "none", "sync", "full", "finish", NULL
+};
+
+static int lz_stream_write(lua_State *L) {
+
+ z_t *z;
+ int flush;
+ int rc;
+ luaL_Buffer buff;
+
+ lua_getfield(L, 1, "stream");
+ z = (z_t *)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ z->stream.next_in = (uint8_t *)luaL_checklstring(L, 2, &z->stream.avail_in);
+
+ flush = luaL_checkoption(L, 3, flush_opts[3], flush_opts);
+ if (flush) flush++;
+
+ luaL_buffinit(L, &buff);
+ while (z->stream.avail_in) {
+ z->stream.next_out = (uint8_t *)luaL_prepbuffer(&buff);
+ z->stream.avail_out = LUAL_BUFFERSIZE;
+ rc = z->filter(&z->stream, flush);
+ if (rc != Z_BUF_ERROR) {
+ if (rc != Z_OK && rc != Z_STREAM_END) {
+ break;
+ }
+ }
+ luaL_addsize(&buff, LUAL_BUFFERSIZE - z->stream.avail_out);
+ }
+ luaL_pushresult(&buff);
+
+ /*if (rc == Z_STREAM_END) {
+ rc = z->end(&z->stream);
+ }*/
+ if (rc == Z_STREAM_END || rc == Z_BUF_ERROR || rc == Z_OK) {
+ return 1;
+ }
+ lua_pushnil(L);
+ lua_pushinteger(L, rc);
+ return 2;
+}
+
+static int lz_stream_delete(lua_State *L) {
+ lua_getfield(L, -1, "stream");
+ z_t *z = (z_t *)lua_touserdata(L, -1);
+ lua_pop(L, 2);
+ z->end(&z->stream);
+ free(z);
+ return 0;
+}
+
+static int lz_stream_new(lua_State *L) {
+
+ z_t *z = (z_t *)malloc(sizeof(*z));
+ memset(z, 0, sizeof(*z));
+
+ int method = luaL_checkoption(L, 1, NULL, methods);
+ if (method == 0) {
+ int window_size = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : MAX_WBITS + 32;
+ int rc = inflateInit2(&z->stream, window_size);
+ if (rc != Z_OK && rc != Z_STREAM_END) {
+ return luaL_error(L, "inflateInit2: %d", rc);
+ }
+ z->filter = inflate;
+ z->end = inflateEnd;
+ } else if (method == 1) {
+ int level = luaL_optint(L, 2, Z_DEFAULT_COMPRESSION);
+ int rc = deflateInit(&z->stream, level);
+ if (rc != Z_OK && rc != Z_STREAM_END) {
+ return luaL_error(L, "deflateInit: %d", rc);
+ }
+ z->filter = deflate;
+ z->end = deflateEnd;
+ } else {
+ return luaL_error(L, "zlib: unsupported method: %s", method);
+ }
+
+ lua_newtable(L);
+ luaL_getmetatable(L, "luv_zlib");
+ lua_setmetatable(L, -2);
+ lua_pushlightuserdata(L, z);
+ lua_setfield(L, -2, "stream");
+ lua_pushstring(L, methods[method]);
+ lua_setfield(L, -2, "method");
+
+ return 1;
+}
+
+static const luaL_Reg exports[] = {
+ { "new", lz_stream_new },
+ { NULL, NULL }
+};
+
+LUALIB_API int luaopen_zlib_native(lua_State *L) {
+
+ /* zlib stream metatable */
+ luaL_newmetatable(L, "luv_zlib");
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ lua_pushcfunction(L, lz_stream_delete);
+ lua_setfield(L, -2, "__gc");
+ lua_pushcfunction(L, lz_stream_write);
+ lua_setfield(L, -2, "write");
+ lua_pop(L, 1);
+
+ /* module table */
+ lua_newtable(L);
+
+ /* constants */
+ lua_pushstring(L, ZLIB_VERSION);
+ lua_setfield(L, -2, "version");
+
+ luaL_register(L, NULL, exports);
+
+ return 1;
+}
View
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 The Luvit Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef LUV_ZLIB
+#define LUV_ZLIB
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "zlib.h"
+
+LUALIB_API int luaopen_zlib_native(lua_State *L);
+
+#endif
View
@@ -33,6 +33,7 @@
#ifdef USE_OPENSSL
#include "luv_tls.h"
#endif
+#include "luv_zlib.h"
#include "luv_portability.h"
#include "lconstants.h"
#include "lhttp_parser.h"
@@ -188,6 +189,9 @@ int luvit_init(lua_State *L, uv_loop_t* loop, int argc, char *argv[])
/* Register constants */
lua_pushcfunction(L, luaopen_constants);
lua_setfield(L, -2, "constants");
+ /* Register zlib */
+ lua_pushcfunction(L, luaopen_zlib_native);
+ lua_setfield(L, -2, "zlib_native");
/* We're done with preload, put it away */
lua_pop(L, 1);
@@ -224,6 +228,9 @@ int luvit_init(lua_State *L, uv_loop_t* loop, int argc, char *argv[])
lua_pushstring(L, YAJL_VERSIONISH);
lua_setglobal(L, "YAJL_VERSION");
+ lua_pushstring(L, ZLIB_VERSION);
+ lua_setglobal(L, "ZLIB_VERSION");
+
#ifdef USE_OPENSSL
lua_pushstring(L, OPENSSL_VERSION_TEXT);
lua_setglobal(L, "OPENSSL_VERSION");
View
Binary file not shown.
Oops, something went wrong.

2 comments on commit ef58a0d

@zx9597446

luv_zlib.c(85)
z_t *z = (z_t *)lua_touserdata(L, -1);
couldn't compile with msvc2010, error:
2>src\luv_zlib.c(85): error C2275: 'z_t' : illegal use of this type as an expression
2> src\luv_zlib.c(32) : see declaration of 'z_t'

@dvv
Member
dvv commented on ef58a0d Mar 20, 2012

sorry, have no windows at all. consider sharing a fix?

Please sign in to comment.