From 71ae1753196f41d569d20a940ed036a50c292069 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 12 Jan 2012 03:12:13 +0600 Subject: [PATCH] zlib: reset() method for deflate/inflate streams * ammended test-zlib-dictionary to cover reusing streams --- lib/zlib.js | 4 ++ src/node_zlib.cc | 63 ++++++++++++++++++++++------- test/simple/test-zlib-dictionary.js | 58 +++++++++++++++++--------- 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/lib/zlib.js b/lib/zlib.js index eccb9806fe..339f1e7135 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -309,6 +309,10 @@ Zlib.prototype.write = function write(chunk, cb) { return empty; }; +Zlib.prototype.reset = function reset() { + return this._binding.reset(); +}; + Zlib.prototype.flush = function flush(cb) { this._flush = binding.Z_SYNC_FLUSH; return this.write(cb); diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 95c42ba7f4..b8ad339800 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -249,6 +249,17 @@ template class ZCtx : public ObjectWrap { Init(ctx, level, windowBits, memLevel, strategy, dictionary, dictionary_len); + SetDictionary(ctx); + return Undefined(); + } + + static Handle Reset(const Arguments &args) { + HandleScope scope; + + ZCtx *ctx = ObjectWrap::Unwrap< ZCtx >(args.This()); + + Reset(ctx); + SetDictionary(ctx); return Undefined(); } @@ -304,23 +315,46 @@ template class ZCtx : public ObjectWrap { ctx->dictionary_ = reinterpret_cast(dictionary); ctx->dictionary_len_ = dictionary_len; - if (dictionary != NULL) { - switch (mode) { - case DEFLATE: - case DEFLATERAW: - err = deflateSetDictionary(&ctx->strm_, - ctx->dictionary_, - dictionary_len); - break; - default: - break; - } + ctx->write_in_progress_ = false; + ctx->init_done_ = true; + } + + static void SetDictionary(ZCtx* ctx) { + if (ctx->dictionary_ == NULL) return; - assert(err == Z_OK && "Failed to set dictionary"); + int err; + + switch (mode) { + case DEFLATE: + case DEFLATERAW: + err = deflateSetDictionary(&ctx->strm_, + ctx->dictionary_, + ctx->dictionary_len_); + break; + default: + break; } - ctx->write_in_progress_ = false; - ctx->init_done_ = true; + assert(err == Z_OK && "Failed to set dictionary"); + } + + static void Reset(ZCtx* ctx) { + 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: @@ -352,6 +386,7 @@ template class ZCtx : public ObjectWrap { z->InstanceTemplate()->SetInternalFieldCount(1); \ NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write); \ NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init); \ + NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx::Reset); \ z->SetClassName(String::NewSymbol(name)); \ target->Set(String::NewSymbol(name), z->GetFunction()); \ } diff --git a/test/simple/test-zlib-dictionary.js b/test/simple/test-zlib-dictionary.js index d16e415d10..f3b1446071 100644 --- a/test/simple/test-zlib-dictionary.js +++ b/test/simple/test-zlib-dictionary.js @@ -43,7 +43,6 @@ var spdyDict = new Buffer([ ].join('')); var deflate = zlib.createDeflate({ dictionary: spdyDict }); -var inflate = zlib.createInflate({ dictionary: spdyDict }); var input = [ 'HTTP/1.1 200 Ok', @@ -52,22 +51,45 @@ var input = [ '' ].join('\r\n'); -// Put data into deflate stream -deflate.on('data', function(chunk) { - inflate.write(chunk); -}); -deflate.on('end', function() { - inflate.end(); -}); +var called = 0; -// Get data from inflate stream -var output = []; -inflate.on('data', function(chunk) { - output.push(chunk); -}); -inflate.on('end', function() { - assert.equal(output.join(''), input); -}); +// +// 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'); + } -deflate.write(input); -deflate.end(); + // Put data into deflate stream + deflate.on('data', function(chunk) { + inflate.write(chunk); + }); + + // Get data from inflate stream + var output = []; + inflate.on('data', function(chunk) { + output.push(chunk); + }); + inflate.on('end', function() { + called++; + + assert.equal(output.join(''), input); + + if (num < 2) run(num + 1); + }); + + deflate.write(input); + deflate.flush(function() { + inflate.end(); + }); +} +run(1); + +process.on('exit', function() { + assert.equal(called, 2); +});