Skip to content

Commit 9b09c9e

Browse files
mscdexbnoordhuis
authored andcommitted
zlib: allow changing of level and strategy
1 parent 086d4cc commit 9b09c9e

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

doc/api/zlib.markdown

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ class of the compressor/decompressor classes.
151151
Flush pending data. Don't call this frivolously, premature flushes negatively
152152
impact the effectiveness of the compression algorithm.
153153

154+
### zlib.params(level, strategy, callback)
155+
156+
Dynamically update the compression level and compression strategy.
157+
Only applicable to deflate algorithm.
158+
154159
### zlib.reset()
155160

156161
Reset the compressor/decompressor to factory defaults. Only applicable to

lib/zlib.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,43 @@ function Zlib(opts, mode) {
341341
this._buffer = new Buffer(this._chunkSize);
342342
this._offset = 0;
343343
this._closed = false;
344+
this._level = level;
345+
this._strategy = strategy;
344346

345347
this.once('end', this.close);
346348
}
347349

348350
util.inherits(Zlib, Transform);
349351

350-
Zlib.prototype.reset = function reset() {
352+
Zlib.prototype.params = function(level, strategy, callback) {
353+
if (level < exports.Z_MIN_LEVEL ||
354+
level > exports.Z_MAX_LEVEL) {
355+
throw new RangeError('Invalid compression level: ' + level);
356+
}
357+
if (strategy != exports.Z_FILTERED &&
358+
strategy != exports.Z_HUFFMAN_ONLY &&
359+
strategy != exports.Z_RLE &&
360+
strategy != exports.Z_FIXED &&
361+
strategy != exports.Z_DEFAULT_STRATEGY) {
362+
throw new TypeError('Invalid strategy: ' + strategy);
363+
}
364+
365+
if (this._level !== level || this._strategy !== strategy) {
366+
var self = this;
367+
this.flush(binding.Z_SYNC_FLUSH, function() {
368+
self._binding.params(level, strategy);
369+
if (!self._hadError) {
370+
self._level = level;
371+
self._strategy = strategy;
372+
if (callback) callback();
373+
}
374+
});
375+
} else {
376+
process.nextTick(callback);
377+
}
378+
};
379+
380+
Zlib.prototype.reset = function() {
351381
return this._binding.reset();
352382
};
353383

src/node_zlib.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,18 @@ class ZCtx : public ObjectWrap {
360360
return Undefined(node_isolate);
361361
}
362362

363+
static Handle<Value> Params(const Arguments& args) {
364+
HandleScope scope(node_isolate);
365+
366+
assert(args.Length() == 2 && "params(level, strategy)");
367+
368+
ZCtx* ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
369+
370+
Params(ctx, args[0]->Int32Value(), args[1]->Int32Value());
371+
372+
return Undefined(node_isolate);
373+
}
374+
363375
static Handle<Value> Reset(const Arguments &args) {
364376
HandleScope scope(node_isolate);
365377

@@ -455,6 +467,23 @@ class ZCtx : public ObjectWrap {
455467
}
456468
}
457469

470+
static void Params(ZCtx* ctx, int level, int strategy) {
471+
ctx->err_ = Z_OK;
472+
473+
switch (ctx->mode_) {
474+
case DEFLATE:
475+
case DEFLATERAW:
476+
ctx->err_ = deflateParams(&ctx->strm_, level, strategy);
477+
break;
478+
default:
479+
break;
480+
}
481+
482+
if (ctx->err_ != Z_OK && ctx->err_ != Z_BUF_ERROR) {
483+
ZCtx::Error(ctx, "Failed to set parameters");
484+
}
485+
}
486+
458487
static void Reset(ZCtx* ctx) {
459488
ctx->err_ = Z_OK;
460489

@@ -514,6 +543,7 @@ void InitZlib(Handle<Object> target) {
514543
NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write);
515544
NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init);
516545
NODE_SET_PROTOTYPE_METHOD(z, "close", ZCtx::Close);
546+
NODE_SET_PROTOTYPE_METHOD(z, "params", ZCtx::Params);
517547
NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx::Reset);
518548

519549
z->SetClassName(String::NewSymbol("Zlib"));

test/simple/test-zlib-params.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var common = require('../common.js');
2+
var assert = require('assert');
3+
var zlib = require('zlib');
4+
var path = require('path');
5+
var fs = require('fs');
6+
7+
var file = fs.readFileSync(path.resolve(common.fixturesDir, 'person.jpg')),
8+
chunkSize = 24 * 1024,
9+
opts = { level: 9, strategy: zlib.Z_DEFAULT_STRATEGY },
10+
deflater = zlib.createDeflate(opts);
11+
12+
var chunk1 = file.slice(0, chunkSize),
13+
chunk2 = file.slice(chunkSize),
14+
blkhdr = new Buffer([0x00, 0x48, 0x82, 0xb7, 0x7d]),
15+
expected = Buffer.concat([blkhdr, chunk2]),
16+
actual;
17+
18+
deflater.write(chunk1, function() {
19+
deflater.params(0, zlib.Z_DEFAULT_STRATEGY, function() {
20+
while (deflater.read());
21+
deflater.end(chunk2, function() {
22+
var bufs = [], buf;
23+
while (buf = deflater.read())
24+
bufs.push(buf);
25+
actual = Buffer.concat(bufs);
26+
});
27+
});
28+
while (deflater.read());
29+
});
30+
31+
process.once('exit', function() {
32+
assert.deepEqual(actual, expected);
33+
});

0 commit comments

Comments
 (0)