Close #1930 Convenience methods for zlib
authorMatt Robenolt <matt@ydekproductions.com>
Mon, 24 Oct 2011 16:29:24 +0000 (12:29 -0400)
committerisaacs <i@izs.me>
Fri, 4 Nov 2011 17:32:57 +0000 (10:32 -0700)
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

doc/api/zlib.markdown
lib/zlib.js
test/simple/test-zlib-from-string.js [new file with mode: 0644]

index 6e078e4..6484952 100644 (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
+
+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.
+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.
index 0b64dc2..840927b 100644 (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
diff --git a/test/simple/test-zlib-from-string.js b/test/simple/test-zlib-from-string.js
new file mode 100644 (file)
index 0000000..1fda405
--- /dev/null
@@ -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');
+});