Close #1930 Convenience methods for zlib

This is a combination of 20 commits. Their commit messages are preserved
below for the benefit of future generations.

* Adding a shortcut to easily compress/decompress a string of text.
* Making the API consistent. unzip should accept a Buffer for input as well.
* Adding docs.
* Oops, typo.
* Propagate error through the callback.
* Adding zlib from string tests.
* Typo in test.
* Remove 'end' listeners, and join buffers properly instead of joining them
  as a string.
* Oops, needs to be rendered to a string.
* Updated test to include multi-byte characters.
* unzip should return a raw Buffer. Updated docs to reflect.
* And finally updating test.
* EventEmitter.destroy() is a bit more customary
* Revert "EventEmitter.destroy() is a bit more customary"
* Renaming internal methods to "buffer" instead of string.
* Remove the 'error' listeners as well.
* @isaacs: spacing/style, and compress duplicate functions into one
* @isaacs: Update docs
* @isaacs: doc style fix
This commit is contained in:
Matt Robenolt 2011-10-24 12:29:24 -04:00 committed by isaacs
parent 8ef2c13d6c
commit 5213c39038
3 changed files with 176 additions and 2 deletions

View File

@ -20,6 +20,23 @@ fs.ReadStream into a zlib stream, then into an fs.WriteStream.
inp.pipe(gzip).pipe(out);
Compressing or decompressing data in one step can be done by using
the convenience methods.
var input = '.................................';
zlib.deflate(input, function(err, buffer) {
if (!err) {
console.log(buffer.toString('base64'));
}
});
var buffer = new Buffer('eJzT0yMAAGTvBe8=', 'base64');
zlib.unzip(buffer, function(err, buffer) {
if (!err) {
console.log(buffer.toString());
}
});
To use this module in an HTTP client or server, use the
[accept-encoding](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3)
on requests, and the
@ -149,9 +166,46 @@ Decompress a raw deflate stream.
Decompress either a Gzip- or Deflate-compressed stream by auto-detecting
the header.
### Options
## Convenience Methods
Each class takes an options object. All options are optional.
All of these take a string or buffer as the first argument, and call the
supplied callback with `callback(error, result)`. The
compression/decompression engine is created using the default settings
in all convenience methods. To supply different options, use the
zlib classes directly.
### zlib.deflate(buf, callback)
Compress a string with Deflate.
### zlib.deflateRaw(buf, callback)
Compress a string with DeflateRaw.
### zlib.gzip(buf, callback)
Compress a string with Gzip.
### zlib.gunzip(buf, callback)
Decompress a raw Buffer with Gunzip.
### zlib.inflate(buf, callback)
Decompress a raw Buffer with Inflate.
### zlib.inflateRaw(buf, callback)
Decompress a raw Buffer with InflateRaw.
### zlib.unzip(buf, callback)
Decompress a raw Buffer with Unzip.
## Options
Each class takes an options object. All options are optional. (The
convenience methods use the default settings for all options.)
Note that some options are only
relevant when compressing, and are ignored by the decompression classes.

View File

@ -88,6 +88,78 @@ exports.createUnzip = function(o) {
};
// Convenience methods.
// compress/decompress a string or buffer in one step.
exports.deflate = function(buffer, callback) {
zlibBuffer(new Deflate(), buffer, callback);
};
exports.gzip = function(buffer, callback) {
zlibBuffer(new Gzip(), buffer, callback);
};
exports.deflateRaw = function(buffer, callback) {
zlibBuffer(new DeflateRaw(), buffer, callback);
};
exports.unzip = function(buffer, callback) {
zlibBuffer(new Unzip(), buffer, callback);
};
exports.inflate = function(buffer, callback) {
zlibBuffer(new Inflate(), buffer, callback);
};
exports.gunzip = function(buffer, callback) {
zlibBuffer(new Gunzip(), buffer, callback);
};
exports.inflateRaw = function(buffer, callback) {
zlibBuffer(new InflateRaw(), buffer, callback);
};
function zlibBuffer(engine, buffer, callback) {
var buffers = [];
var nread = 0;
engine.on('error', function(err) {
engine.removeListener('end');
engine.removeListener('error');
callback(err);
});
engine.on('data', function(chunk) {
buffers.push(chunk);
nread += chunk.length;
});
engine.on('end', function() {
var buffer;
switch(buffers.length) {
case 0:
buffer = new Buffer(0);
break;
case 1:
buffer = buffers[0];
break;
default:
buffer = new Buffer(nread);
var n = 0;
buffers.forEach(function(b) {
var l = b.length;
b.copy(buffer, n, 0, l);
n += l;
});
break;
}
callback(null, buffer);
});
engine.write(buffer);
engine.end();
}
// generic zlib
// minimal 2-byte header

View File

@ -0,0 +1,48 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// test compressing and uncompressing a string with zlib
var common = require('../common.js');
var assert = require('assert');
var zlib = require('zlib');
var inputString = 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi faucibus, purus at gravida dictum, libero arcu convallis lacus, in commodo libero metus eu nisi. Nullam commodo, neque nec porta placerat, nisi est fermentum augue, vitae gravida tellus sapien sit amet tellus. Aenean non diam orci. Proin quis elit turpis. Suspendisse non diam ipsum. Suspendisse nec ullamcorper odio. Vestibulum arcu mi, sodales non suscipit id, ultrices ut massa. Sed ac sem sit amet arcu malesuada fermentum. Nunc sed. ';
var expectedBase64Deflate = 'eJxdUUtOQzEMvMoc4OndgT0gJCT2buJWlpI4jePeqZfpmXAKLRKbLOzx/HK73q6vOrhCunlF1qIDJhNUeW5I2ozT5OkDlKWLJWkncJG5403HQXAkT3Jw29B9uIEmToMukglZ0vS6ociBh4JG8sV4oVLEUCitK2kxq1WzPnChHDzsaGKy491LofoAbWh8do43oeuYhB5EPCjcLjzYJo48KrfQBvnJecNFJvHT1+RSQsGoC7dn2t/xjhduTA1NWyQIZR0pbHwMDatnD+crPqKSqGPHp1vnlsWM/07ubf7bheF7kqSj84Bm0R1fYTfaK8vqqqfKBtNMhe3OZh6N95CTvMX5HJJi4xOVzCgUOIMSLH7wmeOHaFE4RdpnGavKtrB5xzfO/Ll9';
var expectedBase64Gzip = 'H4sIAAAAAAAAA11RS05DMQy8yhzg6d2BPSAkJPZu4laWkjiN496pl+mZcAotEpss7PH8crverq86uEK6eUXWogMmE1R5bkjajNPk6QOUpYslaSdwkbnjTcdBcCRPcnDb0H24gSZOgy6SCVnS9LqhyIGHgkbyxXihUsRQKK0raTGrVbM+cKEcPOxoYrLj3Uuh+gBtaHx2jjeh65iEHkQ8KNwuPNgmjjwqt9AG+cl5w0Um8dPX5FJCwagLt2fa3/GOF25MDU1bJAhlHSlsfAwNq2cP5ys+opKoY8enW+eWxYz/Tu5t/tuF4XuSpKPzgGbRHV9hN9ory+qqp8oG00yF7c5mHo33kJO8xfkckmLjE5XMKBQ4gxIsfvCZ44doUThF2mcZq8q2sHnHNzRtagj5AQAA';
zlib.deflate(inputString, function(err, buffer) {
assert.equal(buffer.toString('base64'), expectedBase64Deflate, 'deflate encoded string should match');
});
zlib.gzip(inputString, function(err, buffer) {
assert.equal(buffer.toString('base64'), expectedBase64Gzip, 'gzip encoded string should match');
});
var buffer = new Buffer(expectedBase64Deflate, 'base64');
zlib.unzip(buffer, function(err, buffer) {
assert.equal(buffer.toString(), inputString, 'decoded inflated string should match');
});
buffer = new Buffer(expectedBase64Gzip, 'base64');
zlib.unzip(buffer, function(err, buffer) {
assert.equal(buffer.toString(), inputString, 'decoded gunzipped string should match');
});