From 5b7c22f37a08b77ef1c79a7cdd4372ce2fc07de9 Mon Sep 17 00:00:00 2001 From: nik Date: Sun, 30 Mar 2014 16:56:26 -0300 Subject: [PATCH] inflate/deflate wrappers now call onData only if output buffer is full or input reached end & add tests for small input chunks --- lib/deflate.js | 15 ++++++------ lib/inflate.js | 18 ++++++++------ test/chunks.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 test/chunks.js diff --git a/lib/deflate.js b/lib/deflate.js index 97a18f4..d6b7604 100644 --- a/lib/deflate.js +++ b/lib/deflate.js @@ -182,11 +182,14 @@ Deflate.prototype.push = function(data, mode) { strm.next_in = data; strm.next_in_index = 0; strm.avail_in = strm.next_in.length; - strm.next_out = new utils.Buf8(chunkSize); + strm.avail_out = 0; do { - strm.avail_out = this.options.chunkSize; - strm.next_out_index = 0; + if (strm.avail_out === 0) { + strm.next_out = new utils.Buf8(chunkSize); + strm.next_out_index = 0; + strm.avail_out = chunkSize; + } status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ if (status !== Z_STREAM_END && status !== Z_OK) { @@ -194,12 +197,8 @@ Deflate.prototype.push = function(data, mode) { this.ended = true; return false; } - if(strm.next_out_index) { + if (strm.avail_out === 0 || strm.avail_in === 0) { this.onData(utils.shrinkBuf(strm.next_out, strm.next_out_index)); - // Allocate buffer for next chunk, if not last - if (strm.avail_in > 0 || strm.avail_out === 0) { - strm.next_out = new utils.Buf8(this.options.chunkSize); - } } } while (strm.avail_in > 0 || strm.avail_out === 0); diff --git a/lib/inflate.js b/lib/inflate.js index af37e03..25195a0 100644 --- a/lib/inflate.js +++ b/lib/inflate.js @@ -176,11 +176,15 @@ Inflate.prototype.push = function(data, mode) { strm.next_in = data; strm.next_in_index = 0; strm.avail_in = strm.next_in.length; - strm.next_out = new utils.Buf8(chunkSize); + strm.avail_out = 0; do { - strm.avail_out = this.options.chunkSize; - strm.next_out_index = 0; + if (strm.avail_out === 0) { + strm.next_out = new utils.Buf8(chunkSize); + strm.next_out_index = 0; + strm.avail_out = chunkSize; + } + status = zlib_inflate.inflate(strm, _mode); /* no bad return value */ if (status !== c.Z_STREAM_END && status !== c.Z_OK) { @@ -188,11 +192,9 @@ Inflate.prototype.push = function(data, mode) { this.ended = true; return false; } - if(strm.next_out_index) { - this.onData(utils.shrinkBuf(strm.next_out, strm.next_out_index)); - // Allocate buffer for next chunk, if not last - if (strm.avail_in > 0 || strm.avail_out === 0) { - strm.next_out = new utils.Buf8(this.options.chunkSize); + if (strm.next_out_index) { + if (strm.avail_out === 0 || strm.avail_in === 0) { + this.onData(utils.shrinkBuf(strm.next_out, strm.next_out_index)); } } } while (strm.avail_in > 0 || strm.avail_out === 0); diff --git a/test/chunks.js b/test/chunks.js new file mode 100644 index 0000000..8897c68 --- /dev/null +++ b/test/chunks.js @@ -0,0 +1,66 @@ +/*global describe, it*/ + + +'use strict'; + + +var assert = require('assert'); + +var helpers = require('./helpers'); + +var pako_utils = require('../lib/zlib/utils'); +var pako = require('../index'); + +function randomBuf(size) { + var buf = pako_utils.Buf8(size); + for (var i = 0; i < size; i++) { + buf[i] = Math.round(Math.random() * 256); + } + return buf; +} + +function testChunk(buf, expected, packer, chunkSize) { + var i, _in, count, pos, size; + + count = Math.ceil(buf.length / chunkSize); + pos = 0; + for (i = 0; i < count; i++) { + size = (buf.length - pos) < chunkSize ? buf.length - pos : chunkSize; + _in = new pako_utils.Buf8(size); + pako_utils.arraySet(_in, buf, pos, size, 0); + packer.push(_in, i === count - 1); + pos += chunkSize; + } + + assert(!packer.err, 'Packer error: ' + packer.err); + + assert(helpers.cmpBuf(packer.result, expected), 'Result is different'); +} + +describe('Small input chunks', function () { + + it('deflate 100b by 1b chunk', function () { + var buf = randomBuf(100); + var deflated = pako.deflate(buf); + testChunk(buf, deflated, new pako.Deflate(), 1); + }); + + it('deflate 8000b by 10b chunk', function () { + var buf = randomBuf(8000); + var deflated = pako.deflate(buf); + testChunk(buf, deflated, new pako.Deflate(), 10); + }); + + it('inflate 100b result by 1b chunk', function () { + var buf = randomBuf(100); + var deflated = pako.deflate(buf); + testChunk(deflated, buf, new pako.Inflate(), 1); + }); + + it('inflate 8000b result by 10b chunk', function () { + var buf = randomBuf(8000); + var deflated = pako.deflate(buf); + testChunk(deflated, buf, new pako.Inflate(), 10); + }); + +}); \ No newline at end of file