Browse Source

zlib: reset() method for deflate/inflate streams

* ammended test-zlib-dictionary to cover reusing streams
v0.7.4-release
Fedor Indutny 13 years ago
parent
commit
71ae175319
  1. 4
      lib/zlib.js
  2. 43
      src/node_zlib.cc
  3. 52
      test/simple/test-zlib-dictionary.js

4
lib/zlib.js

@ -309,6 +309,10 @@ Zlib.prototype.write = function write(chunk, cb) {
return empty; return empty;
}; };
Zlib.prototype.reset = function reset() {
return this._binding.reset();
};
Zlib.prototype.flush = function flush(cb) { Zlib.prototype.flush = function flush(cb) {
this._flush = binding.Z_SYNC_FLUSH; this._flush = binding.Z_SYNC_FLUSH;
return this.write(cb); return this.write(cb);

43
src/node_zlib.cc

@ -249,6 +249,17 @@ template <node_zlib_mode mode> class ZCtx : public ObjectWrap {
Init(ctx, level, windowBits, memLevel, strategy, Init(ctx, level, windowBits, memLevel, strategy,
dictionary, dictionary_len); dictionary, dictionary_len);
SetDictionary(ctx);
return Undefined();
}
static Handle<Value> Reset(const Arguments &args) {
HandleScope scope;
ZCtx<mode> *ctx = ObjectWrap::Unwrap< ZCtx<mode> >(args.This());
Reset(ctx);
SetDictionary(ctx);
return Undefined(); return Undefined();
} }
@ -304,13 +315,21 @@ template <node_zlib_mode mode> class ZCtx : public ObjectWrap {
ctx->dictionary_ = reinterpret_cast<Bytef *>(dictionary); ctx->dictionary_ = reinterpret_cast<Bytef *>(dictionary);
ctx->dictionary_len_ = dictionary_len; ctx->dictionary_len_ = dictionary_len;
if (dictionary != NULL) { ctx->write_in_progress_ = false;
ctx->init_done_ = true;
}
static void SetDictionary(ZCtx* ctx) {
if (ctx->dictionary_ == NULL) return;
int err;
switch (mode) { switch (mode) {
case DEFLATE: case DEFLATE:
case DEFLATERAW: case DEFLATERAW:
err = deflateSetDictionary(&ctx->strm_, err = deflateSetDictionary(&ctx->strm_,
ctx->dictionary_, ctx->dictionary_,
dictionary_len); ctx->dictionary_len_);
break; break;
default: default:
break; break;
@ -319,8 +338,23 @@ template <node_zlib_mode mode> class ZCtx : public ObjectWrap {
assert(err == Z_OK && "Failed to set dictionary"); assert(err == Z_OK && "Failed to set dictionary");
} }
ctx->write_in_progress_ = false; static void Reset(ZCtx* ctx) {
ctx->init_done_ = true; int err;
switch (mode) {
case DEFLATE:
case DEFLATERAW:
err = deflateReset(&ctx->strm_);
break;
case INFLATE:
case INFLATERAW:
err = inflateReset(&ctx->strm_);
break;
default:
break;
}
assert(err == Z_OK && "Failed to reset stream");
} }
private: private:
@ -352,6 +386,7 @@ template <node_zlib_mode mode> class ZCtx : public ObjectWrap {
z->InstanceTemplate()->SetInternalFieldCount(1); \ z->InstanceTemplate()->SetInternalFieldCount(1); \
NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx<mode>::Write); \ NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx<mode>::Write); \
NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx<mode>::Init); \ NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx<mode>::Init); \
NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx<mode>::Reset); \
z->SetClassName(String::NewSymbol(name)); \ z->SetClassName(String::NewSymbol(name)); \
target->Set(String::NewSymbol(name), z->GetFunction()); \ target->Set(String::NewSymbol(name), z->GetFunction()); \
} }

52
test/simple/test-zlib-dictionary.js

@ -43,7 +43,6 @@ var spdyDict = new Buffer([
].join('')); ].join(''));
var deflate = zlib.createDeflate({ dictionary: spdyDict }); var deflate = zlib.createDeflate({ dictionary: spdyDict });
var inflate = zlib.createInflate({ dictionary: spdyDict });
var input = [ var input = [
'HTTP/1.1 200 Ok', 'HTTP/1.1 200 Ok',
@ -52,22 +51,45 @@ var input = [
'' ''
].join('\r\n'); ].join('\r\n');
// Put data into deflate stream var called = 0;
deflate.on('data', function(chunk) {
//
// We'll use clean-new inflate stream each time
// and .reset() old dirty deflate one
//
function run(num) {
var inflate = zlib.createInflate({ dictionary: spdyDict });
if (num === 2) {
deflate.reset();
deflate.removeAllListeners('data');
}
// Put data into deflate stream
deflate.on('data', function(chunk) {
inflate.write(chunk); inflate.write(chunk);
}); });
deflate.on('end', function() {
inflate.end();
});
// Get data from inflate stream // Get data from inflate stream
var output = []; var output = [];
inflate.on('data', function(chunk) { inflate.on('data', function(chunk) {
output.push(chunk); output.push(chunk);
}); });
inflate.on('end', function() { inflate.on('end', function() {
called++;
assert.equal(output.join(''), input); assert.equal(output.join(''), input);
});
deflate.write(input); if (num < 2) run(num + 1);
deflate.end(); });
deflate.write(input);
deflate.flush(function() {
inflate.end();
});
}
run(1);
process.on('exit', function() {
assert.equal(called, 2);
});

Loading…
Cancel
Save