Skip to content

Commit

Permalink
strdup for *string; length() method instead of strlen(); throwexcepti…
Browse files Browse the repository at this point in the history
…on(); z_stream wrapper;
  • Loading branch information
okertanov committed Mar 30, 2011
1 parent b2cee83 commit 5dba170
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 45 deletions.
93 changes: 48 additions & 45 deletions src/compress-buffer.cc
Expand Up @@ -8,46 +8,48 @@
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "zlib.h"
#ifdef __APPLE__
#include <malloc/malloc.h>
#endif
#include <zlib.h>
#include "czstream.h"

// we don't compress less than that. Actually, zlib refuses to compress less than 18 bytes, but 32 looks
// like a better number :)
#define MIN_BYTES 32

z_stream strmCompress;
z_stream strmUncompress;
zstream::CZStream<z_stream> strmCompress;
zstream::CZStream<z_stream> strmUncompress;

// FIXME make uncompress cyclic so it eats not so much memory

using namespace v8;
using namespace node;

Handle<Value> ThrowNodeError(const char* what = NULL)
{
return ThrowException(Exception::Error(String::New(what)));
}

Handle<Value> compress(const Arguments& args) {
HandleScope scope;
size_t bytesIn=0;
size_t bytesCompressed=0;
char *dataPointer=NULL;
int shouldFreeDataPointer=0;

if (args.Length() < 1) {
return Undefined();
}

if (args[0]->IsString()) {
String::AsciiValue string(args[0]->ToString());
bytesIn = strlen(*string);
bytesIn = string.length();

if (bytesIn<=MIN_BYTES) {
return scope.Close(args[0]);
}

// FIXME why do I have to copy data, why just this doesn't work: dataPointer = (char *) *string ?
dataPointer = (char*)malloc(bytesIn);
strncpy(dataPointer, *string, bytesIn);
shouldFreeDataPointer=1;
dataPointer = strdup(*string);

} else if (Buffer::HasInstance(args[0])) {
Local<Object> bufferIn=args[0]->ToObject();
Expand All @@ -60,39 +62,40 @@ Handle<Value> compress(const Arguments& args) {
dataPointer=Buffer::Data(bufferIn);
}

int compressionLevel = Z_DEFAULT_COMPRESSION;
int compressionLevel = czstream::compression;
if (args.Length() > 1) {
compressionLevel = args[1]->IntegerValue();
if (compressionLevel <= 0 || compressionLevel > 9) {
compressionLevel = Z_DEFAULT_COMPRESSION;
compressionLevel = czstream::compression;
}
}

deflateParams(&strmCompress, compressionLevel, Z_DEFAULT_STRATEGY);
z_streamp stream = strmCompress;
deflateParams(stream, compressionLevel, czstream::strategy);

bytesCompressed=compressBound(bytesIn);
char *bufferOut=(char*) malloc(bytesCompressed);

strmCompress.next_in=(Bytef*) dataPointer;
strmCompress.avail_in=bytesIn;
strmCompress.next_out=(Bytef*) bufferOut;
strmCompress.avail_out=bytesCompressed;
stream->next_in=(Bytef*) dataPointer;
stream->avail_in=bytesIn;
stream->next_out=(Bytef*) bufferOut;
stream->avail_out=bytesCompressed;

if (deflate(&strmCompress, Z_FINISH) != Z_STREAM_END) {
deflateReset(&strmCompress);
if (shouldFreeDataPointer) {
if (deflate(stream, Z_FINISH) != Z_STREAM_END) {
deflateReset(stream);
if (dataPointer) {
free(dataPointer);
}
return Undefined();
}

bytesCompressed=strmCompress.total_out;
deflateReset(&strmCompress);
bytesCompressed=stream->total_out;
deflateReset(stream);

Buffer *BufferOut=Buffer::New(bufferOut, bytesCompressed);
free(bufferOut);

if (shouldFreeDataPointer) {
if (dataPointer) {
free(dataPointer);
}

Expand All @@ -110,19 +113,20 @@ Handle<Value> uncompress(const Arguments &args) {
size_t bytesUncompressed=999*1024*1024; // it's about max size that V8 supports
char *bufferOut=(char*) malloc(bytesUncompressed);

strmUncompress.next_in=(Bytef*) Buffer::Data(bufferIn);
strmUncompress.avail_in=Buffer::Length(bufferIn);
strmUncompress.next_out=(Bytef*) bufferOut;
strmUncompress.avail_out=bytesUncompressed;
z_streamp stream = strmUncompress;
stream->next_in=(Bytef*) Buffer::Data(bufferIn);
stream->avail_in=Buffer::Length(bufferIn);
stream->next_out=(Bytef*) bufferOut;
stream->avail_out=bytesUncompressed;

if (inflate(&strmUncompress, Z_FINISH) != Z_STREAM_END) {
inflateReset(&strmUncompress);
if (inflate(stream, Z_FINISH) != Z_STREAM_END) {
inflateReset(stream);
free(bufferOut);
return Undefined();
}

bytesUncompressed=strmUncompress.total_out;
inflateReset(&strmUncompress);
bytesUncompressed=stream->total_out;
inflateReset(stream);

Buffer *BufferOut=Buffer::New(bufferOut, bytesUncompressed);
free(bufferOut);
Expand All @@ -131,20 +135,19 @@ Handle<Value> uncompress(const Arguments &args) {
return scope.Close(BufferOut->handle_);
}


extern "C" void
init (Handle<Object> target) {
strmCompress.zalloc=Z_NULL;
strmCompress.zfree=Z_NULL;
strmCompress.opaque=Z_NULL;

strmUncompress.zalloc=Z_NULL;
strmUncompress.zfree=Z_NULL;
strmUncompress.opaque=Z_NULL;

deflateInit2(&strmCompress, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 16 + MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
inflateInit2(&strmUncompress, 16 + MAX_WBITS);

NODE_SET_METHOD(target, "compress", compress);
NODE_SET_METHOD(target, "uncompress", uncompress);
init (Handle<Object> target)
{
int rcd = deflateInit2(strmCompress, zstream::compression, zstream::algorithm,
zstream::wbits, zstream::memlevel, zstream::strategy);
int rci = inflateInit2(strmUncompress, zstream::wbits);

if ( rcd != Z_OK || rci != Z_OK)
{
ThrowNodeError("zlib initialization error.");
}

NODE_SET_METHOD(target, "compress", compress);
NODE_SET_METHOD(target, "uncompress", uncompress);
}

39 changes: 39 additions & 0 deletions src/czstream.h
@@ -0,0 +1,39 @@
#ifndef _CZSTREAM_H_
#define _CZSTREAM_H_

#include <zlib.h>

namespace zstream
{

enum {compression = Z_DEFAULT_COMPRESSION};
enum {algorithm = Z_DEFLATED};
enum {strategy = Z_DEFAULT_STRATEGY};
enum {wbits = 16 + MAX_WBITS};
enum {memlevel = 8L};

template<typename Stream>
class CZStream
{
public:
CZStream()
{
stream_.zalloc = Z_NULL;
stream_.zfree = Z_NULL;
stream_.opaque = Z_NULL;
}

~CZStream()
{
}

operator Stream*() const { return const_cast<Stream*>(&stream_); }

private:
Stream stream_;
};

} //namespace zstream

#endif //_CZSTREAM_H_

0 comments on commit 5dba170

Please sign in to comment.