-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
zlib: add sync versions for convenience methods #6987
Changes from all commits
4ec2025
3f9747b
5556317
c027af3
713123b
168d7ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -112,58 +112,62 @@ exports.deflate = function(buffer, opts, callback) { | |
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new Deflate(opts), buffer, callback); | ||
| return zlibBuffer(new Deflate(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.gzip = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new Gzip(opts), buffer, callback); | ||
| return zlibBuffer(new Gzip(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.deflateRaw = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new DeflateRaw(opts), buffer, callback); | ||
| return zlibBuffer(new DeflateRaw(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.unzip = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new Unzip(opts), buffer, callback); | ||
| return zlibBuffer(new Unzip(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.inflate = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new Inflate(opts), buffer, callback); | ||
| return zlibBuffer(new Inflate(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.gunzip = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new Gunzip(opts), buffer, callback); | ||
| return zlibBuffer(new Gunzip(opts), buffer, callback); | ||
| }; | ||
|
|
||
| exports.inflateRaw = function(buffer, opts, callback) { | ||
| if (util.isFunction(opts)) { | ||
| callback = opts; | ||
| opts = {}; | ||
| } | ||
| zlibBuffer(new InflateRaw(opts), buffer, callback); | ||
| return zlibBuffer(new InflateRaw(opts), buffer, callback); | ||
| }; | ||
|
|
||
| function zlibBuffer(engine, buffer, callback) { | ||
| if (!util.isFunction(callback)) { | ||
| return zlibBufferSync(engine, buffer, callback); | ||
| } | ||
|
|
||
| var buffers = []; | ||
| var nread = 0; | ||
|
|
||
|
|
@@ -196,6 +200,16 @@ function zlibBuffer(engine, buffer, callback) { | |
| } | ||
| } | ||
|
|
||
| function zlibBufferSync(engine, buffer, callback) { | ||
| if (util.isString(buffer)) | ||
| buffer = new Buffer(buffer); | ||
| if (!util.isBuffer(buffer)) | ||
| throw new TypeError('Not a string or buffer'); | ||
|
|
||
| var flushFlag = binding.Z_FINISH; | ||
|
|
||
| return engine._processChunk(buffer, flushFlag); | ||
| } | ||
|
|
||
| // generic zlib | ||
| // minimal 2-byte header | ||
|
|
@@ -453,10 +467,48 @@ Zlib.prototype._transform = function(chunk, encoding, cb) { | |
| } | ||
| } | ||
|
|
||
| var self = this; | ||
| this._processChunk(chunk, flushFlag, cb); | ||
| }; | ||
|
|
||
| Zlib.prototype._processChunk = function(chunk, flushFlag, cb) { | ||
| var availInBefore = chunk && chunk.length; | ||
| var availOutBefore = this._chunkSize - this._offset; | ||
| var inOff = 0; | ||
|
|
||
| var self = this; | ||
|
|
||
| var async = util.isFunction(cb); | ||
|
|
||
| if (!async) { | ||
| var buffers = []; | ||
| var nread = 0; | ||
|
|
||
| var error; | ||
| this.on('error', function(er) { | ||
| error = er; | ||
| }); | ||
|
|
||
| do { | ||
| var res = this._binding.writeSync(flushFlag, | ||
| chunk, // in | ||
| inOff, // in_off | ||
| availInBefore, // in_len | ||
| this._buffer, // out | ||
| this._offset, //out_off | ||
| availOutBefore); // out_len | ||
| } while (!this._hadError && callback(res[0], res[1])); | ||
|
|
||
| if (this._hadError) { | ||
| throw error; | ||
| } | ||
|
|
||
| var buf = Buffer.concat(buffers, nread); | ||
| this.close(); | ||
|
|
||
| return buf; | ||
| } | ||
|
|
||
| var req = this._binding.write(flushFlag, | ||
| chunk, // in | ||
| inOff, // in_off | ||
|
|
@@ -468,7 +520,6 @@ Zlib.prototype._transform = function(chunk, encoding, cb) { | |
| req.buffer = chunk; | ||
| req.callback = callback; | ||
|
|
||
| var self = this; | ||
| function callback(availInAfter, availOutAfter) { | ||
| if (self._hadError) | ||
| return; | ||
|
|
@@ -480,7 +531,12 @@ Zlib.prototype._transform = function(chunk, encoding, cb) { | |
| var out = self._buffer.slice(self._offset, self._offset + have); | ||
| self._offset += have; | ||
| // serve some output to the consumer. | ||
| self.push(out); | ||
| if (async) | ||
| self.push(out); | ||
| else { | ||
| buffers.push(out); | ||
| nread += out.length; | ||
| } | ||
| } | ||
|
|
||
| // exhausted the output buffer, or used all the input create a new one. | ||
|
|
@@ -498,6 +554,9 @@ Zlib.prototype._transform = function(chunk, encoding, cb) { | |
| inOff += (availInBefore - availInAfter); | ||
| availInBefore = availInAfter; | ||
|
|
||
| if (!async) | ||
| return true; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very clever |
||
|
|
||
| var newReq = self._binding.write(flushFlag, | ||
| chunk, | ||
| inOff, | ||
|
|
@@ -510,6 +569,9 @@ Zlib.prototype._transform = function(chunk, encoding, cb) { | |
| return; | ||
| } | ||
|
|
||
| if (!async) | ||
| return false; | ||
|
|
||
| // finished with the chunk. | ||
| cb(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ | |
|
|
||
| namespace node { | ||
|
|
||
| using v8::Array; | ||
| using v8::Context; | ||
| using v8::FunctionCallbackInfo; | ||
| using v8::FunctionTemplate; | ||
|
|
@@ -125,6 +126,7 @@ class ZCtx : public AsyncWrap { | |
|
|
||
|
|
||
| // write(flush, in, in_off, in_len, out, out_off, out_len) | ||
| template <bool async> | ||
| static void Write(const FunctionCallbackInfo<Value>& args) { | ||
| HandleScope scope(node_isolate); | ||
| assert(args.Length() == 7); | ||
|
|
@@ -190,6 +192,15 @@ class ZCtx : public AsyncWrap { | |
| // set this so that later on, I can easily tell how much was written. | ||
| ctx->chunk_size_ = out_len; | ||
|
|
||
| if (!async) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Split into another method, please. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean the if clause's body. |
||
| // sync version | ||
| Process(work_req); | ||
| if (CheckError(ctx)) | ||
| AfterSync(ctx, args); | ||
| return; | ||
| } | ||
|
|
||
| // async version | ||
| uv_queue_work(ctx->env()->event_loop(), | ||
| work_req, | ||
| ZCtx::Process, | ||
|
|
@@ -198,6 +209,20 @@ class ZCtx : public AsyncWrap { | |
| args.GetReturnValue().Set(ctx->object()); | ||
| } | ||
|
|
||
| static void AfterSync(ZCtx* ctx, const FunctionCallbackInfo<Value>& args) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a newline before declaration. |
||
| Local<Integer> avail_out = Integer::New(ctx->strm_.avail_out, node_isolate); | ||
| Local<Integer> avail_in = Integer::New(ctx->strm_.avail_in, node_isolate); | ||
|
|
||
| ctx->write_in_progress_ = false; | ||
|
|
||
| Local<Array> result = Array::New(2); | ||
| result->Set(0, avail_in); | ||
| result->Set(1, avail_out); | ||
| args.GetReturnValue().Set(result); | ||
|
|
||
| ctx->Unref(); | ||
| } | ||
|
|
||
|
|
||
| // thread pool! | ||
| // This function may be called multiple times on the uv_work pool | ||
|
|
@@ -249,6 +274,29 @@ class ZCtx : public AsyncWrap { | |
| // or shift the queue and call Process. | ||
| } | ||
|
|
||
| static bool CheckError(ZCtx* ctx) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto. |
||
| // Acceptable error states depend on the type of zlib stream. | ||
| switch (ctx->err_) { | ||
| case Z_OK: | ||
| case Z_STREAM_END: | ||
| case Z_BUF_ERROR: | ||
| // normal statuses, not fatal | ||
| break; | ||
| case Z_NEED_DICT: | ||
| if (ctx->dictionary_ == NULL) | ||
| ZCtx::Error(ctx, "Missing dictionary"); | ||
| else | ||
| ZCtx::Error(ctx, "Bad dictionary"); | ||
| return false; | ||
| default: | ||
| // something else. | ||
| ZCtx::Error(ctx, "Zlib error"); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. newline |
||
| // v8 land! | ||
| static void After(uv_work_t* work_req, int status) { | ||
| assert(status == 0); | ||
|
|
@@ -259,25 +307,8 @@ class ZCtx : public AsyncWrap { | |
| HandleScope handle_scope(env->isolate()); | ||
| Context::Scope context_scope(env->context()); | ||
|
|
||
| // Acceptable error states depend on the type of zlib stream. | ||
| switch (ctx->err_) { | ||
| case Z_OK: | ||
| case Z_STREAM_END: | ||
| case Z_BUF_ERROR: | ||
| // normal statuses, not fatal | ||
| break; | ||
| case Z_NEED_DICT: | ||
| if (ctx->dictionary_ == NULL) { | ||
| ZCtx::Error(ctx, "Missing dictionary"); | ||
| } else { | ||
| ZCtx::Error(ctx, "Bad dictionary"); | ||
| } | ||
| return; | ||
| default: | ||
| // something else. | ||
| ZCtx::Error(ctx, "Zlib error"); | ||
| return; | ||
| } | ||
| if (!CheckError(ctx)) | ||
| return; | ||
|
|
||
| Local<Integer> avail_out = Integer::New(ctx->strm_.avail_out, node_isolate); | ||
| Local<Integer> avail_in = Integer::New(ctx->strm_.avail_in, node_isolate); | ||
|
|
@@ -556,7 +587,8 @@ void InitZlib(Handle<Object> target, | |
|
|
||
| z->InstanceTemplate()->SetInternalFieldCount(1); | ||
|
|
||
| NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write); | ||
| NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write<true>); | ||
| NODE_SET_PROTOTYPE_METHOD(z, "writeSync", ZCtx::Write<false>); | ||
| NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init); | ||
| NODE_SET_PROTOTYPE_METHOD(z, "close", ZCtx::Close); | ||
| NODE_SET_PROTOTYPE_METHOD(z, "params", ZCtx::Params); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add braces here, when
elsehas braces -ifshould have them too.