summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api/zlib.markdown5
-rw-r--r--lib/zlib.js32
-rw-r--r--src/node_zlib.cc30
-rw-r--r--test/simple/test-zlib-params.js33
4 files changed, 99 insertions, 1 deletions
diff --git a/doc/api/zlib.markdown b/doc/api/zlib.markdown
index 92569b7d73..59d73554d5 100644
--- a/doc/api/zlib.markdown
+++ b/doc/api/zlib.markdown
@@ -151,6 +151,11 @@ class of the compressor/decompressor classes.
Flush pending data. Don't call this frivolously, premature flushes negatively
impact the effectiveness of the compression algorithm.
+### zlib.params(level, strategy, callback)
+
+Dynamically update the compression level and compression strategy.
+Only applicable to deflate algorithm.
+
### zlib.reset()
Reset the compressor/decompressor to factory defaults. Only applicable to
diff --git a/lib/zlib.js b/lib/zlib.js
index ef4edd6d7e..e41d27a5af 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -341,13 +341,43 @@ function Zlib(opts, mode) {
this._buffer = new Buffer(this._chunkSize);
this._offset = 0;
this._closed = false;
+ this._level = level;
+ this._strategy = strategy;
this.once('end', this.close);
}
util.inherits(Zlib, Transform);
-Zlib.prototype.reset = function reset() {
+Zlib.prototype.params = function(level, strategy, callback) {
+ if (level < exports.Z_MIN_LEVEL ||
+ level > exports.Z_MAX_LEVEL) {
+ throw new RangeError('Invalid compression level: ' + level);
+ }
+ if (strategy != exports.Z_FILTERED &&
+ strategy != exports.Z_HUFFMAN_ONLY &&
+ strategy != exports.Z_RLE &&
+ strategy != exports.Z_FIXED &&
+ strategy != exports.Z_DEFAULT_STRATEGY) {
+ throw new TypeError('Invalid strategy: ' + strategy);
+ }
+
+ if (this._level !== level || this._strategy !== strategy) {
+ var self = this;
+ this.flush(binding.Z_SYNC_FLUSH, function() {
+ self._binding.params(level, strategy);
+ if (!self._hadError) {
+ self._level = level;
+ self._strategy = strategy;
+ if (callback) callback();
+ }
+ });
+ } else {
+ process.nextTick(callback);
+ }
+};
+
+Zlib.prototype.reset = function() {
return this._binding.reset();
};
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index 229dacb69f..9bfc33e580 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -360,6 +360,18 @@ class ZCtx : public ObjectWrap {
return Undefined(node_isolate);
}
+ static Handle<Value> Params(const Arguments& args) {
+ HandleScope scope(node_isolate);
+
+ assert(args.Length() == 2 && "params(level, strategy)");
+
+ ZCtx* ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+
+ Params(ctx, args[0]->Int32Value(), args[1]->Int32Value());
+
+ return Undefined(node_isolate);
+ }
+
static Handle<Value> Reset(const Arguments &args) {
HandleScope scope(node_isolate);
@@ -455,6 +467,23 @@ class ZCtx : public ObjectWrap {
}
}
+ static void Params(ZCtx* ctx, int level, int strategy) {
+ ctx->err_ = Z_OK;
+
+ switch (ctx->mode_) {
+ case DEFLATE:
+ case DEFLATERAW:
+ ctx->err_ = deflateParams(&ctx->strm_, level, strategy);
+ break;
+ default:
+ break;
+ }
+
+ if (ctx->err_ != Z_OK && ctx->err_ != Z_BUF_ERROR) {
+ ZCtx::Error(ctx, "Failed to set parameters");
+ }
+ }
+
static void Reset(ZCtx* ctx) {
ctx->err_ = Z_OK;
@@ -514,6 +543,7 @@ void InitZlib(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write);
NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init);
NODE_SET_PROTOTYPE_METHOD(z, "close", ZCtx::Close);
+ NODE_SET_PROTOTYPE_METHOD(z, "params", ZCtx::Params);
NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx::Reset);
z->SetClassName(String::NewSymbol("Zlib"));
diff --git a/test/simple/test-zlib-params.js b/test/simple/test-zlib-params.js
new file mode 100644
index 0000000000..006f1ea8e5
--- /dev/null
+++ b/test/simple/test-zlib-params.js
@@ -0,0 +1,33 @@
+var common = require('../common.js');
+var assert = require('assert');
+var zlib = require('zlib');
+var path = require('path');
+var fs = require('fs');
+
+var file = fs.readFileSync(path.resolve(common.fixturesDir, 'person.jpg')),
+ chunkSize = 24 * 1024,
+ opts = { level: 9, strategy: zlib.Z_DEFAULT_STRATEGY },
+ deflater = zlib.createDeflate(opts);
+
+var chunk1 = file.slice(0, chunkSize),
+ chunk2 = file.slice(chunkSize),
+ blkhdr = new Buffer([0x00, 0x48, 0x82, 0xb7, 0x7d]),
+ expected = Buffer.concat([blkhdr, chunk2]),
+ actual;
+
+deflater.write(chunk1, function() {
+ deflater.params(0, zlib.Z_DEFAULT_STRATEGY, function() {
+ while (deflater.read());
+ deflater.end(chunk2, function() {
+ var bufs = [], buf;
+ while (buf = deflater.read())
+ bufs.push(buf);
+ actual = Buffer.concat(bufs);
+ });
+ });
+ while (deflater.read());
+});
+
+process.once('exit', function() {
+ assert.deepEqual(actual, expected);
+});