Browse Source

zlib: allow changing of level and strategy

v0.11.4-release
Brian White 12 years ago
committed by Ben Noordhuis
parent
commit
9b09c9eedd
  1. 5
      doc/api/zlib.markdown
  2. 32
      lib/zlib.js
  3. 30
      src/node_zlib.cc
  4. 33
      test/simple/test-zlib-params.js

5
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

32
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();
};

30
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"));

33
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);
});
Loading…
Cancel
Save