From 0de71c6039791d04f064d3ab803a901013362e67 Mon Sep 17 00:00:00 2001 From: perroned Date: Fri, 18 Jul 2014 07:19:49 -0700 Subject: [PATCH] removing things --- labs/node_modules/hiredis/COPYING | 27 - labs/node_modules/hiredis/README.md | 70 - labs/node_modules/hiredis/bench.js | 121 - labs/node_modules/hiredis/binding.gyp | 22 - labs/node_modules/hiredis/build/Makefile | 337 --- .../build/Release/.deps/Release/hiredis.a.d | 1 - .../Release/.deps/Release/hiredis.node.d | 1 - .../.deps/Release/obj.target/deps/hiredis.a.d | 1 - .../.deps/Release/obj.target/hiredis.node.d | 1 - .../obj.target/hiredis/deps/hiredis/async.o.d | 13 - .../hiredis/deps/hiredis/hiredis.o.d | 9 - .../obj.target/hiredis/deps/hiredis/net.o.d | 9 - .../obj.target/hiredis/deps/hiredis/sds.o.d | 5 - .../obj.target/hiredis/src/hiredis.o.d | 29 - .../Release/obj.target/hiredis/src/reader.o.d | 29 - .../hiredis/build/Release/hiredis.a | Bin 57978 -> 0 bytes .../hiredis/build/Release/hiredis.node | Bin 61740 -> 0 bytes .../hiredis/build/Release/linker.lock | 0 .../build/Release/obj.target/deps/hiredis.a | Bin 57978 -> 0 bytes .../build/Release/obj.target/hiredis.node | Bin 61740 -> 0 bytes .../obj.target/hiredis/deps/hiredis/async.o | Bin 15432 -> 0 bytes .../obj.target/hiredis/deps/hiredis/hiredis.o | Bin 23568 -> 0 bytes .../obj.target/hiredis/deps/hiredis/net.o | Bin 6416 -> 0 bytes .../obj.target/hiredis/deps/hiredis/sds.o | Bin 10872 -> 0 bytes .../Release/obj.target/hiredis/src/hiredis.o | Bin 2104 -> 0 bytes .../Release/obj.target/hiredis/src/reader.o | Bin 25656 -> 0 bytes .../hiredis/build/binding.Makefile | 6 - labs/node_modules/hiredis/build/config.gypi | 116 - .../hiredis/build/deps/hiredis.Makefile | 6 - .../hiredis/build/deps/hiredis.target.mk | 139 -- .../hiredis/build/hiredis.target.mk | 143 -- labs/node_modules/hiredis/deps/hiredis.gyp | 27 - .../hiredis/deps/hiredis/CHANGELOG.md | 24 - .../node_modules/hiredis/deps/hiredis/COPYING | 29 - .../hiredis/deps/hiredis/Makefile | 148 -- .../hiredis/deps/hiredis/README.md | 379 --- .../hiredis/deps/hiredis/adapters/ae.h | 97 - .../hiredis/deps/hiredis/adapters/libev.h | 117 - .../hiredis/deps/hiredis/adapters/libevent.h | 78 - .../node_modules/hiredis/deps/hiredis/async.c | 622 ----- .../node_modules/hiredis/deps/hiredis/async.h | 125 - labs/node_modules/hiredis/deps/hiredis/dict.c | 338 --- labs/node_modules/hiredis/deps/hiredis/dict.h | 126 - .../hiredis/deps/hiredis/example-ae.c | 56 - .../hiredis/deps/hiredis/example-libev.c | 51 - .../hiredis/deps/hiredis/example-libevent.c | 52 - .../hiredis/deps/hiredis/example.c | 68 - .../hiredis/deps/hiredis/fmacros.h | 16 - .../hiredis/deps/hiredis/hiredis.c | 1285 ---------- .../hiredis/deps/hiredis/hiredis.h | 210 -- labs/node_modules/hiredis/deps/hiredis/net.c | 291 --- labs/node_modules/hiredis/deps/hiredis/net.h | 47 - labs/node_modules/hiredis/deps/hiredis/sds.c | 605 ----- labs/node_modules/hiredis/deps/hiredis/sds.h | 88 - labs/node_modules/hiredis/deps/hiredis/test.c | 656 ----- labs/node_modules/hiredis/hiredis.js | 34 - .../hiredis/node_modules/bindings/README.md | 97 - .../hiredis/node_modules/bindings/bindings.js | 166 -- .../node_modules/bindings/package.json | 33 - .../hiredis/node_modules/nan/.dntrc | 37 - .../hiredis/node_modules/nan/LICENSE | 46 - .../hiredis/node_modules/nan/README.md | 972 -------- .../node_modules/nan/build/config.gypi | 38 - .../hiredis/node_modules/nan/include_dirs.js | 1 - .../hiredis/node_modules/nan/nan.h | 2155 ----------------- .../hiredis/node_modules/nan/package.json | 54 - labs/node_modules/hiredis/package.json | 44 - labs/node_modules/hiredis/src/hiredis.cc | 13 - labs/node_modules/hiredis/src/reader.cc | 233 -- labs/node_modules/hiredis/src/reader.h | 59 - labs/node_modules/hiredis/test/reader.js | 197 -- labs/node_modules/meteor-npm/.travis.yml | 5 - labs/node_modules/meteor-npm/LICENSE | 22 - labs/node_modules/meteor-npm/README.md | 147 -- labs/node_modules/meteor-npm/bin/meteor-npm | 49 - labs/node_modules/meteor-npm/index.js | 88 - .../meteor-npm/node_modules/mkdirp/.npmignore | 2 - .../node_modules/mkdirp/.travis.yml | 5 - .../meteor-npm/node_modules/mkdirp/LICENSE | 21 - .../node_modules/mkdirp/examples/pow.js | 6 - .../meteor-npm/node_modules/mkdirp/index.js | 82 - .../node_modules/mkdirp/package.json | 36 - .../node_modules/mkdirp/readme.markdown | 63 - .../node_modules/mkdirp/test/chmod.js | 38 - .../node_modules/mkdirp/test/clobber.js | 37 - .../node_modules/mkdirp/test/mkdirp.js | 28 - .../node_modules/mkdirp/test/perm.js | 32 - .../node_modules/mkdirp/test/perm_sync.js | 39 - .../node_modules/mkdirp/test/race.js | 41 - .../node_modules/mkdirp/test/rel.js | 32 - .../node_modules/mkdirp/test/return.js | 25 - .../node_modules/mkdirp/test/return_sync.js | 24 - .../node_modules/mkdirp/test/root.js | 18 - .../node_modules/mkdirp/test/sync.js | 32 - .../node_modules/mkdirp/test/umask.js | 28 - .../node_modules/mkdirp/test/umask_sync.js | 32 - .../meteor-npm/node_modules/rimraf/AUTHORS | 6 - .../meteor-npm/node_modules/rimraf/LICENSE | 23 - .../meteor-npm/node_modules/rimraf/README.md | 30 - .../meteor-npm/node_modules/rimraf/bin.js | 33 - .../node_modules/rimraf/package.json | 58 - .../meteor-npm/node_modules/rimraf/rimraf.js | 248 -- .../node_modules/rimraf/test/run.sh | 16 - .../node_modules/rimraf/test/setup.sh | 47 - .../node_modules/rimraf/test/test-async.js | 5 - .../node_modules/rimraf/test/test-sync.js | 3 - labs/node_modules/meteor-npm/package.js | 40 - labs/node_modules/meteor-npm/package.json | 31 - labs/node_modules/meteor-npm/smart.json | 8 - labs/node_modules/meteor-npm/test.js | 119 - labs/node_modules/redis/.npmignore | 8 - labs/node_modules/redis/README.md | 757 ------ labs/node_modules/redis/connection_breaker.js | 80 - labs/node_modules/redis/index.js | 1248 ---------- labs/node_modules/redis/lib/commands.js | 163 -- labs/node_modules/redis/lib/parser/hiredis.js | 46 - .../redis/lib/parser/javascript.js | 301 --- labs/node_modules/redis/lib/queue.js | 59 - labs/node_modules/redis/lib/to_array.js | 12 - labs/node_modules/redis/lib/util.js | 11 - labs/node_modules/redis/package.json | 37 - 121 files changed, 15120 deletions(-) delete mode 100644 labs/node_modules/hiredis/COPYING delete mode 100644 labs/node_modules/hiredis/README.md delete mode 100644 labs/node_modules/hiredis/bench.js delete mode 100644 labs/node_modules/hiredis/binding.gyp delete mode 100644 labs/node_modules/hiredis/build/Makefile delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.a.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.node.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/deps/hiredis.a.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis.node.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/async.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/hiredis.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/net.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/sds.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/hiredis.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/reader.o.d delete mode 100644 labs/node_modules/hiredis/build/Release/hiredis.a delete mode 100755 labs/node_modules/hiredis/build/Release/hiredis.node delete mode 100644 labs/node_modules/hiredis/build/Release/linker.lock delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/deps/hiredis.a delete mode 100755 labs/node_modules/hiredis/build/Release/obj.target/hiredis.node delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/async.o delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/hiredis.o delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/net.o delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/sds.o delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/src/hiredis.o delete mode 100644 labs/node_modules/hiredis/build/Release/obj.target/hiredis/src/reader.o delete mode 100644 labs/node_modules/hiredis/build/binding.Makefile delete mode 100644 labs/node_modules/hiredis/build/config.gypi delete mode 100644 labs/node_modules/hiredis/build/deps/hiredis.Makefile delete mode 100644 labs/node_modules/hiredis/build/deps/hiredis.target.mk delete mode 100644 labs/node_modules/hiredis/build/hiredis.target.mk delete mode 100644 labs/node_modules/hiredis/deps/hiredis.gyp delete mode 100644 labs/node_modules/hiredis/deps/hiredis/CHANGELOG.md delete mode 100644 labs/node_modules/hiredis/deps/hiredis/COPYING delete mode 100644 labs/node_modules/hiredis/deps/hiredis/Makefile delete mode 100644 labs/node_modules/hiredis/deps/hiredis/README.md delete mode 100644 labs/node_modules/hiredis/deps/hiredis/adapters/ae.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/adapters/libev.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/adapters/libevent.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/async.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/async.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/dict.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/dict.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/example-ae.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/example-libev.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/example-libevent.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/example.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/fmacros.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/hiredis.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/hiredis.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/net.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/net.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/sds.c delete mode 100644 labs/node_modules/hiredis/deps/hiredis/sds.h delete mode 100644 labs/node_modules/hiredis/deps/hiredis/test.c delete mode 100644 labs/node_modules/hiredis/hiredis.js delete mode 100644 labs/node_modules/hiredis/node_modules/bindings/README.md delete mode 100644 labs/node_modules/hiredis/node_modules/bindings/bindings.js delete mode 100644 labs/node_modules/hiredis/node_modules/bindings/package.json delete mode 100644 labs/node_modules/hiredis/node_modules/nan/.dntrc delete mode 100644 labs/node_modules/hiredis/node_modules/nan/LICENSE delete mode 100644 labs/node_modules/hiredis/node_modules/nan/README.md delete mode 100644 labs/node_modules/hiredis/node_modules/nan/build/config.gypi delete mode 100644 labs/node_modules/hiredis/node_modules/nan/include_dirs.js delete mode 100644 labs/node_modules/hiredis/node_modules/nan/nan.h delete mode 100644 labs/node_modules/hiredis/node_modules/nan/package.json delete mode 100644 labs/node_modules/hiredis/package.json delete mode 100644 labs/node_modules/hiredis/src/hiredis.cc delete mode 100644 labs/node_modules/hiredis/src/reader.cc delete mode 100644 labs/node_modules/hiredis/src/reader.h delete mode 100644 labs/node_modules/hiredis/test/reader.js delete mode 100644 labs/node_modules/meteor-npm/.travis.yml delete mode 100644 labs/node_modules/meteor-npm/LICENSE delete mode 100644 labs/node_modules/meteor-npm/README.md delete mode 100755 labs/node_modules/meteor-npm/bin/meteor-npm delete mode 100644 labs/node_modules/meteor-npm/index.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/.npmignore delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/.travis.yml delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/LICENSE delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/examples/pow.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/index.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/package.json delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/readme.markdown delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/chmod.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/clobber.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/mkdirp.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm_sync.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/race.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/rel.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/return.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/return_sync.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/root.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/sync.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask_sync.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/AUTHORS delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/LICENSE delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/README.md delete mode 100755 labs/node_modules/meteor-npm/node_modules/rimraf/bin.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/package.json delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/rimraf.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/test/run.sh delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/test/setup.sh delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/test/test-async.js delete mode 100644 labs/node_modules/meteor-npm/node_modules/rimraf/test/test-sync.js delete mode 100644 labs/node_modules/meteor-npm/package.js delete mode 100644 labs/node_modules/meteor-npm/package.json delete mode 100644 labs/node_modules/meteor-npm/smart.json delete mode 100644 labs/node_modules/meteor-npm/test.js delete mode 100644 labs/node_modules/redis/.npmignore delete mode 100644 labs/node_modules/redis/README.md delete mode 100644 labs/node_modules/redis/connection_breaker.js delete mode 100644 labs/node_modules/redis/index.js delete mode 100644 labs/node_modules/redis/lib/commands.js delete mode 100644 labs/node_modules/redis/lib/parser/hiredis.js delete mode 100644 labs/node_modules/redis/lib/parser/javascript.js delete mode 100644 labs/node_modules/redis/lib/queue.js delete mode 100644 labs/node_modules/redis/lib/to_array.js delete mode 100644 labs/node_modules/redis/lib/util.js delete mode 100644 labs/node_modules/redis/package.json diff --git a/labs/node_modules/hiredis/COPYING b/labs/node_modules/hiredis/COPYING deleted file mode 100644 index 211acd5667..0000000000 --- a/labs/node_modules/hiredis/COPYING +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2010-2012, Pieter Noordhuis -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Redis nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/labs/node_modules/hiredis/README.md b/labs/node_modules/hiredis/README.md deleted file mode 100644 index d6c8780cfe..0000000000 --- a/labs/node_modules/hiredis/README.md +++ /dev/null @@ -1,70 +0,0 @@ -[![Build Status](https://travis-ci.org/redis/hiredis-node.png?branch=master)](https://travis-ci.org/redis/hiredis-node) - -# hiredis-node - -Node extension that wraps [hiredis][hiredis]. -Because Node is already good at doing I/O, hiredis-node only provides -bindings to the protocol parser. -The hiredis protocol parser is faster than JavaScript protocol parsers, -but the speedup only becomes noticable for large replies. -If you use Redis for simple SET/GET operations, there won't be a big -benefit to using hiredis. -If you use Redis for big SUNION/SINTER/LRANGE/ZRANGE operations, the -benefit to using hiredis-node can be significant. - -[hiredis]: http://github.com/redis/hiredis - -## Install - -Install with [NPM][npm]: - -``` -npm install hiredis -``` - -[npm]: https://npmjs.org/ - -## Usage - -hiredis-node works out of the box with Matt Ranney's [node_redis][node_redis]. -The latter has an optional dependency on hiredis-node, so maybe you're -already using it without knowing. - -Alternatively, you can use it directly: - -```javascript -var hiredis = require("hiredis"), - reader = new hiredis.Reader(); - -// Data comes in -reader.feed("$5\r\nhello\r\n"); - -// Reply comes out -reader.get() // => "hello" -``` - -Instead of returning strings for bulk payloads, it can also return -buffers: - -```javascript -var hiredis = require("hiredis"), - reader = new hiredis.Reader({ return_buffers: true }); - -// Data comes in -reader.feed("$5\r\nhello\r\n"); - -// Reply comes out -reader.get() // => -``` - -[node_redis]: http://github.com/mranney/node_redis - -## Windows - -Dmitry Gorbunov (@fuwaneko) made a [fork of hiredis-node][windows_fork] with Windows support. - -[windows_fork]: https://github.com/fuwaneko/hiredis-node - -## License - -This code is released under the BSD license, after the license of hiredis. diff --git a/labs/node_modules/hiredis/bench.js b/labs/node_modules/hiredis/bench.js deleted file mode 100644 index 01433caa00..0000000000 --- a/labs/node_modules/hiredis/bench.js +++ /dev/null @@ -1,121 +0,0 @@ -var hiredis = require("./hiredis"), - num_clients = 10, - active_clients = 0, - pipeline = 0, - num_requests = parseInt(process.argv[2]) || 20000, - issued_requests = 0, - test_start; - -var tests = []; -tests.push({ - descr: "PING", - command: ["PING"] -}); -tests.push({ - descr: "SET", - command: ["SET", "foo", "bar"] -}); -tests.push({ - descr: "GET", - command: ["GET", "foo"] -}); -tests.push({ - descr: "LPUSH 8 bytes", - command: ["LPUSH", "mylist-8", new Buffer(Array(8).join("-"))] -}); -tests.push({ - descr: "LPUSH 64 bytes", - command: ["LPUSH", "mylist-64", new Buffer(Array(64).join("-"))] -}); -tests.push({ - descr: "LPUSH 512 bytes", - command: ["LPUSH", "mylist-512", new Buffer(Array(512).join("-"))] -}); -tests.push({ - descr: "LRANGE 10 elements, 8 bytes", - command: ["LRANGE", "mylist-8", "0", "9"] -}); -tests.push({ - descr: "LRANGE 100 elements, 8 bytes", - command: ["LRANGE", "mylist-8", "0", "99"] -}); -tests.push({ - descr: "LRANGE 100 elements, 64 bytes", - command: ["LRANGE", "mylist-64", "0", "99"] -}); -tests.push({ - descr: "LRANGE 100 elements, 512 bytes", - command: ["LRANGE", "mylist-512", "0", "99"] -}); - -function call(client, test) { - client.on("reply", function() { - if (issued_requests < num_requests) { - request(); - } else { - client.end(); - if (--active_clients == 0) - done(test); - } - }); - - function request() { - issued_requests++; - client.write.apply(client,test.command); - }; - - request(); -} - -function done(test) { - var time = (new Date - test_start); - var op_rate = (num_requests/(time/1000.0)).toFixed(2); - console.log(test.descr + ": " + op_rate + " ops/sec"); - next(); -} - -function concurrent_test(test) { - var i = num_clients; - var client; - - issued_requests = 0; - test_start = new Date; - while(i-- && issued_requests < num_requests) { - active_clients++; - client = hiredis.createConnection(); - call(client, test); - } -} - -function pipelined_test(test) { - var client = hiredis.createConnection(); - var received_replies = 0; - - issued_requests = 0; - while (issued_requests < num_requests) { - issued_requests++; - client.write.apply(client,test.command); - } - - test_start = new Date; - client.on("reply", function() { - if (++received_replies == num_requests) { - client.end(); - done(test); - } - }); -} - -function next() { - var test = tests.shift(); - if (test) { - if (pipeline) { - pipelined_test(test); - } else { - concurrent_test(test); - } - } -} - -next(); - diff --git a/labs/node_modules/hiredis/binding.gyp b/labs/node_modules/hiredis/binding.gyp deleted file mode 100644 index e517b4651a..0000000000 --- a/labs/node_modules/hiredis/binding.gyp +++ /dev/null @@ -1,22 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'hiredis', - 'sources': [ - 'src/hiredis.cc' - , 'src/reader.cc' - ], - 'include_dirs': ["> $(depfile) -# Add extra rules as in (2). -# We remove slashes and replace spaces with new lines; -# remove blank lines; -# delete the first line and append a colon to the remaining lines. -sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ - grep -v '^$$' |\ - sed -e 1d -e 's|$$|:|' \ - >> $(depfile) -rm $(depfile).raw -endef - -# Command definitions: -# - cmd_foo is the actual command to run; -# - quiet_cmd_foo is the brief-output summary of the command. - -quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_touch = TOUCH $@ -cmd_touch = touch $@ - -quiet_cmd_copy = COPY $@ -# send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@") - -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) - -# Due to circular dependencies between libraries :(, we wrap the -# special "figure out circular dependencies" flags around the entire -# input list during linking. -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) - -# We support two kinds of shared objects (.so): -# 1) shared_library, which is just bundling together many dependent libraries -# into a link line. -# 2) loadable_module, which is generating a module intended for dlopen(). -# -# They differ only slightly: -# In the former case, we want to package all dependent code into the .so. -# In the latter case, we want to package just the API exposed by the -# outermost module. -# This means shared_library uses --whole-archive, while loadable_module doesn't. -# (Note that --whole-archive is incompatible with the --start-group used in -# normal linking.) - -# Other shared-object link notes: -# - Set SONAME to the library filename so our binaries don't reference -# the local, absolute paths used on the link command-line. -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) - - -# Define an escape_quotes function to escape single quotes. -# This allows us to handle quotes properly as long as we always use -# use single quotes and escape_quotes. -escape_quotes = $(subst ','\'',$(1)) -# This comment is here just to include a ' to unconfuse syntax highlighting. -# Define an escape_vars function to escape '$' variable syntax. -# This allows us to read/write command lines with shell variables (e.g. -# $LD_LIBRARY_PATH), without triggering make substitution. -escape_vars = $(subst $$,$$$$,$(1)) -# Helper that expands to a shell command to echo a string exactly as it is in -# make. This uses printf instead of echo because printf's behaviour with respect -# to escape sequences is more portable than echo's across different shells -# (e.g., dash, bash). -exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' - -# Helper to compare the command we're about to run against the command -# we logged the last time we ran the command. Produces an empty -# string (false) when the commands match. -# Tricky point: Make has no string-equality test function. -# The kernel uses the following, but it seems like it would have false -# positives, where one string reordered its arguments. -# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ -# $(filter-out $(cmd_$@), $(cmd_$(1)))) -# We instead substitute each for the empty string into the other, and -# say they're equal if both substitutions produce the empty string. -# .d files contain ? instead of spaces, take that into account. -command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ - $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) - -# Helper that is non-empty when a prerequisite changes. -# Normally make does this implicitly, but we force rules to always run -# so we can check their command lines. -# $? -- new prerequisites -# $| -- order-only dependencies -prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) - -# Helper that executes all postbuilds until one fails. -define do_postbuilds - @E=0;\ - for p in $(POSTBUILDS); do\ - eval $$p;\ - E=$$?;\ - if [ $$E -ne 0 ]; then\ - break;\ - fi;\ - done;\ - if [ $$E -ne 0 ]; then\ - rm -rf "$@";\ - exit $$E;\ - fi -endef - -# do_cmd: run a command via the above cmd_foo names, if necessary. -# Should always run for a given target to handle command-line changes. -# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. -# Third argument, if non-zero, makes it do POSTBUILDS processing. -# Note: We intentionally do NOT call dirx for depfile, since it contains ? for -# spaces already and dirx strips the ? characters. -define do_cmd -$(if $(or $(command_changed),$(prereq_changed)), - @$(call exact_echo, $($(quiet)cmd_$(1))) - @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" - $(if $(findstring flock,$(word 1,$(cmd_$1))), - @$(cmd_$(1)) - @echo " $(quiet_cmd_$(1)): Finished", - @$(cmd_$(1)) - ) - @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) - @$(if $(2),$(fixup_dep)) - $(if $(and $(3), $(POSTBUILDS)), - $(call do_postbuilds) - ) -) -endef - -# Declare the "all" target first so it is the default, -# even though we don't have the deps yet. -.PHONY: all -all: - -# make looks for ways to re-generate included makefiles, but in our case, we -# don't have a direct way. Explicitly telling make that it has nothing to do -# for them makes it go faster. -%.d: ; - -# Use FORCE_DO_CMD to force a target to run. Should be coupled with -# do_cmd. -.PHONY: FORCE_DO_CMD -FORCE_DO_CMD: - -TOOLSET := target -# Suffix rules, putting all outputs into $(obj). -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# Try building from generated source, too. -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - - -ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ - $(findstring $(join ^,$(prefix)),\ - $(join ^,deps/hiredis.target.mk)))),) - include deps/hiredis.target.mk -endif -ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ - $(findstring $(join ^,$(prefix)),\ - $(join ^,hiredis.target.mk)))),) - include hiredis.target.mk -endif - -quiet_cmd_regen_makefile = ACTION Regenerating $@ -cmd_regen_makefile = cd $(srcdir); /usr/share/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/home/firstuser/dev/bigbluebutton/labs/node_modules/hiredis/build/config.gypi -I/usr/share/node-gyp/addon.gypi -I/usr/include/nodejs/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/usr/include/nodejs" "-Dmodule_root_dir=/home/firstuser/dev/bigbluebutton/labs/node_modules/hiredis" binding.gyp -Makefile: $(srcdir)/../../../../../../../usr/share/node-gyp/addon.gypi $(srcdir)/../../../../../../../usr/include/nodejs/common.gypi $(srcdir)/deps/hiredis.gyp $(srcdir)/build/config.gypi $(srcdir)/binding.gyp - $(call do_cmd,regen_makefile) - -# "all" is a concatenation of the "all" targets from all the included -# sub-makefiles. This is just here to clarify. -all: - -# Add in dependency-tracking rules. $(all_deps) is the list of every single -# target in our tree. Only consider the ones with .d (dependency) info: -d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) -ifneq ($(d_files),) - include $(d_files) -endif diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.a.d b/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.a.d deleted file mode 100644 index de7fd20817..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.a.d +++ /dev/null @@ -1 +0,0 @@ -cmd_Release/hiredis.a := ln -f "Release/obj.target/deps/hiredis.a" "Release/hiredis.a" 2>/dev/null || (rm -rf "Release/hiredis.a" && cp -af "Release/obj.target/deps/hiredis.a" "Release/hiredis.a") diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.node.d b/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.node.d deleted file mode 100644 index 7fce21e5bc..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/hiredis.node.d +++ /dev/null @@ -1 +0,0 @@ -cmd_Release/hiredis.node := ln -f "Release/obj.target/hiredis.node" "Release/hiredis.node" 2>/dev/null || (rm -rf "Release/hiredis.node" && cp -af "Release/obj.target/hiredis.node" "Release/hiredis.node") diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/deps/hiredis.a.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/deps/hiredis.a.d deleted file mode 100644 index 4d3f3545fd..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/deps/hiredis.a.d +++ /dev/null @@ -1 +0,0 @@ -cmd_Release/obj.target/deps/hiredis.a := rm -f Release/obj.target/deps/hiredis.a && ar crs Release/obj.target/deps/hiredis.a Release/obj.target/hiredis/deps/hiredis/hiredis.o Release/obj.target/hiredis/deps/hiredis/net.o Release/obj.target/hiredis/deps/hiredis/sds.o Release/obj.target/hiredis/deps/hiredis/async.o diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis.node.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis.node.d deleted file mode 100644 index e9001a194b..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis.node.d +++ /dev/null @@ -1 +0,0 @@ -cmd_Release/obj.target/hiredis.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64 -Wl,-soname=hiredis.node -o Release/obj.target/hiredis.node -Wl,--start-group Release/obj.target/hiredis/src/hiredis.o Release/obj.target/hiredis/src/reader.o Release/obj.target/deps/hiredis.a -Wl,--end-group diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/async.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/async.o.d deleted file mode 100644 index 425e2c3f15..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/async.o.d +++ /dev/null @@ -1,13 +0,0 @@ -cmd_Release/obj.target/hiredis/deps/hiredis/async.o := cc '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -MMD -MF ./Release/.deps/Release/obj.target/hiredis/deps/hiredis/async.o.d.raw -c -o Release/obj.target/hiredis/deps/hiredis/async.o ../deps/hiredis/async.c -Release/obj.target/hiredis/deps/hiredis/async.o: ../deps/hiredis/async.c \ - ../deps/hiredis/fmacros.h ../deps/hiredis/async.h \ - ../deps/hiredis/hiredis.h ../deps/hiredis/net.h ../deps/hiredis/dict.c \ - ../deps/hiredis/dict.h ../deps/hiredis/sds.h -../deps/hiredis/async.c: -../deps/hiredis/fmacros.h: -../deps/hiredis/async.h: -../deps/hiredis/hiredis.h: -../deps/hiredis/net.h: -../deps/hiredis/dict.c: -../deps/hiredis/dict.h: -../deps/hiredis/sds.h: diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/hiredis.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/hiredis.o.d deleted file mode 100644 index 563cea7561..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/hiredis.o.d +++ /dev/null @@ -1,9 +0,0 @@ -cmd_Release/obj.target/hiredis/deps/hiredis/hiredis.o := cc '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -MMD -MF ./Release/.deps/Release/obj.target/hiredis/deps/hiredis/hiredis.o.d.raw -c -o Release/obj.target/hiredis/deps/hiredis/hiredis.o ../deps/hiredis/hiredis.c -Release/obj.target/hiredis/deps/hiredis/hiredis.o: \ - ../deps/hiredis/hiredis.c ../deps/hiredis/fmacros.h \ - ../deps/hiredis/hiredis.h ../deps/hiredis/net.h ../deps/hiredis/sds.h -../deps/hiredis/hiredis.c: -../deps/hiredis/fmacros.h: -../deps/hiredis/hiredis.h: -../deps/hiredis/net.h: -../deps/hiredis/sds.h: diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/net.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/net.o.d deleted file mode 100644 index e37c189ce1..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/net.o.d +++ /dev/null @@ -1,9 +0,0 @@ -cmd_Release/obj.target/hiredis/deps/hiredis/net.o := cc '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -MMD -MF ./Release/.deps/Release/obj.target/hiredis/deps/hiredis/net.o.d.raw -c -o Release/obj.target/hiredis/deps/hiredis/net.o ../deps/hiredis/net.c -Release/obj.target/hiredis/deps/hiredis/net.o: ../deps/hiredis/net.c \ - ../deps/hiredis/fmacros.h ../deps/hiredis/net.h \ - ../deps/hiredis/hiredis.h ../deps/hiredis/sds.h -../deps/hiredis/net.c: -../deps/hiredis/fmacros.h: -../deps/hiredis/net.h: -../deps/hiredis/hiredis.h: -../deps/hiredis/sds.h: diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/sds.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/sds.o.d deleted file mode 100644 index a0a53f8db8..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/deps/hiredis/sds.o.d +++ /dev/null @@ -1,5 +0,0 @@ -cmd_Release/obj.target/hiredis/deps/hiredis/sds.o := cc '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -MMD -MF ./Release/.deps/Release/obj.target/hiredis/deps/hiredis/sds.o.d.raw -c -o Release/obj.target/hiredis/deps/hiredis/sds.o ../deps/hiredis/sds.c -Release/obj.target/hiredis/deps/hiredis/sds.o: ../deps/hiredis/sds.c \ - ../deps/hiredis/sds.h -../deps/hiredis/sds.c: -../deps/hiredis/sds.h: diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/hiredis.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/hiredis.o.d deleted file mode 100644 index 8d69f87545..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/hiredis.o.d +++ /dev/null @@ -1,29 +0,0 @@ -cmd_Release/obj.target/hiredis/src/hiredis.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_GNU_SOURCE' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -I../node_modules/nan -I../deps -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -Wall -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/hiredis/src/hiredis.o.d.raw -c -o Release/obj.target/hiredis/src/hiredis.o ../src/hiredis.cc -Release/obj.target/hiredis/src/hiredis.o: ../src/hiredis.cc \ - /usr/include/nodejs/deps/v8/include/v8.h \ - /usr/include/nodejs/deps/v8/include/v8stdint.h \ - /usr/include/nodejs/src/node.h /usr/include/nodejs/deps/uv/include/uv.h \ - /usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h \ - /usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h \ - /usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h \ - /usr/include/nodejs/src/node_object_wrap.h \ - /usr/include/nodejs/src/node.h ../src/reader.h ../deps/hiredis/hiredis.h \ - ../node_modules/nan/nan.h /usr/include/nodejs/src/node_buffer.h \ - /usr/include/nodejs/src/node_version.h \ - /usr/include/nodejs/src/node_object_wrap.h -../src/hiredis.cc: -/usr/include/nodejs/deps/v8/include/v8.h: -/usr/include/nodejs/deps/v8/include/v8stdint.h: -/usr/include/nodejs/src/node.h: -/usr/include/nodejs/deps/uv/include/uv.h: -/usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h: -/usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h: -/usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h: -/usr/include/nodejs/src/node_object_wrap.h: -/usr/include/nodejs/src/node.h: -../src/reader.h: -../deps/hiredis/hiredis.h: -../node_modules/nan/nan.h: -/usr/include/nodejs/src/node_buffer.h: -/usr/include/nodejs/src/node_version.h: -/usr/include/nodejs/src/node_object_wrap.h: diff --git a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/reader.o.d b/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/reader.o.d deleted file mode 100644 index d3e4b61197..0000000000 --- a/labs/node_modules/hiredis/build/Release/.deps/Release/obj.target/hiredis/src/reader.o.d +++ /dev/null @@ -1,29 +0,0 @@ -cmd_Release/obj.target/hiredis/src/reader.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_GNU_SOURCE' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -I../node_modules/nan -I../deps -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -Wall -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/hiredis/src/reader.o.d.raw -c -o Release/obj.target/hiredis/src/reader.o ../src/reader.cc -Release/obj.target/hiredis/src/reader.o: ../src/reader.cc \ - /usr/include/nodejs/deps/v8/include/v8.h \ - /usr/include/nodejs/deps/v8/include/v8stdint.h \ - /usr/include/nodejs/src/node.h /usr/include/nodejs/deps/uv/include/uv.h \ - /usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h \ - /usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h \ - /usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h \ - /usr/include/nodejs/src/node_object_wrap.h \ - /usr/include/nodejs/src/node.h ../src/reader.h ../deps/hiredis/hiredis.h \ - ../node_modules/nan/nan.h /usr/include/nodejs/src/node_buffer.h \ - /usr/include/nodejs/src/node_version.h \ - /usr/include/nodejs/src/node_object_wrap.h -../src/reader.cc: -/usr/include/nodejs/deps/v8/include/v8.h: -/usr/include/nodejs/deps/v8/include/v8stdint.h: -/usr/include/nodejs/src/node.h: -/usr/include/nodejs/deps/uv/include/uv.h: -/usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h: -/usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h: -/usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h: -/usr/include/nodejs/src/node_object_wrap.h: -/usr/include/nodejs/src/node.h: -../src/reader.h: -../deps/hiredis/hiredis.h: -../node_modules/nan/nan.h: -/usr/include/nodejs/src/node_buffer.h: -/usr/include/nodejs/src/node_version.h: -/usr/include/nodejs/src/node_object_wrap.h: diff --git a/labs/node_modules/hiredis/build/Release/hiredis.a b/labs/node_modules/hiredis/build/Release/hiredis.a deleted file mode 100644 index 7469e5b5aee513b23ae21594b71121e3619db4b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57978 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 BK>Ppz diff --git a/labs/node_modules/hiredis/build/Release/hiredis.node b/labs/node_modules/hiredis/build/Release/hiredis.node deleted file mode 100755 index ea31168a2d2c5e2e193c56cf0b9627244b208d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61740 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 diff --git a/labs/node_modules/hiredis/build/Release/linker.lock b/labs/node_modules/hiredis/build/Release/linker.lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/labs/node_modules/hiredis/build/Release/obj.target/deps/hiredis.a b/labs/node_modules/hiredis/build/Release/obj.target/deps/hiredis.a deleted file mode 100644 index 7469e5b5aee513b23ae21594b71121e3619db4b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57978 zcmdUY4SZD9nfFW*AcA&MwQbsJ9W`iD1rtC_3TlSTz#W_b0zq4$5W@sgLy{&ld{jQt zPNr~s8BJSVX?3^Rw(iodyJg#IsUieHg4R_;YiXrITdj#f#cCm1O5Xqfd`wO*Gq$^Z zci(-_?>BSr{h#MN=Q+>$yyxS&7f-Eity_NG=&St0UD>44t0zt_n=o;*-(M=c%zwYX zY-0HY8Dhz3kH=Hx@r?NX|Lm{!gvVq4ZlC7y{CEBCM_hmXuf8=Jof~awTr>OD&qeEE zp4RBnhPJuU+NIIfs@7<2ENUXtK|Jg^8eM8W&xpnZFNv+3-rTyPHdfWVVnuC}qWeow zpmo_w&*H^Gih0pksI|4ZRdO4OyQ;aVDJ`mcxTztwe15}8;Hxq-rIh#&v=NEiKWe zrNi{KG6VLPAfZE{!Ii^!WqKH*ty&(fyKNp+HB9T!SS-3a=1#JLl|JX!wWQTaYE#W^ zOWT^Fs~V$C9^6G&w8Yl%1`sbx<1M_f4DuRpS&9OuXqUA%ulho?wV57uwK0X_P5>=y zG|(a#0$4A8gcfAAt;^b^A_8q|n(CAq&P0aFpP++s6=_v%W8Jg5IBPoCuWPndZ1|a0Gs(Z^yeUKt7%_qDIR#ydJTT6ulH ztb5U(df!DskEh1B^CO6>{k?IqrS0!s@l(ngYqb(R-uCy-iM1tOE46yM2jLR$owaIw zS$F>jWH@*b@k6e5tL`8J;C7mC=S_nM7(Z(Hey|&HbgIyc_V_Mpr@$caT0OhTkzxAp zHgN(SLbmZbeKim+Fh6Xcn&*s44CKVF-!L{Y;Ensj&f20vD>)b&(Mz_sMC?}s3m5f? zD44E9?+DPXJT%;+(qlO@imhaK>}e~p!S9J(R`#MykL64~M0TSEyRZ{1Dz*}Pyy1$4 zMgCR4wd|fVqEY&zd^ZIagzXbMOA&jZCT#y)3T!2g_q@K1U%_+4el233urelWX zR2C%4b9~8mgb3HoFUki}Y}pqaupO%DRVP3@C5}Fgz^# zh=>wUZo~6za)TyiGdZsoJQ(|s<;*Qed@3h?u~l~iQaKkHllP>^6>>y5Rr#@KPiD>j z7|aB7cYSzA$dMKzEx=Vho?L{9*h>(dONft|LLgbJpSZBXWsd!R9ee%o`iT7dvq*bj zex&aAN|MB}LM;VL`GQdL8s{Ds3S?;Vpl{P!;J%L4 z__yjFOT5M=tv!<3+_P085j=)>AI+Va>KN4pD6u*}C%(pMIXmEl^U-iu?2gZ-AIbZR zMgF1?TnR>r)rWGz_U?GZX*ujz`BtL0m@Rz}Aude3H)snX;s+P)>Dj2uD3e#|sd#JM zHEgweyezkYonw?!hWkq78GAa|} zzho$W8KW)gw7zFmXANQrkosc#lA%@kh|#Ky(XC1jT9u)uM0O;S+mTyjS5n_8`ya)z zAn06nr9n$)e9<-~g}r{-w9By%bLG%`&vV7o38qWQ(H((LLg2XLztRS>j~ z%8IY^Bd~+zssDFY>O&CHvy*v@{E=|)toPv8Q(y0@|2Kv0!N7t*O<+D0^S1THV}}rG zspaI2Ef&E;`^&nap4cd>XCwf0Y@?FhcJfNZDw4Xs~4`z z>xg)d4jzR*0_~?q`#PeC%XeoBgurvYuVc4({s;Wyd6X}CEAAqxe=UVzJxTswvat4& zeaT6<^T_%UN!?$Gr-&^453{oDY{y@<-S<;oG43eq7FtKou@lk&8SMS=yMu!=yhyq) zc`ZZ;J3nF0T3f!@<26vsP}&x`gi zwI*I5H0>yr`jHIli+h<1qOH`ueGq}C$nMe6WpGLVo*Et#lvnqaC9q~+b2<5QBh=EzK-if zn1jAMegLw7y&x}aPcH~KLY=9byaCyya%h@5|7+pY`M>D-(pIDf;tuwF>4Eg!Hr&x! zJzv@`?~wE#cHP|CCH zeUTCj;gb2((~$l?^bQ`Wzr%mVjZ9P6Ml+Bs0AaWUgSTIVQ+Z%+;mDzCoQKk53692T{t zLS!_`KV-1%-QnCjnHDS2?F9=_%^BrsgbVr}Dhs5hAD;SQ-^O}8TPZPU_C3^X)#Yup zyaS@W0$-N4ko|+LEN%7=SVVDQ`3#l4j^;oYPuz9`q(fBuaS6yl1ChSnXt9|usQ1WR zowjtnmqVGp22@7bK7kG@aM6WR9dgKHCs`=^K7lf%-qS$OE~5XRhMv)Oc>4cNJ!9O| z_ib?3{mXVF%F{OwT9WZ?S4|{JIty3t+7m4Q;=XSSsC2u);yHkzmNN(MIS0`Sum$pU zybO%xB=}Z3?@`B4gXqnCJ=k}tOk4*j5gvnb2TclwvMM?8qiGI*fx8Hg;#dE2SQzL(PJME`P$uj4_0xLfG!_!oJ1 zjxYHJ?sR9(~BS;6b}|Z zIus94C@}=UEgPo3&6r+=D{@Us8o9bTtY zzt{K6fuY{B$(^7b@Dy@cjwkHf`GR6hj*9t-;2dvdyes5;NF)7U*ZPUM*{v|*y4CGD z2c9}lRWa+`jB?VqN(-UJb9i5ugO|jy)t3Ee3v_qJ=mlkM6_|wWlVSULnF8_p?(0|r zIN*C|6sl#Y>_ks!6V&19Ksos{JgiiFTiFwq{oryi?f+;eT7l$h)ByyT;SHl>>gbML z8@7Kjb*!)B0K!f6#|{gvM(opiTr659c54^`i*RCAMh1@WVY~8m#1u+Jy(rJ&y63Ik zzs(i%KsD`JQ1m6fjz+R@YTC=t0WB;TaBdh#J`t&V*0<>(s&L?^%P_9%KTFkH`?S4( z_q!LR)_Vgd(TL=fJZV20f6WPP3fZrqtq$6KsbFbd*$K3g(^A2L96PkhXI}y_PX4m; zA#YzH?nJp2@=_U>BmGlv^>rkW_^EBajw!s3?eukw=FO$PjtLN=IyKvCKi2+UsjuTh zc*HCe+Dx!&f6wphcvak70X^ZS7QzNzCQ_LK2X0-5F|Nk@15gPcSY^eC64Kl?;50NU3@I;>P^i)yLS zR56AyW@qqnxrNg&c;N_j@umPbTLZqGWf8kNt^9~n-R|r7K64#m5(A~a#4qrW=*|z= zc}3N!8@+g6sV;dhoOtgX-^R1hav<{~&Z8_c5&Pgz3q<`&EfJ43?QEJ@#3CZWcT*Nw zSTINNp>49Cg%(I&omw;4$BqJxMhC-q0;v#73Hm*mii~CDF<(a|q&Tyz{L;7Sr zWd!t+xw_&T14TxC!6^`V{VwA4(Jnrsq9pOYS8 z%mwzH0);A{0q6Xp1j5=;?|vm$=f@4s)XT&ACAYfbSR6A>CsnO|F@|z=L_BOq z4Coh)vA!>v!|I&ayV@Ay*LQ{;%=jS{R%&K`*p6`aZ-Vd3S0l9Wu~O3jqrmp@?S|!D zl-|@Fpa|I4ExPI;vKVznm3J0p-_GNkk}Oe5v~F3Zzr(@+4tdvdT;luET0DmnV4vSN zmIGNmWyod%O@?pNOBnD3wu_c#l*k9O{Pddb49iYxwbu@{TXpGJ(E$27z5^NcFw^b{ z*}ZtV?0F2b4T`x7At6<7?_Iw>ka*o&ZJ)d$6?}trbQAP5N`(#AowB?~%#bK!`4M!E zsv`?Ks|Etzy^5}G!GPc#b~X$Ioo4wE^1c$8vTjo#RpZ5w3N3KXzP#LXFf!ejci!mu z*Mn1{?Y<;SXt-`K@)e%4dSZmbPR6n^Z+o<_2nm9|Zxk(2-z8L0`f1Ftr*|+I8S?uz zp3q|E0J$lrZy%l#-30;UZeHI%BbY3TMS$BMW!5c^&6hWgzGN+O2f+f~sg1E2vH=v? z++i`>)QEKFah=<~j#36dongL<7VJY1y01b?2R6&&KPA7MaOy_9KGd|c$!B%V#Or0? zCj2NoV!&DdsPr@C)h0-|+beOhB+J?ZE5P-AuS; zr({zql&-prnBP|tYWI~?clt_dx_l*zw)sk;-M*3)2Ye;*qrQ@L$I;{$SgE_q1&3rM zFRA1lTzZnk*edrVr{b;@cjy!>+zM%)*ki~Owx6`$Qi}o@9$=hd|B>qf&vS08IEk)! z-8SE*mr+J`$qrbK?*jG-(E$fiE4?S*)D@!-FAjMq+x9*?w8MADIz-GCCTOqduC{*@ zDjR%+JgV*IBdJM`=fk%ek=Z9u&#N&_)p0#yneCiEmEHEip#AKcF?|;TVm~=l4^Q^% z*!lyh;N(2kit36tr>9~CIq~g5hf)1DXvcR{+fO;69cbtGqn^4eDf#N0d*4dhtB%CJ9dKi2mEe1lWg?TD9!>v~wpEhn^1RPF&Z(8Wdree#z9 zjE>F)y=c+6Y`2m{=19MlFsc58BsY;m`g>;8Ctv2vO3@7WVJ4a?y)~ z3m8L!D~2swBu;zd7YQ$?T+D5z+VX^aiym$VFR@^jS*Al;CX_Ivd>iwt&MuBIl7s8j z)T#4GC!U8Ez*Mu~O9sB(LF|KrGk1((9qDy1LFPd2S}3F3NNI zuaiftSN2|PL~rk5GVmHJ*AZo`Tz`@C%Us_?^MKJLR!;4j-riSw(<-o1HAfM6xZI$m z+$#MtzJF&JDJFE4CB75lmC(y*V`Gf> zYtRSY<__!{9Fzs&VGoG0geGz+F)$db!YlU%T?jbwBE9fRon*nWoa#fE$~;?4Wujm7 zCAkQSc}zws%jlj?$*g=#{HzlR=72Z0zwDss_w`^yPF45+yJ|;wpj961|BfDS>Gwet zX0+LQUKTi1HB?xf>|XycRLF`oWyV0v zdYH+x_Xz^b>l5$)2HJZW!qihDvz|6eJqdb~OCNi>`cA3MzR%(zT|d?8MlLGZzi@Ay2FbeHuo{Sk?<;xO8$~A-|6i@l**Bx390uMWMSOjuHhwVN6 zdx!KP)bPJ){KfX0?cx7JeW>y*hbAZ%=ZTJ2^m~tDSS`v0A*^Gg<_kA$ef@vccozD6 zpY*(b%AKC^K8uPOt%6dut^U{mYtT{;_TT+BQEn<2A1F3juCjgUy%H&1&{zXJJcoYs_EY-0E+Nw#6XM zig;tJ!GCMK@iq~xA=>6&g*~KxXdeI9`L9u-|KDFS?}jzE)`~56X+h=A&*2+wmo_xV zSKsVe(Y!J`zj+q6XwHZ7QFz4Wz;G@vbiLe*ElF`JH&zx&SzTbf4p2=mP~`&Y6DB$ehoD!s96h zG?h5q-|;V?{TGY|LDd+G7i&xu|E2I=P8zsx@=wrKoilRU=GlR(!z~{Jn1mOJ9F>Io0%FB+C0)qjLJzdRB+538QYD#1jc~82*1Pl(fyQv={Qrl zq0M>0#E6{lF(RfTkNn|Q^H0!O=Zp*_a&s!lZn{hgxLyhGQboHmO)Jw8PUNj8b=8>Z zX&EMgW{IMIW*B`ccjo52YRIri#t`8pIHp<#WjtF{xcAcG!q9zE65PN`Xv{70$>Rsj zensD&rmsF{WC&@PPonS`=H)R(6LHb328AEk*_cG8o5eq^FX|x(0zlL$H}cR4ooSk? z&AExZoM#x*Oeml7->m4w)+|jo?athpcjTo;Y#x~ymHSOE>8C6DO^SXWwi=}4u4Y~< z@*R03uVUUZEn?jd*DvFjrqB7J5R~yBQv9yxRp+TFJ0V?ma^DmZ1jdkFtY+f+b^Ox& zf~j0tRH_(vV9aM^3jH7{=YSvX2L9>vQC9&Wg3#4MMN?_gOcUkLN{na}gw$z=qMMnK zZe^P8fxm*EA3UB{bmNEd6LqbQ%t$kkk=N#2E0OnkO>;pW8F)PJ#|Im?gu96U7TW;S z2cfQ+W2S=<)3;R7oX_&7brqs+Q3FJgo;HSbn-yI@?$4kTbz|ljKfHdd=&DRQ=zfXJ zB~hmjDVm2&n&2I|sl4f%N6bi!%$Y{w@EB45u{1=-`s$gf(y(A3{HxC%$rSMxUVi*a z6|IH)w2X**nTng~n6GHuZA2uI*GjS=3Ng#@T1A(s43p1&e+3`X?NxN_|4o@b&B$hs zu_(Q$|9>IAv$@g^_kMglDS@s z!;|-_*-n#oQZaBXnovG^-1?slJd^&*Yh-`}iZR2ni_!6G{nr9x6mI>A#sqjVex~!A z54c~5U#9r;ZT;={!XP>rvDuLba<_QR*y4u53F5uKB`~FvvzLz`RtaR zv|A?15OYS$E904rpF4i$Nv8OFua)7xIznFczdL@7yRW3n^Sm|a#`&C^F~^8!l7#q~ z8b()wbPq`*#_GU6qVN`6>Hbb$#DA{Gl^Erhdq(Rg$9&|!O+_Kb;-KdnpqDjC;pZtH zb8sd7QI#2D>ul+xYGIL#p6SGuc)~aP}M^4C7~nV=u#Ij){{y7-t2{%$u@(f>+$oUN{P3g4@qbx5{{lyjTHwH|DRcPgCafbQE0 zZx>Ip9pddHz=hr}mL8LoKQFmPdJP!3md->;&ze2l9RPovCLRvr>E{A>H7dY=rRYEA z3UNf??B`6!g--IHVuHBuQ}}!r{)WPJJ<;B83w)%fTm$OL4V>h^*@X`(T$f|*ohQou z2+w*AsOwn@Pq^?82z+Gv{aAaSujsdEKwUqk@Nc?szrtBROm~^Wzh{EDzf$44{Alk9 z3g4*#buCx;eizQiTn}5J;qE%npNkS&AoQf(`#~}bxLFr;sHIu(hAenX7JO9}e0>&t za~AxrEcm^^nJ(`6r)wAg9?!pKp?^rxSE`CTOVRIBc&Ebk9K;J*_#9RAU8>^}@73V- zP8RxHw6mG?e0CQ6V_EPkfHS>I)c94rpCjJuv(R(Pccyq}Wx;RBf;VKrTe9Hmfm6=X zk4go9S?T$!3h!39m=A#8R)yi6n?qFOD~at9&b!h_%?;>ay3igm6r~uk1D)d;bn?{o5ID!5HQWB zUE!TYl2Fro^da#&Pg^v4+bmcKXlSB&iQ1(R9I)pv)7@0W!i{>oViZhj&RQ|XAFLISy{$u>deHYS7(^>&PY0`qTD^_o{{eA@-olT zXnif#B&Nrk>S9M}uIR^g#-1`)4XHCQ|&GJ9GevUv9N>GMMK7taq& zi-Z;nDo-7(Dm2%5R;WvKMICHLEM8pO))sAzEv~O^Xq3hsXoMoxO1lywb+RBSBPg)` zAdOcTUPGoAB&k>}0U>NrxR@A*KH8e3Ws1dh%Wq?}(kjK`#dTb^T72tbO1gNlm<1w< z6fe_~4(f?W7DTRF-ik0-#Y4h0-!lwikgE~3U^#q|=uAi~EVLoQ#=uQEYYp6#^EQLODd$z{{Ymrh5mG<~ z12_5efHNKGi}2I>pP_KdZ}OjI&{NNve~p2g{1+PdSc89k7XBRuZtC;z4L%(5YB|4W z&{rCGuYsHGL!N#w1g**c;|6Z>x!l07H~6nLaI+ruXTgsfxXJ&c>b+Cv*D=IF=QnUu zpO+i>WuVh~C{wsQzbXy9%Amj9;B&cw=X1gqPRpbDf78H=;ji(B6wY`<2L2;8m8JQ- z06)5i4ctuEZUZj?o#y{Dg}c-BikcGB{0jwlkEdBpED|@3RKbp71GXBhNv7<{fUaF2SwC;uxAyvo4G8Te-uPB|?DzsJBU4ID3H!jaz0-%11L zyRFve5QBj`vRnJ?DHhex2C%DBD}J|LQVuQ$KwMZr0xu25z<+xgSPka7?dBzd_-Y^D6wb zJYO~FO}*_laFfp{Hl}doZ;nqsrf~8v#ZU8}Xwc6#@C62anSrm$LZ32lbNus712^S7 zXyB%PR;dc;Eo?)*Ar(3|=7K`wB^k>1R&2?{5FlYX{=oB6fcz|Hdi zjV$=@6t4BTnL@z5X5gki-!gDhpMNs=oBAxeK=PyfraV&&d=_TvGLxY>_a_=!r~lz)L=z=GbCzrnz-1&QY0WZ;zs{#^qP z8u*h2Zt_2yg%XZ(M)A}9KWpH12ENL`O?t<`YYqB`47}dJ-!X8rzbm)|L~zV6b6j+x z!YQXIf0coo?cPlWz6@b>y6O$Q+`!jl!5xL?xa7Ilpf}|yy%dCSlyfRJNq)=P10` zML%ERSGw?<70xjmolfsUg|p41)A(|w2kM+o<2#g`Qze|nmn%M%F8p~#A9Ud@ir#YJ zF@;B5_-cjEap7wf&N4%%aQEiU{%g~wcYm(rVpvBD+e(ED@pm50W=Q~}rJQ{#Sx>vE{^u3X8$Z}6F{?s@U6 zdz~)z=&5w!Iz8_6>iqy+E_yBhQ5Sxc5y1&7Qn>1PwVabExPj|*Ep_2q5BIrnz5nMa zH$GDGJ?_HwKA!?5mzGDb?@w~!dVPPP3)k!T+vifSE?loiZ*t+KYMi&th3j=^p5iv+)$7jY{3=D(>&rTSbb9sra!{2=jqCO0 z-FL;7p~Wf_q%YtUVPkz>-FLSRUS2ey5`G@~=Jfl4@(<>}d;J7Ue_R?5q>hF2V7v~E*LF78rO@p0r zWs_@XJN$pjKVh3n9GvD;FMhD0cO2#>CWcGi5syweEMMY$t@N{hB@So9JeYjOX9JXHy>}Utx|8F8t`fMu>!s0aNf`I*kN&!qp?__}v+ON(N zq&Tw+E3sv;A@xkYm|AcD{mD@B1pIx$=agL+NdrsY>ZpI9pkmonAp%cEW~LD8M0k$%JxHLi>O9aE~zq^{q~)+=~Lo`S`o{oTPFJjJ!&pjSuvUY=T&2u;2J*??pIC z3xyBq#}x|sW%cag+FzeAy)%^IuV9Rt&hW3BXR`y_*$q>H^CPL~QJ#B^*uUYSYI!VQ zn`aQY{V<1)Iyte4&LbUomK+f1Vb1>vx-`k<;#{|1m~D_}fRzyto|-@0I}2jrcy<4a zLng5ZU!&l?uoaN%UhGsa3ybrEO?Wcv zJdE_hM$u16D`bT28xQ!DbqfeJI*@n;mdbwdw)HPoDm4HmXa{gptH=sgbqfO8WpWUtB(I2)u{08t}-9rwYn>>w@dkMG->XcI2ti=*Rm&pm z3G^KWNxFG?H3Ul?yI?6&DWdO3@YOZ~%=*HbqHHOOlJ~`9TOf@pYL@*VEhNDv6BQ<^ zLfOGxOpB`!vX}|AsABONNFes6`*GF9<1I*|O4uEMBdJG4N9Kqqwv*|@d>gK}g~6t9 zYJ)WW^Dx^B7|RJ!wLrqOMDH=22*2{4MVlHLY~-mQIBO|=-(j| zQQj8&1PUe-Ewdpiv!Npar2jeSkrMnG*S?iN*qXf>uwUw(HGrln4n(jS+x98Hr@pQ! z)>u4!@r=;?>5-E3Ben?faalChhA-YUx5SF)&0ZXuJ9qZn5*%l5Y%HEof=y|r=iI6V z^TXAl*=~H^tf0cjE;WP9ubQ)X*6d&?68Ln9r>eH;@|a(4Me{SpXzWusvyOG2zwQWg z)-%k-P_KTU-i~{DHV$W)^*KNs1MK7(xfx@``5ucja4G(YbBZCHQNANLl*$Wj9uY~5 zTq_Uxk*|I)`$n1;XNGaMvwCyhoWzJ`5{5aIP>Np{Y2dDAIZB^J1hw0PV9FO^f<3+>2tO>;6(KynMe}-t!MrIhYs-hAu5xlhRC>+u2NlhsJSKe zc*ed{E)8(x<#t`?No2qBWPUQ9d_`EOu9qoXy$UH5dE<&#d#EhXk0Kw*^S>IN>oMdx zA<==9ZL0eTo<{!iA@H+oK2+XZ}2Jx%+p5=TnoKClf`0SRQe*4whzkcUE z8yJ^W-SKm(CsX{r6b$YmSA?!dNtEHAbpM@a&lqK9M=d>r3?SOqL=Xxd9GA=%Mc{)ZdbVD!rK*&F7XVP>C9ddRD98JyL$m-!oQyd ze~)`XYew~|FJCiMZm?`301j7UkW~xv(N_= z{Q*TU`c%-f{mB$B=NL2Lw`IZGvf%AmaGvGM#Gmg#OxF_C;fcN+a{gNudJiXwxN%zS zVb+`f`MpJaL9(eC=j@x>Vla2pGJb;GfD96`dmT1yhV4kcskQ;1u&iCWh8xoVitX%T zQ@Yr_Uhc`f1s&V2%`M-5dH1v{5!|;;n*c+*!Nr)?V{WZ>f4XsKTq{Pi!%}GMU>+Lb z4x>;TtGO#1jB1xIh2@`me1}ntTRl*v`1&R{;1Bt!&EKA7wGHW=;F*|;UD?!6A8CmEz8aS8dHT}OExT%LH z4cv_PIfYYBF0W`lzso|uj)ZVbugU*z1NXyE^WoV*I?{7_Qsb`~xG9fMwLkRs8T1z^ zoP13Br3QY9LBBBz{vCrq+ZQd*!v@ZwhsL!%8On36fx{B4aJ-o1u))BK4EnnboMTGO zf0u!CEUoeXFmO}Pdd{BSmmBmvt3^lL)DO>U(GfTK+-l&(@YC@&D4gj%&%l!gy_w#- z4cx3p|6$-}zI;%%+mxro;D51!n|vlHobqt2qU8)4^k#Z*G;p*2K49Qu4L+w0{0aj< zN4>vL&dUt^^9F9}bGw0?@%j;#j`H)TT}0hzyjwl5cHw#)@LdcVwDiUUXgskM}{((-F2{3q8^N{zv0rI4-?b^L66w=(f2Y!_o@c%E~SRktUS zDjHeseL0+p6`j>fIt#Pe9}AQm#wURCgZ7eBVw!izPA0#5=e7gNuZEtsQtQu>Q@8KP zB@Hlw`QF$pSUU~c{+>$aE+)K|=f}>&$B(eq62rGF#S}O__?^mpOmX$9c`9wkSWc3Y zqW>`Mc_RK_5076Oedo79UQr*r8}2`3_mKviFOrFr2AuK59sPkky>>x+mYncBp*(7= zx>W;1tYKF;iK)O>V!lOGWFG|+b7xv!+7TUQXVRHBU{?*4Jm#HuioBJj%wcvicxR@jUQs4jshp~T+^SPS zyKW#@a@4LmrHw#yWk{{1a6v1dlcF$px&w1{!p^Gv&a2EV*mGCrxe*^f5KvwBXRG3| zRo5}XOJ=6do+6jU@W}xE1y_8t6%p2*g86a3u>U(0ubg@gq8QmP^mfuFKjMARJ=eGT8Kzyw4IcmqMyJ;YpDk`Y1dpTTj zxa}g#e#t6%!Gg8|_)u0X5_D=$1#@c$BB=(X>SfGcLmNm0O1Fr1UtS@;xV8wNr;18j z;)dROpF``14`M-hk-sQ+qWlT{{paMz+%i6tql^V_$1>Xvc7|MGD~A#NE=-$ZJ!Y$} ze5^BzXQg8P)A%%>`ogf7uobqmj|A|EJA4Zw49m-5X9hk$5X#530M~+u6Ovp4?bqRp zz$nG2*n+K|BbQY&{*Oq^#j1S3kZu?Brn2Ek*xsu`97Sm@Hztks+8i?Df16!b`Q75v zT+I}pC=fQt3xoLJ1_Zbzx@;>1Slspr%n+8JO^=tyLDti1(z2YNGWlxm72=m{>MO0Z|2j4y`_O1PF*}<|CWiRf_ z`>3bnxP9Y*Hz3*{ta-8tO7q9Fu=DJFFR-1O2>7f6VES19_oN=Yr_=cH*u`xoBV>#vVnQdXHlN^T6NE%dBoE20o{z;f(0F4aIgFhv522*N%qrhU+3YoqKRV` z>iPa%#Za$Zy%%*Irt!B&@ChbaQn<|jmhX-qVzdypd+bBIdoRLQNRqUqBbFY&fg5J* zTMU0FSaKX6=YtLG&;!0Z?u3_Bw;SK*5Fhb+nO1f@J)v$62=OI~E__#~?zEM=ZhvCk zUVQob9>Pvd7Yu4|7jdK5PeYo5_6dAhvIkbb_XkVfz{e#-4%Tc#S5qwL5NMldJaT*; z2f@S%?G4z6L#ZoAhEnmtKw_UaI3@nTy4FByVUf3DQTK*T&qllPy(g*I{B@CHG%e_zhQ=F84YKr`{cHH)|9DC|w$zDZrRFLn zJ`rTu1NgSv0c-cb_2}LrsaY3UW$#)gyZiG+KUZzEk9oQEb92e%dR7y_cE1Z5+V&Vf>q@E-<%;eCR zd^>Ydc$)IEb4SDdbJ53%zWr^zabVb&xO;pZod_TH{<=Sib|cV!3g3IZ4CUQ-C&%A- zM$y>`3Kd!$D3+qwJw|)SmJ&_rj7UYl43F5P)Vg3JBg$Wv@ixah zScMNg!!Zx)g7`jy81Kl>D5GWChHuqf)bV1x5cih+3Sy; z!%wO8_n74fO%nFy_&RJi zfZRgfzGsH=3)0QN$NuE^2~%^v6;7@4w!e2CMv~io8&6U+{dv}dR^9pcSl;&rf6Mko zB&Kf+3Wn4(@_~F}_~gSn==vikg44Wyd}9^_f|T-$T@_02;#*qwo2eG`_$P)p?c)$8 zTz7s^*nT`>PdX4t3qn`R`nB9`2fYXaajugN-HKXcp8*@kw0ZqGu9e@wx!Gdvk82D+xfV~` z;CJNSkjmRUB8YYVAjxM4Tih+Af#dv=q>aGlIK1)5I9V^~D*30^>0xJB7!02^<_1zy zE-^U7mGhR84zejeen5I|g!4(#ANwDKedbwXNG9fS=?8Zy|IE1H&vdb_(yid1_MguE z3o=mgS1yuSq{!*_wu(_H}y#v@$&p2B#CbU(OM_p$$5^ zD*oxXrOkYrY!@`!{|XwtXMDVi5B8GWN9CXm_FL38k{nTbLSuv} z>*><+zOF>aksqNZ+fCtanwz9Jd~^?*yk(5<-R{A`{JKO4qS&}JW#K2h3d-rVB$*M z3iWu#a={{lBdzI}x8(U>4PS<^EO!2S25FT*4kC0D8`q$6du9Wk?bI%QzSj@dOK|_#CdvWNU zX^)7+sf9CLuE??BxKxW$s^N8sxF3-&pV~|Gzn&3iv^%W#+@qtmR%vqi%>m#{pXnxx zhY@Gw)f9zuKb7e!#lwg*ED^K5GhS7^#1sE!in|eFT|5n{n@oF*X2Z|jmXbW01z!PN z>}4SloERJ8x(dHceAZ{dlUZ<%iOBx|u5>zmcjKP;ae=CFB<}CSFH^kVQS^FkOm`pO zS9qnWfMOg8jBi<)`20lCFH!WD;+bwQew3$E;nWKqWKX8~6wFCLDkGx6b`AM!csqF<5O_4@nVD0&@LrmCsP>C6gD)4jZI-MQ<%|I zTa_~JQc7EsT-w$IL#(iYIow<(j7ws-5QUItFmVGqZ7&l~OXDr{<*p!UbrTQq7JTUh zpP*}^&$8C$RbPm5$Uz#`qRDLY6yEqa+%RwPti9`2w2&(=AZ}}EY!JphanGcR z=hkQ&{pzvXtPw_Q`8#vd76@Q26JMws5=0vN)Ld&@m$iwESKYH1d$8@-dm%U;p=0&r z7(?Tn*QO(G?tOYlpb|ItT0F0CHajeunokbOA07En292-Cf%J zoW+r^$Xfnw2K}W5{)$1*rdiX!nT38LnZl7j-wiaqc;Ux0vFw;Q-g ze@x*_7pt14pQ{F-jMuC$DFZk4c?5KHq&Lg?c}6>I;`$tvoBmT-=w}Z#wrXB+xA(;iWFT zK;e^I_{&P3au;5x=%>2y3lv`I!u<*lx^S&e%Y_#!`iKkH`Q>-v>QUI#-VoME?mEV?Qr4xJ?p3o*Y8t#s=m{k zKmFchxp4j7wAzL1_on+?xPCu+%7yFqpxU-IO?Aeu)xTu_qwMNQ6aTY&RtG*o%}Q4( zE|oAB`vJLUQCkJT<|iw$p}-USye0O({Sg}p2MYq128#;ASWmT_3m(HZsQ4%QZ^Qy; zhv0%0*P>#}IWJwms>6m)xn_#>VSt_ja_icVtJZhUnAjcQNGG0UmSuXY-X3LvW=yFg+eu$MLgQ$Aq02m3e#d;DPk6!^CZVFBZ4sKe3!CVeA!(RJ0YW9AzbL_j}@B?`0NQJ)+oI zJyivK#4eSdD$xVr>L-%k?gAG5Pr3HUxzj6>{{om`f9RA21F=zRPXU!GqC*+DtK0Wb zH+RXRfvwqDjM@)Rn#*7(>QP2nx;Ekd&)AWJgyTQ(3?p zT$NHQ{pz_`TaGK{!fCJhzmtL<`->-4O1QSQEb77Hw9V=g5MMm?I0i)l=@uD z&avz&*$SlhSYwA7H>Ic3&vM4S%0FPXDPtz7Mct6RxW9ny2=>`QLB3={s1H^@-t66v zeGkyt%hjm|ikPqc9~t78rsw1uHtUjpi>7xTC}QUA@*^&hEELzC%6#m_7}WV5v5R%q z_n#}`x6p>J$@ln@HwunNdMjY?1|r3=N&1N35_awreEGbCo(iu1!AjrV`%b=Own}@8Ra35wXrM6F91!G#*uC;y!Sl_&TcBy#F1|lq-I;WP zm*w18FnDAB5W~$N6zxu$UuL@JL8qkYn~v;E_h&Vhs26}Xu%wCI{Mh|0ns@Fg4|Q)l z&0X-9T8YznzAtm?C?L*0sXaW^-oZ%4=~V*}dtGr&EV(}d~v2n|pj*7y4S)pz#Wuaj7gt^(bx=WUu#Cmoxdwdh=^eJUQ}7kBDc-BT%aZn8Dbp5MM;8^o!(nbC}ro zE#x5M>VJ$qmeD?>ZpxF**`L^)IioE5o~;OgUA-H-aE)D>4CS6EJheNe)o z069$cD4wl3GI#)6T5k#3N5wv8QGR7O*ok>X1tK*L4gFq_v&A?UWwifE(H`nE5X1K9 zbL50TzK&0`uuPeOooDypPK?OV$_*BTFq|k1T)Z#r*+#9(E1Kz?f84U? z70k3RIIbD9qw#f6`$K%u!Pw1lw>Qj^9mw^DO*!gdXmfI)pK zSRm?xYOqy3!!efEG8g-ZVSuu*+eay39Hu2bEKU8?gp(88US(fvN>;#?AX5{&DBfDikr6b@J&`<=vj+gPQB0&PT`8vKsmZ?WL-st_s z3FNCS^rgddKF3xZ(z?AYX zBL{BOch;%H4;`<^%8?+^^*eV93wQRu-X~eeV3djtln{~aUGF4_*!Mfpd$tSQd4xkB z7^%|XzQ%CvQoc&25vdbF-$e!Q+bV)q;()|v$T8TrgUxfs7Jcj)=NSDh+zQ=d;BbfAjIKxeWxtzl*)cA@nrti0{fm#@QjU8?>~$BWZV4&FhIB!20IsRL)uoO zXQZ+~8QRppO6P9`B_iN_IPu;{Uq>@EACLlUUE=HD^3Ya4DuOS$kKxdnQVS~svV-J^ zts6y@1Hz44KoCg$Gn4kF+|AtX2e-jF{=f-Q+c7ZYXO_i5Em?I@?dD>Pveo13_?Ae3 z7+X(8mT`E#lsO_wtB5uJ6%`5JFCEQ$7`GTqSXPQUQ#iof+`D>s<&@<)@m`KE`6|Q= zC)WGDzAtwokzr?6F(wBRI~zq^L1P1?lMRmL1oC}% zJ=Srs+85l&3L%)hgrr+_EzrLU z2r|}B%PI9ebkOqt0*&G}%W1(t1dSs*Ms4mf)GgR0yU8$ChCrPHpw9YkH0$ZQO*~`x z@>^1$eg7i-ko?sJcn5iqn!pf~yc6ZQzT`BDo>-mli9ew7^GN@ z<4+yYV89t@d|Uy;&=*t-O|9!3 zpdV;T5vl^F2I zX`Kth&T5QxLhWIvEMix089d0mjiBsFDmlyZv9R-bq`Vqbf_e*HtDI_(g^;{ws1jYy zwuBSQ{ocL{kq4PY>C1sv7_UfBn&k+ES@!w+`<78Z8QbQ2QNm?0%jiAl{k_?@zE9}s z@9SOva7Z2uJ99kEsRg#)vZcw1pWFL)@30k#Pm?`vPOO3hVyGRqKL=w|(V=(aUNz~e zLuZo?s!V6nd1zC&mqTPfL`%i?H+|;3P{rR9I>xBt7xwyu7_l)3R0t+)pR`2BP*;wb zQY~;o#~|`G8Alt2#6L<8K@?Xt?r;)^WSZhn^dA`NPZ&i$B<*9NM?Dtr13dE;u^$s> zgDm@Lp}*9+L(pNN%pV74iS5_qspm*tckg6YK%9oM_eg)FCp|fPW`3m4C`aV5Bx0u+ zd(7`E3AOu5sylrpHC?`vMcaHO(QaSKiUYoq_)%ZUy5kti6hu`6`qT*{={N!kV#0`Z8OY~RmFpZ#>ie&R2ua6aEcvZQeQ_^XyiTiUKtpKHEq zX+s@tEiI3YyDr`qUFyH~T0gcRxrpSXeVwPp)8fDQT7Plz%I1cp{!f;a!hUA_*0#FV zhFhcOjP}Hv%%>I2_{?#0D{$Dx#8#QcHRGoNTVa5y__Er%ao16ThG^TBMv6)p{Wxy5 z@DzihzOi;$oBuL@>FNok{|(ZD)LBH_jw_sMyfzmfEJJX$mDrfJ-1% z%_~-zek4-<_`dKwtyL|q;33Rm&1r3}i?+3CkG3@Tba=r(*wChJI~f%J$=kp2EE3m1 z^*Za_j9Q;>2&Qs3<2`IdPE4MMh=}75f>y6P&Ln+Eoj1vm2Za298i~VQ&%dDZZ;?kZ zrh^URV~|W}Y+hw$WrXZOlykW7x|0 z8Wo)=+9GY>hjUiTK|(&8m4B3cw7wBv5O!E+F=06OL>>HC(cQ!$OPVf~8{V83OpM6A zPaK}XCKs+tA62wJ;#JV%+>1DC16$9VN8#t!||+FB3GP3 ztCn_S_4;Q^ng(Z^#96g3ke4|2LK&7)PPpgNG8ku|9jO2umO2#jI<*5A$G++|w7NJmaJX=aU? z&dba(Vf+gnU&(mj{*`}5y6Z`Yyb~n}xz4hDv!b1A(&8+YwK;D_V#Hdq6uNF#bgNCe zoHpUlGSH>`=bQeLPgwJz*WYYExV0HuWNXJ``)b*EY}J*IxJDam#|t0ajpvuv8$B>$ zxI*+3y z+0I@qDV2m>Ec9^PI>LC=quAFDr$s;3%cUfIB8ACaz>v2)$r`h$#VjJrql7i zX@a=d@#|})!rbA@3uVAX@{<17>DS?BtMIDHNYizx@b{zB=wVKhAzBftl}D=)%W&whz9Ah2^4-i0fj80+E6c1GA$CI~0`MqG>WBVMW!CdOjGu2XoW!k@)6T^K*o z`&GVb`o#(_Rk%{0r&Zxg6fVYUz&7INP3Oi?`DcEU|2CB=bMQ>}J^YC4!lqt7#F=;E zl`5ZftNxUt-==Ue79%6LOlRYM4V-)mxbYNDjK^^8#m|e~s5+e(&ZJ$YvvgjFNInNt zL1X&qIOj(`?cz!9OXY2uqMySIg=>))&kYLiR=60O!S5!8cPT-{*b6xA50k%kTHbYv zzLJ#>PK>{B{i>q(6NEcoUOeAd_!9NZ{kC*GlSBTM;z^DT)GhQm6tBj3&2(l?;-(gd zLgb1TV(6K7hY@ckJKn!hxVxL<3K8ku?PkBg-MuuJ|couwZ7W^w&@UATQzh}W| ziy@PoyRzWVWxhWT$!nY}W zzT&ef3m=c3N95et^ajj~@n#lg%{+J|64P>4ZQJtn!-CqzU=%M?@jA>SdKQzosxeyI znkKj*y2c>TJb+?$4M!@Ym>XQ$&?e@?!kCO~sBLWcLNpyZ2!49bZJs$dn5LirI0>od z<>tiOmg{LZjS1eimS^+0 zrtEzU?2EIi;^?Y4(<;udmWh+C!q$G7Jo73}xt2*!aoDx2EQ=9-aV%Ax+0@55^^sR~ z&{br-$QPE1W`0bdwyiDN8e3dn+t4V>MU~so{u$Q%)j3pLaLg1eG8{Rj@%!4gC{L8? z>0KN^ZCa{T3^COa+@Z3lGf^PwVODdK_=JH`WR*`%Q^RT{ur$_BAOkr*1)xHt3+Ygl z@Ej^|8T^H+hRBC#Wz1(xItx-vRI?1?h%e6TDkbQ{y+%4@$>nz#BseWzUmtB9dKPs^ z65Z6=5L2~QQW?NXL8tX91Xzi)(<^F`Y&n-cB!5-})AK8(6vKiF*dt7?p$$Xx<(Z71 zJ_GfV7&o1XbG$%D`f~gp`>%m$$miN zCZBm(@K27&Os~H&?B=g+l(_M4X5n+xz)gJ)WWh~4@KYd~*27jcbZ5Mrv(&hGcGcvc zQtvfXw;w5q%_Zs+E1HWJ4jF)3?9q(m|q2|99estpuoMQ-0Kgqx^H}LBe z?&e=>;C#o`e7<4e9Mfq0nbCNFBOf#0cdJ(z;+6Pm`d=D&z`&0gxJiGJdN0%I)qM0> zPU2>I#~Jj+2LEdm?oRK$20qQ8KWOkNG4LY>eU*U^8hFsaC#n}s%K1qHuT(hYG5NF^ z^j8@4?OEu5Vc;Qyez6*VYQ0?mKe~DYH}$r{z^??I*7GWbyY-ed@EHdEg9aWp@C9n{ zNItU-{JU9jFDJg>NN?s##K6t;eof&_?>PLl{P!C4a}4|e1HZ<=KYuPB;K*k@ewxoZ zg;Smz4gAOF;Q@}g*$(_k;adOtJvm2>tBITXKg+b*_bWNrR?}%*&$s#oD&th70%2XIBgS7BesnGJlE$^1ce!xQ|Hm%8k^;aT z75_v0wVXmg`004l=~Ce|zJxb$mJ8SOwk#fs;S2Ba(#HM&$HGe&C`?8B(&(B_< z;@9+gzO~YY>v>geYg5zfdDSi#y`EQn%7yFs(*YN*=UEEXxKZ=pruvC;7k*UXH@k2> zZ?f8j>v^*qIQUAUg7_&>>& BK>Ppz diff --git a/labs/node_modules/hiredis/build/Release/obj.target/hiredis.node b/labs/node_modules/hiredis/build/Release/obj.target/hiredis.node deleted file mode 100755 index ea31168a2d2c5e2e193c56cf0b9627244b208d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61740 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 diff --git a/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/async.o b/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/async.o deleted file mode 100644 index 91a15f9774e306ae844e9cb09906bf7ade539a92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15432 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⋙;>&u9F`U6^?gEXE$jXO$5I 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 IT-;Oq57z7cq5uE@ diff --git a/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/hiredis.o b/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/hiredis.o deleted file mode 100644 index 41373d512f930016eb5c0488f9242b9fefa16d2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23568 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 TUwp!b%lqOYVULo(yf6MggmBK3 diff --git a/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/net.o b/labs/node_modules/hiredis/build/Release/obj.target/hiredis/deps/hiredis/net.o deleted file mode 100644 index a526dc8b5f08262c427cd0bf58857e5f5e0e7335..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6416 zcmbtXeNdFg8DBU+Dv}qIwxOn#vlWHW+<2%F&6x1Q9lX~ZVENG4#$1l$PHuoZyn8Rv zwi$4aOWZk5nd#7J$Fxl+%}l2s>9kE+f{GZ3FljTf>ZDAeYMW6(Osb=Um>B8v?7Q!= zo_GJWJ9GQ){`R-e{`T2tKd#eiuS`!%BYH|BPmqP0juLWU@j|(b70XC2Sxg#j^twVX z%G+fqeJ(fDE3uz!o1dRo_FwG6;D8D} zFCWF)6#R(dx@M1USZ^!7$*R#(JN>tv&T4J+AA{J#PXD9Tqt@|eWxX~|Xoa$W1V{dk z{EWOyes?{z>Qs>!pkiqxYseAQOCd z@s68r^bUx=F_?v7_g|gE4~

uta}%0BYi%A2Scx>8-bs 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 diff --git a/labs/node_modules/hiredis/build/Release/obj.target/hiredis/src/hiredis.o b/labs/node_modules/hiredis/build/Release/obj.target/hiredis/src/hiredis.o deleted file mode 100644 index 8a6d1d6ff3b269018ec3d3e032d3d73a241aab8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2104 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 Q(^b diff --git a/labs/node_modules/hiredis/build/binding.Makefile b/labs/node_modules/hiredis/build/binding.Makefile deleted file mode 100644 index 7195cb841a..0000000000 --- a/labs/node_modules/hiredis/build/binding.Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# This file is generated by gyp; do not edit. - -export builddir_name ?= build/./. -.PHONY: all -all: - $(MAKE) hiredis diff --git a/labs/node_modules/hiredis/build/config.gypi b/labs/node_modules/hiredis/build/config.gypi deleted file mode 100644 index f63b5744ec..0000000000 --- a/labs/node_modules/hiredis/build/config.gypi +++ /dev/null @@ -1,116 +0,0 @@ -# Do not edit. File was generated by node-gyp's "configure" step -{ - "target_defaults": { - "cflags": [], - "default_configuration": "Release", - "defines": [], - "include_dirs": [], - "libraries": [] - }, - "variables": { - "clang": 0, - "gcc_version": 48, - "host_arch": "x64", - "node_byteorder": "little", - "node_install_npm": "false", - "node_prefix": "/usr", - "node_shared_cares": "true", - "node_shared_http_parser": "false", - "node_shared_libuv": "false", - "node_shared_openssl": "true", - "node_shared_v8": "true", - "node_shared_zlib": "true", - "node_tag": "", - "node_unsafe_optimizations": 0, - "node_use_dtrace": "false", - "node_use_etw": "false", - "node_use_openssl": "true", - "node_use_perfctr": "false", - "node_use_systemtap": "false", - "python": "/usr/bin/python", - "target_arch": "x64", - "v8_enable_gdbjit": 0, - "v8_no_strict_aliasing": 1, - "v8_use_snapshot": "false", - "nodedir": "/usr/include/nodejs", - "copy_dev_lib": "true", - "standalone_static_library": 1, - "cache_lock_stale": "60000", - "pre": "", - "sign_git_tag": "", - "always_auth": "", - "user_agent": "node/v0.10.25 linux x64", - "bin_links": "true", - "description": "true", - "fetch_retries": "2", - "init_version": "0.0.0", - "user": "", - "force": "", - "ignore": "", - "cache_min": "10", - "editor": "vi", - "rollback": "true", - "cache_max": "null", - "userconfig": "/home/firstuser/.npmrc", - "coverage": "", - "engine_strict": "", - "init_author_name": "", - "init_author_url": "", - "tmp": "/home/firstuser/tmp", - "userignorefile": "/home/firstuser/.npmignore", - "yes": "", - "depth": "null", - "save_dev": "", - "usage": "", - "https_proxy": "", - "onload_script": "", - "rebuild_bundle": "true", - "save_bundle": "", - "shell": "/bin/bash", - "prefix": "/usr/local", - "registry": "https://registry.npmjs.org/", - "__DO_NOT_MODIFY_THIS_FILE___use__etc_npmrc_instead_": "true", - "browser": "", - "cache_lock_wait": "10000", - "save_optional": "", - "searchopts": "", - "versions": "", - "cache": "/home/firstuser/.npm", - "npaturl": "http://npat.npmjs.org/", - "searchsort": "name", - "version": "", - "viewer": "man", - "color": "true", - "fetch_retry_mintimeout": "10000", - "umask": "18", - "fetch_retry_maxtimeout": "60000", - "message": "%s", - "global": "", - "link": "", - "save": "", - "unicode": "true", - "long": "", - "production": "", - "unsafe_perm": "true", - "node_version": "v0.10.25", - "tag": "latest", - "shrinkwrap": "true", - "fetch_retry_factor": "10", - "npat": "", - "proprietary_attribs": "true", - "strict_ssl": "true", - "username": "", - "globalconfig": "/etc/npmrc", - "dev": "", - "init_module": "/home/firstuser/.npm-init.js", - "parseable": "", - "globalignorefile": "/etc/npmignore", - "cache_lock_retries": "10", - "group": "1000", - "init_author_email": "", - "searchexclude": "", - "git": "git", - "optional": "true", - "json": "" - } -} diff --git a/labs/node_modules/hiredis/build/deps/hiredis.Makefile b/labs/node_modules/hiredis/build/deps/hiredis.Makefile deleted file mode 100644 index b441a8b276..0000000000 --- a/labs/node_modules/hiredis/build/deps/hiredis.Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# This file is generated by gyp; do not edit. - -export builddir_name ?= build/./deps/. -.PHONY: all -all: - $(MAKE) -C .. hiredis diff --git a/labs/node_modules/hiredis/build/deps/hiredis.target.mk b/labs/node_modules/hiredis/build/deps/hiredis.target.mk deleted file mode 100644 index 8f9c2630e3..0000000000 --- a/labs/node_modules/hiredis/build/deps/hiredis.target.mk +++ /dev/null @@ -1,139 +0,0 @@ -# This file is generated by gyp; do not edit. - -TOOLSET := target -TARGET := hiredis -DEFS_Debug := \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' \ - '-DDEBUG' \ - '-D_DEBUG' - -# Flags passed to all source files. -CFLAGS_Debug := \ - -fPIC \ - -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -pthread \ - -m64 \ - -g \ - -O0 - -# Flags passed to only C files. -CFLAGS_C_Debug := - -# Flags passed to only C++ files. -CFLAGS_CC_Debug := \ - -fno-rtti \ - -fno-exceptions - -INCS_Debug := \ - -I/usr/include/nodejs/src \ - -I/usr/include/nodejs/deps/uv/include \ - -I/usr/include/nodejs/deps/v8/include - -DEFS_Release := \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' - -# Flags passed to all source files. -CFLAGS_Release := \ - -fPIC \ - -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -pthread \ - -m64 \ - -O2 \ - -fno-strict-aliasing \ - -fno-tree-vrp \ - -fno-omit-frame-pointer - -# Flags passed to only C files. -CFLAGS_C_Release := - -# Flags passed to only C++ files. -CFLAGS_CC_Release := \ - -fno-rtti \ - -fno-exceptions - -INCS_Release := \ - -I/usr/include/nodejs/src \ - -I/usr/include/nodejs/deps/uv/include \ - -I/usr/include/nodejs/deps/v8/include - -OBJS := \ - $(obj).target/$(TARGET)/deps/hiredis/hiredis.o \ - $(obj).target/$(TARGET)/deps/hiredis/net.o \ - $(obj).target/$(TARGET)/deps/hiredis/sds.o \ - $(obj).target/$(TARGET)/deps/hiredis/async.o - -# Add to the list of files we specially track dependencies for. -all_deps += $(OBJS) - -# CFLAGS et al overrides must be target-local. -# See "Target-specific Variable Values" in the GNU Make manual. -$(OBJS): TOOLSET := $(TOOLSET) -$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) -$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) - -# Suffix rules, putting all outputs into $(obj). - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# Try building from generated source, too. - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# End of this set of suffix rules -### Rules for final target. -LDFLAGS_Debug := \ - -pthread \ - -rdynamic \ - -m64 - -LDFLAGS_Release := \ - -pthread \ - -rdynamic \ - -m64 - -LIBS := - -$(obj).target/deps/hiredis.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) -$(obj).target/deps/hiredis.a: LIBS := $(LIBS) -$(obj).target/deps/hiredis.a: TOOLSET := $(TOOLSET) -$(obj).target/deps/hiredis.a: $(OBJS) FORCE_DO_CMD - $(call do_cmd,alink) - -all_deps += $(obj).target/deps/hiredis.a -# Add target alias -.PHONY: hiredis -hiredis: $(obj).target/deps/hiredis.a - -# Add target alias to "all" target. -.PHONY: all -all: hiredis - -# Add target alias -.PHONY: hiredis -hiredis: $(builddir)/hiredis.a - -# Copy this to the static library output path. -$(builddir)/hiredis.a: TOOLSET := $(TOOLSET) -$(builddir)/hiredis.a: $(obj).target/deps/hiredis.a FORCE_DO_CMD - $(call do_cmd,copy) - -all_deps += $(builddir)/hiredis.a -# Short alias for building this static library. -.PHONY: hiredis.a -hiredis.a: $(obj).target/deps/hiredis.a $(builddir)/hiredis.a - -# Add static library to "all" target. -.PHONY: all -all: $(builddir)/hiredis.a - diff --git a/labs/node_modules/hiredis/build/hiredis.target.mk b/labs/node_modules/hiredis/build/hiredis.target.mk deleted file mode 100644 index 87bb2c207e..0000000000 --- a/labs/node_modules/hiredis/build/hiredis.target.mk +++ /dev/null @@ -1,143 +0,0 @@ -# This file is generated by gyp; do not edit. - -TOOLSET := target -TARGET := hiredis -DEFS_Debug := \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' \ - '-D_GNU_SOURCE' \ - '-DBUILDING_NODE_EXTENSION' \ - '-DDEBUG' \ - '-D_DEBUG' - -# Flags passed to all source files. -CFLAGS_Debug := \ - -fPIC \ - -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -pthread \ - -m64 \ - -Wall \ - -O3 \ - -g \ - -O0 - -# Flags passed to only C files. -CFLAGS_C_Debug := - -# Flags passed to only C++ files. -CFLAGS_CC_Debug := \ - -fno-rtti \ - -fno-exceptions - -INCS_Debug := \ - -I/usr/include/nodejs/src \ - -I/usr/include/nodejs/deps/uv/include \ - -I/usr/include/nodejs/deps/v8/include \ - -I$(srcdir)/node_modules/nan \ - -I$(srcdir)/deps - -DEFS_Release := \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' \ - '-D_GNU_SOURCE' \ - '-DBUILDING_NODE_EXTENSION' - -# Flags passed to all source files. -CFLAGS_Release := \ - -fPIC \ - -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -pthread \ - -m64 \ - -Wall \ - -O2 \ - -fno-strict-aliasing \ - -fno-tree-vrp \ - -fno-omit-frame-pointer - -# Flags passed to only C files. -CFLAGS_C_Release := - -# Flags passed to only C++ files. -CFLAGS_CC_Release := \ - -fno-rtti \ - -fno-exceptions - -INCS_Release := \ - -I/usr/include/nodejs/src \ - -I/usr/include/nodejs/deps/uv/include \ - -I/usr/include/nodejs/deps/v8/include \ - -I$(srcdir)/node_modules/nan \ - -I$(srcdir)/deps - -OBJS := \ - $(obj).target/$(TARGET)/src/hiredis.o \ - $(obj).target/$(TARGET)/src/reader.o - -# Add to the list of files we specially track dependencies for. -all_deps += $(OBJS) - -# Make sure our dependencies are built before any of us. -$(OBJS): | $(builddir)/hiredis.a $(obj).target/deps/hiredis.a - -# CFLAGS et al overrides must be target-local. -# See "Target-specific Variable Values" in the GNU Make manual. -$(OBJS): TOOLSET := $(TOOLSET) -$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) -$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) - -# Suffix rules, putting all outputs into $(obj). - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -# Try building from generated source, too. - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -# End of this set of suffix rules -### Rules for final target. -LDFLAGS_Debug := \ - -pthread \ - -rdynamic \ - -m64 - -LDFLAGS_Release := \ - -pthread \ - -rdynamic \ - -m64 - -LIBS := - -$(obj).target/hiredis.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) -$(obj).target/hiredis.node: LIBS := $(LIBS) -$(obj).target/hiredis.node: TOOLSET := $(TOOLSET) -$(obj).target/hiredis.node: $(OBJS) $(obj).target/deps/hiredis.a FORCE_DO_CMD - $(call do_cmd,solink_module) - -all_deps += $(obj).target/hiredis.node -# Add target alias -.PHONY: hiredis -hiredis: $(builddir)/hiredis.node - -# Copy this to the executable output path. -$(builddir)/hiredis.node: TOOLSET := $(TOOLSET) -$(builddir)/hiredis.node: $(obj).target/hiredis.node FORCE_DO_CMD - $(call do_cmd,copy) - -all_deps += $(builddir)/hiredis.node -# Short alias for building this executable. -.PHONY: hiredis.node -hiredis.node: $(obj).target/hiredis.node $(builddir)/hiredis.node - -# Add executable to "all" target. -.PHONY: all -all: $(builddir)/hiredis.node - diff --git a/labs/node_modules/hiredis/deps/hiredis.gyp b/labs/node_modules/hiredis/deps/hiredis.gyp deleted file mode 100644 index 597bb095bb..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis.gyp +++ /dev/null @@ -1,27 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'hiredis', - 'type': 'static_library', - 'direct_dependent_settings': { - 'include_dirs': [ '.' ], - }, - 'sources': [ - './hiredis/hiredis.c', - './hiredis/net.c', - './hiredis/sds.c', - './hiredis/async.c', - ], - 'conditions': [ - ['OS=="mac"', { - 'xcode_settings': { - 'GCC_C_LANGUAGE_STANDARD': 'c99' - } - }], - ['OS=="solaris"', { - 'cflags+': [ '-std=c99' ] - }] - ] - } - ] -} diff --git a/labs/node_modules/hiredis/deps/hiredis/CHANGELOG.md b/labs/node_modules/hiredis/deps/hiredis/CHANGELOG.md deleted file mode 100644 index 4a57b813d7..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -### 0.11.0 - -* Increase the maximum multi-bulk reply depth to 8. - -* Increase the read buffer size from 2k to 16k. - -* Use poll(2) instead of select(2) to support large fds (>= 1024). - -### 0.10.1 - -* Makefile overhaul. Important to check out if you override one or more - variables using environment variables or via arguments to the "make" tool. - -* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements - being created by the default reply object functions. - -* Issue #43: Don't crash in an asynchronous context when Redis returns an error - reply after the connection has been made (this happens when the maximum - number of connections is reached). - -### 0.10.0 - -* See commit log. - diff --git a/labs/node_modules/hiredis/deps/hiredis/COPYING b/labs/node_modules/hiredis/deps/hiredis/COPYING deleted file mode 100644 index a5fc973955..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/COPYING +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2009-2011, Salvatore Sanfilippo -Copyright (c) 2010-2011, Pieter Noordhuis - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/labs/node_modules/hiredis/deps/hiredis/Makefile b/labs/node_modules/hiredis/deps/hiredis/Makefile deleted file mode 100644 index 16b8767b14..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/Makefile +++ /dev/null @@ -1,148 +0,0 @@ -# Hiredis Makefile -# Copyright (C) 2010-2011 Salvatore Sanfilippo -# Copyright (C) 2010-2011 Pieter Noordhuis -# This file is released under the BSD license, see the COPYING file - -OBJ=net.o hiredis.o sds.o async.o -BINS=hiredis-example hiredis-test -LIBNAME=libhiredis - -HIREDIS_MAJOR=0 -HIREDIS_MINOR=10 - -# Fallback to gcc when $CC is not in $PATH. -CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc') -OPTIMIZATION?=-O3 -WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings -DEBUG?= -g -ggdb -REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH) -REAL_LDFLAGS=$(LDFLAGS) $(ARCH) - -DYLIBSUFFIX=so -STLIBSUFFIX=a -DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR) -DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR) -DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) -DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) -STLIBNAME=$(LIBNAME).$(STLIBSUFFIX) -STLIB_MAKE_CMD=ar rcs $(STLIBNAME) - -# Platform-specific overrides -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') -ifeq ($(uname_S),SunOS) - REAL_LDFLAGS+= -ldl -lnsl -lsocket - DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS) - INSTALL= cp -r -endif -ifeq ($(uname_S),Darwin) - DYLIBSUFFIX=dylib - DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX) - DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX) - DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) -endif - -all: $(DYLIBNAME) $(BINS) - -# Deps (use make dep to generate this) -net.o: net.c fmacros.h net.h hiredis.h -async.o: async.c async.h hiredis.h sds.h dict.c dict.h -example.o: example.c hiredis.h -hiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h -sds.o: sds.c sds.h -test.o: test.c hiredis.h - -$(DYLIBNAME): $(OBJ) - $(DYLIB_MAKE_CMD) $(OBJ) - -$(STLIBNAME): $(OBJ) - $(STLIB_MAKE_CMD) $(OBJ) - -dynamic: $(DYLIBNAME) -static: $(STLIBNAME) - -# Binaries: -hiredis-example-libevent: example-libevent.c adapters/libevent.h $(STLIBNAME) - $(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -levent example-libevent.c $(STLIBNAME) - -hiredis-example-libev: example-libev.c adapters/libev.h $(STLIBNAME) - $(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -lev example-libev.c $(STLIBNAME) - -ifndef AE_DIR -hiredis-example-ae: - @echo "Please specify AE_DIR (e.g. /src)" - @false -else -hiredis-example-ae: example-ae.c adapters/ae.h $(STLIBNAME) - $(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I$(AE_DIR) $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o example-ae.c $(STLIBNAME) -endif - -hiredis-%: %.o $(STLIBNAME) - $(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME) - -test: hiredis-test - ./hiredis-test - -check: hiredis-test - echo \ - "daemonize yes\n" \ - "pidfile /tmp/hiredis-test-redis.pid\n" \ - "port 56379\n" \ - "bind 127.0.0.1\n" \ - "unixsocket /tmp/hiredis-test-redis.sock" \ - | redis-server - - ./hiredis-test -h 127.0.0.1 -p 56379 -s /tmp/hiredis-test-redis.sock || \ - ( kill `cat /tmp/hiredis-test-redis.pid` && false ) - kill `cat /tmp/hiredis-test-redis.pid` - -.c.o: - $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $< - -clean: - rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov - -dep: - $(CC) -MM *.c - -# Installation related variables and target -PREFIX?=/usr/local -INCLUDE_PATH?=include/hiredis -LIBRARY_PATH?=lib -INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH) - -ifeq ($(uname_S),SunOS) - INSTALL?= cp -r -endif - -INSTALL?= cp -a - -install: $(DYLIBNAME) $(STLIBNAME) - mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) - $(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME) - $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) - -32bit: - @echo "" - @echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386" - @echo "" - $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" - -gprof: - $(MAKE) CFLAGS="-pg" LDFLAGS="-pg" - -gcov: - $(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs" - -coverage: gcov - make check - mkdir -p tmp/lcov - lcov -d . -c -o tmp/lcov/hiredis.info - genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info - -noopt: - $(MAKE) OPTIMIZATION="" - -.PHONY: all test check clean dep install 32bit gprof gcov noopt diff --git a/labs/node_modules/hiredis/deps/hiredis/README.md b/labs/node_modules/hiredis/deps/hiredis/README.md deleted file mode 100644 index 62fe1067b7..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/README.md +++ /dev/null @@ -1,379 +0,0 @@ -# HIREDIS - -Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database. - -It is minimalistic because it just adds minimal support for the protocol, but -at the same time it uses an high level printf-alike API in order to make it -much higher level than otherwise suggested by its minimal code base and the -lack of explicit bindings for every Redis command. - -Apart from supporting sending commands and receiving replies, it comes with -a reply parser that is decoupled from the I/O layer. It -is a stream parser designed for easy reusability, which can for instance be used -in higher level language bindings for efficient reply parsing. - -Hiredis only supports the binary-safe Redis protocol, so you can use it with any -Redis version >= 1.2.0. - -The library comes with multiple APIs. There is the -*synchronous API*, the *asynchronous API* and the *reply parsing API*. - -## UPGRADING - -Version 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing -code using hiredis should not be a big pain. The key thing to keep in mind when -upgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to -the stateless 0.0.1 that only has a file descriptor to work with. - -## Synchronous API - -To consume the synchronous API, there are only a few function calls that need to be introduced: - - redisContext *redisConnect(const char *ip, int port); - void *redisCommand(redisContext *c, const char *format, ...); - void freeReplyObject(void *reply); - -### Connecting - -The function `redisConnect` is used to create a so-called `redisContext`. The -context is where Hiredis holds state for a connection. The `redisContext` -struct has an integer `err` field that is non-zero when an the connection is in -an error state. The field `errstr` will contain a string with a description of -the error. More information on errors can be found in the **Errors** section. -After trying to connect to Redis using `redisConnect` you should -check the `err` field to see if establishing the connection was successful: - - redisContext *c = redisConnect("127.0.0.1", 6379); - if (c->err) { - printf("Error: %s\n", c->errstr); - // handle error - } - -### Sending commands - -There are several ways to issue commands to Redis. The first that will be introduced is -`redisCommand`. This function takes a format similar to printf. In the simplest form, -it is used like this: - - reply = redisCommand(context, "SET foo bar"); - -The specifier `%s` interpolates a string in the command, and uses `strlen` to -determine the length of the string: - - reply = redisCommand(context, "SET foo %s", value); - -When you need to pass binary safe strings in a command, the `%b` specifier can be -used. Together with a pointer to the string, it requires a `size_t` length argument -of the string: - - reply = redisCommand(context, "SET foo %b", value, valuelen); - -Internally, Hiredis splits the command in different arguments and will -convert it to the protocol used to communicate with Redis. -One or more spaces separates arguments, so you can use the specifiers -anywhere in an argument: - - reply = redisCommand(context, "SET key:%s %s", myid, value); - -### Using replies - -The return value of `redisCommand` holds a reply when the command was -successfully executed. When an error occurs, the return value is `NULL` and -the `err` field in the context will be set (see section on **Errors**). -Once an error is returned the context cannot be reused and you should set up -a new connection. - -The standard replies that `redisCommand` are of the type `redisReply`. The -`type` field in the `redisReply` should be used to test what kind of reply -was received: - -* **`REDIS_REPLY_STATUS`**: - * The command replied with a status reply. The status string can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ERROR`**: - * The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`. - -* **`REDIS_REPLY_INTEGER`**: - * The command replied with an integer. The integer value can be accessed using the - `reply->integer` field of type `long long`. - -* **`REDIS_REPLY_NIL`**: - * The command replied with a **nil** object. There is no data to access. - -* **`REDIS_REPLY_STRING`**: - * A bulk (string) reply. The value of the reply can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ARRAY`**: - * A multi bulk reply. The number of elements in the multi bulk reply is stored in - `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well - and can be accessed via `reply->element[..index..]`. - Redis may reply with nested arrays but this is fully supported. - -Replies should be freed using the `freeReplyObject()` function. -Note that this function will take care of freeing sub-replies objects -contained in arrays and nested arrays, so there is no need for the user to -free the sub replies (it is actually harmful and will corrupt the memory). - -**Important:** the current version of hiredis (0.10.0) free's replies when the -asynchronous API is used. This means you should not call `freeReplyObject` when -you use this API. The reply is cleaned up by hiredis _after_ the callback -returns. This behavior will probably change in future releases, so make sure to -keep an eye on the changelog when upgrading (see issue #39). - -### Cleaning up - -To disconnect and free the context the following function can be used: - - void redisFree(redisContext *c); - -This function immediately closes the socket and then free's the allocations done in -creating the context. - -### Sending commands (cont'd) - -Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands. -It has the following prototype: - - void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -It takes the number of arguments `argc`, an array of strings `argv` and the lengths of the -arguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will -use `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments -need to be binary safe, the entire array of lengths `argvlen` should be provided. - -The return value has the same semantic as `redisCommand`. - -### Pipelining - -To explain how Hiredis supports pipelining in a blocking connection, there needs to be -understanding of the internal execution flow. - -When any of the functions in the `redisCommand` family is called, Hiredis first formats the -command according to the Redis protocol. The formatted command is then put in the output buffer -of the context. This output buffer is dynamic, so it can hold any number of commands. -After the command is put in the output buffer, `redisGetReply` is called. This function has the -following two execution paths: - -1. The input buffer is non-empty: - * Try to parse a single reply from the input buffer and return it - * If no reply could be parsed, continue at *2* -2. The input buffer is empty: - * Write the **entire** output buffer to the socket - * Read from the socket until a single reply could be parsed - -The function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply -is expected on the socket. To pipeline commands, the only things that needs to be done is -filling up the output buffer. For this cause, two commands can be used that are identical -to the `redisCommand` family, apart from not returning a reply: - - void redisAppendCommand(redisContext *c, const char *format, ...); - void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -After calling either function one or more times, `redisGetReply` can be used to receive the -subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where -the latter means an error occurred while reading a reply. Just as with the other commands, -the `err` field in the context can be used to find out what the cause of this error is. - -The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and -a single call to `read(2)`): - - redisReply *reply; - redisAppendCommand(context,"SET foo bar"); - redisAppendCommand(context,"GET foo"); - redisGetReply(context,&reply); // reply for SET - freeReplyObject(reply); - redisGetReply(context,&reply); // reply for GET - freeReplyObject(reply); - -This API can also be used to implement a blocking subscriber: - - reply = redisCommand(context,"SUBSCRIBE foo"); - freeReplyObject(reply); - while(redisGetReply(context,&reply) == REDIS_OK) { - // consume message - freeReplyObject(reply); - } - -### Errors - -When a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is -returned. The `err` field inside the context will be non-zero and set to one of the -following constants: - -* **`REDIS_ERR_IO`**: - There was an I/O error while creating the connection, trying to write - to the socket or read from the socket. If you included `errno.h` in your - application, you can use the global `errno` variable to find out what is - wrong. - -* **`REDIS_ERR_EOF`**: - The server closed the connection which resulted in an empty read. - -* **`REDIS_ERR_PROTOCOL`**: - There was an error while parsing the protocol. - -* **`REDIS_ERR_OTHER`**: - Any other error. Currently, it is only used when a specified hostname to connect - to cannot be resolved. - -In every case, the `errstr` field in the context will be set to hold a string representation -of the error. - -## Asynchronous API - -Hiredis comes with an asynchronous API that works easily with any event library. -Examples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html) -and [libevent](http://monkey.org/~provos/libevent/). - -### Connecting - -The function `redisAsyncConnect` can be used to establish a non-blocking connection to -Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field -should be checked after creation to see if there were errors creating the connection. -Because the connection that will be created is non-blocking, the kernel is not able to -instantly return if the specified host and port is able to accept a connection. - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - printf("Error: %s\n", c->errstr); - // handle error - } - -The asynchronous context can hold a disconnect callback function that is called when the -connection is disconnected (either because of an error or per user request). This function should -have the following prototype: - - void(const redisAsyncContext *c, int status); - -On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the -user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err` -field in the context can be accessed to find out the cause of the error. - -The context object is always free'd after the disconnect callback fired. When a reconnect is needed, -the disconnect callback is a good point to do so. - -Setting the disconnect callback can only be done once per context. For subsequent calls it will -return `REDIS_ERR`. The function to set the disconnect callback has the following prototype: - - int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); - -### Sending commands and their callbacks - -In an asynchronous context, commands are automatically pipelined due to the nature of an event loop. -Therefore, unlike the synchronous API, there is only a single way to send commands. -Because commands are sent to Redis asynchronously, issuing a command requires a callback function -that is called when the reply is received. Reply callbacks should have the following prototype: - - void(redisAsyncContext *c, void *reply, void *privdata); - -The `privdata` argument can be used to curry arbitrary data to the callback from the point where -the command is initially queued for execution. - -The functions that can be used to issue commands in an asynchronous context are: - - int redisAsyncCommand( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - const char *format, ...); - int redisAsyncCommandArgv( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - int argc, const char **argv, const size_t *argvlen); - -Both functions work like their blocking counterparts. The return value is `REDIS_OK` when the command -was successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection -is being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is -returned on calls to the `redisAsyncCommand` family. - -If the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback -for a command is non-`NULL`, the memory is free'd immediately following the callback: the reply is only -valid for the duration of the callback. - -All pending callbacks are called with a `NULL` reply when the context encountered an error. - -### Disconnecting - -An asynchronous connection can be terminated using: - - void redisAsyncDisconnect(redisAsyncContext *ac); - -When this function is called, the connection is **not** immediately terminated. Instead, new -commands are no longer accepted and the connection is only terminated when all pending commands -have been written to the socket, their respective replies have been read and their respective -callbacks have been executed. After this, the disconnection callback is executed with the -`REDIS_OK` status and the context object is free'd. - -### Hooking it up to event library *X* - -There are a few hooks that need to be set on the context object after it is created. -See the `adapters/` directory for bindings to *libev* and *libevent*. - -## Reply parsing API - -Hiredis comes with a reply parsing API that makes it easy for writing higher -level language bindings. - -The reply parsing API consists of the following functions: - - redisReader *redisReaderCreate(void); - void redisReaderFree(redisReader *reader); - int redisReaderFeed(redisReader *reader, const char *buf, size_t len); - int redisReaderGetReply(redisReader *reader, void **reply); - -The same set of functions are used internally by hiredis when creating a -normal Redis context, the above API just exposes it to the user for a direct -usage. - -### Usage - -The function `redisReaderCreate` creates a `redisReader` structure that holds a -buffer with unparsed data and state for the protocol parser. - -Incoming data -- most likely from a socket -- can be placed in the internal -buffer of the `redisReader` using `redisReaderFeed`. This function will make a -copy of the buffer pointed to by `buf` for `len` bytes. This data is parsed -when `redisReaderGetReply` is called. This function returns an integer status -and a reply object (as described above) via `void **reply`. The returned status -can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went -wrong (either a protocol error, or an out of memory error). - -### Customizing replies - -The function `redisReaderGetReply` creates `redisReply` and makes the function -argument `reply` point to the created `redisReply` variable. For instance, if -the response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply` -will hold the status as a vanilla C string. However, the functions that are -responsible for creating instances of the `redisReply` can be customized by -setting the `fn` field on the `redisReader` struct. This should be done -immediately after creating the `redisReader`. - -For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c) -uses customized reply object functions to create Ruby objects. - -### Reader max buffer - -Both when using the Reader API directly or when using it indirectly via a -normal Redis context, the redisReader structure uses a buffer in order to -accumulate data from the server. -Usually this buffer is destroyed when it is empty and is larger than 16 -kb in order to avoid wasting memory in unused buffers - -However when working with very big payloads destroying the buffer may slow -down performances considerably, so it is possible to modify the max size of -an idle buffer changing the value of the `maxbuf` field of the reader structure -to the desired value. The special value of 0 means that there is no maximum -value for an idle buffer, so the buffer will never get freed. - -For instance if you have a normal Redis context you can set the maximum idle -buffer to zero (unlimited) just with: - - context->reader->maxbuf = 0; - -This should be done only in order to maximize performances when working with -large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again -as soon as possible in order to prevent allocation of useless memory. - -## AUTHORS - -Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and -Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. diff --git a/labs/node_modules/hiredis/deps/hiredis/adapters/ae.h b/labs/node_modules/hiredis/deps/hiredis/adapters/ae.h deleted file mode 100644 index 65235f802a..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/adapters/ae.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef __HIREDIS_AE_H__ -#define __HIREDIS_AE_H__ -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisAeEvents { - redisAsyncContext *context; - aeEventLoop *loop; - int fd; - int reading, writing; -} redisAeEvents; - -static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleRead(e->context); -} - -static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleWrite(e->context); -} - -static void redisAeAddRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->reading) { - e->reading = 1; - aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e); - } -} - -static void redisAeDelRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->reading) { - e->reading = 0; - aeDeleteFileEvent(loop,e->fd,AE_READABLE); - } -} - -static void redisAeAddWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->writing) { - e->writing = 1; - aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e); - } -} - -static void redisAeDelWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->writing) { - e->writing = 0; - aeDeleteFileEvent(loop,e->fd,AE_WRITABLE); - } -} - -static void redisAeCleanup(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - redisAeDelRead(privdata); - redisAeDelWrite(privdata); - free(e); -} - -static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisAeEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisAeEvents*)malloc(sizeof(*e)); - e->context = ac; - e->loop = loop; - e->fd = c->fd; - e->reading = e->writing = 0; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisAeAddRead; - ac->ev.delRead = redisAeDelRead; - ac->ev.addWrite = redisAeAddWrite; - ac->ev.delWrite = redisAeDelWrite; - ac->ev.cleanup = redisAeCleanup; - ac->ev.data = e; - - return REDIS_OK; -} -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/adapters/libev.h b/labs/node_modules/hiredis/deps/hiredis/adapters/libev.h deleted file mode 100644 index 534d743601..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/adapters/libev.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __HIREDIS_LIBEV_H__ -#define __HIREDIS_LIBEV_H__ -#include -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisLibevEvents { - redisAsyncContext *context; - struct ev_loop *loop; - int reading, writing; - ev_io rev, wev; -} redisLibevEvents; - -static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleRead(e->context); -} - -static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleWrite(e->context); -} - -static void redisLibevAddRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->reading) { - e->reading = 1; - ev_io_start(EV_A_ &e->rev); - } -} - -static void redisLibevDelRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->reading) { - e->reading = 0; - ev_io_stop(EV_A_ &e->rev); - } -} - -static void redisLibevAddWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->writing) { - e->writing = 1; - ev_io_start(EV_A_ &e->wev); - } -} - -static void redisLibevDelWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->writing) { - e->writing = 0; - ev_io_stop(EV_A_ &e->wev); - } -} - -static void redisLibevCleanup(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - redisLibevDelRead(privdata); - redisLibevDelWrite(privdata); - free(e); -} - -static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisLibevEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibevEvents*)malloc(sizeof(*e)); - e->context = ac; -#if EV_MULTIPLICITY - e->loop = loop; -#else - e->loop = NULL; -#endif - e->reading = e->writing = 0; - e->rev.data = e; - e->wev.data = e; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibevAddRead; - ac->ev.delRead = redisLibevDelRead; - ac->ev.addWrite = redisLibevAddWrite; - ac->ev.delWrite = redisLibevDelWrite; - ac->ev.cleanup = redisLibevCleanup; - ac->ev.data = e; - - /* Initialize read/write events */ - ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ); - ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE); - return REDIS_OK; -} - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/adapters/libevent.h b/labs/node_modules/hiredis/deps/hiredis/adapters/libevent.h deleted file mode 100644 index 4055ec0f11..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/adapters/libevent.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __HIREDIS_LIBEVENT_H__ -#define __HIREDIS_LIBEVENT_H__ -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisLibeventEvents { - redisAsyncContext *context; - struct event rev, wev; -} redisLibeventEvents; - -static void redisLibeventReadEvent(int fd, short event, void *arg) { - ((void)fd); ((void)event); - redisLibeventEvents *e = (redisLibeventEvents*)arg; - redisAsyncHandleRead(e->context); -} - -static void redisLibeventWriteEvent(int fd, short event, void *arg) { - ((void)fd); ((void)event); - redisLibeventEvents *e = (redisLibeventEvents*)arg; - redisAsyncHandleWrite(e->context); -} - -static void redisLibeventAddRead(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_add(&e->rev,NULL); -} - -static void redisLibeventDelRead(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_del(&e->rev); -} - -static void redisLibeventAddWrite(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_add(&e->wev,NULL); -} - -static void redisLibeventDelWrite(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_del(&e->wev); -} - -static void redisLibeventCleanup(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_del(&e->rev); - event_del(&e->wev); - free(e); -} - -static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { - redisContext *c = &(ac->c); - redisLibeventEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibeventEvents*)malloc(sizeof(*e)); - e->context = ac; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibeventAddRead; - ac->ev.delRead = redisLibeventDelRead; - ac->ev.addWrite = redisLibeventAddWrite; - ac->ev.delWrite = redisLibeventDelWrite; - ac->ev.cleanup = redisLibeventCleanup; - ac->ev.data = e; - - /* Initialize and install read/write events */ - event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e); - event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e); - event_base_set(base,&e->rev); - event_base_set(base,&e->wev); - return REDIS_OK; -} -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/async.c b/labs/node_modules/hiredis/deps/hiredis/async.c deleted file mode 100644 index f65f8694cc..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/async.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include "async.h" -#include "net.h" -#include "dict.c" -#include "sds.h" - -#define _EL_ADD_READ(ctx) do { \ - if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \ - } while(0) -#define _EL_DEL_READ(ctx) do { \ - if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \ - } while(0) -#define _EL_ADD_WRITE(ctx) do { \ - if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \ - } while(0) -#define _EL_DEL_WRITE(ctx) do { \ - if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \ - } while(0) -#define _EL_CLEANUP(ctx) do { \ - if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \ - } while(0); - -/* Forward declaration of function in hiredis.c */ -void __redisAppendCommand(redisContext *c, char *cmd, size_t len); - -/* Functions managing dictionary of callbacks for pub/sub. */ -static unsigned int callbackHash(const void *key) { - return dictGenHashFunction((unsigned char*)key,sdslen((char*)key)); -} - -static void *callbackValDup(void *privdata, const void *src) { - ((void) privdata); - redisCallback *dup = malloc(sizeof(*dup)); - memcpy(dup,src,sizeof(*dup)); - return dup; -} - -static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) { - int l1, l2; - ((void) privdata); - - l1 = sdslen((sds)key1); - l2 = sdslen((sds)key2); - if (l1 != l2) return 0; - return memcmp(key1,key2,l1) == 0; -} - -static void callbackKeyDestructor(void *privdata, void *key) { - ((void) privdata); - sdsfree((sds)key); -} - -static void callbackValDestructor(void *privdata, void *val) { - ((void) privdata); - free(val); -} - -static dictType callbackDict = { - callbackHash, - NULL, - callbackValDup, - callbackKeyCompare, - callbackKeyDestructor, - callbackValDestructor -}; - -static redisAsyncContext *redisAsyncInitialize(redisContext *c) { - redisAsyncContext *ac = realloc(c,sizeof(redisAsyncContext)); - c = &(ac->c); - - /* The regular connect functions will always set the flag REDIS_CONNECTED. - * For the async API, we want to wait until the first write event is - * received up before setting this flag, so reset it here. */ - c->flags &= ~REDIS_CONNECTED; - - ac->err = 0; - ac->errstr = NULL; - ac->data = NULL; - - ac->ev.data = NULL; - ac->ev.addRead = NULL; - ac->ev.delRead = NULL; - ac->ev.addWrite = NULL; - ac->ev.delWrite = NULL; - ac->ev.cleanup = NULL; - - ac->onConnect = NULL; - ac->onDisconnect = NULL; - - ac->replies.head = NULL; - ac->replies.tail = NULL; - ac->sub.invalid.head = NULL; - ac->sub.invalid.tail = NULL; - ac->sub.channels = dictCreate(&callbackDict,NULL); - ac->sub.patterns = dictCreate(&callbackDict,NULL); - return ac; -} - -/* We want the error field to be accessible directly instead of requiring - * an indirection to the redisContext struct. */ -static void __redisAsyncCopyError(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - ac->err = c->err; - ac->errstr = c->errstr; -} - -redisAsyncContext *redisAsyncConnect(const char *ip, int port) { - redisContext *c = redisConnectNonBlock(ip,port); - redisAsyncContext *ac = redisAsyncInitialize(c); - __redisAsyncCopyError(ac); - return ac; -} - -redisAsyncContext *redisAsyncConnectUnix(const char *path) { - redisContext *c = redisConnectUnixNonBlock(path); - redisAsyncContext *ac = redisAsyncInitialize(c); - __redisAsyncCopyError(ac); - return ac; -} - -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) { - if (ac->onConnect == NULL) { - ac->onConnect = fn; - - /* The common way to detect an established connection is to wait for - * the first write event to be fired. This assumes the related event - * library functions are already set. */ - _EL_ADD_WRITE(ac); - return REDIS_OK; - } - return REDIS_ERR; -} - -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) { - if (ac->onDisconnect == NULL) { - ac->onDisconnect = fn; - return REDIS_OK; - } - return REDIS_ERR; -} - -/* Helper functions to push/shift callbacks */ -static int __redisPushCallback(redisCallbackList *list, redisCallback *source) { - redisCallback *cb; - - /* Copy callback from stack to heap */ - cb = malloc(sizeof(*cb)); - if (source != NULL) { - memcpy(cb,source,sizeof(*cb)); - cb->next = NULL; - } - - /* Store callback in list */ - if (list->head == NULL) - list->head = cb; - if (list->tail != NULL) - list->tail->next = cb; - list->tail = cb; - return REDIS_OK; -} - -static int __redisShiftCallback(redisCallbackList *list, redisCallback *target) { - redisCallback *cb = list->head; - if (cb != NULL) { - list->head = cb->next; - if (cb == list->tail) - list->tail = NULL; - - /* Copy callback from heap to stack */ - if (target != NULL) - memcpy(target,cb,sizeof(*cb)); - free(cb); - return REDIS_OK; - } - return REDIS_ERR; -} - -static void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) { - redisContext *c = &(ac->c); - if (cb->fn != NULL) { - c->flags |= REDIS_IN_CALLBACK; - cb->fn(ac,reply,cb->privdata); - c->flags &= ~REDIS_IN_CALLBACK; - } -} - -/* Helper function to free the context. */ -static void __redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb; - dictIterator *it; - dictEntry *de; - - /* Execute pending callbacks with NULL reply. */ - while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Execute callbacks for invalid commands */ - while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Run subscription callbacks callbacks with NULL reply */ - it = dictGetIterator(ac->sub.channels); - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - dictRelease(ac->sub.channels); - - it = dictGetIterator(ac->sub.patterns); - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - dictRelease(ac->sub.patterns); - - /* Signal event lib to clean up */ - _EL_CLEANUP(ac); - - /* Execute disconnect callback. When redisAsyncFree() initiated destroying - * this context, the status will always be REDIS_OK. */ - if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) { - if (c->flags & REDIS_FREEING) { - ac->onDisconnect(ac,REDIS_OK); - } else { - ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR); - } - } - - /* Cleanup self */ - redisFree(c); -} - -/* Free the async context. When this function is called from a callback, - * control needs to be returned to redisProcessCallbacks() before actual - * free'ing. To do so, a flag is set on the context which is picked up by - * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */ -void redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_FREEING; - if (!(c->flags & REDIS_IN_CALLBACK)) - __redisAsyncFree(ac); -} - -/* Helper function to make the disconnect happen and clean up. */ -static void __redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - /* Make sure error is accessible if there is any */ - __redisAsyncCopyError(ac); - - if (ac->err == 0) { - /* For clean disconnects, there should be no pending callbacks. */ - assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR); - } else { - /* Disconnection is caused by an error, make sure that pending - * callbacks cannot call new commands. */ - c->flags |= REDIS_DISCONNECTING; - } - - /* For non-clean disconnects, __redisAsyncFree() will execute pending - * callbacks with a NULL-reply. */ - __redisAsyncFree(ac); -} - -/* Tries to do a clean disconnect from Redis, meaning it stops new commands - * from being issued, but tries to flush the output buffer and execute - * callbacks for all remaining replies. When this function is called from a - * callback, there might be more replies and we can safely defer disconnecting - * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately - * when there are no pending callbacks. */ -void redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_DISCONNECTING; - if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL) - __redisAsyncDisconnect(ac); -} - -static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) { - redisContext *c = &(ac->c); - dict *callbacks; - dictEntry *de; - int pvariant; - char *stype; - sds sname; - - /* Custom reply functions are not supported for pub/sub. This will fail - * very hard when they are used... */ - if (reply->type == REDIS_REPLY_ARRAY) { - assert(reply->elements >= 2); - assert(reply->element[0]->type == REDIS_REPLY_STRING); - stype = reply->element[0]->str; - pvariant = (tolower(stype[0]) == 'p') ? 1 : 0; - - if (pvariant) - callbacks = ac->sub.patterns; - else - callbacks = ac->sub.channels; - - /* Locate the right callback */ - assert(reply->element[1]->type == REDIS_REPLY_STRING); - sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len); - de = dictFind(callbacks,sname); - if (de != NULL) { - memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb)); - - /* If this is an unsubscribe message, remove it. */ - if (strcasecmp(stype+pvariant,"unsubscribe") == 0) { - dictDelete(callbacks,sname); - - /* If this was the last unsubscribe message, revert to - * non-subscribe mode. */ - assert(reply->element[2]->type == REDIS_REPLY_INTEGER); - if (reply->element[2]->integer == 0) - c->flags &= ~REDIS_SUBSCRIBED; - } - } - sdsfree(sname); - } else { - /* Shift callback for invalid commands. */ - __redisShiftCallback(&ac->sub.invalid,dstcb); - } - return REDIS_OK; -} - -void redisProcessCallbacks(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb; - void *reply = NULL; - int status; - - while((status = redisGetReply(c,&reply)) == REDIS_OK) { - if (reply == NULL) { - /* When the connection is being disconnected and there are - * no more replies, this is the cue to really disconnect. */ - if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) { - __redisAsyncDisconnect(ac); - return; - } - - /* If monitor mode, repush callback */ - if(c->flags & REDIS_MONITORING) { - __redisPushCallback(&ac->replies,&cb); - } - - /* When the connection is not being disconnected, simply stop - * trying to get replies and wait for the next loop tick. */ - break; - } - - /* Even if the context is subscribed, pending regular callbacks will - * get a reply before pub/sub messages arrive. */ - if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) { - /* - * A spontaneous reply in a not-subscribed context can be the error - * reply that is sent when a new connection exceeds the maximum - * number of allowed connections on the server side. - * - * This is seen as an error instead of a regular reply because the - * server closes the connection after sending it. - * - * To prevent the error from being overwritten by an EOF error the - * connection is closed here. See issue #43. - * - * Another possibility is that the server is loading its dataset. - * In this case we also want to close the connection, and have the - * user wait until the server is ready to take our request. - */ - if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) { - c->err = REDIS_ERR_OTHER; - snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str); - __redisAsyncDisconnect(ac); - return; - } - /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */ - assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING)); - if(c->flags & REDIS_SUBSCRIBED) - __redisGetSubscribeCallback(ac,reply,&cb); - } - - if (cb.fn != NULL) { - __redisRunCallback(ac,&cb,reply); - c->reader->fn->freeObject(reply); - - /* Proceed with free'ing when redisAsyncFree() was called. */ - if (c->flags & REDIS_FREEING) { - __redisAsyncFree(ac); - return; - } - } else { - /* No callback for this reply. This can either be a NULL callback, - * or there were no callbacks to begin with. Either way, don't - * abort with an error, but simply ignore it because the client - * doesn't know what the server will spit out over the wire. */ - c->reader->fn->freeObject(reply); - } - } - - /* Disconnect when there was an error reading the reply */ - if (status != REDIS_OK) - __redisAsyncDisconnect(ac); -} - -/* Internal helper function to detect socket status the first time a read or - * write event fires. When connecting was not succesful, the connect callback - * is called with a REDIS_ERR status and the context is free'd. */ -static int __redisAsyncHandleConnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (redisCheckSocketError(c,c->fd) == REDIS_ERR) { - /* Try again later when connect(2) is still in progress. */ - if (errno == EINPROGRESS) - return REDIS_OK; - - if (ac->onConnect) ac->onConnect(ac,REDIS_ERR); - __redisAsyncDisconnect(ac); - return REDIS_ERR; - } - - /* Mark context as connected. */ - c->flags |= REDIS_CONNECTED; - if (ac->onConnect) ac->onConnect(ac,REDIS_OK); - return REDIS_OK; -} - -/* This function should be called when the socket is readable. - * It processes all replies that can be read and executes their callbacks. - */ -void redisAsyncHandleRead(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - if (redisBufferRead(c) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Always re-schedule reads */ - _EL_ADD_READ(ac); - redisProcessCallbacks(ac); - } -} - -void redisAsyncHandleWrite(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - int done = 0; - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - if (redisBufferWrite(c,&done) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Continue writing when not done, stop writing otherwise */ - if (!done) - _EL_ADD_WRITE(ac); - else - _EL_DEL_WRITE(ac); - - /* Always schedule reads after writes */ - _EL_ADD_READ(ac); - } -} - -/* Sets a pointer to the first argument and its length starting at p. Returns - * the number of bytes to skip to get to the following argument. */ -static char *nextArgument(char *start, char **str, size_t *len) { - char *p = start; - if (p[0] != '$') { - p = strchr(p,'$'); - if (p == NULL) return NULL; - } - - *len = (int)strtol(p+1,NULL,10); - p = strchr(p,'\r'); - assert(p); - *str = p+2; - return p+2+(*len)+2; -} - -/* Helper function for the redisAsyncCommand* family of functions. Writes a - * formatted command to the output buffer and registers the provided callback - * function with the context. */ -static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, char *cmd, size_t len) { - redisContext *c = &(ac->c); - redisCallback cb; - int pvariant, hasnext; - char *cstr, *astr; - size_t clen, alen; - char *p; - sds sname; - - /* Don't accept new commands when the connection is about to be closed. */ - if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR; - - /* Setup callback */ - cb.fn = fn; - cb.privdata = privdata; - - /* Find out which command will be appended. */ - p = nextArgument(cmd,&cstr,&clen); - assert(p != NULL); - hasnext = (p[0] == '$'); - pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0; - cstr += pvariant; - clen -= pvariant; - - if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) { - c->flags |= REDIS_SUBSCRIBED; - - /* Add every channel/pattern to the list of subscription callbacks. */ - while ((p = nextArgument(p,&astr,&alen)) != NULL) { - sname = sdsnewlen(astr,alen); - if (pvariant) - dictReplace(ac->sub.patterns,sname,&cb); - else - dictReplace(ac->sub.channels,sname,&cb); - } - } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) { - /* It is only useful to call (P)UNSUBSCRIBE when the context is - * subscribed to one or more channels or patterns. */ - if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR; - - /* (P)UNSUBSCRIBE does not have its own response: every channel or - * pattern that is unsubscribed will receive a message. This means we - * should not append a callback function for this command. */ - } else if(strncasecmp(cstr,"monitor\r\n",9) == 0) { - /* Set monitor flag and push callback */ - c->flags |= REDIS_MONITORING; - __redisPushCallback(&ac->replies,&cb); - } else { - if (c->flags & REDIS_SUBSCRIBED) - /* This will likely result in an error reply, but it needs to be - * received and passed to the callback. */ - __redisPushCallback(&ac->sub.invalid,&cb); - else - __redisPushCallback(&ac->replies,&cb); - } - - __redisAppendCommand(c,cmd,len); - - /* Always schedule a write when the write buffer is non-empty */ - _EL_ADD_WRITE(ac); - - return REDIS_OK; -} - -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) { - char *cmd; - int len; - int status; - len = redisvFormatCommand(&cmd,format,ap); - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - free(cmd); - return status; -} - -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) { - va_list ap; - int status; - va_start(ap,format); - status = redisvAsyncCommand(ac,fn,privdata,format,ap); - va_end(ap); - return status; -} - -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) { - char *cmd; - int len; - int status; - len = redisFormatCommandArgv(&cmd,argc,argv,argvlen); - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - free(cmd); - return status; -} diff --git a/labs/node_modules/hiredis/deps/hiredis/async.h b/labs/node_modules/hiredis/deps/hiredis/async.h deleted file mode 100644 index 268274e8e7..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/async.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/dict.c b/labs/node_modules/hiredis/deps/hiredis/dict.c deleted file mode 100644 index 79b1041cad..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/dict.c +++ /dev/null @@ -1,338 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include "dict.h" - -/* -------------------------- private prototypes ---------------------------- */ - -static int _dictExpandIfNeeded(dict *ht); -static unsigned long _dictNextPower(unsigned long size); -static int _dictKeyIndex(dict *ht, const void *key); -static int _dictInit(dict *ht, dictType *type, void *privDataPtr); - -/* -------------------------- hash functions -------------------------------- */ - -/* Generic hash function (a popular one from Bernstein). - * I tested a few and this was the best. */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; - - while (len--) - hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */ - return hash; -} - -/* ----------------------------- API implementation ------------------------- */ - -/* Reset an hashtable already initialized with ht_init(). - * NOTE: This function should only called by ht_destroy(). */ -static void _dictReset(dict *ht) { - ht->table = NULL; - ht->size = 0; - ht->sizemask = 0; - ht->used = 0; -} - -/* Create a new hash table */ -static dict *dictCreate(dictType *type, void *privDataPtr) { - dict *ht = malloc(sizeof(*ht)); - _dictInit(ht,type,privDataPtr); - return ht; -} - -/* Initialize the hash table */ -static int _dictInit(dict *ht, dictType *type, void *privDataPtr) { - _dictReset(ht); - ht->type = type; - ht->privdata = privDataPtr; - return DICT_OK; -} - -/* Expand or create the hashtable */ -static int dictExpand(dict *ht, unsigned long size) { - dict n; /* the new hashtable */ - unsigned long realsize = _dictNextPower(size), i; - - /* the size is invalid if it is smaller than the number of - * elements already inside the hashtable */ - if (ht->used > size) - return DICT_ERR; - - _dictInit(&n, ht->type, ht->privdata); - n.size = realsize; - n.sizemask = realsize-1; - n.table = calloc(realsize,sizeof(dictEntry*)); - - /* Copy all the elements from the old to the new table: - * note that if the old hash table is empty ht->size is zero, - * so dictExpand just creates an hash table. */ - n.used = ht->used; - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if (ht->table[i] == NULL) continue; - - /* For each hash entry on this slot... */ - he = ht->table[i]; - while(he) { - unsigned int h; - - nextHe = he->next; - /* Get the new element index */ - h = dictHashKey(ht, he->key) & n.sizemask; - he->next = n.table[h]; - n.table[h] = he; - ht->used--; - /* Pass to the next element */ - he = nextHe; - } - } - assert(ht->used == 0); - free(ht->table); - - /* Remap the new hashtable in the old */ - *ht = n; - return DICT_OK; -} - -/* Add an element to the target hash table */ -static int dictAdd(dict *ht, void *key, void *val) { - int index; - dictEntry *entry; - - /* Get the index of the new element, or -1 if - * the element already exists. */ - if ((index = _dictKeyIndex(ht, key)) == -1) - return DICT_ERR; - - /* Allocates the memory and stores key */ - entry = malloc(sizeof(*entry)); - entry->next = ht->table[index]; - ht->table[index] = entry; - - /* Set the hash entry fields. */ - dictSetHashKey(ht, entry, key); - dictSetHashVal(ht, entry, val); - ht->used++; - return DICT_OK; -} - -/* Add an element, discarding the old if the key already exists. - * Return 1 if the key was added from scratch, 0 if there was already an - * element with such key and dictReplace() just performed a value update - * operation. */ -static int dictReplace(dict *ht, void *key, void *val) { - dictEntry *entry, auxentry; - - /* Try to add the element. If the key - * does not exists dictAdd will suceed. */ - if (dictAdd(ht, key, val) == DICT_OK) - return 1; - /* It already exists, get the entry */ - entry = dictFind(ht, key); - /* Free the old value and set the new one */ - /* Set the new value and free the old one. Note that it is important - * to do that in this order, as the value may just be exactly the same - * as the previous one. In this context, think to reference counting, - * you want to increment (set), and then decrement (free), and not the - * reverse. */ - auxentry = *entry; - dictSetHashVal(ht, entry, val); - dictFreeEntryVal(ht, &auxentry); - return 0; -} - -/* Search and remove an element */ -static int dictDelete(dict *ht, const void *key) { - unsigned int h; - dictEntry *de, *prevde; - - if (ht->size == 0) - return DICT_ERR; - h = dictHashKey(ht, key) & ht->sizemask; - de = ht->table[h]; - - prevde = NULL; - while(de) { - if (dictCompareHashKeys(ht,key,de->key)) { - /* Unlink the element from the list */ - if (prevde) - prevde->next = de->next; - else - ht->table[h] = de->next; - - dictFreeEntryKey(ht,de); - dictFreeEntryVal(ht,de); - free(de); - ht->used--; - return DICT_OK; - } - prevde = de; - de = de->next; - } - return DICT_ERR; /* not found */ -} - -/* Destroy an entire hash table */ -static int _dictClear(dict *ht) { - unsigned long i; - - /* Free all the elements */ - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if ((he = ht->table[i]) == NULL) continue; - while(he) { - nextHe = he->next; - dictFreeEntryKey(ht, he); - dictFreeEntryVal(ht, he); - free(he); - ht->used--; - he = nextHe; - } - } - /* Free the table and the allocated cache structure */ - free(ht->table); - /* Re-initialize the table */ - _dictReset(ht); - return DICT_OK; /* never fails */ -} - -/* Clear & Release the hash table */ -static void dictRelease(dict *ht) { - _dictClear(ht); - free(ht); -} - -static dictEntry *dictFind(dict *ht, const void *key) { - dictEntry *he; - unsigned int h; - - if (ht->size == 0) return NULL; - h = dictHashKey(ht, key) & ht->sizemask; - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return he; - he = he->next; - } - return NULL; -} - -static dictIterator *dictGetIterator(dict *ht) { - dictIterator *iter = malloc(sizeof(*iter)); - - iter->ht = ht; - iter->index = -1; - iter->entry = NULL; - iter->nextEntry = NULL; - return iter; -} - -static dictEntry *dictNext(dictIterator *iter) { - while (1) { - if (iter->entry == NULL) { - iter->index++; - if (iter->index >= - (signed)iter->ht->size) break; - iter->entry = iter->ht->table[iter->index]; - } else { - iter->entry = iter->nextEntry; - } - if (iter->entry) { - /* We need to save the 'next' here, the iterator user - * may delete the entry we are returning. */ - iter->nextEntry = iter->entry->next; - return iter->entry; - } - } - return NULL; -} - -static void dictReleaseIterator(dictIterator *iter) { - free(iter); -} - -/* ------------------------- private functions ------------------------------ */ - -/* Expand the hash table if needed */ -static int _dictExpandIfNeeded(dict *ht) { - /* If the hash table is empty expand it to the intial size, - * if the table is "full" dobule its size. */ - if (ht->size == 0) - return dictExpand(ht, DICT_HT_INITIAL_SIZE); - if (ht->used == ht->size) - return dictExpand(ht, ht->size*2); - return DICT_OK; -} - -/* Our hash table capability is a power of two */ -static unsigned long _dictNextPower(unsigned long size) { - unsigned long i = DICT_HT_INITIAL_SIZE; - - if (size >= LONG_MAX) return LONG_MAX; - while(1) { - if (i >= size) - return i; - i *= 2; - } -} - -/* Returns the index of a free slot that can be populated with - * an hash entry for the given 'key'. - * If the key already exists, -1 is returned. */ -static int _dictKeyIndex(dict *ht, const void *key) { - unsigned int h; - dictEntry *he; - - /* Expand the hashtable if needed */ - if (_dictExpandIfNeeded(ht) == DICT_ERR) - return -1; - /* Compute the key hash value */ - h = dictHashKey(ht, key) & ht->sizemask; - /* Search if this slot does not already contain the given key */ - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return -1; - he = he->next; - } - return h; -} - diff --git a/labs/node_modules/hiredis/deps/hiredis/dict.h b/labs/node_modules/hiredis/deps/hiredis/dict.h deleted file mode 100644 index 95fcd280e2..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - unsigned long size; - unsigned long sizemask; - unsigned long used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, unsigned long size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/labs/node_modules/hiredis/deps/hiredis/example-ae.c b/labs/node_modules/hiredis/deps/hiredis/example-ae.c deleted file mode 100644 index 5ed34a3a68..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/example-ae.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include "hiredis.h" -#include "async.h" -#include "adapters/ae.h" - -/* Put event loop in the global scope, so it can be explicitly stopped */ -static aeEventLoop *loop; - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - loop = aeCreateEventLoop(); - redisAeAttach(loop, c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - aeMain(loop); - return 0; -} - diff --git a/labs/node_modules/hiredis/deps/hiredis/example-libev.c b/labs/node_modules/hiredis/deps/hiredis/example-libev.c deleted file mode 100644 index 7894f1f487..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/example-libev.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include "hiredis.h" -#include "async.h" -#include "adapters/libev.h" - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibevAttach(EV_DEFAULT_ c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - ev_loop(EV_DEFAULT_ 0); - return 0; -} diff --git a/labs/node_modules/hiredis/deps/hiredis/example-libevent.c b/labs/node_modules/hiredis/deps/hiredis/example-libevent.c deleted file mode 100644 index 9da8e02bff..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/example-libevent.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include -#include "hiredis.h" -#include "async.h" -#include "adapters/libevent.h" - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - struct event_base *base = event_base_new(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibeventAttach(c,base); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - event_base_dispatch(base); - return 0; -} diff --git a/labs/node_modules/hiredis/deps/hiredis/example.c b/labs/node_modules/hiredis/deps/hiredis/example.c deleted file mode 100644 index 90ff9ed5e9..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/example.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include - -#include "hiredis.h" - -int main(void) { - unsigned int j; - redisContext *c; - redisReply *reply; - - struct timeval timeout = { 1, 500000 }; // 1.5 seconds - c = redisConnectWithTimeout((char*)"127.0.0.2", 6379, timeout); - if (c->err) { - printf("Connection error: %s\n", c->errstr); - exit(1); - } - - /* PING server */ - reply = redisCommand(c,"PING"); - printf("PING: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key */ - reply = redisCommand(c,"SET %s %s", "foo", "hello world"); - printf("SET: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key using binary safe API */ - reply = redisCommand(c,"SET %b %b", "bar", 3, "hello", 5); - printf("SET (binary API): %s\n", reply->str); - freeReplyObject(reply); - - /* Try a GET and two INCR */ - reply = redisCommand(c,"GET foo"); - printf("GET foo: %s\n", reply->str); - freeReplyObject(reply); - - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - /* again ... */ - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - - /* Create a list of numbers, from 0 to 9 */ - reply = redisCommand(c,"DEL mylist"); - freeReplyObject(reply); - for (j = 0; j < 10; j++) { - char buf[64]; - - snprintf(buf,64,"%d",j); - reply = redisCommand(c,"LPUSH mylist element-%s", buf); - freeReplyObject(reply); - } - - /* Let's check what we have inside the list */ - reply = redisCommand(c,"LRANGE mylist 0 -1"); - if (reply->type == REDIS_REPLY_ARRAY) { - for (j = 0; j < reply->elements; j++) { - printf("%u) %s\n", j, reply->element[j]->str); - } - } - freeReplyObject(reply); - - return 0; -} diff --git a/labs/node_modules/hiredis/deps/hiredis/fmacros.h b/labs/node_modules/hiredis/deps/hiredis/fmacros.h deleted file mode 100644 index 21cd9cfee3..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/fmacros.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#if !defined(_BSD_SOURCE) -#define _BSD_SOURCE -#endif - -#if defined(__sun__) -#define _POSIX_C_SOURCE 200112L -#elif defined(__linux__) -#define _XOPEN_SOURCE 600 -#else -#define _XOPEN_SOURCE -#endif - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/hiredis.c b/labs/node_modules/hiredis/deps/hiredis/hiredis.c deleted file mode 100644 index 4709ee3253..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/hiredis.c +++ /dev/null @@ -1,1285 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include - -#include "hiredis.h" -#include "net.h" -#include "sds.h" - -static redisReply *createReplyObject(int type); -static void *createStringObject(const redisReadTask *task, char *str, size_t len); -static void *createArrayObject(const redisReadTask *task, int elements); -static void *createIntegerObject(const redisReadTask *task, long long value); -static void *createNilObject(const redisReadTask *task); - -/* Default set of functions to build the reply. Keep in mind that such a - * function returning NULL is interpreted as OOM. */ -static redisReplyObjectFunctions defaultFunctions = { - createStringObject, - createArrayObject, - createIntegerObject, - createNilObject, - freeReplyObject -}; - -/* Create a reply object */ -static redisReply *createReplyObject(int type) { - redisReply *r = calloc(1,sizeof(*r)); - - if (r == NULL) - return NULL; - - r->type = type; - return r; -} - -/* Free a reply object */ -void freeReplyObject(void *reply) { - redisReply *r = reply; - size_t j; - - switch(r->type) { - case REDIS_REPLY_INTEGER: - break; /* Nothing to free */ - case REDIS_REPLY_ARRAY: - if (r->element != NULL) { - for (j = 0; j < r->elements; j++) - if (r->element[j] != NULL) - freeReplyObject(r->element[j]); - free(r->element); - } - break; - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_STRING: - if (r->str != NULL) - free(r->str); - break; - } - free(r); -} - -static void *createStringObject(const redisReadTask *task, char *str, size_t len) { - redisReply *r, *parent; - char *buf; - - r = createReplyObject(task->type); - if (r == NULL) - return NULL; - - buf = malloc(len+1); - if (buf == NULL) { - freeReplyObject(r); - return NULL; - } - - assert(task->type == REDIS_REPLY_ERROR || - task->type == REDIS_REPLY_STATUS || - task->type == REDIS_REPLY_STRING); - - /* Copy string value */ - memcpy(buf,str,len); - buf[len] = '\0'; - r->str = buf; - r->len = len; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createArrayObject(const redisReadTask *task, int elements) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_ARRAY); - if (r == NULL) - return NULL; - - if (elements > 0) { - r->element = calloc(elements,sizeof(redisReply*)); - if (r->element == NULL) { - freeReplyObject(r); - return NULL; - } - } - - r->elements = elements; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createIntegerObject(const redisReadTask *task, long long value) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_INTEGER); - if (r == NULL) - return NULL; - - r->integer = value; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createNilObject(const redisReadTask *task) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_NIL); - if (r == NULL) - return NULL; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void __redisReaderSetError(redisReader *r, int type, const char *str) { - size_t len; - - if (r->reply != NULL && r->fn && r->fn->freeObject) { - r->fn->freeObject(r->reply); - r->reply = NULL; - } - - /* Clear input buffer on errors. */ - if (r->buf != NULL) { - sdsfree(r->buf); - r->buf = NULL; - r->pos = r->len = 0; - } - - /* Reset task stack. */ - r->ridx = -1; - - /* Set error. */ - r->err = type; - len = strlen(str); - len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1); - memcpy(r->errstr,str,len); - r->errstr[len] = '\0'; -} - -static size_t chrtos(char *buf, size_t size, char byte) { - size_t len = 0; - - switch(byte) { - case '\\': - case '"': - len = snprintf(buf,size,"\"\\%c\"",byte); - break; - case '\n': len = snprintf(buf,size,"\"\\n\""); break; - case '\r': len = snprintf(buf,size,"\"\\r\""); break; - case '\t': len = snprintf(buf,size,"\"\\t\""); break; - case '\a': len = snprintf(buf,size,"\"\\a\""); break; - case '\b': len = snprintf(buf,size,"\"\\b\""); break; - default: - if (isprint(byte)) - len = snprintf(buf,size,"\"%c\"",byte); - else - len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte); - break; - } - - return len; -} - -static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) { - char cbuf[8], sbuf[128]; - - chrtos(cbuf,sizeof(cbuf),byte); - snprintf(sbuf,sizeof(sbuf), - "Protocol error, got %s as reply type byte", cbuf); - __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf); -} - -static void __redisReaderSetErrorOOM(redisReader *r) { - __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory"); -} - -static char *readBytes(redisReader *r, unsigned int bytes) { - char *p; - if (r->len-r->pos >= bytes) { - p = r->buf+r->pos; - r->pos += bytes; - return p; - } - return NULL; -} - -/* Find pointer to \r\n. */ -static char *seekNewline(char *s, size_t len) { - int pos = 0; - int _len = len-1; - - /* Position should be < len-1 because the character at "pos" should be - * followed by a \n. Note that strchr cannot be used because it doesn't - * allow to search a limited length and the buffer that is being searched - * might not have a trailing NULL character. */ - while (pos < _len) { - while(pos < _len && s[pos] != '\r') pos++; - if (s[pos] != '\r') { - /* Not found. */ - return NULL; - } else { - if (s[pos+1] == '\n') { - /* Found. */ - return s+pos; - } else { - /* Continue searching. */ - pos++; - } - } - } - return NULL; -} - -/* Read a long long value starting at *s, under the assumption that it will be - * terminated by \r\n. Ambiguously returns -1 for unexpected input. */ -static long long readLongLong(char *s) { - long long v = 0; - int dec, mult = 1; - char c; - - if (*s == '-') { - mult = -1; - s++; - } else if (*s == '+') { - mult = 1; - s++; - } - - while ((c = *(s++)) != '\r') { - dec = c - '0'; - if (dec >= 0 && dec < 10) { - v *= 10; - v += dec; - } else { - /* Should not happen... */ - return -1; - } - } - - return mult*v; -} - -static char *readLine(redisReader *r, int *_len) { - char *p, *s; - int len; - - p = r->buf+r->pos; - s = seekNewline(p,(r->len-r->pos)); - if (s != NULL) { - len = s-(r->buf+r->pos); - r->pos += len+2; /* skip \r\n */ - if (_len) *_len = len; - return p; - } - return NULL; -} - -static void moveToNextTask(redisReader *r) { - redisReadTask *cur, *prv; - while (r->ridx >= 0) { - /* Return a.s.a.p. when the stack is now empty. */ - if (r->ridx == 0) { - r->ridx--; - return; - } - - cur = &(r->rstack[r->ridx]); - prv = &(r->rstack[r->ridx-1]); - assert(prv->type == REDIS_REPLY_ARRAY); - if (cur->idx == prv->elements-1) { - r->ridx--; - } else { - /* Reset the type because the next item can be anything */ - assert(cur->idx < prv->elements); - cur->type = -1; - cur->elements = -1; - cur->idx++; - return; - } - } -} - -static int processLineItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj; - char *p; - int len; - - if ((p = readLine(r,&len)) != NULL) { - if (cur->type == REDIS_REPLY_INTEGER) { - if (r->fn && r->fn->createInteger) - obj = r->fn->createInteger(cur,readLongLong(p)); - else - obj = (void*)REDIS_REPLY_INTEGER; - } else { - /* Type will be error or status. */ - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,p,len); - else - obj = (void*)(size_t)(cur->type); - } - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj = NULL; - char *p, *s; - long len; - unsigned long bytelen; - int success = 0; - - p = r->buf+r->pos; - s = seekNewline(p,r->len-r->pos); - if (s != NULL) { - p = r->buf+r->pos; - bytelen = s-(r->buf+r->pos)+2; /* include \r\n */ - len = readLongLong(p); - - if (len < 0) { - /* The nil object can always be created. */ - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - success = 1; - } else { - /* Only continue when the buffer contains the entire bulk item. */ - bytelen += len+2; /* include \r\n */ - if (r->pos+bytelen <= r->len) { - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,s+2,len); - else - obj = (void*)REDIS_REPLY_STRING; - success = 1; - } - } - - /* Proceed when obj was created. */ - if (success) { - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - r->pos += bytelen; - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - } - - return REDIS_ERR; -} - -static int processMultiBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj; - char *p; - long elements; - int root = 0; - - /* Set error for nested multi bulks with depth > 7 */ - if (r->ridx == 8) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "No support for nested multi bulk replies with depth > 7"); - return REDIS_ERR; - } - - if ((p = readLine(r,NULL)) != NULL) { - elements = readLongLong(p); - root = (r->ridx == 0); - - if (elements == -1) { - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - moveToNextTask(r); - } else { - if (r->fn && r->fn->createArray) - obj = r->fn->createArray(cur,elements); - else - obj = (void*)REDIS_REPLY_ARRAY; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Modify task stack when there are more than 0 elements. */ - if (elements > 0) { - cur->elements = elements; - cur->obj = obj; - r->ridx++; - r->rstack[r->ridx].type = -1; - r->rstack[r->ridx].elements = -1; - r->rstack[r->ridx].idx = 0; - r->rstack[r->ridx].obj = NULL; - r->rstack[r->ridx].parent = cur; - r->rstack[r->ridx].privdata = r->privdata; - } else { - moveToNextTask(r); - } - } - - /* Set reply if this is the root object. */ - if (root) r->reply = obj; - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - char *p; - - /* check if we need to read type */ - if (cur->type < 0) { - if ((p = readBytes(r,1)) != NULL) { - switch (p[0]) { - case '-': - cur->type = REDIS_REPLY_ERROR; - break; - case '+': - cur->type = REDIS_REPLY_STATUS; - break; - case ':': - cur->type = REDIS_REPLY_INTEGER; - break; - case '$': - cur->type = REDIS_REPLY_STRING; - break; - case '*': - cur->type = REDIS_REPLY_ARRAY; - break; - default: - __redisReaderSetErrorProtocolByte(r,*p); - return REDIS_ERR; - } - } else { - /* could not consume 1 byte */ - return REDIS_ERR; - } - } - - /* process typed item */ - switch(cur->type) { - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_INTEGER: - return processLineItem(r); - case REDIS_REPLY_STRING: - return processBulkItem(r); - case REDIS_REPLY_ARRAY: - return processMultiBulkItem(r); - default: - assert(NULL); - return REDIS_ERR; /* Avoid warning. */ - } -} - -redisReader *redisReaderCreate(void) { - redisReader *r; - - r = calloc(sizeof(redisReader),1); - if (r == NULL) - return NULL; - - r->err = 0; - r->errstr[0] = '\0'; - r->fn = &defaultFunctions; - r->buf = sdsempty(); - r->maxbuf = REDIS_READER_MAX_BUF; - if (r->buf == NULL) { - free(r); - return NULL; - } - - r->ridx = -1; - return r; -} - -void redisReaderFree(redisReader *r) { - if (r->reply != NULL && r->fn && r->fn->freeObject) - r->fn->freeObject(r->reply); - if (r->buf != NULL) - sdsfree(r->buf); - free(r); -} - -int redisReaderFeed(redisReader *r, const char *buf, size_t len) { - sds newbuf; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* Copy the provided buffer. */ - if (buf != NULL && len >= 1) { - /* Destroy internal buffer when it is empty and is quite large. */ - if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) { - sdsfree(r->buf); - r->buf = sdsempty(); - r->pos = 0; - - /* r->buf should not be NULL since we just free'd a larger one. */ - assert(r->buf != NULL); - } - - newbuf = sdscatlen(r->buf,buf,len); - if (newbuf == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - r->buf = newbuf; - r->len = sdslen(r->buf); - } - - return REDIS_OK; -} - -int redisReaderGetReply(redisReader *r, void **reply) { - /* Default target pointer to NULL. */ - if (reply != NULL) - *reply = NULL; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* When the buffer is empty, there will never be a reply. */ - if (r->len == 0) - return REDIS_OK; - - /* Set first item to process when the stack is empty. */ - if (r->ridx == -1) { - r->rstack[0].type = -1; - r->rstack[0].elements = -1; - r->rstack[0].idx = -1; - r->rstack[0].obj = NULL; - r->rstack[0].parent = NULL; - r->rstack[0].privdata = r->privdata; - r->ridx = 0; - } - - /* Process items in reply. */ - while (r->ridx >= 0) - if (processItem(r) != REDIS_OK) - break; - - /* Return ASAP when an error occurred. */ - if (r->err) - return REDIS_ERR; - - /* Discard part of the buffer when we've consumed at least 1k, to avoid - * doing unnecessary calls to memmove() in sds.c. */ - if (r->pos >= 1024) { - r->buf = sdsrange(r->buf,r->pos,-1); - r->pos = 0; - r->len = sdslen(r->buf); - } - - /* Emit a reply when there is one. */ - if (r->ridx == -1) { - if (reply != NULL) - *reply = r->reply; - r->reply = NULL; - } - return REDIS_OK; -} - -/* Calculate the number of bytes needed to represent an integer as string. */ -static int intlen(int i) { - int len = 0; - if (i < 0) { - len++; - i = -i; - } - do { - len++; - i /= 10; - } while(i); - return len; -} - -/* Helper that calculates the bulk length given a certain string length. */ -static size_t bulklen(size_t len) { - return 1+intlen(len)+2+len+2; -} - -int redisvFormatCommand(char **target, const char *format, va_list ap) { - const char *c = format; - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - sds curarg, newarg; /* current argument */ - int touched = 0; /* was the current argument touched? */ - char **curargv = NULL, **newargv = NULL; - int argc = 0; - int totlen = 0; - int j; - - /* Abort if there is not target to set */ - if (target == NULL) - return -1; - - /* Build the command string accordingly to protocol */ - curarg = sdsempty(); - if (curarg == NULL) - return -1; - - while(*c != '\0') { - if (*c != '%' || c[1] == '\0') { - if (*c == ' ') { - if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - - /* curarg is put in argv so it can be overwritten. */ - curarg = sdsempty(); - if (curarg == NULL) goto err; - touched = 0; - } - } else { - newarg = sdscatlen(curarg,c,1); - if (newarg == NULL) goto err; - curarg = newarg; - touched = 1; - } - } else { - char *arg; - size_t size; - - /* Set newarg so it can be checked even if it is not touched. */ - newarg = curarg; - - switch(c[1]) { - case 's': - arg = va_arg(ap,char*); - size = strlen(arg); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case 'b': - arg = va_arg(ap,char*); - size = va_arg(ap,size_t); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case '%': - newarg = sdscat(curarg,"%"); - break; - default: - /* Try to detect printf format */ - { - static const char intfmts[] = "diouxX"; - char _format[16]; - const char *_p = c+1; - size_t _l = 0; - va_list _cpy; - - /* Flags */ - if (*_p != '\0' && *_p == '#') _p++; - if (*_p != '\0' && *_p == '0') _p++; - if (*_p != '\0' && *_p == '-') _p++; - if (*_p != '\0' && *_p == ' ') _p++; - if (*_p != '\0' && *_p == '+') _p++; - - /* Field width */ - while (*_p != '\0' && isdigit(*_p)) _p++; - - /* Precision */ - if (*_p == '.') { - _p++; - while (*_p != '\0' && isdigit(*_p)) _p++; - } - - /* Copy va_list before consuming with va_arg */ - va_copy(_cpy,ap); - - /* Integer conversion (without modifiers) */ - if (strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); - goto fmt_valid; - } - - /* Double conversion (without modifiers) */ - if (strchr("eEfFgGaA",*_p) != NULL) { - va_arg(ap,double); - goto fmt_valid; - } - - /* Size: char */ - if (_p[0] == 'h' && _p[1] == 'h') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* char gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: short */ - if (_p[0] == 'h') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* short gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long long */ - if (_p[0] == 'l' && _p[1] == 'l') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long long); - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long */ - if (_p[0] == 'l') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long); - goto fmt_valid; - } - goto fmt_invalid; - } - - fmt_invalid: - va_end(_cpy); - goto err; - - fmt_valid: - _l = (_p+1)-c; - if (_l < sizeof(_format)-2) { - memcpy(_format,c,_l); - _format[_l] = '\0'; - newarg = sdscatvprintf(curarg,_format,_cpy); - - /* Update current position (note: outer blocks - * increment c twice so compensate here) */ - c = _p-1; - } - - va_end(_cpy); - break; - } - } - - if (newarg == NULL) goto err; - curarg = newarg; - - touched = 1; - c++; - } - c++; - } - - /* Add the last argument if needed */ - if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - } else { - sdsfree(curarg); - } - - /* Clear curarg because it was put in curargv or was free'd. */ - curarg = NULL; - - /* Add bytes needed to hold multi bulk count */ - totlen += 1+intlen(argc)+2; - - /* Build the command at protocol level */ - cmd = malloc(totlen+1); - if (cmd == NULL) goto err; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j])); - memcpy(cmd+pos,curargv[j],sdslen(curargv[j])); - pos += sdslen(curargv[j]); - sdsfree(curargv[j]); - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - free(curargv); - *target = cmd; - return totlen; - -err: - while(argc--) - sdsfree(curargv[argc]); - free(curargv); - - if (curarg != NULL) - sdsfree(curarg); - - /* No need to check cmd since it is the last statement that can fail, - * but do it anyway to be as defensive as possible. */ - if (cmd != NULL) - free(cmd); - - return -1; -} - -/* Format a command according to the Redis protocol. This function - * takes a format similar to printf: - * - * %s represents a C null terminated string you want to interpolate - * %b represents a binary safe string - * - * When using %b you need to provide both the pointer to the string - * and the length in bytes. Examples: - * - * len = redisFormatCommand(target, "GET %s", mykey); - * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen); - */ -int redisFormatCommand(char **target, const char *format, ...) { - va_list ap; - int len; - va_start(ap,format); - len = redisvFormatCommand(target,format,ap); - va_end(ap); - return len; -} - -/* Format a command according to the Redis protocol. This function takes the - * number of arguments, an array with arguments and an array with their - * lengths. If the latter is set to NULL, strlen will be used to compute the - * argument lengths. - */ -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) { - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - size_t len; - int totlen, j; - - /* Calculate number of bytes needed for the command */ - totlen = 1+intlen(argc)+2; - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - totlen += bulklen(len); - } - - /* Build the command at protocol level */ - cmd = malloc(totlen+1); - if (cmd == NULL) - return -1; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - pos += sprintf(cmd+pos,"$%zu\r\n",len); - memcpy(cmd+pos,argv[j],len); - pos += len; - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - *target = cmd; - return totlen; -} - -void __redisSetError(redisContext *c, int type, const char *str) { - size_t len; - - c->err = type; - if (str != NULL) { - len = strlen(str); - len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1); - memcpy(c->errstr,str,len); - c->errstr[len] = '\0'; - } else { - /* Only REDIS_ERR_IO may lack a description! */ - assert(type == REDIS_ERR_IO); - strerror_r(errno,c->errstr,sizeof(c->errstr)); - } -} - -static redisContext *redisContextInit(void) { - redisContext *c; - - c = calloc(1,sizeof(redisContext)); - if (c == NULL) - return NULL; - - c->err = 0; - c->errstr[0] = '\0'; - c->obuf = sdsempty(); - c->reader = redisReaderCreate(); - return c; -} - -void redisFree(redisContext *c) { - if (c->fd > 0) - close(c->fd); - if (c->obuf != NULL) - sdsfree(c->obuf); - if (c->reader != NULL) - redisReaderFree(c->reader); - free(c); -} - -/* Connect to a Redis instance. On error the field error in the returned - * context will be set to the return value of the error function. - * When no set of reply functions is given, the default set will be used. */ -redisContext *redisConnect(const char *ip, int port) { - redisContext *c = redisContextInit(); - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; -} - -redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) { - redisContext *c = redisContextInit(); - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,&tv); - return c; -} - -redisContext *redisConnectNonBlock(const char *ip, int port) { - redisContext *c = redisContextInit(); - c->flags &= ~REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; -} - -redisContext *redisConnectUnix(const char *path) { - redisContext *c = redisContextInit(); - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; -} - -redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) { - redisContext *c = redisContextInit(); - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,&tv); - return c; -} - -redisContext *redisConnectUnixNonBlock(const char *path) { - redisContext *c = redisContextInit(); - c->flags &= ~REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; -} - -/* Set read/write timeout on a blocking socket. */ -int redisSetTimeout(redisContext *c, struct timeval tv) { - if (c->flags & REDIS_BLOCK) - return redisContextSetTimeout(c,tv); - return REDIS_ERR; -} - -/* Use this function to handle a read event on the descriptor. It will try - * and read some bytes from the socket and feed them to the reply parser. - * - * After this function is called, you may use redisContextReadReply to - * see if there is a reply available. */ -int redisBufferRead(redisContext *c) { - char buf[1024*16]; - int nread; - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - nread = read(c->fd,buf,sizeof(buf)); - if (nread == -1) { - if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - } else if (nread == 0) { - __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); - return REDIS_ERR; - } else { - if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - } - return REDIS_OK; -} - -/* Write the output buffer to the socket. - * - * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was - * succesfully written to the socket. When the buffer is empty after the - * write operation, "done" is set to 1 (if given). - * - * Returns REDIS_ERR if an error occured trying to write and sets - * c->errstr to hold the appropriate error string. - */ -int redisBufferWrite(redisContext *c, int *done) { - int nwritten; - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - if (sdslen(c->obuf) > 0) { - nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); - if (nwritten == -1) { - if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - } else if (nwritten > 0) { - if (nwritten == (signed)sdslen(c->obuf)) { - sdsfree(c->obuf); - c->obuf = sdsempty(); - } else { - c->obuf = sdsrange(c->obuf,nwritten,-1); - } - } - } - if (done != NULL) *done = (sdslen(c->obuf) == 0); - return REDIS_OK; -} - -/* Internal helper function to try and get a reply from the reader, - * or set an error in the context otherwise. */ -int redisGetReplyFromReader(redisContext *c, void **reply) { - if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - return REDIS_OK; -} - -int redisGetReply(redisContext *c, void **reply) { - int wdone = 0; - void *aux = NULL; - - /* Try to read pending replies */ - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - - /* For the blocking context, flush output buffer and read reply */ - if (aux == NULL && c->flags & REDIS_BLOCK) { - /* Write until done */ - do { - if (redisBufferWrite(c,&wdone) == REDIS_ERR) - return REDIS_ERR; - } while (!wdone); - - /* Read until there is a reply */ - do { - if (redisBufferRead(c) == REDIS_ERR) - return REDIS_ERR; - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - } while (aux == NULL); - } - - /* Set reply object */ - if (reply != NULL) *reply = aux; - return REDIS_OK; -} - - -/* Helper function for the redisAppendCommand* family of functions. - * - * Write a formatted command to the output buffer. When this family - * is used, you need to call redisGetReply yourself to retrieve - * the reply (or replies in pub/sub). - */ -int __redisAppendCommand(redisContext *c, char *cmd, size_t len) { - sds newbuf; - - newbuf = sdscatlen(c->obuf,cmd,len); - if (newbuf == NULL) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - c->obuf = newbuf; - return REDIS_OK; -} - -int redisvAppendCommand(redisContext *c, const char *format, va_list ap) { - char *cmd; - int len; - - len = redisvFormatCommand(&cmd,format,ap); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - free(cmd); - return REDIS_ERR; - } - - free(cmd); - return REDIS_OK; -} - -int redisAppendCommand(redisContext *c, const char *format, ...) { - va_list ap; - int ret; - - va_start(ap,format); - ret = redisvAppendCommand(c,format,ap); - va_end(ap); - return ret; -} - -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - char *cmd; - int len; - - len = redisFormatCommandArgv(&cmd,argc,argv,argvlen); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - free(cmd); - return REDIS_ERR; - } - - free(cmd); - return REDIS_OK; -} - -/* Helper function for the redisCommand* family of functions. - * - * Write a formatted command to the output buffer. If the given context is - * blocking, immediately read the reply into the "reply" pointer. When the - * context is non-blocking, the "reply" pointer will not be used and the - * command is simply appended to the write buffer. - * - * Returns the reply when a reply was succesfully retrieved. Returns NULL - * otherwise. When NULL is returned in a blocking context, the error field - * in the context will be set. - */ -static void *__redisBlockForReply(redisContext *c) { - void *reply; - - if (c->flags & REDIS_BLOCK) { - if (redisGetReply(c,&reply) != REDIS_OK) - return NULL; - return reply; - } - return NULL; -} - -void *redisvCommand(redisContext *c, const char *format, va_list ap) { - if (redisvAppendCommand(c,format,ap) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} - -void *redisCommand(redisContext *c, const char *format, ...) { - va_list ap; - void *reply = NULL; - va_start(ap,format); - reply = redisvCommand(c,format,ap); - va_end(ap); - return reply; -} - -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} diff --git a/labs/node_modules/hiredis/deps/hiredis/hiredis.h b/labs/node_modules/hiredis/deps/hiredis/hiredis.h deleted file mode 100644 index aadcf35c94..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/hiredis.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_H -#define __HIREDIS_H -#include /* for size_t */ -#include /* for va_list */ -#include /* for struct timeval */ - -#define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 11 -#define HIREDIS_PATCH 0 - -#define REDIS_ERR -1 -#define REDIS_OK 0 - -/* When an error occurs, the err flag in a context is set to hold the type of - * error that occured. REDIS_ERR_IO means there was an I/O error and you - * should use the "errno" variable to find out what is wrong. - * For other values, the "errstr" field will hold a description. */ -#define REDIS_ERR_IO 1 /* Error in read or write */ -#define REDIS_ERR_EOF 3 /* End of file */ -#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ -#define REDIS_ERR_OOM 5 /* Out of memory */ -#define REDIS_ERR_OTHER 2 /* Everything else... */ - -/* Connection type can be blocking or non-blocking and is set in the - * least significant bit of the flags field in redisContext. */ -#define REDIS_BLOCK 0x1 - -/* Connection may be disconnected before being free'd. The second bit - * in the flags field is set when the context is connected. */ -#define REDIS_CONNECTED 0x2 - -/* The async API might try to disconnect cleanly and flush the output - * buffer and read all subsequent replies before disconnecting. - * This flag means no new commands can come in and the connection - * should be terminated once all replies have been read. */ -#define REDIS_DISCONNECTING 0x4 - -/* Flag specific to the async API which means that the context should be clean - * up as soon as possible. */ -#define REDIS_FREEING 0x8 - -/* Flag that is set when an async callback is executed. */ -#define REDIS_IN_CALLBACK 0x10 - -/* Flag that is set when the async context has one or more subscriptions. */ -#define REDIS_SUBSCRIBED 0x20 - -/* Flag that is set when monitor mode is active */ -#define REDIS_MONITORING 0x40 - -#define REDIS_REPLY_STRING 1 -#define REDIS_REPLY_ARRAY 2 -#define REDIS_REPLY_INTEGER 3 -#define REDIS_REPLY_NIL 4 -#define REDIS_REPLY_STATUS 5 -#define REDIS_REPLY_ERROR 6 - -#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the reply object returned by redisCommand() */ -typedef struct redisReply { - int type; /* REDIS_REPLY_* */ - long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ - int len; /* Length of string */ - char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ - size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ - struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ -} redisReply; - -typedef struct redisReadTask { - int type; - int elements; /* number of elements in multibulk container */ - int idx; /* index in parent (array) object */ - void *obj; /* holds user-generated value for a read task */ - struct redisReadTask *parent; /* parent task */ - void *privdata; /* user-settable arbitrary field */ -} redisReadTask; - -typedef struct redisReplyObjectFunctions { - void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, int); - void *(*createInteger)(const redisReadTask*, long long); - void *(*createNil)(const redisReadTask*); - void (*freeObject)(void*); -} redisReplyObjectFunctions; - -/* State for the protocol parser */ -typedef struct redisReader { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - - char *buf; /* Read buffer */ - size_t pos; /* Buffer cursor */ - size_t len; /* Buffer length */ - size_t maxbuf; /* Max length of unused buffer */ - - redisReadTask rstack[9]; - int ridx; /* Index of current read task */ - void *reply; /* Temporary reply pointer */ - - redisReplyObjectFunctions *fn; - void *privdata; -} redisReader; - -/* Public API for the protocol parser. */ -redisReader *redisReaderCreate(void); -void redisReaderFree(redisReader *r); -int redisReaderFeed(redisReader *r, const char *buf, size_t len); -int redisReaderGetReply(redisReader *r, void **reply); - -/* Backwards compatibility, can be removed on big version bump. */ -#define redisReplyReaderCreate redisReaderCreate -#define redisReplyReaderFree redisReaderFree -#define redisReplyReaderFeed redisReaderFeed -#define redisReplyReaderGetReply redisReaderGetReply -#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) -#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply) -#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr) - -/* Function to free the reply objects hiredis returns by default. */ -void freeReplyObject(void *reply); - -/* Functions to format a command according to the protocol. */ -int redisvFormatCommand(char **target, const char *format, va_list ap); -int redisFormatCommand(char **target, const char *format, ...); -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); - -/* Context for a connection to Redis */ -typedef struct redisContext { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - int fd; - int flags; - char *obuf; /* Write buffer */ - redisReader *reader; /* Protocol reader */ -} redisContext; - -redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv); -redisContext *redisConnectNonBlock(const char *ip, int port); -redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv); -redisContext *redisConnectUnixNonBlock(const char *path); -int redisSetTimeout(redisContext *c, struct timeval tv); -void redisFree(redisContext *c); -int redisBufferRead(redisContext *c); -int redisBufferWrite(redisContext *c, int *done); - -/* In a blocking context, this function first checks if there are unconsumed - * replies to return and returns one if so. Otherwise, it flushes the output - * buffer to the socket and reads until it has a reply. In a non-blocking - * context, it will return unconsumed replies until there are no more. */ -int redisGetReply(redisContext *c, void **reply); -int redisGetReplyFromReader(redisContext *c, void **reply); - -/* Write a command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisvAppendCommand(redisContext *c, const char *format, va_list ap); -int redisAppendCommand(redisContext *c, const char *format, ...); -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -/* Issue a command to Redis. In a blocking context, it is identical to calling - * redisAppendCommand, followed by redisGetReply. The function will return - * NULL if there was an error in performing the request, otherwise it will - * return the reply. In a non-blocking context, it is identical to calling - * only redisAppendCommand and will always return NULL. */ -void *redisvCommand(redisContext *c, const char *format, va_list ap); -void *redisCommand(redisContext *c, const char *format, ...); -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/net.c b/labs/node_modules/hiredis/deps/hiredis/net.c deleted file mode 100644 index 82ab2b468c..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/net.c +++ /dev/null @@ -1,291 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2006-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "net.h" -#include "sds.h" - -/* Defined in hiredis.c */ -void __redisSetError(redisContext *c, int type, const char *str); - -static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { - char buf[128]; - size_t len = 0; - - if (prefix != NULL) - len = snprintf(buf,sizeof(buf),"%s: ",prefix); - strerror_r(errno,buf+len,sizeof(buf)-len); - __redisSetError(c,type,buf); -} - -static int redisSetReuseAddr(redisContext *c, int fd) { - int on = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - close(fd); - return REDIS_ERR; - } - return REDIS_OK; -} - -static int redisCreateSocket(redisContext *c, int type) { - int s; - if ((s = socket(type, SOCK_STREAM, 0)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - if (type == AF_INET) { - if (redisSetReuseAddr(c,s) == REDIS_ERR) { - return REDIS_ERR; - } - } - return s; -} - -static int redisSetBlocking(redisContext *c, int fd, int blocking) { - int flags; - - /* Set the socket nonblocking. - * Note that fcntl(2) for F_GETFL and F_SETFL can't be - * interrupted by a signal. */ - if ((flags = fcntl(fd, F_GETFL)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); - close(fd); - return REDIS_ERR; - } - - if (blocking) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if (fcntl(fd, F_SETFL, flags) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); - close(fd); - return REDIS_ERR; - } - return REDIS_OK; -} - -static int redisSetTcpNoDelay(redisContext *c, int fd) { - int yes = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); - close(fd); - return REDIS_ERR; - } - return REDIS_OK; -} - -#define __MAX_MSEC (((LONG_MAX) - 999) / 1000) - -static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) { - struct pollfd wfd[1]; - long msec; - - msec = -1; - wfd[0].fd = fd; - wfd[0].events = POLLOUT; - - /* Only use timeout when not NULL. */ - if (timeout != NULL) { - if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { - close(fd); - return REDIS_ERR; - } - - msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000); - - if (msec < 0 || msec > INT_MAX) { - msec = INT_MAX; - } - } - - if (errno == EINPROGRESS) { - int res; - - if ((res = poll(wfd, 1, msec)) == -1) { - __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); - close(fd); - return REDIS_ERR; - } else if (res == 0) { - errno = ETIMEDOUT; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - close(fd); - return REDIS_ERR; - } - - if (redisCheckSocketError(c, fd) != REDIS_OK) - return REDIS_ERR; - - return REDIS_OK; - } - - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - close(fd); - return REDIS_ERR; -} - -int redisCheckSocketError(redisContext *c, int fd) { - int err = 0; - socklen_t errlen = sizeof(err); - - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); - close(fd); - return REDIS_ERR; - } - - if (err) { - errno = err; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - close(fd); - return REDIS_ERR; - } - - return REDIS_OK; -} - -int redisContextSetTimeout(redisContext *c, struct timeval tv) { - if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); - return REDIS_ERR; - } - if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); - return REDIS_ERR; - } - return REDIS_OK; -} - -int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { - int s, rv; - char _port[6]; /* strlen("65535"); */ - struct addrinfo hints, *servinfo, *p; - int blocking = (c->flags & REDIS_BLOCK); - - snprintf(_port, 6, "%d", port); - memset(&hints,0,sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { - __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); - return REDIS_ERR; - } - for (p = servinfo; p != NULL; p = p->ai_next) { - if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) - continue; - - if (redisSetBlocking(c,s,0) != REDIS_OK) - goto error; - if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { - if (errno == EHOSTUNREACH) { - close(s); - continue; - } else if (errno == EINPROGRESS && !blocking) { - /* This is ok. */ - } else { - if (redisContextWaitReady(c,s,timeout) != REDIS_OK) - goto error; - } - } - if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) - goto error; - if (redisSetTcpNoDelay(c,s) != REDIS_OK) - goto error; - - c->fd = s; - c->flags |= REDIS_CONNECTED; - rv = REDIS_OK; - goto end; - } - if (p == NULL) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - -error: - rv = REDIS_ERR; -end: - freeaddrinfo(servinfo); - return rv; // Need to return REDIS_OK if alright -} - -int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) { - int s; - int blocking = (c->flags & REDIS_BLOCK); - struct sockaddr_un sa; - - if ((s = redisCreateSocket(c,AF_LOCAL)) < 0) - return REDIS_ERR; - if (redisSetBlocking(c,s,0) != REDIS_OK) - return REDIS_ERR; - - sa.sun_family = AF_LOCAL; - strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); - if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { - if (errno == EINPROGRESS && !blocking) { - /* This is ok. */ - } else { - if (redisContextWaitReady(c,s,timeout) != REDIS_OK) - return REDIS_ERR; - } - } - - /* Reset socket to be blocking after connect(2). */ - if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) - return REDIS_ERR; - - c->fd = s; - c->flags |= REDIS_CONNECTED; - return REDIS_OK; -} diff --git a/labs/node_modules/hiredis/deps/hiredis/net.h b/labs/node_modules/hiredis/deps/hiredis/net.h deleted file mode 100644 index eb8a0a1cfb..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/net.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2006-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -#if defined(__sun) -#define AF_LOCAL AF_UNIX -#endif - -int redisCheckSocketError(redisContext *c, int fd); -int redisContextSetTimeout(redisContext *c, struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout); -int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout); - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/sds.c b/labs/node_modules/hiredis/deps/hiredis/sds.c deleted file mode 100644 index 0af9c67209..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/sds.c +++ /dev/null @@ -1,605 +0,0 @@ -/* SDSLib, A C dynamic strings library - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include "sds.h" - -#ifdef SDS_ABORT_ON_OOM -static void sdsOomAbort(void) { - fprintf(stderr,"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)\n"); - abort(); -} -#endif - -sds sdsnewlen(const void *init, size_t initlen) { - struct sdshdr *sh; - - sh = malloc(sizeof(struct sdshdr)+initlen+1); -#ifdef SDS_ABORT_ON_OOM - if (sh == NULL) sdsOomAbort(); -#else - if (sh == NULL) return NULL; -#endif - sh->len = initlen; - sh->free = 0; - if (initlen) { - if (init) memcpy(sh->buf, init, initlen); - else memset(sh->buf,0,initlen); - } - sh->buf[initlen] = '\0'; - return (char*)sh->buf; -} - -sds sdsempty(void) { - return sdsnewlen("",0); -} - -sds sdsnew(const char *init) { - size_t initlen = (init == NULL) ? 0 : strlen(init); - return sdsnewlen(init, initlen); -} - -sds sdsdup(const sds s) { - return sdsnewlen(s, sdslen(s)); -} - -void sdsfree(sds s) { - if (s == NULL) return; - free(s-sizeof(struct sdshdr)); -} - -void sdsupdatelen(sds s) { - struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - int reallen = strlen(s); - sh->free += (sh->len-reallen); - sh->len = reallen; -} - -static sds sdsMakeRoomFor(sds s, size_t addlen) { - struct sdshdr *sh, *newsh; - size_t free = sdsavail(s); - size_t len, newlen; - - if (free >= addlen) return s; - len = sdslen(s); - sh = (void*) (s-(sizeof(struct sdshdr))); - newlen = (len+addlen)*2; - newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1); -#ifdef SDS_ABORT_ON_OOM - if (newsh == NULL) sdsOomAbort(); -#else - if (newsh == NULL) return NULL; -#endif - - newsh->free = newlen - len; - return newsh->buf; -} - -/* Grow the sds to have the specified length. Bytes that were not part of - * the original length of the sds will be set to zero. */ -sds sdsgrowzero(sds s, size_t len) { - struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); - size_t totlen, curlen = sh->len; - - if (len <= curlen) return s; - s = sdsMakeRoomFor(s,len-curlen); - if (s == NULL) return NULL; - - /* Make sure added region doesn't contain garbage */ - sh = (void*)(s-(sizeof(struct sdshdr))); - memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ - totlen = sh->len+sh->free; - sh->len = len; - sh->free = totlen-sh->len; - return s; -} - -sds sdscatlen(sds s, const void *t, size_t len) { - struct sdshdr *sh; - size_t curlen = sdslen(s); - - s = sdsMakeRoomFor(s,len); - if (s == NULL) return NULL; - sh = (void*) (s-(sizeof(struct sdshdr))); - memcpy(s+curlen, t, len); - sh->len = curlen+len; - sh->free = sh->free-len; - s[curlen+len] = '\0'; - return s; -} - -sds sdscat(sds s, const char *t) { - return sdscatlen(s, t, strlen(t)); -} - -sds sdscpylen(sds s, char *t, size_t len) { - struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - size_t totlen = sh->free+sh->len; - - if (totlen < len) { - s = sdsMakeRoomFor(s,len-sh->len); - if (s == NULL) return NULL; - sh = (void*) (s-(sizeof(struct sdshdr))); - totlen = sh->free+sh->len; - } - memcpy(s, t, len); - s[len] = '\0'; - sh->len = len; - sh->free = totlen-len; - return s; -} - -sds sdscpy(sds s, char *t) { - return sdscpylen(s, t, strlen(t)); -} - -sds sdscatvprintf(sds s, const char *fmt, va_list ap) { - va_list cpy; - char *buf, *t; - size_t buflen = 16; - - while(1) { - buf = malloc(buflen); -#ifdef SDS_ABORT_ON_OOM - if (buf == NULL) sdsOomAbort(); -#else - if (buf == NULL) return NULL; -#endif - buf[buflen-2] = '\0'; - va_copy(cpy,ap); - vsnprintf(buf, buflen, fmt, cpy); - if (buf[buflen-2] != '\0') { - free(buf); - buflen *= 2; - continue; - } - break; - } - t = sdscat(s, buf); - free(buf); - return t; -} - -sds sdscatprintf(sds s, const char *fmt, ...) { - va_list ap; - char *t; - va_start(ap, fmt); - t = sdscatvprintf(s,fmt,ap); - va_end(ap); - return t; -} - -sds sdstrim(sds s, const char *cset) { - struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - char *start, *end, *sp, *ep; - size_t len; - - sp = start = s; - ep = end = s+sdslen(s)-1; - while(sp <= end && strchr(cset, *sp)) sp++; - while(ep > start && strchr(cset, *ep)) ep--; - len = (sp > ep) ? 0 : ((ep-sp)+1); - if (sh->buf != sp) memmove(sh->buf, sp, len); - sh->buf[len] = '\0'; - sh->free = sh->free+(sh->len-len); - sh->len = len; - return s; -} - -sds sdsrange(sds s, int start, int end) { - struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - size_t newlen, len = sdslen(s); - - if (len == 0) return s; - if (start < 0) { - start = len+start; - if (start < 0) start = 0; - } - if (end < 0) { - end = len+end; - if (end < 0) end = 0; - } - newlen = (start > end) ? 0 : (end-start)+1; - if (newlen != 0) { - if (start >= (signed)len) { - newlen = 0; - } else if (end >= (signed)len) { - end = len-1; - newlen = (start > end) ? 0 : (end-start)+1; - } - } else { - start = 0; - } - if (start && newlen) memmove(sh->buf, sh->buf+start, newlen); - sh->buf[newlen] = 0; - sh->free = sh->free+(sh->len-newlen); - sh->len = newlen; - return s; -} - -void sdstolower(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = tolower(s[j]); -} - -void sdstoupper(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = toupper(s[j]); -} - -int sdscmp(sds s1, sds s2) { - size_t l1, l2, minlen; - int cmp; - - l1 = sdslen(s1); - l2 = sdslen(s2); - minlen = (l1 < l2) ? l1 : l2; - cmp = memcmp(s1,s2,minlen); - if (cmp == 0) return l1-l2; - return cmp; -} - -/* Split 's' with separator in 'sep'. An array - * of sds strings is returned. *count will be set - * by reference to the number of tokens returned. - * - * On out of memory, zero length string, zero length - * separator, NULL is returned. - * - * Note that 'sep' is able to split a string using - * a multi-character separator. For example - * sdssplit("foo_-_bar","_-_"); will return two - * elements "foo" and "bar". - * - * This version of the function is binary-safe but - * requires length arguments. sdssplit() is just the - * same function but for zero-terminated strings. - */ -sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) { - int elements = 0, slots = 5, start = 0, j; - - sds *tokens = malloc(sizeof(sds)*slots); -#ifdef SDS_ABORT_ON_OOM - if (tokens == NULL) sdsOomAbort(); -#endif - if (seplen < 1 || len < 0 || tokens == NULL) return NULL; - if (len == 0) { - *count = 0; - return tokens; - } - for (j = 0; j < (len-(seplen-1)); j++) { - /* make sure there is room for the next element and the final one */ - if (slots < elements+2) { - sds *newtokens; - - slots *= 2; - newtokens = realloc(tokens,sizeof(sds)*slots); - if (newtokens == NULL) { -#ifdef SDS_ABORT_ON_OOM - sdsOomAbort(); -#else - goto cleanup; -#endif - } - tokens = newtokens; - } - /* search the separator */ - if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { - tokens[elements] = sdsnewlen(s+start,j-start); - if (tokens[elements] == NULL) { -#ifdef SDS_ABORT_ON_OOM - sdsOomAbort(); -#else - goto cleanup; -#endif - } - elements++; - start = j+seplen; - j = j+seplen-1; /* skip the separator */ - } - } - /* Add the final element. We are sure there is room in the tokens array. */ - tokens[elements] = sdsnewlen(s+start,len-start); - if (tokens[elements] == NULL) { -#ifdef SDS_ABORT_ON_OOM - sdsOomAbort(); -#else - goto cleanup; -#endif - } - elements++; - *count = elements; - return tokens; - -#ifndef SDS_ABORT_ON_OOM -cleanup: - { - int i; - for (i = 0; i < elements; i++) sdsfree(tokens[i]); - free(tokens); - return NULL; - } -#endif -} - -void sdsfreesplitres(sds *tokens, int count) { - if (!tokens) return; - while(count--) - sdsfree(tokens[count]); - free(tokens); -} - -sds sdsfromlonglong(long long value) { - char buf[32], *p; - unsigned long long v; - - v = (value < 0) ? -value : value; - p = buf+31; /* point to the last character */ - do { - *p-- = '0'+(v%10); - v /= 10; - } while(v); - if (value < 0) *p-- = '-'; - p++; - return sdsnewlen(p,32-(p-buf)); -} - -sds sdscatrepr(sds s, char *p, size_t len) { - s = sdscatlen(s,"\"",1); - if (s == NULL) return NULL; - - while(len--) { - switch(*p) { - case '\\': - case '"': - s = sdscatprintf(s,"\\%c",*p); - break; - case '\n': s = sdscatlen(s,"\\n",2); break; - case '\r': s = sdscatlen(s,"\\r",2); break; - case '\t': s = sdscatlen(s,"\\t",2); break; - case '\a': s = sdscatlen(s,"\\a",2); break; - case '\b': s = sdscatlen(s,"\\b",2); break; - default: - if (isprint(*p)) - s = sdscatprintf(s,"%c",*p); - else - s = sdscatprintf(s,"\\x%02x",(unsigned char)*p); - break; - } - p++; - if (s == NULL) return NULL; - } - return sdscatlen(s,"\"",1); -} - -/* Split a line into arguments, where every argument can be in the - * following programming-language REPL-alike form: - * - * foo bar "newline are supported\n" and "\xff\x00otherstuff" - * - * The number of arguments is stored into *argc, and an array - * of sds is returned. The caller should sdsfree() all the returned - * strings and finally free() the array itself. - * - * Note that sdscatrepr() is able to convert back a string into - * a quoted string in the same format sdssplitargs() is able to parse. - */ -sds *sdssplitargs(char *line, int *argc) { - char *p = line; - char *current = NULL; - char **vector = NULL, **_vector = NULL; - - *argc = 0; - while(1) { - /* skip blanks */ - while(*p && isspace(*p)) p++; - if (*p) { - /* get a token */ - int inq=0; /* set to 1 if we are in "quotes" */ - int done=0; - - if (current == NULL) { - current = sdsempty(); - if (current == NULL) goto err; - } - - while(!done) { - if (inq) { - if (*p == '\\' && *(p+1)) { - char c; - - p++; - switch(*p) { - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'b': c = '\b'; break; - case 'a': c = '\a'; break; - default: c = *p; break; - } - current = sdscatlen(current,&c,1); - } else if (*p == '"') { - /* closing quote must be followed by a space */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else { - switch(*p) { - case ' ': - case '\n': - case '\r': - case '\t': - case '\0': - done=1; - break; - case '"': - inq=1; - break; - default: - current = sdscatlen(current,p,1); - break; - } - } - if (*p) p++; - if (current == NULL) goto err; - } - /* add the token to the vector */ - _vector = realloc(vector,((*argc)+1)*sizeof(char*)); - if (_vector == NULL) goto err; - - vector = _vector; - vector[*argc] = current; - (*argc)++; - current = NULL; - } else { - return vector; - } - } - -err: - while((*argc)--) - sdsfree(vector[*argc]); - if (vector != NULL) free(vector); - if (current != NULL) sdsfree(current); - return NULL; -} - -#ifdef SDS_TEST_MAIN -#include - -int __failed_tests = 0; -int __test_num = 0; -#define test_cond(descr,_c) do { \ - __test_num++; printf("%d - %s: ", __test_num, descr); \ - if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \ -} while(0); -#define test_report() do { \ - printf("%d tests, %d passed, %d failed\n", __test_num, \ - __test_num-__failed_tests, __failed_tests); \ - if (__failed_tests) { \ - printf("=== WARNING === We have failed tests here...\n"); \ - } \ -} while(0); - -int main(void) { - { - sds x = sdsnew("foo"), y; - - test_cond("Create a string and obtain the length", - sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0) - - sdsfree(x); - x = sdsnewlen("foo",2); - test_cond("Create a string with specified length", - sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0) - - x = sdscat(x,"bar"); - test_cond("Strings concatenation", - sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0); - - x = sdscpy(x,"a"); - test_cond("sdscpy() against an originally longer string", - sdslen(x) == 1 && memcmp(x,"a\0",2) == 0) - - x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk"); - test_cond("sdscpy() against an originally shorter string", - sdslen(x) == 33 && - memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0) - - sdsfree(x); - x = sdscatprintf(sdsempty(),"%d",123); - test_cond("sdscatprintf() seems working in the base case", - sdslen(x) == 3 && memcmp(x,"123\0",4) ==0) - - sdsfree(x); - x = sdstrim(sdsnew("xxciaoyyy"),"xy"); - test_cond("sdstrim() correctly trims characters", - sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0) - - y = sdsrange(sdsdup(x),1,1); - test_cond("sdsrange(...,1,1)", - sdslen(y) == 1 && memcmp(y,"i\0",2) == 0) - - sdsfree(y); - y = sdsrange(sdsdup(x),1,-1); - test_cond("sdsrange(...,1,-1)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsrange(sdsdup(x),-2,-1); - test_cond("sdsrange(...,-2,-1)", - sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0) - - sdsfree(y); - y = sdsrange(sdsdup(x),2,1); - test_cond("sdsrange(...,2,1)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - y = sdsrange(sdsdup(x),1,100); - test_cond("sdsrange(...,1,100)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsrange(sdsdup(x),100,100); - test_cond("sdsrange(...,100,100)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("foo"); - y = sdsnew("foa"); - test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("bar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("aar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0) - } - test_report() -} -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/sds.h b/labs/node_modules/hiredis/deps/hiredis/sds.h deleted file mode 100644 index 94f5871f54..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/sds.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SDSLib, A C dynamic strings library - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#include -#include - -typedef char *sds; - -struct sdshdr { - int len; - int free; - char buf[]; -}; - -static inline size_t sdslen(const sds s) { - struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); - return sh->len; -} - -static inline size_t sdsavail(const sds s) { - struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); - return sh->free; -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -size_t sdslen(const sds s); -sds sdsdup(const sds s); -void sdsfree(sds s); -size_t sdsavail(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscpylen(sds s, char *t, size_t len); -sds sdscpy(sds s, char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdstrim(sds s, const char *cset); -sds sdsrange(sds s, int start, int end); -void sdsupdatelen(sds s); -int sdscmp(sds s1, sds s2); -sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(long long value); -sds sdscatrepr(sds s, char *p, size_t len); -sds *sdssplitargs(char *line, int *argc); - -#endif diff --git a/labs/node_modules/hiredis/deps/hiredis/test.c b/labs/node_modules/hiredis/deps/hiredis/test.c deleted file mode 100644 index 737ad1cc7e..0000000000 --- a/labs/node_modules/hiredis/deps/hiredis/test.c +++ /dev/null @@ -1,656 +0,0 @@ -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hiredis.h" - -enum connection_type { - CONN_TCP, - CONN_UNIX -}; - -struct config { - enum connection_type type; - - struct { - const char *host; - int port; - } tcp; - - struct { - const char *path; - } unix; -}; - -/* The following lines make up our testing "framework" :) */ -static int tests = 0, fails = 0; -#define test(_s) { printf("#%02d ", ++tests); printf(_s); } -#define test_cond(_c) if(_c) printf("\033[0;32mPASSED\033[0;0m\n"); else {printf("\033[0;31mFAILED\033[0;0m\n"); fails++;} - -static long long usec(void) { - struct timeval tv; - gettimeofday(&tv,NULL); - return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; -} - -static redisContext *select_database(redisContext *c) { - redisReply *reply; - - /* Switch to DB 9 for testing, now that we know we can chat. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Make sure the DB is emtpy */ - reply = redisCommand(c,"DBSIZE"); - assert(reply != NULL); - if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) { - /* Awesome, DB 9 is empty and we can continue. */ - freeReplyObject(reply); - } else { - printf("Database #9 is not empty, test can not continue\n"); - exit(1); - } - - return c; -} - -static void disconnect(redisContext *c) { - redisReply *reply; - - /* Make sure we're on DB 9. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - reply = redisCommand(c,"FLUSHDB"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Free the context as well. */ - redisFree(c); -} - -static redisContext *connect(struct config config) { - redisContext *c = NULL; - - if (config.type == CONN_TCP) { - c = redisConnect(config.tcp.host, config.tcp.port); - } else if (config.type == CONN_UNIX) { - c = redisConnectUnix(config.unix.path); - } else { - assert(NULL); - } - - if (c->err) { - printf("Connection error: %s\n", c->errstr); - exit(1); - } - - return select_database(c); -} - -static void test_format_commands(void) { - char *cmd; - int len; - - test("Format command without interpolation: "); - len = redisFormatCommand(&cmd,"SET foo bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%s string interpolation: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo","bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%s and an empty string: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo",""); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - free(cmd); - - test("Format command with an empty string in between proper interpolations: "); - len = redisFormatCommand(&cmd,"SET %s %s","","foo"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 && - len == 4+4+(3+2)+4+(0+2)+4+(3+2)); - free(cmd); - - test("Format command with %%b string interpolation: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%b and an empty string: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - free(cmd); - - test("Format command with literal %%: "); - len = redisFormatCommand(&cmd,"SET %% %%"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 && - len == 4+4+(3+2)+4+(1+2)+4+(1+2)); - free(cmd); - - /* Vararg width depends on the type. These tests make sure that the - * width is correctly determined using the format and subsequent varargs - * can correctly be interpolated. */ -#define INTEGER_WIDTH_TEST(fmt, type) do { \ - type value = 123; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - free(cmd); \ -} while(0) - -#define FLOAT_WIDTH_TEST(type) do { \ - type value = 123.0; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - free(cmd); \ -} while(0) - - INTEGER_WIDTH_TEST("d", int); - INTEGER_WIDTH_TEST("hhd", char); - INTEGER_WIDTH_TEST("hd", short); - INTEGER_WIDTH_TEST("ld", long); - INTEGER_WIDTH_TEST("lld", long long); - INTEGER_WIDTH_TEST("u", unsigned int); - INTEGER_WIDTH_TEST("hhu", unsigned char); - INTEGER_WIDTH_TEST("hu", unsigned short); - INTEGER_WIDTH_TEST("lu", unsigned long); - INTEGER_WIDTH_TEST("llu", unsigned long long); - FLOAT_WIDTH_TEST(float); - FLOAT_WIDTH_TEST(double); - - test("Format command with invalid printf format: "); - len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3); - test_cond(len == -1); - - const char *argv[3]; - argv[0] = "SET"; - argv[1] = "foo\0xxx"; - argv[2] = "bar"; - size_t lens[3] = { 3, 7, 3 }; - int argc = 3; - - test("Format command by passing argc/argv without lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,NULL); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command by passing argc/argv with lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,lens); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(7+2)+4+(3+2)); - free(cmd); -} - -static void test_reply_reader(void) { - redisReader *reader; - void *reply; - int ret; - int i; - - test("Error handling in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - /* when the reply already contains multiple items, they must be free'd - * on an error. valgrind will bark when this doesn't happen. */ - test("Memory cleanup in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*2\r\n",4); - redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - test("Set error on nested multi bulks with depth > 7: "); - reader = redisReaderCreate(); - - for (i = 0; i < 9; i++) { - redisReaderFeed(reader,(char*)"*1\r\n",4); - } - - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strncasecmp(reader->errstr,"No support for",14) == 0); - redisReaderFree(reader); - - test("Works with NULL functions for reply: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r\n",5); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Works when a single newline (\\r\\n) covers two calls to feed: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r",4); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_OK && reply == NULL); - redisReaderFeed(reader,(char*)"\n",1); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Don't reset state after protocol error: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"x",1); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_ERR); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && reply == NULL); - redisReaderFree(reader); - - /* Regression test for issue #45 on GitHub. */ - test("Don't do empty allocation for empty multi bulk: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*0\r\n",4); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_ARRAY && - ((redisReply*)reply)->elements == 0); - freeReplyObject(reply); - redisReaderFree(reader); -} - -static void test_blocking_connection_errors(void) { - redisContext *c; - - test("Returns error when host cannot be resolved: "); - c = redisConnect((char*)"idontexist.local", 6379); - test_cond(c->err == REDIS_ERR_OTHER && - (strcmp(c->errstr,"Name or service not known") == 0 || - strcmp(c->errstr,"Can't resolve: idontexist.local") == 0)); - redisFree(c); - - test("Returns error when the port is not open: "); - c = redisConnect((char*)"localhost", 1); - test_cond(c->err == REDIS_ERR_IO && - strcmp(c->errstr,"Connection refused") == 0); - redisFree(c); - - test("Returns error when the unix socket path doesn't accept connections: "); - c = redisConnectUnix((char*)"/tmp/idontexist.sock"); - test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */ - redisFree(c); -} - -static void test_blocking_connection(struct config config) { - redisContext *c; - redisReply *reply; - - c = connect(config); - - test("Is able to deliver commands: "); - reply = redisCommand(c,"PING"); - test_cond(reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"pong") == 0) - freeReplyObject(reply); - - test("Is a able to send commands verbatim: "); - reply = redisCommand(c,"SET foo bar"); - test_cond (reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"ok") == 0) - freeReplyObject(reply); - - test("%%s String interpolation works: "); - reply = redisCommand(c,"SET %s %s","foo","hello world"); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - strcmp(reply->str,"hello world") == 0); - freeReplyObject(reply); - - test("%%b String interpolation works: "); - reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - memcmp(reply->str,"hello\x00world",11) == 0) - - test("Binary reply length is correct: "); - test_cond(reply->len == 11) - freeReplyObject(reply); - - test("Can parse nil replies: "); - reply = redisCommand(c,"GET nokey"); - test_cond(reply->type == REDIS_REPLY_NIL) - freeReplyObject(reply); - - /* test 7 */ - test("Can parse integer replies: "); - reply = redisCommand(c,"INCR mycounter"); - test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1) - freeReplyObject(reply); - - test("Can parse multi bulk replies: "); - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - freeReplyObject(redisCommand(c,"LPUSH mylist bar")); - reply = redisCommand(c,"LRANGE mylist 0 -1"); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - !memcmp(reply->element[0]->str,"bar",3) && - !memcmp(reply->element[1]->str,"foo",3)) - freeReplyObject(reply); - - /* m/e with multi bulk reply *before* other reply. - * specifically test ordering of reply items to parse. */ - test("Can handle nested multi bulk replies: "); - freeReplyObject(redisCommand(c,"MULTI")); - freeReplyObject(redisCommand(c,"LRANGE mylist 0 -1")); - freeReplyObject(redisCommand(c,"PING")); - reply = (redisCommand(c,"EXEC")); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - reply->element[0]->type == REDIS_REPLY_ARRAY && - reply->element[0]->elements == 2 && - !memcmp(reply->element[0]->element[0]->str,"bar",3) && - !memcmp(reply->element[0]->element[1]->str,"foo",3) && - reply->element[1]->type == REDIS_REPLY_STATUS && - strcasecmp(reply->element[1]->str,"pong") == 0); - freeReplyObject(reply); - - disconnect(c); -} - -static void test_blocking_io_errors(struct config config) { - redisContext *c; - redisReply *reply; - void *_reply; - int major, minor; - - /* Connect to target given by config. */ - c = connect(config); - { - /* Find out Redis version to determine the path for the next test */ - const char *field = "redis_version:"; - char *p, *eptr; - - reply = redisCommand(c,"INFO"); - p = strstr(reply->str,field); - major = strtol(p+strlen(field),&eptr,10); - p = eptr+1; /* char next to the first "." */ - minor = strtol(p,&eptr,10); - freeReplyObject(reply); - } - - test("Returns I/O error when the connection is lost: "); - reply = redisCommand(c,"QUIT"); - if (major >= 2 && minor > 0) { - /* > 2.0 returns OK on QUIT and read() should be issued once more - * to know the descriptor is at EOF. */ - test_cond(strcasecmp(reply->str,"OK") == 0 && - redisGetReply(c,&_reply) == REDIS_ERR); - freeReplyObject(reply); - } else { - test_cond(reply == NULL); - } - - /* On 2.0, QUIT will cause the connection to be closed immediately and - * the read(2) for the reply on QUIT will set the error to EOF. - * On >2.0, QUIT will return with OK and another read(2) needed to be - * issued to find out the socket was closed by the server. In both - * conditions, the error will be set to EOF. */ - assert(c->err == REDIS_ERR_EOF && - strcmp(c->errstr,"Server closed the connection") == 0); - redisFree(c); - - c = connect(config); - test("Returns I/O error on socket timeout: "); - struct timeval tv = { 0, 1000 }; - assert(redisSetTimeout(c,tv) == REDIS_OK); - test_cond(redisGetReply(c,&_reply) == REDIS_ERR && - c->err == REDIS_ERR_IO && errno == EAGAIN); - redisFree(c); -} - -static void test_throughput(struct config config) { - redisContext *c = connect(config); - redisReply **replies; - int i, num; - long long t1, t2; - - test("Throughput:\n"); - for (i = 0; i < 500; i++) - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - - num = 1000; - replies = malloc(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"PING"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"LRANGE mylist 0 499"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0); - - num = 10000; - replies = malloc(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"PING"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"LRANGE mylist 0 499"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - disconnect(c); -} - -// static long __test_callback_flags = 0; -// static void __test_callback(redisContext *c, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// } -// -// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// if (reply) freeReplyObject(reply); -// } -// -// static redisContext *__connect_nonblock() { -// /* Reset callback flags */ -// __test_callback_flags = 0; -// return redisConnectNonBlock("127.0.0.1", port, NULL); -// } -// -// static void test_nonblocking_connection() { -// redisContext *c; -// int wdone = 0; -// -// test("Calls command callback when command is issued: "); -// c = __connect_nonblock(); -// redisSetCommandCallback(c,__test_callback,(void*)1); -// redisCommand(c,"PING"); -// test_cond(__test_callback_flags == 1); -// redisFree(c); -// -// test("Calls disconnect callback on redisDisconnect: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 2); -// redisFree(c); -// -// test("Calls disconnect callback and free callback on redisFree: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisSetFreeCallback(c,__test_callback,(void*)4); -// redisFree(c); -// test_cond(__test_callback_flags == ((2 << 8) | 4)); -// -// test("redisBufferWrite against empty write buffer: "); -// c = __connect_nonblock(); -// test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1); -// redisFree(c); -// -// test("redisBufferWrite against not yet connected fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("redisBufferWrite against closed fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// redisDisconnect(c); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("Process callbacks in the right sequence: "); -// c = __connect_nonblock(); -// redisCommandWithCallback(c,__test_reply_callback,(void*)1,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)3,"PING"); -// -// /* Write output buffer */ -// wdone = 0; -// while(!wdone) { -// usleep(500); -// redisBufferWrite(c,&wdone); -// } -// -// /* Read until at least one callback is executed (the 3 replies will -// * arrive in a single packet, causing all callbacks to be executed in -// * a single pass). */ -// while(__test_callback_flags == 0) { -// assert(redisBufferRead(c) == REDIS_OK); -// redisProcessCallbacks(c); -// } -// test_cond(__test_callback_flags == 0x010203); -// redisFree(c); -// -// test("redisDisconnect executes pending callbacks with NULL reply: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)1); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 0x0201); -// redisFree(c); -// } - -int main(int argc, char **argv) { - struct config cfg = { - .tcp = { - .host = "127.0.0.1", - .port = 6379 - }, - .unix = { - .path = "/tmp/redis.sock" - } - }; - int throughput = 1; - - /* Ignore broken pipe signal (for I/O error tests). */ - signal(SIGPIPE, SIG_IGN); - - /* Parse command line options. */ - argv++; argc--; - while (argc) { - if (argc >= 2 && !strcmp(argv[0],"-h")) { - argv++; argc--; - cfg.tcp.host = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"-p")) { - argv++; argc--; - cfg.tcp.port = atoi(argv[0]); - } else if (argc >= 2 && !strcmp(argv[0],"-s")) { - argv++; argc--; - cfg.unix.path = argv[0]; - } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) { - throughput = 0; - } else { - fprintf(stderr, "Invalid argument: %s\n", argv[0]); - exit(1); - } - argv++; argc--; - } - - test_format_commands(); - test_reply_reader(); - test_blocking_connection_errors(); - - printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port); - cfg.type = CONN_TCP; - test_blocking_connection(cfg); - test_blocking_io_errors(cfg); - if (throughput) test_throughput(cfg); - - printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path); - cfg.type = CONN_UNIX; - test_blocking_connection(cfg); - test_blocking_io_errors(cfg); - if (throughput) test_throughput(cfg); - - if (fails) { - printf("*** %d TESTS FAILED ***\n", fails); - return 1; - } - - printf("ALL TESTS PASSED\n"); - return 0; -} diff --git a/labs/node_modules/hiredis/hiredis.js b/labs/node_modules/hiredis/hiredis.js deleted file mode 100644 index 527c75e043..0000000000 --- a/labs/node_modules/hiredis/hiredis.js +++ /dev/null @@ -1,34 +0,0 @@ -var net = require("net"), - hiredis = require('bindings')('hiredis.node'); - -exports.Reader = hiredis.Reader; -exports.createConnection = function(port, host) { - var s = net.createConnection(port || 6379, host); - var r = new hiredis.Reader(); - var _write = s.write; - - s.write = function() { - var i, args = arguments; - _write.call(s, "*" + args.length + "\r\n"); - for (i = 0; i < args.length; i++) { - var arg = args[i]; - _write.call(s, "$" + arg.length + "\r\n" + arg + "\r\n"); - } - } - - s.on("data", function(data) { - var reply; - r.feed(data); - try { - while((reply = r.get()) !== undefined) - s.emit("reply", reply); - } catch(err) { - r = null; - s.emit("error", err); - s.destroy(); - } - }); - - return s; -} - diff --git a/labs/node_modules/hiredis/node_modules/bindings/README.md b/labs/node_modules/hiredis/node_modules/bindings/README.md deleted file mode 100644 index 585cf512b9..0000000000 --- a/labs/node_modules/hiredis/node_modules/bindings/README.md +++ /dev/null @@ -1,97 +0,0 @@ -node-bindings -============= -### Helper module for loading your native module's .node file - -This is a helper module for authors of Node.js native addon modules. -It is basically the "swiss army knife" of `require()`ing your native module's -`.node` file. - -Throughout the course of Node's native addon history, addons have ended up being -compiled in a variety of different places, depending on which build tool and which -version of node was used. To make matters worse, now the _gyp_ build tool can -produce either a _Release_ or _Debug_ build, each being built into different -locations. - -This module checks _all_ the possible locations that a native addon would be built -at, and returns the first one that loads successfully. - - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install bindings -``` - -Or add it to the `"dependencies"` section of your _package.json_ file. - - -Example -------- - -`require()`ing the proper bindings file for the current node version, platform -and architecture is as simple as: - -``` js -var bindings = require('bindings')('binding.node') - -// Use your bindings defined in your C files -bindings.your_c_function() -``` - - -Nice Error Output ------------------ - -When the `.node` file could not be loaded, `node-bindings` throws an Error with -a nice error message telling you exactly what was tried. You can also check the -`err.tries` Array property. - -``` -Error: Could not load the bindings file. Tried: - → /Users/nrajlich/ref/build/binding.node - → /Users/nrajlich/ref/build/Debug/binding.node - → /Users/nrajlich/ref/build/Release/binding.node - → /Users/nrajlich/ref/out/Debug/binding.node - → /Users/nrajlich/ref/Debug/binding.node - → /Users/nrajlich/ref/out/Release/binding.node - → /Users/nrajlich/ref/Release/binding.node - → /Users/nrajlich/ref/build/default/binding.node - → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node - at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13) - at Object. (/Users/nrajlich/ref/lib/ref.js:5:47) - at Module._compile (module.js:449:26) - at Object.Module._extensions..js (module.js:467:10) - at Module.load (module.js:356:32) - at Function.Module._load (module.js:312:12) - ... -``` - - -License -------- - -(The MIT License) - -Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> - -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. diff --git a/labs/node_modules/hiredis/node_modules/bindings/bindings.js b/labs/node_modules/hiredis/node_modules/bindings/bindings.js deleted file mode 100644 index 93dcf85a18..0000000000 --- a/labs/node_modules/hiredis/node_modules/bindings/bindings.js +++ /dev/null @@ -1,166 +0,0 @@ - -/** - * Module dependencies. - */ - -var fs = require('fs') - , path = require('path') - , join = path.join - , dirname = path.dirname - , exists = fs.existsSync || path.existsSync - , defaults = { - arrow: process.env.NODE_BINDINGS_ARROW || ' → ' - , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled' - , platform: process.platform - , arch: process.arch - , version: process.versions.node - , bindings: 'bindings.node' - , try: [ - // node-gyp's linked version in the "build" dir - [ 'module_root', 'build', 'bindings' ] - // node-waf and gyp_addon (a.k.a node-gyp) - , [ 'module_root', 'build', 'Debug', 'bindings' ] - , [ 'module_root', 'build', 'Release', 'bindings' ] - // Debug files, for development (legacy behavior, remove for node v0.9) - , [ 'module_root', 'out', 'Debug', 'bindings' ] - , [ 'module_root', 'Debug', 'bindings' ] - // Release files, but manually compiled (legacy behavior, remove for node v0.9) - , [ 'module_root', 'out', 'Release', 'bindings' ] - , [ 'module_root', 'Release', 'bindings' ] - // Legacy from node-waf, node <= 0.4.x - , [ 'module_root', 'build', 'default', 'bindings' ] - // Production "Release" buildtype binary (meh...) - , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ] - ] - } - -/** - * The main `bindings()` function loads the compiled bindings for a given module. - * It uses V8's Error API to determine the parent filename that this function is - * being invoked from, which is then used to find the root directory. - */ - -function bindings (opts) { - - // Argument surgery - if (typeof opts == 'string') { - opts = { bindings: opts } - } else if (!opts) { - opts = {} - } - opts.__proto__ = defaults - - // Get the module root - if (!opts.module_root) { - opts.module_root = exports.getRoot(exports.getFileName()) - } - - // Ensure the given bindings name ends with .node - if (path.extname(opts.bindings) != '.node') { - opts.bindings += '.node' - } - - var tries = [] - , i = 0 - , l = opts.try.length - , n - , b - , err - - for (; i (/Users/nrajlich/ref/lib/ref.js:5:47)\n at Module._compile (module.js:449:26)\n at Object.Module._extensions..js (module.js:467:10)\n at Module.load (module.js:356:32)\n at Function.Module._load (module.js:312:12)\n ...\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", - "readmeFilename": "README.md", - "_id": "bindings@1.2.1", - "_from": "bindings@*" -} diff --git a/labs/node_modules/hiredis/node_modules/nan/.dntrc b/labs/node_modules/hiredis/node_modules/nan/.dntrc deleted file mode 100644 index fc7ee64f2f..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/.dntrc +++ /dev/null @@ -1,37 +0,0 @@ -## DNT config file -## see https://github.com/rvagg/dnt - -NODE_VERSIONS="\ - master \ - v0.11.13 \ - v0.11.10 \ - v0.11.9 \ - v0.11.8 \ - v0.11.7 \ - v0.11.6 \ - v0.11.5 \ - v0.11.4 \ - v0.10.28 \ - v0.10.26 \ - v0.10.25 \ - v0.10.24 \ - v0.10.23 \ - v0.10.22 \ - v0.10.21 \ - v0.10.20 \ - v0.10.19 \ - v0.10.18 \ - v0.8.26 \ - v0.8.25 \ - v0.8.24 \ - v0.8.23 \ - v0.8.22 \ -" -OUTPUT_PREFIX="nan-" -TEST_CMD="\ - cd /dnt/test/ && \ - npm install && \ - node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild && \ - node_modules/.bin/tap --gc js/*-test.js; \ -" - diff --git a/labs/node_modules/hiredis/node_modules/nan/LICENSE b/labs/node_modules/hiredis/node_modules/nan/LICENSE deleted file mode 100644 index d502e18a19..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -Copyright 2013, NAN contributors: - - Rod Vagg - - Benjamin Byholm - - Trevor Norris - - Nathan Rajlich - - Brett Lawson - - Ben Noordhuis -(the "Original Author") -All rights reserved. - -MIT +no-false-attribs License - -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. - -Distributions of all or part of the Software intended to be used -by the recipients as they would use the unmodified Software, -containing modifications that substantially alter, remove, or -disable functionality of the Software, outside of the documented -configuration mechanisms provided by the Software, shall be -modified such that the Original Author's bug reporting email -addresses and urls are either replaced with the contact information -of the parties responsible for the changes, or removed entirely. - -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. - - -Except where noted, this license applies to any and all software -programs and associated documentation files created by the -Original Author, when distributed with the Software. diff --git a/labs/node_modules/hiredis/node_modules/nan/README.md b/labs/node_modules/hiredis/node_modules/nan/README.md deleted file mode 100644 index 1836252b9d..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/README.md +++ /dev/null @@ -1,972 +0,0 @@ -Native Abstractions for Node.js -=============================== - -**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** - -***Current version: 1.1.2*** *(See [nan.h](https://github.com/rvagg/nan/blob/master/nan.h) for complete ChangeLog)* - -[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) - -Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. - -This project also contains some helper utilities that make addon development a bit more pleasant. - - * **[News & Updates](#news)** - * **[Usage](#usage)** - * **[Example](#example)** - * **[API](#api)** - - -## News & Updates - -### May-2014: 1.1.0 release - -* We've deprecated `NanSymbol()`, you should just use `NanNew()` now. -* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now. -* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`. -* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``. -* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*. - - -### May-2014: Major changes for V8 3.25 / Node 0.11.13 - -Node 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes. - -Because we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API. - -We have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously. - -The major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`. - -We also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this. - -V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality. - -`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead. - -Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++. - -There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details. - -### Dec-2013: NanCString and NanRawString - -Two new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments. - -### Nov-2013: Node 0.11.9+ breaking V8 change - -The version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases). - -For example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`. - -### Nov-2013: Change to binding.gyp `"include_dirs"` for NAN - -Inclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `" -## Usage - -Simply add **NAN** as a dependency in the *package.json* of your Node addon: - -``` bash -$ npm install --save nan -``` - -Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: - -``` python -"include_dirs" : [ - "` when compiling your addon. - - -## Example - -See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. - -For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. - -Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). - -Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. - -```c++ -// addon.cc -#include -#include -// ... - -using v8::FunctionTemplate; -using v8::Handle; -using v8::Object; -using v8::String; - -void InitAll(Handle exports) { - exports->Set(NanNew("calculateSync"), - NanNew(CalculateSync)->GetFunction()); - - exports->Set(NanNew("calculateAsync"), - NanNew(CalculateAsync)->GetFunction()); -} - -NODE_MODULE(addon, InitAll) -``` - -```c++ -// sync.h -#include -#include - -NAN_METHOD(CalculateSync); -``` - -```c++ -// sync.cc -#include -#include -#include "./sync.h" -// ... - -using v8::Number; - -// Simple synchronous access to the `Estimate()` function -NAN_METHOD(CalculateSync) { - NanScope(); - - // expect a number as the first argument - int points = args[0]->Uint32Value(); - double est = Estimate(points); - - NanReturnValue(NanNew(est)); -} -``` - -```c++ -// async.cc -#include -#include -#include "./async.h" - -// ... - -using v8::Function; -using v8::Local; -using v8::Null; -using v8::Number; -using v8::Value; - -class PiWorker : public NanAsyncWorker { - public: - PiWorker(NanCallback *callback, int points) - : NanAsyncWorker(callback), points(points) {} - ~PiWorker() {} - - // Executed inside the worker-thread. - // It is not safe to access V8, or V8 data structures - // here, so everything we need for input and output - // should go on `this`. - void Execute () { - estimate = Estimate(points); - } - - // Executed when the async work is complete - // this function will be run inside the main event loop - // so it is safe to use V8 again - void HandleOKCallback () { - NanScope(); - - Local argv[] = { - NanNull() - , NanNew(estimate) - }; - - callback->Call(2, argv); - }; - - private: - int points; - double estimate; -}; - -// Asynchronous access to the `Estimate()` function -NAN_METHOD(CalculateAsync) { - NanScope(); - - int points = args[0]->Uint32Value(); - NanCallback *callback = new NanCallback(args[1].As()); - - NanAsyncQueueWorker(new PiWorker(callback, points)); - NanReturnUndefined(); -} -``` - - -## API - - * NAN_METHOD - * NAN_GETTER - * NAN_SETTER - * NAN_PROPERTY_GETTER - * NAN_PROPERTY_SETTER - * NAN_PROPERTY_ENUMERATOR - * NAN_PROPERTY_DELETER - * NAN_PROPERTY_QUERY - * NAN_INDEX_GETTER - * NAN_INDEX_SETTER - * NAN_INDEX_ENUMERATOR - * NAN_INDEX_DELETER - * NAN_INDEX_QUERY - * NAN_WEAK_CALLBACK - * NAN_DEPRECATED - * NAN_INLINE - * NanNew - * NanUndefined - * NanNull - * NanTrue - * NanFalse - * NanReturnValue - * NanReturnUndefined - * NanReturnNull - * NanReturnEmptyString - * NanScope - * NanEscapableScope - * NanEscapeScope - * NanLocker - * NanUnlocker - * NanGetInternalFieldPointer - * NanSetInternalFieldPointer - * NanObjectWrapHandle - * NanSymbol - * NanGetPointerSafe - * NanSetPointerSafe - * NanRawString - * NanCString - * NanBooleanOptionValue - * NanUInt32OptionValue - * NanError, NanTypeError, NanRangeError - * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) - * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) - * NanBufferUse(char *, uint32_t) - * NanNewContextHandle - * NanGetCurrentContext - * NanHasInstance - * NanDisposePersistent - * NanAssignPersistent - * NanMakeWeakPersistent - * NanSetTemplate - * NanMakeCallback - * NanCompileScript - * NanRunScript - * NanAdjustExternalMemory - * NanAddGCEpilogueCallback - * NanAddGCPrologueCallback - * NanRemoveGCEpilogueCallback - * NanRemoveGCPrologueCallback - * NanGetHeapStatistics - * NanCallback - * NanAsyncWorker - * NanAsyncQueueWorker - - -### NAN_METHOD(methodname) - -Use `NAN_METHOD` to define your V8 accessible methods: - -```c++ -// .h: -class Foo : public node::ObjectWrap { - ... - - static NAN_METHOD(Bar); - static NAN_METHOD(Baz); -} - - -// .cc: -NAN_METHOD(Foo::Bar) { - ... -} - -NAN_METHOD(Foo::Baz) { - ... -} -``` - -The reason for this macro is because of the method signature change in 0.11: - -```c++ -// 0.10 and below: -Handle name(const Arguments& args) - -// 0.11 and above -void name(const FunctionCallbackInfo& args) -``` - -The introduction of `FunctionCallbackInfo` brings additional complications: - - -### NAN_GETTER(methodname) - -Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. - - -### NAN_SETTER(methodname) - -Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_GETTER(cbname) -Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. - - -### NAN_PROPERTY_SETTER(cbname) -Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_ENUMERATOR(cbname) -Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. - - -### NAN_PROPERTY_DELETER(cbname) -Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. - - -### NAN_PROPERTY_QUERY(cbname) -Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. - - -### NAN_INDEX_GETTER(cbname) -Use `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`. - - -### NAN_INDEX_SETTER(cbname) -Use `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_INDEX_ENUMERATOR(cbname) -Use `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`. - - -### NAN_INDEX_DELETER(cbname) -Use `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`. - - -### NAN_INDEX_QUERY(cbname) -Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`. - - -### NAN_WEAK_CALLBACK(cbname) - -Use `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. Do not use for declaration. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - int *parameter = data.GetParameter(); - NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL); - if ((*parameter)++ == 0) { - data.Revive(); - } else { - delete parameter; - } -} -``` - - -### NAN_DEPRECATED -Declares a function as deprecated. - -```c++ -static NAN_DEPRECATED NAN_METHOD(foo) { - ... -} -``` - - -### NAN_INLINE -Inlines a function. - -```c++ -NAN_INLINE int foo(int bar) { - ... -} -``` - - -### Local<T> NanNew<T>( ... ) - -Use `NanNew` to construct almost all v8 objects and make new local handles. - -```c++ -Local s = NanNew("value"); - -... - -Persistent o; - -... - -Local lo = NanNew(o); - -``` - - -### Local<Primitive> NanUndefined() - -Use instead of `Undefined()` - - -### Local<Primitive> NanNull() - -Use instead of `Null()` - - -### Local<Boolean> NanTrue() - -Use instead of `True()` - - -### Local<Boolean> NanFalse() - -Use instead of `False()` - - -### NanReturnValue(Handle<Value>) - -Use `NanReturnValue` when you want to return a value from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Bar) { - ... - - NanReturnValue(NanNew("FooBar!")); -} -``` - -No `return` statement required. - - -### NanReturnUndefined() - -Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnUndefined(); -} -``` - - -### NanReturnNull() - -Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnNull(); -} -``` - - -### NanReturnEmptyString() - -Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnEmptyString(); -} -``` - - -### NanScope() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense): - -```c++ -NAN_METHOD(Foo::Bar) { - NanScope(); - - NanReturnValue(NanNew("FooBar!")); -} -``` - -This method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope: - -```c++ -bool Foo::Bar() { - NanScope(); - - Local val = NanFalse(); - ... - return val->Value(); -} -``` - - -### NanEscapableScope() - -The separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8: - -```c++ -Handle Foo::Bar() { - NanEscapableScope(); - - return NanEscapeScope(NanNew("FooBar!")); -} -``` - - -### Local<T> NanEscapeScope(Handle<T> value); -Use together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`. - - -### NanLocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### NanUnlocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### void * NanGetInternalFieldPointer(Handle<Object>, int) - -Gets a pointer to the internal field with at `index` from a V8 `Object` handle. - -```c++ -Local obj; -... -NanGetInternalFieldPointer(obj, 0); -``` - -### void NanSetInternalFieldPointer(Handle<Object>, int, void *) - -Sets the value of the internal field at `index` on a V8 `Object` handle. - -```c++ -static Persistent dataWrapperCtor; -... -Local wrapper = NanNew(dataWrapperCtor)->NewInstance(); -NanSetInternalFieldPointer(wrapper, 0, this); -``` - - -### Local<Object> NanObjectWrapHandle(Object) - -When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: - -```c++ -NanObjectWrapHandle(iterator)->Get(NanNew("end")) -``` - - -### Local<String> NanSymbol(const char *) - -Deprecated. Use `NanNew` instead. -Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects. - -```c++ -bool foo = false; -if (obj->Has(NanNew("foo"))) - foo = optionsObj->Get(NanNew("foo"))->BooleanValue() -``` - - -### Type NanGetPointerSafe(Type *[, Type]) - -A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. - -```c++ -char *plugh(uint32_t *optional) { - char res[] = "xyzzy"; - uint32_t param = NanGetPointerSafe(optional, 0x1337); - switch (param) { - ... - } - NanSetPointerSafe(optional, 0xDEADBEEF); -} -``` - - -### bool NanSetPointerSafe(Type *, Type) - -A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to. - -```c++ -const char *plugh(size_t *outputsize) { - char res[] = "xyzzy"; - if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { - ... - } - - ... -} -``` - - -### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int) - -When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -void* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); -char param_copy[count]; -memcpy(param_copy, decoded, count); -delete[] decoded; -``` - - -### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int]) - -When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -char* name = NanCString(args[0], &count); -``` - - -### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) - -When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. - -The optional last parameter is the *default* value, which is `false` if left off: - -```c++ -// `foo` is false unless the user supplies a truthy value for it -bool foo = NanBooleanOptionValue(optionsObj, NanNew("foo")); -// `bar` is true unless the user supplies a falsy value for it -bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew("bar"), true); -``` - - -### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) - -Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. - -Requires all 3 arguments as a default is not optional: - -```c++ -uint32_t count = NanUInt32OptionValue(optionsObj, NanNew("count"), 1024); -``` - - -### NanError(message), NanTypeError(message), NanRangeError(message) - -For making `Error`, `TypeError` and `RangeError` objects. - -```c++ -Local res = NanError("you must supply a callback argument"); -``` - - -### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) - -For throwing `Error`, `TypeError` and `RangeError` objects. - -```c++ -NanThrowError("you must supply a callback argument"); -``` - -Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. - - -### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) - -The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: - -```c++ -NanNewBufferHandle((char*)value.data(), value.size()); -``` - -Can also be used to initialize a `Buffer` with just a `size` argument. - -Can also be supplied with a `NanFreeCallback` and a hint for the garbage collector. - - -### Local<Object> NanBufferUse(char*, uint32_t) - -`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. -While it was possible to get around this, it required a shim by passing a -callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove -needing to use this shim. - -`NanBufferUse` uses the `char*` passed as the backing data, and will free the -memory automatically when the weak callback is called. Keep this in mind, as -careless use can lead to "double free or corruption" and other cryptic failures. - - -### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) - -Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. - - -### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) -Creates a new `Local` handle. - -```c++ -Local ftmpl = NanNew(); -Local otmpl = ftmpl->InstanceTemplate(); -Local ctx = NanNewContextHandle(NULL, otmpl); -``` - - -### Local<Context> NanGetCurrentContext() - -Gets the current context. - -```c++ -Local ctx = NanGetCurrentContext(); -``` - - -### void NanDisposePersistent(Persistent<T> &) - -Use `NanDisposePersistent` to dispose a `Persistent` handle. - -```c++ -NanDisposePersistent(persistentHandle); -``` - - -### NanAssignPersistent(handle, object) - -Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. - -In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: - -```c++ -Persistent persistentHandle; - -... - -Local obj = NanNew(); -obj->Set(NanNew("key"), keyHandle); // where keyHandle might be a Local -NanAssignPersistent(persistentHandle, obj) -``` - - -### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback) - -Creates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. The callback has to be fully specialized to work on all versions of Node. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - -... - -} - -Local func; - -... - -int *parameter = new int(0); -NanMakeWeakPersistent(func, parameter, &weakCallback); -``` - - -### NanSetTemplate(templ, name, value) - -Use to add properties on object and function templates. - - -### NanMakeCallback(target, func, argc, argv) - -Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions. - - -### NanCompileScript(Handle s [, const ScriptOrigin& origin]) - -Use to create new scripts bound to the current context. - - -### NanRunScript(script) - -Use to run both bound and unbound scripts. - - -### NanAdjustExternalMemory(int change_in_bytes) - -Simply does `AdjustAmountOfExternalAllocatedMemory` - - -### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCEpilogueCallback` - - -### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCPrologueCallback` - - -### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback) - -Simply does `RemoveGCEpilogueCallback` - - -### NanRemoveGCPrologueCallback(GCPrologueCallback callback) - -Simply does `RemoveGCPrologueCallback` - - -### NanGetHeapStatistics(HeapStatistics *heap_statistics) - -Simply does `GetHeapStatistics` - - -### NanCallback - -Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. - -```c++ -Local callbackHandle = args[0].As(); -NanCallback *callback = new NanCallback(callbackHandle); -// pass `callback` around and it's safe from GC until you: -delete callback; -``` - -You can execute the callback like so: - -```c++ -// no arguments: -callback->Call(0, NULL); - -// an error argument: -Handle argv[] = { - NanError(NanNew("fail!")) -}; -callback->Call(1, argv); - -// a success argument: -Handle argv[] = { - NanNull(), - NanNew("w00t!") -}; -callback->Call(2, argv); -``` - -`NanCallback` also has a `Local GetCallback()` method that you can use -to fetch a local handle to the underlying callback function, as well as a -`void SetFunction(Handle)` for setting the callback on the -`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using -`NanCallback` without performing heap allocations. - - -### NanAsyncWorker - -`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. - -See a rough outline of the implementation: - -```c++ -class NanAsyncWorker { -public: - NanAsyncWorker (NanCallback *callback); - - // Clean up persistent handles and delete the *callback - virtual ~NanAsyncWorker (); - - // Check the `ErrorMessage()` and call HandleOKCallback() - // or HandleErrorCallback depending on whether it has been set or not - virtual void WorkComplete (); - - // You must implement this to do some async work. If there is an - // error then use `SetErrorMessage()` to set an error message and the callback will - // be passed that string in an Error object - virtual void Execute (); - - // Save a V8 object in a Persistent handle to protect it from GC - void SaveToPersistent(const char *key, Local &obj); - - // Fetch a stored V8 object (don't call from within `Execute()`) - Local GetFromPersistent(const char *key); - - // Get the error message (or NULL) - const char *ErrorMessage(); - - // Set an error message - void SetErrorMessage(const char *msg); - -protected: - // Default implementation calls the callback function with no arguments. - // Override this to return meaningful data - virtual void HandleOKCallback (); - - // Default implementation calls the callback function with an Error object - // wrapping the `errmsg` string - virtual void HandleErrorCallback (); -}; -``` - - -### NanAsyncQueueWorker(NanAsyncWorker *) - -`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. - -### Contributors - -NAN is only possible due to the excellent work of the following contributors: - - - - - - - - -
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
- -Licence & copyright ------------------------ - -Copyright (c) 2014 NAN contributors (listed above). - -Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/labs/node_modules/hiredis/node_modules/nan/build/config.gypi b/labs/node_modules/hiredis/node_modules/nan/build/config.gypi deleted file mode 100644 index e085a5008e..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/build/config.gypi +++ /dev/null @@ -1,38 +0,0 @@ -# Do not edit. File was generated by node-gyp's "configure" step -{ - "target_defaults": { - "cflags": [], - "default_configuration": "Release", - "defines": [], - "include_dirs": [], - "libraries": [] - }, - "variables": { - "clang": 0, - "gcc_version": 47, - "host_arch": "x64", - "node_install_npm": "true", - "node_prefix": "", - "node_shared_cares": "false", - "node_shared_http_parser": "false", - "node_shared_libuv": "false", - "node_shared_openssl": "false", - "node_shared_v8": "false", - "node_shared_zlib": "false", - "node_tag": "", - "node_unsafe_optimizations": 0, - "node_use_dtrace": "false", - "node_use_etw": "false", - "node_use_openssl": "true", - "node_use_perfctr": "false", - "node_use_systemtap": "false", - "python": "/usr/bin/python", - "target_arch": "x64", - "v8_enable_gdbjit": 0, - "v8_no_strict_aliasing": 1, - "v8_use_snapshot": "true", - "nodedir": "/home/rvagg/.node-gyp/0.10.21", - "copy_dev_lib": "true", - "standalone_static_library": 1 - } -} diff --git a/labs/node_modules/hiredis/node_modules/nan/include_dirs.js b/labs/node_modules/hiredis/node_modules/nan/include_dirs.js deleted file mode 100644 index 4f1dfb4166..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/include_dirs.js +++ /dev/null @@ -1 +0,0 @@ -console.log(require('path').relative('.', __dirname)); diff --git a/labs/node_modules/hiredis/node_modules/nan/nan.h b/labs/node_modules/hiredis/node_modules/nan/nan.h deleted file mode 100644 index d7097acd0e..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/nan.h +++ /dev/null @@ -1,2155 +0,0 @@ -/********************************************************************************** - * NAN - Native Abstractions for Node.js - * - * Copyright (c) 2014 NAN contributors: - * - Rod Vagg - * - Benjamin Byholm - * - Trevor Norris - * - Nathan Rajlich - * - Brett Lawson - * - Ben Noordhuis - * - * MIT +no-false-attribs License - * - * Version 1.1.2 (current Node unstable: 0.11.13, Node stable: 0.10.28) - * - * ChangeLog: - * * 1.1.2 May 28 2014 - * - Release to fix more stuff-ups in 1.1.1 - * - * * 1.1.1 May 28 2014 - * - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 - * - * * 1.1.0 May 25 2014 - * - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead - * - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), - * (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, - * v8::String::ExternalAsciiStringResource* - * - Deprecate NanSymbol() - * - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker - * - * * 1.0.0 May 4 2014 - * - Heavy API changes for V8 3.25 / Node 0.11.13 - * - Use cpplint.py - * - Removed NanInitPersistent - * - Removed NanPersistentToLocal - * - Removed NanFromV8String - * - Removed NanMakeWeak - * - Removed NanNewLocal - * - Removed NAN_WEAK_CALLBACK_OBJECT - * - Removed NAN_WEAK_CALLBACK_DATA - * - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions - * - Introduce NanUndefined, NanNull, NanTrue and NanFalse - * - Introduce NanEscapableScope and NanEscapeScope - * - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) - * - Introduce NanMakeCallback for node::MakeCallback - * - Introduce NanSetTemplate - * - Introduce NanGetCurrentContext - * - Introduce NanCompileScript and NanRunScript - * - Introduce NanAdjustExternalMemory - * - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback - * - Introduce NanGetHeapStatistics - * - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() - * - * * 0.8.0 Jan 9 2014 - * - NanDispose -> NanDisposePersistent, deprecate NanDispose - * - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() - * - * * 0.7.1 Jan 9 2014 - * - Fixes to work against debug builds of Node - * - Safer NanPersistentToLocal (avoid reinterpret_cast) - * - Speed up common NanRawString case by only extracting flattened string when necessary - * - * * 0.7.0 Dec 17 2013 - * - New no-arg form of NanCallback() constructor. - * - NanCallback#Call takes Handle rather than Local - * - Removed deprecated NanCallback#Run method, use NanCallback#Call instead - * - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS - * - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() - * - Introduce NanRawString() for char* (or appropriate void*) from v8::String - * (replacement for NanFromV8String) - * - Introduce NanCString() for null-terminated char* from v8::String - * - * * 0.6.0 Nov 21 2013 - * - Introduce NanNewLocal(v8::Handle value) for use in place of - * v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 - * - * * 0.5.2 Nov 16 2013 - * - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public - * - * * 0.5.1 Nov 12 2013 - * - Use node::MakeCallback() instead of direct v8::Function::Call() - * - * * 0.5.0 Nov 11 2013 - * - Added @TooTallNate as collaborator - * - New, much simpler, "include_dirs" for binding.gyp - * - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros - * - * * 0.4.4 Nov 2 2013 - * - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ - * - * * 0.4.3 Nov 2 2013 - * - Include node_object_wrap.h, removed from node.h for Node 0.11.8. - * - * * 0.4.2 Nov 2 2013 - * - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for - * Node 0.11.8 release. - * - * * 0.4.1 Sep 16 2013 - * - Added explicit `#include ` as it was removed from node.h for v0.11.8 - * - * * 0.4.0 Sep 2 2013 - * - Added NAN_INLINE and NAN_DEPRECATED and made use of them - * - Added NanError, NanTypeError and NanRangeError - * - Cleaned up code - * - * * 0.3.2 Aug 30 2013 - * - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent - * in NanAsyncWorker - * - * * 0.3.1 Aug 20 2013 - * - fix "not all control paths return a value" compile warning on some platforms - * - * * 0.3.0 Aug 19 2013 - * - Made NAN work with NPM - * - Lots of fixes to NanFromV8String, pulling in features from new Node core - * - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API - * - Added optional error number argument for NanThrowError() - * - Added NanInitPersistent() - * - Added NanReturnNull() and NanReturnEmptyString() - * - Added NanLocker and NanUnlocker - * - Added missing scopes - * - Made sure to clear disposed Persistent handles - * - Changed NanAsyncWorker to allocate error messages on the heap - * - Changed NanThrowError(Local) to NanThrowError(Handle) - * - Fixed leak in NanAsyncWorker when errmsg is used - * - * * 0.2.2 Aug 5 2013 - * - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() - * - * * 0.2.1 Aug 5 2013 - * - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for - * NanFromV8String() - * - * * 0.2.0 Aug 5 2013 - * - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, - * NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY - * - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, - * _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, - * _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, - * _NAN_PROPERTY_QUERY_ARGS - * - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer - * - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, - * NAN_WEAK_CALLBACK_DATA, NanMakeWeak - * - Renamed THROW_ERROR to _NAN_THROW_ERROR - * - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) - * - Added NanBufferUse(char*, uint32_t) - * - Added NanNewContextHandle(v8::ExtensionConfiguration*, - * v8::Handle, v8::Handle) - * - Fixed broken NanCallback#GetFunction() - * - Added optional encoding and size arguments to NanFromV8String() - * - Added NanGetPointerSafe() and NanSetPointerSafe() - * - Added initial test suite (to be expanded) - * - Allow NanUInt32OptionValue to convert any Number object - * - * * 0.1.0 Jul 21 2013 - * - Added `NAN_GETTER`, `NAN_SETTER` - * - Added `NanThrowError` with single Local argument - * - Added `NanNewBufferHandle` with single uint32_t argument - * - Added `NanHasInstance(Persistent&, Handle)` - * - Added `Local NanCallback#GetFunction()` - * - Added `NanCallback#Call(int, Local[])` - * - Deprecated `NanCallback#Run(int, Local[])` in favour of Call - * - * See https://github.com/rvagg/nan for the latest update to this file - **********************************************************************************/ - -#ifndef NAN_H_ -#define NAN_H_ - -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) && !defined(DEBUG) -# define NAN_INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) && !defined(DEBUG) -# define NAN_INLINE __forceinline -#else -# define NAN_INLINE inline -#endif - -#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __declspec(deprecated) -#else -# define NAN_DEPRECATED -#endif - -// some generic helpers - -template NAN_INLINE bool NanSetPointerSafe( - T *var - , T val -) { - if (var) { - *var = val; - return true; - } else { - return false; - } -} - -template NAN_INLINE T NanGetPointerSafe( - T *var - , T fallback = reinterpret_cast(0) -) { - if (var) { - return *var; - } else { - return fallback; - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt, bool def -) { - if (def) { - return optionsObj.IsEmpty() - || !optionsObj->Has(opt) - || optionsObj->Get(opt)->BooleanValue(); - } else { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->BooleanValue(); - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt -) { - return NanBooleanOptionValue(optionsObj, opt, false); -} - -NAN_INLINE uint32_t NanUInt32OptionValue( - v8::Local optionsObj - , v8::Handle opt - , uint32_t def -) { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->IsNumber() - ? optionsObj->Get(opt)->Uint32Value() - : def; -} - -#if (NODE_MODULE_VERSION > 0x000B) -// Node 0.11+ (0.11.3 and below won't compile with these) - -# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE void - -# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE void - -# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_DELETER_ARGS \ - _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE void - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE void - -# define _NAN_INDEX_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE void - -# define _NAN_INDEX_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE void - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void - -# define _NAN_INDEX_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE void - -# define _NAN_INDEX_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE void - - typedef v8::FunctionCallback NanFunctionCallback; - - template - NAN_INLINE v8::Local NanNew() { - return T::New(v8::Isolate::GetCurrent()); - } - - template - NAN_INLINE v8::Local NanNew(P arg1) { - return T::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(v8::Isolate::GetCurrent(), callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(P arg1, int arg2) { - return T::New(v8::Isolate::GetCurrent(), arg1, arg2); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(v8::Isolate::GetCurrent()); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(v8::Isolate::GetCurrent(), length); - } - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - typedef v8::UnboundScript NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New( - v8::Isolate::GetCurrent(), val).As(); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(v8::Isolate::GetCurrent()); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - -# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) -# define NanEscapableScope() \ - v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { - return NanNew(val); - } - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { - return val; - } - -# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) -# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) -# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) -# define NanReturnValue(value) return args.GetReturnValue().Set(value) -# define NanReturnUndefined() return -# define NanReturnNull() return args.GetReturnValue().SetNull() -# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() - -# define NanObjectWrapHandle(obj) obj->handle() - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(v8::Isolate::GetCurrent(), name, value); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Isolate::GetCurrent()->GetCurrentContext(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetAlignedPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetAlignedPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); - } - - NAN_INLINE void NanAddGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); - } - - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); - } - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol(const char* data, int length = -1) { - return NanNew(data, length); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , const v8::Persistent& obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)( - const v8::WeakCallbackData >& data); - _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) - : parameter(param), callback(cb) { - NanAssignPersistent(persistent, handle); - } - - ~_NanWeakCallbackInfo() { - persistent.Reset(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const { - info_->persistent.SetWeak(info_, info_->callback); - } - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - -// do not use for declaration -# define NAN_WEAK_CALLBACK(name) \ - template \ - static NAN_INLINE void _Nan_Weak_Callback_ ## name( \ - const _NanWeakCallbackData &data); \ - template \ - static void name( \ - const v8::WeakCallbackData > &data) { \ - _NanWeakCallbackData wcbd( \ - data.GetParameter()); \ - _Nan_Weak_Callback_ ## name(wcbd); \ - if (wcbd.IsNearDeath()) delete wcbd.GetCallbackInfo(); \ - } \ - \ - template \ - static NAN_INLINE void _Nan_Weak_Callback_ ## name( \ - const _NanWeakCallbackData &data) - -template -NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.SetWeak(cbinfo, callback); - return cbinfo; -} - -# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(v8::Handle error) { - NanScope(); - v8::Isolate::GetCurrent()->ThrowException(error); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(NanNew(msg)); - v8::Local obj = err.As(); - obj->Set(NanNew("code"), NanNew(errorNumber)); - return err; - } - - NAN_INLINE void NanThrowError( - const char *msg - , const int errorNumber - ) { - NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE void NanThrowTypeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE void NanThrowRangeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle - ) { - handle.Reset(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::smalloc::FreeCallback callback - , void *hint - ) { - return node::Buffer::New( - v8::Isolate::GetCurrent(), data, length, callback, hint); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { - return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return node::Buffer::New(v8::Isolate::GetCurrent(), size); - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return NanNew(function_template)->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return v8::Local::New( - isolate - , v8::Context::New(isolate, extensions, tmpl, obj) - ); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->BindToCurrentContext()->Run(); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, func, argc, argv)); - } - -#else -// Node 0.8 and 0.10 - -# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE v8::Handle - -# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle - - typedef v8::InvocationCallback NanFunctionCallback; - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( - const char* data, int length = -1) { - return v8::String::NewSymbol(data, length); - } - - template - NAN_INLINE v8::Local NanNew() { - return v8::Local::New(T::New()); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew(P arg) { - return v8::Local::New(T::New(arg)); - } - - template - NAN_INLINE v8::Local NanNew(P arg, int length) { - return v8::Local::New(T::New(arg, length)); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(length); - } - - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(time).As(); - } - - typedef v8::Script NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::New(s, const_cast(&origin)); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - return v8::Script::New(s); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New(val).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - len = strlen(reinterpret_cast(arg)); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - len = strlen(reinterpret_cast(arg)); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - int length = strlen(reinterpret_cast(arg)); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - int length = strlen(reinterpret_cast(arg)); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(resource); - } - -# define NanScope() v8::HandleScope scope -# define NanEscapableScope() v8::HandleScope scope -# define NanEscapeScope(val) scope.Close(val) -# define NanLocker() v8::Locker locker -# define NanUnlocker() v8::Unlocker unlocker -# define NanReturnValue(value) return scope.Close(value) -# define NanReturnUndefined() return v8::Undefined() -# define NanReturnNull() return v8::Null() -# define NanReturnEmptyString() return v8::String::Empty() -# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined())); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null())); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True())); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False())); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return v8::V8::AdjustAmountOfExternalAllocatedMemory(bc); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(name, value); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Context::GetCurrent(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::GCEpilogueCallback callback) { - v8::V8::RemoveGCEpilogueCallback(callback); - } - NAN_INLINE void NanAddGCPrologueCallback( - v8::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCPrologueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::GCPrologueCallback callback) { - v8::V8::RemoveGCPrologueCallback(callback); - } - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::V8::GetHeapStatistics(heap_statistics); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Dispose(); - handle = v8::Persistent::New(obj); - } - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)(v8::Persistent object, void* parameter); - _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) : - parameter(param) - , callback(cb) - , persistent(v8::Persistent::New(handle)) { } - - ~_NanWeakCallbackInfo() { - persistent.Dispose(); - persistent.Clear(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const { - info_->persistent.MakeWeak(info_, info_->callback); - } - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - -// do not use for declaration -# define NAN_WEAK_CALLBACK(name) \ - template \ - static NAN_INLINE void _Nan_Weak_Callback_ ## name( \ - const _NanWeakCallbackData &data); \ - template \ - static void name( \ - v8::Persistent object, void *data) { \ - _NanWeakCallbackData wcbd( \ - static_cast<_NanWeakCallbackInfo*>(data)); \ - _Nan_Weak_Callback_ ## name(wcbd); \ - if (wcbd.IsNearDeath()) delete wcbd.GetCallbackInfo(); \ - } \ - \ - template \ - static NAN_INLINE void _Nan_Weak_Callback_ ## name( \ - const _NanWeakCallbackData &data) - - template - NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.MakeWeak(cbinfo, callback); - return cbinfo; - } - -# define _NAN_ERROR(fun, errmsg) \ - fun(v8::String::New(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - return v8::Local::New( \ - v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError( - v8::Handle error - ) { - NanScope(); - return v8::Local::New(v8::ThrowException(error)); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(v8::String::New(msg)); - v8::Local obj = err.As(); - obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); - return err; - } - - NAN_INLINE v8::Local NanThrowError( - const char *msg - , const int errorNumber - ) { - return NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowTypeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError( - const char* errmsg - ) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowRangeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template - NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle) { // NOLINT(runtime/references) - handle.Dispose(); - handle.Clear(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::Buffer::free_callback callback - , void *hint - ) { - return NanNew( - node::Buffer::New(data, length, callback, hint)->handle_); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { -#if NODE_MODULE_VERSION >= 0x000B - return NanNew(node::Buffer::New(data, size)->handle_); -#else - return NanNew( - node::Buffer::New(const_cast(data), size)->handle_); -#endif - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return NanNew(node::Buffer::New(size)->handle_); - } - - NAN_INLINE void FreeData(char *data, void *hint) { - delete[] data; - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return NanNew( - node::Buffer::New(data, size, FreeData, NULL)->handle_); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return function_template->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); - v8::Local lctx = NanNew(ctx); - ctx.Dispose(); - return lctx; - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::Compile(s, const_cast(&origin)); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - return v8::Script::Compile(s); - } - - NAN_INLINE v8::Local NanRunScript(v8::Handle script) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, func, argc, argv)); -# else - v8::TryCatch try_catch; - v8::Local result = NanNew(func->Call(target, argc, argv)); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - return result; -# endif - } - -#endif // NODE_MODULE_VERSION - -typedef void (*NanFreeCallback)(char *data, void *hint); - -#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) -#define NAN_GETTER(name) \ - _NAN_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_GETTER_ARGS) -#define NAN_SETTER(name) \ - _NAN_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_SETTER_ARGS) -#define NAN_PROPERTY_GETTER(name) \ - _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_GETTER_ARGS) -#define NAN_PROPERTY_SETTER(name) \ - _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_PROPERTY_SETTER_ARGS) -#define NAN_PROPERTY_ENUMERATOR(name) \ - _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) -#define NAN_PROPERTY_DELETER(name) \ - _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_DELETER_ARGS) -#define NAN_PROPERTY_QUERY(name) \ - _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_QUERY_ARGS) -# define NAN_INDEX_GETTER(name) \ - _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) -#define NAN_INDEX_SETTER(name) \ - _NAN_INDEX_SETTER_RETURN_TYPE name( \ - uint32_t index \ - , v8::Local value \ - , _NAN_INDEX_SETTER_ARGS) -#define NAN_INDEX_ENUMERATOR(name) \ - _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) -#define NAN_INDEX_DELETER(name) \ - _NAN_INDEX_DELETER_RETURN_TYPE name( \ - uint32_t index \ - , _NAN_INDEX_DELETER_ARGS) -#define NAN_INDEX_QUERY(name) \ - _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) - -class NanCallback { - public: - NanCallback() { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - } - - explicit NanCallback(const v8::Handle &fn) { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - SetFunction(fn); - } - - ~NanCallback() { - if (handle.IsEmpty()) return; - NanDisposePersistent(handle); - } - - NAN_INLINE void SetFunction(const v8::Handle &fn) { - NanScope(); - NanNew(handle)->Set(kCallbackIndex, fn); - } - - NAN_INLINE v8::Local GetFunction() const { - NanEscapableScope(); - return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) - .As()); - } - - NAN_INLINE bool IsEmpty() const { - NanScope(); - return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); - } - - void Call(int argc, v8::Handle argv[]) const { - NanScope(); -#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Local callback = NanNew(handle)-> - Get(kCallbackIndex).As(); - node::MakeCallback( - isolate - , isolate->GetCurrentContext()->Global() - , callback - , argc - , argv - ); -#else -#if NODE_VERSION_AT_LEAST(0, 8, 0) - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - node::MakeCallback( - v8::Context::GetCurrent()->Global() - , callback - , argc - , argv - ); -#else - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - NanMakeCallback(v8::Context::GetCurrent()->Global(), callback, argc, argv); -#endif -#endif - } - - private: - v8::Persistent handle; - static const uint32_t kCallbackIndex = 0; -}; - -/* abstract */ class NanAsyncWorker { - public: - explicit NanAsyncWorker(NanCallback *callback) - : callback(callback), errmsg_(NULL) { - request.data = this; - - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(persistentHandle, obj); - } - - virtual ~NanAsyncWorker() { - NanScope(); - - if (!persistentHandle.IsEmpty()) - NanDisposePersistent(persistentHandle); - if (callback) - delete callback; - if (errmsg_) - delete[] errmsg_; - } - - virtual void WorkComplete() { - NanScope(); - - if (errmsg_ == NULL) - HandleOKCallback(); - else - HandleErrorCallback(); - delete callback; - callback = NULL; - } - - NAN_INLINE void SaveToPersistent( - const char *key, const v8::Local &obj) { - v8::Local handle = NanNew(persistentHandle); - handle->Set(NanNew(key), obj); - } - - v8::Local GetFromPersistent(const char *key) const { - NanEscapableScope(); - v8::Local handle = NanNew(persistentHandle); - return NanEscapeScope(handle->Get(NanNew(key)).As()); - } - - virtual void Execute() = 0; - - uv_work_t request; - - protected: - v8::Persistent persistentHandle; - NanCallback *callback; - - virtual void HandleOKCallback() { - NanScope(); - - callback->Call(0, NULL); - } - - virtual void HandleErrorCallback() { - NanScope(); - - v8::Local argv[] = { - v8::Exception::Error(NanNew(ErrorMessage())) - }; - callback->Call(1, argv); - } - - void SetErrorMessage(const char *msg) { - if (errmsg_) { - delete[] errmsg_; - } - - size_t size = strlen(msg) + 1; - errmsg_ = new char[size]; - memcpy(errmsg_, msg, size); - } - - const char* ErrorMessage() const { - return errmsg_; - } - - private: - char *errmsg_; -}; - -NAN_INLINE void NanAsyncExecute (uv_work_t* req) { - NanAsyncWorker *worker = static_cast(req->data); - worker->Execute(); -} - -NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { - NanAsyncWorker* worker = static_cast(req->data); - worker->WorkComplete(); - delete worker; -} - -NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { - uv_queue_work( - uv_default_loop() - , &worker->request - , NanAsyncExecute - , (uv_after_work_cb)NanAsyncExecuteComplete - ); -} - -//// Base 64 //// - -#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) - -// Doesn't check for padding at the end. Can be 1-2 bytes over. -NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { - size_t remainder = size % 4; - - size = (size / 4) * 3; - if (remainder) { - if (size == 0 && remainder == 1) { - // special case: 1-byte input cannot be decoded - size = 0; - } else { - // non-padded input, add 1 or 2 extra bytes - size += 1 + (remainder == 3); - } - } - - return size; -} - -template -NAN_INLINE size_t _nan_base64_decoded_size( - const T* src - , size_t size -) { - if (size == 0) - return 0; - - if (src[size - 1] == '=') - size--; - if (size > 0 && src[size - 1] == '=') - size--; - - return _nan_base64_decoded_size_fast(size); -} - -// supports regular and URL-safe base64 -static const int _nan_unbase64_table[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 - , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 - , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 - , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 - , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] - -template static size_t _nan_base64_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - char* dst = buf; - char* dstEnd = buf + len; - const T* srcEnd = src + srcLen; - - while (src < srcEnd && dst < dstEnd) { - ptrdiff_t remaining = srcEnd - src; - char a, b, c, d; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining == 0 || *src == '=') break; - a = _nan_unbase64(*src++); - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 1 || *src == '=') break; - b = _nan_unbase64(*src++); - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 2 || *src == '=') break; - c = _nan_unbase64(*src++); - - *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 3 || *src == '=') break; - d = _nan_unbase64(*src++); - - *dst++ = ((c & 0x03) << 6) | (d & 0x3F); - } - - return dst - buf; -} - -//// HEX //// - -template unsigned _nan_hex2bin(T c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); - if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); - return static_cast(-1); -} - -template static size_t _nan_hex_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - size_t i; - for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { - unsigned a = _nan_hex2bin(src[i * 2 + 0]); - unsigned b = _nan_hex2bin(src[i * 2 + 1]); - if (!~a || !~b) return i; - buf[i] = a * 16 + b; - } - - return i; -} - -static bool _NanGetExternalParts( - v8::Handle val - , const char** data - , size_t* len -) { - if (node::Buffer::HasInstance(val)) { - *data = node::Buffer::Data(val.As()); - *len = node::Buffer::Length(val.As()); - return true; - } - - assert(val->IsString()); - v8::Local str = NanNew(val.As()); - - if (str->IsExternalAscii()) { - const v8::String::ExternalAsciiStringResource* ext; - ext = str->GetExternalAsciiStringResource(); - *data = ext->data(); - *len = ext->length(); - return true; - - } else if (str->IsExternal()) { - const v8::String::ExternalStringResource* ext; - ext = str->GetExternalStringResource(); - *data = reinterpret_cast(ext->data()); - *len = ext->length(); - return true; - } - - return false; -} - -namespace Nan { - enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; -} - -NAN_INLINE void* NanRawString( - v8::Handle from - , enum Nan::Encoding encoding - , size_t *datalen - , void *buf - , size_t buflen - , int flags -) { - NanScope(); - - size_t sz_; - size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); - char *data = NULL; - size_t len; - bool is_extern = _NanGetExternalParts( - from - , const_cast(&data) - , &len); - - if (is_extern && !term_len) { - NanSetPointerSafe(datalen, len); - return data; - } - - v8::Local toStr = from->ToString(); - - char *to = static_cast(buf); - - switch (encoding) { - case Nan::ASCII: -#if NODE_MODULE_VERSION < 0x000C - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); - return to; -#endif - case Nan::BINARY: - case Nan::BUFFER: - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } -#if NODE_MODULE_VERSION < 0x000C - { - uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; - - size_t len = toStr->Write(twobytebuf, 0, - static_cast(sz_ + term_len), flags); - - for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { - unsigned char *b = reinterpret_cast(&twobytebuf[i]); - to[i] = *b; - } - - NanSetPointerSafe(datalen, len); - - delete[] twobytebuf; - return to; - } -#else - NanSetPointerSafe( - datalen, - toStr->WriteOneByte( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags)); - return to; -#endif - case Nan::UTF8: - sz_ = toStr->Utf8Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteUtf8(to, static_cast(sz_ + term_len) - , NULL, flags) - - term_len); - return to; - case Nan::BASE64: - { - v8::String::Value value(toStr); - sz_ = _nan_base64_decoded_size(*value, value.length()); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len); - } - NanSetPointerSafe( - datalen - , _nan_base64_decode(to, sz_, *value, value.length())); - if (term_len) { - to[sz_] = '\0'; - } - return to; - } - case Nan::UCS2: - { - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[(sz_ + term_len) * 2]; - } else { - assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); - } - - int bc = 2 * toStr->Write( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags); - NanSetPointerSafe(datalen, bc); - return to; - } - case Nan::HEX: - { - v8::String::Value value(toStr); - sz_ = value.length(); - assert(!(sz_ & 1) && "bad hex data"); - if (to == NULL) { - to = new char[sz_ / 2 + term_len]; - } else { - assert(buflen >= sz_ / 2 + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , _nan_hex_decode(to, sz_ / 2, *value, value.length())); - } - if (term_len) { - to[sz_ / 2] = '\0'; - } - return to; - default: - assert(0 && "unknown encoding"); - } - return to; -} - -NAN_INLINE char* NanCString( - v8::Handle from - , size_t *datalen - , char *buf = NULL - , size_t buflen = 0 - , int flags = v8::String::NO_OPTIONS -) { - return static_cast( - NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) - ); -} - -#endif // NAN_H_ diff --git a/labs/node_modules/hiredis/node_modules/nan/package.json b/labs/node_modules/hiredis/node_modules/nan/package.json deleted file mode 100644 index 52eb3bebb3..0000000000 --- a/labs/node_modules/hiredis/node_modules/nan/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "nan", - "version": "1.1.2", - "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", - "main": "include_dirs.js", - "repository": { - "type": "git", - "url": "git://github.com/rvagg/nan.git" - }, - "contributors": [ - { - "name": "Rod Vagg", - "email": "r@va.gg", - "url": "https://github.com/rvagg" - }, - { - "name": "Benjamin Byholm", - "email": "bbyholm@abo.fi", - "url": "https://github.com/kkoopa/" - }, - { - "name": "Trevor Norris", - "email": "trev.norris@gmail.com", - "url": "https://github.com/trevnorris" - }, - { - "name": "Nathan Rajlich", - "email": "nathan@tootallnate.net", - "url": "https://github.com/TooTallNate" - }, - { - "name": "Brett Lawson", - "email": "brett19@gmail.com", - "url": "https://github.com/brett19" - }, - { - "name": "Ben Noordhuis", - "email": "info@bnoordhuis.nl", - "url": "https://github.com/bnoordhuis" - } - ], - "license": "MIT", - "readme": "Native Abstractions for Node.js\n===============================\n\n**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.**\n\n***Current version: 1.1.2*** *(See [nan.h](https://github.com/rvagg/nan/blob/master/nan.h) for complete ChangeLog)*\n\n[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/)\n\nThanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle.\n\nThis project also contains some helper utilities that make addon development a bit more pleasant.\n\n * **[News & Updates](#news)**\n * **[Usage](#usage)**\n * **[Example](#example)**\n * **[API](#api)**\n\n\n## News & Updates\n\n### May-2014: 1.1.0 release\n\n* We've deprecated `NanSymbol()`, you should just use `NanNew()` now.\n* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now.\n* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`.\n* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``.\n* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*.\n\n\n### May-2014: Major changes for V8 3.25 / Node 0.11.13\n\nNode 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes.\n\nBecause we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API.\n\nWe have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously.\n\nThe major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`.\n\nWe also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this.\n\nV8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality.\n\n`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead.\n\nBecause `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++.\n\nThere's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details.\n\n### Dec-2013: NanCString and NanRawString\n\nTwo new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments.\n\n### Nov-2013: Node 0.11.9+ breaking V8 change\n\nThe version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases).\n\nFor example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`.\n\n### Nov-2013: Change to binding.gyp `\"include_dirs\"` for NAN\n\nInclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `\"\n## Usage\n\nSimply add **NAN** as a dependency in the *package.json* of your Node addon:\n\n``` bash\n$ npm install --save nan\n```\n\nPull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files:\n\n``` python\n\"include_dirs\" : [\n \"` when compiling your addon.\n\n\n## Example\n\nSee **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use.\n\nFor a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**.\n\nCompare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work).\n\nNote that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class.\n\n```c++\n// addon.cc\n#include \n#include \n// ...\n\nusing v8::FunctionTemplate;\nusing v8::Handle;\nusing v8::Object;\nusing v8::String;\n\nvoid InitAll(Handle exports) {\n exports->Set(NanNew(\"calculateSync\"),\n NanNew(CalculateSync)->GetFunction());\n\n exports->Set(NanNew(\"calculateAsync\"),\n NanNew(CalculateAsync)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)\n```\n\n```c++\n// sync.h\n#include \n#include \n\nNAN_METHOD(CalculateSync);\n```\n\n```c++\n// sync.cc\n#include \n#include \n#include \"./sync.h\"\n// ...\n\nusing v8::Number;\n\n// Simple synchronous access to the `Estimate()` function\nNAN_METHOD(CalculateSync) {\n NanScope();\n\n // expect a number as the first argument\n int points = args[0]->Uint32Value();\n double est = Estimate(points);\n\n NanReturnValue(NanNew(est));\n}\n```\n\n```c++\n// async.cc\n#include \n#include \n#include \"./async.h\"\n\n// ...\n\nusing v8::Function;\nusing v8::Local;\nusing v8::Null;\nusing v8::Number;\nusing v8::Value;\n\nclass PiWorker : public NanAsyncWorker {\n public:\n PiWorker(NanCallback *callback, int points)\n : NanAsyncWorker(callback), points(points) {}\n ~PiWorker() {}\n\n // Executed inside the worker-thread.\n // It is not safe to access V8, or V8 data structures\n // here, so everything we need for input and output\n // should go on `this`.\n void Execute () {\n estimate = Estimate(points);\n }\n\n // Executed when the async work is complete\n // this function will be run inside the main event loop\n // so it is safe to use V8 again\n void HandleOKCallback () {\n NanScope();\n\n Local argv[] = {\n NanNull()\n , NanNew(estimate)\n };\n\n callback->Call(2, argv);\n };\n\n private:\n int points;\n double estimate;\n};\n\n// Asynchronous access to the `Estimate()` function\nNAN_METHOD(CalculateAsync) {\n NanScope();\n\n int points = args[0]->Uint32Value();\n NanCallback *callback = new NanCallback(args[1].As());\n\n NanAsyncQueueWorker(new PiWorker(callback, points));\n NanReturnUndefined();\n}\n```\n\n\n## API\n\n * NAN_METHOD\n * NAN_GETTER\n * NAN_SETTER\n * NAN_PROPERTY_GETTER\n * NAN_PROPERTY_SETTER\n * NAN_PROPERTY_ENUMERATOR\n * NAN_PROPERTY_DELETER\n * NAN_PROPERTY_QUERY\n * NAN_INDEX_GETTER\n * NAN_INDEX_SETTER\n * NAN_INDEX_ENUMERATOR\n * NAN_INDEX_DELETER\n * NAN_INDEX_QUERY\n * NAN_WEAK_CALLBACK\n * NAN_DEPRECATED\n * NAN_INLINE\n * NanNew\n * NanUndefined\n * NanNull\n * NanTrue\n * NanFalse\n * NanReturnValue\n * NanReturnUndefined\n * NanReturnNull\n * NanReturnEmptyString\n * NanScope\n * NanEscapableScope\n * NanEscapeScope\n * NanLocker\n * NanUnlocker\n * NanGetInternalFieldPointer\n * NanSetInternalFieldPointer\n * NanObjectWrapHandle\n * NanSymbol\n * NanGetPointerSafe\n * NanSetPointerSafe\n * NanRawString\n * NanCString\n * NanBooleanOptionValue\n * NanUInt32OptionValue\n * NanError, NanTypeError, NanRangeError\n * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int)\n * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t)\n * NanBufferUse(char *, uint32_t)\n * NanNewContextHandle\n * NanGetCurrentContext\n * NanHasInstance\n * NanDisposePersistent\n * NanAssignPersistent\n * NanMakeWeakPersistent\n * NanSetTemplate\n * NanMakeCallback\n * NanCompileScript\n * NanRunScript\n * NanAdjustExternalMemory\n * NanAddGCEpilogueCallback\n * NanAddGCPrologueCallback\n * NanRemoveGCEpilogueCallback\n * NanRemoveGCPrologueCallback\n * NanGetHeapStatistics\n * NanCallback\n * NanAsyncWorker\n * NanAsyncQueueWorker\n\n\n### NAN_METHOD(methodname)\n\nUse `NAN_METHOD` to define your V8 accessible methods:\n\n```c++\n// .h:\nclass Foo : public node::ObjectWrap {\n ...\n\n static NAN_METHOD(Bar);\n static NAN_METHOD(Baz);\n}\n\n\n// .cc:\nNAN_METHOD(Foo::Bar) {\n ...\n}\n\nNAN_METHOD(Foo::Baz) {\n ...\n}\n```\n\nThe reason for this macro is because of the method signature change in 0.11:\n\n```c++\n// 0.10 and below:\nHandle name(const Arguments& args)\n\n// 0.11 and above\nvoid name(const FunctionCallbackInfo& args)\n```\n\nThe introduction of `FunctionCallbackInfo` brings additional complications:\n\n\n### NAN_GETTER(methodname)\n\nUse `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`.\n\n\n### NAN_SETTER(methodname)\n\nUse `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with.\n\n\n### NAN_PROPERTY_GETTER(cbname)\nUse `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`.\n\n\n### NAN_PROPERTY_SETTER(cbname)\nUse `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with.\n\n\n### NAN_PROPERTY_ENUMERATOR(cbname)\nUse `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`.\n\n\n### NAN_PROPERTY_DELETER(cbname)\nUse `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`.\n\n\n### NAN_PROPERTY_QUERY(cbname)\nUse `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`.\n\n\n### NAN_INDEX_GETTER(cbname)\nUse `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`.\n\n\n### NAN_INDEX_SETTER(cbname)\nUse `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with.\n\n\n### NAN_INDEX_ENUMERATOR(cbname)\nUse `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`.\n\n\n### NAN_INDEX_DELETER(cbname)\nUse `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`.\n\n\n### NAN_INDEX_QUERY(cbname)\nUse `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`.\n\n\n### NAN_WEAK_CALLBACK(cbname)\n\nUse `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. Do not use for declaration. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round.\n\n```c++\nNAN_WEAK_CALLBACK(weakCallback) {\n int *parameter = data.GetParameter();\n NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL);\n if ((*parameter)++ == 0) {\n data.Revive();\n } else {\n delete parameter;\n }\n}\n```\n\n\n### NAN_DEPRECATED\nDeclares a function as deprecated.\n\n```c++\nstatic NAN_DEPRECATED NAN_METHOD(foo) {\n ...\n}\n```\n\n\n### NAN_INLINE\nInlines a function.\n\n```c++\nNAN_INLINE int foo(int bar) {\n ...\n}\n```\n\n\n### Local<T> NanNew<T>( ... )\n\nUse `NanNew` to construct almost all v8 objects and make new local handles.\n\n```c++\nLocal s = NanNew(\"value\");\n\n...\n\nPersistent o;\n\n...\n\nLocal lo = NanNew(o);\n\n```\n\n\n### Local<Primitive> NanUndefined()\n\nUse instead of `Undefined()`\n\n\n### Local<Primitive> NanNull()\n\nUse instead of `Null()`\n\n\n### Local<Boolean> NanTrue()\n\nUse instead of `True()`\n\n\n### Local<Boolean> NanFalse()\n\nUse instead of `False()`\n\n\n### NanReturnValue(Handle<Value>)\n\nUse `NanReturnValue` when you want to return a value from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n ...\n\n NanReturnValue(NanNew(\"FooBar!\"));\n}\n```\n\nNo `return` statement required.\n\n\n### NanReturnUndefined()\n\nUse `NanReturnUndefined` when you don't want to return anything from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnUndefined();\n}\n```\n\n\n### NanReturnNull()\n\nUse `NanReturnNull` when you want to return `Null` from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnNull();\n}\n```\n\n\n### NanReturnEmptyString()\n\nUse `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnEmptyString();\n}\n```\n\n\n### NanScope()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense):\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanScope();\n\n NanReturnValue(NanNew(\"FooBar!\"));\n}\n```\n\nThis method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope:\n\n```c++\nbool Foo::Bar() {\n NanScope();\n \n Local val = NanFalse();\n ...\n return val->Value();\n}\n```\n\n\n### NanEscapableScope()\n\nThe separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8:\n\n```c++\nHandle Foo::Bar() {\n NanEscapableScope();\n\n return NanEscapeScope(NanNew(\"FooBar!\"));\n}\n```\n\n\n### Local<T> NanEscapeScope(Handle<T> value);\nUse together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`.\n\n\n### NanLocker()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanLocker();\n ...\n NanUnlocker();\n}\n```\n\n\n### NanUnlocker()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanLocker();\n ...\n NanUnlocker();\n}\n```\n\n\n### void * NanGetInternalFieldPointer(Handle<Object>, int)\n\nGets a pointer to the internal field with at `index` from a V8 `Object` handle.\n\n```c++\nLocal obj;\n...\nNanGetInternalFieldPointer(obj, 0);\n```\n\n### void NanSetInternalFieldPointer(Handle<Object>, int, void *)\n\nSets the value of the internal field at `index` on a V8 `Object` handle.\n\n```c++\nstatic Persistent dataWrapperCtor;\n...\nLocal wrapper = NanNew(dataWrapperCtor)->NewInstance();\nNanSetInternalFieldPointer(wrapper, 0, this);\n```\n\n\n### Local<Object> NanObjectWrapHandle(Object)\n\nWhen you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`:\n\n```c++\nNanObjectWrapHandle(iterator)->Get(NanNew(\"end\"))\n```\n\n\n### Local<String> NanSymbol(const char *)\n\nDeprecated. Use `NanNew` instead.\nUse to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects.\n\n```c++\nbool foo = false;\nif (obj->Has(NanNew(\"foo\")))\n foo = optionsObj->Get(NanNew(\"foo\"))->BooleanValue()\n```\n\n\n### Type NanGetPointerSafe(Type *[, Type])\n\nA helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to.\n\n```c++\nchar *plugh(uint32_t *optional) {\n char res[] = \"xyzzy\";\n uint32_t param = NanGetPointerSafe(optional, 0x1337);\n switch (param) {\n ...\n }\n NanSetPointerSafe(optional, 0xDEADBEEF);\n} \n```\n\n\n### bool NanSetPointerSafe(Type *, Type)\n\nA helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to.\n\n```c++\nconst char *plugh(size_t *outputsize) {\n char res[] = \"xyzzy\";\n if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) {\n ...\n }\n\n ...\n}\n```\n\n\n### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int)\n\nWhen you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`.\nJust remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:\n\n```c++\nsize_t count;\nvoid* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED);\nchar param_copy[count];\nmemcpy(param_copy, decoded, count);\ndelete[] decoded;\n```\n\n\n### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int])\n\nWhen you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`.\nJust remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:\n\n```c++\nsize_t count;\nchar* name = NanCString(args[0], &count);\n```\n\n\n### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool])\n\nWhen you have an \"options\" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`.\n\nThe optional last parameter is the *default* value, which is `false` if left off:\n\n```c++\n// `foo` is false unless the user supplies a truthy value for it\nbool foo = NanBooleanOptionValue(optionsObj, NanNew(\"foo\"));\n// `bar` is true unless the user supplies a falsy value for it\nbool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew(\"bar\"), true);\n```\n\n\n### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t)\n\nSimilar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer.\n\nRequires all 3 arguments as a default is not optional:\n\n```c++\nuint32_t count = NanUInt32OptionValue(optionsObj, NanNew(\"count\"), 1024);\n```\n\n\n### NanError(message), NanTypeError(message), NanRangeError(message)\n\nFor making `Error`, `TypeError` and `RangeError` objects.\n\n```c++\nLocal res = NanError(\"you must supply a callback argument\");\n```\n\n\n### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int)\n\nFor throwing `Error`, `TypeError` and `RangeError` objects.\n\n```c++\nNanThrowError(\"you must supply a callback argument\");\n```\n\nCan also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`.\n\n\n### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t)\n\nThe `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation:\n\n```c++\nNanNewBufferHandle((char*)value.data(), value.size());\n```\n\nCan also be used to initialize a `Buffer` with just a `size` argument.\n\nCan also be supplied with a `NanFreeCallback` and a hint for the garbage collector.\n\n\n### Local<Object> NanBufferUse(char*, uint32_t)\n\n`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data.\nWhile it was possible to get around this, it required a shim by passing a\ncallback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove\nneeding to use this shim.\n\n`NanBufferUse` uses the `char*` passed as the backing data, and will free the\nmemory automatically when the weak callback is called. Keep this in mind, as\ncareless use can lead to \"double free or corruption\" and other cryptic failures.\n\n\n### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)\n\nCan be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for.\n\n\n### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>])\nCreates a new `Local` handle.\n\n```c++\nLocal ftmpl = NanNew();\nLocal otmpl = ftmpl->InstanceTemplate();\nLocal ctx = NanNewContextHandle(NULL, otmpl);\n```\n\n\n### Local<Context> NanGetCurrentContext()\n\nGets the current context.\n\n```c++\nLocal ctx = NanGetCurrentContext();\n```\n\n\n### void NanDisposePersistent(Persistent<T> &)\n\nUse `NanDisposePersistent` to dispose a `Persistent` handle.\n\n```c++\nNanDisposePersistent(persistentHandle);\n```\n\n\n### NanAssignPersistent(handle, object)\n\nUse `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier.\n\nIn general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`:\n\n```c++\nPersistent persistentHandle;\n\n...\n\nLocal obj = NanNew();\nobj->Set(NanNew(\"key\"), keyHandle); // where keyHandle might be a Local\nNanAssignPersistent(persistentHandle, obj)\n```\n\n\n### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback)\n\nCreates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. The callback has to be fully specialized to work on all versions of Node.\n\n```c++\nNAN_WEAK_CALLBACK(weakCallback) {\n\n...\n\n}\n\nLocal func;\n\n...\n\nint *parameter = new int(0);\nNanMakeWeakPersistent(func, parameter, &weakCallback);\n```\n\n\n### NanSetTemplate(templ, name, value)\n\nUse to add properties on object and function templates.\n\n\n### NanMakeCallback(target, func, argc, argv)\n\nUse instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions.\n\n\n### NanCompileScript(Handle s [, const ScriptOrigin& origin])\n\nUse to create new scripts bound to the current context.\n\n\n### NanRunScript(script)\n\nUse to run both bound and unbound scripts.\n\n\n### NanAdjustExternalMemory(int change_in_bytes)\n\nSimply does `AdjustAmountOfExternalAllocatedMemory`\n\n\n### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll)\n\nSimply does `AddGCEpilogueCallback`\n\n\n### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll)\n\nSimply does `AddGCPrologueCallback`\n\n\n### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback)\n\nSimply does `RemoveGCEpilogueCallback`\n\n\n### NanRemoveGCPrologueCallback(GCPrologueCallback callback)\n\nSimply does `RemoveGCPrologueCallback`\n\n\n### NanGetHeapStatistics(HeapStatistics *heap_statistics)\n\nSimply does `GetHeapStatistics`\n\n\n### NanCallback\n\nBecause of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`.\n\n```c++\nLocal callbackHandle = args[0].As();\nNanCallback *callback = new NanCallback(callbackHandle);\n// pass `callback` around and it's safe from GC until you:\ndelete callback;\n```\n\nYou can execute the callback like so:\n\n```c++\n// no arguments:\ncallback->Call(0, NULL);\n\n// an error argument:\nHandle argv[] = {\n NanError(NanNew(\"fail!\"))\n};\ncallback->Call(1, argv);\n\n// a success argument:\nHandle argv[] = {\n NanNull(),\n NanNew(\"w00t!\")\n};\ncallback->Call(2, argv);\n```\n\n`NanCallback` also has a `Local GetCallback()` method that you can use\nto fetch a local handle to the underlying callback function, as well as a\n`void SetFunction(Handle)` for setting the callback on the\n`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using\n`NanCallback` without performing heap allocations.\n\n\n### NanAsyncWorker\n\n`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress.\n\nSee a rough outline of the implementation:\n\n```c++\nclass NanAsyncWorker {\npublic:\n NanAsyncWorker (NanCallback *callback);\n\n // Clean up persistent handles and delete the *callback\n virtual ~NanAsyncWorker ();\n\n // Check the `ErrorMessage()` and call HandleOKCallback()\n // or HandleErrorCallback depending on whether it has been set or not\n virtual void WorkComplete ();\n\n // You must implement this to do some async work. If there is an\n // error then use `SetErrorMessage()` to set an error message and the callback will\n // be passed that string in an Error object\n virtual void Execute ();\n\n // Save a V8 object in a Persistent handle to protect it from GC\n void SaveToPersistent(const char *key, Local &obj);\n\n // Fetch a stored V8 object (don't call from within `Execute()`)\n Local GetFromPersistent(const char *key);\n \n // Get the error message (or NULL)\n const char *ErrorMessage();\n \n // Set an error message\n void SetErrorMessage(const char *msg);\n \nprotected:\n // Default implementation calls the callback function with no arguments.\n // Override this to return meaningful data\n virtual void HandleOKCallback ();\n\n // Default implementation calls the callback function with an Error object\n // wrapping the `errmsg` string\n virtual void HandleErrorCallback ();\n};\n```\n\n\n### NanAsyncQueueWorker(NanAsyncWorker *)\n\n`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`.\n\n### Contributors\n\nNAN is only possible due to the excellent work of the following contributors:\n\n\n\n\n\n\n\n\n
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
\n\nLicence & copyright\n-----------------------\n\nCopyright (c) 2014 NAN contributors (listed above).\n\nNative Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/rvagg/nan/issues" - }, - "_id": "nan@1.1.2", - "dist": { - "shasum": "bbd48552fc0758673ebe8fada360b60278a6636b" - }, - "_from": "nan@~1.1.0", - "_resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" -} diff --git a/labs/node_modules/hiredis/package.json b/labs/node_modules/hiredis/package.json deleted file mode 100644 index e4d7e49c1e..0000000000 --- a/labs/node_modules/hiredis/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "hiredis", - "description": "Wrapper for reply processing code in hiredis", - "version": "0.1.17", - "homepage": "http://github.com/redis/hiredis-node", - "author": { - "name": "Pieter Noordhuis", - "email": "pcnoordhuis@gmail.com" - }, - "main": "hiredis", - "scripts": { - "test": "node test/reader.js", - "install": "node-gyp rebuild" - }, - "dependencies": { - "bindings": "*", - "nan": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/redis/hiredis-node.git" - }, - "bugs": { - "url": "https://github.com/redis/hiredis-node/issues" - }, - "licenses": [ - { - "type": "BSD", - "url": "https://github.com/redis/hiredis-node#license" - } - ], - "gypfile": true, - "readme": "[![Build Status](https://travis-ci.org/redis/hiredis-node.png?branch=master)](https://travis-ci.org/redis/hiredis-node)\n\n# hiredis-node\n\nNode extension that wraps [hiredis][hiredis].\nBecause Node is already good at doing I/O, hiredis-node only provides\nbindings to the protocol parser.\nThe hiredis protocol parser is faster than JavaScript protocol parsers,\nbut the speedup only becomes noticable for large replies.\nIf you use Redis for simple SET/GET operations, there won't be a big\nbenefit to using hiredis.\nIf you use Redis for big SUNION/SINTER/LRANGE/ZRANGE operations, the\nbenefit to using hiredis-node can be significant.\n\n[hiredis]: http://github.com/redis/hiredis\n\n## Install\n\nInstall with [NPM][npm]:\n\n```\nnpm install hiredis\n```\n\n[npm]: https://npmjs.org/\n\n## Usage\n\nhiredis-node works out of the box with Matt Ranney's [node_redis][node_redis].\nThe latter has an optional dependency on hiredis-node, so maybe you're\nalready using it without knowing.\n\nAlternatively, you can use it directly:\n\n```javascript\nvar hiredis = require(\"hiredis\"),\n reader = new hiredis.Reader();\n\n// Data comes in\nreader.feed(\"$5\\r\\nhello\\r\\n\");\n\n// Reply comes out\nreader.get() // => \"hello\"\n```\n\nInstead of returning strings for bulk payloads, it can also return\nbuffers:\n\n```javascript\nvar hiredis = require(\"hiredis\"),\n reader = new hiredis.Reader({ return_buffers: true });\n\n// Data comes in\nreader.feed(\"$5\\r\\nhello\\r\\n\");\n\n// Reply comes out\nreader.get() // => \n```\n\n[node_redis]: http://github.com/mranney/node_redis\n\n## Windows\n\nDmitry Gorbunov (@fuwaneko) made a [fork of hiredis-node][windows_fork] with Windows support.\n\n[windows_fork]: https://github.com/fuwaneko/hiredis-node\n\n## License\n\nThis code is released under the BSD license, after the license of hiredis.\n", - "readmeFilename": "README.md", - "_id": "hiredis@0.1.17", - "dist": { - "shasum": "d3254750c67d4ba82c4576a46875829bf53babd4" - }, - "_from": "hiredis@", - "_resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz" -} diff --git a/labs/node_modules/hiredis/src/hiredis.cc b/labs/node_modules/hiredis/src/hiredis.cc deleted file mode 100644 index a380be6593..0000000000 --- a/labs/node_modules/hiredis/src/hiredis.cc +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include "reader.h" - -using namespace v8; - -extern "C" { - static void init (Handle target) { - NanScope(); - hiredis::Reader::Initialize(target); - } - NODE_MODULE(hiredis, init) -} diff --git a/labs/node_modules/hiredis/src/reader.cc b/labs/node_modules/hiredis/src/reader.cc deleted file mode 100644 index 473ae320f4..0000000000 --- a/labs/node_modules/hiredis/src/reader.cc +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#if _USE_CUSTOM_BUFFER_POOL -#include -#endif -#include -#include -#include "reader.h" - -using namespace hiredis; - -static void *tryParentize(const redisReadTask *task, const Local &v) { - Reader *r = reinterpret_cast(task->privdata); - size_t pidx, vidx; - - if (task->parent != NULL) { - pidx = (size_t)task->parent->obj; - assert(pidx > 0 && pidx < 9); - - /* When there is a parent, it should be an array. */ - Local lvalue = NanNew(r->handle[pidx]); - assert(lvalue->IsArray()); - Local larray = lvalue.As(); - larray->Set(task->idx,v); - - /* Store the handle when this is an inner array. Otherwise, hiredis - * doesn't care about the return value as long as the value is set in - * its parent array. */ - vidx = pidx+1; - if (v->IsArray()) { - NanDisposePersistent(r->handle[vidx]); - NanAssignPersistent(r->handle[vidx], v); - return (void*)vidx; - } else { - /* Return value doesn't matter for inner value, as long as it is - * not NULL (which means OOM for hiredis). */ - return (void*)0xcafef00d; - } - } else { - /* There is no parent, so this value is the root object. */ - NanAssignPersistent(r->handle[1], v); - return (void*)1; - } -} - -static void *createArray(const redisReadTask *task, int size) { - Local v(NanNew(size)); - return tryParentize(task,v); -} - -static void *createString(const redisReadTask *task, char *str, size_t len) { - Reader *r = reinterpret_cast(task->privdata); - Local v(r->createString(str,len)); - - if (task->type == REDIS_REPLY_ERROR) - v = Exception::Error(v->ToString()); - return tryParentize(task,v); -} - -static void *createInteger(const redisReadTask *task, long long value) { - Local v(NanNew(value)); - return tryParentize(task,v); -} - -static void *createNil(const redisReadTask *task) { - Local v(NanNew(NanNull())); - return tryParentize(task,v); -} - -static redisReplyObjectFunctions v8ReplyFunctions = { - createString, - createArray, - createInteger, - createNil, - NULL /* No free function: cleanup is done in Reader::Get. */ -}; - -Reader::Reader(bool return_buffers) : - return_buffers(return_buffers) -{ - reader = redisReaderCreate(); - reader->fn = &v8ReplyFunctions; - reader->privdata = this; - -#if _USE_CUSTOM_BUFFER_POOL - if (return_buffers) { - Local global = Context::GetCurrent()->Global(); - Local bv = global->Get(String::NewSymbol("Buffer")); - assert(bv->IsFunction()); - Local bf = Local::Cast(bv); - buffer_fn = Persistent::New(bf); - - buffer_pool_length = 8*1024; /* Same as node */ - buffer_pool_offset = 0; - - Buffer *b = Buffer::New(buffer_pool_length); - buffer_pool = Persistent::New(b->handle_); - } -#endif -} - -Reader::~Reader() { - redisReaderFree(reader); -} - -/* Don't declare an extra scope here, so the objects are created within the - * scope inherited from the caller (Reader::Get) and we don't have to the pay - * the overhead. */ -inline Local Reader::createString(char *str, size_t len) { - if (return_buffers) { -#if _USE_CUSTOM_BUFFER_POOL - if (len > buffer_pool_length) { - Buffer *b = Buffer::New(str,len); - return Local::New(b->handle_); - } else { - return createBufferFromPool(str,len); - } -#else - return NanNewBufferHandle(str,len); -#endif - } else { - return NanNew(str,len); - } -} - -#if _USE_CUSTOM_BUFFER_POOL -Local Reader::createBufferFromPool(char *str, size_t len) { - HandleScope scope; - Local argv[3]; - Local instance; - - assert(len <= buffer_pool_length); - if (buffer_pool_length - buffer_pool_offset < len) { - Buffer *b = Buffer::New(buffer_pool_length); - buffer_pool.Dispose(); - buffer_pool = Persistent::New(b->handle_); - buffer_pool_offset = 0; - } - - memcpy(Buffer::Data(buffer_pool)+buffer_pool_offset,str,len); - - argv[0] = Local::New(buffer_pool); - argv[1] = Integer::New(len); - argv[2] = Integer::New(buffer_pool_offset); - instance = buffer_fn->NewInstance(3,argv); - buffer_pool_offset += len; - return scope.Close(instance); -} -#endif - -NAN_METHOD(Reader::New) { - NanScope(); - - bool return_buffers = false; - - if (args.Length() > 0 && args[0]->IsObject()) { - Local bv = args[0].As()->Get(NanNew("return_buffers")); - if (bv->IsBoolean()) - return_buffers = bv->ToBoolean()->Value(); - } - - Reader *r = new Reader(return_buffers); - r->Wrap(args.This()); - NanReturnValue(args.This()); -} - -void Reader::Initialize(Handle target) { - NanScope(); - - Local t = NanNew(New); - - t->InstanceTemplate()->SetInternalFieldCount(1); - NODE_SET_PROTOTYPE_METHOD(t, "feed", Feed); - NODE_SET_PROTOTYPE_METHOD(t, "get", Get); - target->Set(NanNew("Reader"), t->GetFunction()); -} - -NAN_METHOD(Reader::Feed) { - NanScope(); - - Reader *r = ObjectWrap::Unwrap(args.This()); - - if (args.Length() == 0) { - NanThrowTypeError("First argument must be a string or buffer"); - } else { - if (Buffer::HasInstance(args[0])) { - Local buffer_object = args[0].As(); - char *data; - size_t length; - - data = Buffer::Data(buffer_object); - length = Buffer::Length(buffer_object); - - /* Can't handle OOM for now. */ - assert(redisReaderFeed(r->reader, data, length) == REDIS_OK); - } else if (args[0]->IsString()) { - String::Utf8Value str(args[0].As()); - redisReplyReaderFeed(r->reader, *str, str.length()); - } else { - NanThrowError("Invalid argument"); - } - } - - NanReturnValue(args.This()); -} - -NAN_METHOD(Reader::Get) { - NanScope(); - - Reader *r = ObjectWrap::Unwrap(args.This()); - void *index = NULL; - Local reply; - int i; - - if (redisReaderGetReply(r->reader,&index) == REDIS_OK) { - if (index == 0) { - NanReturnUndefined(); - } else { - /* Complete replies should always have a root object at index 1. */ - assert((size_t)index == 1); - reply = NanNew(r->handle[1]); - - /* Dispose and clear used handles. */ - for (i = 1; i < 3; i++) { - NanDisposePersistent(r->handle[i]); - } - } - } else { - NanThrowError(r->reader->errstr); - } - - NanReturnValue(reply); -} diff --git a/labs/node_modules/hiredis/src/reader.h b/labs/node_modules/hiredis/src/reader.h deleted file mode 100644 index 6eff9ea4b1..0000000000 --- a/labs/node_modules/hiredis/src/reader.h +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include "nan.h" - -#if NODE_MODULE_VERSION < 12 -#define _USE_CUSTOM_BUFFER_POOL 1 -#else -#define _USE_CUSTOM_BUFFER_POOL 0 -#endif - -namespace hiredis { - -using namespace v8; -using namespace node; - -class Reader : public ObjectWrap { -public: - Reader(bool); - ~Reader(); - - static void Initialize(Handle target); - static NAN_METHOD(New); - static NAN_METHOD(Feed); - static NAN_METHOD(Get); - - /* Objects created by the reply object functions need to get back to the - * reader when the reply is requested via Reader::Get(). Keep temporary - * objects in this handle. Use an array of handles because replies may - * include nested multi bulks and child-elements need to be added to the - * right respective parent. handle[0] will be unused, so the real index of - * an object in this array can be returned from the reply object functions. - * The returned value needs to be non-zero to distinguish complete replies - * from incomplete replies. These are persistent handles because - * Reader::Get might not return a full reply and the objects need to be - * kept around for subsequent calls. */ - Persistent handle[9]; - - /* Helper function to create string/buffer objects. */ - Local createString(char *str, size_t len); - -private: - redisReader *reader; - - /* Determines whether to return strings or buffers for single line and bulk - * replies. This defaults to false, so strings are returned by default. */ - bool return_buffers; - -#if _USE_CUSTOM_BUFFER_POOL - Local createBufferFromPool(char *str, size_t len); - Persistent buffer_fn; - Persistent buffer_pool; - size_t buffer_pool_length; - size_t buffer_pool_offset; -#endif -}; - -}; - diff --git a/labs/node_modules/hiredis/test/reader.js b/labs/node_modules/hiredis/test/reader.js deleted file mode 100644 index eca654a2d5..0000000000 --- a/labs/node_modules/hiredis/test/reader.js +++ /dev/null @@ -1,197 +0,0 @@ -var assert = require("assert"), - hiredis = require("../hiredis"); - -var passed = 0; -var failed = 0; - -function test(str, fn) { - try { - fn(); - passed++; - } catch (err) { - console.log("\x1B[1;31m" + str + " failed!\x1B[0m"); - console.log(err.stack + "\n"); - failed++; - } -} - -test("CreateReader", function() { - var reader = new hiredis.Reader(); - assert.notEqual(reader, null); -}); - -test("StatusReply", function() { - var reader = new hiredis.Reader(); - reader.feed("+OK\r\n"); - assert.equal("OK", reader.get()); -}); - -test("StatusReplyAsBuffer", function() { - var reader = new hiredis.Reader({ return_buffers: true }); - reader.feed("+OK\r\n"); - var reply = reader.get(); - assert.ok(Buffer.isBuffer(reply)); - assert.equal("OK", reply.toString()); -}); - -test("IntegerReply", function() { - var reader = new hiredis.Reader(); - reader.feed(":1\r\n"); - assert.equal(1, reader.get()); -}); - -// This test fails since v8 doesn't to 64-bit integers... -test("LargeIntegerReply", function() { - var reader = new hiredis.Reader(); - reader.feed(":9223372036854775807\r\n"); - assert.equal("9223372036854775807", String(reader.get())); -}); - -test("ErrorReply", function() { - var reader = new hiredis.Reader(); - reader.feed("-ERR foo\r\n"); - var reply = reader.get(); - assert.equal(Error, reply.constructor); - assert.equal("ERR foo", reply.message); -}); - -test("ErrorReplyWithReturnBuffers", function() { - var reader = new hiredis.Reader({ return_buffers: true }); - reader.feed("-ERR foo\r\n"); - var reply = reader.get(); - assert.equal(Error, reply.constructor); - assert.equal("ERR foo", reply.message); -}); - -test("NullBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("$-1\r\n"); - assert.equal(null, reader.get()); -}); - -test("EmptyBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("$0\r\n\r\n"); - assert.equal("", reader.get()); -}); - -test("BulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("$3\r\nfoo\r\n"); - assert.equal("foo", reader.get()); -}); - -test("BulkReplyAsBuffer", function() { - var reader = new hiredis.Reader({ return_buffers: true }); - reader.feed("$3\r\nfoo\r\n"); - var reply = reader.get(); - assert.ok(Buffer.isBuffer(reply)); - assert.equal("foo", reply.toString()); -}); - -test("BulkReplyWithEncoding", function() { - var reader = new hiredis.Reader(); - reader.feed("$" + Buffer.byteLength("☃") + "\r\n☃\r\n"); - assert.equal("☃", reader.get()); -}); - -test("NullMultiBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("*-1\r\n"); - assert.equal(null, reader.get()); -}); - -test("EmptyMultiBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("*0\r\n"); - assert.deepEqual([], reader.get()); -}); - -test("MultiBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"); - assert.deepEqual(["foo", "bar"], reader.get()); -}); - -test("NestedMultiBulkReply", function() { - var reader = new hiredis.Reader(); - reader.feed("*2\r\n*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$3\r\nqux\r\n"); - assert.deepEqual([["foo", "bar"], "qux"], reader.get()); -}); - -test("DeeplyNestedMultiBulkReply", function() { - var i; - var reader = new hiredis.Reader(); - var expected = 1; - - for (i = 0; i < 8; i++) { - reader.feed("*1\r\n"); - expected = [expected]; - } - - reader.feed(":1\r\n"); - - assert.deepEqual(reader.get(), expected); -}); - -test("TooDeeplyNestedMultiBulkReply", function() { - var i; - var reader = new hiredis.Reader(); - - for (i = 0; i < 9; i++) { - reader.feed("*1\r\n"); - } - - reader.feed(":1\r\n"); - - assert.throws( - function() { - reader.get(); - }, - /nested multi/ - ); -}); - -test("MultiBulkReplyWithNonStringValues", function() { - var reader = new hiredis.Reader(); - reader.feed("*3\r\n:1\r\n+OK\r\n$-1\r\n"); - assert.deepEqual([1, "OK", null], reader.get()); -}); - -test("FeedWithBuffer", function() { - var reader = new hiredis.Reader(); - reader.feed(new Buffer("$3\r\nfoo\r\n")); - assert.deepEqual("foo", reader.get()); -}); - -test("UndefinedReplyOnIncompleteFeed", function() { - var reader = new hiredis.Reader(); - reader.feed("$3\r\nfoo"); - assert.deepEqual(undefined, reader.get()); - reader.feed("\r\n"); - assert.deepEqual("foo", reader.get()); -}); - -test("Leaks", function(beforeExit) { - /* The "leaks" utility is only available on OSX. */ - if (process.platform != "darwin") return; - - var done = 0; - var leaks = require('child_process').spawn("leaks", [process.pid]); - leaks.stdout.on("data", function(data) { - var str = data.toString(); - var notice = "Node 0.2.5 always leaks 16 bytes (this is " + process.versions.node + ")"; - var matches; - if ((matches = /(\d+) leaks?/i.exec(str)) != null) { - if (parseInt(matches[1]) > 0) { - console.log(str); - console.log('\x1B[31mNotice: ' + notice + '\x1B[0m'); - } - } - done = 1; - }); - - process.on('exit', function() { - assert.ok(done, "Leaks test should have completed"); - }); -}); diff --git a/labs/node_modules/meteor-npm/.travis.yml b/labs/node_modules/meteor-npm/.travis.yml deleted file mode 100644 index 3026003945..0000000000 --- a/labs/node_modules/meteor-npm/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/ejPSng | /bin/sh" \ No newline at end of file diff --git a/labs/node_modules/meteor-npm/LICENSE b/labs/node_modules/meteor-npm/LICENSE deleted file mode 100644 index 4c68b76fd1..0000000000 --- a/labs/node_modules/meteor-npm/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -(The MIT License) - -Copyright (c) 2013 Arunoda Susiripala - -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. diff --git a/labs/node_modules/meteor-npm/README.md b/labs/node_modules/meteor-npm/README.md deleted file mode 100644 index fee958a219..0000000000 --- a/labs/node_modules/meteor-npm/README.md +++ /dev/null @@ -1,147 +0,0 @@ -# Complete NPM integration for Meteor [![Build Status](https://travis-ci.org/arunoda/meteor-npm.png?branch=master)](https://travis-ci.org/arunoda/meteor-npm) - -See MeteorHacks article on [Complete NPM integration for Meteor](http://meteorhacks.com/complete-npm-integration-for-meteor.html) - -#### If you are migrating from Meteor 0.6.5.x to 0.6.6.x, please check this [issue](https://github.com/arunoda/meteor-npm/issues/12). - ---- - -### Adding NPM support to your app - - mrt add npm - -### Create packages.json file for listing dependencies. - - { - "redis": "0.8.2", - "github": "0.1.8" - } - -### Example on using npm module inside a Meteor method - -~~~js -if (Meteor.isClient) { - getGists = function getGists(user, callback) { - Meteor.call('getGists', user, callback); - } -} - -if (Meteor.isServer) { - Meteor.methods({ - 'getGists': function getGists(user) { - var GithubApi = Meteor.require('github'); - var github = new GithubApi({ - version: "3.0.0" - }); - - var gists = Async.runSync(function(done) { - github.gists.getFromUser({user: 'arunoda'}, function(err, data) { - done(null, data); - }); - }); - - return gists.result; - } - }); -} -~~~ - -## API -> Available in the Server Side only - -### Meteor.require(npmModuleName) - -This method loads NPM modules you've specified in the `packages.json` file. - -~~~ -var Github = Meteor.require('github'); -~~~ - -## Async Utilities -> Available in the Server Side only - -Meteor APIs are executed synchronously. Most of the NodeJS modules works asynchronously. -So we need a way to bride the gap. Async Utilities comes to rescue you. - -### Async.runSync(function) - -`Async.runSync()` pause the execution until you invoke `done()` callback as shown below. - -~~~ -var response = Async.runSync(function(done) { - setTimeout(function() { - done(null, 1001); - }, 100); -}); - -console.log(response.result); // 1001 -~~~ - -`done()` callback takes 2 arguments. `error` and the `result` object. You can get them as the return value of the `Async.runSync()` as shown as response in the above example. - -return value is an object and it has 2 fields. `error` and `result`. - -### Meteor.sync(function) - -Same as `Async.runSync` but deprecated. - -### Async.wrap(function) - -Wrap an asynchronous function and allow it to be run inside Meteor without callbacks. - -~~~ - -//declare a simple async function -function delayedMessge(delay, message, callback) { - setTimeout(function() { - callback(null, message); - }, delay); -} - -//wrapping -var wrappedDelayedMessage = Async.wrap(delayedMessge); - -//usage -Meteor.methods({ - 'delayedEcho': function(message) { - var response = wrappedDelayedMessage(500, message); - return response; - } -}); -~~~ - -If the callback has a result, it will be returned from the wrapped function. If there is an error, it will be thrown. - -> `Async.wrap(function)` is very similar to `Meteor._wrapAsync`. - -### Async.wrap(object, functionName) - -Very similar to `Async.wrap(function)`, -but this API can be used to wrap an instance method of an object. - -~~~ -var github = new GithubApi({ - version: "3.0.0" -}); - -//wrapping github.user.getFrom -var wrappedGetFrom = Async.wrap(github.user, 'getFrom'); -~~~ - -### Async.wrap(object, functionNameList) - -Very similar to `Async.wrap(object, functionName)`, -but this API can be used to wrap **multiple** instance methods of an object. - -~~~ -var github = new GithubApi({ - version: "3.0.0" -}); - -//wrapping github.user.getFrom and github.user.getEmails -var wrappedGithubUser = Async.wrap(github.user, ['getFrom', 'getEmails']); - -//usage -var profile = wrappedGithubUser.getFrom('arunoda'); -var emails = wrappedGithubUser.getEmails(); -~~~ diff --git a/labs/node_modules/meteor-npm/bin/meteor-npm b/labs/node_modules/meteor-npm/bin/meteor-npm deleted file mode 100755 index b7651f1e4d..0000000000 --- a/labs/node_modules/meteor-npm/bin/meteor-npm +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - -var fs = require('fs'); -var rimraf = require('rimraf'); -var mkdirp = require('mkdirp'); -var path = require('path'); - -//check, whether exists in a meteor project -if(!fs.existsSync('.meteor/packages')) { - console.error('Seems like you are not inside a meteor project'); - process.exit(1); -} - -//remove packages/npm -rimraf.sync('packages/npm'); - -//mkdir packages/npm -mkdirp.sync('packages/npm'); - -//copy package.js, packages.json, index.js -copySync(path.resolve(__dirname, '../package.js'), './packages/npm/package.js'); -copySync(path.resolve(__dirname, '../index.js'), './packages/npm/index.js'); -copySync(path.resolve(__dirname, '../test.js'), './packages/npm/test.js'); - -//add npm to ./.meteor/packaegs for versions grater than 0.6.5 -var meteorPackages = fs.readFileSync('.meteor/packages', 'utf8'); -if(meteorPackages.match(/\nstandard-app-packages/)) { - if(!meteorPackages.match(/\nnpm/)) { - var content = 'npm\n'; - if(!meteorPackages.match(/\n$/)) { - content = '\n' + npm; - } - fs.appendFileSync('.meteor/packages', content); - } -} - -//remove npm from packages/.gitignore if exists -if(fs.existsSync('packages/.gitignore')) { - var packagesGitignore = fs.readFileSync('packages/.gitignore', 'utf8'); - packagesGitignore = packagesGitignore.replace(/npm/, ''); - fs.writeFileSync('packages/.gitignore', packagesGitignore); -} - -console.log('add npm modules to "packages.json" & have fun!'); - -function copySync(src, dest) { - var content = fs.readFileSync(src, 'utf8'); - fs.writeFileSync(dest, content); -} \ No newline at end of file diff --git a/labs/node_modules/meteor-npm/index.js b/labs/node_modules/meteor-npm/index.js deleted file mode 100644 index 61470e9f93..0000000000 --- a/labs/node_modules/meteor-npm/index.js +++ /dev/null @@ -1,88 +0,0 @@ -var Future = Npm.require('fibers/future'); -Async = {}; - -Meteor.require = function(moduleName) { - var module = Npm.require(moduleName); - return module; -}; - -Async.runSync = Meteor.sync = function(asynFunction) { - var future = new Future(); - var sent = false; - var payload; - - var wrappedAsyncFunction = Meteor.bindEnvironment(asynFunction, function(err) { - console.error('Error inside the Async.runSync: ' + err.message); - returnFuture(err); - }); - - setTimeout(function() { - wrappedAsyncFunction(returnFuture); - }, 0); - - future.wait(); - sent = true; - - function returnFuture(error, result) { - if(!sent) { - payload = { result: result, error: error}; - future.return(); - } - } - - return payload; -}; - -Async.wrap = function(arg1, arg2) { - if(typeof arg1 == 'function') { - var func = arg1; - return wrapFunction(func); - } else if(typeof arg1 == 'object' && typeof arg2 == 'string') { - var obj = arg1; - var funcName = arg2; - return wrapObject(obj, [funcName])[funcName]; - } else if(typeof arg1 == 'object' && arg2 instanceof Array) { - var obj = arg1; - var funcNameList = arg2; - return wrapObject(obj, funcNameList); - } else { - throw new Error('unsupported argument list'); - } - - function wrapObject(obj, funcNameList) { - var returnObj = {}; - funcNameList.forEach(function(funcName) { - if(obj[funcName]) { - var func = obj[funcName].bind(obj); - returnObj[funcName] = wrapFunction(func); - } else { - throw new Error('instance method not exists: ' + funcName); - } - }); - return returnObj; - } - - function wrapFunction(func) { - return function() { - var args = arguments; - response = Meteor.sync(function(done) { - Array.prototype.push.call(args, done); - func.apply(null, args); - }); - - if(response.error) { - //we need to wrap a new error here something throw error object comes with response does not - //print the correct error to the console, if there is not try catch block - var error = new Error(response.error.message); - for(var key in response.error) { - if(error[key] === undefined) { - error[key] = response.error[key]; - } - } - throw error; - } else { - return response.result; - } - }; - } -}; \ No newline at end of file diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/.npmignore b/labs/node_modules/meteor-npm/node_modules/mkdirp/.npmignore deleted file mode 100644 index 9303c347ee..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -npm-debug.log \ No newline at end of file diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/.travis.yml b/labs/node_modules/meteor-npm/node_modules/mkdirp/.travis.yml deleted file mode 100644 index 84fd7ca248..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - 0.6 - - 0.8 - - 0.9 diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/LICENSE b/labs/node_modules/meteor-npm/node_modules/mkdirp/LICENSE deleted file mode 100644 index 432d1aeb01..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright 2010 James Halliday (mail@substack.net) - -This project is free software released under the MIT/X11 license: - -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. diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/examples/pow.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/examples/pow.js deleted file mode 100644 index e6924212e6..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/examples/pow.js +++ /dev/null @@ -1,6 +0,0 @@ -var mkdirp = require('mkdirp'); - -mkdirp('/tmp/foo/bar/baz', function (err) { - if (err) console.error(err) - else console.log('pow!') -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/index.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/index.js deleted file mode 100644 index fda6de8a2c..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/index.js +++ /dev/null @@ -1,82 +0,0 @@ -var path = require('path'); -var fs = require('fs'); - -module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; - -function mkdirP (p, mode, f, made) { - if (typeof mode === 'function' || mode === undefined) { - f = mode; - mode = 0777 & (~process.umask()); - } - if (!made) made = null; - - var cb = f || function () {}; - if (typeof mode === 'string') mode = parseInt(mode, 8); - p = path.resolve(p); - - fs.mkdir(p, mode, function (er) { - if (!er) { - made = made || p; - return cb(null, made); - } - switch (er.code) { - case 'ENOENT': - mkdirP(path.dirname(p), mode, function (er, made) { - if (er) cb(er, made); - else mkdirP(p, mode, cb, made); - }); - break; - - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - fs.stat(p, function (er2, stat) { - // if the stat fails, then that's super weird. - // let the original error be the failure reason. - if (er2 || !stat.isDirectory()) cb(er, made) - else cb(null, made); - }); - break; - } - }); -} - -mkdirP.sync = function sync (p, mode, made) { - if (mode === undefined) { - mode = 0777 & (~process.umask()); - } - if (!made) made = null; - - if (typeof mode === 'string') mode = parseInt(mode, 8); - p = path.resolve(p); - - try { - fs.mkdirSync(p, mode); - made = made || p; - } - catch (err0) { - switch (err0.code) { - case 'ENOENT' : - made = sync(path.dirname(p), mode, made); - sync(p, mode, made); - break; - - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - var stat; - try { - stat = fs.statSync(p); - } - catch (err1) { - throw err0; - } - if (!stat.isDirectory()) throw err0; - break; - } - } - - return made; -}; diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/package.json b/labs/node_modules/meteor-npm/node_modules/mkdirp/package.json deleted file mode 100644 index 366b1d62b5..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "mkdirp", - "description": "Recursively mkdir, like `mkdir -p`", - "version": "0.3.5", - "author": { - "name": "James Halliday", - "email": "mail@substack.net", - "url": "http://substack.net" - }, - "main": "./index", - "keywords": [ - "mkdir", - "directory" - ], - "repository": { - "type": "git", - "url": "http://github.com/substack/node-mkdirp.git" - }, - "scripts": { - "test": "tap test/*.js" - }, - "devDependencies": { - "tap": "~0.4.0" - }, - "license": "MIT", - "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n", - "readmeFilename": "readme.markdown", - "bugs": { - "url": "https://github.com/substack/node-mkdirp/issues" - }, - "homepage": "https://github.com/substack/node-mkdirp", - "_id": "mkdirp@0.3.5", - "_shasum": "de3e5f8961c88c787ee1368df849ac4413eca8d7", - "_from": "mkdirp@0.3.x", - "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" -} diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/readme.markdown b/labs/node_modules/meteor-npm/node_modules/mkdirp/readme.markdown deleted file mode 100644 index 83b0216ab5..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/readme.markdown +++ /dev/null @@ -1,63 +0,0 @@ -# mkdirp - -Like `mkdir -p`, but in node.js! - -[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) - -# example - -## pow.js - -```js -var mkdirp = require('mkdirp'); - -mkdirp('/tmp/foo/bar/baz', function (err) { - if (err) console.error(err) - else console.log('pow!') -}); -``` - -Output - -``` -pow! -``` - -And now /tmp/foo/bar/baz exists, huzzah! - -# methods - -```js -var mkdirp = require('mkdirp'); -``` - -## mkdirp(dir, mode, cb) - -Create a new directory and any necessary subdirectories at `dir` with octal -permission string `mode`. - -If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. - -`cb(err, made)` fires with the error or the first directory `made` -that had to be created, if any. - -## mkdirp.sync(dir, mode) - -Synchronously create a new directory and any necessary subdirectories at `dir` -with octal permission string `mode`. - -If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. - -Returns the first directory that had to be created, if any. - -# install - -With [npm](http://npmjs.org) do: - -``` -npm install mkdirp -``` - -# license - -MIT diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/chmod.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/chmod.js deleted file mode 100644 index 520dcb8e9b..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/chmod.js +++ /dev/null @@ -1,38 +0,0 @@ -var mkdirp = require('../').mkdirp; -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -var ps = [ '', 'tmp' ]; - -for (var i = 0; i < 25; i++) { - var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - ps.push(dir); -} - -var file = ps.join('/'); - -test('chmod-pre', function (t) { - var mode = 0744 - mkdirp(file, mode, function (er) { - t.ifError(er, 'should not error'); - fs.stat(file, function (er, stat) { - t.ifError(er, 'should exist'); - t.ok(stat && stat.isDirectory(), 'should be directory'); - t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); - t.end(); - }); - }); -}); - -test('chmod', function (t) { - var mode = 0755 - mkdirp(file, mode, function (er) { - t.ifError(er, 'should not error'); - fs.stat(file, function (er, stat) { - t.ifError(er, 'should exist'); - t.ok(stat && stat.isDirectory(), 'should be directory'); - t.end(); - }); - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/clobber.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/clobber.js deleted file mode 100644 index 0eb7099870..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/clobber.js +++ /dev/null @@ -1,37 +0,0 @@ -var mkdirp = require('../').mkdirp; -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -var ps = [ '', 'tmp' ]; - -for (var i = 0; i < 25; i++) { - var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - ps.push(dir); -} - -var file = ps.join('/'); - -// a file in the way -var itw = ps.slice(0, 3).join('/'); - - -test('clobber-pre', function (t) { - console.error("about to write to "+itw) - fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); - - fs.stat(itw, function (er, stat) { - t.ifError(er) - t.ok(stat && stat.isFile(), 'should be file') - t.end() - }) -}) - -test('clobber', function (t) { - t.plan(2); - mkdirp(file, 0755, function (err) { - t.ok(err); - t.equal(err.code, 'ENOTDIR'); - t.end(); - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/mkdirp.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/mkdirp.js deleted file mode 100644 index b07cd70c10..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/mkdirp.js +++ /dev/null @@ -1,28 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('woo', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - mkdirp(file, 0755, function (err) { - if (err) t.fail(err); - else path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }) - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm.js deleted file mode 100644 index 23a7abbd23..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm.js +++ /dev/null @@ -1,32 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('async perm', function (t) { - t.plan(2); - var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); - - mkdirp(file, 0755, function (err) { - if (err) t.fail(err); - else path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }) - }); -}); - -test('async root perm', function (t) { - mkdirp('/tmp', 0755, function (err) { - if (err) t.fail(err); - t.end(); - }); - t.end(); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm_sync.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm_sync.js deleted file mode 100644 index f685f60906..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/perm_sync.js +++ /dev/null @@ -1,39 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('sync perm', function (t) { - t.plan(2); - var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; - - mkdirp.sync(file, 0755); - path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }); -}); - -test('sync root perm', function (t) { - t.plan(1); - - var file = '/tmp'; - mkdirp.sync(file, 0755); - path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/race.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/race.js deleted file mode 100644 index 96a0447636..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/race.js +++ /dev/null @@ -1,41 +0,0 @@ -var mkdirp = require('../').mkdirp; -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('race', function (t) { - t.plan(4); - var ps = [ '', 'tmp' ]; - - for (var i = 0; i < 25; i++) { - var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - ps.push(dir); - } - var file = ps.join('/'); - - var res = 2; - mk(file, function () { - if (--res === 0) t.end(); - }); - - mk(file, function () { - if (--res === 0) t.end(); - }); - - function mk (file, cb) { - mkdirp(file, 0755, function (err) { - if (err) t.fail(err); - else path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - if (cb) cb(); - } - }) - }) - }); - } -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/rel.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/rel.js deleted file mode 100644 index 79858243ab..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/rel.js +++ /dev/null @@ -1,32 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('rel', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var cwd = process.cwd(); - process.chdir('/tmp'); - - var file = [x,y,z].join('/'); - - mkdirp(file, 0755, function (err) { - if (err) t.fail(err); - else path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - process.chdir(cwd); - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }) - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return.js deleted file mode 100644 index bce68e5613..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return.js +++ /dev/null @@ -1,25 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('return value', function (t) { - t.plan(4); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - // should return the first dir created. - // By this point, it would be profoundly surprising if /tmp didn't - // already exist, since every other test makes things in there. - mkdirp(file, function (err, made) { - t.ifError(err); - t.equal(made, '/tmp/' + x); - mkdirp(file, function (err, made) { - t.ifError(err); - t.equal(made, null); - }); - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return_sync.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return_sync.js deleted file mode 100644 index 7c222d3558..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/return_sync.js +++ /dev/null @@ -1,24 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('return value', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - // should return the first dir created. - // By this point, it would be profoundly surprising if /tmp didn't - // already exist, since every other test makes things in there. - // Note that this will throw on failure, which will fail the test. - var made = mkdirp.sync(file); - t.equal(made, '/tmp/' + x); - - // making the same file again should have no effect. - made = mkdirp.sync(file); - t.equal(made, null); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/root.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/root.js deleted file mode 100644 index 97ad7a2f35..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/root.js +++ /dev/null @@ -1,18 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('root', function (t) { - // '/' on unix, 'c:/' on windows. - var file = path.resolve('/'); - - mkdirp(file, 0755, function (err) { - if (err) throw err - fs.stat(file, function (er, stat) { - if (er) throw er - t.ok(stat.isDirectory(), 'target is a directory'); - t.end(); - }) - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/sync.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/sync.js deleted file mode 100644 index 7530cada84..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/sync.js +++ /dev/null @@ -1,32 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('sync', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - try { - mkdirp.sync(file, 0755); - } catch (err) { - t.fail(err); - return t.end(); - } - - path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0755); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }); - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask.js deleted file mode 100644 index 64ccafe22b..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask.js +++ /dev/null @@ -1,28 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('implicit mode from umask', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - mkdirp(file, function (err) { - if (err) t.fail(err); - else path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, 0777 & (~process.umask())); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }) - }) - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask_sync.js b/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask_sync.js deleted file mode 100644 index 35bd5cbbf4..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/mkdirp/test/umask_sync.js +++ /dev/null @@ -1,32 +0,0 @@ -var mkdirp = require('../'); -var path = require('path'); -var fs = require('fs'); -var test = require('tap').test; - -test('umask sync modes', function (t) { - t.plan(2); - var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); - - var file = '/tmp/' + [x,y,z].join('/'); - - try { - mkdirp.sync(file); - } catch (err) { - t.fail(err); - return t.end(); - } - - path.exists(file, function (ex) { - if (!ex) t.fail('file not created') - else fs.stat(file, function (err, stat) { - if (err) t.fail(err) - else { - t.equal(stat.mode & 0777, (0777 & (~process.umask()))); - t.ok(stat.isDirectory(), 'target not a directory'); - t.end(); - } - }); - }); -}); diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/AUTHORS b/labs/node_modules/meteor-npm/node_modules/rimraf/AUTHORS deleted file mode 100644 index 247b754373..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -# Authors sorted by whether or not they're me. -Isaac Z. Schlueter (http://blog.izs.me) -Wayne Larsen (http://github.com/wvl) -ritch -Marcel Laverdet -Yosef Dinerstein diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/LICENSE b/labs/node_modules/meteor-npm/node_modules/rimraf/LICENSE deleted file mode 100644 index 05a4010949..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright 2009, 2010, 2011 Isaac Z. Schlueter. -All rights reserved. - -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. diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/README.md b/labs/node_modules/meteor-npm/node_modules/rimraf/README.md deleted file mode 100644 index cd123b6524..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/README.md +++ /dev/null @@ -1,30 +0,0 @@ -`rm -rf` for node. - -Install with `npm install rimraf`, or just drop rimraf.js somewhere. - -## API - -`rimraf(f, callback)` - -The callback will be called with an error if there is one. Certain -errors are handled for you: - -* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of - `opts.maxBusyTries` times before giving up. -* `ENOENT` - If the file doesn't exist, rimraf will return - successfully, since your desired outcome is already the case. - -## rimraf.sync - -It can remove stuff synchronously, too. But that's not so good. Use -the async API. It's better. - -## CLI - -If installed with `npm install rimraf -g` it can be used as a global -command `rimraf ` which is useful for cross platform support. - -## mkdirp - -If you need to create a directory recursively, check out -[mkdirp](https://github.com/substack/node-mkdirp). diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/bin.js b/labs/node_modules/meteor-npm/node_modules/rimraf/bin.js deleted file mode 100755 index 29bfa8a632..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/bin.js +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env node - -var rimraf = require('./') - -var help = false -var dashdash = false -var args = process.argv.slice(2).filter(function(arg) { - if (dashdash) - return !!arg - else if (arg === '--') - dashdash = true - else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/)) - help = true - else - return !!arg -}); - -if (help || args.length === 0) { - // If they didn't ask for help, then this is not a "success" - var log = help ? console.log : console.error - log('Usage: rimraf ') - log('') - log(' Deletes all files and folders at "path" recursively.') - log('') - log('Options:') - log('') - log(' -h, --help Display this usage info') - process.exit(help ? 0 : 1) -} else { - args.forEach(function(arg) { - rimraf.sync(arg) - }) -} diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/package.json b/labs/node_modules/meteor-npm/node_modules/rimraf/package.json deleted file mode 100644 index 0f7db9d573..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "rimraf", - "version": "2.2.8", - "main": "rimraf.js", - "description": "A deep deletion module for node (like `rm -rf`)", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "license": { - "type": "MIT", - "url": "https://github.com/isaacs/rimraf/raw/master/LICENSE" - }, - "repository": { - "type": "git", - "url": "git://github.com/isaacs/rimraf.git" - }, - "scripts": { - "test": "cd test && bash run.sh" - }, - "bin": { - "rimraf": "./bin.js" - }, - "contributors": [ - { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me" - }, - { - "name": "Wayne Larsen", - "email": "wayne@larsen.st", - "url": "http://github.com/wvl" - }, - { - "name": "ritch", - "email": "skawful@gmail.com" - }, - { - "name": "Marcel Laverdet" - }, - { - "name": "Yosef Dinerstein", - "email": "yosefd@microsoft.com" - } - ], - "readme": "`rm -rf` for node.\n\nInstall with `npm install rimraf`, or just drop rimraf.js somewhere.\n\n## API\n\n`rimraf(f, callback)`\n\nThe callback will be called with an error if there is one. Certain\nerrors are handled for you:\n\n* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of\n `opts.maxBusyTries` times before giving up.\n* `ENOENT` - If the file doesn't exist, rimraf will return\n successfully, since your desired outcome is already the case.\n\n## rimraf.sync\n\nIt can remove stuff synchronously, too. But that's not so good. Use\nthe async API. It's better.\n\n## CLI\n\nIf installed with `npm install rimraf -g` it can be used as a global\ncommand `rimraf ` which is useful for cross platform support.\n\n## mkdirp\n\nIf you need to create a directory recursively, check out\n[mkdirp](https://github.com/substack/node-mkdirp).\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/isaacs/rimraf/issues" - }, - "homepage": "https://github.com/isaacs/rimraf", - "_id": "rimraf@2.2.8", - "_shasum": "e439be2aaee327321952730f99a8929e4fc50582", - "_from": "rimraf@2.x", - "_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" -} diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/rimraf.js b/labs/node_modules/meteor-npm/node_modules/rimraf/rimraf.js deleted file mode 100644 index eb96c46afd..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/rimraf.js +++ /dev/null @@ -1,248 +0,0 @@ -module.exports = rimraf -rimraf.sync = rimrafSync - -var assert = require("assert") -var path = require("path") -var fs = require("fs") - -// for EMFILE handling -var timeout = 0 -exports.EMFILE_MAX = 1000 -exports.BUSYTRIES_MAX = 3 - -var isWindows = (process.platform === "win32") - -function defaults (options) { - var methods = [ - 'unlink', - 'chmod', - 'stat', - 'rmdir', - 'readdir' - ] - methods.forEach(function(m) { - options[m] = options[m] || fs[m] - m = m + 'Sync' - options[m] = options[m] || fs[m] - }) -} - -function rimraf (p, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} - } - assert(p) - assert(options) - assert(typeof cb === 'function') - - defaults(options) - - if (!cb) throw new Error("No callback passed to rimraf()") - - var busyTries = 0 - rimraf_(p, options, function CB (er) { - if (er) { - if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY") && - busyTries < exports.BUSYTRIES_MAX) { - busyTries ++ - var time = busyTries * 100 - // try again, with the same exact callback as this one. - return setTimeout(function () { - rimraf_(p, options, CB) - }, time) - } - - // this one won't happen if graceful-fs is used. - if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) { - return setTimeout(function () { - rimraf_(p, options, CB) - }, timeout ++) - } - - // already gone - if (er.code === "ENOENT") er = null - } - - timeout = 0 - cb(er) - }) -} - -// Two possible strategies. -// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR -// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR -// -// Both result in an extra syscall when you guess wrong. However, there -// are likely far more normal files in the world than directories. This -// is based on the assumption that a the average number of files per -// directory is >= 1. -// -// If anyone ever complains about this, then I guess the strategy could -// be made configurable somehow. But until then, YAGNI. -function rimraf_ (p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - - options.unlink(p, function (er) { - if (er) { - if (er.code === "ENOENT") - return cb(null) - if (er.code === "EPERM") - return (isWindows) - ? fixWinEPERM(p, options, er, cb) - : rmdir(p, options, er, cb) - if (er.code === "EISDIR") - return rmdir(p, options, er, cb) - } - return cb(er) - }) -} - -function fixWinEPERM (p, options, er, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - if (er) - assert(er instanceof Error) - - options.chmod(p, 666, function (er2) { - if (er2) - cb(er2.code === "ENOENT" ? null : er) - else - options.stat(p, function(er3, stats) { - if (er3) - cb(er3.code === "ENOENT" ? null : er) - else if (stats.isDirectory()) - rmdir(p, options, er, cb) - else - options.unlink(p, cb) - }) - }) -} - -function fixWinEPERMSync (p, options, er) { - assert(p) - assert(options) - if (er) - assert(er instanceof Error) - - try { - options.chmodSync(p, 666) - } catch (er2) { - if (er2.code === "ENOENT") - return - else - throw er - } - - try { - var stats = options.statSync(p) - } catch (er3) { - if (er3.code === "ENOENT") - return - else - throw er - } - - if (stats.isDirectory()) - rmdirSync(p, options, er) - else - options.unlinkSync(p) -} - -function rmdir (p, options, originalEr, cb) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - assert(typeof cb === 'function') - - // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) - // if we guessed wrong, and it's not a directory, then - // raise the original error. - options.rmdir(p, function (er) { - if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) - rmkids(p, options, cb) - else if (er && er.code === "ENOTDIR") - cb(originalEr) - else - cb(er) - }) -} - -function rmkids(p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - - options.readdir(p, function (er, files) { - if (er) - return cb(er) - var n = files.length - if (n === 0) - return options.rmdir(p, cb) - var errState - files.forEach(function (f) { - rimraf(path.join(p, f), options, function (er) { - if (errState) - return - if (er) - return cb(errState = er) - if (--n === 0) - options.rmdir(p, cb) - }) - }) - }) -} - -// this looks simpler, and is strictly *faster*, but will -// tie up the JavaScript thread and fail on excessively -// deep directory trees. -function rimrafSync (p, options) { - options = options || {} - defaults(options) - - assert(p) - assert(options) - - try { - options.unlinkSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "EPERM") - return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) - if (er.code !== "EISDIR") - throw er - rmdirSync(p, options, er) - } -} - -function rmdirSync (p, options, originalEr) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - - try { - options.rmdirSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "ENOTDIR") - throw originalEr - if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") - rmkidsSync(p, options) - } -} - -function rmkidsSync (p, options) { - assert(p) - assert(options) - options.readdirSync(p).forEach(function (f) { - rimrafSync(path.join(p, f), options) - }) - options.rmdirSync(p, options) -} diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/test/run.sh b/labs/node_modules/meteor-npm/node_modules/rimraf/test/run.sh deleted file mode 100644 index 653ff9b798..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/test/run.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -e -code=0 -for i in test-*.js; do - echo -n $i ... - bash setup.sh - node $i - if [ -d target ]; then - echo "fail" - code=1 - else - echo "pass" - fi -done -rm -rf target -exit $code diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/test/setup.sh b/labs/node_modules/meteor-npm/node_modules/rimraf/test/setup.sh deleted file mode 100644 index 2602e63160..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/test/setup.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -set -e - -files=10 -folders=2 -depth=4 -target="$PWD/target" - -rm -rf target - -fill () { - local depth=$1 - local files=$2 - local folders=$3 - local target=$4 - - if ! [ -d $target ]; then - mkdir -p $target - fi - - local f - - f=$files - while [ $f -gt 0 ]; do - touch "$target/f-$depth-$f" - let f-- - done - - let depth-- - - if [ $depth -le 0 ]; then - return 0 - fi - - f=$folders - while [ $f -gt 0 ]; do - mkdir "$target/folder-$depth-$f" - fill $depth $files $folders "$target/d-$depth-$f" - let f-- - done -} - -fill $depth $files $folders $target - -# sanity assert -[ -d $target ] diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-async.js b/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-async.js deleted file mode 100644 index 9c2e0b7be0..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-async.js +++ /dev/null @@ -1,5 +0,0 @@ -var rimraf = require("../rimraf") - , path = require("path") -rimraf(path.join(__dirname, "target"), function (er) { - if (er) throw er -}) diff --git a/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-sync.js b/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-sync.js deleted file mode 100644 index eb71f10476..0000000000 --- a/labs/node_modules/meteor-npm/node_modules/rimraf/test/test-sync.js +++ /dev/null @@ -1,3 +0,0 @@ -var rimraf = require("../rimraf") - , path = require("path") -rimraf.sync(path.join(__dirname, "target")) diff --git a/labs/node_modules/meteor-npm/package.js b/labs/node_modules/meteor-npm/package.js deleted file mode 100644 index 3911651c6f..0000000000 --- a/labs/node_modules/meteor-npm/package.js +++ /dev/null @@ -1,40 +0,0 @@ -var path = Npm.require('path'); -var fs = Npm.require('fs'); -var packagesJsonFile = path.resolve('./packages.json'); - -//creating `packages.json` file for the first-time if not exists -if(!fs.existsSync(packagesJsonFile)) { - fs.writeFileSync(packagesJsonFile, '{\n \n}') -} - -try { - var fileContent = fs.readFileSync(packagesJsonFile); - var packages = JSON.parse(fileContent.toString()); - Npm.depends(packages); -} catch(ex) { - console.error('ERROR: packages.json parsing error [ ' + ex.message + ' ]'); -} - -Package.describe({ - summary: "complete npm integration/support for Meteor" -}); - -Package.on_use(function (api, where) { - api.export('Async'); - - var packagesFile = './.meteor/packages'; - if(fs.existsSync(packagesFile) && isNewerMeteor) { - api.add_files(['index.js', '../../packages.json'], 'server'); - } else { - api.add_files(['index.js'], 'server'); - } - - function isNewerMeteor() { - return fs.readFileSync(packagesFile, 'utf8').match(/\nstandard-app-packages/); - } -}); - -Package.on_test(function (api) { - api.use(['tinytest']); - api.add_files(['index.js', 'test.js'], 'server'); -}); diff --git a/labs/node_modules/meteor-npm/package.json b/labs/node_modules/meteor-npm/package.json deleted file mode 100644 index a17295bd82..0000000000 --- a/labs/node_modules/meteor-npm/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "meteor-npm", - "version": "0.1.10", - "description": "Complete NPM support for Meteor", - "bin": { - "meteor-npm": "./bin/meteor-npm" - }, - "author": { - "name": "Arunoda Susiripala", - "email": "arunoda.susiripala@gmail.com" - }, - "dependencies": { - "rimraf": "2.x", - "mkdirp": "0.3.x" - }, - "repository": { - "type": "git", - "url": "git://github.com/arunoda/meteor-npm.git" - }, - "readme": "# Complete NPM integration for Meteor [![Build Status](https://travis-ci.org/arunoda/meteor-npm.png?branch=master)](https://travis-ci.org/arunoda/meteor-npm)\n\nSee MeteorHacks article on [Complete NPM integration for Meteor](http://meteorhacks.com/complete-npm-integration-for-meteor.html)\n\n#### If you are migrating from Meteor 0.6.5.x to 0.6.6.x, please check this [issue](https://github.com/arunoda/meteor-npm/issues/12).\n\n---\n\n### Adding NPM support to your app\n\n mrt add npm\n\n### Create packages.json file for listing dependencies.\n\n {\n \"redis\": \"0.8.2\",\n \"github\": \"0.1.8\"\n }\n\n### Example on using npm module inside a Meteor method\n\n~~~js\nif (Meteor.isClient) {\n getGists = function getGists(user, callback) {\n Meteor.call('getGists', user, callback);\n }\n}\n\nif (Meteor.isServer) {\n Meteor.methods({\n 'getGists': function getGists(user) {\n var GithubApi = Meteor.require('github');\n var github = new GithubApi({\n version: \"3.0.0\"\n });\n\n var gists = Async.runSync(function(done) {\n github.gists.getFromUser({user: 'arunoda'}, function(err, data) {\n done(null, data);\n });\n });\n\n return gists.result;\n }\n });\n}\n~~~\n\n## API\n> Available in the Server Side only\n\n### Meteor.require(npmModuleName)\n\nThis method loads NPM modules you've specified in the `packages.json` file.\n\n~~~\nvar Github = Meteor.require('github');\n~~~\n\n## Async Utilities\n> Available in the Server Side only\n\nMeteor APIs are executed synchronously. Most of the NodeJS modules works asynchronously. \nSo we need a way to bride the gap. Async Utilities comes to rescue you.\n\n### Async.runSync(function) \n\n`Async.runSync()` pause the execution until you invoke `done()` callback as shown below.\n\n~~~\nvar response = Async.runSync(function(done) {\n setTimeout(function() { \n done(null, 1001);\n }, 100);\n});\n\nconsole.log(response.result); // 1001\n~~~\n\n`done()` callback takes 2 arguments. `error` and the `result` object. You can get them as the return value of the `Async.runSync()` as shown as response in the above example.\n\nreturn value is an object and it has 2 fields. `error` and `result`.\n\n### Meteor.sync(function)\n\nSame as `Async.runSync` but deprecated. \n\n### Async.wrap(function) \n\nWrap an asynchronous function and allow it to be run inside Meteor without callbacks.\n\n~~~\n\n//declare a simple async function\nfunction delayedMessge(delay, message, callback) {\n setTimeout(function() {\n callback(null, message);\n }, delay);\n}\n\n//wrapping\nvar wrappedDelayedMessage = Async.wrap(delayedMessge);\n\n//usage\nMeteor.methods({\n 'delayedEcho': function(message) {\n var response = wrappedDelayedMessage(500, message);\n return response;\n }\n});\n~~~\n\nIf the callback has a result, it will be returned from the wrapped function. If there is an error, it will be thrown.\n\n> `Async.wrap(function)` is very similar to `Meteor._wrapAsync`. \n\n### Async.wrap(object, functionName)\n\nVery similar to `Async.wrap(function)`, \nbut this API can be used to wrap an instance method of an object.\n\n~~~\nvar github = new GithubApi({\n version: \"3.0.0\"\n});\n\n//wrapping github.user.getFrom\nvar wrappedGetFrom = Async.wrap(github.user, 'getFrom');\n~~~\n\n### Async.wrap(object, functionNameList)\n\nVery similar to `Async.wrap(object, functionName)`, \nbut this API can be used to wrap **multiple** instance methods of an object.\n\n~~~\nvar github = new GithubApi({\n version: \"3.0.0\"\n});\n\n//wrapping github.user.getFrom and github.user.getEmails\nvar wrappedGithubUser = Async.wrap(github.user, ['getFrom', 'getEmails']);\n\n//usage\nvar profile = wrappedGithubUser.getFrom('arunoda');\nvar emails = wrappedGithubUser.getEmails();\n~~~\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/arunoda/meteor-npm/issues" - }, - "_id": "meteor-npm@0.1.10", - "dist": { - "shasum": "f70425eda4eb4a82362dba4b73523aaf316097a1" - }, - "_from": "meteor-npm@", - "_resolved": "https://registry.npmjs.org/meteor-npm/-/meteor-npm-0.1.10.tgz" -} diff --git a/labs/node_modules/meteor-npm/smart.json b/labs/node_modules/meteor-npm/smart.json deleted file mode 100644 index 2434f413f4..0000000000 --- a/labs/node_modules/meteor-npm/smart.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "npm", - "description": "Complete NPM integration/support for Meteor", - "homepage": "https://github.com/arunoda/meteor-npm", - "author": "Arunoda Susiripala ", - "version": "0.2.6", - "git": "https://github.com/arunoda/meteor-npm.git" -} diff --git a/labs/node_modules/meteor-npm/test.js b/labs/node_modules/meteor-npm/test.js deleted file mode 100644 index 59bfcfb390..0000000000 --- a/labs/node_modules/meteor-npm/test.js +++ /dev/null @@ -1,119 +0,0 @@ -Tinytest.add('Async.runSync - with done()', function(test) { - var output = Async.runSync(function(done) { - setTimeout(function() { - done(null, 10001); - }, 10); - }); - - test.equal(output.result, 10001); - test.equal(output.error, null); -}); - -Tinytest.add('Async.runSync - with error()', function(test) { - var output = Async.runSync(function(done) { - setTimeout(function() { - done({message: 'error-message', code: 402}); - }, 10); - }); - - test.equal(output.result, undefined); - test.equal(output.error.code, 402); -}); - -Tinytest.add('Async.runSync - with error in the callback', function(test) { - var output = Async.runSync(function(done) { - throw new Error('SOME_ERROR'); - }); - - test.equal(output.result, undefined); - test.equal(output.error.message, 'SOME_ERROR'); -}); - -Tinytest.add('Async.wrap function mode - success', function(test) { - function wait(timeout, callback) { - setTimeout(function() { - callback(null, 'okay'); - }, timeout); - }; - - var enclosedWait = Async.wrap(wait); - var output = enclosedWait(100); - - test.equal(output, 'okay'); -}); - -Tinytest.add('Async.wrap function mode - error', function(test) { - function wait(timeout, callback) { - setTimeout(function() { - var error = new Error('THE_ERROR'); - error.code = 500; - callback(error); - }, timeout); - }; - - var enclosedWait = Async.wrap(wait); - try { - enclosedWait(100); - test.fail('there must be an error'); - } catch(err) { - test.ok(err.message.match('THE_ERROR')); - test.equal(err.code, 500); - } - -}); - -Tinytest.add('Async.wrap object mode - success', function(test) { - function Wait() { - this.start = function(timeout, callback) { - setTimeout(function() { - callback(null, 'okay'); - }, timeout); - }; - } - - var wait = new Wait(); - - var enclosedWait = Async.wrap(wait, 'start'); - - var output = enclosedWait(100); - test.equal(output, 'okay'); -}); - -Tinytest.add('Async.wrap object mode - funcName not exists', function(test) { - function Wait() { - this.start = function(timeout, callback) { - setTimeout(function() { - callback(null, 'okay'); - }, timeout); - }; - } - - var wait = new Wait(); - try { - var enclosedWait = Async.wrap(wait, 'startz'); - test.fail('shoud throw an error'); - } catch(ex) { - - } -}); - -Tinytest.add('Async.wrap object mode - multi function mode', function(test) { - function Wait() { - this.start = function(timeout, callback) { - setTimeout(function() { - callback(null, 'okay'); - }, timeout); - }; - - this.start2 = function(timeout, callback) { - setTimeout(function() { - callback(null, 'okay'); - }, timeout); - }; - } - - var wait = new Wait(); - var enclosedWait = Async.wrap(wait, ['start', 'start2']); - enclosedWait.start(100); - enclosedWait.start2(100); -}); \ No newline at end of file diff --git a/labs/node_modules/redis/.npmignore b/labs/node_modules/redis/.npmignore deleted file mode 100644 index 61755a69fc..0000000000 --- a/labs/node_modules/redis/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -examples/ -benches/ -test.js -diff_multi_bench_output.js -generate_commands.js -multi_bench.js -test-unref.js -changelog.md diff --git a/labs/node_modules/redis/README.md b/labs/node_modules/redis/README.md deleted file mode 100644 index d1ae32e26b..0000000000 --- a/labs/node_modules/redis/README.md +++ /dev/null @@ -1,757 +0,0 @@ -redis - a node.js redis client -=========================== - -This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from -experimental Redis server branches. - - -Install with: - - npm install redis - -Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do: - - npm install hiredis redis - -If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used. - -If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can -happen between node and native code modules after a node upgrade. - - -## Usage - -Simple example, included as `examples/simple.js`: - -```js - var redis = require("redis"), - client = redis.createClient(); - - // if you'd like to select database 3, instead of 0 (default), call - // client.select(3, function() { /* ... */ }); - - client.on("error", function (err) { - console.log("Error " + err); - }); - - client.set("string key", "string val", redis.print); - client.hset("hash key", "hashtest 1", "some value", redis.print); - client.hset(["hash key", "hashtest 2", "some other value"], redis.print); - client.hkeys("hash key", function (err, replies) { - console.log(replies.length + " replies:"); - replies.forEach(function (reply, i) { - console.log(" " + i + ": " + reply); - }); - client.quit(); - }); -``` - -This will display: - - mjr:~/work/node_redis (master)$ node example.js - Reply: OK - Reply: 0 - Reply: 0 - 2 replies: - 0: hashtest 1 - 1: hashtest 2 - mjr:~/work/node_redis (master)$ - - -## Performance - -Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution. -It uses 50 concurrent connections with no pipelining. - -JavaScript parser: - - PING: 20000 ops 42283.30 ops/sec 0/5/1.182 - SET: 20000 ops 32948.93 ops/sec 1/7/1.515 - GET: 20000 ops 28694.40 ops/sec 0/9/1.740 - INCR: 20000 ops 39370.08 ops/sec 0/8/1.269 - LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370 - LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048 - LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072 - -hiredis parser: - - PING: 20000 ops 46189.38 ops/sec 1/4/1.082 - SET: 20000 ops 41237.11 ops/sec 0/6/1.210 - GET: 20000 ops 39682.54 ops/sec 1/7/1.257 - INCR: 20000 ops 40080.16 ops/sec 0/8/1.242 - LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212 - LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363 - LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287 - -The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs. - - -### Sending Commands - -Each Redis command is exposed as a function on the `client` object. -All functions take either an `args` Array plus optional `callback` Function or -a variable number of individual arguments followed by an optional callback. -Here is an example of passing an array of arguments and a callback: - - client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {}); - -Here is that same call in the second style: - - client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {}); - -Note that in either form the `callback` is optional: - - client.set("some key", "some val"); - client.set(["some other key", "some val"]); - -If the key is missing, reply will be null (probably): - - client.get("missingkey", function(err, reply) { - // reply is null when the key is missing - console.log(reply); - }); - -For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands) - -The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`. - -Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings, -integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a -JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys. - -# API - -## Connection Events - -`client` will emit some events about the state of the connection to the Redis server. - -### "ready" - -`client` will emit `ready` a connection is established to the Redis server and the server reports -that it is ready to receive commands. Commands issued before the `ready` event are queued, -then replayed just before this event is emitted. - -### "connect" - -`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check` -is set. If this options is set, `connect` will be emitted when the stream is connected, and then -you are free to try to send commands. - -### "error" - -`client` will emit `error` when encountering an error connecting to the Redis server. - -Note that "error" is a special event type in node. If there are no listeners for an -"error" event, node will exit. This is usually what you want, but it can lead to some -cryptic error messages like this: - - mjr:~/work/node_redis (master)$ node example.js - - node.js:50 - throw e; - ^ - Error: ECONNREFUSED, Connection refused - at IOWatcher.callback (net:870:22) - at node.js:607:9 - -Not very useful in diagnosing the problem, but if your program isn't ready to handle this, -it is probably the right thing to just exit. - -`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason. -It would be nice to distinguish these two cases. - -### "end" - -`client` will emit `end` when an established Redis server connection has closed. - -### "drain" - -`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now -writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now, -you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can -resume sending when you get `drain`. - -### "idle" - -`client` will emit `idle` when there are no outstanding commands that are awaiting a response. - -## redis.createClient(port, host, options) - -Create a new client connection. `port` defaults to `6379` and `host` defaults -to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for -port and host are probably fine. `options` in an object with the following possible properties: - -* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed. -This may also be set to `javascript`. -* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer -objects instead of JavaScript Strings. -* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects -if any of the input arguments to the original command were Buffer objects. -This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to -every command on a client. -* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the -Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the -cost of more latency. Most applications will want this set to `true`. -* `socket_keepalive` defaults to `true`. Whether the keep-alive functionality is enabled on the underlying socket. -* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still -be loading the database from disk. While loading, the server not respond to any commands. To work around this, -`node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command -indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. -Setting `no_ready_check` to `true` will inhibit this check. -* `enable_offline_queue`: defaults to `true`. By default, if there is no active -connection to the redis server, commands are added to a queue and are executed -once the connection has been established. Setting `enable_offline_queue` to -`false` will disable this feature and the callback will be execute immediately -with an error, or an error will be thrown if no callback is specified. -* `retry_max_delay`: defaults to `null`. By default every time the client tries to connect and fails time before -reconnection (delay) almost doubles. This delay normally grows infinitely, but setting `retry_max_delay` limits delay -to maximum value, provided in milliseconds. -* `connect_timeout` defaults to `false`. By default client will try reconnecting until connected. Setting `connect_timeout` -limits total time for client to reconnect. Value is provided in milliseconds and is counted once the disconnect occured. -* `max_attempts` defaults to `null`. By default client will try reconnecting until connected. Setting `max_attempts` -limits total amount of reconnects. -* `auth_pass` defaults to `null`. By default client will try connecting without auth. If set, client will run redis auth command on connect. -* `family` defaults to `IPv4`. The client connects in IPv4 if not specified or if the DNS resolution returns an IPv4 address. -You can force an IPv6 if you set the family to 'IPv6'. See nodejs net or dns modules how to use the family type. - -```js - var redis = require("redis"), - client = redis.createClient(null, null, {detect_buffers: true}); - - client.set("foo_rand000000000000", "OK"); - - // This will return a JavaScript String - client.get("foo_rand000000000000", function (err, reply) { - console.log(reply.toString()); // Will print `OK` - }); - - // This will return a Buffer since original key is specified as a Buffer - client.get(new Buffer("foo_rand000000000000"), function (err, reply) { - console.log(reply.toString()); // Will print `` - }); - client.end(); -``` - -`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here. - -### Unix Domain Socket - -You can also create a connection to Redis server via the unix domain socket if the server -has it enabled: - -```js -var redis = require("redis"); -var client = redis.createClient("/tmp/redis.sock"); -``` - -Sample `redis.conf` configuration to enable unix domain socket listening: - -```conf -unixsocket /tmp/redis.sock -unixsocketperm 755 -``` - -See [issue #204](https://github.com/mranney/node_redis/issues/204) for more information. - -## client.auth(password, callback) - -When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the -first command after connecting. This can be tricky to coordinate with reconnections, the ready check, -etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection, -including reconnections. `callback` is invoked only once, after the response to the very first -`AUTH` command sent. -NOTE: Your call to `client.auth()` should not be inside the ready handler. If -you are doing this wrong, `client` will emit an error that looks -something like this `Error: Ready check failed: ERR operation not permitted`. - -## client.end() - -Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed. -If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies. - -This example closes the connection to the Redis server before the replies have been read. You probably don't -want to do this: - -```js - var redis = require("redis"), - client = redis.createClient(); - - client.set("foo_rand000000000000", "some fantastic value"); - client.get("foo_rand000000000000", function (err, reply) { - console.log(reply.toString()); - }); - client.end(); -``` - -`client.end()` is useful for timeout cases where something is stuck or taking too long and you want -to start over. - -## client.unref() - -Call `unref()` on the underlying socket connection to the Redis server, allowing the program to exit once no more commands are pending. - -This is an **experimental** feature, and only supports a subset of the Redis protocol. Any commands where client state is saved on the Redis server, e.g. `*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`. - -```js -var redis = require("redis") -var client = redis.createClient() - -/* - Calling unref() will allow this program to exit immediately after the get command finishes. Otherwise the client would hang as long as the client-server connection is alive. -*/ -client.unref() -client.get("foo", function (err, value){ - if (err) throw(err) - console.log(value) -}) -``` - -## Friendlier hash commands - -Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. -When dealing with hash values, there are a couple of useful exceptions to this. - -### client.hgetall(hash) - -The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact -with the responses using JavaScript syntax. - -Example: - - client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234"); - client.hgetall("hosts", function (err, obj) { - console.dir(obj); - }); - -Output: - - { mjr: '1', another: '23', home: '1234' } - -### client.hmset(hash, obj, [callback]) - -Multiple values in a hash can be set by supplying an object: - - client.HMSET(key2, { - "0123456789": "abcdefghij", // NOTE: key and value will be coerced to strings - "some manner of key": "a type of value" - }); - -The properties and values of this Object will be set as keys and values in the Redis hash. - -### client.hmset(hash, key1, val1, ... keyn, valn, [callback]) - -Multiple values may also be set by supplying a list: - - client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value"); - - -## Publish / Subscribe - -Here is a simple example of the API for publish / subscribe. This program opens two -client connections, subscribes to a channel on one of them, and publishes to that -channel on the other: - -```js - var redis = require("redis"), - client1 = redis.createClient(), client2 = redis.createClient(), - msg_count = 0; - - client1.on("subscribe", function (channel, count) { - client2.publish("a nice channel", "I am sending a message."); - client2.publish("a nice channel", "I am sending a second message."); - client2.publish("a nice channel", "I am sending my last message."); - }); - - client1.on("message", function (channel, message) { - console.log("client1 channel " + channel + ": " + message); - msg_count += 1; - if (msg_count === 3) { - client1.unsubscribe(); - client1.end(); - client2.end(); - } - }); - - client1.incr("did a thing"); - client1.subscribe("a nice channel"); -``` - -When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into a "subscriber" mode. -At that point, only commands that modify the subscription set are valid. When the subscription -set is empty, the connection is put back into regular mode. - -If you need to send regular commands to Redis while in subscriber mode, just open another connection. - -## Subscriber Events - -If a client has subscriptions active, it may emit these events: - -### "message" (channel, message) - -Client will emit `message` for every message received that matches an active subscription. -Listeners are passed the channel name as `channel` and the message Buffer as `message`. - -### "pmessage" (pattern, channel, message) - -Client will emit `pmessage` for every message received that matches an active subscription pattern. -Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel -name as `channel`, and the message Buffer as `message`. - -### "subscribe" (channel, count) - -Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the -channel name as `channel` and the new count of subscriptions for this client as `count`. - -### "psubscribe" (pattern, count) - -Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the -original pattern as `pattern`, and the new count of subscriptions for this client as `count`. - -### "unsubscribe" (channel, count) - -Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the -channel name as `channel` and the new count of subscriptions for this client as `count`. When -`count` is 0, this client has left subscriber mode and no more subscriber events will be emitted. - -### "punsubscribe" (pattern, count) - -Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the -channel name as `channel` and the new count of subscriptions for this client as `count`. When -`count` is 0, this client has left subscriber mode and no more subscriber events will be emitted. - -## client.multi([commands]) - -`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by -Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`. - -```js - var redis = require("./index"), - client = redis.createClient(), set_size = 20; - - client.sadd("bigset", "a member"); - client.sadd("bigset", "another member"); - - while (set_size > 0) { - client.sadd("bigset", "member " + set_size); - set_size -= 1; - } - - // multi chain with an individual callback - client.multi() - .scard("bigset") - .smembers("bigset") - .keys("*", function (err, replies) { - // NOTE: code in this callback is NOT atomic - // this only happens after the the .exec call finishes. - client.mget(replies, redis.print); - }) - .dbsize() - .exec(function (err, replies) { - console.log("MULTI got " + replies.length + " replies"); - replies.forEach(function (reply, index) { - console.log("Reply " + index + ": " + reply.toString()); - }); - }); -``` - -### Multi.exec( callback ) - -`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the -same command methods as `client` objects do. Commands are queued up inside the `Multi` object -until `Multi.exec()` is invoked. - -The `callback` of `.exec()` will get invoked with two arguments: - -* `err` **type:** `null | Array` err is either null or an array of Error Objects corresponding the the sequence the commands where chained. The last item of the array will always be an `EXECABORT` type of error originating from the `.exec()` itself. -* `results` **type:** `null | Array` results is an array of responses corresponding the the sequence the commands where chained. - -You can either chain together `MULTI` commands as in the above example, or you can queue individual -commands while still sending regular client command as in this example: - -```js - var redis = require("redis"), - client = redis.createClient(), multi; - - // start a separate multi command queue - multi = client.multi(); - multi.incr("incr thing", redis.print); - multi.incr("incr other thing", redis.print); - - // runs immediately - client.mset("incr thing", 100, "incr other thing", 1, redis.print); - - // drains multi queue and runs atomically - multi.exec(function (err, replies) { - console.log(replies); // 101, 2 - }); - - // you can re-run the same transaction if you like - multi.exec(function (err, replies) { - console.log(replies); // 102, 3 - client.quit(); - }); -``` - -In addition to adding commands to the `MULTI` queue individually, you can also pass an array -of commands and arguments to the constructor: - -```js - var redis = require("redis"), - client = redis.createClient(), multi; - - client.multi([ - ["mget", "multifoo", "multibar", redis.print], - ["incr", "multifoo"], - ["incr", "multibar"] - ]).exec(function (err, replies) { - console.log(replies); - }); -``` - - -## Monitor mode - -Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server -across all client connections, including from other client libraries and other computers. - -After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis` -will emit a `monitor` event for every new monitor message that comes across. The callback for the -`monitor` event takes a timestamp from the Redis server and an array of command arguments. - -Here is a simple example: - -```js - var client = require("redis").createClient(), - util = require("util"); - - client.monitor(function (err, res) { - console.log("Entering monitoring mode."); - }); - - client.on("monitor", function (time, args) { - console.log(time + ": " + util.inspect(args)); - }); -``` - -# Extras - -Some other things you might like to know about. - -## client.server_info - -After the ready probe completes, the results from the INFO command are saved in the `client.server_info` -object. - -The `versions` key contains an array of the elements of the version string for easy comparison. - - > client.server_info.redis_version - '2.3.0' - > client.server_info.versions - [ 2, 3, 0 ] - -## redis.print() - -A handy callback function for displaying return values when testing. Example: - -```js - var redis = require("redis"), - client = redis.createClient(); - - client.on("connect", function () { - client.set("foo_rand000000000000", "some fantastic value", redis.print); - client.get("foo_rand000000000000", redis.print); - }); -``` - -This will print: - - Reply: OK - Reply: some fantastic value - -Note that this program will not exit cleanly because the client is still connected. - -## redis.debug_mode - -Boolean to enable debug mode and protocol tracing. - -```js - var redis = require("redis"), - client = redis.createClient(); - - redis.debug_mode = true; - - client.on("connect", function () { - client.set("foo_rand000000000000", "some fantastic value"); - }); -``` - -This will display: - - mjr:~/work/node_redis (master)$ node ~/example.js - send command: *3 - $3 - SET - $20 - foo_rand000000000000 - $20 - some fantastic value - - on_data: +OK - -`send command` is data sent into Redis and `on_data` is data received from Redis. - -## Multi-word commands - -To execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass -the second word as first parameter: - - client.script('load', 'return 1'); - client.multi().script('load', 'return 1').exec(...); - client.multi([['script', 'load', 'return 1']]).exec(...); - -## client.send_command(command_name, args, callback) - -Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis -Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before -this library is updated, you can use `send_command()` to send arbitrary commands to Redis. - -All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted. - -## client.connected - -Boolean tracking the state of the connection to the Redis server. - -## client.command_queue.length - -The number of commands that have been sent to the Redis server but not yet replied to. You can use this to -enforce some kind of maximum queue depth for commands while connected. - -Don't mess with `client.command_queue` though unless you really know what you are doing. - -## client.offline_queue.length - -The number of commands that have been queued up for a future connection. You can use this to enforce -some kind of maximum queue depth for pre-connection commands. - -## client.retry_delay - -Current delay in milliseconds before a connection retry will be attempted. This starts at `250`. - -## client.retry_backoff - -Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries. -Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc. - -### Commands with Optional and Keyword arguments - -This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation. - -Example: -```js -var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ]; -client.zadd(args, function (err, response) { - if (err) throw err; - console.log('added '+response+' items.'); - - // -Infinity and +Infinity also work - var args1 = [ 'myzset', '+inf', '-inf' ]; - client.zrevrangebyscore(args1, function (err, response) { - if (err) throw err; - console.log('example1', response); - // write your code here - }); - - var max = 3, min = 1, offset = 1, count = 2; - var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ]; - client.zrevrangebyscore(args2, function (err, response) { - if (err) throw err; - console.log('example2', response); - // write your code here - }); -}); -``` - -## TODO - -Better tests for auth, disconnect/reconnect, and all combinations thereof. - -Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory. - -Performance can be better for very large values. - -I think there are more performance improvements left in there for smaller values, especially for large lists of small values. - -## How to Contribute -- open a pull request and then wait for feedback (if - [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days, - comment again with indignation!) - -## Contributors -Some people have have added features and fixed bugs in `node_redis` other than me. - -Ordered by date of first contribution. -[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT). - -- [Matt Ranney aka `mranney`](https://github.com/mranney) -- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart) -- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia) -- [rick aka `technoweenie`](https://github.com/technoweenie) -- [Orion Henry aka `orionz`](https://github.com/orionz) -- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas) -- [Hank Sims aka `hanksims`](https://github.com/hanksims) -- [Paul Carey aka `paulcarey`](https://github.com/paulcarey) -- [Pieter Noordhuis aka `pietern`](https://github.com/pietern) -- [nithesh aka `nithesh`](https://github.com/nithesh) -- [Andy Ray aka `andy2ray`](https://github.com/andy2ray) -- [unknown aka `unknowdna`](https://github.com/unknowdna) -- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel) -- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv) -- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique) -- [Louis-Philippe Perron aka `lp`](https://github.com/lp) -- [Mark Dawson aka `markdaws`](https://github.com/markdaws) -- [Ian Babrou aka `bobrik`](https://github.com/bobrik) -- [Felix Geisendörfer aka `felixge`](https://github.com/felixge) -- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined) -- [Maksim Lin aka `maks`](https://github.com/maks) -- [Owen Smith aka `orls`](https://github.com/orls) -- [Zachary Scott aka `zzak`](https://github.com/zzak) -- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK) -- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs) -- [David Trejo aka `DTrejo`](https://github.com/DTrejo) -- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi) -- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon) -- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2) -- [Jed Schmidt aka `jed`](https://github.com/jed) -- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3) -- [Trae Robrock aka `trobrock`](https://github.com/trobrock) -- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306) -- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio) - -Thanks. - -## LICENSE - "MIT License" - -Copyright (c) 2010 Matthew Ranney, http://ranney.com/ - -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. - -![spacer](http://ranney.com/1px.gif) diff --git a/labs/node_modules/redis/connection_breaker.js b/labs/node_modules/redis/connection_breaker.js deleted file mode 100644 index 489f5d5645..0000000000 --- a/labs/node_modules/redis/connection_breaker.js +++ /dev/null @@ -1,80 +0,0 @@ -var net = require('net'); - -var proxyPort = 6379; -var counter = 0; - -function breaker(conn) { - conn.end(); - conn.destroy(); -} - -var server = net.createServer(function(conn) { - counter++; - var proxyConn = net.createConnection({ - port: proxyPort - }); - conn.pipe(proxyConn); - proxyConn.pipe(conn); - proxyConn.on('end', function() { - conn.end(); - }); - conn.on('end', function() { - proxyConn.end(); - }); - conn.on('close', function() { - proxyConn.end(); - }); - proxyConn.on('close', function() { - conn.end(); - }); - proxyConn.on('error', function() { - conn.end(); - }); - conn.on('error', function() { - proxyConn.end(); - }); - - setTimeout(breaker.bind(null, conn), Math.floor(Math.random() * 2000)); -}); -server.listen(6479); - -var redis = require('./'); - -var port = 6479; - -var client = redis.createClient(6479, 'localhost'); - -function iter() { - var k = "k" + Math.floor(Math.random() * 10); - var coinflip = Math.random() > 0.5; - if (coinflip) { - client.set(k, k, function(err, resp) { - if (!err && resp !== "OK") { - console.log("Unexpected set response " + resp); - } - }); - } else { - client.get(k, function(err, resp) { - if (!err) { - if (k !== resp) { - console.log("Key response mismatch: " + k + " " + resp); - } - } - }); - } -} - -function iters() { - for (var i = 0; i < 100; ++i) { - iter(); - } - setTimeout(iters, 10); -} - -client.on("connect", function () { - iters(); -}); - -client.on("error", function (err) { - console.log("Client error " + err); -}); diff --git a/labs/node_modules/redis/index.js b/labs/node_modules/redis/index.js deleted file mode 100644 index 9674e7a528..0000000000 --- a/labs/node_modules/redis/index.js +++ /dev/null @@ -1,1248 +0,0 @@ -/*global Buffer require exports console setTimeout */ - -var net = require("net"), - util = require("./lib/util"), - Queue = require("./lib/queue"), - to_array = require("./lib/to_array"), - events = require("events"), - crypto = require("crypto"), - parsers = [], commands, - connection_id = 0, - default_port = 6379, - default_host = "127.0.0.1"; - -// can set this to true to enable for all connections -exports.debug_mode = false; - -var arraySlice = Array.prototype.slice -function trace() { - if (!exports.debug_mode) return; - console.log.apply(null, arraySlice.call(arguments)) -} - -// hiredis might not be installed -try { - require("./lib/parser/hiredis"); - parsers.push(require("./lib/parser/hiredis")); -} catch (err) { - if (exports.debug_mode) { - console.warn("hiredis parser not installed."); - } -} - -parsers.push(require("./lib/parser/javascript")); - -function RedisClient(stream, options) { - this.stream = stream; - this.options = options = options || {}; - - this.connection_id = ++connection_id; - this.connected = false; - this.ready = false; - this.connections = 0; - if (this.options.socket_nodelay === undefined) { - this.options.socket_nodelay = true; - } - if (this.options.socket_keepalive === undefined) { - this.options.socket_keepalive = true; - } - this.should_buffer = false; - this.command_queue_high_water = this.options.command_queue_high_water || 1000; - this.command_queue_low_water = this.options.command_queue_low_water || 0; - this.max_attempts = null; - if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) { - this.max_attempts = +options.max_attempts; - } - this.command_queue = new Queue(); // holds sent commands to de-pipeline them - this.offline_queue = new Queue(); // holds commands issued but not able to be sent - this.commands_sent = 0; - this.connect_timeout = false; - if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) { - this.connect_timeout = +options.connect_timeout; - } - this.enable_offline_queue = true; - if (typeof this.options.enable_offline_queue === "boolean") { - this.enable_offline_queue = this.options.enable_offline_queue; - } - this.retry_max_delay = null; - if (options.retry_max_delay !== undefined && !isNaN(options.retry_max_delay) && options.retry_max_delay > 0) { - this.retry_max_delay = options.retry_max_delay; - } - - this.initialize_retry_vars(); - this.pub_sub_mode = false; - this.subscription_set = {}; - this.monitoring = false; - this.closing = false; - this.server_info = {}; - this.auth_pass = null; - if (options.auth_pass !== undefined) { - this.auth_pass = options.auth_pass; - } - this.parser_module = null; - this.selected_db = null; // save the selected db here, used when reconnecting - - this.old_state = null; - - this.install_stream_listeners(); - - events.EventEmitter.call(this); -} -util.inherits(RedisClient, events.EventEmitter); -exports.RedisClient = RedisClient; - -RedisClient.prototype.install_stream_listeners = function() { - var self = this; - - this.stream.on("connect", function () { - self.on_connect(); - }); - - this.stream.on("data", function (buffer_from_socket) { - self.on_data(buffer_from_socket); - }); - - this.stream.on("error", function (msg) { - self.on_error(msg.message); - }); - - this.stream.on("close", function () { - self.connection_gone("close"); - }); - - this.stream.on("end", function () { - self.connection_gone("end"); - }); - - this.stream.on("drain", function () { - self.should_buffer = false; - self.emit("drain"); - }); -}; - -RedisClient.prototype.initialize_retry_vars = function () { - this.retry_timer = null; - this.retry_totaltime = 0; - this.retry_delay = 150; - this.retry_backoff = 1.7; - this.attempts = 1; -}; - -RedisClient.prototype.unref = function () { - trace("User requesting to unref the connection"); - if (this.connected) { - trace("unref'ing the socket connection"); - this.stream.unref(); - } - else { - trace("Not connected yet, will unref later"); - this.once("connect", function () { - this.unref(); - }) - } -}; - -// flush offline_queue and command_queue, erroring any items with a callback first -RedisClient.prototype.flush_and_error = function (message) { - var command_obj, error; - - error = new Error(message); - - while (this.offline_queue.length > 0) { - command_obj = this.offline_queue.shift(); - if (typeof command_obj.callback === "function") { - try { - command_obj.callback(error); - } catch (callback_err) { - process.nextTick(function () { - throw callback_err; - }); - } - } - } - this.offline_queue = new Queue(); - - while (this.command_queue.length > 0) { - command_obj = this.command_queue.shift(); - if (typeof command_obj.callback === "function") { - try { - command_obj.callback(error); - } catch (callback_err) { - process.nextTick(function () { - throw callback_err; - }); - } - } - } - this.command_queue = new Queue(); -}; - -RedisClient.prototype.on_error = function (msg) { - var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg; - - if (this.closing) { - return; - } - - if (exports.debug_mode) { - console.warn(message); - } - - this.flush_and_error(message); - - this.connected = false; - this.ready = false; - - this.emit("error", new Error(message)); - // "error" events get turned into exceptions if they aren't listened for. If the user handled this error - // then we should try to reconnect. - this.connection_gone("error"); -}; - -RedisClient.prototype.do_auth = function () { - var self = this; - - if (exports.debug_mode) { - console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id); - } - self.send_anyway = true; - self.send_command("auth", [this.auth_pass], function (err, res) { - if (err) { - if (err.toString().match("LOADING")) { - // if redis is still loading the db, it will not authenticate and everything else will fail - console.log("Redis still loading, trying to authenticate later"); - setTimeout(function () { - self.do_auth(); - }, 2000); // TODO - magic number alert - return; - } else if (err.toString().match("no password is set")) { - console.log("Warning: Redis server does not require a password, but a password was supplied.") - err = null; - res = "OK"; - } else { - return self.emit("error", new Error("Auth error: " + err.message)); - } - } - if (res.toString() !== "OK") { - return self.emit("error", new Error("Auth failed: " + res.toString())); - } - if (exports.debug_mode) { - console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id); - } - if (self.auth_callback) { - self.auth_callback(err, res); - self.auth_callback = null; - } - - // now we are really connected - self.emit("connect"); - self.initialize_retry_vars(); - - if (self.options.no_ready_check) { - self.on_ready(); - } else { - self.ready_check(); - } - }); - self.send_anyway = false; -}; - -RedisClient.prototype.on_connect = function () { - if (exports.debug_mode) { - console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id); - } - - this.connected = true; - this.ready = false; - this.connections += 1; - this.command_queue = new Queue(); - this.emitted_end = false; - if (this.options.socket_nodelay) { - this.stream.setNoDelay(); - } - this.stream.setKeepAlive(this.options.socket_keepalive); - this.stream.setTimeout(0); - - this.init_parser(); - - if (this.auth_pass) { - this.do_auth(); - } else { - this.emit("connect"); - this.initialize_retry_vars(); - - if (this.options.no_ready_check) { - this.on_ready(); - } else { - this.ready_check(); - } - } -}; - -RedisClient.prototype.init_parser = function () { - var self = this; - - if (this.options.parser) { - if (! parsers.some(function (parser) { - if (parser.name === self.options.parser) { - self.parser_module = parser; - if (exports.debug_mode) { - console.log("Using parser module: " + self.parser_module.name); - } - return true; - } - })) { - throw new Error("Couldn't find named parser " + self.options.parser + " on this system"); - } - } else { - if (exports.debug_mode) { - console.log("Using default parser module: " + parsers[0].name); - } - this.parser_module = parsers[0]; - } - - this.parser_module.debug_mode = exports.debug_mode; - - // return_buffers sends back Buffers from parser to callback. detect_buffers sends back Buffers from parser, but - // converts to Strings if the input arguments are not Buffers. - this.reply_parser = new this.parser_module.Parser({ - return_buffers: self.options.return_buffers || self.options.detect_buffers || false - }); - - // "reply error" is an error sent back by Redis - this.reply_parser.on("reply error", function (reply) { - if (reply instanceof Error) { - self.return_error(reply); - } else { - self.return_error(new Error(reply)); - } - }); - this.reply_parser.on("reply", function (reply) { - self.return_reply(reply); - }); - // "error" is bad. Somehow the parser got confused. It'll try to reset and continue. - this.reply_parser.on("error", function (err) { - self.emit("error", new Error("Redis reply parser error: " + err.stack)); - }); -}; - -RedisClient.prototype.on_ready = function () { - var self = this; - - this.ready = true; - - if (this.old_state !== null) { - this.monitoring = this.old_state.monitoring; - this.pub_sub_mode = this.old_state.pub_sub_mode; - this.selected_db = this.old_state.selected_db; - this.old_state = null; - } - - // magically restore any modal commands from a previous connection - if (this.selected_db !== null) { - // this trick works if and only if the following send_command - // never goes into the offline queue - var pub_sub_mode = this.pub_sub_mode; - this.pub_sub_mode = false; - this.send_command('select', [this.selected_db]); - this.pub_sub_mode = pub_sub_mode; - } - if (this.pub_sub_mode === true) { - // only emit "ready" when all subscriptions were made again - var callback_count = 0; - var callback = function () { - callback_count--; - if (callback_count === 0) { - self.emit("ready"); - } - }; - Object.keys(this.subscription_set).forEach(function (key) { - var parts = key.split(" "); - if (exports.debug_mode) { - console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]); - } - callback_count++; - self.send_command(parts[0] + "scribe", [parts[1]], callback); - }); - return; - } else if (this.monitoring) { - this.send_command("monitor"); - } else { - this.send_offline_queue(); - } - this.emit("ready"); -}; - -RedisClient.prototype.on_info_cmd = function (err, res) { - var self = this, obj = {}, lines, retry_time; - - if (err) { - return self.emit("error", new Error("Ready check failed: " + err.message)); - } - - lines = res.toString().split("\r\n"); - - lines.forEach(function (line) { - var parts = line.split(':'); - if (parts[1]) { - obj[parts[0]] = parts[1]; - } - }); - - obj.versions = []; - if( obj.redis_version ){ - obj.redis_version.split('.').forEach(function (num) { - obj.versions.push(+num); - }); - } - - // expose info key/vals to users - this.server_info = obj; - - if (!obj.loading || (obj.loading && obj.loading === "0")) { - if (exports.debug_mode) { - console.log("Redis server ready."); - } - this.on_ready(); - } else { - retry_time = obj.loading_eta_seconds * 1000; - if (retry_time > 1000) { - retry_time = 1000; - } - if (exports.debug_mode) { - console.log("Redis server still loading, trying again in " + retry_time); - } - setTimeout(function () { - self.ready_check(); - }, retry_time); - } -}; - -RedisClient.prototype.ready_check = function () { - var self = this; - - if (exports.debug_mode) { - console.log("checking server ready state..."); - } - - this.send_anyway = true; // secret flag to send_command to send something even if not "ready" - this.info(function (err, res) { - self.on_info_cmd(err, res); - }); - this.send_anyway = false; -}; - -RedisClient.prototype.send_offline_queue = function () { - var command_obj, buffered_writes = 0; - - while (this.offline_queue.length > 0) { - command_obj = this.offline_queue.shift(); - if (exports.debug_mode) { - console.log("Sending offline command: " + command_obj.command); - } - buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback); - } - this.offline_queue = new Queue(); - // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue - - if (!buffered_writes) { - this.should_buffer = false; - this.emit("drain"); - } -}; - -RedisClient.prototype.connection_gone = function (why) { - var self = this; - - // If a retry is already in progress, just let that happen - if (this.retry_timer) { - return; - } - - if (exports.debug_mode) { - console.warn("Redis connection is gone from " + why + " event."); - } - this.connected = false; - this.ready = false; - - if (this.old_state === null) { - var state = { - monitoring: this.monitoring, - pub_sub_mode: this.pub_sub_mode, - selected_db: this.selected_db - }; - this.old_state = state; - this.monitoring = false; - this.pub_sub_mode = false; - this.selected_db = null; - } - - // since we are collapsing end and close, users don't expect to be called twice - if (! this.emitted_end) { - this.emit("end"); - this.emitted_end = true; - } - - this.flush_and_error("Redis connection gone from " + why + " event."); - - // If this is a requested shutdown, then don't retry - if (this.closing) { - this.retry_timer = null; - if (exports.debug_mode) { - console.warn("connection ended from quit command, not retrying."); - } - return; - } - - var nextDelay = Math.floor(this.retry_delay * this.retry_backoff); - if (this.retry_max_delay !== null && nextDelay > this.retry_max_delay) { - this.retry_delay = this.retry_max_delay; - } else { - this.retry_delay = nextDelay; - } - - if (exports.debug_mode) { - console.log("Retry connection in " + this.retry_delay + " ms"); - } - - if (this.max_attempts && this.attempts >= this.max_attempts) { - this.retry_timer = null; - // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others - // want the program to exit. Right now, we just log, which doesn't really help in either case. - console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts."); - return; - } - - this.attempts += 1; - this.emit("reconnecting", { - delay: self.retry_delay, - attempt: self.attempts - }); - this.retry_timer = setTimeout(function () { - if (exports.debug_mode) { - console.log("Retrying connection..."); - } - - self.retry_totaltime += self.retry_delay; - - if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) { - self.retry_timer = null; - // TODO - engage Redis is Broken mode for future commands, or whatever - console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms."); - return; - } - - self.stream = net.createConnection(self.port, self.host); - self.install_stream_listeners(); - self.retry_timer = null; - }, this.retry_delay); -}; - -RedisClient.prototype.on_data = function (data) { - if (exports.debug_mode) { - console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString()); - } - - try { - this.reply_parser.execute(data); - } catch (err) { - // This is an unexpected parser problem, an exception that came from the parser code itself. - // Parser should emit "error" events if it notices things are out of whack. - // Callbacks that throw exceptions will land in return_reply(), below. - // TODO - it might be nice to have a different "error" event for different types of errors - this.emit("error", err); - } -}; - -RedisClient.prototype.return_error = function (err) { - var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength(); - - if (this.pub_sub_mode === false && queue_len === 0) { - this.command_queue = new Queue(); - this.emit("idle"); - } - if (this.should_buffer && queue_len <= this.command_queue_low_water) { - this.emit("drain"); - this.should_buffer = false; - } - - if (command_obj && typeof command_obj.callback === "function") { - try { - command_obj.callback(err); - } catch (callback_err) { - // if a callback throws an exception, re-throw it on a new stack so the parser can keep going - process.nextTick(function () { - throw callback_err; - }); - } - } else { - console.log("node_redis: no callback to send error: " + err.message); - // this will probably not make it anywhere useful, but we might as well throw - process.nextTick(function () { - throw err; - }); - } -}; - -// if a callback throws an exception, re-throw it on a new stack so the parser can keep going. -// if a domain is active, emit the error on the domain, which will serve the same function. -// put this try/catch in its own function because V8 doesn't optimize this well yet. -function try_callback(callback, reply) { - try { - callback(null, reply); - } catch (err) { - if (process.domain) { - var currDomain = process.domain; - currDomain.emit('error', err); - if (process.domain === currDomain) { - currDomain.exit(); - } - } else { - process.nextTick(function () { - throw err; - }); - } - } -} - -// hgetall converts its replies to an Object. If the reply is empty, null is returned. -function reply_to_object(reply) { - var obj = {}, j, jl, key, val; - - if (reply.length === 0) { - return null; - } - - for (j = 0, jl = reply.length; j < jl; j += 2) { - key = reply[j].toString('binary'); - val = reply[j + 1]; - obj[key] = val; - } - - return obj; -} - -function reply_to_strings(reply) { - var i; - - if (Buffer.isBuffer(reply)) { - return reply.toString(); - } - - if (Array.isArray(reply)) { - for (i = 0; i < reply.length; i++) { - if (reply[i] !== null && reply[i] !== undefined) { - reply[i] = reply[i].toString(); - } - } - return reply; - } - - return reply; -} - -RedisClient.prototype.return_reply = function (reply) { - var command_obj, len, type, timestamp, argindex, args, queue_len; - - // If the "reply" here is actually a message received asynchronously due to a - // pubsub subscription, don't pop the command queue as we'll only be consuming - // the head command prematurely. - if (Array.isArray(reply) && reply.length > 0 && reply[0]) { - type = reply[0].toString(); - } - - if (this.pub_sub_mode && (type == 'message' || type == 'pmessage')) { - trace("received pubsub message"); - } - else { - command_obj = this.command_queue.shift(); - } - - queue_len = this.command_queue.getLength(); - - if (this.pub_sub_mode === false && queue_len === 0) { - this.command_queue = new Queue(); // explicitly reclaim storage from old Queue - this.emit("idle"); - } - if (this.should_buffer && queue_len <= this.command_queue_low_water) { - this.emit("drain"); - this.should_buffer = false; - } - - if (command_obj && !command_obj.sub_command) { - if (typeof command_obj.callback === "function") { - if (this.options.detect_buffers && command_obj.buffer_args === false) { - // If detect_buffers option was specified, then the reply from the parser will be Buffers. - // If this command did not use Buffer arguments, then convert the reply to Strings here. - reply = reply_to_strings(reply); - } - - // TODO - confusing and error-prone that hgetall is special cased in two places - if (reply && 'hgetall' === command_obj.command.toLowerCase()) { - reply = reply_to_object(reply); - } - - try_callback(command_obj.callback, reply); - } else if (exports.debug_mode) { - console.log("no callback for reply: " + (reply && reply.toString && reply.toString())); - } - } else if (this.pub_sub_mode || (command_obj && command_obj.sub_command)) { - if (Array.isArray(reply)) { - type = reply[0].toString(); - - if (type === "message") { - this.emit("message", reply[1].toString(), reply[2]); // channel, message - } else if (type === "pmessage") { - this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message - } else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") { - if (reply[2] === 0) { - this.pub_sub_mode = false; - if (this.debug_mode) { - console.log("All subscriptions removed, exiting pub/sub mode"); - } - } else { - this.pub_sub_mode = true; - } - // subscribe commands take an optional callback and also emit an event, but only the first response is included in the callback - // TODO - document this or fix it so it works in a more obvious way - // reply[1] can be null - var reply1String = (reply[1] === null) ? null : reply[1].toString(); - if (command_obj && typeof command_obj.callback === "function") { - try_callback(command_obj.callback, reply1String); - } - this.emit(type, reply1String, reply[2]); // channel, count - } else { - throw new Error("subscriptions are active but got unknown reply type " + type); - } - } else if (! this.closing) { - throw new Error("subscriptions are active but got an invalid reply: " + reply); - } - } else if (this.monitoring) { - len = reply.indexOf(" "); - timestamp = reply.slice(0, len); - argindex = reply.indexOf('"'); - args = reply.slice(argindex + 1, -1).split('" "').map(function (elem) { - return elem.replace(/\\"/g, '"'); - }); - this.emit("monitor", timestamp, args); - } else { - throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); - } -}; - -// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using -// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots. -function Command(command, args, sub_command, buffer_args, callback) { - this.command = command; - this.args = args; - this.sub_command = sub_command; - this.buffer_args = buffer_args; - this.callback = callback; -} - -RedisClient.prototype.send_command = function (command, args, callback) { - var arg, command_obj, i, il, elem_count, buffer_args, stream = this.stream, command_str = "", buffered_writes = 0, last_arg_type, lcaseCommand; - - if (typeof command !== "string") { - throw new Error("First argument to send_command must be the command name string, not " + typeof command); - } - - if (Array.isArray(args)) { - if (typeof callback === "function") { - // probably the fastest way: - // client.command([arg1, arg2], cb); (straight passthrough) - // send_command(command, [arg1, arg2], cb); - } else if (! callback) { - // most people find this variable argument length form more convenient, but it uses arguments, which is slower - // client.command(arg1, arg2, cb); (wraps up arguments into an array) - // send_command(command, [arg1, arg2, cb]); - // client.command(arg1, arg2); (callback is optional) - // send_command(command, [arg1, arg2]); - // client.command(arg1, arg2, undefined); (callback is undefined) - // send_command(command, [arg1, arg2, undefined]); - last_arg_type = typeof args[args.length - 1]; - if (last_arg_type === "function" || last_arg_type === "undefined") { - callback = args.pop(); - } - } else { - throw new Error("send_command: last argument must be a callback or undefined"); - } - } else { - throw new Error("send_command: second argument must be an array"); - } - - if (callback && process.domain) callback = process.domain.bind(callback); - - // if the last argument is an array and command is sadd or srem, expand it out: - // client.sadd(arg1, [arg2, arg3, arg4], cb); - // converts to: - // client.sadd(arg1, arg2, arg3, arg4, cb); - lcaseCommand = command.toLowerCase(); - if ((lcaseCommand === 'sadd' || lcaseCommand === 'srem') && args.length > 0 && Array.isArray(args[args.length - 1])) { - args = args.slice(0, -1).concat(args[args.length - 1]); - } - - // if the value is undefined or null and command is set or setx, need not to send message to redis - if (command === 'set' || command === 'setex') { - if(args[args.length - 1] === undefined || args[args.length - 1] === null) { - var err = new Error('send_command: ' + command + ' value must not be undefined or null'); - return callback && callback(err); - } - } - - buffer_args = false; - for (i = 0, il = args.length, arg; i < il; i += 1) { - if (Buffer.isBuffer(args[i])) { - buffer_args = true; - } - } - - command_obj = new Command(command, args, false, buffer_args, callback); - - if ((!this.ready && !this.send_anyway) || !stream.writable) { - if (exports.debug_mode) { - if (!stream.writable) { - console.log("send command: stream is not writeable."); - } - } - - if (this.enable_offline_queue) { - if (exports.debug_mode) { - console.log("Queueing " + command + " for next server connection."); - } - this.offline_queue.push(command_obj); - this.should_buffer = true; - } else { - var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false'); - if (command_obj.callback) { - command_obj.callback(not_writeable_error); - } else { - throw not_writeable_error; - } - } - - return false; - } - - if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") { - this.pub_sub_command(command_obj); - } else if (command === "monitor") { - this.monitoring = true; - } else if (command === "quit") { - this.closing = true; - } else if (this.pub_sub_mode === true) { - throw new Error("Connection in subscriber mode, only subscriber commands may be used"); - } - this.command_queue.push(command_obj); - this.commands_sent += 1; - - elem_count = args.length + 1; - - // Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg. - // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer. - - command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n"; - - if (! buffer_args) { // Build up a string and send entire command in one write - for (i = 0, il = args.length, arg; i < il; i += 1) { - arg = args[i]; - if (typeof arg !== "string") { - arg = String(arg); - } - command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"; - } - if (exports.debug_mode) { - console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str); - } - buffered_writes += !stream.write(command_str); - } else { - if (exports.debug_mode) { - console.log("send command (" + command_str + ") has Buffer arguments"); - } - buffered_writes += !stream.write(command_str); - - for (i = 0, il = args.length, arg; i < il; i += 1) { - arg = args[i]; - if (!(Buffer.isBuffer(arg) || arg instanceof String)) { - arg = String(arg); - } - - if (Buffer.isBuffer(arg)) { - if (arg.length === 0) { - if (exports.debug_mode) { - console.log("send_command: using empty string for 0 length buffer"); - } - buffered_writes += !stream.write("$0\r\n\r\n"); - } else { - buffered_writes += !stream.write("$" + arg.length + "\r\n"); - buffered_writes += !stream.write(arg); - buffered_writes += !stream.write("\r\n"); - if (exports.debug_mode) { - console.log("send_command: buffer send " + arg.length + " bytes"); - } - } - } else { - if (exports.debug_mode) { - console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg); - } - buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"); - } - } - } - if (exports.debug_mode) { - console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer); - } - if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) { - this.should_buffer = true; - } - return !this.should_buffer; -}; - -RedisClient.prototype.pub_sub_command = function (command_obj) { - var i, key, command, args; - - if (this.pub_sub_mode === false && exports.debug_mode) { - console.log("Entering pub/sub mode from " + command_obj.command); - } - this.pub_sub_mode = true; - command_obj.sub_command = true; - - command = command_obj.command; - args = command_obj.args; - if (command === "subscribe" || command === "psubscribe") { - if (command === "subscribe") { - key = "sub"; - } else { - key = "psub"; - } - for (i = 0; i < args.length; i++) { - this.subscription_set[key + " " + args[i]] = true; - } - } else { - if (command === "unsubscribe") { - key = "sub"; - } else { - key = "psub"; - } - for (i = 0; i < args.length; i++) { - delete this.subscription_set[key + " " + args[i]]; - } - } -}; - -RedisClient.prototype.end = function () { - this.stream._events = {}; - - //clear retry_timer - if(this.retry_timer){ - clearTimeout(this.retry_timer); - this.retry_timer=null; - } - this.stream.on("error", function(){}); - - this.connected = false; - this.ready = false; - this.closing = true; - return this.stream.destroySoon(); -}; - -function Multi(client, args) { - this._client = client; - this.queue = [["MULTI"]]; - if (Array.isArray(args)) { - this.queue = this.queue.concat(args); - } -} - -exports.Multi = Multi; - -// take 2 arrays and return the union of their elements -function set_union(seta, setb) { - var obj = {}; - - seta.forEach(function (val) { - obj[val] = true; - }); - setb.forEach(function (val) { - obj[val] = true; - }); - return Object.keys(obj); -} - -// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js -commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr", - "incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex", - "lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore", - "sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore", - "zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx", - "hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx", - "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave", - "bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl", - "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster", - "restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands")); - -commands.forEach(function (fullCommand) { - var command = fullCommand.split(' ')[0]; - - RedisClient.prototype[command] = function (args, callback) { - if (Array.isArray(args) && typeof callback === "function") { - return this.send_command(command, args, callback); - } else { - return this.send_command(command, to_array(arguments)); - } - }; - RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command]; - - Multi.prototype[command] = function () { - this.queue.push([command].concat(to_array(arguments))); - return this; - }; - Multi.prototype[command.toUpperCase()] = Multi.prototype[command]; -}); - -// store db in this.select_db to restore it on reconnect -RedisClient.prototype.select = function (db, callback) { - var self = this; - - this.send_command('select', [db], function (err, res) { - if (err === null) { - self.selected_db = db; - } - if (typeof(callback) === 'function') { - callback(err, res); - } else if (err) { - self.emit('error', err); - } - }); -}; -RedisClient.prototype.SELECT = RedisClient.prototype.select; - -// Stash auth for connect and reconnect. Send immediately if already connected. -RedisClient.prototype.auth = function () { - var args = to_array(arguments); - this.auth_pass = args[0]; - this.auth_callback = args[1]; - if (exports.debug_mode) { - console.log("Saving auth as " + this.auth_pass); - } - - if (this.connected) { - this.send_command("auth", args); - } -}; -RedisClient.prototype.AUTH = RedisClient.prototype.auth; - -RedisClient.prototype.hmget = function (arg1, arg2, arg3) { - if (Array.isArray(arg2) && typeof arg3 === "function") { - return this.send_command("hmget", [arg1].concat(arg2), arg3); - } else if (Array.isArray(arg1) && typeof arg2 === "function") { - return this.send_command("hmget", arg1, arg2); - } else { - return this.send_command("hmget", to_array(arguments)); - } -}; -RedisClient.prototype.HMGET = RedisClient.prototype.hmget; - -RedisClient.prototype.hmset = function (args, callback) { - var tmp_args, tmp_keys, i, il, key; - - if (Array.isArray(args) && typeof callback === "function") { - return this.send_command("hmset", args, callback); - } - - args = to_array(arguments); - if (typeof args[args.length - 1] === "function") { - callback = args[args.length - 1]; - args.length -= 1; - } else { - callback = null; - } - - if (args.length === 2 && (typeof args[0] === "string" || typeof args[0] === "number") && typeof args[1] === "object") { - // User does: client.hmset(key, {key1: val1, key2: val2}) - // assuming key is a string, i.e. email address - - // if key is a number, i.e. timestamp, convert to string - if (typeof args[0] === "number") { - args[0] = args[0].toString(); - } - - tmp_args = [ args[0] ]; - tmp_keys = Object.keys(args[1]); - for (i = 0, il = tmp_keys.length; i < il ; i++) { - key = tmp_keys[i]; - tmp_args.push(key); - tmp_args.push(args[1][key]); - } - args = tmp_args; - } - - return this.send_command("hmset", args, callback); -}; -RedisClient.prototype.HMSET = RedisClient.prototype.hmset; - -Multi.prototype.hmset = function () { - var args = to_array(arguments), tmp_args; - if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") { - tmp_args = [ "hmset", args[0] ]; - Object.keys(args[1]).map(function (key) { - tmp_args.push(key); - tmp_args.push(args[1][key]); - }); - if (args[2]) { - tmp_args.push(args[2]); - } - args = tmp_args; - } else { - args.unshift("hmset"); - } - - this.queue.push(args); - return this; -}; -Multi.prototype.HMSET = Multi.prototype.hmset; - -Multi.prototype.exec = function (callback) { - var self = this; - var errors = []; - // drain queue, callback will catch "QUEUED" or error - // TODO - get rid of all of these anonymous functions which are elegant but slow - this.queue.forEach(function (args, index) { - var command = args[0], obj; - if (typeof args[args.length - 1] === "function") { - args = args.slice(1, -1); - } else { - args = args.slice(1); - } - if (args.length === 1 && Array.isArray(args[0])) { - args = args[0]; - } - if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') { - obj = args.pop(); - Object.keys(obj).forEach(function (key) { - args.push(key); - args.push(obj[key]); - }); - } - this._client.send_command(command, args, function (err, reply) { - if (err) { - var cur = self.queue[index]; - if (typeof cur[cur.length - 1] === "function") { - cur[cur.length - 1](err); - } else { - errors.push(new Error(err)); - } - } - }); - }, this); - - // TODO - make this callback part of Multi.prototype instead of creating it each time - return this._client.send_command("EXEC", [], function (err, replies) { - if (err) { - if (callback) { - errors.push(new Error(err)); - callback(errors); - return; - } else { - throw new Error(err); - } - } - - var i, il, reply, args; - - if (replies) { - for (i = 1, il = self.queue.length; i < il; i += 1) { - reply = replies[i - 1]; - args = self.queue[i]; - - // TODO - confusing and error-prone that hgetall is special cased in two places - if (reply && args[0].toLowerCase() === "hgetall") { - replies[i - 1] = reply = reply_to_object(reply); - } - - if (typeof args[args.length - 1] === "function") { - args[args.length - 1](null, reply); - } - } - } - - if (callback) { - callback(null, replies); - } - }); -}; -Multi.prototype.EXEC = Multi.prototype.exec; - -RedisClient.prototype.multi = function (args) { - return new Multi(this, args); -}; -RedisClient.prototype.MULTI = function (args) { - return new Multi(this, args); -}; - - -// stash original eval method -var eval_orig = RedisClient.prototype.eval; -// hook eval with an attempt to evalsha for cached scripts -RedisClient.prototype.eval = RedisClient.prototype.EVAL = function () { - var self = this, - args = to_array(arguments), - callback; - - if (typeof args[args.length - 1] === "function") { - callback = args.pop(); - } - - if (Array.isArray(args[0])) { - args = args[0]; - } - - // replace script source with sha value - var source = args[0]; - args[0] = crypto.createHash("sha1").update(source).digest("hex"); - - self.evalsha(args, function (err, reply) { - if (err && /NOSCRIPT/.test(err.message)) { - args[0] = source; - eval_orig.call(self, args, callback); - - } else if (callback) { - callback(err, reply); - } - }); -}; - - -exports.createClient = function (port_arg, host_arg, options) { - - var cnxFamily; - - if (options && options.family) { - cnxFamily = (options.family == 'IPv6' ? 6 : 4); - } - - var cnxOptions = { - 'port' : port_arg || default_port, - 'host' : host_arg || default_host, - 'family' : cnxFamily || '4' - }; - - var redis_client, net_client; - - net_client = net.createConnection(cnxOptions); - - redis_client = new RedisClient(net_client, options); - - redis_client.port = cnxOptions.port; - redis_client.host = cnxOptions.host; - - return redis_client; -}; - -exports.print = function (err, reply) { - if (err) { - console.log("Error: " + err); - } else { - console.log("Reply: " + reply); - } -}; diff --git a/labs/node_modules/redis/lib/commands.js b/labs/node_modules/redis/lib/commands.js deleted file mode 100644 index b0365350cd..0000000000 --- a/labs/node_modules/redis/lib/commands.js +++ /dev/null @@ -1,163 +0,0 @@ -// This file was generated by ./generate_commands.js on Wed Apr 23 2014 14:51:21 GMT-0700 (PDT) -module.exports = [ - "append", - "auth", - "bgrewriteaof", - "bgsave", - "bitcount", - "bitop", - "bitpos", - "blpop", - "brpop", - "brpoplpush", - "client kill", - "client list", - "client getname", - "client pause", - "client setname", - "config get", - "config rewrite", - "config set", - "config resetstat", - "dbsize", - "debug object", - "debug segfault", - "decr", - "decrby", - "del", - "discard", - "dump", - "echo", - "eval", - "evalsha", - "exec", - "exists", - "expire", - "expireat", - "flushall", - "flushdb", - "get", - "getbit", - "getrange", - "getset", - "hdel", - "hexists", - "hget", - "hgetall", - "hincrby", - "hincrbyfloat", - "hkeys", - "hlen", - "hmget", - "hmset", - "hset", - "hsetnx", - "hvals", - "incr", - "incrby", - "incrbyfloat", - "info", - "keys", - "lastsave", - "lindex", - "linsert", - "llen", - "lpop", - "lpush", - "lpushx", - "lrange", - "lrem", - "lset", - "ltrim", - "mget", - "migrate", - "monitor", - "move", - "mset", - "msetnx", - "multi", - "object", - "persist", - "pexpire", - "pexpireat", - "pfadd", - "pfcount", - "pfmerge", - "ping", - "psetex", - "psubscribe", - "pubsub", - "pttl", - "publish", - "punsubscribe", - "quit", - "randomkey", - "rename", - "renamenx", - "restore", - "rpop", - "rpoplpush", - "rpush", - "rpushx", - "sadd", - "save", - "scard", - "script exists", - "script flush", - "script kill", - "script load", - "sdiff", - "sdiffstore", - "select", - "set", - "setbit", - "setex", - "setnx", - "setrange", - "shutdown", - "sinter", - "sinterstore", - "sismember", - "slaveof", - "slowlog", - "smembers", - "smove", - "sort", - "spop", - "srandmember", - "srem", - "strlen", - "subscribe", - "sunion", - "sunionstore", - "sync", - "time", - "ttl", - "type", - "unsubscribe", - "unwatch", - "watch", - "zadd", - "zcard", - "zcount", - "zincrby", - "zinterstore", - "zlexcount", - "zrange", - "zrangebylex", - "zrangebyscore", - "zrank", - "zrem", - "zremrangebylex", - "zremrangebyrank", - "zremrangebyscore", - "zrevrange", - "zrevrangebyscore", - "zrevrank", - "zscore", - "zunionstore", - "scan", - "sscan", - "hscan", - "zscan" -]; diff --git a/labs/node_modules/redis/lib/parser/hiredis.js b/labs/node_modules/redis/lib/parser/hiredis.js deleted file mode 100644 index 940bfeeb76..0000000000 --- a/labs/node_modules/redis/lib/parser/hiredis.js +++ /dev/null @@ -1,46 +0,0 @@ -var events = require("events"), - util = require("../util"), - hiredis = require("hiredis"); - -exports.debug_mode = false; -exports.name = "hiredis"; - -function HiredisReplyParser(options) { - this.name = exports.name; - this.options = options || {}; - this.reset(); - events.EventEmitter.call(this); -} - -util.inherits(HiredisReplyParser, events.EventEmitter); - -exports.Parser = HiredisReplyParser; - -HiredisReplyParser.prototype.reset = function () { - this.reader = new hiredis.Reader({ - return_buffers: this.options.return_buffers || false - }); -}; - -HiredisReplyParser.prototype.execute = function (data) { - var reply; - this.reader.feed(data); - while (true) { - try { - reply = this.reader.get(); - } catch (err) { - this.emit("error", err); - break; - } - - if (reply === undefined) { - break; - } - - if (reply && reply.constructor === Error) { - this.emit("reply error", reply); - } else { - this.emit("reply", reply); - } - } -}; diff --git a/labs/node_modules/redis/lib/parser/javascript.js b/labs/node_modules/redis/lib/parser/javascript.js deleted file mode 100644 index 0990cc098d..0000000000 --- a/labs/node_modules/redis/lib/parser/javascript.js +++ /dev/null @@ -1,301 +0,0 @@ -var events = require("events"), - util = require("../util"); - -function Packet(type, size) { - this.type = type; - this.size = +size; -} - -exports.name = "javascript"; -exports.debug_mode = false; - -function ReplyParser(options) { - this.name = exports.name; - this.options = options || { }; - - this._buffer = null; - this._offset = 0; - this._encoding = "utf-8"; - this._debug_mode = options.debug_mode; - this._reply_type = null; -} - -util.inherits(ReplyParser, events.EventEmitter); - -exports.Parser = ReplyParser; - -function IncompleteReadBuffer(message) { - this.name = "IncompleteReadBuffer"; - this.message = message; -} -util.inherits(IncompleteReadBuffer, Error); - -// Buffer.toString() is quite slow for small strings -function small_toString(buf, start, end) { - var tmp = "", i; - - for (i = start; i < end; i++) { - tmp += String.fromCharCode(buf[i]); - } - - return tmp; -} - -ReplyParser.prototype._parseResult = function (type) { - var start, end, offset, packetHeader; - - if (type === 43 || type === 45) { // + or - - // up to the delimiter - end = this._packetEndOffset() - 1; - start = this._offset; - - // include the delimiter - this._offset = end + 2; - - if (end > this._buffer.length) { - this._offset = start; - throw new IncompleteReadBuffer("Wait for more data."); - } - - if (this.options.return_buffers) { - return this._buffer.slice(start, end); - } else { - if (end - start < 65536) { // completely arbitrary - return small_toString(this._buffer, start, end); - } else { - return this._buffer.toString(this._encoding, start, end); - } - } - } else if (type === 58) { // : - // up to the delimiter - end = this._packetEndOffset() - 1; - start = this._offset; - - // include the delimiter - this._offset = end + 2; - - if (end > this._buffer.length) { - this._offset = start; - throw new IncompleteReadBuffer("Wait for more data."); - } - - if (this.options.return_buffers) { - return this._buffer.slice(start, end); - } - - // return the coerced numeric value - return +small_toString(this._buffer, start, end); - } else if (type === 36) { // $ - // set a rewind point, as the packet could be larger than the - // buffer in memory - offset = this._offset - 1; - - packetHeader = new Packet(type, this.parseHeader()); - - // packets with a size of -1 are considered null - if (packetHeader.size === -1) { - return undefined; - } - - end = this._offset + packetHeader.size; - start = this._offset; - - // set the offset to after the delimiter - this._offset = end + 2; - - if (end > this._buffer.length) { - this._offset = offset; - throw new IncompleteReadBuffer("Wait for more data."); - } - - if (this.options.return_buffers) { - return this._buffer.slice(start, end); - } else { - return this._buffer.toString(this._encoding, start, end); - } - } else if (type === 42) { // * - offset = this._offset; - packetHeader = new Packet(type, this.parseHeader()); - - if (packetHeader.size < 0) { - return null; - } - - if (packetHeader.size > this._bytesRemaining()) { - this._offset = offset - 1; - throw new IncompleteReadBuffer("Wait for more data."); - } - - var reply = [ ]; - var ntype, i, res; - - offset = this._offset - 1; - - for (i = 0; i < packetHeader.size; i++) { - ntype = this._buffer[this._offset++]; - - if (this._offset > this._buffer.length) { - throw new IncompleteReadBuffer("Wait for more data."); - } - res = this._parseResult(ntype); - if (res === undefined) { - res = null; - } - reply.push(res); - } - - return reply; - } -}; - -ReplyParser.prototype.execute = function (buffer) { - this.append(buffer); - - var type, ret, offset; - - while (true) { - offset = this._offset; - try { - // at least 4 bytes: :1\r\n - if (this._bytesRemaining() < 4) { - break; - } - - type = this._buffer[this._offset++]; - - if (type === 43) { // + - ret = this._parseResult(type); - - if (ret === null) { - break; - } - - this.send_reply(ret); - } else if (type === 45) { // - - ret = this._parseResult(type); - - if (ret === null) { - break; - } - - this.send_error(ret); - } else if (type === 58) { // : - ret = this._parseResult(type); - - if (ret === null) { - break; - } - - this.send_reply(ret); - } else if (type === 36) { // $ - ret = this._parseResult(type); - - if (ret === null) { - break; - } - - // check the state for what is the result of - // a -1, set it back up for a null reply - if (ret === undefined) { - ret = null; - } - - this.send_reply(ret); - } else if (type === 42) { // * - // set a rewind point. if a failure occurs, - // wait for the next execute()/append() and try again - offset = this._offset - 1; - - ret = this._parseResult(type); - - this.send_reply(ret); - } - } catch (err) { - // catch the error (not enough data), rewind, and wait - // for the next packet to appear - if (! (err instanceof IncompleteReadBuffer)) { - throw err; - } - this._offset = offset; - break; - } - } -}; - -ReplyParser.prototype.append = function (newBuffer) { - if (!newBuffer) { - return; - } - - // first run - if (this._buffer === null) { - this._buffer = newBuffer; - - return; - } - - // out of data - if (this._offset >= this._buffer.length) { - this._buffer = newBuffer; - this._offset = 0; - - return; - } - - // very large packet - // check for concat, if we have it, use it - if (Buffer.concat !== undefined) { - this._buffer = Buffer.concat([this._buffer.slice(this._offset), newBuffer]); - } else { - var remaining = this._bytesRemaining(), - newLength = remaining + newBuffer.length, - tmpBuffer = new Buffer(newLength); - - this._buffer.copy(tmpBuffer, 0, this._offset); - newBuffer.copy(tmpBuffer, remaining, 0); - - this._buffer = tmpBuffer; - } - - this._offset = 0; -}; - -ReplyParser.prototype.parseHeader = function () { - var end = this._packetEndOffset(), - value = small_toString(this._buffer, this._offset, end - 1); - - this._offset = end + 1; - - return value; -}; - -ReplyParser.prototype._packetEndOffset = function () { - var offset = this._offset; - - while (this._buffer[offset] !== 0x0d && this._buffer[offset + 1] !== 0x0a) { - offset++; - - if (offset >= this._buffer.length) { - throw new IncompleteReadBuffer("didn't see LF after NL reading multi bulk count (" + offset + " => " + this._buffer.length + ", " + this._offset + ")"); - } - } - - offset++; - return offset; -}; - -ReplyParser.prototype._bytesRemaining = function () { - return (this._buffer.length - this._offset) < 0 ? 0 : (this._buffer.length - this._offset); -}; - -ReplyParser.prototype.parser_error = function (message) { - this.emit("error", message); -}; - -ReplyParser.prototype.send_error = function (reply) { - this.emit("reply error", reply); -}; - -ReplyParser.prototype.send_reply = function (reply) { - this.emit("reply", reply); -}; diff --git a/labs/node_modules/redis/lib/queue.js b/labs/node_modules/redis/lib/queue.js deleted file mode 100644 index 3fc87ab102..0000000000 --- a/labs/node_modules/redis/lib/queue.js +++ /dev/null @@ -1,59 +0,0 @@ -// Queue class adapted from Tim Caswell's pattern library -// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js - -function Queue() { - this.tail = []; - this.head = []; - this.offset = 0; -} - -Queue.prototype.shift = function () { - if (this.offset === this.head.length) { - var tmp = this.head; - tmp.length = 0; - this.head = this.tail; - this.tail = tmp; - this.offset = 0; - if (this.head.length === 0) { - return; - } - } - return this.head[this.offset++]; // sorry, JSLint -}; - -Queue.prototype.push = function (item) { - return this.tail.push(item); -}; - -Queue.prototype.forEach = function (fn, thisv) { - var array = this.head.slice(this.offset), i, il; - - array.push.apply(array, this.tail); - - if (thisv) { - for (i = 0, il = array.length; i < il; i += 1) { - fn.call(thisv, array[i], i, array); - } - } else { - for (i = 0, il = array.length; i < il; i += 1) { - fn(array[i], i, array); - } - } - - return array; -}; - -Queue.prototype.getLength = function () { - return this.head.length - this.offset + this.tail.length; -}; - -Object.defineProperty(Queue.prototype, "length", { - get: function () { - return this.getLength(); - } -}); - - -if (typeof module !== "undefined" && module.exports) { - module.exports = Queue; -} diff --git a/labs/node_modules/redis/lib/to_array.js b/labs/node_modules/redis/lib/to_array.js deleted file mode 100644 index 88a57e18a4..0000000000 --- a/labs/node_modules/redis/lib/to_array.js +++ /dev/null @@ -1,12 +0,0 @@ -function to_array(args) { - var len = args.length, - arr = new Array(len), i; - - for (i = 0; i < len; i += 1) { - arr[i] = args[i]; - } - - return arr; -} - -module.exports = to_array; diff --git a/labs/node_modules/redis/lib/util.js b/labs/node_modules/redis/lib/util.js deleted file mode 100644 index fc255ae953..0000000000 --- a/labs/node_modules/redis/lib/util.js +++ /dev/null @@ -1,11 +0,0 @@ -// Support for very old versions of node where the module was called "sys". At some point, we should abandon this. - -var util; - -try { - util = require("util"); -} catch (err) { - util = require("sys"); -} - -module.exports = util; diff --git a/labs/node_modules/redis/package.json b/labs/node_modules/redis/package.json deleted file mode 100644 index 4ced92cacf..0000000000 --- a/labs/node_modules/redis/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "redis", - "version": "0.11.0", - "description": "Redis client library", - "keywords": [ - "redis", - "database" - ], - "author": { - "name": "Matt Ranney", - "email": "mjr@ranney.com" - }, - "main": "./index.js", - "scripts": { - "test": "node ./test.js" - }, - "devDependencies": { - "metrics": ">=0.1.5", - "colors": "~0.6.0-1", - "underscore": "~1.4.4" - }, - "repository": { - "type": "git", - "url": "git://github.com/mranney/node_redis.git" - }, - "readme": "redis - a node.js redis client\n===========================\n\nThis is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from\nexperimental Redis server branches.\n\n\nInstall with:\n\n npm install redis\n\nPieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:\n\n npm install hiredis redis\n\nIf `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.\n\nIf you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can\nhappen between node and native code modules after a node upgrade.\n\n\n## Usage\n\nSimple example, included as `examples/simple.js`:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n // if you'd like to select database 3, instead of 0 (default), call\n // client.select(3, function() { /* ... */ });\n\n client.on(\"error\", function (err) {\n console.log(\"Error \" + err);\n });\n\n client.set(\"string key\", \"string val\", redis.print);\n client.hset(\"hash key\", \"hashtest 1\", \"some value\", redis.print);\n client.hset([\"hash key\", \"hashtest 2\", \"some other value\"], redis.print);\n client.hkeys(\"hash key\", function (err, replies) {\n console.log(replies.length + \" replies:\");\n replies.forEach(function (reply, i) {\n console.log(\" \" + i + \": \" + reply);\n });\n client.quit();\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node example.js\n Reply: OK\n Reply: 0\n Reply: 0\n 2 replies:\n 0: hashtest 1\n 1: hashtest 2\n mjr:~/work/node_redis (master)$\n\n\n## Performance\n\nHere are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.\nIt uses 50 concurrent connections with no pipelining.\n\nJavaScript parser:\n\n PING: 20000 ops 42283.30 ops/sec 0/5/1.182\n SET: 20000 ops 32948.93 ops/sec 1/7/1.515\n GET: 20000 ops 28694.40 ops/sec 0/9/1.740\n INCR: 20000 ops 39370.08 ops/sec 0/8/1.269\n LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370\n LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048\n LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072\n\nhiredis parser:\n\n PING: 20000 ops 46189.38 ops/sec 1/4/1.082\n SET: 20000 ops 41237.11 ops/sec 0/6/1.210\n GET: 20000 ops 39682.54 ops/sec 1/7/1.257\n INCR: 20000 ops 40080.16 ops/sec 0/8/1.242\n LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212\n LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363\n LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287\n\nThe performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.\n\n\n### Sending Commands\n\nEach Redis command is exposed as a function on the `client` object.\nAll functions take either an `args` Array plus optional `callback` Function or\na variable number of individual arguments followed by an optional callback.\nHere is an example of passing an array of arguments and a callback:\n\n client.mset([\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\"], function (err, res) {});\n\nHere is that same call in the second style:\n\n client.mset(\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\", function (err, res) {});\n\nNote that in either form the `callback` is optional:\n\n client.set(\"some key\", \"some val\");\n client.set([\"some other key\", \"some val\"]);\n\nIf the key is missing, reply will be null (probably):\n\n client.get(\"missingkey\", function(err, reply) {\n // reply is null when the key is missing\n console.log(reply);\n });\n\nFor a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)\n\nThe commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.\n\nMinimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,\ninteger replies return JavaScript Numbers, \"bulk\" replies return node Buffers, and \"multi bulk\" replies return a\nJavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.\n\n# API\n\n## Connection Events\n\n`client` will emit some events about the state of the connection to the Redis server.\n\n### \"ready\"\n\n`client` will emit `ready` a connection is established to the Redis server and the server reports\nthat it is ready to receive commands. Commands issued before the `ready` event are queued,\nthen replayed just before this event is emitted.\n\n### \"connect\"\n\n`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`\nis set. If this options is set, `connect` will be emitted when the stream is connected, and then\nyou are free to try to send commands.\n\n### \"error\"\n\n`client` will emit `error` when encountering an error connecting to the Redis server.\n\nNote that \"error\" is a special event type in node. If there are no listeners for an\n\"error\" event, node will exit. This is usually what you want, but it can lead to some\ncryptic error messages like this:\n\n mjr:~/work/node_redis (master)$ node example.js\n\n node.js:50\n throw e;\n ^\n Error: ECONNREFUSED, Connection refused\n at IOWatcher.callback (net:870:22)\n at node.js:607:9\n\nNot very useful in diagnosing the problem, but if your program isn't ready to handle this,\nit is probably the right thing to just exit.\n\n`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.\nIt would be nice to distinguish these two cases.\n\n### \"end\"\n\n`client` will emit `end` when an established Redis server connection has closed.\n\n### \"drain\"\n\n`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now\nwritable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,\nyou need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can\nresume sending when you get `drain`.\n\n### \"idle\"\n\n`client` will emit `idle` when there are no outstanding commands that are awaiting a response.\n\n## redis.createClient(port, host, options)\n\nCreate a new client connection. `port` defaults to `6379` and `host` defaults\nto `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for\nport and host are probably fine. `options` in an object with the following possible properties:\n\n* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.\nThis may also be set to `javascript`.\n* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer\nobjects instead of JavaScript Strings.\n* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects\nif any of the input arguments to the original command were Buffer objects.\nThis option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to\nevery command on a client.\n* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the\nNagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the\ncost of more latency. Most applications will want this set to `true`.\n* `socket_keepalive` defaults to `true`. Whether the keep-alive functionality is enabled on the underlying socket. \n* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still\nbe loading the database from disk. While loading, the server not respond to any commands. To work around this,\n`node_redis` has a \"ready check\" which sends the `INFO` command to the server. The response from the `INFO` command\nindicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event.\nSetting `no_ready_check` to `true` will inhibit this check.\n* `enable_offline_queue`: defaults to `true`. By default, if there is no active\nconnection to the redis server, commands are added to a queue and are executed\nonce the connection has been established. Setting `enable_offline_queue` to\n`false` will disable this feature and the callback will be execute immediately\nwith an error, or an error will be thrown if no callback is specified.\n* `retry_max_delay`: defaults to `null`. By default every time the client tries to connect and fails time before\nreconnection (delay) almost doubles. This delay normally grows infinitely, but setting `retry_max_delay` limits delay\nto maximum value, provided in milliseconds.\n* `connect_timeout` defaults to `false`. By default client will try reconnecting until connected. Setting `connect_timeout`\nlimits total time for client to reconnect. Value is provided in milliseconds and is counted once the disconnect occured.\n* `max_attempts` defaults to `null`. By default client will try reconnecting until connected. Setting `max_attempts`\nlimits total amount of reconnects.\n* `auth_pass` defaults to `null`. By default client will try connecting without auth. If set, client will run redis auth command on connect.\n* `family` defaults to `IPv4`. The client connects in IPv4 if not specified or if the DNS resolution returns an IPv4 address. \nYou can force an IPv6 if you set the family to 'IPv6'. See nodejs net or dns modules how to use the family type. \n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(null, null, {detect_buffers: true});\n\n client.set(\"foo_rand000000000000\", \"OK\");\n\n // This will return a JavaScript String\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString()); // Will print `OK`\n });\n\n // This will return a Buffer since original key is specified as a Buffer\n client.get(new Buffer(\"foo_rand000000000000\"), function (err, reply) {\n console.log(reply.toString()); // Will print ``\n });\n client.end();\n```\n\n`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.\n\n### Unix Domain Socket\n\nYou can also create a connection to Redis server via the unix domain socket if the server\nhas it enabled:\n\n```js\nvar redis = require(\"redis\");\nvar client = redis.createClient(\"/tmp/redis.sock\");\n```\n\nSample `redis.conf` configuration to enable unix domain socket listening:\n\n```conf\nunixsocket /tmp/redis.sock\nunixsocketperm 755\n```\n\nSee [issue #204](https://github.com/mranney/node_redis/issues/204) for more information.\n\n## client.auth(password, callback)\n\nWhen connecting to Redis servers that require authentication, the `AUTH` command must be sent as the\nfirst command after connecting. This can be tricky to coordinate with reconnections, the ready check,\netc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,\nincluding reconnections. `callback` is invoked only once, after the response to the very first\n`AUTH` command sent.\nNOTE: Your call to `client.auth()` should not be inside the ready handler. If\nyou are doing this wrong, `client` will emit an error that looks\nsomething like this `Error: Ready check failed: ERR operation not permitted`.\n\n## client.end()\n\nForcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.\nIf you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.\n\nThis example closes the connection to the Redis server before the replies have been read. You probably don't\nwant to do this:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString());\n });\n client.end();\n```\n\n`client.end()` is useful for timeout cases where something is stuck or taking too long and you want\nto start over.\n\n## client.unref()\n\nCall `unref()` on the underlying socket connection to the Redis server, allowing the program to exit once no more commands are pending.\n\nThis is an **experimental** feature, and only supports a subset of the Redis protocol. Any commands where client state is saved on the Redis server, e.g. `*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`.\n\n```js\nvar redis = require(\"redis\")\nvar client = redis.createClient()\n\n/*\n Calling unref() will allow this program to exit immediately after the get command finishes. Otherwise the client would hang as long as the client-server connection is alive.\n*/\nclient.unref()\nclient.get(\"foo\", function (err, value){\n if (err) throw(err)\n console.log(value)\n})\n```\n\n## Friendlier hash commands\n\nMost Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings.\nWhen dealing with hash values, there are a couple of useful exceptions to this.\n\n### client.hgetall(hash)\n\nThe reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact\nwith the responses using JavaScript syntax.\n\nExample:\n\n client.hmset(\"hosts\", \"mjr\", \"1\", \"another\", \"23\", \"home\", \"1234\");\n client.hgetall(\"hosts\", function (err, obj) {\n console.dir(obj);\n });\n\nOutput:\n\n { mjr: '1', another: '23', home: '1234' }\n\n### client.hmset(hash, obj, [callback])\n\nMultiple values in a hash can be set by supplying an object:\n\n client.HMSET(key2, {\n \"0123456789\": \"abcdefghij\", // NOTE: key and value will be coerced to strings\n \"some manner of key\": \"a type of value\"\n });\n\nThe properties and values of this Object will be set as keys and values in the Redis hash.\n\n### client.hmset(hash, key1, val1, ... keyn, valn, [callback])\n\nMultiple values may also be set by supplying a list:\n\n client.HMSET(key1, \"0123456789\", \"abcdefghij\", \"some manner of key\", \"a type of value\");\n\n\n## Publish / Subscribe\n\nHere is a simple example of the API for publish / subscribe. This program opens two\nclient connections, subscribes to a channel on one of them, and publishes to that\nchannel on the other:\n\n```js\n var redis = require(\"redis\"),\n client1 = redis.createClient(), client2 = redis.createClient(),\n msg_count = 0;\n\n client1.on(\"subscribe\", function (channel, count) {\n client2.publish(\"a nice channel\", \"I am sending a message.\");\n client2.publish(\"a nice channel\", \"I am sending a second message.\");\n client2.publish(\"a nice channel\", \"I am sending my last message.\");\n });\n\n client1.on(\"message\", function (channel, message) {\n console.log(\"client1 channel \" + channel + \": \" + message);\n msg_count += 1;\n if (msg_count === 3) {\n client1.unsubscribe();\n client1.end();\n client2.end();\n }\n });\n\n client1.incr(\"did a thing\");\n client1.subscribe(\"a nice channel\");\n```\n\nWhen a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into a \"subscriber\" mode.\nAt that point, only commands that modify the subscription set are valid. When the subscription\nset is empty, the connection is put back into regular mode.\n\nIf you need to send regular commands to Redis while in subscriber mode, just open another connection.\n\n## Subscriber Events\n\nIf a client has subscriptions active, it may emit these events:\n\n### \"message\" (channel, message)\n\nClient will emit `message` for every message received that matches an active subscription.\nListeners are passed the channel name as `channel` and the message Buffer as `message`.\n\n### \"pmessage\" (pattern, channel, message)\n\nClient will emit `pmessage` for every message received that matches an active subscription pattern.\nListeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel\nname as `channel`, and the message Buffer as `message`.\n\n### \"subscribe\" (channel, count)\n\nClient will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`.\n\n### \"psubscribe\" (pattern, count)\n\nClient will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the\noriginal pattern as `pattern`, and the new count of subscriptions for this client as `count`.\n\n### \"unsubscribe\" (channel, count)\n\nClient will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left subscriber mode and no more subscriber events will be emitted.\n\n### \"punsubscribe\" (pattern, count)\n\nClient will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left subscriber mode and no more subscriber events will be emitted.\n\n## client.multi([commands])\n\n`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by\nRedis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.\n\n```js\n var redis = require(\"./index\"),\n client = redis.createClient(), set_size = 20;\n\n client.sadd(\"bigset\", \"a member\");\n client.sadd(\"bigset\", \"another member\");\n\n while (set_size > 0) {\n client.sadd(\"bigset\", \"member \" + set_size);\n set_size -= 1;\n }\n\n // multi chain with an individual callback\n client.multi()\n .scard(\"bigset\")\n .smembers(\"bigset\")\n .keys(\"*\", function (err, replies) {\n // NOTE: code in this callback is NOT atomic\n // this only happens after the the .exec call finishes.\n client.mget(replies, redis.print);\n })\n .dbsize()\n .exec(function (err, replies) {\n console.log(\"MULTI got \" + replies.length + \" replies\");\n replies.forEach(function (reply, index) {\n console.log(\"Reply \" + index + \": \" + reply.toString());\n });\n });\n```\n\n### Multi.exec( callback )\n\n`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the\nsame command methods as `client` objects do. Commands are queued up inside the `Multi` object\nuntil `Multi.exec()` is invoked.\n\nThe `callback` of `.exec()` will get invoked with two arguments:\n\n* `err` **type:** `null | Array` err is either null or an array of Error Objects corresponding the the sequence the commands where chained. The last item of the array will always be an `EXECABORT` type of error originating from the `.exec()` itself.\n* `results` **type:** `null | Array` results is an array of responses corresponding the the sequence the commands where chained.\n\nYou can either chain together `MULTI` commands as in the above example, or you can queue individual\ncommands while still sending regular client command as in this example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n // start a separate multi command queue\n multi = client.multi();\n multi.incr(\"incr thing\", redis.print);\n multi.incr(\"incr other thing\", redis.print);\n\n // runs immediately\n client.mset(\"incr thing\", 100, \"incr other thing\", 1, redis.print);\n\n // drains multi queue and runs atomically\n multi.exec(function (err, replies) {\n console.log(replies); // 101, 2\n });\n\n // you can re-run the same transaction if you like\n multi.exec(function (err, replies) {\n console.log(replies); // 102, 3\n client.quit();\n });\n```\n\nIn addition to adding commands to the `MULTI` queue individually, you can also pass an array\nof commands and arguments to the constructor:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n client.multi([\n [\"mget\", \"multifoo\", \"multibar\", redis.print],\n [\"incr\", \"multifoo\"],\n [\"incr\", \"multibar\"]\n ]).exec(function (err, replies) {\n console.log(replies);\n });\n```\n\n\n## Monitor mode\n\nRedis supports the `MONITOR` command, which lets you see all commands received by the Redis server\nacross all client connections, including from other client libraries and other computers.\n\nAfter you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`\nwill emit a `monitor` event for every new monitor message that comes across. The callback for the\n`monitor` event takes a timestamp from the Redis server and an array of command arguments.\n\nHere is a simple example:\n\n```js\n var client = require(\"redis\").createClient(),\n util = require(\"util\");\n\n client.monitor(function (err, res) {\n console.log(\"Entering monitoring mode.\");\n });\n\n client.on(\"monitor\", function (time, args) {\n console.log(time + \": \" + util.inspect(args));\n });\n```\n\n# Extras\n\nSome other things you might like to know about.\n\n## client.server_info\n\nAfter the ready probe completes, the results from the INFO command are saved in the `client.server_info`\nobject.\n\nThe `versions` key contains an array of the elements of the version string for easy comparison.\n\n > client.server_info.redis_version\n '2.3.0'\n > client.server_info.versions\n [ 2, 3, 0 ]\n\n## redis.print()\n\nA handy callback function for displaying return values when testing. Example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\", redis.print);\n client.get(\"foo_rand000000000000\", redis.print);\n });\n```\n\nThis will print:\n\n Reply: OK\n Reply: some fantastic value\n\nNote that this program will not exit cleanly because the client is still connected.\n\n## redis.debug_mode\n\nBoolean to enable debug mode and protocol tracing.\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n redis.debug_mode = true;\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node ~/example.js\n send command: *3\n $3\n SET\n $20\n foo_rand000000000000\n $20\n some fantastic value\n\n on_data: +OK\n\n`send command` is data sent into Redis and `on_data` is data received from Redis.\n\n## Multi-word commands\n\nTo execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass\nthe second word as first parameter:\n\n client.script('load', 'return 1');\n client.multi().script('load', 'return 1').exec(...);\n client.multi([['script', 'load', 'return 1']]).exec(...);\n\n## client.send_command(command_name, args, callback)\n\nUsed internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis\nWiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before\nthis library is updated, you can use `send_command()` to send arbitrary commands to Redis.\n\nAll commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted.\n\n## client.connected\n\nBoolean tracking the state of the connection to the Redis server.\n\n## client.command_queue.length\n\nThe number of commands that have been sent to the Redis server but not yet replied to. You can use this to\nenforce some kind of maximum queue depth for commands while connected.\n\nDon't mess with `client.command_queue` though unless you really know what you are doing.\n\n## client.offline_queue.length\n\nThe number of commands that have been queued up for a future connection. You can use this to enforce\nsome kind of maximum queue depth for pre-connection commands.\n\n## client.retry_delay\n\nCurrent delay in milliseconds before a connection retry will be attempted. This starts at `250`.\n\n## client.retry_backoff\n\nMultiplier for future retry timeouts. This should be larger than 1 to add more time between retries.\nDefaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.\n\n### Commands with Optional and Keyword arguments\n\nThis applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.\n\nExample:\n```js\nvar args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];\nclient.zadd(args, function (err, response) {\n if (err) throw err;\n console.log('added '+response+' items.');\n\n // -Infinity and +Infinity also work\n var args1 = [ 'myzset', '+inf', '-inf' ];\n client.zrevrangebyscore(args1, function (err, response) {\n if (err) throw err;\n console.log('example1', response);\n // write your code here\n });\n\n var max = 3, min = 1, offset = 1, count = 2;\n var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];\n client.zrevrangebyscore(args2, function (err, response) {\n if (err) throw err;\n console.log('example2', response);\n // write your code here\n });\n});\n```\n\n## TODO\n\nBetter tests for auth, disconnect/reconnect, and all combinations thereof.\n\nStream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.\n\nPerformance can be better for very large values.\n\nI think there are more performance improvements left in there for smaller values, especially for large lists of small values.\n\n## How to Contribute\n- open a pull request and then wait for feedback (if\n [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days,\n comment again with indignation!)\n\n## Contributors\nSome people have have added features and fixed bugs in `node_redis` other than me.\n\nOrdered by date of first contribution.\n[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT).\n\n- [Matt Ranney aka `mranney`](https://github.com/mranney)\n- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart)\n- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia)\n- [rick aka `technoweenie`](https://github.com/technoweenie)\n- [Orion Henry aka `orionz`](https://github.com/orionz)\n- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas)\n- [Hank Sims aka `hanksims`](https://github.com/hanksims)\n- [Paul Carey aka `paulcarey`](https://github.com/paulcarey)\n- [Pieter Noordhuis aka `pietern`](https://github.com/pietern)\n- [nithesh aka `nithesh`](https://github.com/nithesh)\n- [Andy Ray aka `andy2ray`](https://github.com/andy2ray)\n- [unknown aka `unknowdna`](https://github.com/unknowdna)\n- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel)\n- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv)\n- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique)\n- [Louis-Philippe Perron aka `lp`](https://github.com/lp)\n- [Mark Dawson aka `markdaws`](https://github.com/markdaws)\n- [Ian Babrou aka `bobrik`](https://github.com/bobrik)\n- [Felix Geisendörfer aka `felixge`](https://github.com/felixge)\n- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined)\n- [Maksim Lin aka `maks`](https://github.com/maks)\n- [Owen Smith aka `orls`](https://github.com/orls)\n- [Zachary Scott aka `zzak`](https://github.com/zzak)\n- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK)\n- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs)\n- [David Trejo aka `DTrejo`](https://github.com/DTrejo)\n- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi)\n- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon)\n- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2)\n- [Jed Schmidt aka `jed`](https://github.com/jed)\n- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3)\n- [Trae Robrock aka `trobrock`](https://github.com/trobrock)\n- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306)\n- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio)\n\nThanks.\n\n## LICENSE - \"MIT License\"\n\nCopyright (c) 2010 Matthew Ranney, http://ranney.com/\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n![spacer](http://ranney.com/1px.gif)\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/mranney/node_redis/issues" - }, - "_id": "redis@0.11.0", - "dist": { - "shasum": "76137b992378e229efa154304f59af4010fc7952" - }, - "_from": "redis@", - "_resolved": "https://registry.npmjs.org/redis/-/redis-0.11.0.tgz" -}