text: //    PouchDB in-memory plugin 4.0.3
  //    Based on MemDOWN: https://github.com/rvagg/memdown
  //    
  //    (c) 2012-2015 Dale Harvey and the PouchDB team
  //    PouchDB may be freely distributed under the Apache license, version 2.0.
  //    For all details and documentation:
  //    http://pouchdb.com
  (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = _dereq_(52);
  },{"52":52}],2:[function(_dereq_,module,exports){
  'use strict';
  
  var createBlob = _dereq_(19);
  
  module.exports = function createEmptyBlobOrBuffer(type) {
    return createBlob([''], {type: type});
  };
  },{"19":19}],3:[function(_dereq_,module,exports){
  (function (process,Buffer){
  'use strict';
  
  var levelup = _dereq_(114);
  var sublevel = _dereq_(87);
  var through = _dereq_(163).obj;
  
  var originalLeveldown;
  function requireLeveldown() {
    // wrapped try/catch inside a function to confine code
    // de-optimalization
    try {
      originalLeveldown = _dereq_(55);
    } catch (e) {}
  }
  requireLeveldown();
  
  var errors = _dereq_(31);
  var utils = _dereq_(53);
  var calculateWinningRev = _dereq_(41);
  var traverseRevTree = _dereq_(40);
  var collectConflicts = _dereq_(35);
  var isDeleted = _dereq_(24);
  var isLocalId = _dereq_(25);
  var processDocs = _dereq_(27);
  var md5 = _dereq_(34);
  var migrate = _dereq_(42);
  var Deque = _dereq_(83);
  var atob = _dereq_(16).atob;
  var functionName = _dereq_(33);
  var readAsBluffer = _dereq_(5);
  var prepareAttachmentForStorage = _dereq_(4);
  var createEmptyBluffer = _dereq_(2);
  
  var binStringToBluffer =
    _dereq_(18);
  
  var LevelTransaction = _dereq_(6);
  
  var DOC_STORE = 'document-store';
  var BY_SEQ_STORE = 'by-sequence';
  var ATTACHMENT_STORE = 'attach-store';
  var BINARY_STORE = 'attach-binary-store';
  var LOCAL_STORE = 'local-store';
  var META_STORE = 'meta-store';
  
  // leveldb barks if we try to open a db multiple times
  // so we cache opened connections here for initstore()
  var dbStores = new utils.Map();
  
  // store the value of update_seq in the by-sequence store the key name will
  // never conflict, since the keys in the by-sequence store are integers
  var UPDATE_SEQ_KEY = '_local_last_update_seq';
  var DOC_COUNT_KEY = '_local_doc_count';
  var UUID_KEY = '_local_uuid';
  
  var MD5_PREFIX = 'md5-';
  
  var safeJsonEncoding = {
    encode: utils.safeJsonStringify,
    decode: utils.safeJsonParse,
    buffer: false,
    type: 'cheap-json'
  };
  
  // winningRev and deleted are performance-killers, but
  // in newer versions of PouchDB, they are cached on the metadata
  function getWinningRev(metadata) {
    return 'winningRev' in metadata ?
      metadata.winningRev : calculateWinningRev(metadata);
  }
  
  function getIsDeleted(metadata, winningRev) {
    return 'deleted' in metadata ?
      metadata.deleted : isDeleted(metadata, winningRev);
  }
  
  function fetchAttachment(att, stores, opts) {
    var type = att.content_type;
    return new utils.Promise(function (resolve, reject) {
      stores.binaryStore.get(att.digest, function (err, buffer) {
        var data;
        if (err) {
          if (err.name !== 'NotFoundError') {
            return reject(err);
          } else {
            // empty
            if (!opts.binary) {
              data = '';
            } else {
              data = binStringToBluffer('', type);
            }
          }
        } else { // non-empty
          if (opts.binary) {
            data = readAsBluffer(buffer, type);
          } else {
            data = buffer.toString('base64');
          }
        }
        delete att.stub;
        delete att.length;
        att.data = data;
        resolve();
      });
    });
  }
  
  function fetchAttachments(results, stores, opts) {
    var atts = [];
    results.forEach(function (row) {
      if (!(row.doc && row.doc._attachments)) {
        return;
      }
      var attNames = Object.keys(row.doc._attachments);
      attNames.forEach(function (attName) {
        var att = row.doc._attachments[attName];
        if (!('data' in att)) {
          atts.push(att);
        }
      });
    });
  
    return utils.Promise.all(atts.map(function (att) {
      return fetchAttachment(att, stores, opts);
    }));
  }
  
  function LevelPouch(opts, callback) {
    opts = utils.clone(opts);
    var api = this;
    var instanceId;
    var stores = {};
    var db;
    var name = opts.name;
    if (typeof opts.createIfMissing === 'undefined') {
      opts.createIfMissing = true;
    }
  
    var leveldown = opts.db || originalLeveldown;
    if (!leveldown) {
      return callback(new Error(
        "leveldown not available " +
        "(specify another backend using the 'db' option)"
      ));
    }
  
    if (typeof leveldown.destroy !== 'function') {
      leveldown.destroy = function (name, cb) { cb(); };
    }
    var dbStore;
    var leveldownName = functionName(leveldown);
    if (dbStores.has(leveldownName)) {
      dbStore = dbStores.get(leveldownName);
    } else {
      dbStore = new utils.Map();
      dbStores.set(leveldownName, dbStore);
    }
    if (dbStore.has(name)) {
      db = dbStore.get(name);
      afterDBCreated();
    } else {
      dbStore.set(name, sublevel(levelup(name, opts, function (err) {
        if (err) {
          dbStore["delete"](name);
          return callback(err);
        }
        db = dbStore.get(name);
        db._docCount  = -1;
        db._queue = new Deque();
        if (opts.db || opts.noMigrate) {
          afterDBCreated();
        } else {
          migrate.toSublevel(name, db, afterDBCreated);
        }
      })));
    }
  
    function afterDBCreated() {
      stores.docStore = db.sublevel(DOC_STORE, {valueEncoding: safeJsonEncoding});
      stores.bySeqStore = db.sublevel(BY_SEQ_STORE, {valueEncoding: 'json'});
      stores.attachmentStore =
        db.sublevel(ATTACHMENT_STORE, {valueEncoding: 'json'});
      stores.binaryStore = db.sublevel(BINARY_STORE, {valueEncoding: 'binary'});
      stores.localStore = db.sublevel(LOCAL_STORE, {valueEncoding: 'json'});
      stores.metaStore = db.sublevel(META_STORE, {valueEncoding: 'json'});
      migrate.localAndMetaStores(db, stores, function () {
        stores.metaStore.get(UPDATE_SEQ_KEY, function (err, value) {
          if (typeof db._updateSeq === 'undefined') {
            db._updateSeq = value || 0;
          }
          stores.metaStore.get(DOC_COUNT_KEY, function (err, value) {
            db._docCount = !err ? value : 0;
            stores.metaStore.get(UUID_KEY, function (err, value) {
              instanceId = !err ? value : utils.uuid();
              stores.metaStore.put(UUID_KEY, instanceId, function (err, value) {
                process.nextTick(function () {
                  callback(null, api);
                });
              });
            });
          });
        });
      });
    }
  
    function countDocs(callback) {
      if (db.isClosed()) {
        return callback(new Error('database is closed'));
      }
      return callback(null, db._docCount); // use cached value
    }
  
    api.type = function () {
      return 'leveldb';
    };
  
    api._id = function (callback) {
      callback(null, instanceId);
    };
  
    api._info = function (callback) {
      var res = {
        doc_count: db._docCount,
        update_seq: db._updateSeq,
        backend_adapter: functionName(leveldown)
      };
      return process.nextTick(function () {
        callback(null, res);
      });
    };
  
    function tryCode(fun, args) {
      try {
        fun.apply(null, args);
      } catch (err) {
        args[args.length - 1](err);
      }
    }
  
    function executeNext() {
      var firstTask = db._queue.peekFront();
  
      if (firstTask.type === 'read') {
        runReadOperation(firstTask);
      } else { // write, only do one at a time
        runWriteOperation(firstTask);
      }
    }
  
    function runReadOperation(firstTask) {
      // do multiple reads at once simultaneously, because it's safe
  
      var readTasks = [firstTask];
      var i = 1;
      var nextTask = db._queue.get(i);
      while (typeof nextTask !== 'undefined' && nextTask.type === 'read') {
        readTasks.push(nextTask);
        i++;
        nextTask = db._queue.get(i);
      }
  
      var numDone = 0;
  
      readTasks.forEach(function (readTask) {
        var args = readTask.args;
        var callback = args[args.length - 1];
        args[args.length - 1] = utils.getArguments(function (cbArgs) {
          callback.apply(null, cbArgs);
          if (++numDone === readTasks.length) {
            process.nextTick(function () {
              // all read tasks have finished
              readTasks.forEach(function () {
                db._queue.shift();
              });
              if (db._queue.length) {
                executeNext();
              }
            });
          }
        });
        tryCode(readTask.fun, args);
      });
    }
  
    function runWriteOperation(firstTask) {
      var args = firstTask.args;
      var callback = args[args.length - 1];
      args[args.length - 1] = utils.getArguments(function (cbArgs) {
        callback.apply(null, cbArgs);
        process.nextTick(function () {
          db._queue.shift();
          if (db._queue.length) {
            executeNext();
          }
        });
      });
      tryCode(firstTask.fun, args);
    }
  
    // all read/write operations to the database are done in a queue,
    // similar to how websql/idb works. this avoids problems such
    // as e.g. compaction needing to have a lock on the database while
    // it updates stuff. in the future we can revisit this.
    function writeLock(fun) {
      return utils.getArguments(function (args) {
        db._queue.push({
          fun: fun,
          args: args,
          type: 'write'
        });
  
        if (db._queue.length === 1) {
          process.nextTick(executeNext);
        }
      });
    }
  
    // same as the writelock, but multiple can run at once
    function readLock(fun) {
      return utils.getArguments(function (args) {
        db._queue.push({
          fun: fun,
          args: args,
          type: 'read'
        });
  
        if (db._queue.length === 1) {
          process.nextTick(executeNext);
        }
      });
    }
  
    function formatSeq(n) {
      return ('0000000000000000' + n).slice(-16);
    }
  
    function parseSeq(s) {
      return parseInt(s, 10);
    }
  
    api._get = readLock(function (id, opts, callback) {
      opts = utils.clone(opts);
  
      stores.docStore.get(id, function (err, metadata) {
  
        if (err || !metadata) {
          return callback(errors.error(errors.MISSING_DOC, 'missing'));
        }
  
        var rev = getWinningRev(metadata);
        var deleted = getIsDeleted(metadata, rev);
        if (deleted && !opts.rev) {
          return callback(errors.error(errors.MISSING_DOC, "deleted"));
        }
  
        rev = opts.rev ? opts.rev : rev;
  
        var seq = metadata.rev_map[rev];
  
        stores.bySeqStore.get(formatSeq(seq), function (err, doc) {
          if (!doc) {
            return callback(errors.error(errors.MISSING_DOC));
          }
          if ('_id' in doc && doc._id !== metadata.id) {
            // this failing implies something very wrong
            return callback(new Error('wrong doc returned'));
          }
          doc._id = metadata.id;
          if ('_rev' in doc) {
            if (doc._rev !== rev) {
              // this failing implies something very wrong
              return callback(new Error('wrong doc returned'));
            }
          } else {
            // we didn't always store this
            doc._rev = rev;
          }
          return callback(null, {doc: doc, metadata: metadata});
        });
      });
    });
  
    // not technically part of the spec, but if putAttachment has its own
    // method...
    api._getAttachment = function (attachment, opts, callback) {
      var digest = attachment.digest;
      var type = attachment.content_type;
  
      stores.binaryStore.get(digest, function (err, attach) {
        if (err) {
          if (err.name !== 'NotFoundError') {
            return callback(err);
          }
          // Empty attachment
          return callback(null, opts.binary ? createEmptyBluffer(type) : '');
        }
  
        if (opts.binary) {
          callback(null, readAsBluffer(attach, type));
        } else {
          callback(null, attach.toString('base64'));
        }
      });
    };
  
    api._bulkDocs = writeLock(function (req, opts, callback) {
      var newEdits = opts.new_edits;
      var results = new Array(req.docs.length);
      var fetchedDocs = new utils.Map();
      var txn = new LevelTransaction();
      var docCountDelta = 0;
      var newUpdateSeq = db._updateSeq;
  
      // parse the docs and give each a sequence number
      var userDocs = req.docs;
      var docInfos = userDocs.map(function (doc, i) {
        if (doc._id && isLocalId(doc._id)) {
          return doc;
        }
        var newDoc = utils.parseDoc(doc, newEdits);
  
        if (newDoc.metadata && !newDoc.metadata.rev_map) {
          newDoc.metadata.rev_map = {};
        }
  
        return newDoc;
      });
      var infoErrors = docInfos.filter(function (doc) {
        return doc.error;
      });
  
      if (infoErrors.length) {
        return callback(infoErrors[0]);
      }
  
      // verify any stub attachments as a precondition test
  
      function verifyAttachment(digest, callback) {
        txn.get(stores.attachmentStore, digest, function (levelErr) {
          if (levelErr) {
            var err = errors.error(errors.MISSING_STUB,
                                  'unknown stub attachment with digest ' +
                                  digest);
            callback(err);
          } else {
            callback();
          }
        });
      }
  
      function verifyAttachments(finish) {
        var digests = [];
        userDocs.forEach(function (doc) {
          if (doc && doc._attachments) {
            Object.keys(doc._attachments).forEach(function (filename) {
              var att = doc._attachments[filename];
              if (att.stub) {
                digests.push(att.digest);
              }
            });
          }
        });
        if (!digests.length) {
          return finish();
        }
        var numDone = 0;
        var err;
  
        digests.forEach(function (digest) {
          verifyAttachment(digest, function (attErr) {
            if (attErr && !err) {
              err = attErr;
            }
  
            if (++numDone === digests.length) {
              finish(err);
            }
          });
        });
      }
  
      function fetchExistingDocs(finish) {
        var numDone = 0;
        var overallErr;
        function checkDone() {
          if (++numDone === userDocs.length) {
            return finish(overallErr);
          }
        }
  
        userDocs.forEach(function (doc) {
          if (doc._id && isLocalId(doc._id)) {
            // skip local docs
            return checkDone();
          }
          txn.get(stores.docStore, doc._id, function (err, info) {
            if (err) {
              if (err.name !== 'NotFoundError') {
                overallErr = err;
              }
            } else {
              fetchedDocs.set(doc._id, info);
            }
            checkDone();
          });
        });
      }
  
      function autoCompact(callback) {
  
        var promise = utils.Promise.resolve();
  
        fetchedDocs.forEach(function (metadata, docId) {
          // TODO: parallelize, for now need to be sequential to
          // pass orphaned attachment tests
          promise = promise.then(function () {
            return new utils.Promise(function (resolve, reject) {
              var revs = utils.compactTree(metadata);
              api._doCompactionNoLock(docId, revs, {ctx: txn}, function (err) {
                if (err) {
                  return reject(err);
                }
                resolve();
              });
            });
          });
        });
  
        promise.then(function () {
          callback();
        }, callback);
      }
  
      function finish() {
        if (api.auto_compaction) {
          return autoCompact(complete);
        }
        return complete();
      }
  
      function writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
                        isUpdate, delta, resultsIdx, callback2) {
        docCountDelta += delta;
  
        var err = null;
        var recv = 0;
  
        docInfo.metadata.winningRev = winningRev;
        docInfo.metadata.deleted = winningRevIsDeleted;
  
        docInfo.data._id = docInfo.metadata.id;
        docInfo.data._rev = docInfo.metadata.rev;
  
        if (newRevIsDeleted) {
          docInfo.data._deleted = true;
        }
  
        var attachments = docInfo.data._attachments ?
          Object.keys(docInfo.data._attachments) :
          [];
  
        function attachmentSaved(attachmentErr) {
          recv++;
          if (!err) {
            if (attachmentErr) {
              err = attachmentErr;
              callback2(err);
            } else if (recv === attachments.length) {
              finish();
            }
          }
        }
  
        function onMD5Load(doc, key, data, attachmentSaved) {
          return function (result) {
            saveAttachment(doc, MD5_PREFIX + result, key, data, attachmentSaved);
          };
        }
  
        function doMD5(doc, key, attachmentSaved) {
          return function (data) {
            md5(data).then(
              onMD5Load(doc, key, data, attachmentSaved)
            );
          };
        }
  
        for (var i = 0; i < attachments.length; i++) {
          var key = attachments[i];
          var att = docInfo.data._attachments[key];
  
          if (att.stub) {
            // still need to update the refs mapping
            var id = docInfo.data._id;
            var rev = docInfo.data._rev;
            saveAttachmentRefs(id, rev, att.digest, attachmentSaved);
            continue;
          }
          var data;
          if (typeof att.data === 'string') {
            try {
              data = atob(att.data);
            } catch (e) {
              callback(errors.error(errors.BAD_ARG,
                       'Attachments need to be base64 encoded'));
              return;
            }
            doMD5(docInfo, key, attachmentSaved)(data);
          } else {
            prepareAttachmentForStorage(att.data,
              doMD5(docInfo, key, attachmentSaved));
          }
        }
  
        function finish() {
          var seq = docInfo.metadata.rev_map[docInfo.metadata.rev];
          if (seq) {
            // check that there aren't any existing revisions with the same
            // revision id, else we shouldn't do anything
            return callback2();
          }
          seq = ++newUpdateSeq;
          docInfo.metadata.rev_map[docInfo.metadata.rev] =
            docInfo.metadata.seq = seq;
          var seqKey = formatSeq(seq);
          var batch = [{
            key: seqKey,
            value: docInfo.data,
            prefix: stores.bySeqStore,
            type: 'put'
          }, {
            key: docInfo.metadata.id,
            value: docInfo.metadata,
            prefix: stores.docStore,
            type: 'put'
          }];
          txn.batch(batch);
          results[resultsIdx] = {
            ok: true,
            id: docInfo.metadata.id,
            rev: winningRev
          };
          fetchedDocs.set(docInfo.metadata.id, docInfo.metadata);
          callback2();
        }
  
        if (!attachments.length) {
          finish();
        }
      }
  
      // attachments are queued per-digest, otherwise the refs could be
      // overwritten by concurrent writes in the same bulkDocs session
      var attachmentQueues = {};
  
      function saveAttachmentRefs(id, rev, digest, callback) {
  
        function fetchAtt() {
          return new utils.Promise(function (resolve, reject) {
            txn.get(stores.attachmentStore, digest, function (err, oldAtt) {
              if (err && err.name !== 'NotFoundError') {
                return reject(err);
              }
              resolve(oldAtt);
            });
          });
        }
  
        function saveAtt(oldAtt) {
          var ref = [id, rev].join('@');
          var newAtt = {};
  
          if (oldAtt) {
            if (oldAtt.refs) {
              // only update references if this attachment already has them
              // since we cannot migrate old style attachments here without
              // doing a full db scan for references
              newAtt.refs = oldAtt.refs;
              newAtt.refs[ref] = true;
            }
          } else {
            newAtt.refs = {};
            newAtt.refs[ref] = true;
          }
  
          return new utils.Promise(function (resolve, reject) {
            txn.batch([{
              type: 'put',
              prefix: stores.attachmentStore,
              key: digest,
              value: newAtt
            }]);
            resolve(!oldAtt);
          });
        }
  
        // put attachments in a per-digest queue, to avoid two docs with the same
        // attachment overwriting each other
        var queue = attachmentQueues[digest] || utils.Promise.resolve();
        attachmentQueues[digest] = queue.then(function () {
          return fetchAtt().then(saveAtt).then(function (isNewAttachment) {
            callback(null, isNewAttachment);
          }, callback);
        });
      }
  
      function saveAttachment(docInfo, digest, key, data, callback) {
        var att = docInfo.data._attachments[key];
        delete att.data;
        att.digest = digest;
        att.length = data.length;
        var id = docInfo.metadata.id;
        var rev = docInfo.metadata.rev;
  
        saveAttachmentRefs(id, rev, digest, function (err, isNewAttachment) {
          if (err) {
            return callback(err);
          }
          // do not try to store empty attachments
          if (data.length === 0) {
            return callback(err);
          }
          if (!isNewAttachment) {
            // small optimization - don't bother writing it again
            return callback(err);
          }
          txn.batch([{
            type: 'put',
            prefix: stores.binaryStore,
            key: digest,
            value: new Buffer(data, 'binary')
          }]);
          callback();
        });
      }
  
      function complete(err) {
        if (err) {
          return process.nextTick(function () {
            callback(err);
          });
        }
        txn.batch([
          {
            prefix: stores.metaStore,
            type: 'put',
            key: UPDATE_SEQ_KEY,
            value: newUpdateSeq
          },
          {
            prefix: stores.metaStore,
            type: 'put',
            key: DOC_COUNT_KEY,
            value: db._docCount + docCountDelta
          }
        ]);
        txn.execute(db, function (err) {
          if (err) {
            return callback(err);
          }
          db._docCount += docCountDelta;
          db._updateSeq = newUpdateSeq;
          LevelPouch.Changes.notify(name);
          process.nextTick(function () {
            callback(null, results);
          });
        });
      }
  
      if (!docInfos.length) {
        return callback(null, []);
      }
  
      verifyAttachments(function (err) {
        if (err) {
          return callback(err);
        }
        fetchExistingDocs(function (err) {
          if (err) {
            return callback(err);
          }
          processDocs(docInfos, api, fetchedDocs, txn, results, writeDoc,
            opts, finish);
        });
      });
    });
    api._allDocs = readLock(function (opts, callback) {
      opts = utils.clone(opts);
      countDocs(function (err, docCount) {
        if (err) {
          return callback(err);
        }
        var readstreamOpts = {};
        var skip = opts.skip || 0;
        if (opts.startkey) {
          readstreamOpts.gte = opts.startkey;
        }
        if (opts.endkey) {
          readstreamOpts.lte = opts.endkey;
        }
        if (opts.key) {
          readstreamOpts.gte = readstreamOpts.lte = opts.key;
        }
        if (opts.descending) {
          readstreamOpts.reverse = true;
          // switch start and ends
          var tmp = readstreamOpts.lte;
          readstreamOpts.lte = readstreamOpts.gte;
          readstreamOpts.gte = tmp;
        }
        var limit;
        if (typeof opts.limit === 'number') {
          limit = opts.limit;
        }
        if (limit === 0 ||
            ('start' in readstreamOpts && 'end' in readstreamOpts &&
            readstreamOpts.start > readstreamOpts.end)) {
          // should return 0 results when start is greater than end.
          // normally level would "fix" this for us by reversing the order,
          // so short-circuit instead
          return callback(null, {
            total_rows: docCount,
            offset: opts.skip,
            rows: []
          });
        }
        var results = [];
        var docstream = stores.docStore.readStream(readstreamOpts);
  
        var throughStream = through(function (entry, _, next) {
          var metadata = entry.value;
          // winningRev and deleted are performance-killers, but
          // in newer versions of PouchDB, they are cached on the metadata
          var winningRev = getWinningRev(metadata);
          var deleted = getIsDeleted(metadata, winningRev);
          if (!deleted) {
            if (skip-- > 0) {
              next();
              return;
            } else if (typeof limit === 'number' && limit-- <= 0) {
              docstream.unpipe();
              docstream.destroy();
              next();
              return;
            }
          } else if (opts.deleted !== 'ok') {
            next();
            return;
          }
          function allDocsInner(data) {
            var doc = {
              id: metadata.id,
              key: metadata.id,
              value: {
                rev: winningRev
              }
            };
            if (opts.include_docs) {
              doc.doc = data;
              doc.doc._rev = doc.value.rev;
              if (opts.conflicts) {
                doc.doc._conflicts = collectConflicts(metadata);
              }
              for (var att in doc.doc._attachments) {
                if (doc.doc._attachments.hasOwnProperty(att)) {
                  doc.doc._attachments[att].stub = true;
                }
              }
            }
            if (opts.inclusive_end === false && metadata.id === opts.endkey) {
              return next();
            } else if (deleted) {
              if (opts.deleted === 'ok') {
                doc.value.deleted = true;
                doc.doc = null;
              } else {
                return next();
              }
            }
            results.push(doc);
            next();
          }
          if (opts.include_docs) {
            var seq = metadata.rev_map[winningRev];
            stores.bySeqStore.get(formatSeq(seq), function (err, data) {
              allDocsInner(data);
            });
          }
          else {
            allDocsInner();
          }
        }, function (next) {
          utils.Promise.resolve().then(function () {
            if (opts.include_docs && opts.attachments){
              return fetchAttachments(results, stores, opts);
            }
          }).then(function () {
            callback(null, {
              total_rows: docCount,
              offset: opts.skip,
              rows: results
            });
          }, callback);
          next();
        }).on('unpipe', function () {
          throughStream.end();
        });
  
        docstream.on('error', callback);
  
        docstream.pipe(throughStream);
      });
    });
  
    api._changes = function (opts) {
      opts = utils.clone(opts);
  
      if (opts.continuous) {
        var id = name + ':' + utils.uuid();
        LevelPouch.Changes.addListener(name, id, api, opts);
        LevelPouch.Changes.notify(name);
        return {
          cancel: function () {
            LevelPouch.Changes.removeListener(name, id);
          }
        };
      }
  
      var descending = opts.descending;
      var results = [];
      var lastSeq = opts.since || 0;
      var called = 0;
      var streamOpts = {
        reverse: descending
      };
      var limit;
      if ('limit' in opts && opts.limit > 0) {
        limit = opts.limit;
      }
      if (!streamOpts.reverse) {
        streamOpts.start = formatSeq(opts.since || 0);
      }
  
      var docIds = opts.doc_ids && new utils.Set(opts.doc_ids);
      var filter = utils.filterChange(opts);
      var docIdsToMetadata = new utils.Map();
  
      var returnDocs;
      if ('returnDocs' in opts) {
        returnDocs = opts.returnDocs;
      } else {
        returnDocs = true;
      }
  
      function complete() {
        opts.done = true;
        if (returnDocs && opts.limit) {
          if (opts.limit < results.length) {
            results.length = opts.limit;
          }
        }
        changeStream.unpipe(throughStream);
        changeStream.destroy();
        if (!opts.continuous && !opts.cancelled) {
          if (opts.include_docs && opts.attachments) {
            fetchAttachments(results, stores, opts).then(function () {
              opts.complete(null, {results: results, last_seq: lastSeq});
            });
          } else {
            opts.complete(null, {results: results, last_seq: lastSeq});
          }
        }
      }
      var changeStream = stores.bySeqStore.readStream(streamOpts);
      var throughStream = through(function (data, _, next) {
        if (limit && called >= limit) {
          complete();
          return next();
        }
        if (opts.cancelled || opts.done) {
          return next();
        }
  
        var seq = parseSeq(data.key);
        var doc = data.value;
  
        if (seq === opts.since && !descending) {
          // couchdb ignores `since` if descending=true
          return next();
        }
  
        if (docIds && !docIds.has(doc._id)) {
          return next();
        }
  
        var metadata;
  
        function onGetMetadata(metadata) {
          var winningRev = getWinningRev(metadata);
  
          function onGetWinningDoc(winningDoc) {
  
            var change = opts.processChange(winningDoc, metadata, opts);
            change.seq = metadata.seq;
  
            var filtered = filter(change);
            if (typeof filtered === 'object') {
              return opts.complete(filtered);
            }
  
            if (filtered) {
              called++;
  
              if (opts.attachments && opts.include_docs) {
                // fetch attachment immediately for the benefit
                // of live listeners
                fetchAttachments([change], stores, opts).then(function () {
                  opts.onChange(change);
                });
              } else {
                opts.onChange(change);
              }
  
              if (returnDocs) {
                results.push(change);
              }
            }
            next();
          }
  
          if (metadata.seq !== seq) {
            // some other seq is later
            return next();
          }
  
          lastSeq = seq;
  
          if (winningRev === doc._rev) {
            return onGetWinningDoc(doc);
          }
  
          // fetch the winner
  
          var winningSeq = metadata.rev_map[winningRev];
  
          stores.bySeqStore.get(formatSeq(winningSeq), function (err, doc) {
            onGetWinningDoc(doc);
          });
        }
  
        metadata = docIdsToMetadata.get(doc._id);
        if (metadata) { // cached
          return onGetMetadata(metadata);
        }
        // metadata not cached, have to go fetch it
        stores.docStore.get(doc._id, function (err, metadata) {
          if (opts.cancelled || opts.done || db.isClosed() ||
            isLocalId(metadata.id)) {
            return next();
          }
          docIdsToMetadata.set(doc._id, metadata);
          onGetMetadata(metadata);
        });
      }, function (next) {
        if (opts.cancelled) {
          return next();
        }
        if (returnDocs && opts.limit) {
          if (opts.limit < results.length) {
            results.length = opts.limit;
          }
        }
  
        next();
      }).on('unpipe', function () {
        throughStream.end();
        complete();
      });
      changeStream.pipe(throughStream);
      return {
        cancel: function () {
          opts.cancelled = true;
          complete();
        }
      };
    };
  
    api._close = function (callback) {
      if (db.isClosed()) {
        return callback(errors.error(errors.NOT_OPEN));
      }
      db.close(function (err) {
        if (err) {
          callback(err);
        } else {
          dbStore["delete"](name);
          callback();
        }
      });
    };
  
    api._getRevisionTree = function (docId, callback) {
      stores.docStore.get(docId, function (err, metadata) {
        if (err) {
          callback(errors.error(errors.MISSING_DOC));
        } else {
          callback(null, metadata.rev_tree);
        }
      });
    };
  
    api._doCompaction = writeLock(function (docId, revs, opts, callback) {
      api._doCompactionNoLock(docId, revs, opts, callback);
    });
  
    // the NoLock version is for use by bulkDocs
    api._doCompactionNoLock = function (docId, revs, opts, callback) {
      if (typeof opts === 'function') {
        callback = opts;
        opts = {};
      }
  
      if (!revs.length) {
        return callback();
      }
      var txn = opts.ctx || new LevelTransaction();
  
      txn.get(stores.docStore, docId, function (err, metadata) {
        if (err) {
          return callback(err);
        }
        var seqs = metadata.rev_map; // map from rev to seq
        traverseRevTree(metadata.rev_tree, function (isLeaf, pos,
                                                           revHash, ctx, opts) {
          var rev = pos + '-' + revHash;
          if (revs.indexOf(rev) !== -1) {
            opts.status = 'missing';
          }
        });
        var batch = [];
        batch.push({
          key: metadata.id,
          value: metadata,
          type: 'put',
          prefix: stores.docStore
        });
  
        var digestMap = {};
        var numDone = 0;
        var overallErr;
        function checkDone(err) {
          if (err) {
            overallErr = err;
          }
          if (++numDone === revs.length) { // done
            if (overallErr) {
              return callback(overallErr);
            }
            deleteOrphanedAttachments();
          }
        }
  
        function finish(err) {
          if (err) {
            return callback(err);
          }
          txn.batch(batch);
          if (opts.ctx) {
            // don't execute immediately
            return callback();
          }
          txn.execute(db, callback);
        }
  
        function deleteOrphanedAttachments() {
          var possiblyOrphanedAttachments = Object.keys(digestMap);
          if (!possiblyOrphanedAttachments.length) {
            return finish();
          }
          var numDone = 0;
          var overallErr;
          function checkDone(err) {
            if (err) {
              overallErr = err;
            }
            if (++numDone === possiblyOrphanedAttachments.length) {
              finish(overallErr);
            }
          }
          var refsToDelete = new utils.Map();
          revs.forEach(function (rev) {
            refsToDelete.set(docId + '@' + rev, true);
          });
          possiblyOrphanedAttachments.forEach(function (digest) {
            txn.get(stores.attachmentStore, digest, function (err, attData) {
              if (err) {
                if (err.name === 'NotFoundError') {
                  return checkDone();
                } else {
                  return checkDone(err);
                }
              }
              var refs = Object.keys(attData.refs || {}).filter(function (ref) {
                return !refsToDelete.has(ref);
              });
              var newRefs = {};
              refs.forEach(function (ref) {
                newRefs[ref] = true;
              });
              if (refs.length) { // not orphaned
                batch.push({
                  key: digest,
                  type: 'put',
                  value: {refs: newRefs},
                  prefix: stores.attachmentStore
                });
              } else { // orphaned, can safely delete
                batch = batch.concat([{
                  key: digest,
                  type: 'del',
                  prefix: stores.attachmentStore
                }, {
                  key: digest,
                  type: 'del',
                  prefix: stores.binaryStore
                }]);
              }
              checkDone();
            });
          });
        }
  
        revs.forEach(function (rev) {
          var seq = seqs[rev];
          batch.push({
            key: formatSeq(seq),
            type: 'del',
            prefix: stores.bySeqStore
          });
          txn.get(stores.bySeqStore, formatSeq(seq), function (err, doc) {
            if (err) {
              if (err.name === 'NotFoundError') {
                return checkDone();
              } else {
                return checkDone(err);
              }
            }
            var atts = Object.keys(doc._attachments || {});
            atts.forEach(function (attName) {
              var digest = doc._attachments[attName].digest;
              digestMap[digest] = true;
            });
            checkDone();
          });
        });
      });
    };
  
    api._getLocal = function (id, callback) {
      stores.localStore.get(id, function (err, doc) {
        if (err) {
          callback(errors.error(errors.MISSING_DOC));
        } else {
          callback(null, doc);
        }
      });
    };
  
    api._putLocal = function (doc, opts, callback) {
      if (typeof opts === 'function') {
        callback = opts;
        opts = {};
      }
      if (opts.ctx) {
        api._putLocalNoLock(doc, opts, callback);
      } else {
        api._putLocalWithLock(doc, opts, callback);
      }
    };
  
    api._putLocalWithLock = writeLock(function (doc, opts, callback) {
      api._putLocalNoLock(doc, opts, callback);
    });
  
    // the NoLock version is for use by bulkDocs
    api._putLocalNoLock = function (doc, opts, callback) {
      delete doc._revisions; // ignore this, trust the rev
      var oldRev = doc._rev;
      var id = doc._id;
  
      var txn = opts.ctx || new LevelTransaction();
  
      txn.get(stores.localStore, id, function (err, resp) {
        if (err && oldRev) {
          return callback(errors.error(errors.REV_CONFLICT));
        }
        if (resp && resp._rev !== oldRev) {
          return callback(errors.error(errors.REV_CONFLICT));
        }
        doc._rev =
            oldRev ? '0-' + (parseInt(oldRev.split('-')[1], 10) + 1) : '0-1';
        var batch = [
          {
            type: 'put',
            prefix: stores.localStore,
            key: id,
            value: doc
          }
        ];
  
        txn.batch(batch);
        var ret = {ok: true, id: doc._id, rev: doc._rev};
  
        if (opts.ctx) {
          // don't execute immediately
          return callback(null, ret);
        }
        txn.execute(db, function (err) {
          if (err) {
            return callback(err);
          }
          callback(null, ret);
        });
      });
    };
  
    api._removeLocal = function (doc, opts, callback) {
      if (typeof opts === 'function') {
        callback = opts;
        opts = {};
      }
      if (opts.ctx) {
        api._removeLocalNoLock(doc, opts, callback);
      } else {
        api._removeLocalWithLock(doc, opts, callback);
      }
    };
  
    api._removeLocalWithLock = writeLock(function (doc, opts, callback) {
      api._removeLocalNoLock(doc, opts, callback);
    });
  
    // the NoLock version is for use by bulkDocs
    api._removeLocalNoLock = function (doc, opts, callback) {
      var txn = opts.ctx || new LevelTransaction();
      txn.get(stores.localStore, doc._id, function (err, resp) {
        if (err) {
          if (err.name !== 'NotFoundError') {
            return callback(err);
          } else {
            return callback(errors.error(errors.MISSING_DOC));
          }
        }
        if (resp._rev !== doc._rev) {
          return callback(errors.error(errors.REV_CONFLICT));
        }
        txn.batch([{
          prefix: stores.localStore,
          type: 'del',
          key: doc._id
        }]);
        var ret = {ok: true, id: doc._id, rev: '0-0'};
        if (opts.ctx) {
          // don't execute immediately
          return callback(null, ret);
        }
        txn.execute(db, function (err) {
          if (err) {
            return callback(err);
          }
          callback(null, ret);
        });
      });
    };
  
    // close and delete open leveldb stores
    api._destroy = function (opts, callback) {
      var dbStore;
      var leveldownName = functionName(leveldown);
      if (dbStores.has(leveldownName)) {
        dbStore = dbStores.get(leveldownName);
      } else {
        return callDestroy(name, callback);
      }
  
      if (dbStore.has(name)) {
        LevelPouch.Changes.removeAllListeners(name);
  
        dbStore.get(name).close(function () {
          dbStore["delete"](name);
          callDestroy(name, callback);
        });
      } else {
        callDestroy(name, callback);
      }
    };
    function callDestroy(name, cb) {
      if (typeof leveldown.destroy === 'function') {
        leveldown.destroy(name, cb);
      } else {
        process.nextTick(cb);
      }
    }
  }
  
  LevelPouch.valid = function () {
    // this gets overriden by the *down-based browser adapters
    return true;
  };
  
  LevelPouch.use_prefix = false;
  
  LevelPouch.Changes = new utils.Changes();
  
  module.exports = LevelPouch;
  
  }).call(this,_dereq_(62),_dereq_(56).Buffer)
  },{"114":114,"16":16,"163":163,"18":18,"2":2,"24":24,"25":25,"27":27,"31":31,"33":33,"34":34,"35":35,"4":4,"40":40,"41":41,"42":42,"5":5,"53":53,"55":55,"56":56,"6":6,"62":62,"83":83,"87":87}],4:[function(_dereq_,module,exports){
  'use strict';
  
  var readAsBinaryString = _dereq_(22);
  
  // In the browser, we store a binary string
  module.exports = function prepareAttachmentForStorage(attData, cb) {
    readAsBinaryString(attData, cb);
  };
  },{"22":22}],5:[function(_dereq_,module,exports){
  'use strict';
  
  var createBlob = _dereq_(19);
  
  module.exports = function readAsBlobOrBuffer(storedObject, type) {
    // In the browser, we've stored a binary string. This now comes back as a
    // browserified Node-style Buffer, but we want a Blob instead.
    return createBlob([storedObject.toArrayBuffer()], {type: type});
  };
  },{"19":19}],6:[function(_dereq_,module,exports){
  (function (process){
  'use strict';
  
  // similar to an idb or websql transaction object
  // designed to be passed around. basically just caches
  // things in-memory and then does a big batch() operation
  // when you're done
  
  var utils = _dereq_(53);
  
  function getCacheFor(transaction, store) {
    var prefix = store.prefix()[0];
    var cache = transaction._cache;
    var subCache = cache.get(prefix);
    if (!subCache) {
      subCache = new utils.Map();
      cache.set(prefix, subCache);
    }
    return subCache;
  }
  
  function LevelTransaction() {
    this._batch = [];
    this._cache = new utils.Map();
  }
  
  LevelTransaction.prototype.get = function (store, key, callback) {
    var cache = getCacheFor(this, store);
    var exists = cache.get(key);
    if (exists) {
      return process.nextTick(function () {
        callback(null, exists);
      });
    } else if (exists === null) { // deleted marker
      return process.nextTick(function () {
        callback({name: 'NotFoundError'});
      });
    }
    store.get(key, function (err, res) {
      if (err) {
        /* istanbul ignore else */
        if (err.name === 'NotFoundError') {
          cache.set(key, null);
        }
        return callback(err);
      }
      cache.set(key, res);
      callback(null, res);
    });
  };
  
  LevelTransaction.prototype.batch = function (batch) {
    for (var i = 0, len = batch.length; i < len; i++) {
      var operation = batch[i];
  
      var cache = getCacheFor(this, operation.prefix);
  
      if (operation.type === 'put') {
        cache.set(operation.key, operation.value);
      } else {
        cache.set(operation.key, null);
      }
    }
    this._batch = this._batch.concat(batch);
  };
  
  LevelTransaction.prototype.execute = function (db, callback) {
  
    var keys = new utils.Set();
    var uniqBatches = [];
  
    // remove duplicates; last one wins
    for (var i = this._batch.length - 1; i >= 0; i--) {
      var operation = this._batch[i];
      var lookupKey = operation.prefix.prefix()[0] + '\xff' + operation.key;
      if (keys.has(lookupKey)) {
        continue;
      }
      keys.add(lookupKey);
      uniqBatches.push(operation);
    }
  
    db.batch(uniqBatches, callback);
  };
  
  module.exports = LevelTransaction;
  }).call(this,_dereq_(62))
  },{"53":53,"62":62}],7:[function(_dereq_,module,exports){
  'use strict';
  
  var EventEmitter = _dereq_(60).EventEmitter;
  var inherits = _dereq_(84);
  var isChromeApp = _dereq_(30);
  var hasLocalStorage = _dereq_(29);
  var pick = _dereq_(45);
  
  inherits(Changes, EventEmitter);
  
  /* istanbul ignore next */
  function attachBrowserEvents(self) {
    if (isChromeApp()) {
      chrome.storage.onChanged.addListener(function (e) {
        // make sure it's event addressed to us
        if (e.db_name != null) {
          //object only has oldValue, newValue members
          self.emit(e.dbName.newValue);
        }
      });
    } else if (hasLocalStorage()) {
      if (typeof addEventListener !== 'undefined') {
        addEventListener("storage", function (e) {
          self.emit(e.key);
        });
      } else { // old IE
        window.attachEvent("storage", function (e) {
          self.emit(e.key);
        });
      }
    }
  }
  
  function Changes() {
    EventEmitter.call(this);
    this._listeners = {};
  
    attachBrowserEvents(this);
  }
  Changes.prototype.addListener = function (dbName, id, db, opts) {
    if (this._listeners[id]) {
      return;
    }
    var self = this;
    var inprogress = false;
    function eventFunction() {
      if (!self._listeners[id]) {
        return;
      }
      if (inprogress) {
        inprogress = 'waiting';
        return;
      }
      inprogress = true;
      var changesOpts = pick(opts, [
        'style', 'include_docs', 'attachments', 'conflicts', 'filter',
        'doc_ids', 'view', 'since', 'query_params', 'binary'
      ]);
  
      db.changes(changesOpts).on('change', function (c) {
        if (c.seq > opts.since && !opts.cancelled) {
          opts.since = c.seq;
          opts.onChange(c);
        }
      }).on('complete', function () {
        if (inprogress === 'waiting') {
          setTimeout(function(){
            eventFunction();
          },0);
        }
        inprogress = false;
      }).on('error', function () {
        inprogress = false;
      });
    }
    this._listeners[id] = eventFunction;
    this.on(dbName, eventFunction);
  };
  
  Changes.prototype.removeListener = function (dbName, id) {
    if (!(id in this._listeners)) {
      return;
    }
    EventEmitter.prototype.removeListener.call(this, dbName,
      this._listeners[id]);
  };
  
  
  /* istanbul ignore next */
  Changes.prototype.notifyLocalWindows = function (dbName) {
    //do a useless change on a storage thing
    //in order to get other windows's listeners to activate
    if (isChromeApp()) {
      chrome.storage.local.set({dbName: dbName});
    } else if (hasLocalStorage()) {
      localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a";
    }
  };
  
  Changes.prototype.notify = function (dbName) {
    this.emit(dbName);
    this.notifyLocalWindows(dbName);
  };
  
  module.exports = Changes;
  
  },{"29":29,"30":30,"45":45,"60":60,"84":84}],8:[function(_dereq_,module,exports){
  "use strict";
  
  var request = _dereq_(14);
  
  var errors = _dereq_(31);
  var utils = _dereq_(53);
  var applyTypeToBuffer = _dereq_(9);
  var defaultBody = _dereq_(10);
  var explainCors = _dereq_(12);
  
  function ajax(options, callback) {
  
    options = utils.clone(options);
  
    var defaultOptions = {
      method : "GET",
      headers: {},
      json: true,
      processData: true,
      timeout: 10000,
      cache: false
    };
  
    options = utils.extend(defaultOptions, options);
  
  
    function onSuccess(obj, resp, cb) {
      if (!options.binary && !options.json && options.processData &&
        typeof obj !== 'string') {
        obj = JSON.stringify(obj);
      } else if (!options.binary && options.json && typeof obj === 'string') {
        try {
          obj = JSON.parse(obj);
        } catch (e) {
          // Probably a malformed JSON from server
          return cb(e);
        }
      }
      if (Array.isArray(obj)) {
        obj = obj.map(function (v) {
          if (v.error || v.missing) {
            return errors.generateErrorFromResponse(v);
          } else {
            return v;
          }
        });
      }
      if (options.binary) {
        applyTypeToBuffer(obj, resp);
      }
      cb(null, obj, resp);
    }
  
    function onError(err, cb) {
      var errParsed, errObj;
      if (err.code && err.status) {
        var err2 = new Error(err.message || err.code);
        err2.status = err.status;
        return cb(err2);
      }
      try {
        errParsed = JSON.parse(err.responseText);
        //would prefer not to have a try/catch clause
        errObj = errors.generateErrorFromResponse(errParsed);
      } catch (e) {
        errObj = errors.generateErrorFromResponse(err);
      }
      cb(errObj);
    }
  
  
    if (options.json) {
      if (!options.binary) {
        options.headers.Accept = 'application/json';
      }
      options.headers['Content-Type'] = options.headers['Content-Type'] ||
        'application/json';
    }
  
    if (options.binary) {
      options.encoding = null;
      options.json = false;
    }
  
    if (!options.processData) {
      options.json = false;
    }
  
    return request(options, function (err, response, body) {
      if (err) {
        if (response) {
          var origin = (typeof document !== 'undefined') &&
            document.location.origin;
          var isCrossOrigin = origin && options.url.indexOf(origin) === 0;
          if (isCrossOrigin && response.statusCode === 0) {
            explainCors();
          }
          err.status = response.statusCode;
        } else {
          err.status = 400;
        }
        return onError(err, callback);
      }
  
      var error;
      var content_type = response.headers && response.headers['content-type'];
      var data = body || defaultBody();
  
      // CouchDB doesn't always return the right content-type for JSON data, so
      // we check for ^{ and }$ (ignoring leading/trailing whitespace)
      if (!options.binary && (options.json || !options.processData) &&
          typeof data !== 'object' &&
          (/json/.test(content_type) ||
           (/^[\s]*\{/.test(data) && /\}[\s]*$/.test(data)))) {
        try {
          data = JSON.parse(data.toString());
        } catch (e) {}
      }
  
      if (response.statusCode >= 200 && response.statusCode < 300) {
        onSuccess(data, response, callback);
      } else {
        error = errors.generateErrorFromResponse(data);
        error.status = response.statusCode;
        callback(error);
      }
    });
  }
  
  module.exports = ajax;
  
  },{"10":10,"12":12,"14":14,"31":31,"53":53,"9":9}],9:[function(_dereq_,module,exports){
  'use strict';
  
  // the blob already has a type; do nothing
  module.exports = function () {};
  },{}],10:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = function defaultBody() {
    return '';
  };
  },{}],11:[function(_dereq_,module,exports){
  (function (global){
  'use strict';
  
  // designed to give info to browser users, who are disturbed
  // when they see 404s in the console
  module.exports = function explain404(str) {
    if ('console' in global && 'info' in console) {
      console.info('The above 404 is totally normal. ' + str);
    }
  };
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],12:[function(_dereq_,module,exports){
  (function (global){
  'use strict';
  
  module.exports = function () {
    if ('console' in global && 'warn' in console) {
      console.warn('PouchDB: the remote database may not have CORS enabled.' +
        'If not please enable CORS: ' +
        'http://pouchdb.com/errors.html#no_access_control_allow_origin_header');
    }
  };
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],13:[function(_dereq_,module,exports){
  'use strict';
  
  var ajax = _dereq_(8);
  
  module.exports = function(opts, callback) {
  
    // cache-buster, specifically designed to work around IE's aggressive caching
    // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/
    // Also Safari caches POSTs, so we need to cache-bust those too.
    if ((opts.method === 'POST' || opts.method === 'GET') && !opts.cache) {
      var hasArgs = opts.url.indexOf('?') !== -1;
      opts.url += (hasArgs ? '&' : '?') + '_nonce=' + Date.now();
    }
  
    return ajax(opts, callback);
  };
  
  },{"8":8}],14:[function(_dereq_,module,exports){
  /* global fetch */
  /* global Headers */
  'use strict';
  
  var createBlob = _dereq_(19);
  var utils = _dereq_(53);
  var readAsArrayBuffer = _dereq_(21);
  
  function wrappedFetch() {
    var wrappedPromise = {};
  
    var promise = new utils.Promise(function(resolve, reject) {
      wrappedPromise.resolve = resolve;
      wrappedPromise.reject = reject;
    });
  
    var args = new Array(arguments.length);
  
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
  
    wrappedPromise.promise = promise;
  
    utils.Promise.resolve().then(function () {
      return fetch.apply(null, args);
    }).then(function(response) {
      wrappedPromise.resolve(response);
    })["catch"](function(error) {
      wrappedPromise.reject(error);
    });
  
    return wrappedPromise;
  }
  
  function fetchRequest(options, callback) {
    var wrappedPromise, timer, response;
  
    var headers = new Headers();
  
    var fetchOptions = {
      method: options.method,
      credentials: 'include',
      headers: headers
    };
  
    if (options.json) {
      headers.set('Accept', 'application/json');
      headers.set('Content-Type', options.headers['Content-Type'] ||
        'application/json');
    }
  
    if (options.body && (options.body instanceof Blob)) {
      readAsArrayBuffer(options.body, function (arrayBuffer) {
        fetchOptions.body = arrayBuffer;
      });
    } else if (options.body &&
               options.processData &&
               typeof options.body !== 'string') {
      fetchOptions.body = JSON.stringify(options.body);
    } else if ('body' in options) {
      fetchOptions.body = options.body;
    } else {
      fetchOptions.body = null;
    }
  
    Object.keys(options.headers).forEach(function(key) {
      if (options.headers.hasOwnProperty(key)) {
        headers.set(key, options.headers[key]);
      }
    });
  
    wrappedPromise = wrappedFetch(options.url, fetchOptions);
  
    if (options.timeout > 0) {
      timer = setTimeout(function() {
        wrappedPromise.reject(new Error('Load timeout for resource: ' +
          options.url));
      }, options.timeout);
    }
  
    wrappedPromise.promise.then(function(fetchResponse) {
      response = {
        statusCode: fetchResponse.status
      };
  
      if (options.timeout > 0) {
        clearTimeout(timer);
      }
  
      if (response.statusCode >= 200 && response.statusCode < 300) {
        return options.binary ? fetchResponse.blob() : fetchResponse.text();
      }
  
      return fetchResponse.json();
    }).then(function(result) {
      if (response.statusCode >= 200 && response.statusCode < 300) {
        callback(null, response, result);
      } else {
        callback(result, response);
      }
    })["catch"](function(error) {
      callback(error, response);
    });
  
    return {abort: wrappedPromise.reject};
  }
  
  function xhRequest(options, callback) {
  
    var xhr, timer, hasUpload;
  
    var abortReq = function () {
      xhr.abort();
    };
  
    if (options.xhr) {
      xhr = new options.xhr();
    } else {
      xhr = new XMLHttpRequest();
    }
  
    xhr.open(options.method, options.url);
    xhr.withCredentials = true;
  
    if (options.method === 'GET') {
      delete options.headers['Content-Type'];
    } else if (options.json) {
      options.headers.Accept = 'application/json';
      options.headers['Content-Type'] = options.headers['Content-Type'] ||
        'application/json';
      if (options.body &&
          options.processData &&
          typeof options.body !== "string") {
        options.body = JSON.stringify(options.body);
      }
    }
  
    if (options.binary) {
      xhr.responseType = 'arraybuffer';
    }
  
    if (!('body' in options)) {
      options.body = null;
    }
  
    for (var key in options.headers) {
      if (options.headers.hasOwnProperty(key)) {
        xhr.setRequestHeader(key, options.headers[key]);
      }
    }
  
    if (options.timeout > 0) {
      timer = setTimeout(abortReq, options.timeout);
      xhr.onprogress = function () {
        clearTimeout(timer);
        timer = setTimeout(abortReq, options.timeout);
      };
      if (typeof hasUpload === 'undefined') {
        // IE throws an error if you try to access it directly
        hasUpload = Object.keys(xhr).indexOf('upload') !== -1 &&
                    typeof xhr.upload !== 'undefined';
      }
      if (hasUpload) { // does not exist in ie9
        xhr.upload.onprogress = xhr.onprogress;
      }
    }
  
    xhr.onreadystatechange = function () {
      if (xhr.readyState !== 4) {
        return;
      }
  
      var response = {
        statusCode: xhr.status
      };
  
      if (xhr.status >= 200 && xhr.status < 300) {
        var data;
        if (options.binary) {
          data = createBlob([xhr.response || ''], {
            type: xhr.getResponseHeader('Content-Type')
          });
        } else {
          data = xhr.responseText;
        }
        callback(null, response, data);
      } else {
        var err = {};
        try {
          err = JSON.parse(xhr.response);
        } catch(e) {}
        callback(err, response);
      }
    };
  
    if (options.body && (options.body instanceof Blob)) {
      readAsArrayBuffer(options.body, function (arrayBuffer) {
        xhr.send(arrayBuffer);
      });
    } else {
      xhr.send(options.body);
    }
  
    return {abort: abortReq};
  }
  
  function testXhr() {
    try {
      new XMLHttpRequest();
      return true;
    } catch (err) {
      return false;
    }
  }
  
  var hasXhr = testXhr();
  
  module.exports = function(options, callback) {
    if (hasXhr || options.xhr) {
      return xhRequest(options, callback);
    } else {
      return fetchRequest(options, callback);
    }
  };
  
  },{"19":19,"21":21,"53":53}],15:[function(_dereq_,module,exports){
  'use strict';
  
  //Can't find original post, but this is close
  //http://stackoverflow.com/questions/6965107/ (continues on next line)
  //converting-between-strings-and-arraybuffers
  module.exports = function (buffer) {
    var binary = '';
    var bytes = new Uint8Array(buffer);
    var length = bytes.byteLength;
    for (var i = 0; i < length; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    return binary;
  };
  },{}],16:[function(_dereq_,module,exports){
  'use strict';
  
  var buffer = _dereq_(20);
  
  /* istanbul ignore if */
  if (typeof atob === 'function') {
    exports.atob = function (str) {
      /* global atob */
      return atob(str);
    };
  } else {
    exports.atob = function (str) {
      var base64 = new buffer(str, 'base64');
      // Node.js will just skip the characters it can't encode instead of
      // throwing and exception
      if (base64.toString('base64') !== str) {
        throw ("Cannot base64 encode full string");
      }
      return base64.toString('binary');
    };
  }
  
  /* istanbul ignore if */
  if (typeof btoa === 'function') {
    exports.btoa = function (str) {
      /* global btoa */
      return btoa(str);
    };
  } else {
    exports.btoa = function (str) {
      return new buffer(str, 'binary').toString('base64');
    };
  }
  },{"20":20}],17:[function(_dereq_,module,exports){
  'use strict';
  
  // From http://stackoverflow.com/questions/14967647/ (continues on next line)
  // encode-decode-image-with-base64-breaks-image (2013-04-21)
  module.exports = function (bin) {
    var length = bin.length;
    var buf = new ArrayBuffer(length);
    var arr = new Uint8Array(buf);
    for (var i = 0; i < length; i++) {
      arr[i] = bin.charCodeAt(i);
    }
    return buf;
  };
  },{}],18:[function(_dereq_,module,exports){
  'use strict';
  
  var createBlob = _dereq_(19);
  var binaryStringToArrayBuffer = _dereq_(17);
  
  module.exports = function (binString, type) {
    return createBlob([binaryStringToArrayBuffer(binString)], {type: type});
  };
  },{"17":17,"19":19}],19:[function(_dereq_,module,exports){
  "use strict";
  
  // Abstracts constructing a Blob object, so it also works in older
  // browsers that don't support the native Blob constructor (e.g.
  // old QtWebKit versions, Android < 4.4).
  function createBlob(parts, properties) {
    /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
    parts = parts || [];
    properties = properties || {};
    try {
      return new Blob(parts, properties);
    } catch (e) {
      if (e.name !== "TypeError") {
        throw e;
      }
      var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder :
                    typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder :
                    typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder :
                    WebKitBlobBuilder;
      var builder = new Builder();
      for (var i = 0; i < parts.length; i += 1) {
        builder.append(parts[i]);
      }
      return builder.getBlob(properties.type);
    }
  }
  
  module.exports = createBlob;
  
  
  },{}],20:[function(_dereq_,module,exports){
  // hey guess what, we don't need this in the browser
  module.exports = {};
  },{}],21:[function(_dereq_,module,exports){
  'use strict';
  
  // simplified API. universal browser support is assumed
  module.exports = function (blob, callback) {
    var reader = new FileReader();
    reader.onloadend = function (e) {
      var result = e.target.result || new ArrayBuffer(0);
      callback(result);
    };
    reader.readAsArrayBuffer(blob);
  };
  },{}],22:[function(_dereq_,module,exports){
  'use strict';
  
  var arrayBufferToBinaryString = _dereq_(15);
  
  // shim for browsers that don't support it
  module.exports = function (blob, callback) {
    var reader = new FileReader();
    var hasBinaryString = typeof reader.readAsBinaryString === 'function';
    reader.onloadend = function (e) {
      var result = e.target.result || '';
      if (hasBinaryString) {
        return callback(result);
      }
      callback(arrayBufferToBinaryString(result));
    };
    if (hasBinaryString) {
      reader.readAsBinaryString(blob);
    } else {
      reader.readAsArrayBuffer(blob);
    }
  };
  },{"15":15}],23:[function(_dereq_,module,exports){
  'use strict';
  
  function isPlainObject(object) {
    // dead-simple "is this a straight-up object" test, taken
    // from pouchdb-extend ala jQuery 1.9.0
    // Own properties are enumerated firstly, so to speed up,
    // if last one is own, then all properties are own.
  
    if (typeof object.hasOwnProperty !== 'function') {
      return false;
    }
  
    var key;
    for (key in object) {}
    return key === undefined || object.hasOwnProperty(key);
  }
  
  module.exports = function clone(object) {
    var newObject;
    var i;
    var len;
  
    if (!object || typeof object !== 'object') {
      return object;
    }
  
    if (Array.isArray(object)) {
      newObject = [];
      for (i = 0, len = object.length; i < len; i++) {
        newObject[i] = clone(object[i]);
      }
      return newObject;
    }
  
    // special case: to avoid inconsistencies between IndexedDB
    // and other backends, we automatically stringify Dates
    if (object instanceof Date) {
      return object.toISOString();
    }
  
    if (!isPlainObject(object)) {
      return object;
    }
  
    newObject = {};
    for (i in object) {
      if (object.hasOwnProperty(i)) {
        var value = clone(object[i]);
        if (typeof value !== 'undefined') {
          newObject[i] = value;
        }
      }
    }
    return newObject;
  };
  },{}],24:[function(_dereq_,module,exports){
  'use strict';
  
  var winningRev = _dereq_(41);
  
  function getTrees(node) {
    return node.ids;
  }
  
  // check if a specific revision of a doc has been deleted
  //  - metadata: the metadata object from the doc store
  //  - rev: (optional) the revision to check. defaults to winning revision
  function isDeleted(metadata, rev) {
    if (!rev) {
      rev = winningRev(metadata);
    }
    var id = rev.substring(rev.indexOf('-') + 1);
    var toVisit = metadata.rev_tree.map(getTrees);
  
    var tree;
    while ((tree = toVisit.pop())) {
      if (tree[0] === id) {
        return !!tree[1].deleted;
      }
      toVisit = toVisit.concat(tree[2]);
    }
  }
  
  module.exports = isDeleted;
  },{"41":41}],25:[function(_dereq_,module,exports){
  'use strict';
  
  function isLocalId(id) {
    return (/^_local/).test(id);
  }
  
  module.exports = isLocalId;
  },{}],26:[function(_dereq_,module,exports){
  'use strict';
  
  var errors = _dereq_(31);
  var uuid = _dereq_(48);
  
  function toObject(array) {
    return array.reduce(function (obj, item) {
      obj[item] = true;
      return obj;
    }, {});
  }
  // List of top level reserved words for doc
  var reservedWords = toObject([
    '_id',
    '_rev',
    '_attachments',
    '_deleted',
    '_revisions',
    '_revs_info',
    '_conflicts',
    '_deleted_conflicts',
    '_local_seq',
    '_rev_tree',
    //replication documents
    '_replication_id',
    '_replication_state',
    '_replication_state_time',
    '_replication_state_reason',
    '_replication_stats',
    // Specific to Couchbase Sync Gateway
    '_removed'
  ]);
  
  // List of reserved words that should end up the document
  var dataWords = toObject([
    '_attachments',
    //replication documents
    '_replication_id',
    '_replication_state',
    '_replication_state_time',
    '_replication_state_reason',
    '_replication_stats'
  ]);
  
  // Determine id an ID is valid
  //   - invalid IDs begin with an underescore that does not begin '_design' or
  //     '_local'
  //   - any other string value is a valid id
  // Returns the specific error object for each case
  exports.invalidIdError = function (id) {
    var err;
    if (!id) {
      err = errors.error(errors.MISSING_ID);
    } else if (typeof id !== 'string') {
      err = errors.error(errors.INVALID_ID);
    } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) {
      err = errors.error(errors.RESERVED_ID);
    }
    if (err) {
      throw err;
    }
  };
  
  function parseRevisionInfo(rev) {
    if (!/^\d+\-./.test(rev)) {
      return errors.error(errors.INVALID_REV);
    }
    var idx = rev.indexOf('-');
    var left = rev.substring(0, idx);
    var right = rev.substring(idx + 1);
    return {
      prefix: parseInt(left, 10),
      id: right
    };
  }
  
  function makeRevTreeFromRevisions(revisions, opts) {
    var pos = revisions.start - revisions.ids.length + 1;
  
    var revisionIds = revisions.ids;
    var ids = [revisionIds[0], opts, []];
  
    for (var i = 1, len = revisionIds.length; i < len; i++) {
      ids = [revisionIds[i], {status: 'missing'}, [ids]];
    }
  
    return [{
      pos: pos,
      ids: ids
    }];
  }
  
  // Preprocess documents, parse their revisions, assign an id and a
  // revision for new writes that are missing them, etc
  exports.parseDoc = function (doc, newEdits) {
  
    var nRevNum;
    var newRevId;
    var revInfo;
    var opts = {status: 'available'};
    if (doc._deleted) {
      opts.deleted = true;
    }
  
    if (newEdits) {
      if (!doc._id) {
        doc._id = uuid();
      }
      newRevId = uuid(32, 16).toLowerCase();
      if (doc._rev) {
        revInfo = parseRevisionInfo(doc._rev);
        if (revInfo.error) {
          return revInfo;
        }
        doc._rev_tree = [{
          pos: revInfo.prefix,
          ids: [revInfo.id, {status: 'missing'}, [[newRevId, opts, []]]]
        }];
        nRevNum = revInfo.prefix + 1;
      } else {
        doc._rev_tree = [{
          pos: 1,
          ids : [newRevId, opts, []]
        }];
        nRevNum = 1;
      }
    } else {
      if (doc._revisions) {
        doc._rev_tree = makeRevTreeFromRevisions(doc._revisions, opts);
        nRevNum = doc._revisions.start;
        newRevId = doc._revisions.ids[0];
      }
      if (!doc._rev_tree) {
        revInfo = parseRevisionInfo(doc._rev);
        if (revInfo.error) {
          return revInfo;
        }
        nRevNum = revInfo.prefix;
        newRevId = revInfo.id;
        doc._rev_tree = [{
          pos: nRevNum,
          ids: [newRevId, opts, []]
        }];
      }
    }
  
    exports.invalidIdError(doc._id);
  
    doc._rev = nRevNum + '-' + newRevId;
  
    var result = {metadata : {}, data : {}};
    for (var key in doc) {
      /* istanbul ignore else */
      if (Object.prototype.hasOwnProperty.call(doc, key)) {
        var specialKey = key[0] === '_';
        if (specialKey && !reservedWords[key]) {
          var error = errors.error(errors.DOC_VALIDATION, key);
          error.message = errors.DOC_VALIDATION.message + ': ' + key;
          throw error;
        } else if (specialKey && !dataWords[key]) {
          result.metadata[key.slice(1)] = doc[key];
        } else {
          result.data[key] = doc[key];
        }
      }
    }
    return result;
  };
  
  },{"31":31,"48":48}],27:[function(_dereq_,module,exports){
  'use strict';
  
  var errors = _dereq_(31);
  var updateDoc = _dereq_(28);
  var isDeleted = _dereq_(24);
  var isLocalId = _dereq_(25);
  var calculateWinningRev = _dereq_(41);
  var merge = _dereq_(37);
  var collections = _dereq_(150);
  var Map = collections.Map;
  
  function processDocs(docInfos, api, fetchedDocs, tx, results, writeDoc, opts,
                       overallCallback) {
  
    function insertDoc(docInfo, resultsIdx, callback) {
      // Cant insert new deleted documents
      var winningRev = calculateWinningRev(docInfo.metadata);
      var deleted = isDeleted(docInfo.metadata, winningRev);
      if ('was_delete' in opts && deleted) {
        results[resultsIdx] = errors.error(errors.MISSING_DOC, 'deleted');
        return callback();
      }
  
      var delta = deleted ? 0 : 1;
  
      writeDoc(docInfo, winningRev, deleted, deleted, false,
        delta, resultsIdx, callback);
    }
  
    var newEdits = opts.new_edits;
    var idsToDocs = new Map();
  
    var docsDone = 0;
    var docsToDo = docInfos.length;
  
    function checkAllDocsDone() {
      if (++docsDone === docsToDo && overallCallback) {
        overallCallback();
      }
    }
  
    docInfos.forEach(function (currentDoc, resultsIdx) {
  
      if (currentDoc._id && isLocalId(currentDoc._id)) {
        api[currentDoc._deleted ? '_removeLocal' : '_putLocal'](
          currentDoc, {ctx: tx}, function (err) {
            if (err) {
              results[resultsIdx] = err;
            } else {
              results[resultsIdx] = {ok: true};
            }
            checkAllDocsDone();
          });
        return;
      }
  
      var id = currentDoc.metadata.id;
      if (idsToDocs.has(id)) {
        docsToDo--; // duplicate
        idsToDocs.get(id).push([currentDoc, resultsIdx]);
      } else {
        idsToDocs.set(id, [[currentDoc, resultsIdx]]);
      }
    });
  
    // in the case of new_edits, the user can provide multiple docs
    // with the same id. these need to be processed sequentially
    idsToDocs.forEach(function (docs, id) {
      var numDone = 0;
  
      function docWritten() {
        if (++numDone < docs.length) {
          nextDoc();
        } else {
          checkAllDocsDone();
        }
      }
      function nextDoc() {
        var value = docs[numDone];
        var currentDoc = value[0];
        var resultsIdx = value[1];
  
        if (fetchedDocs.has(id)) {
          updateDoc(fetchedDocs.get(id), currentDoc, results,
            resultsIdx, docWritten, writeDoc, newEdits);
        } else {
          // Ensure stemming applies to new writes as well
          var merged = merge([], currentDoc.metadata.rev_tree[0], 1000);
          currentDoc.metadata.rev_tree = merged.tree;
          insertDoc(currentDoc, resultsIdx, docWritten);
        }
      }
      nextDoc();
    });
  }
  
  module.exports = processDocs;
  
  },{"150":150,"24":24,"25":25,"28":28,"31":31,"37":37,"41":41}],28:[function(_dereq_,module,exports){
  'use strict';
  
  var errors = _dereq_(31);
  var isDeleted = _dereq_(24);
  var parseDoc = _dereq_(26).parseDoc;
  var calculateWinningRev = _dereq_(41);
  var merge = _dereq_(37);
  var revExists = _dereq_(38);
  
  function updateDoc(prev, docInfo, results, i, cb, writeDoc, newEdits) {
  
    if (revExists(prev.rev_tree, docInfo.metadata.rev)) {
      results[i] = docInfo;
      return cb();
    }
  
    // sometimes this is pre-calculated. historically not always
    var previousWinningRev = prev.winningRev || calculateWinningRev(prev);
    var previouslyDeleted = 'deleted' in prev ? prev.deleted :
      isDeleted(prev, previousWinningRev);
    var deleted = 'deleted' in docInfo.metadata ? docInfo.metadata.deleted :
      isDeleted(docInfo.metadata);
    var isRoot = /^1-/.test(docInfo.metadata.rev);
  
    if (previouslyDeleted && !deleted && newEdits && isRoot) {
      var newDoc = docInfo.data;
      newDoc._rev = previousWinningRev;
      newDoc._id = docInfo.metadata.id;
      docInfo = parseDoc(newDoc, newEdits);
    }
  
    var merged = merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000);
  
    var inConflict = newEdits && (((previouslyDeleted && deleted) ||
      (!previouslyDeleted && merged.conflicts !== 'new_leaf') ||
      (previouslyDeleted && !deleted && merged.conflicts === 'new_branch')));
  
    if (inConflict) {
      var err = errors.error(errors.REV_CONFLICT);
      results[i] = err;
      return cb();
    }
  
    var newRev = docInfo.metadata.rev;
    docInfo.metadata.rev_tree = merged.tree;
    /* istanbul ignore else */
    if (prev.rev_map) {
      docInfo.metadata.rev_map = prev.rev_map; // used only by leveldb
    }
  
    // recalculate
    var winningRev = calculateWinningRev(docInfo.metadata);
    var winningRevIsDeleted = isDeleted(docInfo.metadata, winningRev);
  
    // calculate the total number of documents that were added/removed,
    // from the perspective of total_rows/doc_count
    var delta = (previouslyDeleted === winningRevIsDeleted) ? 0 :
      previouslyDeleted < winningRevIsDeleted ? -1 : 1;
  
    var newRevIsDeleted;
    if (newRev === winningRev) {
      // if the new rev is the same as the winning rev, we can reuse that value
      newRevIsDeleted = winningRevIsDeleted;
    } else {
      // if they're not the same, then we need to recalculate
      newRevIsDeleted = isDeleted(docInfo.metadata, newRev);
    }
  
    writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
      true, delta, i, cb);
  }
  
  module.exports = updateDoc;
  },{"24":24,"26":26,"31":31,"37":37,"38":38,"41":41}],29:[function(_dereq_,module,exports){
  'use strict';
  
  var isChromeApp = _dereq_(30);
  
  var hasLocal;
  
  if (isChromeApp()) {
    hasLocal = false;
  } else {
    try {
      localStorage.setItem('_pouch_check_localstorage', 1);
      hasLocal = !!localStorage.getItem('_pouch_check_localstorage');
    } catch (e) {
      hasLocal = false;
    }
  }
  
  module.exports = function hasLocalStorage() {
    return hasLocal;
  };
  },{"30":30}],30:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = function isChromeApp() {
    return (typeof chrome !== "undefined" &&
      typeof chrome.storage !== "undefined" &&
      typeof chrome.storage.local !== "undefined");
  };
  },{}],31:[function(_dereq_,module,exports){
  "use strict";
  
  var inherits = _dereq_(84);
  inherits(PouchError, Error);
  
  function PouchError(opts) {
    Error.call(this, opts.reason);
    this.status = opts.status;
    this.name = opts.error;
    this.message = opts.reason;
    this.error = true;
  }
  
  PouchError.prototype.toString = function () {
    return JSON.stringify({
      status: this.status,
      name: this.name,
      message: this.message
    });
  };
  
  exports.UNAUTHORIZED = new PouchError({
    status: 401,
    error: 'unauthorized',
    reason: "Name or password is incorrect."
  });
  
  exports.MISSING_BULK_DOCS = new PouchError({
    status: 400,
    error: 'bad_request',
    reason: "Missing JSON list of 'docs'"
  });
  
  exports.MISSING_DOC = new PouchError({
    status: 404,
    error: 'not_found',
    reason: 'missing'
  });
  
  exports.REV_CONFLICT = new PouchError({
    status: 409,
    error: 'conflict',
    reason: 'Document update conflict'
  });
  
  exports.INVALID_ID = new PouchError({
    status: 400,
    error: 'invalid_id',
    reason: '_id field must contain a string'
  });
  
  exports.MISSING_ID = new PouchError({
    status: 412,
    error: 'missing_id',
    reason: '_id is required for puts'
  });
  
  exports.RESERVED_ID = new PouchError({
    status: 400,
    error: 'bad_request',
    reason: 'Only reserved document ids may start with underscore.'
  });
  
  exports.NOT_OPEN = new PouchError({
    status: 412,
    error: 'precondition_failed',
    reason: 'Database not open'
  });
  
  exports.UNKNOWN_ERROR = new PouchError({
    status: 500,
    error: 'unknown_error',
    reason: 'Database encountered an unknown error'
  });
  
  exports.BAD_ARG = new PouchError({
    status: 500,
    error: 'badarg',
    reason: 'Some query argument is invalid'
  });
  
  exports.INVALID_REQUEST = new PouchError({
    status: 400,
    error: 'invalid_request',
    reason: 'Request was invalid'
  });
  
  exports.QUERY_PARSE_ERROR = new PouchError({
    status: 400,
    error: 'query_parse_error',
    reason: 'Some query parameter is invalid'
  });
  
  exports.DOC_VALIDATION = new PouchError({
    status: 500,
    error: 'doc_validation',
    reason: 'Bad special document member'
  });
  
  exports.BAD_REQUEST = new PouchError({
    status: 400,
    error: 'bad_request',
    reason: 'Something wrong with the request'
  });
  
  exports.NOT_AN_OBJECT = new PouchError({
    status: 400,
    error: 'bad_request',
    reason: 'Document must be a JSON object'
  });
  
  exports.DB_MISSING = new PouchError({
    status: 404,
    error: 'not_found',
    reason: 'Database not found'
  });
  
  exports.IDB_ERROR = new PouchError({
    status: 500,
    error: 'indexed_db_went_bad',
    reason: 'unknown'
  });
  
  exports.WSQ_ERROR = new PouchError({
    status: 500,
    error: 'web_sql_went_bad',
    reason: 'unknown'
  });
  
  exports.LDB_ERROR = new PouchError({
    status: 500,
    error: 'levelDB_went_went_bad',
    reason: 'unknown'
  });
  
  exports.FORBIDDEN = new PouchError({
    status: 403,
    error: 'forbidden',
    reason: 'Forbidden by design doc validate_doc_update function'
  });
  
  exports.INVALID_REV = new PouchError({
    status: 400,
    error: 'bad_request',
    reason: 'Invalid rev format'
  });
  
  exports.FILE_EXISTS = new PouchError({
    status: 412,
    error: 'file_exists',
    reason: 'The database could not be created, the file already exists.'
  });
  
  exports.MISSING_STUB = new PouchError({
    status: 412,
    error: 'missing_stub'
  });
  
  exports.error = function (error, reason, name) {
    function CustomPouchError(reason) {
      // inherit error properties from our parent error manually
      // so as to allow proper JSON parsing.
      /* jshint ignore:start */
      for (var p in error) {
        if (typeof error[p] !== 'function') {
          this[p] = error[p];
        }
      }
      /* jshint ignore:end */
      if (name !== undefined) {
        this.name = name;
      }
      if (reason !== undefined) {
        this.reason = reason;
      }
    }
    CustomPouchError.prototype = PouchError.prototype;
    return new CustomPouchError(reason);
  };
  
  // Find one of the errors defined above based on the value
  // of the specified property.
  // If reason is provided prefer the error matching that reason.
  // This is for differentiating between errors with the same name and status,
  // eg, bad_request.
  exports.getErrorTypeByProp = function (prop, value, reason) {
    var errors = exports;
    var keys = Object.keys(errors).filter(function (key) {
      var error = errors[key];
      return typeof error !== 'function' && error[prop] === value;
    });
    var key = reason && keys.filter(function (key) {
          var error = errors[key];
          return error.message === reason;
        })[0] || keys[0];
    return (key) ? errors[key] : null;
  };
  
  exports.generateErrorFromResponse = function (res) {
    var error, errName, errType, errMsg, errReason;
    var errors = exports;
  
    errName = (res.error === true && typeof res.name === 'string') ?
                res.name :
                res.error;
    errReason = res.reason;
    errType = errors.getErrorTypeByProp('name', errName, errReason);
  
    if (res.missing ||
        errReason === 'missing' ||
        errReason === 'deleted' ||
        errName === 'not_found') {
      errType = errors.MISSING_DOC;
    } else if (errName === 'doc_validation') {
      // doc validation needs special treatment since
      // res.reason depends on the validation error.
      // see utils.js
      errType = errors.DOC_VALIDATION;
      errMsg = errReason;
    } else if (errName === 'bad_request' && errType.message !== errReason) {
      // if bad_request error already found based on reason don't override.
      errType = errors.BAD_REQUEST;
    }
  
    // fallback to error by status or unknown error.
    if (!errType) {
      errType = errors.getErrorTypeByProp('status', res.status, errReason) ||
                  errors.UNKNOWN_ERROR;
    }
  
    error = errors.error(errType, errReason, errName);
  
    // Keep custom message.
    if (errMsg) {
      error.message = errMsg;
    }
  
    // Keep helpful response data in our error messages.
    if (res.id) {
      error.id = res.id;
    }
    if (res.status) {
      error.status = res.status;
    }
    if (res.missing) {
      error.missing = res.missing;
    }
  
    return error;
  };
  
  },{"84":84}],32:[function(_dereq_,module,exports){
  'use strict';
  
  var clone = _dereq_(23);
  
  function extendInner(obj, otherObj) {
    for (var key in otherObj) {
      if (otherObj.hasOwnProperty(key)) {
        var value = clone(otherObj[key]);
        if (typeof value !== 'undefined') {
          obj[key] = value;
        }
      }
    }
  }
  
  module.exports = function extend(obj, obj2, obj3) {
    extendInner(obj, obj2);
    if (obj3) {
      extendInner(obj, obj3);
    }
    return obj;
  };
  },{"23":23}],33:[function(_dereq_,module,exports){
  'use strict';
  
  // shim for Function.prototype.name,
  // for browsers that don't support it like IE
  if ((function f() {}).name) {
    module.exports = function (fun) {
      return fun.name;
    };
  } else {
    module.exports = function (fun) {
      return fun.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];
    };
  }
  
  },{}],34:[function(_dereq_,module,exports){
  (function (global){
  'use strict';
  
  var toPromise = _dereq_(47);
  var base64 = _dereq_(16);
  var Md5 = _dereq_(151);
  var setImmediateShim = global.setImmediate || global.setTimeout;
  var MD5_CHUNK_SIZE = 32768;
  
  // convert a 64-bit int to a binary string
  function intToString(int) {
    return String.fromCharCode(int & 0xff) +
      String.fromCharCode((int >>> 8) & 0xff) +
      String.fromCharCode((int >>> 16) & 0xff) +
      String.fromCharCode((int >>> 24) & 0xff);
  }
  
  // convert an array of 64-bit ints into
  // a base64-encoded string
  function rawToBase64(raw) {
    var res = '';
    for (var i = 0, len = raw.length; i < len; i++) {
      res += intToString(raw[i]);
    }
    return base64.btoa(res);
  }
  
  function appendBuffer(buffer, data, start, end) {
    if (start > 0 || end < data.byteLength) {
      // only create a subarray if we really need to
      data = new Uint8Array(data, start,
        Math.min(end, data.byteLength) - start);
    }
    buffer.append(data);
  }
  
  function appendString(buffer, data, start, end) {
    if (start > 0 || end < data.length) {
      // only create a substring if we really need to
      data = data.substring(start, end);
    }
    buffer.appendBinary(data);
  }
  
  module.exports = toPromise(function (data, callback) {
    var inputIsString = typeof data === 'string';
    var len = inputIsString ? data.length : data.byteLength;
    var chunkSize = Math.min(MD5_CHUNK_SIZE, len);
    var chunks = Math.ceil(len / chunkSize);
    var currentChunk = 0;
    var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer();
  
    var append = inputIsString ? appendString : appendBuffer;
  
    function loadNextChunk() {
      var start = currentChunk * chunkSize;
      var end = start + chunkSize;
      currentChunk++;
      if (currentChunk < chunks) {
        append(buffer, data, start, end);
        setImmediateShim(loadNextChunk);
      } else {
        append(buffer, data, start, end);
        var raw = buffer.end(true);
        var base64 = rawToBase64(raw);
        callback(null, base64);
        buffer.destroy();
      }
    }
    loadNextChunk();
  });
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"151":151,"16":16,"47":47}],35:[function(_dereq_,module,exports){
  'use strict';
  
  var winningRev = _dereq_(41);
  var collectLeaves = _dereq_(36);
  
  // returns revs of all conflicts that is leaves such that
  // 1. are not deleted and
  // 2. are different than winning revision
  module.exports = function collectConflicts(metadata) {
    var win = winningRev(metadata);
    var leaves = collectLeaves(metadata.rev_tree);
    var conflicts = [];
    for (var i = 0, len = leaves.length; i < len; i++) {
      var leaf = leaves[i];
      if (leaf.rev !== win && !leaf.opts.deleted) {
        conflicts.push(leaf.rev);
      }
    }
    return conflicts;
  };
  },{"36":36,"41":41}],36:[function(_dereq_,module,exports){
  'use strict';
  
  var traverseRevTree = _dereq_(40);
  
  function sortByPos(a, b) {
    return a.pos - b.pos;
  }
  
  module.exports = function collectLeaves(revs) {
    var leaves = [];
    traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) {
      if (isLeaf) {
        leaves.push({rev: pos + "-" + id, pos: pos, opts: opts});
      }
    });
    leaves.sort(sortByPos).reverse();
    for (var i = 0, len = leaves.length; i < len; i++) {
      delete leaves[i].pos;
    }
    return leaves;
  };
  },{"40":40}],37:[function(_dereq_,module,exports){
  'use strict';
  
  // for a better overview of what this is doing, read:
  // https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl
  //
  // But for a quick intro, CouchDB uses a revision tree to store a documents
  // history, A -> B -> C, when a document has conflicts, that is a branch in the
  // tree, A -> (B1 | B2 -> C), We store these as a nested array in the format
  //
  // KeyTree = [Path ... ]
  // Path = {pos: position_from_root, ids: Tree}
  // Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []]
  
  var rootToLeaf = _dereq_(39);
  
  function sortByPos(a, b) {
    return a.pos - b.pos;
  }
  
  // classic binary search
  function binarySearch(arr, item, comparator) {
    var low = 0;
    var high = arr.length;
    var mid;
    while (low < high) {
      mid = (low + high) >>> 1;
      if (comparator(arr[mid], item) < 0) {
        low = mid + 1;
      } else {
        high = mid;
      }
    }
    return low;
  }
  
  // assuming the arr is sorted, insert the item in the proper place
  function insertSorted(arr, item, comparator) {
    var idx = binarySearch(arr, item, comparator);
    arr.splice(idx, 0, item);
  }
  
  // Turn a path as a flat array into a tree with a single branch.
  // If any should be stemmed from the beginning of the array, that's passed
  // in as the second argument
  function pathToTree(path, numStemmed) {
    var root;
    var leaf;
    for (var i = numStemmed, len = path.length; i < len; i++) {
      var node = path[i];
      var currentLeaf = [node.id, node.opts, []];
      if (leaf) {
        leaf[2].push(currentLeaf);
        leaf = currentLeaf;
      } else {
        root = leaf = currentLeaf;
      }
    }
    return root;
  }
  
  // compare the IDs of two trees
  function compareTree(a, b) {
    return a[0] < b[0] ? -1 : 1;
  }
  
  // Merge two trees together
  // The roots of tree1 and tree2 must be the same revision
  function mergeTree(in_tree1, in_tree2) {
    var queue = [{tree1: in_tree1, tree2: in_tree2}];
    var conflicts = false;
    while (queue.length > 0) {
      var item = queue.pop();
      var tree1 = item.tree1;
      var tree2 = item.tree2;
  
      if (tree1[1].status || tree2[1].status) {
        tree1[1].status =
          (tree1[1].status ===  'available' ||
          tree2[1].status === 'available') ? 'available' : 'missing';
      }
  
      for (var i = 0; i < tree2[2].length; i++) {
        if (!tree1[2][0]) {
          conflicts = 'new_leaf';
          tree1[2][0] = tree2[2][i];
          continue;
        }
  
        var merged = false;
        for (var j = 0; j < tree1[2].length; j++) {
          if (tree1[2][j][0] === tree2[2][i][0]) {
            queue.push({tree1: tree1[2][j], tree2: tree2[2][i]});
            merged = true;
          }
        }
        if (!merged) {
          conflicts = 'new_branch';
          insertSorted(tree1[2], tree2[2][i], compareTree);
        }
      }
    }
    return {conflicts: conflicts, tree: in_tree1};
  }
  
  function doMerge(tree, path, dontExpand) {
    var restree = [];
    var conflicts = false;
    var merged = false;
    var res;
  
    if (!tree.length) {
      return {tree: [path], conflicts: 'new_leaf'};
    }
  
    for (var i = 0, len = tree.length; i < len; i++) {
      var branch = tree[i];
      if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) {
        // Paths start at the same position and have the same root, so they need
        // merged
        res = mergeTree(branch.ids, path.ids);
        restree.push({pos: branch.pos, ids: res.tree});
        conflicts = conflicts || res.conflicts;
        merged = true;
      } else if (dontExpand !== true) {
        // The paths start at a different position, take the earliest path and
        // traverse up until it as at the same point from root as the path we
        // want to merge.  If the keys match we return the longer path with the
        // other merged After stemming we dont want to expand the trees
  
        var t1 = branch.pos < path.pos ? branch : path;
        var t2 = branch.pos < path.pos ? path : branch;
        var diff = t2.pos - t1.pos;
  
        var candidateParents = [];
  
        var trees = [];
        trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null});
        while (trees.length > 0) {
          var item = trees.pop();
          if (item.diff === 0) {
            if (item.ids[0] === t2.ids[0]) {
              candidateParents.push(item);
            }
            continue;
          }
          var elements = item.ids[2];
          for (var j = 0, elementsLen = elements.length; j < elementsLen; j++) {
            trees.push({
              ids: elements[j],
              diff: item.diff - 1,
              parent: item.ids,
              parentIdx: j
            });
          }
        }
  
        var el = candidateParents[0];
  
        if (!el) {
          restree.push(branch);
        } else {
          res = mergeTree(el.ids, t2.ids);
          el.parent[2][el.parentIdx] = res.tree;
          restree.push({pos: t1.pos, ids: t1.ids});
          conflicts = conflicts || res.conflicts;
          merged = true;
        }
      } else {
        restree.push(branch);
      }
    }
  
    // We didnt find
    if (!merged) {
      restree.push(path);
    }
  
    restree.sort(sortByPos);
  
    return {
      tree: restree,
      conflicts: conflicts || 'internal_node'
    };
  }
  
  // To ensure we dont grow the revision tree infinitely, we stem old revisions
  function stem(tree, depth) {
    // First we break out the tree into a complete list of root to leaf paths
    var paths = rootToLeaf(tree);
    var result;
    for (var i = 0, len = paths.length; i < len; i++) {
      // Then for each path, we cut off the start of the path based on the
      // `depth` to stem to, and generate a new set of flat trees
      var path = paths[i];
      var stemmed = path.ids;
      var numStemmed = Math.max(0, stemmed.length - depth);
      var stemmedNode = {
        pos: path.pos + numStemmed,
        ids: pathToTree(stemmed, numStemmed)
      };
      // Then we remerge all those flat trees together, ensuring that we dont
      // connect trees that would go beyond the depth limit
      if (result) {
        result = doMerge(result, stemmedNode, true).tree;
      } else {
        result = [stemmedNode];
      }
    }
    return result;
  }
  
  module.exports = function merge(tree, path, depth) {
    var newTree = doMerge(tree, path);
    return {
      tree: stem(newTree.tree, depth),
      conflicts: newTree.conflicts
    };
  };
  },{"39":39}],38:[function(_dereq_,module,exports){
  'use strict';
  
  // return true if a rev exists in the rev tree, false otherwise
  module.exports = function revExists(revs, rev) {
    var toVisit = revs.slice();
    var splitRev = rev.split('-');
    var targetPos = parseInt(splitRev[0], 10);
    var targetId = splitRev[1];
  
    var node;
    while ((node = toVisit.pop())) {
      if (node.pos === targetPos && node.ids[0] === targetId) {
        return true;
      }
      var branches = node.ids[2];
      for (var i = 0, len = branches.length; i < len; i++) {
        toVisit.push({pos: node.pos + 1, ids: branches[i]});
      }
    }
    return false;
  };
  },{}],39:[function(_dereq_,module,exports){
  'use strict';
  // build up a list of all the paths to the leafs in this revision tree
  module.exports = function rootToLeaf(revs) {
    var paths = [];
    var toVisit = revs.slice();
    var node;
    while ((node = toVisit.pop())) {
      var pos = node.pos;
      var tree = node.ids;
      var id = tree[0];
      var opts = tree[1];
      var branches = tree[2];
      var isLeaf = branches.length === 0;
  
      var history = node.history ? node.history.slice() : [];
      history.push({id: id, opts: opts});
      if (isLeaf) {
        paths.push({pos: (pos + 1 - history.length), ids: history});
      }
      for (var i = 0, len = branches.length; i < len; i++) {
        toVisit.push({pos: pos + 1, ids: branches[i], history: history});
      }
    }
    return paths.reverse();
  };
  },{}],40:[function(_dereq_,module,exports){
  'use strict';
  
  // Pretty much all below can be combined into a higher order function to
  // traverse revisions
  // The return value from the callback will be passed as context to all
  // children of that node
  module.exports = function traverseRevTree(revs, callback) {
    var toVisit = revs.slice();
  
    var node;
    while ((node = toVisit.pop())) {
      var pos = node.pos;
      var tree = node.ids;
      var branches = tree[2];
      var newCtx =
        callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]);
      for (var i = 0, len = branches.length; i < len; i++) {
        toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx});
      }
    }
  };
  },{}],41:[function(_dereq_,module,exports){
  'use strict';
  
  // We fetch all leafs of the revision tree, and sort them based on tree length
  // and whether they were deleted, undeleted documents with the longest revision
  // tree (most edits) win
  // The final sort algorithm is slightly documented in a sidebar here:
  // http://guide.couchdb.org/draft/conflicts.html
  module.exports = function winningRev(metadata) {
    var winningId;
    var winningPos;
    var winningDeleted;
    var toVisit = metadata.rev_tree.slice();
    var node;
    while ((node = toVisit.pop())) {
      var tree = node.ids;
      var branches = tree[2];
      var pos = node.pos;
      if (branches.length) { // non-leaf
        for (var i = 0, len = branches.length; i < len; i++) {
          toVisit.push({pos: pos + 1, ids: branches[i]});
        }
        continue;
      }
      var deleted = !!tree[1].deleted;
      var id = tree[0];
      // sort by deleted, then pos, then id
      if (!winningId || (winningDeleted !== deleted ? winningDeleted :
          winningPos !== pos ? winningPos < pos : winningId < id)) {
        winningId = id;
        winningPos = pos;
        winningDeleted = deleted;
      }
    }
  
    return winningPos + '-' + winningId;
  };
  },{}],42:[function(_dereq_,module,exports){
  (function (process){
  'use strict';
  // in the browser, LevelAlt doesn't need the
  // pre-2.2.0 LevelDB-specific migrations
  exports.toSublevel = function (name, db, callback) {
    process.nextTick(function () {
      callback();
    });
  };
  
  exports.localAndMetaStores = function (db, stores, callback) {
    process.nextTick(function () {
      callback();
    });
  };
  }).call(this,_dereq_(62))
  },{"62":62}],43:[function(_dereq_,module,exports){
  'use strict';
  
  var getArguments = _dereq_(54);
  
  function once(fun) {
    var called = false;
    return getArguments(function (args) {
      /* istanbul ignore if */
      if (called) {
        // this is a smoke test and should never actually happen
        throw new Error('once called more than once');
      } else {
        called = true;
        fun.apply(this, args);
      }
    });
  }
  
  module.exports = once;
  },{"54":54}],44:[function(_dereq_,module,exports){
  'use strict';
  
  // originally parseUri 1.2.2, now patched by us
  // (c) Steven Levithan <stevenlevithan.com>
  // MIT License
  var keys = ["source", "protocol", "authority", "userInfo", "user", "password",
      "host", "port", "relative", "path", "directory", "file", "query", "anchor"];
  var qName ="queryKey";
  var qParser = /(?:^|&)([^&=]*)=?([^&]*)/g;
  
  // use the "loose" parser
  /* jshint maxlen: false */
  var parser = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
  
  function parseUri(str) {
    var m = parser.exec(str);
    var uri = {};
    var i = 14;
  
    while (i--) {
      var key = keys[i];
      var value = m[i] || "";
      var encoded = ['user', 'password'].indexOf(key) !== -1;
      uri[key] = encoded ? decodeURIComponent(value) : value;
    }
  
    uri[qName] = {};
    uri[keys[12]].replace(qParser, function ($0, $1, $2) {
      if ($1) {
        uri[qName][$1] = $2;
      }
    });
  
    return uri;
  }
  
  module.exports = parseUri;
  },{}],45:[function(_dereq_,module,exports){
  'use strict';
  
  // like underscore/lodash _.pick()
  module.exports = function pick(obj, arr) {
    var res = {};
    for (var i = 0, len = arr.length; i < len; i++) {
      var prop = arr[i];
      if (prop in obj) {
        res[prop] = obj[prop];
      }
    }
    return res;
  };
  },{}],46:[function(_dereq_,module,exports){
  'use strict';
  /* istanbul ignore next */
  module.exports = typeof Promise === 'function' ? Promise : _dereq_(139);
  
  },{"139":139}],47:[function(_dereq_,module,exports){
  (function (process){
  'use strict';
  
  var Promise = _dereq_(46);
  var getArguments = _dereq_(54);
  var once = _dereq_(43);
  
  function toPromise(func) {
    //create the function we will be returning
    return getArguments(function (args) {
      var self = this;
      var tempCB =
        (typeof args[args.length - 1] === 'function') ? args.pop() : false;
      // if the last argument is a function, assume its a callback
      var usedCB;
      if (tempCB) {
        // if it was a callback, create a new callback which calls it,
        // but do so async so we don't trap any errors
        usedCB = function (err, resp) {
          process.nextTick(function () {
            tempCB(err, resp);
          });
        };
      }
      var promise = new Promise(function (fulfill, reject) {
        var resp;
        try {
          var callback = once(function (err, mesg) {
            if (err) {
              reject(err);
            } else {
              fulfill(mesg);
            }
          });
          // create a callback for this invocation
          // apply the function in the orig context
          args.push(callback);
          resp = func.apply(self, args);
          if (resp && typeof resp.then === 'function') {
            fulfill(resp);
          }
        } catch (e) {
          reject(e);
        }
      });
      // if there is a callback, call it back
      if (usedCB) {
        promise.then(function (result) {
          usedCB(null, result);
        }, usedCB);
      }
      return promise;
    });
  }
  
  module.exports = toPromise;
  }).call(this,_dereq_(62))
  },{"43":43,"46":46,"54":54,"62":62}],48:[function(_dereq_,module,exports){
  "use strict";
  
  // BEGIN Math.uuid.js
  
  /*!
  Math.uuid.js (v1.4)
  http://www.broofa.com
  mailto:robert@broofa.com
  
  Copyright (c) 2010 Robert Kieffer
  Dual licensed under the MIT and GPL licenses.
  */
  
  /*
   * Generate a random uuid.
   *
   * USAGE: Math.uuid(length, radix)
   *   length - the desired number of characters
   *   radix  - the number of allowable values for each character.
   *
   * EXAMPLES:
   *   // No arguments  - returns RFC4122, version 4 ID
   *   >>> Math.uuid()
   *   "92329D39-6F5C-4520-ABFC-AAB64544E172"
   *
   *   // One argument - returns ID of the specified length
   *   >>> Math.uuid(15)     // 15 character ID (default base=62)
   *   "VcydxgltxrVZSTV"
   *
   *   // Two arguments - returns ID of the specified length, and radix. 
   *   // (Radix must be <= 62)
   *   >>> Math.uuid(8, 2)  // 8 character ID (base=2)
   *   "01001010"
   *   >>> Math.uuid(8, 10) // 8 character ID (base=10)
   *   "47473046"
   *   >>> Math.uuid(8, 16) // 8 character ID (base=16)
   *   "098F4D35"
   */
  var chars = (
    '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
    'abcdefghijklmnopqrstuvwxyz'
  ).split('');
  function getValue(radix) {
    return 0 | Math.random() * radix;
  }
  function uuid(len, radix) {
    radix = radix || chars.length;
    var out = '';
    var i = -1;
  
    if (len) {
      // Compact form
      while (++i < len) {
        out += chars[getValue(radix)];
      }
      return out;
    }
      // rfc4122, version 4 form
      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
    while (++i < 36) {
      switch (i) {
        case 8:
        case 13:
        case 18:
        case 23:
          out += '-';
          break;
        case 19:
          out += chars[(getValue(16) & 0x3) | 0x8];
          break;
        default:
          out += chars[getValue(16)];
      }
    }
  
    return out;
  }
  
  
  
  module.exports = uuid;
  
  
  },{}],49:[function(_dereq_,module,exports){
  'use strict';
  /* global PouchDB */
  
  function pluginBase(adapterConfig, downAdapter) {
    var adapterName = adapterConfig.name;
    var adapter = _dereq_(50)(adapterConfig, downAdapter);
    // use global PouchDB if it's there (e.g. window.PouchDB)
    var PDB = (typeof PouchDB !== 'undefined') ? PouchDB : _dereq_("pouchdb");
    if (!PDB) {
      console.error(adapterConfig.name + ' adapter plugin error: ' +
        'Cannot find global "PouchDB" object! ' +
        'Did you remember to include pouchdb.js?');
    } else {
      PDB.adapter(adapterName, adapter, true);
    }
  }
  
  module.exports = pluginBase;
  },{"50":50,"pouchdb":"pouchdb"}],50:[function(_dereq_,module,exports){
  'use strict';
  
  var LevelPouch = _dereq_(3);
  var utils = _dereq_(53);
  module.exports = altFactory;
  function altFactory(adapterConfig, downAdapter) {
  
    function LevelPouchAlt(opts, callback) {
      var _opts = utils.extend({
        db: downAdapter
      }, opts);
  
      LevelPouch.call(this, _opts, callback);
    }
  
    // overrides for normal LevelDB behavior on Node
    LevelPouchAlt.valid = function () {
      return adapterConfig.valid();
    };
    LevelPouchAlt.use_prefix = adapterConfig.use_prefix;
  
    LevelPouchAlt.destroy = utils.toPromise(function (name, opts, callback) {
      if (typeof opts === 'function') {
        callback = opts;
        opts = {};
      }
      var _opts = utils.extend({
        db: downAdapter
      }, opts);
  
      return LevelPouch.destroy(name, _opts, callback);
    });
    return LevelPouchAlt;
  
  }
  
  },{"3":3,"53":53}],51:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = {
    name: 'memory',
    valid: function () {
      return true;
    },
    use_prefix: false
  };
  
  },{}],52:[function(_dereq_,module,exports){
  'use strict';
  
  var pluginBase = _dereq_(49);
  var adapterConfig = _dereq_(51);
  var downAdapter = _dereq_(141);
  pluginBase(adapterConfig, downAdapter);
  },{"141":141,"49":49,"51":51}],53:[function(_dereq_,module,exports){
  /*jshint strict: false */
  var traverseRevTree = _dereq_(40);
  exports.ajax = _dereq_(13);
  exports.uuid = _dereq_(48);
  exports.getArguments = _dereq_(54);
  var collections = _dereq_(150);
  exports.Map = collections.Map;
  exports.Set = collections.Set;
  var parseDoc = _dereq_(26);
  
  var Promise = _dereq_(46);
  exports.Promise = Promise;
  
  var base64 = _dereq_(16);
  var errors = _dereq_(31);
  
  // TODO: don't export these
  exports.atob = base64.atob;
  exports.btoa = base64.btoa;
  
  var binStringToBlobOrBuffer =
    _dereq_(18);
  
  // TODO: only used by the integration tests
  exports.binaryStringToBlobOrBuffer = binStringToBlobOrBuffer;
  
  exports.clone = _dereq_(23);
  exports.extend = _dereq_(32);
  
  exports.pick = _dereq_(45);
  exports.inherits = _dereq_(84);
  
  function tryFilter(filter, doc, req) {
    try {
      return !filter(doc, req);
    } catch (err) {
      var msg = 'Filter function threw: ' + err.toString();
      return errors.error(errors.BAD_REQUEST, msg);
    }
  }
  
  exports.filterChange = function filterChange(opts) {
    var req = {};
    var hasFilter = opts.filter && typeof opts.filter === 'function';
    req.query = opts.query_params;
  
    return function filter(change) {
      if (!change.doc) {
        // CSG sends events on the changes feed that don't have documents,
        // this hack makes a whole lot of existing code robust.
        change.doc = {};
      }
  
      var filterReturn = hasFilter && tryFilter(opts.filter, change.doc, req);
  
      if (typeof filterReturn === 'object') {
        return filterReturn;
      }
  
      if (filterReturn) {
        return false;
      }
  
      if (!opts.include_docs) {
        delete change.doc;
      } else if (!opts.attachments) {
        for (var att in change.doc._attachments) {
          /* istanbul ignore else */
          if (change.doc._attachments.hasOwnProperty(att)) {
            change.doc._attachments[att].stub = true;
          }
        }
      }
      return true;
    };
  };
  
  exports.parseDoc = parseDoc.parseDoc;
  exports.invalidIdError = parseDoc.invalidIdError;
  
  exports.isCordova = function () {
    return (typeof cordova !== "undefined" ||
            typeof PhoneGap !== "undefined" ||
            typeof phonegap !== "undefined");
  };
  
  exports.Changes = _dereq_(7);
  
  exports.once = _dereq_(43);
  
  exports.toPromise = _dereq_(47);
  
  exports.adapterFun = function (name, callback) {
    var log = _dereq_(80)('pouchdb:api');
  
    function logApiCall(self, name, args) {
      /* istanbul ignore if */
      if (log.enabled) {
        var logArgs = [self._db_name, name];
        for (var i = 0; i < args.length - 1; i++) {
          logArgs.push(args[i]);
        }
        log.apply(null, logArgs);
  
        // override the callback itself to log the response
        var origCallback = args[args.length - 1];
        args[args.length - 1] = function (err, res) {
          var responseArgs = [self._db_name, name];
          responseArgs = responseArgs.concat(
            err ? ['error', err] : ['success', res]
          );
          log.apply(null, responseArgs);
          origCallback(err, res);
        };
      }
    }
  
  
    return exports.toPromise(exports.getArguments(function (args) {
      if (this._closed) {
        return Promise.reject(new Error('database is closed'));
      }
      var self = this;
      logApiCall(self, name, args);
      if (!this.taskqueue.isReady) {
        return new Promise(function (fulfill, reject) {
          self.taskqueue.addTask(function (failed) {
            if (failed) {
              reject(failed);
            } else {
              fulfill(self[name].apply(self, args));
            }
          });
        });
      }
      return callback.apply(this, args);
    }));
  };
  
  exports.explain404 = _dereq_(11);
  
  exports.parseUri = _dereq_(44);
  
  exports.compare = function (left, right) {
    return left < right ? -1 : left > right ? 1 : 0;
  };
  
  
  // compact a tree by marking its non-leafs as missing,
  // and return a list of revs to delete
  exports.compactTree = function compactTree(metadata) {
    var revs = [];
    traverseRevTree(metadata.rev_tree, function (isLeaf, pos,
                                                       revHash, ctx, opts) {
      if (opts.status === 'available' && !isLeaf) {
        revs.push(pos + '-' + revHash);
        opts.status = 'missing';
      }
    });
    return revs;
  };
  
  var vuvuzela = _dereq_(164);
  
  exports.safeJsonParse = function safeJsonParse(str) {
    try {
      return JSON.parse(str);
    } catch (e) {
      return vuvuzela.parse(str);
    }
  };
  
  exports.safeJsonStringify = function safeJsonStringify(json) {
    try {
      return JSON.stringify(json);
    } catch (e) {
      return vuvuzela.stringify(json);
    }
  };
  
  },{"11":11,"13":13,"150":150,"16":16,"164":164,"18":18,"23":23,"26":26,"31":31,"32":32,"40":40,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"54":54,"7":7,"80":80,"84":84}],54:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = argsArray;
  
  function argsArray(fun) {
    return function () {
      var len = arguments.length;
      if (len) {
        var args = [];
        var i = -1;
        while (++i < len) {
          args[i] = arguments[i];
        }
        return fun.call(this, args);
      } else {
        return fun.call(this, []);
      }
    };
  }
  },{}],55:[function(_dereq_,module,exports){
  
  },{}],56:[function(_dereq_,module,exports){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  
  var base64 = _dereq_(57)
  var ieee754 = _dereq_(58)
  var isArray = _dereq_(59)
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
   *     on objects.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = (function () {
    function Bar () {}
    try {
      var arr = new Uint8Array(1)
      arr.foo = function () { return 42 }
      arr.constructor = Bar
      return arr.foo() === 42 && // typed array instances can be augmented
          arr.constructor === Bar && // constructor can be set
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  })()
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (arg) {
    if (!(this instanceof Buffer)) {
      // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
      if (arguments.length > 1) return new Buffer(arg, arguments[1])
      return new Buffer(arg)
    }
  
    this.length = 0
    this.parent = undefined
  
    // Common case.
    if (typeof arg === 'number') {
      return fromNumber(this, arg)
    }
  
    // Slightly less common case.
    if (typeof arg === 'string') {
      return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
    }
  
    // Unusual.
    return fromObject(this, arg)
  }
  
  function fromNumber (that, length) {
    that = allocate(that, length < 0 ? 0 : checked(length) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < length; i++) {
        that[i] = 0
      }
    }
    return that
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
  
    // Assumption: byteLength() return value is always < kMaxLength.
    var length = byteLength(string, encoding) | 0
    that = allocate(that, length)
  
    that.write(string, encoding)
    return that
  }
  
  function fromObject (that, object) {
    if (Buffer.isBuffer(object)) return fromBuffer(that, object)
  
    if (isArray(object)) return fromArray(that, object)
  
    if (object == null) {
      throw new TypeError('must start with number, buffer, array or string')
    }
  
    if (typeof ArrayBuffer !== 'undefined') {
      if (object.buffer instanceof ArrayBuffer) {
        return fromTypedArray(that, object)
      }
      if (object instanceof ArrayBuffer) {
        return fromArrayBuffer(that, object)
      }
    }
  
    if (object.length) return fromArrayLike(that, object)
  
    return fromJsonObject(that, object)
  }
  
  function fromBuffer (that, buffer) {
    var length = checked(buffer.length) | 0
    that = allocate(that, length)
    buffer.copy(that, 0, 0, length)
    return that
  }
  
  function fromArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Duplicate of fromArray() to keep fromArray() monomorphic.
  function fromTypedArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    // Truncating the elements is probably not what people expect from typed
    // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
    // of the old Buffer constructor.
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      array.byteLength
      that = Buffer._augment(new Uint8Array(array))
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromTypedArray(that, new Uint8Array(array))
    }
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
  // Returns a zero-length buffer for inputs that don't conform to the spec.
  function fromJsonObject (that, object) {
    var array
    var length = 0
  
    if (object.type === 'Buffer' && isArray(object.data)) {
      array = object.data
      length = checked(array.length) | 0
    }
    that = allocate(that, length)
  
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function allocate (that, length) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = Buffer._augment(new Uint8Array(length))
    } else {
      // Fallback: Return an object instance of the Buffer class
      that.length = length
      that._isBuffer = true
    }
  
    var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
    if (fromPool) that.parent = rootParent
  
    return that
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (subject, encoding) {
    if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
  
    var buf = new Buffer(subject, encoding)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    var i = 0
    var len = Math.min(x, y)
    while (i < len) {
      if (a[i] !== b[i]) break
  
      ++i
    }
  
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
  
    if (list.length === 0) {
      return new Buffer(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; i++) {
        length += list[i].length
      }
    }
  
    var buf = new Buffer(length)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  function byteLength (string, encoding) {
    if (typeof string !== 'string') string = '' + string
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'binary':
        // Deprecated
        case 'raw':
        case 'raws':
          return len
        case 'utf8':
        case 'utf-8':
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  // pre-set for values that may exist in the future
  Buffer.prototype.length = undefined
  Buffer.prototype.parent = undefined
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    start = start | 0
    end = end === undefined || end === Infinity ? this.length : end | 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return 0
    return Buffer.compare(this, b)
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
    if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
    else if (byteOffset < -0x80000000) byteOffset = -0x80000000
    byteOffset >>= 0
  
    if (this.length === 0) return -1
    if (byteOffset >= this.length) return -1
  
    // Negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
  
    if (typeof val === 'string') {
      if (val.length === 0) return -1 // special case: looking for empty string always fails
      return String.prototype.indexOf.call(this, val, byteOffset)
    }
    if (Buffer.isBuffer(val)) {
      return arrayIndexOf(this, val, byteOffset)
    }
    if (typeof val === 'number') {
      if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
      }
      return arrayIndexOf(this, [ val ], byteOffset)
    }
  
    function arrayIndexOf (arr, val, byteOffset) {
      var foundIndex = -1
      for (var i = 0; byteOffset + i < arr.length; i++) {
        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
        } else {
          foundIndex = -1
        }
      }
      return -1
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  // `get` is deprecated
  Buffer.prototype.get = function get (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` is deprecated
  Buffer.prototype.set = function set (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) throw new Error('Invalid hex string')
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      var swap = encoding
      encoding = offset
      offset = length | 0
      length = swap
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'binary':
          return binaryWrite(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length) newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = value
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = value
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = value
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), targetStart)
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function fill (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function _augment (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array set method before overwriting
    arr._set = arr.set
  
    // deprecated
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.indexOf = BP.indexOf
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUIntLE = BP.readUIntLE
    arr.readUIntBE = BP.readUIntBE
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readIntLE = BP.readIntLE
    arr.readIntBE = BP.readIntBE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUIntLE = BP.writeUIntLE
    arr.writeUIntBE = BP.writeUIntBE
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeIntLE = BP.writeIntLE
    arr.writeIntBE = BP.writeIntBE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  },{"57":57,"58":58,"59":59}],57:[function(_dereq_,module,exports){
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  	var PLUS_URL_SAFE = '-'.charCodeAt(0)
  	var SLASH_URL_SAFE = '_'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS ||
  		    code === PLUS_URL_SAFE)
  			return 62 // '+'
  		if (code === SLASH ||
  		    code === SLASH_URL_SAFE)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('Invalid string. Length must be a multiple of 4')
  		}
  
  		// the number of equal signs (place holders)
  		// if there are two placeholders, than the two characters before it
  		// represent one byte
  		// if there is only one, then the three characters before it represent 2 bytes
  		// this is just a cheap hack to not do indexOf twice
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(b64.length * 3 / 4 - placeHolders)
  
  		// if there are placeholders, only get up to the last complete 4 chars
  		l = placeHolders > 0 ? b64.length - 4 : b64.length
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			push(tmp & 0xFF)
  		}
  
  		return arr
  	}
  
  	function uint8ToBase64 (uint8) {
  		var i,
  			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  			output = "",
  			temp, length
  
  		function encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  		}
  
  		// go through the array every three bytes, we'll deal with trailing stuff later
  		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  			output += tripletToBase64(temp)
  		}
  
  		// pad the end with zeros, but make sure to not forget the extra bytes
  		switch (extraBytes) {
  			case 1:
  				temp = uint8[uint8.length - 1]
  				output += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },{}],58:[function(_dereq_,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },{}],59:[function(_dereq_,module,exports){
  
  /**
   * isArray
   */
  
  var isArray = Array.isArray;
  
  /**
   * toString
   */
  
  var str = Object.prototype.toString;
  
  /**
   * Whether or not the given `val`
   * is an array.
   *
   * example:
   *
   *        isArray([]);
   *        // > true
   *        isArray(arguments);
   *        // > false
   *        isArray('');
   *        // > false
   *
   * @param {mixed} val
   * @return {bool}
   */
  
  module.exports = isArray || function (val) {
    return !! val && '[object Array]' == str.call(val);
  };
  
  },{}],60:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        }
        throw TypeError('Uncaught, unspecified "error" event.');
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          len = arguments.length;
          args = new Array(len - 1);
          for (i = 1; i < len; i++)
            args[i - 1] = arguments[i];
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      len = arguments.length;
      args = new Array(len - 1);
      for (i = 1; i < len; i++)
        args[i - 1] = arguments[i];
  
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      var m;
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    var ret;
    if (!emitter._events || !emitter._events[type])
      ret = 0;
    else if (isFunction(emitter._events[type]))
      ret = 1;
    else
      ret = emitter._events[type].length;
    return ret;
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  },{}],61:[function(_dereq_,module,exports){
  module.exports = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) == '[object Array]';
  };
  
  },{}],62:[function(_dereq_,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = setTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      clearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          setTimeout(drainQueue, 0);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  },{}],63:[function(_dereq_,module,exports){
  module.exports = _dereq_(64)
  
  },{"64":64}],64:[function(_dereq_,module,exports){
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  'use strict';
  
  /*<replacement>*/
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  /*</replacement>*/
  
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var processNextTick = _dereq_(70);
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var util = _dereq_(69);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var Readable = _dereq_(66);
  var Writable = _dereq_(68);
  
  util.inherits(Duplex, Readable);
  
  var keys = objectKeys(Writable.prototype);
  for (var v = 0; v < keys.length; v++) {
    var method = keys[v];
    if (!Duplex.prototype[method])
      Duplex.prototype[method] = Writable.prototype[method];
  }
  
  function Duplex(options) {
    if (!(this instanceof Duplex))
      return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false)
      this.readable = false;
  
    if (options && options.writable === false)
      this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false)
      this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended)
      return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    processNextTick(onEndNT, this);
  }
  
  function onEndNT(self) {
    self.end();
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  },{"66":66,"68":68,"69":69,"70":70,"84":84}],65:[function(_dereq_,module,exports){
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  'use strict';
  
  module.exports = PassThrough;
  
  var Transform = _dereq_(67);
  
  /*<replacement>*/
  var util = _dereq_(69);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough))
      return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function(chunk, encoding, cb) {
    cb(null, chunk);
  };
  
  },{"67":67,"69":69,"84":84}],66:[function(_dereq_,module,exports){
  (function (process){
  'use strict';
  
  module.exports = Readable;
  
  /*<replacement>*/
  var processNextTick = _dereq_(70);
  /*</replacement>*/
  
  
  /*<replacement>*/
  var isArray = _dereq_(61);
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = _dereq_(60).EventEmitter;
  
  /*<replacement>*/
  if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var Stream;
  (function (){try{
    Stream = _dereq_('st' + 'ream');
  }catch(_){}finally{
    if (!Stream)
      Stream = _dereq_(60).EventEmitter;
  }}())
  /*</replacement>*/
  
  var Buffer = _dereq_(56).Buffer;
  
  /*<replacement>*/
  var util = _dereq_(69);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var debug = _dereq_(55);
  if (debug && debug.debuglog) {
    debug = debug.debuglog('stream');
  } else {
    debug = function () {};
  }
  /*</replacement>*/
  
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    var Duplex = _dereq_(64);
  
    options = options || {};
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.readableObjectMode;
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = null;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = _dereq_(77).StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    var Duplex = _dereq_(64);
  
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    if (options && typeof options.read === 'function')
      this._read = options.read;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (!state.objectMode && typeof chunk === 'string') {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  Readable.prototype.isPaused = function() {
    return this._readableState.flowing === false;
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null) {
      state.reading = false;
      onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        if (!addToFront)
          state.reading = false;
  
        // if we want the data now, just emit it.
        if (state.flowing && state.length === 0 && !state.sync) {
          stream.emit('data', chunk);
          stream.read(0);
        } else {
          // update the buffer info.
          state.length += state.objectMode ? 1 : chunk.length;
          if (addToFront)
            state.buffer.unshift(chunk);
          else
            state.buffer.push(chunk);
  
          if (state.needReadable)
            emitReadable(stream);
        }
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = _dereq_(77).StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
    return this;
  };
  
  // Don't raise the hwm > 128MB
  var MAX_HWM = 0x800000;
  function roundUpToNextPowerOf2(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      for (var p = 1; p < 32; p <<= 1) n |= n >> p;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (n === null || isNaN(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = roundUpToNextPowerOf2(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else {
        return state.length;
      }
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    debug('read', n);
    var state = this._readableState;
    var nOrig = n;
  
    if (typeof n !== 'number' || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      debug('read: emitReadable', state.length, state.ended);
      if (state.length === 0 && state.ended)
        endReadable(this);
      else
        emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      if (state.length === 0)
        endReadable(this);
      return null;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
    debug('need readable', doRead);
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length === 0 || state.length - n < state.highWaterMark) {
      doRead = true;
      debug('length less than watermark', doRead);
    }
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading) {
      doRead = false;
      debug('reading or ended', doRead);
    }
  
    if (doRead) {
      debug('do read');
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read pushed data synchronously, then `reading` will be false,
    // and we need to re-evaluate how much data we can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    var ret;
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we tried to read() past the EOF, then emit end on the next tick.
    if (nOrig !== n && state.ended && state.length === 0)
      endReadable(this);
  
    if (ret !== null)
      this.emit('data', ret);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!(Buffer.isBuffer(chunk)) &&
        typeof chunk !== 'string' &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.ended) return;
    if (state.decoder) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // emit 'readable' now to make sure it gets picked up.
    emitReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (!state.emittedReadable) {
      debug('emitReadable', state.flowing);
      state.emittedReadable = true;
      if (state.sync)
        processNextTick(emitReadable_, stream);
      else
        emitReadable_(stream);
    }
  }
  
  function emitReadable_(stream) {
    debug('emit readable');
    stream.emit('readable');
    flow(stream);
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      processNextTick(maybeReadMore_, stream, state);
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      debug('maybeReadMore read 0');
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
    debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      processNextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      debug('onunpipe');
      if (readable === src) {
        cleanup();
      }
    }
  
    function onend() {
      debug('onend');
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    function cleanup() {
      debug('cleanup');
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
      src.removeListener('data', ondata);
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (state.awaitDrain &&
          (!dest._writableState || dest._writableState.needDrain))
        ondrain();
    }
  
    src.on('data', ondata);
    function ondata(chunk) {
      debug('ondata');
      var ret = dest.write(chunk);
      if (false === ret) {
        debug('false write response, pause',
              src._readableState.awaitDrain);
        src._readableState.awaitDrain++;
        src.pause();
      }
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      debug('onerror', er);
      unpipe();
      dest.removeListener('error', onerror);
      if (EE.listenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      debug('onfinish');
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      debug('unpipe');
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      debug('pipe resume');
      src.resume();
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var state = src._readableState;
      debug('pipeOnDrain', state.awaitDrain);
      if (state.awaitDrain)
        state.awaitDrain--;
      if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
        state.flowing = true;
        flow(src);
      }
    };
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    // If listening to data, and it has not explicitly been paused,
    // then call resume to start the flow of data on the next tick.
    if (ev === 'data' && false !== this._readableState.flowing) {
      this.resume();
    }
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          processNextTick(nReadingNextTick, this);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  function nReadingNextTick(self) {
    debug('readable nexttick read 0');
    self.read(0);
  }
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    var state = this._readableState;
    if (!state.flowing) {
      debug('resume');
      state.flowing = true;
      resume(this, state);
    }
    return this;
  };
  
  function resume(stream, state) {
    if (!state.resumeScheduled) {
      state.resumeScheduled = true;
      processNextTick(resume_, stream, state);
    }
  }
  
  function resume_(stream, state) {
    if (!state.reading) {
      debug('resume read 0');
      stream.read(0);
    }
  
    state.resumeScheduled = false;
    stream.emit('resume');
    flow(stream);
    if (state.flowing && !state.reading)
      stream.read(0);
  }
  
  Readable.prototype.pause = function() {
    debug('call pause flowing=%j', this._readableState.flowing);
    if (false !== this._readableState.flowing) {
      debug('pause');
      this._readableState.flowing = false;
      this.emit('pause');
    }
    return this;
  };
  
  function flow(stream) {
    var state = stream._readableState;
    debug('flow', state.flowing);
    if (state.flowing) {
      do {
        var chunk = stream.read();
      } while (null !== chunk && state.flowing);
    }
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      debug('wrapped end');
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      debug('wrapped data');
      if (state.decoder)
        chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      if (state.objectMode && (chunk === null || chunk === undefined))
        return;
      else if (!state.objectMode && (!chunk || !chunk.length))
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (this[i] === undefined && typeof stream[i] === 'function') {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }; }(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      debug('wrapped _read', n);
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted) {
      state.ended = true;
      processNextTick(endReadableNT, state, stream);
    }
  }
  
  function endReadableNT(state, stream) {
    // Check that we didn't get one last unshift.
    if (!state.endEmitted && state.length === 0) {
      state.endEmitted = true;
      stream.readable = false;
      stream.emit('end');
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,_dereq_(62))
  },{"55":55,"56":56,"60":60,"61":61,"62":62,"64":64,"69":69,"70":70,"77":77,"84":84}],67:[function(_dereq_,module,exports){
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  'use strict';
  
  module.exports = Transform;
  
  var Duplex = _dereq_(64);
  
  /*<replacement>*/
  var util = _dereq_(69);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined)
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    this._transformState = new TransformState(this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    if (options) {
      if (typeof options.transform === 'function')
        this._transform = options.transform;
  
      if (typeof options.flush === 'function')
        this._flush = options.flush;
    }
  
    this.once('prefinish', function() {
      if (typeof this._flush === 'function')
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"64":64,"69":69,"84":84}],68:[function(_dereq_,module,exports){
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, cb), and it'll handle all
  // the drain event emission and buffering.
  
  'use strict';
  
  module.exports = Writable;
  
  /*<replacement>*/
  var processNextTick = _dereq_(70);
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = _dereq_(69);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var Stream;
  (function (){try{
    Stream = _dereq_('st' + 'ream');
  }catch(_){}finally{
    if (!Stream)
      Stream = _dereq_(60).EventEmitter;
  }}())
  /*</replacement>*/
  
  var Buffer = _dereq_(56).Buffer;
  
  util.inherits(Writable, Stream);
  
  function nop() {}
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
    this.next = null;
  }
  
  function WritableState(options, stream) {
    var Duplex = _dereq_(64);
  
    options = options || {};
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.writableObjectMode;
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // when true all writes will be buffered until .uncork() call
    this.corked = 0;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.bufferedRequest = null;
    this.lastBufferedRequest = null;
  
    // number of pending user-supplied write callbacks
    // this must be 0 before 'finish' can be emitted
    this.pendingcb = 0;
  
    // emit prefinish if the only thing we're waiting for is _write cbs
    // This is relevant for synchronous Transform streams
    this.prefinished = false;
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  WritableState.prototype.getBuffer = function writableStateGetBuffer() {
    var current = this.bufferedRequest;
    var out = [];
    while (current) {
      out.push(current);
      current = current.next;
    }
    return out;
  };
  
  (function (){try {
  Object.defineProperty(WritableState.prototype, 'buffer', {
    get: _dereq_(71)(function() {
      return this.getBuffer();
    }, '_writableState.buffer is deprecated. Use ' +
        '_writableState.getBuffer() instead.')
  });
  }catch(_){}}());
  
  
  function Writable(options) {
    var Duplex = _dereq_(64);
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    if (options) {
      if (typeof options.write === 'function')
        this._write = options.write;
  
      if (typeof options.writev === 'function')
        this._writev = options.writev;
    }
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    processNextTick(cb, er);
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
  
    if (!(Buffer.isBuffer(chunk)) &&
        typeof chunk !== 'string' &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      processNextTick(cb, er);
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function')
      cb = nop;
  
    if (state.ended)
      writeAfterEnd(this, cb);
    else if (validChunk(this, state, chunk, cb)) {
      state.pendingcb++;
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
    }
  
    return ret;
  };
  
  Writable.prototype.cork = function() {
    var state = this._writableState;
  
    state.corked++;
  };
  
  Writable.prototype.uncork = function() {
    var state = this._writableState;
  
    if (state.corked) {
      state.corked--;
  
      if (!state.writing &&
          !state.corked &&
          !state.finished &&
          !state.bufferProcessing &&
          state.bufferedRequest)
        clearBuffer(this, state);
    }
  };
  
  Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
    // node::ParseEncoding() requires lower case.
    if (typeof encoding === 'string')
      encoding = encoding.toLowerCase();
    if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64',
  'ucs2', 'ucs-2','utf16le', 'utf-16le', 'raw']
  .indexOf((encoding + '').toLowerCase()) > -1))
      throw new TypeError('Unknown encoding: ' + encoding);
    this._writableState.defaultEncoding = encoding;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        typeof chunk === 'string') {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing || state.corked) {
      var last = state.lastBufferedRequest;
      state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
      if (last) {
        last.next = state.lastBufferedRequest;
      } else {
        state.bufferedRequest = state.lastBufferedRequest;
      }
    } else {
      doWrite(stream, state, false, len, chunk, encoding, cb);
    }
  
    return ret;
  }
  
  function doWrite(stream, state, writev, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    if (writev)
      stream._writev(chunk, state.onwrite);
    else
      stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    --state.pendingcb;
    if (sync)
      processNextTick(cb, er);
    else
      cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(state);
  
      if (!finished &&
          !state.corked &&
          !state.bufferProcessing &&
          state.bufferedRequest) {
        clearBuffer(stream, state);
      }
  
      if (sync) {
        processNextTick(afterWrite, stream, state, finished, cb);
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    state.pendingcb--;
    cb();
    finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
    var entry = state.bufferedRequest;
  
    if (stream._writev && entry && entry.next) {
      // Fast case, write everything using _writev()
      var buffer = [];
      var cbs = [];
      while (entry) {
        cbs.push(entry.callback);
        buffer.push(entry);
        entry = entry.next;
      }
  
      // count the one we are adding, as well.
      // TODO(isaacs) clean this up
      state.pendingcb++;
      state.lastBufferedRequest = null;
      doWrite(stream, state, true, state.length, buffer, '', function(err) {
        for (var i = 0; i < cbs.length; i++) {
          state.pendingcb--;
          cbs[i](err);
        }
      });
  
      // Clear buffer
    } else {
      // Slow case, write chunks one-by-one
      while (entry) {
        var chunk = entry.chunk;
        var encoding = entry.encoding;
        var cb = entry.callback;
        var len = state.objectMode ? 1 : chunk.length;
  
        doWrite(stream, state, false, len, chunk, encoding, cb);
        entry = entry.next;
        // if we didn't call the onwrite immediately, then
        // it means that we need to wait until it does.
        // also, that means that the chunk and cb are currently
        // being processed, so move the buffer counter past them.
        if (state.writing) {
          break;
        }
      }
  
      if (entry === null)
        state.lastBufferedRequest = null;
    }
    state.bufferedRequest = entry;
    state.bufferProcessing = false;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  };
  
  Writable.prototype._writev = null;
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (chunk !== null && chunk !== undefined)
      this.write(chunk, encoding);
  
    // .end() fully uncorks
    if (state.corked) {
      state.corked = 1;
      this.uncork();
    }
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(state) {
    return (state.ending &&
            state.length === 0 &&
            state.bufferedRequest === null &&
            !state.finished &&
            !state.writing);
  }
  
  function prefinish(stream, state) {
    if (!state.prefinished) {
      state.prefinished = true;
      stream.emit('prefinish');
    }
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(state);
    if (need) {
      if (state.pendingcb === 0) {
        prefinish(stream, state);
        state.finished = true;
        stream.emit('finish');
      } else {
        prefinish(stream, state);
      }
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        processNextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  },{"56":56,"60":60,"64":64,"69":69,"70":70,"71":71,"84":84}],69:[function(_dereq_,module,exports){
  (function (Buffer){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  function isBuffer(arg) {
    return Buffer.isBuffer(arg);
  }
  exports.isBuffer = isBuffer;
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  }).call(this,_dereq_(56).Buffer)
  },{"56":56}],70:[function(_dereq_,module,exports){
  (function (process){
  'use strict';
  module.exports = nextTick;
  
  function nextTick(fn) {
    var args = new Array(arguments.length - 1);
    var i = 0;
    while (i < args.length) {
      args[i++] = arguments[i];
    }
    process.nextTick(function afterTick() {
      fn.apply(null, args);
    });
  }
  
  }).call(this,_dereq_(62))
  },{"62":62}],71:[function(_dereq_,module,exports){
  (function (global){
  
  /**
   * Module exports.
   */
  
  module.exports = deprecate;
  
  /**
   * Mark that a method should not be used.
   * Returns a modified function which warns once by default.
   *
   * If `localStorage.noDeprecation = true` is set, then it is a no-op.
   *
   * If `localStorage.throwDeprecation = true` is set, then deprecated functions
   * will throw an Error when invoked.
   *
   * If `localStorage.traceDeprecation = true` is set, then deprecated functions
   * will invoke `console.trace()` instead of `console.error()`.
   *
   * @param {Function} fn - the function to deprecate
   * @param {String} msg - the string to print to the console when `fn` is invoked
   * @returns {Function} a new "deprecated" version of `fn`
   * @api public
   */
  
  function deprecate (fn, msg) {
    if (config('noDeprecation')) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (config('throwDeprecation')) {
          throw new Error(msg);
        } else if (config('traceDeprecation')) {
          console.trace(msg);
        } else {
          console.warn(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  }
  
  /**
   * Checks `localStorage` for boolean values for the given `name`.
   *
   * @param {String} name
   * @returns {Boolean}
   * @api private
   */
  
  function config (name) {
    if (!global.localStorage) return false;
    var val = global.localStorage[name];
    if (null == val) return false;
    return String(val).toLowerCase() === 'true';
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],72:[function(_dereq_,module,exports){
  module.exports = _dereq_(65)
  
  },{"65":65}],73:[function(_dereq_,module,exports){
  var Stream = (function (){
    try {
      return _dereq_('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify
    } catch(_){}
  }());
  exports = module.exports = _dereq_(66);
  exports.Stream = Stream || exports;
  exports.Readable = exports;
  exports.Writable = _dereq_(68);
  exports.Duplex = _dereq_(64);
  exports.Transform = _dereq_(67);
  exports.PassThrough = _dereq_(65);
  
  },{"64":64,"65":65,"66":66,"67":67,"68":68}],74:[function(_dereq_,module,exports){
  module.exports = _dereq_(67)
  
  },{"67":67}],75:[function(_dereq_,module,exports){
  module.exports = _dereq_(68)
  
  },{"68":68}],76:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  module.exports = Stream;
  
  var EE = _dereq_(60).EventEmitter;
  var inherits = _dereq_(84);
  
  inherits(Stream, EE);
  Stream.Readable = _dereq_(73);
  Stream.Writable = _dereq_(75);
  Stream.Duplex = _dereq_(63);
  Stream.Transform = _dereq_(74);
  Stream.PassThrough = _dereq_(72);
  
  // Backwards-compat with node 0.4.x
  Stream.Stream = Stream;
  
  
  
  // old-style streams.  Note that the pipe method (the only relevant
  // part of this class) is overridden in the Readable class.
  
  function Stream() {
    EE.call(this);
  }
  
  Stream.prototype.pipe = function(dest, options) {
    var source = this;
  
    function ondata(chunk) {
      if (dest.writable) {
        if (false === dest.write(chunk) && source.pause) {
          source.pause();
        }
      }
    }
  
    source.on('data', ondata);
  
    function ondrain() {
      if (source.readable && source.resume) {
        source.resume();
      }
    }
  
    dest.on('drain', ondrain);
  
    // If the 'end' option is not supplied, dest.end() will be called when
    // source gets the 'end' or 'close' events.  Only dest.end() once.
    if (!dest._isStdio && (!options || options.end !== false)) {
      source.on('end', onend);
      source.on('close', onclose);
    }
  
    var didOnEnd = false;
    function onend() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      dest.end();
    }
  
  
    function onclose() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      if (typeof dest.destroy === 'function') dest.destroy();
    }
  
    // don't leave dangling pipes when there are errors.
    function onerror(er) {
      cleanup();
      if (EE.listenerCount(this, 'error') === 0) {
        throw er; // Unhandled stream error in pipe.
      }
    }
  
    source.on('error', onerror);
    dest.on('error', onerror);
  
    // remove all the event listeners that were added.
    function cleanup() {
      source.removeListener('data', ondata);
      dest.removeListener('drain', ondrain);
  
      source.removeListener('end', onend);
      source.removeListener('close', onclose);
  
      source.removeListener('error', onerror);
      dest.removeListener('error', onerror);
  
      source.removeListener('end', cleanup);
      source.removeListener('close', cleanup);
  
      dest.removeListener('close', cleanup);
    }
  
    source.on('end', cleanup);
    source.on('close', cleanup);
  
    dest.on('close', cleanup);
  
    dest.emit('pipe', source);
  
    // Allow for unix-like usage: A.pipe(B).pipe(C)
    return dest;
  };
  
  },{"60":60,"63":63,"72":72,"73":73,"74":74,"75":75,"84":84}],77:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var Buffer = _dereq_(56).Buffer;
  
  var isBufferEncoding = Buffer.isEncoding
    || function(encoding) {
         switch (encoding && encoding.toLowerCase()) {
           case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
           default: return false;
         }
       }
  
  
  function assertEncoding(encoding) {
    if (encoding && !isBufferEncoding(encoding)) {
      throw new Error('Unknown encoding: ' + encoding);
    }
  }
  
  // StringDecoder provides an interface for efficiently splitting a series of
  // buffers into a series of JS strings without breaking apart multi-byte
  // characters. CESU-8 is handled as part of the UTF-8 encoding.
  //
  // @TODO Handling all encodings inside a single object makes it very difficult
  // to reason about this code, so it should be split up in the future.
  // @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
  // points as used by CESU-8.
  var StringDecoder = exports.StringDecoder = function(encoding) {
    this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
    assertEncoding(encoding);
    switch (this.encoding) {
      case 'utf8':
        // CESU-8 represents each of Surrogate Pair by 3-bytes
        this.surrogateSize = 3;
        break;
      case 'ucs2':
      case 'utf16le':
        // UTF-16 represents each of Surrogate Pair by 2-bytes
        this.surrogateSize = 2;
        this.detectIncompleteChar = utf16DetectIncompleteChar;
        break;
      case 'base64':
        // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
        this.surrogateSize = 3;
        this.detectIncompleteChar = base64DetectIncompleteChar;
        break;
      default:
        this.write = passThroughWrite;
        return;
    }
  
    // Enough space to store all bytes of a single character. UTF-8 needs 4
    // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
    this.charBuffer = new Buffer(6);
    // Number of bytes received for the current incomplete multi-byte character.
    this.charReceived = 0;
    // Number of bytes expected for the current incomplete multi-byte character.
    this.charLength = 0;
  };
  
  
  // write decodes the given buffer and returns it as JS string that is
  // guaranteed to not contain any partial multi-byte characters. Any partial
  // character found at the end of the buffer is buffered up, and will be
  // returned when calling write again with the remaining bytes.
  //
  // Note: Converting a Buffer containing an orphan surrogate to a String
  // currently works, but converting a String to a Buffer (via `new Buffer`, or
  // Buffer#write) will replace incomplete surrogates with the unicode
  // replacement character. See https://codereview.chromium.org/121173009/ .
  StringDecoder.prototype.write = function(buffer) {
    var charStr = '';
    // if our last write ended with an incomplete multibyte character
    while (this.charLength) {
      // determine how many remaining bytes this buffer has to offer for this char
      var available = (buffer.length >= this.charLength - this.charReceived) ?
          this.charLength - this.charReceived :
          buffer.length;
  
      // add the new bytes to the char buffer
      buffer.copy(this.charBuffer, this.charReceived, 0, available);
      this.charReceived += available;
  
      if (this.charReceived < this.charLength) {
        // still not enough chars in this buffer? wait for more ...
        return '';
      }
  
      // remove bytes belonging to the current character from the buffer
      buffer = buffer.slice(available, buffer.length);
  
      // get the character that was split
      charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
  
      // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
      var charCode = charStr.charCodeAt(charStr.length - 1);
      if (charCode >= 0xD800 && charCode <= 0xDBFF) {
        this.charLength += this.surrogateSize;
        charStr = '';
        continue;
      }
      this.charReceived = this.charLength = 0;
  
      // if there are no more bytes in this buffer, just emit our char
      if (buffer.length === 0) {
        return charStr;
      }
      break;
    }
  
    // determine and set charLength / charReceived
    this.detectIncompleteChar(buffer);
  
    var end = buffer.length;
    if (this.charLength) {
      // buffer the incomplete character bytes we got
      buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
      end -= this.charReceived;
    }
  
    charStr += buffer.toString(this.encoding, 0, end);
  
    var end = charStr.length - 1;
    var charCode = charStr.charCodeAt(end);
    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      var size = this.surrogateSize;
      this.charLength += size;
      this.charReceived += size;
      this.charBuffer.copy(this.charBuffer, size, 0, size);
      buffer.copy(this.charBuffer, 0, 0, size);
      return charStr.substring(0, end);
    }
  
    // or just emit the charStr
    return charStr;
  };
  
  // detectIncompleteChar determines if there is an incomplete UTF-8 character at
  // the end of the given buffer. If so, it sets this.charLength to the byte
  // length that character, and sets this.charReceived to the number of bytes
  // that are available for this character.
  StringDecoder.prototype.detectIncompleteChar = function(buffer) {
    // determine how many bytes we have to check at the end of this buffer
    var i = (buffer.length >= 3) ? 3 : buffer.length;
  
    // Figure out if one of the last i bytes of our buffer announces an
    // incomplete char.
    for (; i > 0; i--) {
      var c = buffer[buffer.length - i];
  
      // See http://en.wikipedia.org/wiki/UTF-8#Description
  
      // 110XXXXX
      if (i == 1 && c >> 5 == 0x06) {
        this.charLength = 2;
        break;
      }
  
      // 1110XXXX
      if (i <= 2 && c >> 4 == 0x0E) {
        this.charLength = 3;
        break;
      }
  
      // 11110XXX
      if (i <= 3 && c >> 3 == 0x1E) {
        this.charLength = 4;
        break;
      }
    }
    this.charReceived = i;
  };
  
  StringDecoder.prototype.end = function(buffer) {
    var res = '';
    if (buffer && buffer.length)
      res = this.write(buffer);
  
    if (this.charReceived) {
      var cr = this.charReceived;
      var buf = this.charBuffer;
      var enc = this.encoding;
      res += buf.slice(0, cr).toString(enc);
    }
  
    return res;
  };
  
  function passThroughWrite(buffer) {
    return buffer.toString(this.encoding);
  }
  
  function utf16DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 2;
    this.charLength = this.charReceived ? 2 : 0;
  }
  
  function base64DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 3;
    this.charLength = this.charReceived ? 3 : 0;
  }
  
  },{"56":56}],78:[function(_dereq_,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],79:[function(_dereq_,module,exports){
  (function (process,global){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = _dereq_(78);
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = _dereq_(84);
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  }).call(this,_dereq_(62),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"62":62,"78":78,"84":84}],80:[function(_dereq_,module,exports){
  
  /**
   * This is the web browser implementation of `debug()`.
   *
   * Expose `debug()` as the module.
   */
  
  exports = module.exports = _dereq_(81);
  exports.log = log;
  exports.formatArgs = formatArgs;
  exports.save = save;
  exports.load = load;
  exports.useColors = useColors;
  exports.storage = 'undefined' != typeof chrome
                 && 'undefined' != typeof chrome.storage
                    ? chrome.storage.local
                    : localstorage();
  
  /**
   * Colors.
   */
  
  exports.colors = [
    'lightseagreen',
    'forestgreen',
    'goldenrod',
    'dodgerblue',
    'darkorchid',
    'crimson'
  ];
  
  /**
   * Currently only WebKit-based Web Inspectors, Firefox >= v31,
   * and the Firebug extension (any Firefox version) are known
   * to support "%c" CSS customizations.
   *
   * TODO: add a `localStorage` variable to explicitly enable/disable colors
   */
  
  function useColors() {
    // is webkit? http://stackoverflow.com/a/16459606/376773
    return ('WebkitAppearance' in document.documentElement.style) ||
      // is firebug? http://stackoverflow.com/a/398120/376773
      (window.console && (console.firebug || (console.exception && console.table))) ||
      // is firefox >= v31?
      // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
      (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
  }
  
  /**
   * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
   */
  
  exports.formatters.j = function(v) {
    return JSON.stringify(v);
  };
  
  
  /**
   * Colorize log arguments if enabled.
   *
   * @api public
   */
  
  function formatArgs() {
    var args = arguments;
    var useColors = this.useColors;
  
    args[0] = (useColors ? '%c' : '')
      + this.namespace
      + (useColors ? ' %c' : ' ')
      + args[0]
      + (useColors ? '%c ' : ' ')
      + '+' + exports.humanize(this.diff);
  
    if (!useColors) return args;
  
    var c = 'color: ' + this.color;
    args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
  
    // the final "%c" is somewhat tricky, because there could be other
    // arguments passed either before or after the %c, so we need to
    // figure out the correct index to insert the CSS into
    var index = 0;
    var lastC = 0;
    args[0].replace(/%[a-z%]/g, function(match) {
      if ('%%' === match) return;
      index++;
      if ('%c' === match) {
        // we only are interested in the *last* %c
        // (the user may have provided their own)
        lastC = index;
      }
    });
  
    args.splice(lastC, 0, c);
    return args;
  }
  
  /**
   * Invokes `console.log()` when available.
   * No-op when `console.log` is not a "function".
   *
   * @api public
   */
  
  function log() {
    // this hackery is required for IE8/9, where
    // the `console.log` function doesn't have 'apply'
    return 'object' === typeof console
      && console.log
      && Function.prototype.apply.call(console.log, console, arguments);
  }
  
  /**
   * Save `namespaces`.
   *
   * @param {String} namespaces
   * @api private
   */
  
  function save(namespaces) {
    try {
      if (null == namespaces) {
        exports.storage.removeItem('debug');
      } else {
        exports.storage.debug = namespaces;
      }
    } catch(e) {}
  }
  
  /**
   * Load `namespaces`.
   *
   * @return {String} returns the previously persisted debug modes
   * @api private
   */
  
  function load() {
    var r;
    try {
      r = exports.storage.debug;
    } catch(e) {}
    return r;
  }
  
  /**
   * Enable namespaces listed in `localStorage.debug` initially.
   */
  
  exports.enable(load());
  
  /**
   * Localstorage attempts to return the localstorage.
   *
   * This is necessary because safari throws
   * when a user disables cookies/localstorage
   * and you attempt to access it.
   *
   * @return {LocalStorage}
   * @api private
   */
  
  function localstorage(){
    try {
      return window.localStorage;
    } catch (e) {}
  }
  
  },{"81":81}],81:[function(_dereq_,module,exports){
  
  /**
   * This is the common logic for both the Node.js and web browser
   * implementations of `debug()`.
   *
   * Expose `debug()` as the module.
   */
  
  exports = module.exports = debug;
  exports.coerce = coerce;
  exports.disable = disable;
  exports.enable = enable;
  exports.enabled = enabled;
  exports.humanize = _dereq_(82);
  
  /**
   * The currently active debug mode names, and names to skip.
   */
  
  exports.names = [];
  exports.skips = [];
  
  /**
   * Map of special "%n" handling functions, for the debug "format" argument.
   *
   * Valid key names are a single, lowercased letter, i.e. "n".
   */
  
  exports.formatters = {};
  
  /**
   * Previously assigned color.
   */
  
  var prevColor = 0;
  
  /**
   * Previous log timestamp.
   */
  
  var prevTime;
  
  /**
   * Select a color.
   *
   * @return {Number}
   * @api private
   */
  
  function selectColor() {
    return exports.colors[prevColor++ % exports.colors.length];
  }
  
  /**
   * Create a debugger with the given `namespace`.
   *
   * @param {String} namespace
   * @return {Function}
   * @api public
   */
  
  function debug(namespace) {
  
    // define the `disabled` version
    function disabled() {
    }
    disabled.enabled = false;
  
    // define the `enabled` version
    function enabled() {
  
      var self = enabled;
  
      // set `diff` timestamp
      var curr = +new Date();
      var ms = curr - (prevTime || curr);
      self.diff = ms;
      self.prev = prevTime;
      self.curr = curr;
      prevTime = curr;
  
      // add the `color` if not set
      if (null == self.useColors) self.useColors = exports.useColors();
      if (null == self.color && self.useColors) self.color = selectColor();
  
      var args = Array.prototype.slice.call(arguments);
  
      args[0] = exports.coerce(args[0]);
  
      if ('string' !== typeof args[0]) {
        // anything else let's inspect with %o
        args = ['%o'].concat(args);
      }
  
      // apply any `formatters` transformations
      var index = 0;
      args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
        // if we encounter an escaped % then don't increase the array index
        if (match === '%%') return match;
        index++;
        var formatter = exports.formatters[format];
        if ('function' === typeof formatter) {
          var val = args[index];
          match = formatter.call(self, val);
  
          // now we need to remove `args[index]` since it's inlined in the `format`
          args.splice(index, 1);
          index--;
        }
        return match;
      });
  
      if ('function' === typeof exports.formatArgs) {
        args = exports.formatArgs.apply(self, args);
      }
      var logFn = enabled.log || exports.log || console.log.bind(console);
      logFn.apply(self, args);
    }
    enabled.enabled = true;
  
    var fn = exports.enabled(namespace) ? enabled : disabled;
  
    fn.namespace = namespace;
  
    return fn;
  }
  
  /**
   * Enables a debug mode by namespaces. This can include modes
   * separated by a colon and wildcards.
   *
   * @param {String} namespaces
   * @api public
   */
  
  function enable(namespaces) {
    exports.save(namespaces);
  
    var split = (namespaces || '').split(/[\s,]+/);
    var len = split.length;
  
    for (var i = 0; i < len; i++) {
      if (!split[i]) continue; // ignore empty strings
      namespaces = split[i].replace(/\*/g, '.*?');
      if (namespaces[0] === '-') {
        exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
      } else {
        exports.names.push(new RegExp('^' + namespaces + '$'));
      }
    }
  }
  
  /**
   * Disable debug output.
   *
   * @api public
   */
  
  function disable() {
    exports.enable('');
  }
  
  /**
   * Returns true if the given mode name is enabled, false otherwise.
   *
   * @param {String} name
   * @return {Boolean}
   * @api public
   */
  
  function enabled(name) {
    var i, len;
    for (i = 0, len = exports.skips.length; i < len; i++) {
      if (exports.skips[i].test(name)) {
        return false;
      }
    }
    for (i = 0, len = exports.names.length; i < len; i++) {
      if (exports.names[i].test(name)) {
        return true;
      }
    }
    return false;
  }
  
  /**
   * Coerce `val`.
   *
   * @param {Mixed} val
   * @return {Mixed}
   * @api private
   */
  
  function coerce(val) {
    if (val instanceof Error) return val.stack || val.message;
    return val;
  }
  
  },{"82":82}],82:[function(_dereq_,module,exports){
  /**
   * Helpers.
   */
  
  var s = 1000;
  var m = s * 60;
  var h = m * 60;
  var d = h * 24;
  var y = d * 365.25;
  
  /**
   * Parse or format the given `val`.
   *
   * Options:
   *
   *  - `long` verbose formatting [false]
   *
   * @param {String|Number} val
   * @param {Object} options
   * @return {String|Number}
   * @api public
   */
  
  module.exports = function(val, options){
    options = options || {};
    if ('string' == typeof val) return parse(val);
    return options["long"]
      ? long(val)
      : short(val);
  };
  
  /**
   * Parse the given `str` and return milliseconds.
   *
   * @param {String} str
   * @return {Number}
   * @api private
   */
  
  function parse(str) {
    str = '' + str;
    if (str.length > 10000) return;
    var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
    if (!match) return;
    var n = parseFloat(match[1]);
    var type = (match[2] || 'ms').toLowerCase();
    switch (type) {
      case 'years':
      case 'year':
      case 'yrs':
      case 'yr':
      case 'y':
        return n * y;
      case 'days':
      case 'day':
      case 'd':
        return n * d;
      case 'hours':
      case 'hour':
      case 'hrs':
      case 'hr':
      case 'h':
        return n * h;
      case 'minutes':
      case 'minute':
      case 'mins':
      case 'min':
      case 'm':
        return n * m;
      case 'seconds':
      case 'second':
      case 'secs':
      case 'sec':
      case 's':
        return n * s;
      case 'milliseconds':
      case 'millisecond':
      case 'msecs':
      case 'msec':
      case 'ms':
        return n;
    }
  }
  
  /**
   * Short format for `ms`.
   *
   * @param {Number} ms
   * @return {String}
   * @api private
   */
  
  function short(ms) {
    if (ms >= d) return Math.round(ms / d) + 'd';
    if (ms >= h) return Math.round(ms / h) + 'h';
    if (ms >= m) return Math.round(ms / m) + 'm';
    if (ms >= s) return Math.round(ms / s) + 's';
    return ms + 'ms';
  }
  
  /**
   * Long format for `ms`.
   *
   * @param {Number} ms
   * @return {String}
   * @api private
   */
  
  function long(ms) {
    return plural(ms, d, 'day')
      || plural(ms, h, 'hour')
      || plural(ms, m, 'minute')
      || plural(ms, s, 'second')
      || ms + ' ms';
  }
  
  /**
   * Pluralization helper.
   */
  
  function plural(ms, n, name) {
    if (ms < n) return;
    if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
    return Math.ceil(ms / n) + ' ' + name + 's';
  }
  
  },{}],83:[function(_dereq_,module,exports){
  /**
   * Copyright (c) 2013 Petka Antonov
   * 
   * 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:</p>
   * 
   * 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.
   */
  "use strict";
  function Deque(capacity) {
      this._capacity = getCapacity(capacity);
      this._length = 0;
      this._front = 0;
      this._makeCapacity();
      if (isArray(capacity)) {
          var len = capacity.length;
          for (var i = 0; i < len; ++i) {
              this[i] = capacity[i];
          }
          this._length = len;
      }
  }
  
  Deque.prototype.toArray = function Deque$toArray() {
      var len = this._length;
      var ret = new Array(len);
      var front = this._front;
      var capacity = this._capacity;
      for (var j = 0; j < len; ++j) {
          ret[j] = this[(front + j) & (capacity - 1)];
      }
      return ret;
  };
  
  Deque.prototype.push = function Deque$push(item) {
      var argsLength = arguments.length;
      var length = this._length;
      if (argsLength > 1) {
          var capacity = this._capacity;
          if (length + argsLength > capacity) {
              for (var i = 0; i < argsLength; ++i) {
                  this._checkCapacity(length + 1);
                  var j = (this._front + length) & (this._capacity - 1);
                  this[j] = arguments[i];
                  length++;
                  this._length = length;
              }
              return length;
          }
          else {
              var j = this._front;
              for (var i = 0; i < argsLength; ++i) {
                  this[(j + length) & (capacity - 1)] = arguments[i];
                  j++;
              }
              this._length = length + argsLength;
              return length + argsLength;
          }
  
      }
  
      if (argsLength === 0) return length;
  
      this._checkCapacity(length + 1);
      var i = (this._front + length) & (this._capacity - 1);
      this[i] = item;
      this._length = length + 1;
      return length + 1;
  };
  
  Deque.prototype.pop = function Deque$pop() {
      var length = this._length;
      if (length === 0) {
          return void 0;
      }
      var i = (this._front + length - 1) & (this._capacity - 1);
      var ret = this[i];
      this[i] = void 0;
      this._length = length - 1;
      return ret;
  };
  
  Deque.prototype.shift = function Deque$shift() {
      var length = this._length;
      if (length === 0) {
          return void 0;
      }
      var front = this._front;
      var ret = this[front];
      this[front] = void 0;
      this._front = (front + 1) & (this._capacity - 1);
      this._length = length - 1;
      return ret;
  };
  
  Deque.prototype.unshift = function Deque$unshift(item) {
      var length = this._length;
      var argsLength = arguments.length;
  
  
      if (argsLength > 1) {
          var capacity = this._capacity;
          if (length + argsLength > capacity) {
              for (var i = argsLength - 1; i >= 0; i--) {
                  this._checkCapacity(length + 1);
                  var capacity = this._capacity;
                  var j = (((( this._front - 1 ) &
                      ( capacity - 1) ) ^ capacity ) - capacity );
                  this[j] = arguments[i];
                  length++;
                  this._length = length;
                  this._front = j;
              }
              return length;
          }
          else {
              var front = this._front;
              for (var i = argsLength - 1; i >= 0; i--) {
                  var j = (((( front - 1 ) &
                      ( capacity - 1) ) ^ capacity ) - capacity );
                  this[j] = arguments[i];
                  front = j;
              }
              this._front = front;
              this._length = length + argsLength;
              return length + argsLength;
          }
      }
  
      if (argsLength === 0) return length;
  
      this._checkCapacity(length + 1);
      var capacity = this._capacity;
      var i = (((( this._front - 1 ) &
          ( capacity - 1) ) ^ capacity ) - capacity );
      this[i] = item;
      this._length = length + 1;
      this._front = i;
      return length + 1;
  };
  
  Deque.prototype.peekBack = function Deque$peekBack() {
      var length = this._length;
      if (length === 0) {
          return void 0;
      }
      var index = (this._front + length - 1) & (this._capacity - 1);
      return this[index];
  };
  
  Deque.prototype.peekFront = function Deque$peekFront() {
      if (this._length === 0) {
          return void 0;
      }
      return this[this._front];
  };
  
  Deque.prototype.get = function Deque$get(index) {
      var i = index;
      if ((i !== (i | 0))) {
          return void 0;
      }
      var len = this._length;
      if (i < 0) {
          i = i + len;
      }
      if (i < 0 || i >= len) {
          return void 0;
      }
      return this[(this._front + i) & (this._capacity - 1)];
  };
  
  Deque.prototype.isEmpty = function Deque$isEmpty() {
      return this._length === 0;
  };
  
  Deque.prototype.clear = function Deque$clear() {
      this._length = 0;
      this._front = 0;
      this._makeCapacity();
  };
  
  Deque.prototype.toString = function Deque$toString() {
      return this.toArray().toString();
  };
  
  Deque.prototype.valueOf = Deque.prototype.toString;
  Deque.prototype.removeFront = Deque.prototype.shift;
  Deque.prototype.removeBack = Deque.prototype.pop;
  Deque.prototype.insertFront = Deque.prototype.unshift;
  Deque.prototype.insertBack = Deque.prototype.push;
  Deque.prototype.enqueue = Deque.prototype.push;
  Deque.prototype.dequeue = Deque.prototype.shift;
  Deque.prototype.toJSON = Deque.prototype.toArray;
  
  Object.defineProperty(Deque.prototype, "length", {
      get: function() {
          return this._length;
      },
      set: function() {
          throw new RangeError("");
      }
  });
  
  Deque.prototype._makeCapacity = function Deque$_makeCapacity() {
      var len = this._capacity;
      for (var i = 0; i < len; ++i) {
          this[i] = void 0;
      }
  };
  
  Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) {
      if (this._capacity < size) {
          this._resizeTo(getCapacity(this._capacity * 1.5 + 16));
      }
  };
  
  Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) {
      var oldFront = this._front;
      var oldCapacity = this._capacity;
      var oldDeque = new Array(oldCapacity);
      var length = this._length;
  
      arrayCopy(this, 0, oldDeque, 0, oldCapacity);
      this._capacity = capacity;
      this._makeCapacity();
      this._front = 0;
      if (oldFront + length <= oldCapacity) {
          arrayCopy(oldDeque, oldFront, this, 0, length);
      } else {        var lengthBeforeWrapping =
              length - ((oldFront + length) & (oldCapacity - 1));
  
          arrayCopy(oldDeque, oldFront, this, 0, lengthBeforeWrapping);
          arrayCopy(oldDeque, 0, this, lengthBeforeWrapping,
              length - lengthBeforeWrapping);
      }
  };
  
  
  var isArray = Array.isArray;
  
  function arrayCopy(src, srcIndex, dst, dstIndex, len) {
      for (var j = 0; j < len; ++j) {
          dst[j + dstIndex] = src[j + srcIndex];
      }
  }
  
  function pow2AtLeast(n) {
      n = n >>> 0;
      n = n - 1;
      n = n | (n >> 1);
      n = n | (n >> 2);
      n = n | (n >> 4);
      n = n | (n >> 8);
      n = n | (n >> 16);
      return n + 1;
  }
  
  function getCapacity(capacity) {
      if (typeof capacity !== "number") {
          if (isArray(capacity)) {
              capacity = capacity.length;
          }
          else {
              return 16;
          }
      }
      return pow2AtLeast(
          Math.min(
              Math.max(16, capacity), 1073741824)
      );
  }
  
  module.exports = Deque;
  
  },{}],84:[function(_dereq_,module,exports){
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  },{}],85:[function(_dereq_,module,exports){
  module.exports = {
    encode: function (e) {
      var s = '';
      var prefix = e[0].slice()
      while(prefix.length) {
        s += '\xff' + prefix.shift().toString() + '\xff'
      }
      return s + (e[1] || '').toString()
    },
    decode: function (e) {
      var k = e.toString().split('\xff').filter(Boolean)
      var j = k.pop()
      return [k, j]
    },
    lowerBound: '\x00',
    upperBound: '\xff'
  }
  
  
  },{}],86:[function(_dereq_,module,exports){
  
  var inRange = _dereq_(111)
  
  module.exports = function (compare) {
    var hooks = []
  
    return {
      add: function (range, hook) {
        var m = {range: range, hook: hook}
        hooks.push(m)
        //call this to remove
        return function () {
          var i = hooks.indexOf(m)
          if(~i) return hooks.splice(i, 1)
        }
  
      },
  
      //remove all listeners within a range.
      //this will be used to close a sublevel.
      removeAll: function (range) {
        throw new Error('not implemented')
      },
  
      trigger: function (key, args) {
        for(var i = 0; i < hooks.length; i++) {
          var test = hooks[i]
          if(inRange(test.range, key, compare))
            test.hook.apply(this, args)
        }
      }
    }
  }
  
  },{"111":111}],87:[function(_dereq_,module,exports){
  var nut   = _dereq_(109)
  var shell = _dereq_(112) //the shell surrounds the nut
  var codec = _dereq_(88)
  var merge = _dereq_(108)
  
  var ReadStream = _dereq_(91)
  
  var precodec = _dereq_(85)
  
  module.exports = function (db, opts) {
  
    opts = merge(db.options, opts)
  
    return shell ( nut ( db, precodec, codec ), [], ReadStream, db.options)
  
  }
  
  
  },{"108":108,"109":109,"112":112,"85":85,"88":88,"91":91}],88:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2014 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License
   * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  var encodings = _dereq_(89)
  
  function getKeyEncoder (options, op) {
    var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8'
    return encodings[type] || type
  }
  
  function getValueEncoder (options, op) {
    var type = (((op && (op.valueEncoding || op.encoding))
        || options.valueEncoding || options.encoding)) || 'utf8'
    return encodings[type] || type
  }
  
  /*
    Encode a key.
    This method takes two options, because the leveldb instance
    has options, and this operation (a put, del, or batch)
    also has options that may override the leveldb's options.
  */
  
  function encodeKey (key, options, op) {
    return getKeyEncoder(options, op).encode(key)
  }
  
  /*
    Encode a value.
    Takes 2 options, for the same reason as encodeKey
  */
  
  function encodeValue (value, options, op) {
    return getValueEncoder(options, op).encode(value)
  }
  
  /*
    Decode an encoded key
  */
  
  function decodeKey (key, options) {
    return getKeyEncoder(options).decode(key)
  }
  
  /*
    Decode an encoded value
  */
  
  function decodeValue (value, options) {
    return getValueEncoder(options).decode(value)
  }
  
  /*
    check whether this value should be requested as a buffer
    (if false, then it will be a string)
    this allows an optimization in leveldown where leveldown
    retrives a string directly, and thus avoids a memory copy.
  */
  
  function isValueAsBuffer (options, op) {
    return getValueEncoder(options, op).buffer
  }
  
  /*
    check whether a given key should be requested as a buffer.
  */
  
  function isKeyAsBuffer (options, op) {
    return getKeyEncoder(options, op).buffer
  }
  
  
  module.exports = {
      encodeKey       : encodeKey
    , encodeValue     : encodeValue
    , isValueAsBuffer : isValueAsBuffer
    , isKeyAsBuffer   : isKeyAsBuffer
    , decodeValue     : decodeValue
    , decodeKey       : decodeKey
  }
  
  },{"89":89}],89:[function(_dereq_,module,exports){
  (function (Buffer){
  /* Copyright (c) 2012-2014 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License
   * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  var encodingNames = [
          'hex'
        , 'utf8'
        , 'utf-8'
        , 'ascii'
        , 'binary'
        , 'base64'
        , 'ucs2'
        , 'ucs-2'
        , 'utf16le'
        , 'utf-16le'
      ]
  
  module.exports = (function () {
    function isBinary (data) {
      return data === undefined || data === null || Buffer.isBuffer(data)
    }
  
    var encodings = {}
  
    encodings.utf8 = encodings['utf-8'] = {
        encode : function (data) {
          return isBinary(data) ? data : String(data)
        }
      , decode : function (data) { return data }
      , buffer : false
      , type   : 'utf8'
    }
  
    encodings.json = {
        encode : JSON.stringify
      , decode : JSON.parse
      , buffer : false
      , type   : 'json'
    }
  
    encodings.binary = {
        encode : function (data) {
          return isBinary(data) ? data : new Buffer(data)
        }
      , decode : function (data) {
          return data
        }
      , buffer : true
      , type   : 'binary'
    }
  
    encodingNames.forEach(function (type) {
      if (encodings[type])
        return
  
      encodings[type] = {
          encode : function (data) {
            return isBinary(data) ? data : new Buffer(data, type)
          }
        , decode : function (buffer) {
            return buffer.toString(type)
          }
        , buffer : true
        , type   : type // useful for debugging purposes
      }
    })
  
    return encodings
  })()
  
  
  }).call(this,_dereq_(56).Buffer)
  },{"56":56}],90:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2014 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License
   * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  var createError   = _dereq_(94).create
    , LevelUPError  = createError('LevelUPError')
    , NotFoundError = createError('NotFoundError', LevelUPError)
  
  NotFoundError.prototype.notFound = true
  NotFoundError.prototype.status   = 404
  
  module.exports = {
      LevelUPError        : LevelUPError
    , InitializationError : createError('InitializationError', LevelUPError)
    , OpenError           : createError('OpenError', LevelUPError)
    , ReadError           : createError('ReadError', LevelUPError)
    , WriteError          : createError('WriteError', LevelUPError)
    , NotFoundError       : NotFoundError
    , EncodingError       : createError('EncodingError', LevelUPError)
  }
  
  },{"94":94}],91:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2014 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  // NOTE: we are fixed to readable-stream@1.0.x for now
  // for pure Streams2 across Node versions
  var Readable      = _dereq_(104).Readable
    , inherits      = _dereq_(79).inherits
    , extend        = _dereq_(105)
    , EncodingError = _dereq_(90).EncodingError
    , util          = _dereq_(92)
  
  
  
  function ReadStream (options, makeData) {
    if (!(this instanceof ReadStream))
      return new ReadStream(options, makeData)
  
    Readable.call(this, { objectMode: true, highWaterMark: options.highWaterMark })
  
    // purely to keep `db` around until we're done so it's not GCed if the user doesn't keep a ref
  
    this._waiting = false
    this._options = options
    this._makeData = makeData
  }
  
  inherits(ReadStream, Readable)
  
  ReadStream.prototype.setIterator = function (it) {
    var self = this
    this._iterator = it
    if(this._destroyed) return it.end(function () {})
    if(this._waiting) {
      this._waiting = false
      return this._read()
    }
    return this
  }
  
  ReadStream.prototype._read = function read () {
    var self = this
    if (self._destroyed)
      return
    if(!self._iterator)
      return this._waiting = true
  
    self._iterator.next(function(err, key, value) {
      if (err || (key === undefined && value === undefined)) {
        if (!err && !self._destroyed)
          self.push(null)
        return self._cleanup(err)
      }
  
  
      try {
        value = self._makeData(key, value)
      } catch (e) {
        return self._cleanup(new EncodingError(e))
      }
      if (!self._destroyed)
        self.push(value)
    })
  }
  
  ReadStream.prototype._cleanup = function (err) {
    if (this._destroyed)
      return
  
    this._destroyed = true
  
    var self = this
    if (err)
      self.emit('error', err)
  
    if (self._iterator) {
      self._iterator.end(function () {
        self._iterator = null
        self.emit('close')
      })
    } else {
      self.emit('close')
    }
  }
  
  ReadStream.prototype.destroy = function () {
    this._cleanup()
  }
  
  ReadStream.prototype.toString = function () {
    return 'LevelUP.ReadStream'
  }
  
  
  module.exports = ReadStream
  
  
  },{"104":104,"105":105,"79":79,"90":90,"92":92}],92:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2014 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License
   * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  var extend        = _dereq_(105)
    , LevelUPError  = _dereq_(90).LevelUPError
    , encodings     = _dereq_(89)
    , defaultOptions = {
          createIfMissing : true
        , errorIfExists   : false
        , keyEncoding     : 'utf8'
        , valueEncoding   : 'utf8'
        , compression     : true
      }
  
    , leveldown
    , encodingOpts = (function () {
        var eo = {}
        for(var e in encodings)
          eo[e] = {valueEncoding: encodings[e]}
        return eo
      }())
  
  function copy (srcdb, dstdb, callback) {
    srcdb.readStream()
      .pipe(dstdb.writeStream())
      .on('close', callback ? callback : function () {})
      .on('error', callback ? callback : function (err) { throw err })
  }
  
  function getOptions (levelup, options) {
    var s = typeof options == 'string' // just an encoding
    if (!s && options && options.encoding && !options.valueEncoding)
      options.valueEncoding = options.encoding
    return extend(
        (levelup && levelup.options) || {}
      , s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding]
          : options
    )
  }
  
  function getLevelDOWN () {
    if (leveldown)
      return leveldown
  
    var requiredVersion       = _dereq_(106).devDependencies.leveldown
      , missingLevelDOWNError = 'Could not locate LevelDOWN, try `npm install leveldown`'
      , leveldownVersion
  
    try {
      leveldownVersion = _dereq_(55).version
    } catch (e) {
      throw new LevelUPError(missingLevelDOWNError)
    }
  
    if (!_dereq_(55).satisfies(leveldownVersion, requiredVersion)) {
      throw new LevelUPError(
          'Installed version of LevelDOWN ('
        + leveldownVersion
        + ') does not match required version ('
        + requiredVersion
        + ')'
      )
    }
  
    try {
      return leveldown = _dereq_(55)
    } catch (e) {
      throw new LevelUPError(missingLevelDOWNError)
    }
  }
  
  function dispatchError (levelup, error, callback) {
    return typeof callback == 'function'
      ? callback(error)
      : levelup.emit('error', error)
  }
  
  function isDefined (v) {
    return typeof v !== 'undefined'
  }
  
  module.exports = {
      defaultOptions  : defaultOptions
    , copy            : copy
    , getOptions      : getOptions
    , getLevelDOWN    : getLevelDOWN
    , dispatchError   : dispatchError
    , isDefined       : isDefined
  }
  
  },{"105":105,"106":106,"55":55,"89":89,"90":90}],93:[function(_dereq_,module,exports){
  var prr = _dereq_(95)
  
  function init (type, message, cause) {
    prr(this, {
        type    : type
      , name    : type
        // can be passed just a 'cause'
      , cause   : typeof message != 'string' ? message : cause
      , message : !!message && typeof message != 'string' ? message.message : message
  
    }, 'ewr')
  }
  
  // generic prototype, not intended to be actually used - helpful for `instanceof`
  function CustomError (message, cause) {
    Error.call(this)
    if (Error.captureStackTrace)
      Error.captureStackTrace(this, arguments.callee)
    init.call(this, 'CustomError', message, cause)
  }
  
  CustomError.prototype = new Error()
  
  function createError (errno, type, proto) {
    var err = function (message, cause) {
      init.call(this, type, message, cause)
      //TODO: the specificity here is stupid, errno should be available everywhere
      if (type == 'FilesystemError') {
        this.code    = this.cause.code
        this.path    = this.cause.path
        this.errno   = this.cause.errno
        this.message =
          (errno.errno[this.cause.errno]
            ? errno.errno[this.cause.errno].description
            : this.cause.message)
          + (this.cause.path ? ' [' + this.cause.path + ']' : '')
      }
      Error.call(this)
      if (Error.captureStackTrace)
        Error.captureStackTrace(this, arguments.callee)
    }
    err.prototype = !!proto ? new proto() : new CustomError()
    return err
  }
  
  module.exports = function (errno) {
    var ce = function (type, proto) {
      return createError(errno, type, proto)
    }
    return {
        CustomError     : CustomError
      , FilesystemError : ce('FilesystemError')
      , createError     : ce
    }
  }
  
  },{"95":95}],94:[function(_dereq_,module,exports){
  var all = module.exports.all = [
    {
      errno: -2,
      code: 'ENOENT',
      description: 'no such file or directory'
    },
    {
      errno: -1,
      code: 'UNKNOWN',
      description: 'unknown error'
    },
    {
      errno: 0,
      code: 'OK',
      description: 'success'
    },
    {
      errno: 1,
      code: 'EOF',
      description: 'end of file'
    },
    {
      errno: 2,
      code: 'EADDRINFO',
      description: 'getaddrinfo error'
    },
    {
      errno: 3,
      code: 'EACCES',
      description: 'permission denied'
    },
    {
      errno: 4,
      code: 'EAGAIN',
      description: 'resource temporarily unavailable'
    },
    {
      errno: 5,
      code: 'EADDRINUSE',
      description: 'address already in use'
    },
    {
      errno: 6,
      code: 'EADDRNOTAVAIL',
      description: 'address not available'
    },
    {
      errno: 7,
      code: 'EAFNOSUPPORT',
      description: 'address family not supported'
    },
    {
      errno: 8,
      code: 'EALREADY',
      description: 'connection already in progress'
    },
    {
      errno: 9,
      code: 'EBADF',
      description: 'bad file descriptor'
    },
    {
      errno: 10,
      code: 'EBUSY',
      description: 'resource busy or locked'
    },
    {
      errno: 11,
      code: 'ECONNABORTED',
      description: 'software caused connection abort'
    },
    {
      errno: 12,
      code: 'ECONNREFUSED',
      description: 'connection refused'
    },
    {
      errno: 13,
      code: 'ECONNRESET',
      description: 'connection reset by peer'
    },
    {
      errno: 14,
      code: 'EDESTADDRREQ',
      description: 'destination address required'
    },
    {
      errno: 15,
      code: 'EFAULT',
      description: 'bad address in system call argument'
    },
    {
      errno: 16,
      code: 'EHOSTUNREACH',
      description: 'host is unreachable'
    },
    {
      errno: 17,
      code: 'EINTR',
      description: 'interrupted system call'
    },
    {
      errno: 18,
      code: 'EINVAL',
      description: 'invalid argument'
    },
    {
      errno: 19,
      code: 'EISCONN',
      description: 'socket is already connected'
    },
    {
      errno: 20,
      code: 'EMFILE',
      description: 'too many open files'
    },
    {
      errno: 21,
      code: 'EMSGSIZE',
      description: 'message too long'
    },
    {
      errno: 22,
      code: 'ENETDOWN',
      description: 'network is down'
    },
    {
      errno: 23,
      code: 'ENETUNREACH',
      description: 'network is unreachable'
    },
    {
      errno: 24,
      code: 'ENFILE',
      description: 'file table overflow'
    },
    {
      errno: 25,
      code: 'ENOBUFS',
      description: 'no buffer space available'
    },
    {
      errno: 26,
      code: 'ENOMEM',
      description: 'not enough memory'
    },
    {
      errno: 27,
      code: 'ENOTDIR',
      description: 'not a directory'
    },
    {
      errno: 28,
      code: 'EISDIR',
      description: 'illegal operation on a directory'
    },
    {
      errno: 29,
      code: 'ENONET',
      description: 'machine is not on the network'
    },
    {
      errno: 31,
      code: 'ENOTCONN',
      description: 'socket is not connected'
    },
    {
      errno: 32,
      code: 'ENOTSOCK',
      description: 'socket operation on non-socket'
    },
    {
      errno: 33,
      code: 'ENOTSUP',
      description: 'operation not supported on socket'
    },
    {
      errno: 34,
      code: 'ENOENT',
      description: 'no such file or directory'
    },
    {
      errno: 35,
      code: 'ENOSYS',
      description: 'function not implemented'
    },
    {
      errno: 36,
      code: 'EPIPE',
      description: 'broken pipe'
    },
    {
      errno: 37,
      code: 'EPROTO',
      description: 'protocol error'
    },
    {
      errno: 38,
      code: 'EPROTONOSUPPORT',
      description: 'protocol not supported'
    },
    {
      errno: 39,
      code: 'EPROTOTYPE',
      description: 'protocol wrong type for socket'
    },
    {
      errno: 40,
      code: 'ETIMEDOUT',
      description: 'connection timed out'
    },
    {
      errno: 41,
      code: 'ECHARSET',
      description: 'invalid Unicode character'
    },
    {
      errno: 42,
      code: 'EAIFAMNOSUPPORT',
      description: 'address family for hostname not supported'
    },
    {
      errno: 44,
      code: 'EAISERVICE',
      description: 'servname not supported for ai_socktype'
    },
    {
      errno: 45,
      code: 'EAISOCKTYPE',
      description: 'ai_socktype not supported'
    },
    {
      errno: 46,
      code: 'ESHUTDOWN',
      description: 'cannot send after transport endpoint shutdown'
    },
    {
      errno: 47,
      code: 'EEXIST',
      description: 'file already exists'
    },
    {
      errno: 48,
      code: 'ESRCH',
      description: 'no such process'
    },
    {
      errno: 49,
      code: 'ENAMETOOLONG',
      description: 'name too long'
    },
    {
      errno: 50,
      code: 'EPERM',
      description: 'operation not permitted'
    },
    {
      errno: 51,
      code: 'ELOOP',
      description: 'too many symbolic links encountered'
    },
    {
      errno: 52,
      code: 'EXDEV',
      description: 'cross-device link not permitted'
    },
    {
      errno: 53,
      code: 'ENOTEMPTY',
      description: 'directory not empty'
    },
    {
      errno: 54,
      code: 'ENOSPC',
      description: 'no space left on device'
    },
    {
      errno: 55,
      code: 'EIO',
      description: 'i/o error'
    },
    {
      errno: 56,
      code: 'EROFS',
      description: 'read-only file system'
    },
    {
      errno: 57,
      code: 'ENODEV',
      description: 'no such device'
    },
    {
      errno: 58,
      code: 'ESPIPE',
      description: 'invalid seek'
    },
    {
      errno: 59,
      code: 'ECANCELED',
      description: 'operation canceled'
    }
  ]
  
  module.exports.errno = {}
  module.exports.code = {}
  
  all.forEach(function (error) {
    module.exports.errno[error.errno] = error
    module.exports.code[error.code] = error
  })
  
  module.exports.custom = _dereq_(93)(module.exports)
  module.exports.create = module.exports.custom.createError
  
  },{"93":93}],95:[function(_dereq_,module,exports){
  /*!
    * prr
    * (c) 2013 Rod Vagg <rod@vagg.org>
    * https://github.com/rvagg/prr
    * License: MIT
    */
  
  (function (name, context, definition) {
    if (typeof module != 'undefined' && module.exports)
      module.exports = definition()
    else
      context[name] = definition()
  })('prr', this, function() {
  
    var setProperty = typeof Object.defineProperty == 'function'
        ? function (obj, key, options) {
            Object.defineProperty(obj, key, options)
            return obj
          }
        : function (obj, key, options) { // < es5
            obj[key] = options.value
            return obj
          }
  
      , makeOptions = function (value, options) {
          var oo = typeof options == 'object'
            , os = !oo && typeof options == 'string'
            , op = function (p) {
                return oo
                  ? !!options[p]
                  : os
                    ? options.indexOf(p[0]) > -1
                    : false
              }
  
          return {
              enumerable   : op('enumerable')
            , configurable : op('configurable')
            , writable     : op('writable')
            , value        : value
          }
        }
  
      , prr = function (obj, key, value, options) {
          var k
  
          options = makeOptions(value, options)
  
          if (typeof key == 'object') {
            for (k in key) {
              if (Object.hasOwnProperty.call(key, k)) {
                options.value = key[k]
                setProperty(obj, k, options)
              }
            }
            return obj
          }
  
          return setProperty(obj, key, options)
        }
  
    return prr
  })
  },{}],96:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  /*</replacement>*/
  
  
  /*<replacement>*/
  var util = _dereq_(101);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var Readable = _dereq_(98);
  var Writable = _dereq_(100);
  
  util.inherits(Duplex, Readable);
  
  forEach(objectKeys(Writable.prototype), function(method) {
    if (!Duplex.prototype[method])
      Duplex.prototype[method] = Writable.prototype[method];
  });
  
  function Duplex(options) {
    if (!(this instanceof Duplex))
      return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false)
      this.readable = false;
  
    if (options && options.writable === false)
      this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false)
      this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended)
      return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    process.nextTick(this.end.bind(this));
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  }).call(this,_dereq_(62))
  },{"100":100,"101":101,"62":62,"84":84,"98":98}],97:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  module.exports = PassThrough;
  
  var Transform = _dereq_(99);
  
  /*<replacement>*/
  var util = _dereq_(101);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough))
      return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function(chunk, encoding, cb) {
    cb(null, chunk);
  };
  
  },{"101":101,"84":84,"99":99}],98:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  module.exports = Readable;
  
  /*<replacement>*/
  var isArray = _dereq_(102);
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = _dereq_(60).EventEmitter;
  
  /*<replacement>*/
  if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  var Stream = _dereq_(76);
  
  /*<replacement>*/
  var util = _dereq_(101);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    options = options || {};
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = false;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // In streams that never have any data, and do push(null) right away,
    // the consumer can miss the 'end' event if they do some I/O before
    // consuming the stream.  So, we don't emit('end') until some reading
    // happens.
    this.calledRead = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = _dereq_(103).StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (typeof chunk === 'string' && !state.objectMode) {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null || chunk === undefined) {
      state.reading = false;
      if (!state.ended)
        onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        // update the buffer info.
        state.length += state.objectMode ? 1 : chunk.length;
        if (addToFront) {
          state.buffer.unshift(chunk);
        } else {
          state.reading = false;
          state.buffer.push(chunk);
        }
  
        if (state.needReadable)
          emitReadable(stream);
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = _dereq_(103).StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
  };
  
  // Don't raise the hwm > 128MB
  var MAX_HWM = 0x800000;
  function roundUpToNextPowerOf2(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      for (var p = 1; p < 32; p <<= 1) n |= n >> p;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (n === null || isNaN(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = roundUpToNextPowerOf2(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else
        return state.length;
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    var state = this._readableState;
    state.calledRead = true;
    var nOrig = n;
    var ret;
  
    if (typeof n !== 'number' || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      ret = null;
  
      // In cases where the decoder did not receive enough data
      // to produce a full chunk, then immediately received an
      // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>].
      // howMuchToRead will see this and coerce the amount to
      // read to zero (because it's looking at the length of the
      // first <Buffer > in state.buffer), and we'll end up here.
      //
      // This can only happen via state.decoder -- no other venue
      // exists for pushing a zero-length chunk into state.buffer
      // and triggering this behavior. In this case, we return our
      // remaining data and end the stream, if appropriate.
      if (state.length > 0 && state.decoder) {
        ret = fromList(n, state);
        state.length -= ret.length;
      }
  
      if (state.length === 0)
        endReadable(this);
  
      return ret;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length - n <= state.highWaterMark)
      doRead = true;
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading)
      doRead = false;
  
    if (doRead) {
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read called its callback synchronously, then `reading`
    // will be false, and we need to re-evaluate how much data we
    // can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we happened to read() exactly the remaining amount in the
    // buffer, and the EOF has been seen at this point, then make sure
    // that we emit 'end' on the very next tick.
    if (state.ended && !state.endEmitted && state.length === 0)
      endReadable(this);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.decoder && !state.ended) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // if we've ended and we have some data left, then emit
    // 'readable' now to make sure it gets picked up.
    if (state.length > 0)
      emitReadable(stream);
    else
      endReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (state.emittedReadable)
      return;
  
    state.emittedReadable = true;
    if (state.sync)
      process.nextTick(function() {
        emitReadable_(stream);
      });
    else
      emitReadable_(stream);
  }
  
  function emitReadable_(stream) {
    stream.emit('readable');
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      process.nextTick(function() {
        maybeReadMore_(stream, state);
      });
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      process.nextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      if (readable !== src) return;
      cleanup();
    }
  
    function onend() {
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    function cleanup() {
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (!dest._writableState || dest._writableState.needDrain)
        ondrain();
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      unpipe();
      dest.removeListener('error', onerror);
      if (EE.listenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      // the handler that waits for readable events after all
      // the data gets sucked out in flow.
      // This would be easier to follow with a .once() handler
      // in flow(), but that is too slow.
      this.on('readable', pipeOnReadable);
  
      state.flowing = true;
      process.nextTick(function() {
        flow(src);
      });
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var dest = this;
      var state = src._readableState;
      state.awaitDrain--;
      if (state.awaitDrain === 0)
        flow(src);
    };
  }
  
  function flow(src) {
    var state = src._readableState;
    var chunk;
    state.awaitDrain = 0;
  
    function write(dest, i, list) {
      var written = dest.write(chunk);
      if (false === written) {
        state.awaitDrain++;
      }
    }
  
    while (state.pipesCount && null !== (chunk = src.read())) {
  
      if (state.pipesCount === 1)
        write(state.pipes, 0, null);
      else
        forEach(state.pipes, write);
  
      src.emit('data', chunk);
  
      // if anyone needs a drain, then we have to wait for that.
      if (state.awaitDrain > 0)
        return;
    }
  
    // if every destination was unpiped, either before entering this
    // function, or in the while loop, then stop flowing.
    //
    // NB: This is a pretty rare edge case.
    if (state.pipesCount === 0) {
      state.flowing = false;
  
      // if there were data event listeners added, then switch to old mode.
      if (EE.listenerCount(src, 'data') > 0)
        emitDataEvents(src);
      return;
    }
  
    // at this point, no one needed a drain, so we just ran out of data
    // on the next readable event, start it over again.
    state.ranOut = true;
  }
  
  function pipeOnReadable() {
    if (this._readableState.ranOut) {
      this._readableState.ranOut = false;
      flow(this);
    }
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    if (ev === 'data' && !this._readableState.flowing)
      emitDataEvents(this);
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          this.read(0);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    emitDataEvents(this);
    this.read(0);
    this.emit('resume');
  };
  
  Readable.prototype.pause = function() {
    emitDataEvents(this, true);
    this.emit('pause');
  };
  
  function emitDataEvents(stream, startPaused) {
    var state = stream._readableState;
  
    if (state.flowing) {
      // https://github.com/isaacs/readable-stream/issues/16
      throw new Error('Cannot switch to old mode now.');
    }
  
    var paused = startPaused || false;
    var readable = false;
  
    // convert to an old-style stream.
    stream.readable = true;
    stream.pipe = Stream.prototype.pipe;
    stream.on = stream.addListener = Stream.prototype.on;
  
    stream.on('readable', function() {
      readable = true;
  
      var c;
      while (!paused && (null !== (c = stream.read())))
        stream.emit('data', c);
  
      if (c === null) {
        readable = false;
        stream._readableState.needReadable = true;
      }
    });
  
    stream.pause = function() {
      paused = true;
      this.emit('pause');
    };
  
    stream.resume = function() {
      paused = false;
      if (readable)
        process.nextTick(function() {
          stream.emit('readable');
        });
      else
        this.read(0);
      this.emit('resume');
    };
  
    // now make it start, just in case it hadn't already.
    stream.emit('readable');
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      if (state.decoder)
        chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      //if (state.objectMode && util.isNullOrUndefined(chunk))
      if (state.objectMode && (chunk === null || chunk === undefined))
        return;
      else if (!state.objectMode && (!chunk || !chunk.length))
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (typeof stream[i] === 'function' &&
          typeof this[i] === 'undefined') {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }}(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted && state.calledRead) {
      state.ended = true;
      process.nextTick(function() {
        // Check that we didn't get one last unshift.
        if (!state.endEmitted && state.length === 0) {
          state.endEmitted = true;
          stream.readable = false;
          stream.emit('end');
        }
      });
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,_dereq_(62))
  },{"101":101,"102":102,"103":103,"56":56,"60":60,"62":62,"76":76,"84":84}],99:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  module.exports = Transform;
  
  var Duplex = _dereq_(96);
  
  /*<replacement>*/
  var util = _dereq_(101);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(options, stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined)
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    var ts = this._transformState = new TransformState(options, this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    this.once('finish', function() {
      if ('function' === typeof this._flush)
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var rs = stream._readableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"101":101,"84":84,"96":96}],100:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, cb), and it'll handle all
  // the drain event emission and buffering.
  
  module.exports = Writable;
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = _dereq_(101);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var Stream = _dereq_(76);
  
  util.inherits(Writable, Stream);
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
  }
  
  function WritableState(options, stream) {
    options = options || {};
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.buffer = [];
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  function Writable(options) {
    var Duplex = _dereq_(96);
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, state, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    process.nextTick(function() {
      cb(er);
    });
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      process.nextTick(function() {
        cb(er);
      });
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function')
      cb = function() {};
  
    if (state.ended)
      writeAfterEnd(this, state, cb);
    else if (validChunk(this, state, chunk, cb))
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
  
    return ret;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        typeof chunk === 'string') {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing)
      state.buffer.push(new WriteReq(chunk, encoding, cb));
    else
      doWrite(stream, state, len, chunk, encoding, cb);
  
    return ret;
  }
  
  function doWrite(stream, state, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    if (sync)
      process.nextTick(function() {
        cb(er);
      });
    else
      cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(stream, state);
  
      if (!finished && !state.bufferProcessing && state.buffer.length)
        clearBuffer(stream, state);
  
      if (sync) {
        process.nextTick(function() {
          afterWrite(stream, state, finished, cb);
        });
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    cb();
    if (finished)
      finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
  
    for (var c = 0; c < state.buffer.length; c++) {
      var entry = state.buffer[c];
      var chunk = entry.chunk;
      var encoding = entry.encoding;
      var cb = entry.callback;
      var len = state.objectMode ? 1 : chunk.length;
  
      doWrite(stream, state, len, chunk, encoding, cb);
  
      // if we didn't call the onwrite immediately, then
      // it means that we need to wait until it does.
      // also, that means that the chunk and cb are currently
      // being processed, so move the buffer counter past them.
      if (state.writing) {
        c++;
        break;
      }
    }
  
    state.bufferProcessing = false;
    if (c < state.buffer.length)
      state.buffer = state.buffer.slice(c);
    else
      state.buffer.length = 0;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  };
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (typeof chunk !== 'undefined' && chunk !== null)
      this.write(chunk, encoding);
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(stream, state) {
    return (state.ending &&
            state.length === 0 &&
            !state.finished &&
            !state.writing);
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(stream, state);
    if (need) {
      state.finished = true;
      stream.emit('finish');
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        process.nextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  }).call(this,_dereq_(62))
  },{"101":101,"56":56,"62":62,"76":76,"84":84,"96":96}],101:[function(_dereq_,module,exports){
  arguments[4][69][0].apply(exports,arguments)
  },{"56":56,"69":69}],102:[function(_dereq_,module,exports){
  arguments[4][61][0].apply(exports,arguments)
  },{"61":61}],103:[function(_dereq_,module,exports){
  arguments[4][77][0].apply(exports,arguments)
  },{"56":56,"77":77}],104:[function(_dereq_,module,exports){
  var Stream = _dereq_(76); // hack to fix a circular dependency issue when used with browserify
  exports = module.exports = _dereq_(98);
  exports.Stream = Stream;
  exports.Readable = exports;
  exports.Writable = _dereq_(100);
  exports.Duplex = _dereq_(96);
  exports.Transform = _dereq_(99);
  exports.PassThrough = _dereq_(97);
  
  },{"100":100,"76":76,"96":96,"97":97,"98":98,"99":99}],105:[function(_dereq_,module,exports){
  module.exports = extend
  
  function extend() {
      var target = {}
  
      for (var i = 0; i < arguments.length; i++) {
          var source = arguments[i]
  
          for (var key in source) {
              if (source.hasOwnProperty(key)) {
                  target[key] = source[key]
              }
          }
      }
  
      return target
  }
  
  },{}],106:[function(_dereq_,module,exports){
  module.exports={
    "name": "levelup",
    "description": "Fast & simple storage - a Node.js-style LevelDB wrapper",
    "version": "0.19.0",
    "contributors": [
      {
        "name": "Rod Vagg",
        "email": "r@va.gg",
        "url": "https://github.com/rvagg"
      },
      {
        "name": "John Chesley",
        "email": "john@chesl.es",
        "url": "https://github.com/chesles/"
      },
      {
        "name": "Jake Verbaten",
        "email": "raynos2@gmail.com",
        "url": "https://github.com/raynos"
      },
      {
        "name": "Dominic Tarr",
        "email": "dominic.tarr@gmail.com",
        "url": "https://github.com/dominictarr"
      },
      {
        "name": "Max Ogden",
        "email": "max@maxogden.com",
        "url": "https://github.com/maxogden"
      },
      {
        "name": "Lars-Magnus Skog",
        "email": "lars.magnus.skog@gmail.com",
        "url": "https://github.com/ralphtheninja"
      },
      {
        "name": "David Björklund",
        "email": "david.bjorklund@gmail.com",
        "url": "https://github.com/kesla"
      },
      {
        "name": "Julian Gruber",
        "email": "julian@juliangruber.com",
        "url": "https://github.com/juliangruber"
      },
      {
        "name": "Paolo Fragomeni",
        "email": "paolo@async.ly",
        "url": "https://github.com/hij1nx"
      },
      {
        "name": "Anton Whalley",
        "email": "anton.whalley@nearform.com",
        "url": "https://github.com/No9"
      },
      {
        "name": "Matteo Collina",
        "email": "matteo.collina@gmail.com",
        "url": "https://github.com/mcollina"
      },
      {
        "name": "Pedro Teixeira",
        "email": "pedro.teixeira@gmail.com",
        "url": "https://github.com/pgte"
      },
      {
        "name": "James Halliday",
        "email": "mail@substack.net",
        "url": "https://github.com/substack"
      }
    ],
    "repository": {
      "type": "git",
      "url": "git+https://github.com/rvagg/node-levelup.git"
    },
    "homepage": "https://github.com/rvagg/node-levelup",
    "keywords": [
      "leveldb",
      "stream",
      "database",
      "db",
      "store",
      "storage",
      "json"
    ],
    "main": "lib/levelup.js",
    "dependencies": {
      "bl": "~0.8.1",
      "deferred-leveldown": "~0.2.0",
      "errno": "~0.1.1",
      "prr": "~0.0.0",
      "readable-stream": "~1.0.26",
      "semver": "~2.3.1",
      "xtend": "~3.0.0"
    },
    "devDependencies": {
      "leveldown": "~0.10.0",
      "bustermove": "*",
      "tap": "*",
      "referee": "*",
      "rimraf": "*",
      "async": "*",
      "fstream": "*",
      "tar": "*",
      "mkfiletree": "*",
      "readfiletree": "*",
      "slow-stream": ">=0.0.4",
      "delayed": "*",
      "boganipsum": "*",
      "du": "*",
      "memdown": "*",
      "msgpack-js": "*"
    },
    "browser": {
      "leveldown": false,
      "leveldown/package": false,
      "semver": false
    },
    "scripts": {
      "test": "tap test/*-test.js --stderr",
      "functionaltests": "node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js",
      "alltests": "npm test && npm run-script functionaltests"
    },
    "license": "MIT",
    "readme": "LevelUP\n=======\n\n![LevelDB Logo](https://0.gravatar.com/avatar/a498b122aecb7678490a38bb593cc12d)\n\n**Fast & simple storage - a Node.js-style LevelDB wrapper**\n\n[![Build Status](https://secure.travis-ci.org/rvagg/node-levelup.png)](http://travis-ci.org/rvagg/node-levelup)\n\n[![NPM](https://nodei.co/npm/levelup.png?stars&downloads&downloadRank)](https://nodei.co/npm/levelup/) [![NPM](https://nodei.co/npm-dl/levelup.png?months=6&height=3)](https://nodei.co/npm/levelup/)\n\n\n  * <a href=\"#intro\">Introduction</a>\n  * <a href=\"#leveldown\">Relationship to LevelDOWN</a>\n  * <a href=\"#platforms\">Tested &amp; supported platforms</a>\n  * <a href=\"#basic\">Basic usage</a>\n  * <a href=\"#api\">API</a>\n  * <a href=\"#events\">Events</a>\n  * <a href=\"#json\">JSON data</a>\n  * <a href=\"#custom_encodings\">Custom encodings</a>\n  * <a href=\"#extending\">Extending LevelUP</a>\n  * <a href=\"#multiproc\">Multi-process access</a>\n  * <a href=\"#support\">Getting support</a>\n  * <a href=\"#contributing\">Contributing</a>\n  * <a href=\"#licence\">Licence &amp; copyright</a>\n\n<a name=\"intro\"></a>\nIntroduction\n------------\n\n**[LevelDB](http://code.google.com/p/leveldb/)** is a simple key/value data store built by Google, inspired by BigTable. It's used in Google Chrome and many other products. LevelDB supports arbitrary byte arrays as both keys and values, singular *get*, *put* and *delete* operations, *batched put and delete*, bi-directional iterators and simple compression using the very fast [Snappy](http://code.google.com/p/snappy/) algorithm.\n\n**LevelUP** aims to expose the features of LevelDB in a **Node.js-friendly way**. All standard `Buffer` encoding types are supported, as is a special JSON encoding. LevelDB's iterators are exposed as a Node.js-style **readable stream** a matching **writeable stream** converts writes to *batch* operations.\n\nLevelDB stores entries **sorted lexicographically by keys**. This makes LevelUP's <a href=\"#createReadStream\"><code>ReadStream</code></a> interface a very powerful query mechanism.\n\n**LevelUP** is an **OPEN Open Source Project**, see the <a href=\"#contributing\">Contributing</a> section to find out what this means.\n\n<a name=\"leveldown\"></a>\nRelationship to LevelDOWN\n-------------------------\n\nLevelUP is designed to be backed by **[LevelDOWN](https://github.com/rvagg/node-leveldown/)** which provides a pure C++ binding to LevelDB and can be used as a stand-alone package if required.\n\n**As of version 0.9, LevelUP no longer requires LevelDOWN as a dependency so you must `npm install leveldown` when you install LevelUP.**\n\nLevelDOWN is now optional because LevelUP can be used with alternative backends, such as **[level.js](https://github.com/maxogden/level.js)** in the browser or [MemDOWN](https://github.com/rvagg/node-memdown) for a pure in-memory store.\n\nLevelUP will look for LevelDOWN and throw an error if it can't find it in its Node `require()` path. It will also tell you if the installed version of LevelDOWN is incompatible.\n\n**The [level](https://github.com/level/level) package is available as an alternative installation mechanism.** Install it instead to automatically get both LevelUP & LevelDOWN. It exposes LevelUP on its export (i.e. you can `var leveldb = require('level')`).\n\n\n<a name=\"platforms\"></a>\nTested & supported platforms\n----------------------------\n\n  * **Linux**: including ARM platforms such as Raspberry Pi *and Kindle!*\n  * **Mac OS**\n  * **Solaris**: including Joyent's SmartOS & Nodejitsu\n  * **Windows**: Node 0.10 and above only. See installation instructions for *node-gyp's* dependencies [here](https://github.com/TooTallNate/node-gyp#installation), you'll need these (free) components from Microsoft to compile and run any native Node add-on in Windows.\n\n<a name=\"basic\"></a>\nBasic usage\n-----------\n\nFirst you need to install LevelUP!\n\n```sh\n$ npm install levelup leveldown\n```\n\nOr\n\n```sh\n$ npm install level\n```\n\n*(this second option requires you to use LevelUP by calling `var levelup = require('level')`)*\n\n\nAll operations are asynchronous although they don't necessarily require a callback if you don't need to know when the operation was performed.\n\n```js\nvar levelup = require('levelup')\n\n// 1) Create our database, supply location and options.\n//    This will create or open the underlying LevelDB store.\nvar db = levelup('./mydb')\n\n// 2) put a key & value\ndb.put('name', 'LevelUP', function (err) {\n  if (err) return console.log('Ooops!', err) // some kind of I/O error\n\n  // 3) fetch by key\n  db.get('name', function (err, value) {\n    if (err) return console.log('Ooops!', err) // likely the key was not found\n\n    // ta da!\n    console.log('name=' + value)\n  })\n})\n```\n\n<a name=\"api\"></a>\n## API\n\n  * <a href=\"#ctor\"><code><b>levelup()</b></code></a>\n  * <a href=\"#open\"><code>db.<b>open()</b></code></a>\n  * <a href=\"#close\"><code>db.<b>close()</b></code></a>\n  * <a href=\"#put\"><code>db.<b>put()</b></code></a>\n  * <a href=\"#get\"><code>db.<b>get()</b></code></a>\n  * <a href=\"#del\"><code>db.<b>del()</b></code></a>\n  * <a href=\"#batch\"><code>db.<b>batch()</b></code> *(array form)*</a>\n  * <a href=\"#batch_chained\"><code>db.<b>batch()</b></code> *(chained form)*</a>\n  * <a href=\"#isOpen\"><code>db.<b>isOpen()</b></code></a>\n  * <a href=\"#isClosed\"><code>db.<b>isClosed()</b></code></a>\n  * <a href=\"#createReadStream\"><code>db.<b>createReadStream()</b></code></a>\n  * <a href=\"#createKeyStream\"><code>db.<b>createKeyStream()</b></code></a>\n  * <a href=\"#createValueStream\"><code>db.<b>createValueStream()</b></code></a>\n  * <a href=\"#createWriteStream\"><code>db.<b>createWriteStream()</b></code></a>\n\n### Special operations exposed by LevelDOWN\n\n  * <a href=\"#approximateSize\"><code>db.db.<b>approximateSize()</b></code></a>\n  * <a href=\"#getProperty\"><code>db.db.<b>getProperty()</b></code></a>\n  * <a href=\"#destroy\"><code><b>leveldown.destroy()</b></code></a>\n  * <a href=\"#repair\"><code><b>leveldown.repair()</b></code></a>\n\n\n--------------------------------------------------------\n<a name=\"ctor\"></a>\n### levelup(location[, options[, callback]])\n### levelup(options[, callback ])\n### levelup(db[, callback ])\n<code>levelup()</code> is the main entry point for creating a new LevelUP instance and opening the underlying store with LevelDB.\n\nThis function returns a new instance of LevelUP and will also initiate an <a href=\"#open\"><code>open()</code></a> operation. Opening the database is an asynchronous operation which will trigger your callback if you provide one. The callback should take the form: `function (err, db) {}` where the `db` is the LevelUP instance. If you don't provide a callback, any read & write operations are simply queued internally until the database is fully opened.\n\nThis leads to two alternative ways of managing a new LevelUP instance:\n\n```js\nlevelup(location, options, function (err, db) {\n  if (err) throw err\n  db.get('foo', function (err, value) {\n    if (err) return console.log('foo does not exist')\n    console.log('got foo =', value)\n  })\n})\n\n// vs the equivalent:\n\nvar db = levelup(location, options) // will throw if an error occurs\ndb.get('foo', function (err, value) {\n  if (err) return console.log('foo does not exist')\n  console.log('got foo =', value)\n})\n```\n\nThe `location` argument is available as a read-only property on the returned LevelUP instance.\n\nThe `levelup(options, callback)` form (with optional `callback`) is only available where you provide a valid `'db'` property on the options object (see below). Only for back-ends that don't require a `location` argument, such as [MemDOWN](https://github.com/rvagg/memdown).\n\nFor example:\n\n```js\nvar levelup = require('levelup')\nvar memdown = require('memdown')\nvar db = levelup({ db: memdown })\n```\n\nThe `levelup(db, callback)` form (with optional `callback`) is only available where `db` is a factory function, as would be provided as a `'db'` property on an `options` object (see below). Only for back-ends that don't require a `location` argument, such as [MemDOWN](https://github.com/rvagg/memdown).\n\nFor example:\n\n```js\nvar levelup = require('levelup')\nvar memdown = require('memdown')\nvar db = levelup(memdown)\n```\n\n#### `options`\n\n`levelup()` takes an optional options object as its second argument; the following properties are accepted:\n\n* `'createIfMissing'` *(boolean, default: `true`)*: If `true`, will initialise an empty database at the specified location if one doesn't already exist. If `false` and a database doesn't exist you will receive an error in your `open()` callback and your database won't open.\n\n* `'errorIfExists'` *(boolean, default: `false`)*: If `true`, you will receive an error in your `open()` callback if the database exists at the specified location.\n\n* `'compression'` *(boolean, default: `true`)*: If `true`, all *compressible* data will be run through the Snappy compression algorithm before being stored. Snappy is very fast and shouldn't gain much speed by disabling so leave this on unless you have good reason to turn it off.\n\n* `'cacheSize'` *(number, default: `8 * 1024 * 1024`)*: The size (in bytes) of the in-memory [LRU](http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used) cache with frequently used uncompressed block contents. \n\n* `'keyEncoding'` and `'valueEncoding'` *(string, default: `'utf8'`)*: The encoding of the keys and values passed through Node.js' `Buffer` implementation (see [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end)).\n  <p><code>'utf8'</code> is the default encoding for both keys and values so you can simply pass in strings and expect strings from your <code>get()</code> operations. You can also pass <code>Buffer</code> objects as keys and/or values and conversion will be performed.</p>\n  <p>Supported encodings are: hex, utf8, ascii, binary, base64, ucs2, utf16le.</p>\n  <p><code>'json'</code> encoding is also supported, see below.</p>\n\n* `'db'` *(object, default: LevelDOWN)*: LevelUP is backed by [LevelDOWN](https://github.com/rvagg/node-leveldown/) to provide an interface to LevelDB. You can completely replace the use of LevelDOWN by providing a \"factory\" function that will return a LevelDOWN API compatible object given a `location` argument. For further information, see [MemDOWN](https://github.com/rvagg/node-memdown/), a fully LevelDOWN API compatible replacement that uses a memory store rather than LevelDB. Also see [Abstract LevelDOWN](http://github.com/rvagg/node-abstract-leveldown), a partial implementation of the LevelDOWN API that can be used as a base prototype for a LevelDOWN substitute.\n\nAdditionally, each of the main interface methods accept an optional options object that can be used to override `'keyEncoding'` and `'valueEncoding'`.\n\n--------------------------------------------------------\n<a name=\"open\"></a>\n### db.open([callback])\n<code>open()</code> opens the underlying LevelDB store. In general **you should never need to call this method directly** as it's automatically called by <a href=\"#ctor\"><code>levelup()</code></a>.\n\nHowever, it is possible to *reopen* a database after it has been closed with <a href=\"#close\"><code>close()</code></a>, although this is not generally advised.\n\n--------------------------------------------------------\n<a name=\"close\"></a>\n### db.close([callback])\n<code>close()</code> closes the underlying LevelDB store. The callback will receive any error encountered during closing as the first argument.\n\nYou should always clean up your LevelUP instance by calling `close()` when you no longer need it to free up resources. A LevelDB store cannot be opened by multiple instances of LevelDB/LevelUP simultaneously.\n\n--------------------------------------------------------\n<a name=\"put\"></a>\n### db.put(key, value[, options][, callback])\n<code>put()</code> is the primary method for inserting data into the store. Both the `key` and `value` can be arbitrary data objects.\n\nThe callback argument is optional but if you don't provide one and an error occurs then expect the error to be thrown.\n\n#### `options`\n\nEncoding of the `key` and `value` objects will adhere to `'keyEncoding'` and `'valueEncoding'` options provided to <a href=\"#ctor\"><code>levelup()</code></a>, although you can provide alternative encoding settings in the options for `put()` (it's recommended that you stay consistent in your encoding of keys and values in a single store).\n\nIf you provide a `'sync'` value of `true` in your `options` object, LevelDB will perform a synchronous write of the data; although the operation will be asynchronous as far as Node is concerned. Normally, LevelDB passes the data to the operating system for writing and returns immediately, however a synchronous write will use `fsync()` or equivalent so your callback won't be triggered until the data is actually on disk. Synchronous filesystem writes are **significantly** slower than asynchronous writes but if you want to be absolutely sure that the data is flushed then you can use `'sync': true`.\n\n--------------------------------------------------------\n<a name=\"get\"></a>\n### db.get(key[, options][, callback])\n<code>get()</code> is the primary method for fetching data from the store. The `key` can be an arbitrary data object. If it doesn't exist in the store then the callback will receive an error as its first argument. A not-found err object will be of type `'NotFoundError'` so you can `err.type == 'NotFoundError'` or you can perform a truthy test on the property `err.notFound`.\n\n```js\ndb.get('foo', function (err, value) {\n  if (err) {\n    if (err.notFound) {\n      // handle a 'NotFoundError' here\n      return\n    }\n    // I/O or other error, pass it up the callback chain\n    return callback(err)\n  }\n\n  // .. handle `value` here\n})\n```\n\n#### `options`\n\nEncoding of the `key` object will adhere to the `'keyEncoding'` option provided to <a href=\"#ctor\"><code>levelup()</code></a>, although you can provide alternative encoding settings in the options for `get()` (it's recommended that you stay consistent in your encoding of keys and values in a single store).\n\nLevelDB will by default fill the in-memory LRU Cache with data from a call to get. Disabling this is done by setting `fillCache` to `false`. \n\n--------------------------------------------------------\n<a name=\"del\"></a>\n### db.del(key[, options][, callback])\n<code>del()</code> is the primary method for removing data from the store.\n\n#### `options`\n\nEncoding of the `key` object will adhere to the `'keyEncoding'` option provided to <a href=\"#ctor\"><code>levelup()</code></a>, although you can provide alternative encoding settings in the options for `del()` (it's recommended that you stay consistent in your encoding of keys and values in a single store).\n\nA `'sync'` option can also be passed, see <a href=\"#put\"><code>put()</code></a> for details on how this works.\n\n--------------------------------------------------------\n<a name=\"batch\"></a>\n### db.batch(array[, options][, callback]) *(array form)*\n<code>batch()</code> can be used for very fast bulk-write operations (both *put* and *delete*). The `array` argument should contain a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation inside LevelDB. Each operation is contained in an object having the following properties: `type`, `key`, `value`, where the *type* is either `'put'` or `'del'`. In the case of `'del'` the `'value'` property is ignored. Any entries with a `'key'` of `null` or `undefined` will cause an error to be returned on the `callback` and any `'type': 'put'` entry with a `'value'` of `null` or `undefined` will return an error.\n\n```js\nvar ops = [\n    { type: 'del', key: 'father' }\n  , { type: 'put', key: 'name', value: 'Yuri Irsenovich Kim' }\n  , { type: 'put', key: 'dob', value: '16 February 1941' }\n  , { type: 'put', key: 'spouse', value: 'Kim Young-sook' }\n  , { type: 'put', key: 'occupation', value: 'Clown' }\n]\n\ndb.batch(ops, function (err) {\n  if (err) return console.log('Ooops!', err)\n  console.log('Great success dear leader!')\n})\n```\n\n#### `options`\n\nSee <a href=\"#put\"><code>put()</code></a> for a discussion on the `options` object. You can overwrite default `'keyEncoding'` and `'valueEncoding'` and also specify the use of `sync` filesystem operations.\n\nIn addition to encoding options for the whole batch you can also overwrite the encoding per operation, like:\n\n```js\nvar ops = [{\n    type          : 'put'\n  , key           : new Buffer([1, 2, 3])\n  , value         : { some: 'json' }\n  , keyEncoding   : 'binary'\n  , valueEncoding : 'json'\n}]\n```\n\n--------------------------------------------------------\n<a name=\"batch_chained\"></a>\n### db.batch() *(chained form)*\n<code>batch()</code>, when called with no arguments will return a `Batch` object which can be used to build, and eventually commit, an atomic LevelDB batch operation. Depending on how it's used, it is possible to obtain greater performance when using the chained form of `batch()` over the array form.\n\n```js\ndb.batch()\n  .del('father')\n  .put('name', 'Yuri Irsenovich Kim')\n  .put('dob', '16 February 1941')\n  .put('spouse', 'Kim Young-sook')\n  .put('occupation', 'Clown')\n  .write(function () { console.log('Done!') })\n```\n\n<b><code>batch.put(key, value[, options])</code></b>\n\nQueue a *put* operation on the current batch, not committed until a `write()` is called on the batch.\n\nThe optional `options` argument can be used to override the default `'keyEncoding'` and/or `'valueEncoding'`.\n\nThis method may `throw` a `WriteError` if there is a problem with your put (such as the `value` being `null` or `undefined`).\n\n<b><code>batch.del(key[, options])</code></b>\n\nQueue a *del* operation on the current batch, not committed until a `write()` is called on the batch.\n\nThe optional `options` argument can be used to override the default `'keyEncoding'`.\n\nThis method may `throw` a `WriteError` if there is a problem with your delete.\n\n<b><code>batch.clear()</code></b>\n\nClear all queued operations on the current batch, any previous operations will be discarded.\n\n<b><code>batch.write([callback])</code></b>\n\nCommit the queued operations for this batch. All operations not *cleared* will be written to the database atomically, that is, they will either all succeed or fail with no partial commits. The optional `callback` will be called when the operation has completed with an *error* argument if an error has occurred; if no `callback` is supplied and an error occurs then this method will `throw` a `WriteError`.\n\n\n--------------------------------------------------------\n<a name=\"isOpen\"></a>\n### db.isOpen()\n\nA LevelUP object can be in one of the following states:\n\n  * *\"new\"*     - newly created, not opened or closed\n  * *\"opening\"* - waiting for the database to be opened\n  * *\"open\"*    - successfully opened the database, available for use\n  * *\"closing\"* - waiting for the database to be closed\n  * *\"closed\"*  - database has been successfully closed, should not be used\n\n`isOpen()` will return `true` only when the state is \"open\".\n\n--------------------------------------------------------\n<a name=\"isClosed\"></a>\n### db.isClosed()\n\n*See <a href=\"#put\"><code>isOpen()</code></a>*\n\n`isClosed()` will return `true` only when the state is \"closing\" *or* \"closed\", it can be useful for determining if read and write operations are permissible.\n\n--------------------------------------------------------\n<a name=\"createReadStream\"></a>\n### db.createReadStream([options])\n\nYou can obtain a **ReadStream** of the full database by calling the `createReadStream()` method. The resulting stream is a complete Node.js-style [Readable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_readable_stream) where `'data'` events emit objects with `'key'` and `'value'` pairs. You can also use the `gt`, `lt` and `limit` options to control the range of keys that are streamed.\n\n```js\ndb.createReadStream()\n  .on('data', function (data) {\n    console.log(data.key, '=', data.value)\n  })\n  .on('error', function (err) {\n    console.log('Oh my!', err)\n  })\n  .on('close', function () {\n    console.log('Stream closed')\n  })\n  .on('end', function () {\n    console.log('Stream closed')\n  })\n```\n\nThe standard `pause()`, `resume()` and `destroy()` methods are implemented on the ReadStream, as is `pipe()` (see below). `'data'`, '`error'`, `'end'` and `'close'` events are emitted.\n\nAdditionally, you can supply an options object as the first parameter to `createReadStream()` with the following options:\n\n* `'gt'` (greater than), `'gte'` (greater than or equal) define the lower bound of the range to be streamed. Only records where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.\n\n* `'lt'` (less than), `'lte'` (less than or equal) define the higher bound of the range to be streamed. Only key/value pairs where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.\n\n* `'start', 'end'` legacy ranges - instead use `'gte', 'lte'`\n\n* `'reverse'` *(boolean, default: `false`)*: a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.\n\n* `'keys'` *(boolean, default: `true`)*: whether the `'data'` event should contain keys. If set to `true` and `'values'` set to `false` then `'data'` events will simply be keys, rather than objects with a `'key'` property. Used internally by the `createKeyStream()` method.\n\n* `'values'` *(boolean, default: `true`)*: whether the `'data'` event should contain values. If set to `true` and `'keys'` set to `false` then `'data'` events will simply be values, rather than objects with a `'value'` property. Used internally by the `createValueStream()` method.\n\n* `'limit'` *(number, default: `-1`)*: limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.\n\n* `'fillCache'` *(boolean, default: `false`)*: wheather LevelDB's LRU-cache should be filled with data read.\n\n* `'keyEncoding'` / `'valueEncoding'` *(string)*: the encoding applied to each read piece of data.\n\n--------------------------------------------------------\n<a name=\"createKeyStream\"></a>\n### db.createKeyStream([options])\n\nA **KeyStream** is a **ReadStream** where the `'data'` events are simply the keys from the database so it can be used like a traditional stream rather than an object stream.\n\nYou can obtain a KeyStream either by calling the `createKeyStream()` method on a LevelUP object or by passing passing an options object to `createReadStream()` with `keys` set to `true` and `values` set to `false`.\n\n```js\ndb.createKeyStream()\n  .on('data', function (data) {\n    console.log('key=', data)\n  })\n\n// same as:\ndb.createReadStream({ keys: true, values: false })\n  .on('data', function (data) {\n    console.log('key=', data)\n  })\n```\n\n--------------------------------------------------------\n<a name=\"createValueStream\"></a>\n### db.createValueStream([options])\n\nA **ValueStream** is a **ReadStream** where the `'data'` events are simply the values from the database so it can be used like a traditional stream rather than an object stream.\n\nYou can obtain a ValueStream either by calling the `createValueStream()` method on a LevelUP object or by passing passing an options object to `createReadStream()` with `values` set to `true` and `keys` set to `false`.\n\n```js\ndb.createValueStream()\n  .on('data', function (data) {\n    console.log('value=', data)\n  })\n\n// same as:\ndb.createReadStream({ keys: false, values: true })\n  .on('data', function (data) {\n    console.log('value=', data)\n  })\n```\n\n--------------------------------------------------------\n<a name=\"createWriteStream\"></a>\n### db.createWriteStream([options])\n\nA **WriteStream** can be obtained by calling the `createWriteStream()` method. The resulting stream is a complete Node.js-style [Writable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_writable_stream) which accepts objects with `'key'` and `'value'` pairs on its `write()` method.\n\nThe WriteStream will buffer writes and submit them as a `batch()` operations where writes occur *within the same tick*.\n\n```js\nvar ws = db.createWriteStream()\n\nws.on('error', function (err) {\n  console.log('Oh my!', err)\n})\nws.on('close', function () {\n  console.log('Stream closed')\n})\n\nws.write({ key: 'name', value: 'Yuri Irsenovich Kim' })\nws.write({ key: 'dob', value: '16 February 1941' })\nws.write({ key: 'spouse', value: 'Kim Young-sook' })\nws.write({ key: 'occupation', value: 'Clown' })\nws.end()\n```\n\nThe standard `write()`, `end()`, `destroy()` and `destroySoon()` methods are implemented on the WriteStream. `'drain'`, `'error'`, `'close'` and `'pipe'` events are emitted.\n\nYou can specify encodings both for the whole stream and individual entries:\n\nTo set the encoding for the whole stream, provide an options object as the first parameter to `createWriteStream()` with `'keyEncoding'` and/or `'valueEncoding'`.\n\nTo set the encoding for an individual entry:\n\n```js\nwriteStream.write({\n    key           : new Buffer([1, 2, 3])\n  , value         : { some: 'json' }\n  , keyEncoding   : 'binary'\n  , valueEncoding : 'json'\n})\n```\n\n#### write({ type: 'put' })\n\nIf individual `write()` operations are performed with a `'type'` property of `'del'`, they will be passed on as `'del'` operations to the batch.\n\n```js\nvar ws = db.createWriteStream()\n\nws.on('error', function (err) {\n  console.log('Oh my!', err)\n})\nws.on('close', function () {\n  console.log('Stream closed')\n})\n\nws.write({ type: 'del', key: 'name' })\nws.write({ type: 'del', key: 'dob' })\nws.write({ type: 'put', key: 'spouse' })\nws.write({ type: 'del', key: 'occupation' })\nws.end()\n```\n\n#### db.createWriteStream({ type: 'del' })\n\nIf the *WriteStream* is created with a `'type'` option of `'del'`, all `write()` operations will be interpreted as `'del'`, unless explicitly specified as `'put'`.\n\n```js\nvar ws = db.createWriteStream({ type: 'del' })\n\nws.on('error', function (err) {\n  console.log('Oh my!', err)\n})\nws.on('close', function () {\n  console.log('Stream closed')\n})\n\nws.write({ key: 'name' })\nws.write({ key: 'dob' })\n// but it can be overridden\nws.write({ type: 'put', key: 'spouse', value: 'Ri Sol-ju' })\nws.write({ key: 'occupation' })\nws.end()\n```\n\n#### Pipes and Node Stream compatibility\n\nA ReadStream can be piped directly to a WriteStream, allowing for easy copying of an entire database. A simple `copy()` operation is included in LevelUP that performs exactly this on two open databases:\n\n```js\nfunction copy (srcdb, dstdb, callback) {\n  srcdb.createReadStream().pipe(dstdb.createWriteStream()).on('close', callback)\n}\n```\n\nThe ReadStream is also [fstream](https://github.com/isaacs/fstream)-compatible which means you should be able to pipe to and from fstreams. So you can serialize and deserialize an entire database to a directory where keys are filenames and values are their contents, or even into a *tar* file using [node-tar](https://github.com/isaacs/node-tar). See the [fstream functional test](https://github.com/rvagg/node-levelup/blob/master/test/functional/fstream-test.js) for an example. *(Note: I'm not really sure there's a great use-case for this but it's a fun example and it helps to harden the stream implementations.)*\n\nKeyStreams and ValueStreams can be treated like standard streams of raw data. If `'keyEncoding'` or `'valueEncoding'` is set to `'binary'` the `'data'` events will simply be standard Node `Buffer` objects straight out of the data store.\n\n\n--------------------------------------------------------\n<a name='approximateSize'></a>\n### db.db.approximateSize(start, end, callback)\n<code>approximateSize()</code> can used to get the approximate number of bytes of file system space used by the range `[start..end)`. The result may not include recently written data.\n\n```js\nvar db = require('level')('./huge.db')\n\ndb.db.approximateSize('a', 'c', function (err, size) {\n  if (err) return console.error('Ooops!', err)\n  console.log('Approximate size of range is %d', size)\n})\n```\n\n**Note:** `approximateSize()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/), which by default is accessible as the `db` property of your LevelUP instance. This is a specific LevelDB operation and is not likely to be available where you replace LevelDOWN with an alternative back-end via the `'db'` option.\n\n\n--------------------------------------------------------\n<a name='getProperty'></a>\n### db.db.getProperty(property)\n<code>getProperty</code> can be used to get internal details from LevelDB. When issued with a valid property string, a readable string will be returned (this method is synchronous).\n\nCurrently, the only valid properties are:\n\n* <b><code>'leveldb.num-files-at-levelN'</code></b>: returns the number of files at level *N*, where N is an integer representing a valid level (e.g. \"0\").\n\n* <b><code>'leveldb.stats'</code></b>: returns a multi-line string describing statistics about LevelDB's internal operation.\n\n* <b><code>'leveldb.sstables'</code></b>: returns a multi-line string describing all of the *sstables* that make up contents of the current database.\n\n\n```js\nvar db = require('level')('./huge.db')\nconsole.log(db.db.getProperty('leveldb.num-files-at-level3'))\n// → '243'\n```\n\n**Note:** `getProperty()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/), which by default is accessible as the `db` property of your LevelUP instance. This is a specific LevelDB operation and is not likely to be available where you replace LevelDOWN with an alternative back-end via the `'db'` option.\n\n\n--------------------------------------------------------\n<a name=\"destroy\"></a>\n### leveldown.destroy(location, callback)\n<code>destroy()</code> is used to completely remove an existing LevelDB database directory. You can use this function in place of a full directory *rm* if you want to be sure to only remove LevelDB-related files. If the directory only contains LevelDB files, the directory itself will be removed as well. If there are additional, non-LevelDB files in the directory, those files, and the directory, will be left alone.\n\nThe callback will be called when the destroy operation is complete, with a possible `error` argument.\n\n**Note:** `destroy()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/) which you will have to install seperately, e.g.:\n\n```js\nrequire('leveldown').destroy('./huge.db', function (err) { console.log('done!') })\n```\n\n--------------------------------------------------------\n<a name=\"repair\"></a>\n### leveldown.repair(location, callback)\n<code>repair()</code> can be used to attempt a restoration of a damaged LevelDB store. From the LevelDB documentation:\n\n> If a DB cannot be opened, you may attempt to call this method to resurrect as much of the contents of the database as possible. Some data may be lost, so be careful when calling this function on a database that contains important information.\n\nYou will find information on the *repair* operation in the *LOG* file inside the store directory. \n\nA `repair()` can also be used to perform a compaction of the LevelDB log into table files.\n\nThe callback will be called when the repair operation is complete, with a possible `error` argument.\n\n**Note:** `repair()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/) which you will have to install seperately, e.g.:\n\n```js\nrequire('leveldown').repair('./huge.db', function (err) { console.log('done!') })\n```\n\n--------------------------------------------------------\n\n<a name=\"events\"></a>\nEvents\n------\n\nLevelUP emits events when the callbacks to the corresponding methods are called.\n\n* `db.emit('put', key, value)` emitted when a new value is `'put'`\n* `db.emit('del', key)` emitted when a value is deleted\n* `db.emit('batch', ary)` emitted when a batch operation has executed\n* `db.emit('ready')` emitted when the database has opened (`'open'` is synonym)\n* `db.emit('closed')` emitted when the database has closed\n* `db.emit('opening')` emitted when the database is opening\n* `db.emit('closing')` emitted when the database is closing\n\nIf you do not pass a callback to an async function, and there is an error, LevelUP will `emit('error', err)` instead.\n\n<a name=\"json\"></a>\nJSON data\n---------\n\nYou specify `'json'` encoding for both keys and/or values, you can then supply JavaScript objects to LevelUP and receive them from all fetch operations, including ReadStreams. LevelUP will automatically *stringify* your objects and store them as *utf8* and parse the strings back into objects before passing them back to you.\n\n<a name=\"custom_encodings\"></a>\nCustom encodings\n----------------\n\nA custom encoding may be provided by passing in an object as an value for `keyEncoding` or `valueEncoding` (wherever accepted), it must have the following properties:\n\n```js\n{\n    encode : function (val) { ... }\n  , decode : function (val) { ... }\n  , buffer : boolean // encode returns a buffer and decode accepts a buffer\n  , type   : String  // name of this encoding type.\n}\n```\n\n<a name=\"extending\"></a>\nExtending LevelUP\n-----------------\n\nA list of <a href=\"https://github.com/rvagg/node-levelup/wiki/Modules\"><b>Node.js LevelDB modules and projects</b></a> can be found in the wiki.\n\nWhen attempting to extend the functionality of LevelUP, it is recommended that you consider using [level-hooks](https://github.com/dominictarr/level-hooks) and/or [level-sublevel](https://github.com/dominictarr/level-sublevel). **level-sublevel** is particularly helpful for keeping additional, extension-specific, data in a LevelDB store. It allows you to partition a LevelUP instance into multiple sub-instances that each correspond to discrete namespaced key ranges.\n\n<a name=\"multiproc\"></a>\nMulti-process access\n--------------------\n\nLevelDB is thread-safe but is **not** suitable for accessing with multiple processes. You should only ever have a LevelDB database open from a single Node.js process. Node.js clusters are made up of multiple processes so a LevelUP instance cannot be shared between them either.\n\nSee the <a href=\"https://github.com/rvagg/node-levelup/wiki/Modules\"><b>wiki</b></a> for some LevelUP extensions, including [multilevel](https://github.com/juliangruber/multilevel), that may help if you require a single data store to be shared across processes.\n\n<a name=\"support\"></a>\nGetting support\n---------------\n\nThere are multiple ways you can find help in using LevelDB in Node.js:\n\n * **IRC:** you'll find an active group of LevelUP users in the **##leveldb** channel on Freenode, including most of the contributors to this project.\n * **Mailing list:** there is an active [Node.js LevelDB](https://groups.google.com/forum/#!forum/node-levelup) Google Group.\n * **GitHub:** you're welcome to open an issue here on this GitHub repository if you have a question.\n\n<a name=\"contributing\"></a>\nContributing\n------------\n\nLevelUP is an **OPEN Open Source Project**. This means that:\n\n> Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.\n\nSee the [CONTRIBUTING.md](https://github.com/rvagg/node-levelup/blob/master/CONTRIBUTING.md) file for more details.\n\n### Contributors\n\nLevelUP is only possible due to the excellent work of the following contributors:\n\n<table><tbody>\n<tr><th align=\"left\">Rod Vagg</th><td><a href=\"https://github.com/rvagg\">GitHub/rvagg</a></td><td><a href=\"http://twitter.com/rvagg\">Twitter/@rvagg</a></td></tr>\n<tr><th align=\"left\">John Chesley</th><td><a href=\"https://github.com/chesles/\">GitHub/chesles</a></td><td><a href=\"http://twitter.com/chesles\">Twitter/@chesles</a></td></tr>\n<tr><th align=\"left\">Jake Verbaten</th><td><a href=\"https://github.com/raynos\">GitHub/raynos</a></td><td><a href=\"http://twitter.com/raynos2\">Twitter/@raynos2</a></td></tr>\n<tr><th align=\"left\">Dominic Tarr</th><td><a href=\"https://github.com/dominictarr\">GitHub/dominictarr</a></td><td><a href=\"http://twitter.com/dominictarr\">Twitter/@dominictarr</a></td></tr>\n<tr><th align=\"left\">Max Ogden</th><td><a href=\"https://github.com/maxogden\">GitHub/maxogden</a></td><td><a href=\"http://twitter.com/maxogden\">Twitter/@maxogden</a></td></tr>\n<tr><th align=\"left\">Lars-Magnus Skog</th><td><a href=\"https://github.com/ralphtheninja\">GitHub/ralphtheninja</a></td><td><a href=\"http://twitter.com/ralphtheninja\">Twitter/@ralphtheninja</a></td></tr>\n<tr><th align=\"left\">David Björklund</th><td><a href=\"https://github.com/kesla\">GitHub/kesla</a></td><td><a href=\"http://twitter.com/david_bjorklund\">Twitter/@david_bjorklund</a></td></tr>\n<tr><th align=\"left\">Julian Gruber</th><td><a href=\"https://github.com/juliangruber\">GitHub/juliangruber</a></td><td><a href=\"http://twitter.com/juliangruber\">Twitter/@juliangruber</a></td></tr>\n<tr><th align=\"left\">Paolo Fragomeni</th><td><a href=\"https://github.com/hij1nx\">GitHub/hij1nx</a></td><td><a href=\"http://twitter.com/hij1nx\">Twitter/@hij1nx</a></td></tr>\n<tr><th align=\"left\">Anton Whalley</th><td><a href=\"https://github.com/No9\">GitHub/No9</a></td><td><a href=\"https://twitter.com/antonwhalley\">Twitter/@antonwhalley</a></td></tr>\n<tr><th align=\"left\">Matteo Collina</th><td><a href=\"https://github.com/mcollina\">GitHub/mcollina</a></td><td><a href=\"https://twitter.com/matteocollina\">Twitter/@matteocollina</a></td></tr>\n<tr><th align=\"left\">Pedro Teixeira</th><td><a href=\"https://github.com/pgte\">GitHub/pgte</a></td><td><a href=\"https://twitter.com/pgte\">Twitter/@pgte</a></td></tr>\n<tr><th align=\"left\">James Halliday</th><td><a href=\"https://github.com/substack\">GitHub/substack</a></td><td><a href=\"https://twitter.com/substack\">Twitter/@substack</a></td></tr>\n</tbody></table>\n\n### Windows\n\nA large portion of the Windows support comes from code by [Krzysztof Kowalczyk](http://blog.kowalczyk.info/) [@kjk](https://twitter.com/kjk), see his Windows LevelDB port [here](http://code.google.com/r/kkowalczyk-leveldb/). If you're using LevelUP on Windows, you should give him your thanks!\n\n\n<a name=\"license\"></a>\nLicense &amp; copyright\n-------------------\n\nCopyright (c) 2012-2014 LevelUP contributors (listed above).\n\nLevelUP is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details.\n\n=======\n*LevelUP builds on the excellent work of the LevelDB and Snappy teams from Google and additional contributors. LevelDB and Snappy are both issued under the [New BSD Licence](http://opensource.org/licenses/BSD-3-Clause).*\n",
    "readmeFilename": "README.md",
    "bugs": {
      "url": "https://github.com/rvagg/node-levelup/issues"
    },
    "_id": "levelup@0.19.0",
    "_shasum": "f6b60a168c86c2fe5d5953476cbe9786ccf0a3f7",
    "_resolved": "https://registry.npmjs.org/levelup/-/levelup-0.19.0.tgz",
    "_from": "levelup@>=0.19.0 <0.20.0"
  }
  
  },{}],107:[function(_dereq_,module,exports){
  (function (Buffer){
  
  exports.compare = function (a, b) {
  
    if(Buffer.isBuffer(a)) {
      var l = Math.min(a.length, b.length)
      for(var i = 0; i < l; i++) {
        var cmp = a[i] - b[i]
        if(cmp) return cmp
      }
      return a.length - b.length
    }
  
    return a < b ? -1 : a > b ? 1 : 0
  }
  
  function has(obj, key) {
    return Object.hasOwnProperty.call(obj, key)
  }
  
  // to be compatible with the current abstract-leveldown tests
  // nullish or empty strings.
  // I could use !!val but I want to permit numbers and booleans,
  // if possible.
  
  function isDef (val) {
    return val !== undefined && val !== ''
  }
  
  function has (range, name) {
    return Object.hasOwnProperty.call(range, name)
  }
  
  function hasKey(range, name) {
    return Object.hasOwnProperty.call(range, name) && name
  }
  
  var lowerBoundKey = exports.lowerBoundKey = function (range) {
      return (
         hasKey(range, 'gt')
      || hasKey(range, 'gte')
      || hasKey(range, 'min')
      || (range.reverse ? hasKey(range, 'end') : hasKey(range, 'start'))
      || undefined
      )
  }
  
  var lowerBound = exports.lowerBound = function (range) {
    var k = lowerBoundKey(range)
    return k && range[k]
  }
  
  exports.lowerBoundInclusive = function (range) {
    return has(range, 'gt') ? false : true
  }
  
  exports.upperBoundInclusive =
    function (range) {
      return has(range, 'lt') || !range.minEx ? false : true
    }
  
  var lowerBoundExclusive = exports.lowerBoundExclusive =
    function (range) {
      return has(range, 'gt') || range.minEx ? true : false
    }
  
  var upperBoundExclusive = exports.upperBoundExclusive =
    function (range) {
      return has(range, 'lt') ? true : false
    }
  
  var upperBoundKey = exports.upperBoundKey = function (range) {
      return (
         hasKey(range, 'lt')
      || hasKey(range, 'lte')
      || hasKey(range, 'max')
      || (range.reverse ? hasKey(range, 'start') : hasKey(range, 'end'))
      || undefined
      )
  }
  
  var upperBound = exports.upperBound = function (range) {
    var k = upperBoundKey(range)
    return k && range[k]
  }
  
  function id (e) { return e }
  
  exports.toLtgt = function (range, _range, map, lower, upper) {
    _range = _range || {}
    map = map || id
    var defaults = arguments.length > 3
    var lb = exports.lowerBoundKey(range)
    var ub = exports.upperBoundKey(range)
    if(lb) {
      if(lb === 'gt') _range.gt = map(range.gt, false)
      else            _range.gte = map(range[lb], false)
    }
    else if(defaults)
      _range.gte = map(lower, false)
  
    if(ub) {
      if(ub === 'lt') _range.lt = map(range.lt, true)
      else            _range.lte = map(range[ub], true)
    }
    else if(defaults)
      _range.lte = map(upper, true)
  
    if(range.reverse != null)
      _range.reverse = !!range.reverse
  
    //if range was used mutably
    //(in level-sublevel it's part of an options object
    //that has more properties on it.)
    if(has(_range, 'max'))   delete _range.max
    if(has(_range, 'min'))   delete _range.min
    if(has(_range, 'start')) delete _range.start
    if(has(_range, 'end'))   delete _range.end
  
    return _range
  }
  
  exports.contains = function (range, key, compare) {
    compare = compare || exports.compare
  
    var lb = lowerBound(range)
    if(isDef(lb)) {
      var cmp = compare(key, lb)
      if(cmp < 0 || (cmp === 0 && lowerBoundExclusive(range)))
        return false
    }
  
    var ub = upperBound(range)
    if(isDef(ub)) {
      var cmp = compare(key, ub)
      if(cmp > 0 || (cmp === 0) && upperBoundExclusive(range))
        return false
    }
  
    return true
  }
  
  exports.filter = function (range, compare) {
    return function (key) {
      return exports.contains(range, key, compare)
    }
  }
  
  }).call(this,_dereq_(56).Buffer)
  },{"56":56}],108:[function(_dereq_,module,exports){
  arguments[4][105][0].apply(exports,arguments)
  },{"105":105}],109:[function(_dereq_,module,exports){
  var hooks = _dereq_(86)
  var ltgt = _dereq_(107)
  
  function isFunction (f) {
    return 'function' === typeof f
  }
  
  function getPrefix (db) {
    if(db == null) return db
    if(isFunction(db.prefix)) return db.prefix()
    return db
  }
  
  function has(obj, name) {
    return Object.hasOwnProperty.call(obj, name)
  }
  
  function clone (_obj) {
    var obj = {}
    for(var k in _obj)
      obj[k] = _obj[k]
    return obj
  }
  
  module.exports = function (db, precodec, codec, compare) {
    var prehooks = hooks(compare)
    var posthooks = hooks(compare)
    var waiting = [], ready = false
  
    function encodePrefix(prefix, key, opts1, opts2) {
      return precodec.encode([ prefix, codec.encodeKey(key, opts1, opts2 ) ])
    }
  
    function decodePrefix(data) {
      return precodec.decode(data)
    }
  
    function addEncodings(op, prefix) {
      if(prefix && prefix.options) {
        op.keyEncoding =
          op.keyEncoding || prefix.options.keyEncoding
        op.valueEncoding =
          op.valueEncoding || prefix.options.valueEncoding
      }
      return op
    }
  
    function start () {
      ready = true
      while(waiting.length)
        waiting.shift()()
    }
  
    if(isFunction(db.isOpen)) {
      if(db.isOpen())
        ready = true
      else
        db.open(start)
    } else {
      db.open(start)
    }
  
    return {
      apply: function (ops, opts, cb) {
        //apply prehooks here.
        for(var i = 0; i < ops.length; i++) {
          var op = ops[i]
  
          function add(op) {
            if(op === false) return delete ops[i]
            ops.push(op)
          }
  
          addEncodings(op, op.prefix)
          op.prefix = getPrefix(op.prefix)
          prehooks.trigger([op.prefix, op.key], [op, add, ops])
        }
  
        opts = opts || {}
  
        if('object' !== typeof opts) throw new Error('opts must be object, was:'+ opts) 
  
        if('function' === typeof opts) cb = opts, opts = {}
  
        if(ops.length)
          (db.db || db).batch(
            ops.map(function (op) {
              return {
                key: encodePrefix(op.prefix, op.key, opts, op),
                value:
                    op.type !== 'del'
                  ? codec.encodeValue(
                      op.value,
                      opts,
                      op
                    )
                  : undefined,
                type:
                  op.type || (op.value === undefined ? 'del' : 'put')
              }
            }),
            opts,
            function (err) {
                if(err) return cb(err)
              ops.forEach(function (op) {
                posthooks.trigger([op.prefix, op.key], [op])
              })
              cb()
            }
          )
        else
          cb()
      },
      get: function (key, prefix, opts, cb) {
        opts.asBuffer = codec.isValueAsBuffer(opts)
        return (db.db || db).get(
          encodePrefix(prefix, key, opts),
          opts,
          function (err, value) {
            if(err) cb(err)
            else    cb(null, codec.decodeValue(value, opts))
          }
        )
      },
      pre: prehooks.add,
      post: posthooks.add,
      createDecoder: function (opts) {
        if(opts.keys !== false && opts.values !== false)
          return function (key, value) {
            return {
              key: codec.decodeKey(precodec.decode(key)[1], opts),
              value: codec.decodeValue(value, opts)
            }
          }
        if(opts.values !== false)
          return function (_, value) {
            return codec.decodeValue(value, opts)
          }
        if(opts.keys !== false)
          return function (key) {
            return codec.decodeKey(precodec.decode(key)[1], opts)
          }
        return function () {}
      },
      isOpen: function isOpen() {
        if (db.db && isFunction(db.db.isOpen))
          return db.db.isOpen()
  
        return db.isOpen()
      },
      isClosed: function isClosed() {
        if (db.db && isFunction(db.db.isClosed))
          return db.db.isClosed()
  
        return db.isClosed()
      },
      close: function close (cb) {
        return db.close(cb)
      },
      iterator: function (_opts, cb) {
        var opts = clone(_opts || {})
        var prefix = _opts.prefix || []
  
        function encodeKey(key) {
          return encodePrefix(prefix, key, opts, {})
        }
  
        ltgt.toLtgt(_opts, opts, encodeKey, precodec.lowerBound, precodec.upperBound)
  
        // if these legacy values are in the options, remove them
  
        opts.prefix = null
  
        //************************************************
        //hard coded defaults, for now...
        //TODO: pull defaults and encoding out of levelup.
        opts.keyAsBuffer = opts.valueAsBuffer = false
        //************************************************
  
  
        //this is vital, otherwise limit: undefined will
        //create an empty stream.
        if ('number' !== typeof opts.limit)
          opts.limit = -1
  
        opts.keyAsBuffer = precodec.buffer
        opts.valueAsBuffer = codec.isValueAsBuffer(opts)
  
        function wrapIterator (iterator) {
          return {
            next: function (cb) {
              return iterator.next(cb)
            },
            end: function (cb) {
              iterator.end(cb)
            }
          }
        }
  
        if(ready)
          return wrapIterator((db.db || db).iterator(opts))
        else
          waiting.push(function () {
            cb(null, wrapIterator((db.db || db).iterator(opts)))
          })
  
      }
    }
  
  }
  
  },{"107":107,"86":86}],110:[function(_dereq_,module,exports){
  module.exports={
    "name": "level-sublevel",
    "description": "partition levelup databases",
    "version": "6.5.1",
    "homepage": "https://github.com/dominictarr/level-sublevel",
    "repository": {
      "type": "git",
      "url": "git://github.com/dominictarr/level-sublevel.git"
    },
    "dependencies": {
      "pull-stream": "~2.21.0",
      "ltgt": "~2.1.1",
      "levelup": "~0.19.0",
      "xtend": "~4.0.0",
      "bytewise": "~0.7.1",
      "typewiselite": "~1.0.0"
    },
    "devDependencies": {
      "level": "~0.18.0",
      "level-test": ">=1.5.1 <2",
      "monotonic-timestamp": "0.0.8",
      "pull-level": "~1.1.1",
      "rimraf": "~2.1.4",
      "shasum": "0.0.2",
      "stream-to-pull-stream": "~1.2.0",
      "tape": "~2.14.0",
      "through": "~2.3.4",
      "leveldown": "~1.0.1"
    },
    "scripts": {
      "test": "set -e; for t in test/*.js; do node $t; done"
    },
    "author": {
      "name": "Dominic Tarr",
      "email": "dominic.tarr@gmail.com",
      "url": "http://dominictarr.com"
    },
    "license": "MIT",
    "stability": "unstable",
    "testling": {
      "files": "test/*.js",
      "browsers": [
        "ie/8..latest",
        "firefox/17..latest",
        "firefox/nightly",
        "chrome/22..latest",
        "chrome/canary",
        "opera/12..latest",
        "opera/next",
        "safari/5.1..latest",
        "ipad/6.0..latest",
        "iphone/6.0..latest",
        "android-browser/4.2..latest"
      ]
    },
    "gitHead": "2e0b099c01a724f8eb8750b4db53e72f3e7d1829",
    "bugs": {
      "url": "https://github.com/dominictarr/level-sublevel/issues"
    },
    "_id": "level-sublevel@6.5.1",
    "_shasum": "0f4fa2f5aa2a89a37a4161021e3f816b77d41858",
    "_from": "level-sublevel@>=6.5.0 <7.0.0",
    "_npmVersion": "3.3.1",
    "_nodeVersion": "2.3.1",
    "_npmUser": {
      "name": "dominictarr",
      "email": "dominic.tarr@gmail.com"
    },
    "maintainers": [
      {
        "name": "dominictarr",
        "email": "dominic.tarr@gmail.com"
      }
    ],
    "dist": {
      "shasum": "0f4fa2f5aa2a89a37a4161021e3f816b77d41858",
      "tarball": "http://127.0.0.1:5080/tarballs/level-sublevel/6.5.1.tgz"
    },
    "_resolved": "http://127.0.0.1:5080/tarballs/level-sublevel/6.5.1.tgz",
    "readme": "ERROR: No README data found!"
  }
  
  },{}],111:[function(_dereq_,module,exports){
  (function (Buffer){
  var ltgt = _dereq_(107)
  
  //compare two array items
  function isArrayLike (a) {
    return Array.isArray(a) || Buffer.isBuffer(a)
  }
  
  function isPrimitive (a) {
    return 'string' === typeof a || 'number' === typeof a
  }
  
  function has(o, k) {
    return Object.hasOwnProperty.call(o, k)
  }
  
  function compare (a, b) {
  
    if(isArrayLike(a) && isArrayLike(b)) {
      var l = Math.min(a.length, b.length)
      for(var i = 0; i < l; i++) {
        var c = compare(a[i], b[i])
        if(c) return c
      }
      return a.length - b.length
    }
    if(isPrimitive(a) && isPrimitive(b))
      return a < b ? -1 : a > b ? 1 : 0
  
    throw new Error('items not comparable:'
      + JSON.stringify(a) + ' ' + JSON.stringify(b))
  }
  
  //this assumes that the prefix is of the form:
  // [Array, string]
  
  function prefix (a, b) {
    if(a.length > b.length) return false
    var l = a.length - 1
    var lastA = a[l]
    var lastB = b[l]
  
    if(typeof lastA !== typeof lastB)
      return false
  
    if('string' == typeof lastA
      && 0 != lastB.indexOf(lastA))
        return false
    
    //handle cas where there is no key prefix
    //(a hook on an entire sublevel)
    if(a.length == 1 && isArrayLike(lastA)) l ++
    
    while(l--) {
      if(compare(a[l], b[l])) return false
    }
    return true
  }
  
  exports = module.exports = function (range, key, _compare) {
    _compare = _compare || compare
    //handle prefix specially,
    //check that everything up to the last item is equal
    //then check the last item starts with
    if(isArrayLike(range)) return prefix(range, key)
  
    return ltgt.contains(range, key, compare)
  }
  
  function addPrefix(prefix, range) {
    var o = ltgt.toLtgt(range, null, function (key) {
      return [prefix, key]
    })
  
    //if there where no ranges, then then just use a prefix.
    if(!has(o, 'gte') && !has(o, 'lte')) return [prefix]
  
    return o
  }
  
  exports.compare = compare
  exports.prefix = prefix
  exports.addPrefix = addPrefix
  
  }).call(this,_dereq_(56).Buffer)
  },{"107":107,"56":56}],112:[function(_dereq_,module,exports){
  (function (process){
  var EventEmitter = _dereq_(60).EventEmitter
  var addpre = _dereq_(111).addPrefix
  
  var errors = _dereq_(90)
  
  function isFunction (f) {
    return 'function' === typeof f
  }
  
  function isString (s) {
    return 'string' === typeof s
  }
  
  function isObject (o) {
    return o && 'object' === typeof o
  }
  
  var version = _dereq_(110).version
  
  var sublevel = module.exports = function (nut, prefix, createStream, options) {
    var emitter = new EventEmitter()
    emitter.sublevels = {}
    emitter.options = options
  
    emitter.version = version
  
    emitter.methods = {}
    prefix = prefix || []
  
    function errback (err) { if (err) emitter.emit('error', err) }
  
    createStream = createStream || function (e) { return e }
  
    function mergeOpts(opts) {
      var o = {}
      if(options)
        for(var k in options)
          if(options[k] != undefined)o[k] = options[k]
      if(opts)
        for(var k in opts)
          if(opts[k] != undefined) o[k] = opts[k]
      return o
    }
  
    emitter.put = function (key, value, opts, cb) {
      if('function' === typeof opts) cb = opts, opts = {}
      if(!cb) cb = errback
  
      nut.apply([{
        key: key, value: value,
        prefix: prefix.slice(), type: 'put'
      }], mergeOpts(opts), function (err) {
        if(!err) { emitter.emit('put', key, value); cb(null) }
        if(err) return cb(err)
      })
    }
  
    emitter.prefix = function () {
      return prefix.slice()
    }
  
    emitter.del = function (key, opts, cb) {
      if('function' === typeof opts) cb = opts, opts = {}
      if(!cb) cb = errback
  
      nut.apply([{
        key: key,
        prefix: prefix.slice(), type: 'del'
      }], mergeOpts(opts), function (err) {
        if(!err) { emitter.emit('del', key); cb(null) }
        if(err) return cb(err)
      })
    }
  
    emitter.batch = function (ops, opts, cb) {
      if('function' === typeof opts)
        cb = opts, opts = {}
      if(!cb) cb = errback
  
      ops = ops.map(function (op) {
        return {
          key:           op.key,
          value:         op.value,
          prefix:        op.prefix || prefix,
          keyEncoding:   op.keyEncoding,    // *
          valueEncoding: op.valueEncoding,  // * (TODO: encodings on sublevel)
          type:          op.type
        }
      })
  
      nut.apply(ops, mergeOpts(opts), function (err) {
        if(!err) { emitter.emit('batch', ops); cb(null) }
        if(err) return cb(err)
      })
    }
  
    emitter.get = function (key, opts, cb) {
      if('function' === typeof opts)
        cb = opts, opts = {}
      nut.get(key, prefix, mergeOpts(opts), function (err, value) {
        if(err) cb(new errors.NotFoundError('Key not found in database', err))
        else cb(null, value)
      })
    }
  
    emitter.clone = function(opts) {
      return sublevel(nut, prefix, createStream, mergeOpts(opts))
    }
  
    emitter.sublevel = function (name, opts) {
      return emitter.sublevels[name] =
        emitter.sublevels[name] || sublevel(nut, prefix.concat(name), createStream, mergeOpts(opts))
    }
  
    emitter.pre = function (key, hook) {
      if(isFunction(key)) return nut.pre([prefix], key)
      if(isString(key)) return nut.pre([prefix, key], hook)
      if(isObject(key)) return nut.pre(addpre(prefix, key), hook)
  
      throw new Error('not implemented yet')
    }
  
    emitter.post = function (key, hook) {
      if(isFunction(key)) return nut.post([prefix], key)
      if(isString(key))   return nut.post([prefix, key], hook)
      if(isObject(key))   return nut.post(addpre(prefix, key), hook)
  
      //TODO: handle ranges, needed for level-live-stream, etc.
      throw new Error('not implemented yet')
    }
  
    emitter.readStream =
    emitter.createReadStream = function (opts) {
      opts = mergeOpts(opts)
      opts.prefix = prefix
      var stream
      var it = nut.iterator(opts, function (err, it) {
        stream.setIterator(it)
      })
  
      stream = createStream(opts, nut.createDecoder(opts))
      if(it) stream.setIterator(it)
  
      return stream
    }
  
    emitter.valueStream =
    emitter.createValueStream = function (opts) {
      opts = opts || {}
      opts.values = true
      opts.keys = false
      return emitter.createReadStream(opts)
    }
  
    emitter.keyStream =
    emitter.createKeyStream = function (opts) {
      opts = opts || {}
      opts.values = false
      opts.keys = true
      return emitter.createReadStream(opts)
    }
  
    emitter.close = function (cb) {
      //TODO: deregister all hooks
      cb = cb || function () {}
      if (!prefix.length) nut.close(cb)
      else process.nextTick(cb)
    }
  
    emitter.isOpen = nut.isOpen
    emitter.isClosed = nut.isClosed
  
    return emitter
  }
  
  }).call(this,_dereq_(62))
  },{"110":110,"111":111,"60":60,"62":62,"90":90}],113:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2015 LevelUP contributors
   * See list at <https://github.com/level/levelup#contributing>
   * MIT License
   * <https://github.com/level/levelup/blob/master/LICENSE.md>
   */
  
  var util          = _dereq_(115)
    , WriteError    = _dereq_(122).WriteError
  
    , getOptions    = util.getOptions
    , dispatchError = util.dispatchError
  
  function Batch (levelup, codec) {
    this._levelup = levelup
    this._codec = codec
    this.batch = levelup.db.batch()
    this.ops = []
  }
  
  Batch.prototype.put = function (key_, value_, options) {
    options = getOptions(options)
  
    var key   = this._codec.encodeKey(key_, options)
      , value = this._codec.encodeValue(value_, options)
  
    try {
      this.batch.put(key, value)
    } catch (e) {
      throw new WriteError(e)
    }
    this.ops.push({ type : 'put', key : key, value : value })
  
    return this
  }
  
  Batch.prototype.del = function (key_, options) {
    options = getOptions(options)
  
    var key = this._codec.encodeKey(key_, options)
  
    try {
      this.batch.del(key)
    } catch (err) {
      throw new WriteError(err)
    }
    this.ops.push({ type : 'del', key : key })
  
    return this
  }
  
  Batch.prototype.clear = function () {
    try {
      this.batch.clear()
    } catch (err) {
      throw new WriteError(err)
    }
  
    this.ops = []
    return this
  }
  
  Batch.prototype.write = function (callback) {
    var levelup = this._levelup
      , ops     = this.ops
  
    try {
      this.batch.write(function (err) {
        if (err)
          return dispatchError(levelup, new WriteError(err), callback)
        levelup.emit('batch', ops)
        if (callback)
          callback()
      })
    } catch (err) {
      throw new WriteError(err)
    }
  }
  
  module.exports = Batch
  
  },{"115":115,"122":122}],114:[function(_dereq_,module,exports){
  (function (process){
  /* Copyright (c) 2012-2015 LevelUP contributors
   * See list at <https://github.com/level/levelup#contributing>
   * MIT License
   * <https://github.com/level/levelup/blob/master/LICENSE.md>
   */
  
  var EventEmitter        = _dereq_(60).EventEmitter
    , inherits            = _dereq_(79).inherits
    , deprecate           = _dereq_(79).deprecate
    , extend              = _dereq_(137)
    , prr                 = _dereq_(136)
    , DeferredLevelDOWN   = _dereq_(116)
    , IteratorStream      = _dereq_(126)
  
    , errors              = _dereq_(122)
    , WriteError          = errors.WriteError
    , ReadError           = errors.ReadError
    , NotFoundError       = errors.NotFoundError
    , OpenError           = errors.OpenError
    , EncodingError       = errors.EncodingError
    , InitializationError = errors.InitializationError
  
    , util                = _dereq_(115)
    , Batch               = _dereq_(113)
    , Codec               = _dereq_(120)
  
    , getOptions          = util.getOptions
    , defaultOptions      = util.defaultOptions
    , getLevelDOWN        = util.getLevelDOWN
    , dispatchError       = util.dispatchError
    , isDefined           = util.isDefined
  
  function getCallback (options, callback) {
    return typeof options == 'function' ? options : callback
  }
  
  // Possible LevelUP#_status values:
  //  - 'new'     - newly created, not opened or closed
  //  - 'opening' - waiting for the database to be opened, post open()
  //  - 'open'    - successfully opened the database, available for use
  //  - 'closing' - waiting for the database to be closed, post close()
  //  - 'closed'  - database has been successfully closed, should not be
  //                 used except for another open() operation
  
  function LevelUP (location, options, callback) {
    if (!(this instanceof LevelUP))
      return new LevelUP(location, options, callback)
  
    var error
  
    EventEmitter.call(this)
    this.setMaxListeners(Infinity)
  
    if (typeof location == 'function') {
      options = typeof options == 'object' ? options : {}
      options.db = location
      location = null
    } else if (typeof location == 'object' && typeof location.db == 'function') {
      options = location
      location = null
    }
  
  
    if (typeof options == 'function') {
      callback = options
      options  = {}
    }
  
    if ((!options || typeof options.db != 'function') && typeof location != 'string') {
      error = new InitializationError(
          'Must provide a location for the database')
      if (callback) {
        return process.nextTick(function () {
          callback(error)
        })
      }
      throw error
    }
  
    options      = getOptions(options)
    this.options = extend(defaultOptions, options)
    this._codec = new Codec(this.options)
    this._status = 'new'
    // set this.location as enumerable but not configurable or writable
    prr(this, 'location', location, 'e')
  
    this.open(callback)
  }
  
  inherits(LevelUP, EventEmitter)
  
  LevelUP.prototype.open = function (callback) {
    var self = this
      , dbFactory
      , db
  
    if (this.isOpen()) {
      if (callback)
        process.nextTick(function () { callback(null, self) })
      return this
    }
  
    if (this._isOpening()) {
      return callback && this.once(
          'open'
        , function () { callback(null, self) }
      )
    }
  
    this.emit('opening')
  
    this._status = 'opening'
    this.db      = new DeferredLevelDOWN(this.location)
    dbFactory    = this.options.db || getLevelDOWN()
    db           = dbFactory(this.location)
  
    db.open(this.options, function (err) {
      if (err) {
        return dispatchError(self, new OpenError(err), callback)
      } else {
        self.db.setDb(db)
        self.db = db
        self._status = 'open'
        if (callback)
          callback(null, self)
        self.emit('open')
        self.emit('ready')
      }
    })
  }
  
  LevelUP.prototype.close = function (callback) {
    var self = this
  
    if (this.isOpen()) {
      this._status = 'closing'
      this.db.close(function () {
        self._status = 'closed'
        self.emit('closed')
        if (callback)
          callback.apply(null, arguments)
      })
      this.emit('closing')
      this.db = new DeferredLevelDOWN(this.location)
    } else if (this._status == 'closed' && callback) {
      return process.nextTick(callback)
    } else if (this._status == 'closing' && callback) {
      this.once('closed', callback)
    } else if (this._isOpening()) {
      this.once('open', function () {
        self.close(callback)
      })
    }
  }
  
  LevelUP.prototype.isOpen = function () {
    return this._status == 'open'
  }
  
  LevelUP.prototype._isOpening = function () {
    return this._status == 'opening'
  }
  
  LevelUP.prototype.isClosed = function () {
    return (/^clos/).test(this._status)
  }
  
  function maybeError(db, options, callback) {
    if (!db._isOpening() && !db.isOpen()) {
      dispatchError(
          db
        , new ReadError('Database is not open')
        , callback
      )
      return true
    }
  }
  
  function writeError (db, message, callback) {
    dispatchError(
        db
       , new WriteError(message)
       , callback
    )
  }
  
  function readError (db, message, callback) {
    dispatchError(
        db
       , new ReadError(message)
       , callback
    )
  }
  
  
  LevelUP.prototype.get = function (key_, options, callback) {
    var self = this
      , key
  
    callback = getCallback(options, callback)
  
    if (maybeError(this, options, callback))
      return
  
    if (key_ === null || key_ === undefined || 'function' !== typeof callback)
      return readError(this
        , 'get() requires key and callback arguments', callback)
  
    options = util.getOptions(options)
    key = this._codec.encodeKey(key_, options)
  
    options.asBuffer = this._codec.valueAsBuffer(options)
  
    this.db.get(key, options, function (err, value) {
      if (err) {
        if ((/notfound/i).test(err) || err.notFound) {
          err = new NotFoundError(
              'Key not found in database [' + key_ + ']', err)
        } else {
          err = new ReadError(err)
        }
        return dispatchError(self, err, callback)
      }
      if (callback) {
        try {
          value = self._codec.decodeValue(value, options)
        } catch (e) {
          return callback(new EncodingError(e))
        }
        callback(null, value)
      }
    })
  }
  
  LevelUP.prototype.put = function (key_, value_, options, callback) {
    var self = this
      , key
      , value
  
    callback = getCallback(options, callback)
  
    if (key_ === null || key_ === undefined)
      return writeError(this, 'put() requires a key argument', callback)
  
    if (maybeError(this, options, callback))
      return
  
    options = getOptions(options)
    key     = this._codec.encodeKey(key_, options)
    value   = this._codec.encodeValue(value_, options)
  
    this.db.put(key, value, options, function (err) {
      if (err) {
        return dispatchError(self, new WriteError(err), callback)
      } else {
        self.emit('put', key_, value_)
        if (callback)
          callback()
      }
    })
  }
  
  LevelUP.prototype.del = function (key_, options, callback) {
    var self = this
      , key
  
    callback = getCallback(options, callback)
  
    if (key_ === null || key_ === undefined)
      return writeError(this, 'del() requires a key argument', callback)
  
    if (maybeError(this, options, callback))
      return
  
    options = getOptions(options)
    key     = this._codec.encodeKey(key_, options)
  
    this.db.del(key, options, function (err) {
      if (err) {
        return dispatchError(self, new WriteError(err), callback)
      } else {
        self.emit('del', key_)
        if (callback)
          callback()
      }
    })
  }
  
  LevelUP.prototype.batch = function (arr_, options, callback) {
    var self = this
      , keyEnc
      , valueEnc
      , arr
  
    if (!arguments.length)
      return new Batch(this, this._codec)
  
    callback = getCallback(options, callback)
  
    if (!Array.isArray(arr_))
      return writeError(this, 'batch() requires an array argument', callback)
  
    if (maybeError(this, options, callback))
      return
  
    options  = getOptions(options)
    arr      = self._codec.encodeBatch(arr_, options)
    arr      = arr.map(function (op) {
      if (!op.type && op.key !== undefined && op.value !== undefined)
        op.type = 'put'
      return op
    })
  
    this.db.batch(arr, options, function (err) {
      if (err) {
        return dispatchError(self, new WriteError(err), callback)
      } else {
        self.emit('batch', arr_)
        if (callback)
          callback()
      }
    })
  }
  
  LevelUP.prototype.approximateSize = deprecate(function (start_, end_, options, callback) {   
    var self = this    
      , start    
      , end    
     
    callback = getCallback(options, callback)    
     
    options = getOptions(options)    
     
    if (start_ === null || start_ === undefined    
          || end_ === null || end_ === undefined || 'function' !== typeof callback)    
      return readError(this, 'approximateSize() requires start, end and callback arguments', callback)   
     
    start = this._codec.encodeKey(start_, options)   
    end   = this._codec.encodeKey(end_, options)   
     
    this.db.approximateSize(start, end, function (err, size) {   
      if (err) {   
        return dispatchError(self, new OpenError(err), callback)   
      } else if (callback) {   
        callback(null, size)   
      }    
    })   
  }, 'db.approximateSize() is deprecated. Use db.db.approximateSize() instead')
  
  LevelUP.prototype.readStream =
  LevelUP.prototype.createReadStream = function (options) {
    options = extend( {keys: true, values: true}, this.options, options)
  
    options.keyEncoding   = options.keyEncoding
    options.valueEncoding = options.valueEncoding
  
    options = this._codec.encodeLtgt(options);
    options.keyAsBuffer   = this._codec.keyAsBuffer(options)
    options.valueAsBuffer = this._codec.valueAsBuffer(options)
  
    if ('number' !== typeof options.limit)
      options.limit = -1
  
    return new IteratorStream(this.db.iterator(options), extend(options, {
      decoder: this._codec.createStreamDecoder(options)
    }))
  }
  
  LevelUP.prototype.keyStream =
  LevelUP.prototype.createKeyStream = function (options) {
    return this.createReadStream(extend(options, { keys: true, values: false }))
  }
  
  LevelUP.prototype.valueStream =
  LevelUP.prototype.createValueStream = function (options) {
    return this.createReadStream(extend(options, { keys: false, values: true }))
  }
  
  LevelUP.prototype.toString = function () {
    return 'LevelUP'
  }
  
  function utilStatic (name) {
    return function (location, callback) {
      getLevelDOWN()[name](location, callback || function () {})
    }
  }
  
  module.exports         = LevelUP
  module.exports.errors  = _dereq_(122)
  module.exports.destroy = deprecate(
      utilStatic('destroy')
    , 'levelup.destroy() is deprecated. Use leveldown.destroy() instead'
  )
  module.exports.repair  = deprecate(
      utilStatic('repair')
    , 'levelup.repair() is deprecated. Use leveldown.repair() instead'
  )
  
  
  }).call(this,_dereq_(62))
  },{"113":113,"115":115,"116":116,"120":120,"122":122,"126":126,"136":136,"137":137,"60":60,"62":62,"79":79}],115:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2015 LevelUP contributors
   * See list at <https://github.com/level/levelup#contributing>
   * MIT License
   * <https://github.com/level/levelup/blob/master/LICENSE.md>
   */
  
  var extend         = _dereq_(137)
    , LevelUPError   = _dereq_(122).LevelUPError
    , format         = _dereq_(79).format
    , defaultOptions = {
          createIfMissing : true
        , errorIfExists   : false
        , keyEncoding     : 'utf8'
        , valueEncoding   : 'utf8'
        , compression     : true
      }
  
    , leveldown
  
  function getOptions (options) {
    if (typeof options == 'string')
      options = { valueEncoding: options }
    if (typeof options != 'object')
      options = {}
    return options
  }
  
  function getLevelDOWN () {
    if (leveldown)
      return leveldown
  
    var requiredVersion  = _dereq_(138).devDependencies.leveldown
      , leveldownVersion
  
    try {
      leveldownVersion = _dereq_(55).version
    } catch (e) {
      throw requireError(e)
    }
  
    if (!_dereq_(55).satisfies(leveldownVersion, requiredVersion)) {
      throw new LevelUPError(
          'Installed version of LevelDOWN ('
        + leveldownVersion
        + ') does not match required version ('
        + requiredVersion
        + ')'
      )
    }
  
    try {
      return leveldown = _dereq_(55)
    } catch (e) {
      throw requireError(e)
    }
  }
  
  function requireError (e) {
    var template = 'Failed to require LevelDOWN (%s). Try `npm install leveldown` if it\'s missing'
    return new LevelUPError(format(template, e.message))
  }
  
  function dispatchError (db, error, callback) {
    typeof callback == 'function' ? callback(error) : db.emit('error', error)
  }
  
  function isDefined (v) {
    return typeof v !== 'undefined'
  }
  
  module.exports = {
      defaultOptions  : defaultOptions
    , getOptions      : getOptions
    , getLevelDOWN    : getLevelDOWN
    , dispatchError   : dispatchError
    , isDefined       : isDefined
  }
  
  },{"122":122,"137":137,"138":138,"55":55,"79":79}],116:[function(_dereq_,module,exports){
  (function (process,Buffer){
  var util              = _dereq_(79)
    , AbstractLevelDOWN = _dereq_(119).AbstractLevelDOWN
    , AbstractIterator  = _dereq_(119).AbstractIterator
  
  function DeferredLevelDOWN (location) {
    AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '') // optional location, who cares?
    this._db         = undefined
    this._operations = []
    this._iterators  = []
  }
  
  util.inherits(DeferredLevelDOWN, AbstractLevelDOWN)
  
  // called by LevelUP when we have a real DB to take its place
  DeferredLevelDOWN.prototype.setDb = function (db) {
    this._db = db
    this._operations.forEach(function (op) {
      db[op.method].apply(db, op.args)
    })
    this._iterators.forEach(function (it) {
      it.setDb(db)
    })
  }
  
  DeferredLevelDOWN.prototype._open = function (options, callback) {
    return process.nextTick(callback)
  }
  
  // queue a new deferred operation
  DeferredLevelDOWN.prototype._operation = function (method, args) {
    if (this._db)
      return this._db[method].apply(this._db, args)
    this._operations.push({ method: method, args: args })
  }
  
  // deferrables
  'put get del batch approximateSize'.split(' ').forEach(function (m) {
    DeferredLevelDOWN.prototype['_' + m] = function () {
      this._operation(m, arguments)
    }
  })
  
  DeferredLevelDOWN.prototype._isBuffer = function (obj) {
    return Buffer.isBuffer(obj)
  }
  
  DeferredLevelDOWN.prototype._iterator = function (options) {
    var it = new Iterator(options)
    this._iterators.push(it)
    return it
  }
  
  function Iterator (options) {
    AbstractIterator.call(this, options)
  
    this._options = options
    this._iterator = null
    this._operations = []
  }
  
  util.inherits(Iterator, AbstractIterator)
  
  Iterator.prototype.setDb = function (db) {
    var it = this._iterator = db.iterator(this._options)
    this._operations.forEach(function (op) {
      it[op.method].apply(it, op.args)
    })
  }
  
  Iterator.prototype._operation = function (method, args) {
    if (this._iterator)
      return this._iterator[method].apply(this._iterator, args)
    this._operations.push({ method: method, args: args })
  }
  
  'next end'.split(' ').forEach(function (m) {
    Iterator.prototype['_' + m] = function () {
      this._operation(m, arguments)
    }
  })
  
  module.exports = DeferredLevelDOWN
  
  
  }).call(this,_dereq_(62),_dereq_(56).Buffer)
  },{"119":119,"56":56,"62":62,"79":79}],117:[function(_dereq_,module,exports){
  (function (process){
  /* Copyright (c) 2013 Rod Vagg, MIT License */
  
  function AbstractChainedBatch (db) {
    this._db         = db
    this._operations = []
    this._written    = false
  }
  
  AbstractChainedBatch.prototype._checkWritten = function () {
    if (this._written)
      throw new Error('write() already called on this batch')
  }
  
  AbstractChainedBatch.prototype.put = function (key, value) {
    this._checkWritten()
  
    var err = this._db._checkKey(key, 'key', this._db._isBuffer)
    if (err)
      throw err
  
    if (!this._db._isBuffer(key)) key = String(key)
    if (!this._db._isBuffer(value)) value = String(value)
  
    if (typeof this._put == 'function' )
      this._put(key, value)
    else
      this._operations.push({ type: 'put', key: key, value: value })
  
    return this
  }
  
  AbstractChainedBatch.prototype.del = function (key) {
    this._checkWritten()
  
    var err = this._db._checkKey(key, 'key', this._db._isBuffer)
    if (err) throw err
  
    if (!this._db._isBuffer(key)) key = String(key)
  
    if (typeof this._del == 'function' )
      this._del(key)
    else
      this._operations.push({ type: 'del', key: key })
  
    return this
  }
  
  AbstractChainedBatch.prototype.clear = function () {
    this._checkWritten()
  
    this._operations = []
  
    if (typeof this._clear == 'function' )
      this._clear()
  
    return this
  }
  
  AbstractChainedBatch.prototype.write = function (options, callback) {
    this._checkWritten()
  
    if (typeof options == 'function')
      callback = options
    if (typeof callback != 'function')
      throw new Error('write() requires a callback argument')
    if (typeof options != 'object')
      options = {}
  
    this._written = true
  
    if (typeof this._write == 'function' )
      return this._write(callback)
  
    if (typeof this._db._batch == 'function')
      return this._db._batch(this._operations, options, callback)
  
    process.nextTick(callback)
  }
  
  module.exports = AbstractChainedBatch
  }).call(this,_dereq_(62))
  },{"62":62}],118:[function(_dereq_,module,exports){
  (function (process){
  /* Copyright (c) 2013 Rod Vagg, MIT License */
  
  function AbstractIterator (db) {
    this.db = db
    this._ended = false
    this._nexting = false
  }
  
  AbstractIterator.prototype.next = function (callback) {
    var self = this
  
    if (typeof callback != 'function')
      throw new Error('next() requires a callback argument')
  
    if (self._ended)
      return callback(new Error('cannot call next() after end()'))
    if (self._nexting)
      return callback(new Error('cannot call next() before previous next() has completed'))
  
    self._nexting = true
    if (typeof self._next == 'function') {
      return self._next(function () {
        self._nexting = false
        callback.apply(null, arguments)
      })
    }
  
    process.nextTick(function () {
      self._nexting = false
      callback()
    })
  }
  
  AbstractIterator.prototype.end = function (callback) {
    if (typeof callback != 'function')
      throw new Error('end() requires a callback argument')
  
    if (this._ended)
      return callback(new Error('end() already called on iterator'))
  
    this._ended = true
  
    if (typeof this._end == 'function')
      return this._end(callback)
  
    process.nextTick(callback)
  }
  
  module.exports = AbstractIterator
  
  }).call(this,_dereq_(62))
  },{"62":62}],119:[function(_dereq_,module,exports){
  (function (process,Buffer){
  /* Copyright (c) 2013 Rod Vagg, MIT License */
  
  var xtend                = _dereq_(137)
    , AbstractIterator     = _dereq_(118)
    , AbstractChainedBatch = _dereq_(117)
  
  function AbstractLevelDOWN (location) {
    if (!arguments.length || location === undefined)
      throw new Error('constructor requires at least a location argument')
  
    if (typeof location != 'string')
      throw new Error('constructor requires a location string argument')
  
    this.location = location
  }
  
  AbstractLevelDOWN.prototype.open = function (options, callback) {
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('open() requires a callback argument')
  
    if (typeof options != 'object')
      options = {}
  
    options.createIfMissing = options.createIfMissing != false
    options.errorIfExists = !!options.errorIfExists
  
    if (typeof this._open == 'function')
      return this._open(options, callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.close = function (callback) {
    if (typeof callback != 'function')
      throw new Error('close() requires a callback argument')
  
    if (typeof this._close == 'function')
      return this._close(callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.get = function (key, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('get() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    if (typeof options != 'object')
      options = {}
  
    options.asBuffer = options.asBuffer != false
  
    if (typeof this._get == 'function')
      return this._get(key, options, callback)
  
    process.nextTick(function () { callback(new Error('NotFound')) })
  }
  
  AbstractLevelDOWN.prototype.put = function (key, value, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('put() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    // coerce value to string in node, don't touch it in browser
    // (indexeddb can store any JS type)
    if (value != null && !this._isBuffer(value) && !process.browser)
      value = String(value)
  
    if (typeof options != 'object')
      options = {}
  
    if (typeof this._put == 'function')
      return this._put(key, value, options, callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.del = function (key, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('del() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    if (typeof options != 'object')
      options = {}
  
    if (typeof this._del == 'function')
      return this._del(key, options, callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
    if (!arguments.length)
      return this._chainedBatch()
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof array == 'function')
      callback = array
  
    if (typeof callback != 'function')
      throw new Error('batch(array) requires a callback argument')
  
    if (!Array.isArray(array))
      return callback(new Error('batch(array) requires an array argument'))
  
    if (!options || typeof options != 'object')
      options = {}
  
    var i = 0
      , l = array.length
      , e
      , err
  
    for (; i < l; i++) {
      e = array[i]
      if (typeof e != 'object')
        continue
  
      if (err = this._checkKey(e.type, 'type', this._isBuffer))
        return callback(err)
  
      if (err = this._checkKey(e.key, 'key', this._isBuffer))
        return callback(err)
    }
  
    if (typeof this._batch == 'function')
      return this._batch(array, options, callback)
  
    process.nextTick(callback)
  }
  
  //TODO: remove from here, not a necessary primitive
  AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) {
    if (   start == null
        || end == null
        || typeof start == 'function'
        || typeof end == 'function') {
      throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments')
    }
  
    if (typeof callback != 'function')
      throw new Error('approximateSize() requires a callback argument')
  
    if (!this._isBuffer(start))
      start = String(start)
  
    if (!this._isBuffer(end))
      end = String(end)
  
    if (typeof this._approximateSize == 'function')
      return this._approximateSize(start, end, callback)
  
    process.nextTick(function () {
      callback(null, 0)
    })
  }
  
  AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) {
    var self = this
  
    options = xtend(options)
  
    ;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) {
      if (options[o] && self._isBuffer(options[o]) && options[o].length === 0)
        delete options[o]
    })
  
    options.reverse = !!options.reverse
    options.keys = options.keys != false
    options.values = options.values != false
    options.limit = 'limit' in options ? options.limit : -1
    options.keyAsBuffer = options.keyAsBuffer != false
    options.valueAsBuffer = options.valueAsBuffer != false
  
    return options
  }
  
  AbstractLevelDOWN.prototype.iterator = function (options) {
    if (typeof options != 'object')
      options = {}
  
    options = this._setupIteratorOptions(options)
  
    if (typeof this._iterator == 'function')
      return this._iterator(options)
  
    return new AbstractIterator(this)
  }
  
  AbstractLevelDOWN.prototype._chainedBatch = function () {
    return new AbstractChainedBatch(this)
  }
  
  AbstractLevelDOWN.prototype._isBuffer = function (obj) {
    return Buffer.isBuffer(obj)
  }
  
  AbstractLevelDOWN.prototype._checkKey = function (obj, type) {
  
    if (obj === null || obj === undefined)
      return new Error(type + ' cannot be `null` or `undefined`')
  
    if (this._isBuffer(obj)) {
      if (obj.length === 0)
        return new Error(type + ' cannot be an empty Buffer')
    } else if (String(obj) === '')
      return new Error(type + ' cannot be an empty String')
  }
  
  module.exports.AbstractLevelDOWN    = AbstractLevelDOWN
  module.exports.AbstractIterator     = AbstractIterator
  module.exports.AbstractChainedBatch = AbstractChainedBatch
  
  }).call(this,_dereq_(62),_dereq_(56).Buffer)
  },{"117":117,"118":118,"137":137,"56":56,"62":62}],120:[function(_dereq_,module,exports){
  var encodings = _dereq_(121);
  
  module.exports = Codec;
  
  function Codec(opts){
    this.opts = opts || {};
    this.encodings = encodings;
  }
  
  Codec.prototype._encoding = function(encoding){
    if (typeof encoding == 'string') encoding = encodings[encoding];
    if (!encoding) encoding = encodings.id;
    return encoding;
  };
  
  Codec.prototype._keyEncoding = function(opts, batchOpts){
    return this._encoding(batchOpts && batchOpts.keyEncoding
      || opts && opts.keyEncoding
      || this.opts.keyEncoding);
  };
  
  Codec.prototype._valueEncoding = function(opts, batchOpts){
    return this._encoding(batchOpts && batchOpts.valueEncoding
      || opts && opts.valueEncoding
      || this.opts.valueEncoding);
  };
  
  Codec.prototype.encodeKey = function(key, opts, batchOpts){
    return this._keyEncoding(opts, batchOpts).encode(key);
  };
  
  Codec.prototype.encodeValue = function(value, opts, batchOpts){
    return this._valueEncoding(opts, batchOpts).encode(value);
  };
  
  Codec.prototype.decodeKey = function(key, opts){
    return this._keyEncoding(opts).decode(key);
  };
  
  Codec.prototype.decodeValue = function(value, opts){
    return this._valueEncoding(opts).decode(value);
  };
  
  Codec.prototype.encodeBatch = function(ops, opts){
    var self = this;
  
    return ops.map(function(_op){
      var op = {
        type: _op.type,
        key: self.encodeKey(_op.key, opts, _op)
      };
      if (self.keyAsBuffer(opts, _op)) op.keyEncoding = 'binary';
      if (_op.prefix) op.prefix = _op.prefix;
      if ('value' in _op) {
        op.value = self.encodeValue(_op.value, opts, _op);
        if (self.valueAsBuffer(opts, _op)) op.valueEncoding = 'binary';
      }
      return op;
    });
  };
  
  var ltgtKeys = ['lt', 'gt', 'lte', 'gte', 'start', 'end'];
  
  Codec.prototype.encodeLtgt = function(ltgt){
    var self = this;
    var ret = {};
    Object.keys(ltgt).forEach(function(key){
      ret[key] = ltgtKeys.indexOf(key) > -1
        ? self.encodeKey(ltgt[key], ltgt)
        : ltgt[key]
    });
    return ret;
  };
  
  Codec.prototype.createStreamDecoder = function(opts){
    var self = this;
  
    if (opts.keys && opts.values) {
      return function(key, value){
        return {
          key: self.decodeKey(key, opts),
          value: self.decodeValue(value, opts)
        };
      };
    } else if (opts.keys) {
      return function(key) {
        return self.decodeKey(key, opts);
      }; 
    } else if (opts.values) {
      return function(_, value){
        return self.decodeValue(value, opts);
      }
    } else {
      return function(){};
    }
  };
  
  Codec.prototype.keyAsBuffer = function(opts){
    return this._keyEncoding(opts).buffer;
  };
  
  Codec.prototype.valueAsBuffer = function(opts){
    return this._valueEncoding(opts).buffer;
  };
  
  
  },{"121":121}],121:[function(_dereq_,module,exports){
  (function (Buffer){
  
  exports.utf8 = exports['utf-8'] = {
    encode: function(data){
      return isBinary(data)
        ? data
        : String(data);
    },
    decode: identity,
    buffer: false,
    type: 'utf8'
  };
  
  exports.json = {
    encode: JSON.stringify,
    decode: JSON.parse,
    buffer: false,
    type: 'json'
  };
  
  exports.binary = {
    encode: function(data){
      return isBinary(data)
        ? data
        : new Buffer(data);      
    },
    decode: identity,
    buffer: true,
    type: 'binary'
  };
  
  exports.id = {
    encode: function(data){
      return data;
    },
    decode: function(data){
      return data;
    },
    buffer: false,
    type: 'id'
  };
  
  var bufferEncodings = [
    'hex',
    'ascii',
    'base64',
    'ucs2',
    'ucs-2',
    'utf16le',
    'utf-16le'
  ];
  
  bufferEncodings.forEach(function(type){
    exports[type] = {
      encode: function(data){
        return isBinary(data)
          ? data
          : new Buffer(data, type);
      },
      decode: function(buffer){
        return buffer.toString(type);
      },
      buffer: true,
      type: type
    };
  });
  
  function identity(value){
    return value;
  }
  
  function isBinary(data){
    return data === undefined
      || data === null
      || Buffer.isBuffer(data);
  }
  
  
  }).call(this,_dereq_(56).Buffer)
  },{"56":56}],122:[function(_dereq_,module,exports){
  /* Copyright (c) 2012-2015 LevelUP contributors
   * See list at <https://github.com/rvagg/node-levelup#contributing>
   * MIT License
   * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md>
   */
  
  var createError   = _dereq_(124).create
    , LevelUPError  = createError('LevelUPError')
    , NotFoundError = createError('NotFoundError', LevelUPError)
  
  NotFoundError.prototype.notFound = true
  NotFoundError.prototype.status   = 404
  
  module.exports = {
      LevelUPError        : LevelUPError
    , InitializationError : createError('InitializationError', LevelUPError)
    , OpenError           : createError('OpenError', LevelUPError)
    , ReadError           : createError('ReadError', LevelUPError)
    , WriteError          : createError('WriteError', LevelUPError)
    , NotFoundError       : NotFoundError
    , EncodingError       : createError('EncodingError', LevelUPError)
  }
  
  },{"124":124}],123:[function(_dereq_,module,exports){
  arguments[4][93][0].apply(exports,arguments)
  },{"125":125,"93":93}],124:[function(_dereq_,module,exports){
  arguments[4][94][0].apply(exports,arguments)
  },{"123":123,"94":94}],125:[function(_dereq_,module,exports){
  arguments[4][95][0].apply(exports,arguments)
  },{"95":95}],126:[function(_dereq_,module,exports){
  var inherits = _dereq_(84);
  var Readable = _dereq_(135).Readable;
  var extend = _dereq_(137);
  var EncodingError = _dereq_(122).EncodingError;
  
  module.exports = ReadStream;
  inherits(ReadStream, Readable);
  
  function ReadStream(iterator, options){
    if (!(this instanceof ReadStream)) return new ReadStream(iterator, options);
    Readable.call(this, extend(options, {
      objectMode: true
    }));
    this._iterator = iterator;
    this._destroyed = false;
    this._decoder = null;
    if (options && options.decoder) this._decoder = options.decoder;
    this.on('end', this._cleanup.bind(this));
  }
  
  ReadStream.prototype._read = function(){
    var self = this;
    if (this._destroyed) return;
  
    this._iterator.next(function(err, key, value){
      if (self._destroyed) return;
      if (err) return self.emit('error', err);
      if (key === undefined && value === undefined) {
        self.push(null);
      } else {
        if (!self._decoder) return self.push({ key: key, value: value });
  
        try {
          var value = self._decoder(key, value);
        } catch (err) {
          self.emit('error', new EncodingError(err));
          self.push(null);
          return;
        }
        self.push(value);
      }
    });
  };
  
  ReadStream.prototype.destroy =
  ReadStream.prototype._cleanup = function(){
    var self = this;
    if (this._destroyed) return;
    this._destroyed = true;
  
    this._iterator.end(function(err){
      if (err) return self.emit('error', err);
      self.emit('close');
    });
  };
  
  
  },{"122":122,"135":135,"137":137,"84":84}],127:[function(_dereq_,module,exports){
  arguments[4][96][0].apply(exports,arguments)
  },{"129":129,"131":131,"132":132,"62":62,"84":84,"96":96}],128:[function(_dereq_,module,exports){
  arguments[4][97][0].apply(exports,arguments)
  },{"130":130,"132":132,"84":84,"97":97}],129:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  module.exports = Readable;
  
  /*<replacement>*/
  var isArray = _dereq_(133);
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = _dereq_(60).EventEmitter;
  
  /*<replacement>*/
  if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  var Stream = _dereq_(76);
  
  /*<replacement>*/
  var util = _dereq_(132);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var StringDecoder;
  
  
  /*<replacement>*/
  var debug = _dereq_(55);
  if (debug && debug.debuglog) {
    debug = debug.debuglog('stream');
  } else {
    debug = function () {};
  }
  /*</replacement>*/
  
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    var Duplex = _dereq_(127);
  
    options = options || {};
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    var defaultHwm = options.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = null;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.readableObjectMode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = _dereq_(134).StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    var Duplex = _dereq_(127);
  
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (util.isString(chunk) && !state.objectMode) {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (util.isNullOrUndefined(chunk)) {
      state.reading = false;
      if (!state.ended)
        onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        if (!addToFront)
          state.reading = false;
  
        // if we want the data now, just emit it.
        if (state.flowing && state.length === 0 && !state.sync) {
          stream.emit('data', chunk);
          stream.read(0);
        } else {
          // update the buffer info.
          state.length += state.objectMode ? 1 : chunk.length;
          if (addToFront)
            state.buffer.unshift(chunk);
          else
            state.buffer.push(chunk);
  
          if (state.needReadable)
            emitReadable(stream);
        }
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = _dereq_(134).StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
    return this;
  };
  
  // Don't raise the hwm > 128MB
  var MAX_HWM = 0x800000;
  function roundUpToNextPowerOf2(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      for (var p = 1; p < 32; p <<= 1) n |= n >> p;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (isNaN(n) || util.isNull(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = roundUpToNextPowerOf2(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else
        return state.length;
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    debug('read', n);
    var state = this._readableState;
    var nOrig = n;
  
    if (!util.isNumber(n) || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      debug('read: emitReadable', state.length, state.ended);
      if (state.length === 0 && state.ended)
        endReadable(this);
      else
        emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      if (state.length === 0)
        endReadable(this);
      return null;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
    debug('need readable', doRead);
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length === 0 || state.length - n < state.highWaterMark) {
      doRead = true;
      debug('length less than watermark', doRead);
    }
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading) {
      doRead = false;
      debug('reading or ended', doRead);
    }
  
    if (doRead) {
      debug('do read');
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read pushed data synchronously, then `reading` will be false,
    // and we need to re-evaluate how much data we can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    var ret;
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (util.isNull(ret)) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we tried to read() past the EOF, then emit end on the next tick.
    if (nOrig !== n && state.ended && state.length === 0)
      endReadable(this);
  
    if (!util.isNull(ret))
      this.emit('data', ret);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!util.isBuffer(chunk) &&
        !util.isString(chunk) &&
        !util.isNullOrUndefined(chunk) &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.decoder && !state.ended) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // emit 'readable' now to make sure it gets picked up.
    emitReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (!state.emittedReadable) {
      debug('emitReadable', state.flowing);
      state.emittedReadable = true;
      if (state.sync)
        process.nextTick(function() {
          emitReadable_(stream);
        });
      else
        emitReadable_(stream);
    }
  }
  
  function emitReadable_(stream) {
    debug('emit readable');
    stream.emit('readable');
    flow(stream);
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      process.nextTick(function() {
        maybeReadMore_(stream, state);
      });
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      debug('maybeReadMore read 0');
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
    debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      process.nextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      debug('onunpipe');
      if (readable === src) {
        cleanup();
      }
    }
  
    function onend() {
      debug('onend');
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    function cleanup() {
      debug('cleanup');
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
      src.removeListener('data', ondata);
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (state.awaitDrain &&
          (!dest._writableState || dest._writableState.needDrain))
        ondrain();
    }
  
    src.on('data', ondata);
    function ondata(chunk) {
      debug('ondata');
      var ret = dest.write(chunk);
      if (false === ret) {
        debug('false write response, pause',
              src._readableState.awaitDrain);
        src._readableState.awaitDrain++;
        src.pause();
      }
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      debug('onerror', er);
      unpipe();
      dest.removeListener('error', onerror);
      if (EE.listenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      debug('onfinish');
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      debug('unpipe');
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      debug('pipe resume');
      src.resume();
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var state = src._readableState;
      debug('pipeOnDrain', state.awaitDrain);
      if (state.awaitDrain)
        state.awaitDrain--;
      if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
        state.flowing = true;
        flow(src);
      }
    };
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    // If listening to data, and it has not explicitly been paused,
    // then call resume to start the flow of data on the next tick.
    if (ev === 'data' && false !== this._readableState.flowing) {
      this.resume();
    }
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          var self = this;
          process.nextTick(function() {
            debug('readable nexttick read 0');
            self.read(0);
          });
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    var state = this._readableState;
    if (!state.flowing) {
      debug('resume');
      state.flowing = true;
      if (!state.reading) {
        debug('resume read 0');
        this.read(0);
      }
      resume(this, state);
    }
    return this;
  };
  
  function resume(stream, state) {
    if (!state.resumeScheduled) {
      state.resumeScheduled = true;
      process.nextTick(function() {
        resume_(stream, state);
      });
    }
  }
  
  function resume_(stream, state) {
    state.resumeScheduled = false;
    stream.emit('resume');
    flow(stream);
    if (state.flowing && !state.reading)
      stream.read(0);
  }
  
  Readable.prototype.pause = function() {
    debug('call pause flowing=%j', this._readableState.flowing);
    if (false !== this._readableState.flowing) {
      debug('pause');
      this._readableState.flowing = false;
      this.emit('pause');
    }
    return this;
  };
  
  function flow(stream) {
    var state = stream._readableState;
    debug('flow', state.flowing);
    if (state.flowing) {
      do {
        var chunk = stream.read();
      } while (null !== chunk && state.flowing);
    }
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      debug('wrapped end');
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      debug('wrapped data');
      if (state.decoder)
        chunk = state.decoder.write(chunk);
      if (!chunk || !state.objectMode && !chunk.length)
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (util.isFunction(stream[i]) && util.isUndefined(this[i])) {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }}(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      debug('wrapped _read', n);
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted) {
      state.ended = true;
      process.nextTick(function() {
        // Check that we didn't get one last unshift.
        if (!state.endEmitted && state.length === 0) {
          state.endEmitted = true;
          stream.readable = false;
          stream.emit('end');
        }
      });
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,_dereq_(62))
  },{"127":127,"132":132,"133":133,"134":134,"55":55,"56":56,"60":60,"62":62,"76":76,"84":84}],130:[function(_dereq_,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  module.exports = Transform;
  
  var Duplex = _dereq_(127);
  
  /*<replacement>*/
  var util = _dereq_(132);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(options, stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (!util.isNullOrUndefined(data))
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    this._transformState = new TransformState(options, this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    this.once('prefinish', function() {
      if (util.isFunction(this._flush))
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"127":127,"132":132,"84":84}],131:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, cb), and it'll handle all
  // the drain event emission and buffering.
  
  module.exports = Writable;
  
  /*<replacement>*/
  var Buffer = _dereq_(56).Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = _dereq_(132);
  util.inherits = _dereq_(84);
  /*</replacement>*/
  
  var Stream = _dereq_(76);
  
  util.inherits(Writable, Stream);
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
  }
  
  function WritableState(options, stream) {
    var Duplex = _dereq_(127);
  
    options = options || {};
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    var defaultHwm = options.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.writableObjectMode;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // when true all writes will be buffered until .uncork() call
    this.corked = 0;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.buffer = [];
  
    // number of pending user-supplied write callbacks
    // this must be 0 before 'finish' can be emitted
    this.pendingcb = 0;
  
    // emit prefinish if the only thing we're waiting for is _write cbs
    // This is relevant for synchronous Transform streams
    this.prefinished = false;
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  function Writable(options) {
    var Duplex = _dereq_(127);
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, state, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    process.nextTick(function() {
      cb(er);
    });
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
    if (!util.isBuffer(chunk) &&
        !util.isString(chunk) &&
        !util.isNullOrUndefined(chunk) &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      process.nextTick(function() {
        cb(er);
      });
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (util.isFunction(encoding)) {
      cb = encoding;
      encoding = null;
    }
  
    if (util.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (!util.isFunction(cb))
      cb = function() {};
  
    if (state.ended)
      writeAfterEnd(this, state, cb);
    else if (validChunk(this, state, chunk, cb)) {
      state.pendingcb++;
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
    }
  
    return ret;
  };
  
  Writable.prototype.cork = function() {
    var state = this._writableState;
  
    state.corked++;
  };
  
  Writable.prototype.uncork = function() {
    var state = this._writableState;
  
    if (state.corked) {
      state.corked--;
  
      if (!state.writing &&
          !state.corked &&
          !state.finished &&
          !state.bufferProcessing &&
          state.buffer.length)
        clearBuffer(this, state);
    }
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        util.isString(chunk)) {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
    if (util.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing || state.corked)
      state.buffer.push(new WriteReq(chunk, encoding, cb));
    else
      doWrite(stream, state, false, len, chunk, encoding, cb);
  
    return ret;
  }
  
  function doWrite(stream, state, writev, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    if (writev)
      stream._writev(chunk, state.onwrite);
    else
      stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    if (sync)
      process.nextTick(function() {
        state.pendingcb--;
        cb(er);
      });
    else {
      state.pendingcb--;
      cb(er);
    }
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(stream, state);
  
      if (!finished &&
          !state.corked &&
          !state.bufferProcessing &&
          state.buffer.length) {
        clearBuffer(stream, state);
      }
  
      if (sync) {
        process.nextTick(function() {
          afterWrite(stream, state, finished, cb);
        });
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    state.pendingcb--;
    cb();
    finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
  
    if (stream._writev && state.buffer.length > 1) {
      // Fast case, write everything using _writev()
      var cbs = [];
      for (var c = 0; c < state.buffer.length; c++)
        cbs.push(state.buffer[c].callback);
  
      // count the one we are adding, as well.
      // TODO(isaacs) clean this up
      state.pendingcb++;
      doWrite(stream, state, true, state.length, state.buffer, '', function(err) {
        for (var i = 0; i < cbs.length; i++) {
          state.pendingcb--;
          cbs[i](err);
        }
      });
  
      // Clear buffer
      state.buffer = [];
    } else {
      // Slow case, write chunks one-by-one
      for (var c = 0; c < state.buffer.length; c++) {
        var entry = state.buffer[c];
        var chunk = entry.chunk;
        var encoding = entry.encoding;
        var cb = entry.callback;
        var len = state.objectMode ? 1 : chunk.length;
  
        doWrite(stream, state, false, len, chunk, encoding, cb);
  
        // if we didn't call the onwrite immediately, then
        // it means that we need to wait until it does.
        // also, that means that the chunk and cb are currently
        // being processed, so move the buffer counter past them.
        if (state.writing) {
          c++;
          break;
        }
      }
  
      if (c < state.buffer.length)
        state.buffer = state.buffer.slice(c);
      else
        state.buffer.length = 0;
    }
  
    state.bufferProcessing = false;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  
  };
  
  Writable.prototype._writev = null;
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (util.isFunction(chunk)) {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (util.isFunction(encoding)) {
      cb = encoding;
      encoding = null;
    }
  
    if (!util.isNullOrUndefined(chunk))
      this.write(chunk, encoding);
  
    // .end() fully uncorks
    if (state.corked) {
      state.corked = 1;
      this.uncork();
    }
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(stream, state) {
    return (state.ending &&
            state.length === 0 &&
            !state.finished &&
            !state.writing);
  }
  
  function prefinish(stream, state) {
    if (!state.prefinished) {
      state.prefinished = true;
      stream.emit('prefinish');
    }
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(stream, state);
    if (need) {
      if (state.pendingcb === 0) {
        prefinish(stream, state);
        state.finished = true;
        stream.emit('finish');
      } else
        prefinish(stream, state);
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        process.nextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  }).call(this,_dereq_(62))
  },{"127":127,"132":132,"56":56,"62":62,"76":76,"84":84}],132:[function(_dereq_,module,exports){
  arguments[4][69][0].apply(exports,arguments)
  },{"56":56,"69":69}],133:[function(_dereq_,module,exports){
  arguments[4][61][0].apply(exports,arguments)
  },{"61":61}],134:[function(_dereq_,module,exports){
  arguments[4][77][0].apply(exports,arguments)
  },{"56":56,"77":77}],135:[function(_dereq_,module,exports){
  exports = module.exports = _dereq_(129);
  exports.Stream = _dereq_(76);
  exports.Readable = exports;
  exports.Writable = _dereq_(131);
  exports.Duplex = _dereq_(127);
  exports.Transform = _dereq_(130);
  exports.PassThrough = _dereq_(128);
  
  },{"127":127,"128":128,"129":129,"130":130,"131":131,"76":76}],136:[function(_dereq_,module,exports){
  arguments[4][95][0].apply(exports,arguments)
  },{"95":95}],137:[function(_dereq_,module,exports){
  arguments[4][105][0].apply(exports,arguments)
  },{"105":105}],138:[function(_dereq_,module,exports){
  module.exports={
    "name": "levelup",
    "description": "Fast & simple storage - a Node.js-style LevelDB wrapper",
    "version": "1.2.1",
    "contributors": [
      {
        "name": "Rod Vagg",
        "email": "r@va.gg",
        "url": "https://github.com/rvagg"
      },
      {
        "name": "John Chesley",
        "email": "john@chesl.es",
        "url": "https://github.com/chesles/"
      },
      {
        "name": "Jake Verbaten",
        "email": "raynos2@gmail.com",
        "url": "https://github.com/raynos"
      },
      {
        "name": "Dominic Tarr",
        "email": "dominic.tarr@gmail.com",
        "url": "https://github.com/dominictarr"
      },
      {
        "name": "Max Ogden",
        "email": "max@maxogden.com",
        "url": "https://github.com/maxogden"
      },
      {
        "name": "Lars-Magnus Skog",
        "email": "ralphtheninja@riseup.net",
        "url": "https://github.com/ralphtheninja"
      },
      {
        "name": "David Björklund",
        "email": "david.bjorklund@gmail.com",
        "url": "https://github.com/kesla"
      },
      {
        "name": "Julian Gruber",
        "email": "julian@juliangruber.com",
        "url": "https://github.com/juliangruber"
      },
      {
        "name": "Paolo Fragomeni",
        "email": "paolo@async.ly",
        "url": "https://github.com/hij1nx"
      },
      {
        "name": "Anton Whalley",
        "email": "anton.whalley@nearform.com",
        "url": "https://github.com/No9"
      },
      {
        "name": "Matteo Collina",
        "email": "matteo.collina@gmail.com",
        "url": "https://github.com/mcollina"
      },
      {
        "name": "Pedro Teixeira",
        "email": "pedro.teixeira@gmail.com",
        "url": "https://github.com/pgte"
      },
      {
        "name": "James Halliday",
        "email": "mail@substack.net",
        "url": "https://github.com/substack"
      },
      {
        "name": "Jarrett Cruger",
        "email": "jcrugzz@gmail.com",
        "url": "https://github.com/jcrugzz"
      }
    ],
    "repository": {
      "type": "git",
      "url": "git+https://github.com/level/levelup.git"
    },
    "homepage": "https://github.com/level/levelup",
    "keywords": [
      "leveldb",
      "stream",
      "database",
      "db",
      "store",
      "storage",
      "json"
    ],
    "main": "lib/levelup.js",
    "dependencies": {
      "deferred-leveldown": "~1.0.0",
      "level-codec": "~6.0.0",
      "level-errors": "~1.0.3",
      "level-iterator-stream": "~1.3.0",
      "prr": "~1.0.1",
      "semver": "~4.3.3",
      "xtend": "~4.0.0"
    },
    "devDependencies": {
      "async": "~0.9.0",
      "bustermove": "~1.0.0",
      "delayed": "~1.0.1",
      "faucet": "~0.0.1",
      "leveldown": "^1.1.0",
      "memdown": "~1.0.0",
      "msgpack-js": "~0.3.0",
      "referee": "~1.1.1",
      "rimraf": "~2.3.2",
      "slow-stream": "0.0.4",
      "tape": "~4.0.0"
    },
    "browser": {
      "leveldown": false,
      "leveldown/package": false,
      "semver": false
    },
    "scripts": {
      "test": "tape test/*-test.js | faucet"
    },
    "license": "MIT",
    "gitHead": "8f442f77baea1cdb1b7af844e3374380c2bb015f",
    "bugs": {
      "url": "https://github.com/level/levelup/issues"
    },
    "_id": "levelup@1.2.1",
    "_shasum": "13b537deb4a7536c3aa6fbe008a1af4a0350dbd5",
    "_from": "levelup@>=1.2.1 <2.0.0",
    "_npmVersion": "2.11.0",
    "_nodeVersion": "2.2.1",
    "_npmUser": {
      "name": "ralphtheninja",
      "email": "ralphtheninja@riseup.net"
    },
    "maintainers": [
      {
        "name": "rvagg",
        "email": "rod@vagg.org"
      },
      {
        "name": "ralphtheninja",
        "email": "ralphtheninja@riseup.net"
      },
      {
        "name": "juliangruber",
        "email": "julian@juliangruber.com"
      }
    ],
    "dist": {
      "shasum": "13b537deb4a7536c3aa6fbe008a1af4a0350dbd5",
      "tarball": "http://registry.npmjs.org/levelup/-/levelup-1.2.1.tgz"
    },
    "directories": {},
    "_resolved": "https://registry.npmjs.org/levelup/-/levelup-1.2.1.tgz",
    "readme": "ERROR: No README data found!"
  }
  
  },{}],139:[function(_dereq_,module,exports){
  'use strict';
  var immediate = _dereq_(140);
  
  /* istanbul ignore next */
  function INTERNAL() {}
  
  var handlers = {};
  
  var REJECTED = ['REJECTED'];
  var FULFILLED = ['FULFILLED'];
  var PENDING = ['PENDING'];
  var UNHANDLED;
  
  module.exports = exports = Promise;
  
  function Promise(resolver) {
    if (typeof resolver !== 'function') {
      throw new TypeError('resolver must be a function');
    }
    this.state = PENDING;
    this.queue = [];
    this.outcome = void 0;
    if (resolver !== INTERNAL) {
      safelyResolveThenable(this, resolver);
    }
  }
  
  Promise.prototype["catch"] = function (onRejected) {
    return this.then(null, onRejected);
  };
  Promise.prototype.then = function (onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
      typeof onRejected !== 'function' && this.state === REJECTED) {
      return this;
    }
    var promise = new this.constructor(INTERNAL);
    if (this.state !== PENDING) {
      var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
      unwrap(promise, resolver, this.outcome);
    } else {
      this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
    }
  
    return promise;
  };
  function QueueItem(promise, onFulfilled, onRejected) {
    this.promise = promise;
    if (typeof onFulfilled === 'function') {
      this.onFulfilled = onFulfilled;
      this.callFulfilled = this.otherCallFulfilled;
    }
    if (typeof onRejected === 'function') {
      this.onRejected = onRejected;
      this.callRejected = this.otherCallRejected;
    }
  }
  QueueItem.prototype.callFulfilled = function (value) {
    handlers.resolve(this.promise, value);
  };
  QueueItem.prototype.otherCallFulfilled = function (value) {
    unwrap(this.promise, this.onFulfilled, value);
  };
  QueueItem.prototype.callRejected = function (value) {
    handlers.reject(this.promise, value);
  };
  QueueItem.prototype.otherCallRejected = function (value) {
    unwrap(this.promise, this.onRejected, value);
  };
  
  function unwrap(promise, func, value) {
    immediate(function () {
      var returnValue;
      try {
        returnValue = func(value);
      } catch (e) {
        return handlers.reject(promise, e);
      }
      if (returnValue === promise) {
        handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
      } else {
        handlers.resolve(promise, returnValue);
      }
    });
  }
  
  handlers.resolve = function (self, value) {
    var result = tryCatch(getThen, value);
    if (result.status === 'error') {
      return handlers.reject(self, result.value);
    }
    var thenable = result.value;
  
    if (thenable) {
      safelyResolveThenable(self, thenable);
    } else {
      self.state = FULFILLED;
      self.outcome = value;
      var i = -1;
      var len = self.queue.length;
      while (++i < len) {
        self.queue[i].callFulfilled(value);
      }
    }
    return self;
  };
  handlers.reject = function (self, error) {
    self.state = REJECTED;
    self.outcome = error;
    var i = -1;
    var len = self.queue.length;
    while (++i < len) {
      self.queue[i].callRejected(error);
    }
    return self;
  };
  
  function getThen(obj) {
    // Make sure we only access the accessor once as required by the spec
    var then = obj && obj.then;
    if (obj && typeof obj === 'object' && typeof then === 'function') {
      return function appyThen() {
        then.apply(obj, arguments);
      };
    }
  }
  
  function safelyResolveThenable(self, thenable) {
    // Either fulfill, reject or reject with error
    var called = false;
    function onError(value) {
      if (called) {
        return;
      }
      called = true;
      handlers.reject(self, value);
    }
  
    function onSuccess(value) {
      if (called) {
        return;
      }
      called = true;
      handlers.resolve(self, value);
    }
  
    function tryToUnwrap() {
      thenable(onSuccess, onError);
    }
  
    var result = tryCatch(tryToUnwrap);
    if (result.status === 'error') {
      onError(result.value);
    }
  }
  
  function tryCatch(func, value) {
    var out = {};
    try {
      out.value = func(value);
      out.status = 'success';
    } catch (e) {
      out.status = 'error';
      out.value = e;
    }
    return out;
  }
  
  exports.resolve = resolve;
  function resolve(value) {
    if (value instanceof this) {
      return value;
    }
    return handlers.resolve(new this(INTERNAL), value);
  }
  
  exports.reject = reject;
  function reject(reason) {
    var promise = new this(INTERNAL);
    return handlers.reject(promise, reason);
  }
  
  exports.all = all;
  function all(iterable) {
    var self = this;
    if (Object.prototype.toString.call(iterable) !== '[object Array]') {
      return this.reject(new TypeError('must be an array'));
    }
  
    var len = iterable.length;
    var called = false;
    if (!len) {
      return this.resolve([]);
    }
  
    var values = new Array(len);
    var resolved = 0;
    var i = -1;
    var promise = new this(INTERNAL);
  
    while (++i < len) {
      allResolver(iterable[i], i);
    }
    return promise;
    function allResolver(value, i) {
      self.resolve(value).then(resolveFromAll, function (error) {
        if (!called) {
          called = true;
          handlers.reject(promise, error);
        }
      });
      function resolveFromAll(outValue) {
        values[i] = outValue;
        if (++resolved === len && !called) {
          called = true;
          handlers.resolve(promise, values);
        }
      }
    }
  }
  
  exports.race = race;
  function race(iterable) {
    var self = this;
    if (Object.prototype.toString.call(iterable) !== '[object Array]') {
      return this.reject(new TypeError('must be an array'));
    }
  
    var len = iterable.length;
    var called = false;
    if (!len) {
      return this.resolve([]);
    }
  
    var i = -1;
    var promise = new this(INTERNAL);
  
    while (++i < len) {
      resolver(iterable[i]);
    }
    return promise;
    function resolver(value) {
      self.resolve(value).then(function (response) {
        if (!called) {
          called = true;
          handlers.resolve(promise, response);
        }
      }, function (error) {
        if (!called) {
          called = true;
          handlers.reject(promise, error);
        }
      });
    }
  }
  
  },{"140":140}],140:[function(_dereq_,module,exports){
  (function (global){
  'use strict';
  var Mutation = global.MutationObserver || global.WebKitMutationObserver;
  
  var scheduleDrain;
  
  {
    if (Mutation) {
      var called = 0;
      var observer = new Mutation(nextTick);
      var element = global.document.createTextNode('');
      observer.observe(element, {
        characterData: true
      });
      scheduleDrain = function () {
        element.data = (called = ++called % 2);
      };
    } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
      var channel = new global.MessageChannel();
      channel.port1.onmessage = nextTick;
      scheduleDrain = function () {
        channel.port2.postMessage(0);
      };
    } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
      scheduleDrain = function () {
  
        // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
        // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
        var scriptEl = global.document.createElement('script');
        scriptEl.onreadystatechange = function () {
          nextTick();
  
          scriptEl.onreadystatechange = null;
          scriptEl.parentNode.removeChild(scriptEl);
          scriptEl = null;
        };
        global.document.documentElement.appendChild(scriptEl);
      };
    } else {
      scheduleDrain = function () {
        setTimeout(nextTick, 0);
      };
    }
  }
  
  var draining;
  var queue = [];
  //named nextTick for less confusing stack traces
  function nextTick() {
    draining = true;
    var i, oldQueue;
    var len = queue.length;
    while (len) {
      oldQueue = queue;
      queue = [];
      i = -1;
      while (++i < len) {
        oldQueue[i]();
      }
      len = queue.length;
    }
    draining = false;
  }
  
  module.exports = immediate;
  function immediate(task) {
    if (queue.push(task) === 1 && !draining) {
      scheduleDrain();
    }
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],141:[function(_dereq_,module,exports){
  (function (process,global,Buffer){
  var inherits          = _dereq_(84)
    , AbstractLevelDOWN = _dereq_(145).AbstractLevelDOWN
    , AbstractIterator  = _dereq_(145).AbstractIterator
    , ltgt              = _dereq_(149)
    , setImmediate      = global.setImmediate || process.nextTick
    , createRBT = _dereq_(148)
    , globalStore       = {}
  
  function toKey (key) {
    return typeof key == 'string' ? '$' + key : JSON.stringify(key)
  }
  
  function gt(value) {
    return value > this._end
  }
  
  function gte(value) {
    return value >= this._end
  }
  
  function lt(value) {
    return value < this._end
  }
  
  function lte(value) {
    return value <= this._end
  }
  
  
  function MemIterator (db, options) {
    AbstractIterator.call(this, db)
    this._limit   = options.limit
  
    if (this._limit === -1)
      this._limit = Infinity
  
    var tree = db._store[db._location];
  
    this.keyAsBuffer = options.keyAsBuffer !== false
    this.valueAsBuffer = options.valueAsBuffer !== false
    this._reverse   = options.reverse
    this._options = options
    this._done = 0
    
    if (!this._reverse) {
      this._incr = 'next';
      this._start = ltgt.lowerBound(options);
      this._end = ltgt.upperBound(options)
      
      if (typeof this._start === 'undefined')
        this._tree = tree.begin;
      else if (ltgt.lowerBoundInclusive(options))
        this._tree = tree.ge(this._start);
      else
        this._tree = tree.gt(this._start);
      
      if (this._end) {
        if (ltgt.upperBoundInclusive(options))
          this._test = lte
        else
          this._test = lt
      }
    
    } else {
      this._incr = 'prev';
      this._start = ltgt.upperBound(options)
      this._end = ltgt.lowerBound(options)
    
      if (typeof this._start === 'undefined')
        this._tree = tree.end;
      else if (ltgt.upperBoundInclusive(options))
        this._tree = tree.le(this._start)
      else
        this._tree = tree.lt(this._start)
    
      if (this._end) {
        if (ltgt.lowerBoundInclusive(options))
          this._test = gte
        else
          this._test = gt
      }
  
    }
  
  }
  
  inherits(MemIterator, AbstractIterator)
  
  MemIterator.prototype._next = function (callback) {
    var key
      , value
  
    if (this._done++ >= this._limit)
      return setImmediate(callback)
  
    if (!this._tree.valid)
      return setImmediate(callback)
  
    key = this._tree.key
    value = this._tree.value
  
    if (!this._test(key))
      return setImmediate(callback)
  
    if (this.keyAsBuffer)
      key = new Buffer(key)
  
    if (this.valueAsBuffer)
      value = new Buffer(value)
  
    this._tree[this._incr]()
  
    setImmediate(function callNext() {
      callback(null, key, value)
    })
  }
  
  MemIterator.prototype._test = function () {return true}
  
  function MemDOWN (location) {
    if (!(this instanceof MemDOWN))
      return new MemDOWN(location)
  
    AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '')
  
    this._location = this.location ? toKey(this.location) : '_tree'
    this._store = this.location ? globalStore: this
    this._store[this._location] = this._store[this._location] || createRBT()
  }
  
  inherits(MemDOWN, AbstractLevelDOWN)
  
  MemDOWN.prototype._open = function (options, callback) {
    var self = this
    setImmediate(function callNext() { callback(null, self) })
  }
  
  MemDOWN.prototype._put = function (key, value, options, callback) {
    this._store[this._location] = this._store[this._location].remove(key).insert(key, value)
    setImmediate(callback)
  }
  
  MemDOWN.prototype._get = function (key, options, callback) {
    var value = this._store[this._location].get(key)
  
    if (value === undefined) {
      // 'NotFound' error, consistent with LevelDOWN API
      var err = new Error('NotFound')
      return setImmediate(function callNext() { callback(err) })
    }
  
    if (options.asBuffer !== false && !this._isBuffer(value))
      value = new Buffer(String(value))
    
    setImmediate(function callNext () {
      callback(null, value)
    })
  
  }
  
  MemDOWN.prototype._del = function (key, options, callback) {
    this._store[this._location] = this._store[this._location].remove(key)
    setImmediate(callback)
  }
  
  MemDOWN.prototype._batch = function (array, options, callback) {
    var err
      , i = -1
      , key
      , value
      , len = array.length
      , tree = this._store[this._location]
  
    while (++i < len) {
      if (!array[i])
        continue;
      
      key = this._isBuffer(array[i].key) ? array[i].key : String(array[i].key)
      err = this._checkKey(key, 'key')
      if (err)
        return setImmediate(function errorCall() { callback(err) })
      
      tree = tree.remove(array[i].key)
      // we always remove as insert doesn't replace
  
      if (array[i].type === 'put') {
  
        value = this._isBuffer(array[i].value) ? array[i].value : String(array[i].value)
        err = this._checkKey(value, 'value')
  
        if (err)
          return setImmediate(function errorCall() { callback(err) })
  
        tree = tree.insert(key, value)
      }
    
    }
    
    this._store[this._location] = tree;
  
    setImmediate(callback)
  }
  
  MemDOWN.prototype._iterator = function (options) {
    return new MemIterator(this, options)
  }
  
  MemDOWN.prototype._isBuffer = function (obj) {
    return Buffer.isBuffer(obj)
  }
  
  MemDOWN.destroy = function (name, callback) {
    var key = toKey(name)
  
    if (key in globalStore)
      delete globalStore[key]
  
    setImmediate(callback)
  }
  
  module.exports = MemDOWN
  
  }).call(this,_dereq_(62),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},_dereq_(56).Buffer)
  },{"145":145,"148":148,"149":149,"56":56,"62":62,"84":84}],142:[function(_dereq_,module,exports){
  arguments[4][117][0].apply(exports,arguments)
  },{"117":117,"62":62}],143:[function(_dereq_,module,exports){
  arguments[4][118][0].apply(exports,arguments)
  },{"118":118,"62":62}],144:[function(_dereq_,module,exports){
  (function (process,Buffer){
  /* Copyright (c) 2013 Rod Vagg, MIT License */
  
  var xtend                = _dereq_(147)
    , AbstractIterator     = _dereq_(143)
    , AbstractChainedBatch = _dereq_(142)
  
  function AbstractLevelDOWN (location) {
    if (!arguments.length || location === undefined)
      throw new Error('constructor requires at least a location argument')
  
    if (typeof location != 'string')
      throw new Error('constructor requires a location string argument')
  
    this.location = location
    this.status = 'new'
  }
  
  AbstractLevelDOWN.prototype.open = function (options, callback) {
    var self      = this
      , oldStatus = this.status
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('open() requires a callback argument')
  
    if (typeof options != 'object')
      options = {}
  
    options.createIfMissing = options.createIfMissing != false
    options.errorIfExists = !!options.errorIfExists
  
    if (typeof this._open == 'function') {
      this.status = 'opening'
      this._open(options, function (err) {
        if (err) {
          self.status = oldStatus
          return callback(err)
        }
        self.status = 'open'
        callback()
      })
    } else {
      this.status = 'open'
      process.nextTick(callback)
    }
  }
  
  AbstractLevelDOWN.prototype.close = function (callback) {
    var self      = this
      , oldStatus = this.status
  
    if (typeof callback != 'function')
      throw new Error('close() requires a callback argument')
  
    if (typeof this._close == 'function') {
      this.status = 'closing'
      this._close(function (err) {
        if (err) {
          self.status = oldStatus
          return callback(err)
        }
        self.status = 'closed'
        callback()
      })
    } else {
      this.status = 'closed'
      process.nextTick(callback)
    }
  }
  
  AbstractLevelDOWN.prototype.get = function (key, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('get() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    if (typeof options != 'object')
      options = {}
  
    options.asBuffer = options.asBuffer != false
  
    if (typeof this._get == 'function')
      return this._get(key, options, callback)
  
    process.nextTick(function () { callback(new Error('NotFound')) })
  }
  
  AbstractLevelDOWN.prototype.put = function (key, value, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('put() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    // coerce value to string in node, don't touch it in browser
    // (indexeddb can store any JS type)
    if (value != null && !this._isBuffer(value) && !process.browser)
      value = String(value)
  
    if (typeof options != 'object')
      options = {}
  
    if (typeof this._put == 'function')
      return this._put(key, value, options, callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.del = function (key, options, callback) {
    var err
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof callback != 'function')
      throw new Error('del() requires a callback argument')
  
    if (err = this._checkKey(key, 'key', this._isBuffer))
      return callback(err)
  
    if (!this._isBuffer(key))
      key = String(key)
  
    if (typeof options != 'object')
      options = {}
  
    if (typeof this._del == 'function')
      return this._del(key, options, callback)
  
    process.nextTick(callback)
  }
  
  AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
    if (!arguments.length)
      return this._chainedBatch()
  
    if (typeof options == 'function')
      callback = options
  
    if (typeof array == 'function')
      callback = array
  
    if (typeof callback != 'function')
      throw new Error('batch(array) requires a callback argument')
  
    if (!Array.isArray(array))
      return callback(new Error('batch(array) requires an array argument'))
  
    if (!options || typeof options != 'object')
      options = {}
  
    var i = 0
      , l = array.length
      , e
      , err
  
    for (; i < l; i++) {
      e = array[i]
      if (typeof e != 'object')
        continue
  
      if (err = this._checkKey(e.type, 'type', this._isBuffer))
        return callback(err)
  
      if (err = this._checkKey(e.key, 'key', this._isBuffer))
        return callback(err)
    }
  
    if (typeof this._batch == 'function')
      return this._batch(array, options, callback)
  
    process.nextTick(callback)
  }
  
  //TODO: remove from here, not a necessary primitive
  AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) {
    if (   start == null
        || end == null
        || typeof start == 'function'
        || typeof end == 'function') {
      throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments')
    }
  
    if (typeof callback != 'function')
      throw new Error('approximateSize() requires a callback argument')
  
    if (!this._isBuffer(start))
      start = String(start)
  
    if (!this._isBuffer(end))
      end = String(end)
  
    if (typeof this._approximateSize == 'function')
      return this._approximateSize(start, end, callback)
  
    process.nextTick(function () {
      callback(null, 0)
    })
  }
  
  AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) {
    var self = this
  
    options = xtend(options)
  
    ;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) {
      if (options[o] && self._isBuffer(options[o]) && options[o].length === 0)
        delete options[o]
    })
  
    options.reverse = !!options.reverse
    options.keys = options.keys != false
    options.values = options.values != false
    options.limit = 'limit' in options ? options.limit : -1
    options.keyAsBuffer = options.keyAsBuffer != false
    options.valueAsBuffer = options.valueAsBuffer != false
  
    return options
  }
  
  AbstractLevelDOWN.prototype.iterator = function (options) {
    if (typeof options != 'object')
      options = {}
  
    options = this._setupIteratorOptions(options)
  
    if (typeof this._iterator == 'function')
      return this._iterator(options)
  
    return new AbstractIterator(this)
  }
  
  AbstractLevelDOWN.prototype._chainedBatch = function () {
    return new AbstractChainedBatch(this)
  }
  
  AbstractLevelDOWN.prototype._isBuffer = function (obj) {
    return Buffer.isBuffer(obj)
  }
  
  AbstractLevelDOWN.prototype._checkKey = function (obj, type) {
  
    if (obj === null || obj === undefined)
      return new Error(type + ' cannot be `null` or `undefined`')
  
    if (this._isBuffer(obj)) {
      if (obj.length === 0)
        return new Error(type + ' cannot be an empty Buffer')
    } else if (String(obj) === '')
      return new Error(type + ' cannot be an empty String')
  }
  
  module.exports = AbstractLevelDOWN
  
  }).call(this,_dereq_(62),_dereq_(56).Buffer)
  },{"142":142,"143":143,"147":147,"56":56,"62":62}],145:[function(_dereq_,module,exports){
  exports.AbstractLevelDOWN    = _dereq_(144)
  exports.AbstractIterator     = _dereq_(143)
  exports.AbstractChainedBatch = _dereq_(142)
  exports.isLevelDOWN          = _dereq_(146)
  
  },{"142":142,"143":143,"144":144,"146":146}],146:[function(_dereq_,module,exports){
  var AbstractLevelDOWN = _dereq_(144)
  
  function isLevelDOWN (db) {
    if (!db || typeof db !== 'object')
      return false
    return Object.keys(AbstractLevelDOWN.prototype).filter(function (name) {
      // TODO remove approximateSize check when method is gone
      return name[0] != '_' && name != 'approximateSize'
    }).every(function (name) {
      return typeof db[name] == 'function'
    })
  }
  
  module.exports = isLevelDOWN
  
  },{"144":144}],147:[function(_dereq_,module,exports){
  arguments[4][105][0].apply(exports,arguments)
  },{"105":105}],148:[function(_dereq_,module,exports){
  "use strict"
  
  module.exports = createRBTree
  
  var RED   = 0
  var BLACK = 1
  
  function RBNode(color, key, value, left, right, count) {
    this._color = color
    this.key = key
    this.value = value
    this.left = left
    this.right = right
    this._count = count
  }
  
  function cloneNode(node) {
    return new RBNode(node._color, node.key, node.value, node.left, node.right, node._count)
  }
  
  function repaint(color, node) {
    return new RBNode(color, node.key, node.value, node.left, node.right, node._count)
  }
  
  function recount(node) {
    node._count = 1 + (node.left ? node.left._count : 0) + (node.right ? node.right._count : 0)
  }
  
  function RedBlackTree(compare, root) {
    this._compare = compare
    this.root = root
  }
  
  var proto = RedBlackTree.prototype
  
  Object.defineProperty(proto, "keys", {
    get: function() {
      var result = []
      this.forEach(function(k,v) {
        result.push(k)
      })
      return result
    }
  })
  
  Object.defineProperty(proto, "values", {
    get: function() {
      var result = []
      this.forEach(function(k,v) {
        result.push(v)
      })
      return result
    }
  })
  
  //Returns the number of nodes in the tree
  Object.defineProperty(proto, "length", {
    get: function() {
      if(this.root) {
        return this.root._count
      }
      return 0
    }
  })
  
  //Insert a new item into the tree
  proto.insert = function(key, value) {
    var cmp = this._compare
    //Find point to insert new node at
    var n = this.root
    var n_stack = []
    var d_stack = []
    while(n) {
      var d = cmp(key, n.key)
      n_stack.push(n)
      d_stack.push(d)
      if(d <= 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    //Rebuild path to leaf node
    n_stack.push(new RBNode(RED, key, value, null, null, 1))
    for(var s=n_stack.length-2; s>=0; --s) {
      var n = n_stack[s]
      if(d_stack[s] <= 0) {
        n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s+1], n.right, n._count+1)
      } else {
        n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s+1], n._count+1)
      }
    }
    //Rebalance tree using rotations
    //console.log("start insert", key, d_stack)
    for(var s=n_stack.length-1; s>1; --s) {
      var p = n_stack[s-1]
      var n = n_stack[s]
      if(p._color === BLACK || n._color === BLACK) {
        break
      }
      var pp = n_stack[s-2]
      if(pp.left === p) {
        if(p.left === n) {
          var y = pp.right
          if(y && y._color === RED) {
            //console.log("LLr")
            p._color = BLACK
            pp.right = repaint(BLACK, y)
            pp._color = RED
            s -= 1
          } else {
            //console.log("LLb")
            pp._color = RED
            pp.left = p.right
            p._color = BLACK
            p.right = pp
            n_stack[s-2] = p
            n_stack[s-1] = n
            recount(pp)
            recount(p)
            if(s >= 3) {
              var ppp = n_stack[s-3]
              if(ppp.left === pp) {
                ppp.left = p
              } else {
                ppp.right = p
              }
            }
            break
          }
        } else {
          var y = pp.right
          if(y && y._color === RED) {
            //console.log("LRr")
            p._color = BLACK
            pp.right = repaint(BLACK, y)
            pp._color = RED
            s -= 1
          } else {
            //console.log("LRb")
            p.right = n.left
            pp._color = RED
            pp.left = n.right
            n._color = BLACK
            n.left = p
            n.right = pp
            n_stack[s-2] = n
            n_stack[s-1] = p
            recount(pp)
            recount(p)
            recount(n)
            if(s >= 3) {
              var ppp = n_stack[s-3]
              if(ppp.left === pp) {
                ppp.left = n
              } else {
                ppp.right = n
              }
            }
            break
          }
        }
      } else {
        if(p.right === n) {
          var y = pp.left
          if(y && y._color === RED) {
            //console.log("RRr", y.key)
            p._color = BLACK
            pp.left = repaint(BLACK, y)
            pp._color = RED
            s -= 1
          } else {
            //console.log("RRb")
            pp._color = RED
            pp.right = p.left
            p._color = BLACK
            p.left = pp
            n_stack[s-2] = p
            n_stack[s-1] = n
            recount(pp)
            recount(p)
            if(s >= 3) {
              var ppp = n_stack[s-3]
              if(ppp.right === pp) {
                ppp.right = p
              } else {
                ppp.left = p
              }
            }
            break
          }
        } else {
          var y = pp.left
          if(y && y._color === RED) {
            //console.log("RLr")
            p._color = BLACK
            pp.left = repaint(BLACK, y)
            pp._color = RED
            s -= 1
          } else {
            //console.log("RLb")
            p.left = n.right
            pp._color = RED
            pp.right = n.left
            n._color = BLACK
            n.right = p
            n.left = pp
            n_stack[s-2] = n
            n_stack[s-1] = p
            recount(pp)
            recount(p)
            recount(n)
            if(s >= 3) {
              var ppp = n_stack[s-3]
              if(ppp.right === pp) {
                ppp.right = n
              } else {
                ppp.left = n
              }
            }
            break
          }
        }
      }
    }
    //Return new tree
    n_stack[0]._color = BLACK
    return new RedBlackTree(cmp, n_stack[0])
  }
  
  
  //Visit all nodes inorder
  function doVisitFull(visit, node) {
    if(node.left) {
      var v = doVisitFull(visit, node.left)
      if(v) { return v }
    }
    var v = visit(node.key, node.value)
    if(v) { return v }
    if(node.right) {
      return doVisitFull(visit, node.right)
    }
  }
  
  //Visit half nodes in order
  function doVisitHalf(lo, compare, visit, node) {
    var l = compare(lo, node.key)
    if(l <= 0) {
      if(node.left) {
        var v = doVisitHalf(lo, compare, visit, node.left)
        if(v) { return v }
      }
      var v = visit(node.key, node.value)
      if(v) { return v }
    }
    if(node.right) {
      return doVisitHalf(lo, compare, visit, node.right)
    }
  }
  
  //Visit all nodes within a range
  function doVisit(lo, hi, compare, visit, node) {
    var l = compare(lo, node.key)
    var h = compare(hi, node.key)
    var v
    if(l <= 0) {
      if(node.left) {
        v = doVisit(lo, hi, compare, visit, node.left)
        if(v) { return v }
      }
      if(h > 0) {
        v = visit(node.key, node.value)
        if(v) { return v }
      }
    }
    if(h > 0 && node.right) {
      return doVisit(lo, hi, compare, visit, node.right)
    }
  }
  
  
  proto.forEach = function rbTreeForEach(visit, lo, hi) {
    if(!this.root) {
      return
    }
    switch(arguments.length) {
      case 1:
        return doVisitFull(visit, this.root)
      break
  
      case 2:
        return doVisitHalf(lo, this._compare, visit, this.root)
      break
  
      case 3:
        if(this._compare(lo, hi) >= 0) {
          return
        }
        return doVisit(lo, hi, this._compare, visit, this.root)
      break
    }
  }
  
  //First item in list
  Object.defineProperty(proto, "begin", {
    get: function() {
      var stack = []
      var n = this.root
      while(n) {
        stack.push(n)
        n = n.left
      }
      return new RedBlackTreeIterator(this, stack)
    }
  })
  
  //Last item in list
  Object.defineProperty(proto, "end", {
    get: function() {
      var stack = []
      var n = this.root
      while(n) {
        stack.push(n)
        n = n.right
      }
      return new RedBlackTreeIterator(this, stack)
    }
  })
  
  //Find the ith item in the tree
  proto.at = function(idx) {
    if(idx < 0) {
      return new RedBlackTreeIterator(this, [])
    }
    var n = this.root
    var stack = []
    while(true) {
      stack.push(n)
      if(n.left) {
        if(idx < n.left._count) {
          n = n.left
          continue
        }
        idx -= n.left._count
      }
      if(!idx) {
        return new RedBlackTreeIterator(this, stack)
      }
      idx -= 1
      if(n.right) {
        if(idx >= n.right._count) {
          break
        }
        n = n.right
      } else {
        break
      }
    }
    return new RedBlackTreeIterator(this, [])
  }
  
  proto.ge = function(key) {
    var cmp = this._compare
    var n = this.root
    var stack = []
    var last_ptr = 0
    while(n) {
      var d = cmp(key, n.key)
      stack.push(n)
      if(d <= 0) {
        last_ptr = stack.length
      }
      if(d <= 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    stack.length = last_ptr
    return new RedBlackTreeIterator(this, stack)
  }
  
  proto.gt = function(key) {
    var cmp = this._compare
    var n = this.root
    var stack = []
    var last_ptr = 0
    while(n) {
      var d = cmp(key, n.key)
      stack.push(n)
      if(d < 0) {
        last_ptr = stack.length
      }
      if(d < 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    stack.length = last_ptr
    return new RedBlackTreeIterator(this, stack)
  }
  
  proto.lt = function(key) {
    var cmp = this._compare
    var n = this.root
    var stack = []
    var last_ptr = 0
    while(n) {
      var d = cmp(key, n.key)
      stack.push(n)
      if(d > 0) {
        last_ptr = stack.length
      }
      if(d <= 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    stack.length = last_ptr
    return new RedBlackTreeIterator(this, stack)
  }
  
  proto.le = function(key) {
    var cmp = this._compare
    var n = this.root
    var stack = []
    var last_ptr = 0
    while(n) {
      var d = cmp(key, n.key)
      stack.push(n)
      if(d >= 0) {
        last_ptr = stack.length
      }
      if(d < 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    stack.length = last_ptr
    return new RedBlackTreeIterator(this, stack)
  }
  
  //Finds the item with key if it exists
  proto.find = function(key) {
    var cmp = this._compare
    var n = this.root
    var stack = []
    while(n) {
      var d = cmp(key, n.key)
      stack.push(n)
      if(d === 0) {
        return new RedBlackTreeIterator(this, stack)
      }
      if(d <= 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    return new RedBlackTreeIterator(this, [])
  }
  
  //Removes item with key from tree
  proto.remove = function(key) {
    var iter = this.find(key)
    if(iter) {
      return iter.remove()
    }
    return this
  }
  
  //Returns the item at `key`
  proto.get = function(key) {
    var cmp = this._compare
    var n = this.root
    while(n) {
      var d = cmp(key, n.key)
      if(d === 0) {
        return n.value
      }
      if(d <= 0) {
        n = n.left
      } else {
        n = n.right
      }
    }
    return
  }
  
  //Iterator for red black tree
  function RedBlackTreeIterator(tree, stack) {
    this.tree = tree
    this._stack = stack
  }
  
  var iproto = RedBlackTreeIterator.prototype
  
  //Test if iterator is valid
  Object.defineProperty(iproto, "valid", {
    get: function() {
      return this._stack.length > 0
    }
  })
  
  //Node of the iterator
  Object.defineProperty(iproto, "node", {
    get: function() {
      if(this._stack.length > 0) {
        return this._stack[this._stack.length-1]
      }
      return null
    },
    enumerable: true
  })
  
  //Makes a copy of an iterator
  iproto.clone = function() {
    return new RedBlackTreeIterator(this.tree, this._stack.slice())
  }
  
  //Swaps two nodes
  function swapNode(n, v) {
    n.key = v.key
    n.value = v.value
    n.left = v.left
    n.right = v.right
    n._color = v._color
    n._count = v._count
  }
  
  //Fix up a double black node in a tree
  function fixDoubleBlack(stack) {
    var n, p, s, z
    for(var i=stack.length-1; i>=0; --i) {
      n = stack[i]
      if(i === 0) {
        n._color = BLACK
        return
      }
      //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
      p = stack[i-1]
      if(p.left === n) {
        //console.log("left child")
        s = p.right
        if(s.right && s.right._color === RED) {
          //console.log("case 1: right sibling child red")
          s = p.right = cloneNode(s)
          z = s.right = cloneNode(s.right)
          p.right = s.left
          s.left = p
          s.right = z
          s._color = p._color
          n._color = BLACK
          p._color = BLACK
          z._color = BLACK
          recount(p)
          recount(s)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.left === p) {
              pp.left = s
            } else {
              pp.right = s
            }
          }
          stack[i-1] = s
          return
        } else if(s.left && s.left._color === RED) {
          //console.log("case 1: left sibling child red")
          s = p.right = cloneNode(s)
          z = s.left = cloneNode(s.left)
          p.right = z.left
          s.left = z.right
          z.left = p
          z.right = s
          z._color = p._color
          p._color = BLACK
          s._color = BLACK
          n._color = BLACK
          recount(p)
          recount(s)
          recount(z)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.left === p) {
              pp.left = z
            } else {
              pp.right = z
            }
          }
          stack[i-1] = z
          return
        }
        if(s._color === BLACK) {
          if(p._color === RED) {
            //console.log("case 2: black sibling, red parent", p.right.value)
            p._color = BLACK
            p.right = repaint(RED, s)
            return
          } else {
            //console.log("case 2: black sibling, black parent", p.right.value)
            p.right = repaint(RED, s)
            continue  
          }
        } else {
          //console.log("case 3: red sibling")
          s = cloneNode(s)
          p.right = s.left
          s.left = p
          s._color = p._color
          p._color = RED
          recount(p)
          recount(s)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.left === p) {
              pp.left = s
            } else {
              pp.right = s
            }
          }
          stack[i-1] = s
          stack[i] = p
          if(i+1 < stack.length) {
            stack[i+1] = n
          } else {
            stack.push(n)
          }
          i = i+2
        }
      } else {
        //console.log("right child")
        s = p.left
        if(s.left && s.left._color === RED) {
          //console.log("case 1: left sibling child red", p.value, p._color)
          s = p.left = cloneNode(s)
          z = s.left = cloneNode(s.left)
          p.left = s.right
          s.right = p
          s.left = z
          s._color = p._color
          n._color = BLACK
          p._color = BLACK
          z._color = BLACK
          recount(p)
          recount(s)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.right === p) {
              pp.right = s
            } else {
              pp.left = s
            }
          }
          stack[i-1] = s
          return
        } else if(s.right && s.right._color === RED) {
          //console.log("case 1: right sibling child red")
          s = p.left = cloneNode(s)
          z = s.right = cloneNode(s.right)
          p.left = z.right
          s.right = z.left
          z.right = p
          z.left = s
          z._color = p._color
          p._color = BLACK
          s._color = BLACK
          n._color = BLACK
          recount(p)
          recount(s)
          recount(z)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.right === p) {
              pp.right = z
            } else {
              pp.left = z
            }
          }
          stack[i-1] = z
          return
        }
        if(s._color === BLACK) {
          if(p._color === RED) {
            //console.log("case 2: black sibling, red parent")
            p._color = BLACK
            p.left = repaint(RED, s)
            return
          } else {
            //console.log("case 2: black sibling, black parent")
            p.left = repaint(RED, s)
            continue  
          }
        } else {
          //console.log("case 3: red sibling")
          s = cloneNode(s)
          p.left = s.right
          s.right = p
          s._color = p._color
          p._color = RED
          recount(p)
          recount(s)
          if(i > 1) {
            var pp = stack[i-2]
            if(pp.right === p) {
              pp.right = s
            } else {
              pp.left = s
            }
          }
          stack[i-1] = s
          stack[i] = p
          if(i+1 < stack.length) {
            stack[i+1] = n
          } else {
            stack.push(n)
          }
          i = i+2
        }
      }
    }
  }
  
  //Removes item at iterator from tree
  iproto.remove = function() {
    var stack = this._stack
    if(stack.length === 0) {
      return this.tree
    }
    //First copy path to node
    var cstack = new Array(stack.length)
    var n = stack[stack.length-1]
    cstack[cstack.length-1] = new RBNode(n._color, n.key, n.value, n.left, n.right, n._count)
    for(var i=stack.length-2; i>=0; --i) {
      var n = stack[i]
      if(n.left === stack[i+1]) {
        cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count)
      } else {
        cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count)
      }
    }
  
    //Get node
    n = cstack[cstack.length-1]
    //console.log("start remove: ", n.value)
  
    //If not leaf, then swap with previous node
    if(n.left && n.right) {
      //console.log("moving to leaf")
  
      //First walk to previous leaf
      var split = cstack.length
      n = n.left
      while(n.right) {
        cstack.push(n)
        n = n.right
      }
      //Copy path to leaf
      var v = cstack[split-1]
      cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right, n._count))
      cstack[split-1].key = n.key
      cstack[split-1].value = n.value
  
      //Fix up stack
      for(var i=cstack.length-2; i>=split; --i) {
        n = cstack[i]
        cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count)
      }
      cstack[split-1].left = cstack[split]
    }
    //console.log("stack=", cstack.map(function(v) { return v.value }))
  
    //Remove leaf node
    n = cstack[cstack.length-1]
    if(n._color === RED) {
      //Easy case: removing red leaf
      //console.log("RED leaf")
      var p = cstack[cstack.length-2]
      if(p.left === n) {
        p.left = null
      } else if(p.right === n) {
        p.right = null
      }
      cstack.pop()
      for(var i=0; i<cstack.length; ++i) {
        cstack[i]._count--
      }
      return new RedBlackTree(this.tree._compare, cstack[0])
    } else {
      if(n.left || n.right) {
        //Second easy case:  Single child black parent
        //console.log("BLACK single child")
        if(n.left) {
          swapNode(n, n.left)
        } else if(n.right) {
          swapNode(n, n.right)
        }
        //Child must be red, so repaint it black to balance color
        n._color = BLACK
        for(var i=0; i<cstack.length-1; ++i) {
          cstack[i]._count--
        }
        return new RedBlackTree(this.tree._compare, cstack[0])
      } else if(cstack.length === 1) {
        //Third easy case: root
        //console.log("ROOT")
        return new RedBlackTree(this.tree._compare, null)
      } else {
        //Hard case: Repaint n, and then do some nasty stuff
        //console.log("BLACK leaf no children")
        for(var i=0; i<cstack.length; ++i) {
          cstack[i]._count--
        }
        var parent = cstack[cstack.length-2]
        fixDoubleBlack(cstack)
        //Fix up links
        if(parent.left === n) {
          parent.left = null
        } else {
          parent.right = null
        }
      }
    }
    return new RedBlackTree(this.tree._compare, cstack[0])
  }
  
  //Returns key
  Object.defineProperty(iproto, "key", {
    get: function() {
      if(this._stack.length > 0) {
        return this._stack[this._stack.length-1].key
      }
      return
    },
    enumerable: true
  })
  
  //Returns value
  Object.defineProperty(iproto, "value", {
    get: function() {
      if(this._stack.length > 0) {
        return this._stack[this._stack.length-1].value
      }
      return
    },
    enumerable: true
  })
  
  
  //Returns the position of this iterator in the sorted list
  Object.defineProperty(iproto, "index", {
    get: function() {
      var idx = 0
      var stack = this._stack
      if(stack.length === 0) {
        var r = this.tree.root
        if(r) {
          return r._count
        }
        return 0
      } else if(stack[stack.length-1].left) {
        idx = stack[stack.length-1].left._count
      }
      for(var s=stack.length-2; s>=0; --s) {
        if(stack[s+1] === stack[s].right) {
          ++idx
          if(stack[s].left) {
            idx += stack[s].left._count
          }
        }
      }
      return idx
    },
    enumerable: true
  })
  
  //Advances iterator to next element in list
  iproto.next = function() {
    var stack = this._stack
    if(stack.length === 0) {
      return
    }
    var n = stack[stack.length-1]
    if(n.right) {
      n = n.right
      while(n) {
        stack.push(n)
        n = n.left
      }
    } else {
      stack.pop()
      while(stack.length > 0 && stack[stack.length-1].right === n) {
        n = stack[stack.length-1]
        stack.pop()
      }
    }
  }
  
  //Checks if iterator is at end of tree
  Object.defineProperty(iproto, "hasNext", {
    get: function() {
      var stack = this._stack
      if(stack.length === 0) {
        return false
      }
      if(stack[stack.length-1].right) {
        return true
      }
      for(var s=stack.length-1; s>0; --s) {
        if(stack[s-1].left === stack[s]) {
          return true
        }
      }
      return false
    }
  })
  
  //Update value
  iproto.update = function(value) {
    var stack = this._stack
    if(stack.length === 0) {
      throw new Error("Can't update empty node!")
    }
    var cstack = new Array(stack.length)
    var n = stack[stack.length-1]
    cstack[cstack.length-1] = new RBNode(n._color, n.key, value, n.left, n.right, n._count)
    for(var i=stack.length-2; i>=0; --i) {
      n = stack[i]
      if(n.left === stack[i+1]) {
        cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count)
      } else {
        cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count)
      }
    }
    return new RedBlackTree(this.tree._compare, cstack[0])
  }
  
  //Moves iterator backward one element
  iproto.prev = function() {
    var stack = this._stack
    if(stack.length === 0) {
      return
    }
    var n = stack[stack.length-1]
    if(n.left) {
      n = n.left
      while(n) {
        stack.push(n)
        n = n.right
      }
    } else {
      stack.pop()
      while(stack.length > 0 && stack[stack.length-1].left === n) {
        n = stack[stack.length-1]
        stack.pop()
      }
    }
  }
  
  //Checks if iterator is at start of tree
  Object.defineProperty(iproto, "hasPrev", {
    get: function() {
      var stack = this._stack
      if(stack.length === 0) {
        return false
      }
      if(stack[stack.length-1].left) {
        return true
      }
      for(var s=stack.length-1; s>0; --s) {
        if(stack[s-1].right === stack[s]) {
          return true
        }
      }
      return false
    }
  })
  
  //Default comparison function
  function defaultCompare(a, b) {
    if(a < b) {
      return -1
    }
    if(a > b) {
      return 1
    }
    return 0
  }
  
  //Build a tree
  function createRBTree(compare) {
    return new RedBlackTree(compare || defaultCompare, null)
  }
  },{}],149:[function(_dereq_,module,exports){
  (function (Buffer){
  
  exports.compare = function (a, b) {
  
    if(Buffer.isBuffer(a)) {
      var l = Math.min(a.length, b.length)
      for(var i = 0; i < l; i++) {
        var cmp = a[i] - b[i]
        if(cmp) return cmp
      }
      return a.length - b.length
    }
  
    return a < b ? -1 : a > b ? 1 : 0
  }
  
  function has(obj, key) {
    return Object.hasOwnProperty.call(obj, key)
  }
  
  // to be compatible with the current abstract-leveldown tests
  // nullish or empty strings.
  // I could use !!val but I want to permit numbers and booleans,
  // if possible.
  
  function isDef (val) {
    return val != null && val !== ''
  }
  
  var lowerBound = exports.lowerBound = function (range) {
    return (
        isDef(range.gt)                      ? range.gt
      : isDef(range.gte)                     ? range.gte
      : isDef(range.min)                     ? range.min
      : isDef(range.start) && !range.reverse ? range.start
      : isDef(range.end) && range.reverse    ? range.end
      :                                        undefined
    )
  }
  
  exports.lowerBoundInclusive = function (range) {
    return isDef(range.gt) ? false : true
  }
  
  exports.upperBoundInclusive =
    function (range) {
      return isDef(range.lt) ? false : true
    }
  
  var lowerBoundExclusive = exports.lowerBoundExclusive =
    function (range) {
      return isDef(range.gt) ? true : false
    }
  
  var upperBoundExclusive = exports.upperBoundExclusive =
    function (range) {
      return isDef(range.lt) ? true : false
    }
  
  var upperBound = exports.upperBound = function (range) {
    return (
        isDef(range.lt)                     ? range.lt
      : isDef(range.lte)                    ? range.lte
      : isDef(range.max)                    ? range.max
      : isDef(range.start) && range.reverse ? range.start
      : isDef(range.end) && !range.reverse  ? range.end
      :                                       undefined
    )
  }
  
  
  exports.contains = function (range, key, compare) {
    compare = compare || exports.compare
  
    var lb = lowerBound(range)
    if(isDef(lb)) {
      var cmp = compare(key, lb)
      if(cmp < 0 || (cmp === 0 && lowerBoundExclusive(range)))
        return false
    }
  
    var ub = upperBound(range)
    if(isDef(ub)) {
      var cmp = compare(key, ub)
      if(cmp > 0 || (cmp === 0) && upperBoundExclusive(range))
        return false
    }
  
    return true
  }
  
  exports.filter = function (range, compare) {
    return function (key) {
      return exports.contains(range, key, compare)
    }
  }
  
  }).call(this,_dereq_(56).Buffer)
  },{"56":56}],150:[function(_dereq_,module,exports){
  'use strict';
  exports.Map = LazyMap; // TODO: use ES6 map
  exports.Set = LazySet; // TODO: use ES6 set
  // based on https://github.com/montagejs/collections
  function LazyMap() {
    this.store = {};
  }
  LazyMap.prototype.mangle = function (key) {
    if (typeof key !== "string") {
      throw new TypeError("key must be a string but Got " + key);
    }
    return '$' + key;
  };
  LazyMap.prototype.unmangle = function (key) {
    return key.substring(1);
  };
  LazyMap.prototype.get = function (key) {
    var mangled = this.mangle(key);
    if (mangled in this.store) {
      return this.store[mangled];
    }
    return void 0;
  };
  LazyMap.prototype.set = function (key, value) {
    var mangled = this.mangle(key);
    this.store[mangled] = value;
    return true;
  };
  LazyMap.prototype.has = function (key) {
    var mangled = this.mangle(key);
    return mangled in this.store;
  };
  LazyMap.prototype["delete"] = function (key) {
    var mangled = this.mangle(key);
    if (mangled in this.store) {
      delete this.store[mangled];
      return true;
    }
    return false;
  };
  LazyMap.prototype.forEach = function (cb) {
    var keys = Object.keys(this.store);
    for (var i = 0, len = keys.length; i < len; i++) {
      var key = keys[i];
      var value = this.store[key];
      key = this.unmangle(key);
      cb(value, key);
    }
  };
  
  function LazySet(array) {
    this.store = new LazyMap();
  
    // init with an array
    if (array && Array.isArray(array)) {
      for (var i = 0, len = array.length; i < len; i++) {
        this.add(array[i]);
      }
    }
  }
  LazySet.prototype.add = function (key) {
    return this.store.set(key, true);
  };
  LazySet.prototype.has = function (key) {
    return this.store.has(key);
  };
  LazySet.prototype["delete"] = function (key) {
    return this.store["delete"](key);
  };
  
  },{}],151:[function(_dereq_,module,exports){
  /*jshint bitwise:false*/
  /*global unescape*/
  
  (function (factory) {
      if (typeof exports === 'object') {
          // Node/CommonJS
          module.exports = factory();
      } else if (typeof define === 'function' && define.amd) {
          // AMD
          define(factory);
      } else {
          // Browser globals (with support for web workers)
          var glob;
          try {
              glob = window;
          } catch (e) {
              glob = self;
          }
  
          glob.SparkMD5 = factory();
      }
  }(function (undefined) {
  
      'use strict';
  
      ////////////////////////////////////////////////////////////////////////////
  
      /*
       * Fastest md5 implementation around (JKM md5)
       * Credits: Joseph Myers
       *
       * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
       * @see http://jsperf.com/md5-shootout/7
       */
  
      /* this function is much faster,
        so if possible we use it. Some IEs
        are the only ones I know of that
        need the idiotic second function,
        generated by an if clause.  */
      var add32 = function (a, b) {
          return (a + b) & 0xFFFFFFFF;
      },
  
      cmn = function (q, a, b, x, s, t) {
          a = add32(add32(a, q), add32(x, t));
          return add32((a << s) | (a >>> (32 - s)), b);
      },
  
      ff = function (a, b, c, d, x, s, t) {
          return cmn((b & c) | ((~b) & d), a, b, x, s, t);
      },
  
      gg = function (a, b, c, d, x, s, t) {
          return cmn((b & d) | (c & (~d)), a, b, x, s, t);
      },
  
      hh = function (a, b, c, d, x, s, t) {
          return cmn(b ^ c ^ d, a, b, x, s, t);
      },
  
      ii = function (a, b, c, d, x, s, t) {
          return cmn(c ^ (b | (~d)), a, b, x, s, t);
      },
  
      md5cycle = function (x, k) {
          var a = x[0],
              b = x[1],
              c = x[2],
              d = x[3];
  
          a = ff(a, b, c, d, k[0], 7, -680876936);
          d = ff(d, a, b, c, k[1], 12, -389564586);
          c = ff(c, d, a, b, k[2], 17, 606105819);
          b = ff(b, c, d, a, k[3], 22, -1044525330);
          a = ff(a, b, c, d, k[4], 7, -176418897);
          d = ff(d, a, b, c, k[5], 12, 1200080426);
          c = ff(c, d, a, b, k[6], 17, -1473231341);
          b = ff(b, c, d, a, k[7], 22, -45705983);
          a = ff(a, b, c, d, k[8], 7, 1770035416);
          d = ff(d, a, b, c, k[9], 12, -1958414417);
          c = ff(c, d, a, b, k[10], 17, -42063);
          b = ff(b, c, d, a, k[11], 22, -1990404162);
          a = ff(a, b, c, d, k[12], 7, 1804603682);
          d = ff(d, a, b, c, k[13], 12, -40341101);
          c = ff(c, d, a, b, k[14], 17, -1502002290);
          b = ff(b, c, d, a, k[15], 22, 1236535329);
  
          a = gg(a, b, c, d, k[1], 5, -165796510);
          d = gg(d, a, b, c, k[6], 9, -1069501632);
          c = gg(c, d, a, b, k[11], 14, 643717713);
          b = gg(b, c, d, a, k[0], 20, -373897302);
          a = gg(a, b, c, d, k[5], 5, -701558691);
          d = gg(d, a, b, c, k[10], 9, 38016083);
          c = gg(c, d, a, b, k[15], 14, -660478335);
          b = gg(b, c, d, a, k[4], 20, -405537848);
          a = gg(a, b, c, d, k[9], 5, 568446438);
          d = gg(d, a, b, c, k[14], 9, -1019803690);
          c = gg(c, d, a, b, k[3], 14, -187363961);
          b = gg(b, c, d, a, k[8], 20, 1163531501);
          a = gg(a, b, c, d, k[13], 5, -1444681467);
          d = gg(d, a, b, c, k[2], 9, -51403784);
          c = gg(c, d, a, b, k[7], 14, 1735328473);
          b = gg(b, c, d, a, k[12], 20, -1926607734);
  
          a = hh(a, b, c, d, k[5], 4, -378558);
          d = hh(d, a, b, c, k[8], 11, -2022574463);
          c = hh(c, d, a, b, k[11], 16, 1839030562);
          b = hh(b, c, d, a, k[14], 23, -35309556);
          a = hh(a, b, c, d, k[1], 4, -1530992060);
          d = hh(d, a, b, c, k[4], 11, 1272893353);
          c = hh(c, d, a, b, k[7], 16, -155497632);
          b = hh(b, c, d, a, k[10], 23, -1094730640);
          a = hh(a, b, c, d, k[13], 4, 681279174);
          d = hh(d, a, b, c, k[0], 11, -358537222);
          c = hh(c, d, a, b, k[3], 16, -722521979);
          b = hh(b, c, d, a, k[6], 23, 76029189);
          a = hh(a, b, c, d, k[9], 4, -640364487);
          d = hh(d, a, b, c, k[12], 11, -421815835);
          c = hh(c, d, a, b, k[15], 16, 530742520);
          b = hh(b, c, d, a, k[2], 23, -995338651);
  
          a = ii(a, b, c, d, k[0], 6, -198630844);
          d = ii(d, a, b, c, k[7], 10, 1126891415);
          c = ii(c, d, a, b, k[14], 15, -1416354905);
          b = ii(b, c, d, a, k[5], 21, -57434055);
          a = ii(a, b, c, d, k[12], 6, 1700485571);
          d = ii(d, a, b, c, k[3], 10, -1894986606);
          c = ii(c, d, a, b, k[10], 15, -1051523);
          b = ii(b, c, d, a, k[1], 21, -2054922799);
          a = ii(a, b, c, d, k[8], 6, 1873313359);
          d = ii(d, a, b, c, k[15], 10, -30611744);
          c = ii(c, d, a, b, k[6], 15, -1560198380);
          b = ii(b, c, d, a, k[13], 21, 1309151649);
          a = ii(a, b, c, d, k[4], 6, -145523070);
          d = ii(d, a, b, c, k[11], 10, -1120210379);
          c = ii(c, d, a, b, k[2], 15, 718787259);
          b = ii(b, c, d, a, k[9], 21, -343485551);
  
          x[0] = add32(a, x[0]);
          x[1] = add32(b, x[1]);
          x[2] = add32(c, x[2]);
          x[3] = add32(d, x[3]);
      },
  
      /* there needs to be support for Unicode here,
         * unless we pretend that we can redefine the MD-5
         * algorithm for multi-byte characters (perhaps
         * by adding every four 16-bit characters and
         * shortening the sum to 32 bits). Otherwise
         * I suggest performing MD-5 as if every character
         * was two bytes--e.g., 0040 0025 = @%--but then
         * how will an ordinary MD-5 sum be matched?
         * There is no way to standardize text to something
         * like UTF-8 before transformation; speed cost is
         * utterly prohibitive. The JavaScript standard
         * itself needs to look at this: it should start
         * providing access to strings as preformed UTF-8
         * 8-bit unsigned value arrays.
         */
      md5blk = function (s) {
          var md5blks = [],
              i; /* Andy King said do it this way. */
  
          for (i = 0; i < 64; i += 4) {
              md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
          }
          return md5blks;
      },
  
      md5blk_array = function (a) {
          var md5blks = [],
              i; /* Andy King said do it this way. */
  
          for (i = 0; i < 64; i += 4) {
              md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
          }
          return md5blks;
      },
  
      md51 = function (s) {
          var n = s.length,
              state = [1732584193, -271733879, -1732584194, 271733878],
              i,
              length,
              tail,
              tmp,
              lo,
              hi;
  
          for (i = 64; i <= n; i += 64) {
              md5cycle(state, md5blk(s.substring(i - 64, i)));
          }
          s = s.substring(i - 64);
          length = s.length;
          tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
          for (i = 0; i < length; i += 1) {
              tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
          }
          tail[i >> 2] |= 0x80 << ((i % 4) << 3);
          if (i > 55) {
              md5cycle(state, tail);
              for (i = 0; i < 16; i += 1) {
                  tail[i] = 0;
              }
          }
  
          // Beware that the final length might not fit in 32 bits so we take care of that
          tmp = n * 8;
          tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
          lo = parseInt(tmp[2], 16);
          hi = parseInt(tmp[1], 16) || 0;
  
          tail[14] = lo;
          tail[15] = hi;
  
          md5cycle(state, tail);
          return state;
      },
  
      md51_array = function (a) {
          var n = a.length,
              state = [1732584193, -271733879, -1732584194, 271733878],
              i,
              length,
              tail,
              tmp,
              lo,
              hi;
  
          for (i = 64; i <= n; i += 64) {
              md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
          }
  
          // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
          // containing the last element of the parent array if the sub array specified starts
          // beyond the length of the parent array - weird.
          // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
          a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
  
          length = a.length;
          tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
          for (i = 0; i < length; i += 1) {
              tail[i >> 2] |= a[i] << ((i % 4) << 3);
          }
  
          tail[i >> 2] |= 0x80 << ((i % 4) << 3);
          if (i > 55) {
              md5cycle(state, tail);
              for (i = 0; i < 16; i += 1) {
                  tail[i] = 0;
              }
          }
  
          // Beware that the final length might not fit in 32 bits so we take care of that
          tmp = n * 8;
          tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
          lo = parseInt(tmp[2], 16);
          hi = parseInt(tmp[1], 16) || 0;
  
          tail[14] = lo;
          tail[15] = hi;
  
          md5cycle(state, tail);
  
          return state;
      },
  
      hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
  
      rhex = function (n) {
          var s = '',
              j;
          for (j = 0; j < 4; j += 1) {
              s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
          }
          return s;
      },
  
      hex = function (x) {
          var i;
          for (i = 0; i < x.length; i += 1) {
              x[i] = rhex(x[i]);
          }
          return x.join('');
      },
  
      md5 = function (s) {
          return hex(md51(s));
      },
  
  
  
      ////////////////////////////////////////////////////////////////////////////
  
      /**
       * SparkMD5 OOP implementation.
       *
       * Use this class to perform an incremental md5, otherwise use the
       * static methods instead.
       */
      SparkMD5 = function () {
          // call reset to init the instance
          this.reset();
      };
  
  
      // In some cases the fast add32 function cannot be used..
      if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
          add32 = function (x, y) {
              var lsw = (x & 0xFFFF) + (y & 0xFFFF),
                  msw = (x >> 16) + (y >> 16) + (lsw >> 16);
              return (msw << 16) | (lsw & 0xFFFF);
          };
      }
  
  
      /**
       * Appends a string.
       * A conversion will be applied if an utf8 string is detected.
       *
       * @param {String} str The string to be appended
       *
       * @return {SparkMD5} The instance itself
       */
      SparkMD5.prototype.append = function (str) {
          // converts the string to utf8 bytes if necessary
          if (/[\u0080-\uFFFF]/.test(str)) {
              str = unescape(encodeURIComponent(str));
          }
  
          // then append as binary
          this.appendBinary(str);
  
          return this;
      };
  
      /**
       * Appends a binary string.
       *
       * @param {String} contents The binary string to be appended
       *
       * @return {SparkMD5} The instance itself
       */
      SparkMD5.prototype.appendBinary = function (contents) {
          this._buff += contents;
          this._length += contents.length;
  
          var length = this._buff.length,
              i;
  
          for (i = 64; i <= length; i += 64) {
              md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));
          }
  
          this._buff = this._buff.substr(i - 64);
  
          return this;
      };
  
      /**
       * Finishes the incremental computation, reseting the internal state and
       * returning the result.
       * Use the raw parameter to obtain the raw result instead of the hex one.
       *
       * @param {Boolean} raw True to get the raw result, false to get the hex result
       *
       * @return {String|Array} The result
       */
      SparkMD5.prototype.end = function (raw) {
          var buff = this._buff,
              length = buff.length,
              i,
              tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              ret;
  
          for (i = 0; i < length; i += 1) {
              tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
          }
  
          this._finish(tail, length);
          ret = !!raw ? this._state : hex(this._state);
  
          this.reset();
  
          return ret;
      };
  
      /**
       * Finish the final calculation based on the tail.
       *
       * @param {Array}  tail   The tail (will be modified)
       * @param {Number} length The length of the remaining buffer
       */
      SparkMD5.prototype._finish = function (tail, length) {
          var i = length,
              tmp,
              lo,
              hi;
  
          tail[i >> 2] |= 0x80 << ((i % 4) << 3);
          if (i > 55) {
              md5cycle(this._state, tail);
              for (i = 0; i < 16; i += 1) {
                  tail[i] = 0;
              }
          }
  
          // Do the final computation based on the tail and length
          // Beware that the final length may not fit in 32 bits so we take care of that
          tmp = this._length * 8;
          tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
          lo = parseInt(tmp[2], 16);
          hi = parseInt(tmp[1], 16) || 0;
  
          tail[14] = lo;
          tail[15] = hi;
          md5cycle(this._state, tail);
      };
  
      /**
       * Resets the internal state of the computation.
       *
       * @return {SparkMD5} The instance itself
       */
      SparkMD5.prototype.reset = function () {
          this._buff = "";
          this._length = 0;
          this._state = [1732584193, -271733879, -1732584194, 271733878];
  
          return this;
      };
  
      /**
       * Releases memory used by the incremental buffer and other aditional
       * resources. If you plan to use the instance again, use reset instead.
       */
      SparkMD5.prototype.destroy = function () {
          delete this._state;
          delete this._buff;
          delete this._length;
      };
  
  
      /**
       * Performs the md5 hash on a string.
       * A conversion will be applied if utf8 string is detected.
       *
       * @param {String}  str The string
       * @param {Boolean} raw True to get the raw result, false to get the hex result
       *
       * @return {String|Array} The result
       */
      SparkMD5.hash = function (str, raw) {
          // converts the string to utf8 bytes if necessary
          if (/[\u0080-\uFFFF]/.test(str)) {
              str = unescape(encodeURIComponent(str));
          }
  
          var hash = md51(str);
  
          return !!raw ? hash : hex(hash);
      };
  
      /**
       * Performs the md5 hash on a binary string.
       *
       * @param {String}  content The binary string
       * @param {Boolean} raw     True to get the raw result, false to get the hex result
       *
       * @return {String|Array} The result
       */
      SparkMD5.hashBinary = function (content, raw) {
          var hash = md51(content);
  
          return !!raw ? hash : hex(hash);
      };
  
      /**
       * SparkMD5 OOP implementation for array buffers.
       *
       * Use this class to perform an incremental md5 ONLY for array buffers.
       */
      SparkMD5.ArrayBuffer = function () {
          // call reset to init the instance
          this.reset();
      };
  
      ////////////////////////////////////////////////////////////////////////////
  
      /**
       * Appends an array buffer.
       *
       * @param {ArrayBuffer} arr The array to be appended
       *
       * @return {SparkMD5.ArrayBuffer} The instance itself
       */
      SparkMD5.ArrayBuffer.prototype.append = function (arr) {
          // TODO: we could avoid the concatenation here but the algorithm would be more complex
          //       if you find yourself needing extra performance, please make a PR.
          var buff = this._concatArrayBuffer(this._buff, arr),
              length = buff.length,
              i;
  
          this._length += arr.byteLength;
  
          for (i = 64; i <= length; i += 64) {
              md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));
          }
  
          // Avoids IE10 weirdness (documented above)
          this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);
  
          return this;
      };
  
      /**
       * Finishes the incremental computation, reseting the internal state and
       * returning the result.
       * Use the raw parameter to obtain the raw result instead of the hex one.
       *
       * @param {Boolean} raw True to get the raw result, false to get the hex result
       *
       * @return {String|Array} The result
       */
      SparkMD5.ArrayBuffer.prototype.end = function (raw) {
          var buff = this._buff,
              length = buff.length,
              tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              i,
              ret;
  
          for (i = 0; i < length; i += 1) {
              tail[i >> 2] |= buff[i] << ((i % 4) << 3);
          }
  
          this._finish(tail, length);
          ret = !!raw ? this._state : hex(this._state);
  
          this.reset();
  
          return ret;
      };
  
      SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
  
      /**
       * Resets the internal state of the computation.
       *
       * @return {SparkMD5.ArrayBuffer} The instance itself
       */
      SparkMD5.ArrayBuffer.prototype.reset = function () {
          this._buff = new Uint8Array(0);
          this._length = 0;
          this._state = [1732584193, -271733879, -1732584194, 271733878];
  
          return this;
      };
  
      /**
       * Releases memory used by the incremental buffer and other aditional
       * resources. If you plan to use the instance again, use reset instead.
       */
      SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
  
      /**
       * Concats two array buffers, returning a new one.
       *
       * @param  {ArrayBuffer} first  The first array buffer
       * @param  {ArrayBuffer} second The second array buffer
       *
       * @return {ArrayBuffer} The new array buffer
       */
      SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {
          var firstLength = first.length,
              result = new Uint8Array(firstLength + second.byteLength);
  
          result.set(first);
          result.set(new Uint8Array(second), firstLength);
  
          return result;
      };
  
      /**
       * Performs the md5 hash on an array buffer.
       *
       * @param {ArrayBuffer} arr The array buffer
       * @param {Boolean}     raw True to get the raw result, false to get the hex result
       *
       * @return {String|Array} The result
       */
      SparkMD5.ArrayBuffer.hash = function (arr, raw) {
          var hash = md51_array(new Uint8Array(arr));
  
          return !!raw ? hash : hex(hash);
      };
  
      return SparkMD5;
  }));
  
  },{}],152:[function(_dereq_,module,exports){
  arguments[4][64][0].apply(exports,arguments)
  },{"153":153,"155":155,"156":156,"158":158,"64":64,"84":84}],153:[function(_dereq_,module,exports){
  arguments[4][66][0].apply(exports,arguments)
  },{"152":152,"156":156,"157":157,"158":158,"159":159,"55":55,"56":56,"60":60,"62":62,"66":66,"84":84}],154:[function(_dereq_,module,exports){
  arguments[4][67][0].apply(exports,arguments)
  },{"152":152,"156":156,"67":67,"84":84}],155:[function(_dereq_,module,exports){
  arguments[4][68][0].apply(exports,arguments)
  },{"152":152,"156":156,"158":158,"160":160,"56":56,"60":60,"68":68,"84":84}],156:[function(_dereq_,module,exports){
  arguments[4][69][0].apply(exports,arguments)
  },{"56":56,"69":69}],157:[function(_dereq_,module,exports){
  arguments[4][61][0].apply(exports,arguments)
  },{"61":61}],158:[function(_dereq_,module,exports){
  arguments[4][70][0].apply(exports,arguments)
  },{"62":62,"70":70}],159:[function(_dereq_,module,exports){
  arguments[4][77][0].apply(exports,arguments)
  },{"56":56,"77":77}],160:[function(_dereq_,module,exports){
  arguments[4][71][0].apply(exports,arguments)
  },{"71":71}],161:[function(_dereq_,module,exports){
  arguments[4][74][0].apply(exports,arguments)
  },{"154":154,"74":74}],162:[function(_dereq_,module,exports){
  arguments[4][105][0].apply(exports,arguments)
  },{"105":105}],163:[function(_dereq_,module,exports){
  (function (process){
  var Transform = _dereq_(161)
    , inherits  = _dereq_(79).inherits
    , xtend     = _dereq_(162)
  
  function DestroyableTransform(opts) {
    Transform.call(this, opts)
    this._destroyed = false
  }
  
  inherits(DestroyableTransform, Transform)
  
  DestroyableTransform.prototype.destroy = function(err) {
    if (this._destroyed) return
    this._destroyed = true
    
    var self = this
    process.nextTick(function() {
      if (err)
        self.emit('error', err)
      self.emit('close')
    })
  }
  
  // a noop _transform function
  function noop (chunk, enc, callback) {
    callback(null, chunk)
  }
  
  
  // create a new export function, used by both the main export and
  // the .ctor export, contains common logic for dealing with arguments
  function through2 (construct) {
    return function (options, transform, flush) {
      if (typeof options == 'function') {
        flush     = transform
        transform = options
        options   = {}
      }
  
      if (typeof transform != 'function')
        transform = noop
  
      if (typeof flush != 'function')
        flush = null
  
      return construct(options, transform, flush)
    }
  }
  
  
  // main export, just make me a transform stream!
  module.exports = through2(function (options, transform, flush) {
    var t2 = new DestroyableTransform(options)
  
    t2._transform = transform
  
    if (flush)
      t2._flush = flush
  
    return t2
  })
  
  
  // make me a reusable prototype that I can `new`, or implicitly `new`
  // with a constructor call
  module.exports.ctor = through2(function (options, transform, flush) {
    function Through2 (override) {
      if (!(this instanceof Through2))
        return new Through2(override)
  
      this.options = xtend(options, override)
  
      DestroyableTransform.call(this, this.options)
    }
  
    inherits(Through2, DestroyableTransform)
  
    Through2.prototype._transform = transform
  
    if (flush)
      Through2.prototype._flush = flush
  
    return Through2
  })
  
  
  module.exports.obj = through2(function (options, transform, flush) {
    var t2 = new DestroyableTransform(xtend({ objectMode: true, highWaterMark: 16 }, options))
  
    t2._transform = transform
  
    if (flush)
      t2._flush = flush
  
    return t2
  })
  
  }).call(this,_dereq_(62))
  },{"161":161,"162":162,"62":62,"79":79}],164:[function(_dereq_,module,exports){
  'use strict';
  
  /**
   * Stringify/parse functions that don't operate
   * recursively, so they avoid call stack exceeded
   * errors.
   */
  exports.stringify = function stringify(input) {
    var queue = [];
    queue.push({obj: input});
  
    var res = '';
    var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix;
    while ((next = queue.pop())) {
      obj = next.obj;
      prefix = next.prefix || '';
      val = next.val || '';
      res += prefix;
      if (val) {
        res += val;
      } else if (typeof obj !== 'object') {
        res += typeof obj === 'undefined' ? null : JSON.stringify(obj);
      } else if (obj === null) {
        res += 'null';
      } else if (Array.isArray(obj)) {
        queue.push({val: ']'});
        for (i = obj.length - 1; i >= 0; i--) {
          arrayPrefix = i === 0 ? '' : ',';
          queue.push({obj: obj[i], prefix: arrayPrefix});
        }
        queue.push({val: '['});
      } else { // object
        keys = [];
        for (k in obj) {
          if (obj.hasOwnProperty(k)) {
            keys.push(k);
          }
        }
        queue.push({val: '}'});
        for (i = keys.length - 1; i >= 0; i--) {
          key = keys[i];
          value = obj[key];
          objPrefix = (i > 0 ? ',' : '');
          objPrefix += JSON.stringify(key) + ':';
          queue.push({obj: value, prefix: objPrefix});
        }
        queue.push({val: '{'});
      }
    }
    return res;
  };
  
  // Convenience function for the parse function.
  // This pop function is basically copied from
  // pouchCollate.parseIndexableString
  function pop(obj, stack, metaStack) {
    var lastMetaElement = metaStack[metaStack.length - 1];
    if (obj === lastMetaElement.element) {
      // popping a meta-element, e.g. an object whose value is another object
      metaStack.pop();
      lastMetaElement = metaStack[metaStack.length - 1];
    }
    var element = lastMetaElement.element;
    var lastElementIndex = lastMetaElement.index;
    if (Array.isArray(element)) {
      element.push(obj);
    } else if (lastElementIndex === stack.length - 2) { // obj with key+value
      var key = stack.pop();
      element[key] = obj;
    } else {
      stack.push(obj); // obj with key only
    }
  }
  
  exports.parse = function (str) {
    var stack = [];
    var metaStack = []; // stack for arrays and objects
    var i = 0;
    var collationIndex,parsedNum,numChar;
    var parsedString,lastCh,numConsecutiveSlashes,ch;
    var arrayElement, objElement;
    while (true) {
      collationIndex = str[i++];
      if (collationIndex === '}' ||
          collationIndex === ']' ||
          typeof collationIndex === 'undefined') {
        if (stack.length === 1) {
          return stack.pop();
        } else {
          pop(stack.pop(), stack, metaStack);
          continue;
        }
      }
      switch (collationIndex) {
        case ' ':
        case '\t':
        case '\n':
        case ':':
        case ',':
          break;
        case 'n':
          i += 3; // 'ull'
          pop(null, stack, metaStack);
          break;
        case 't':
          i += 3; // 'rue'
          pop(true, stack, metaStack);
          break;
        case 'f':
          i += 4; // 'alse'
          pop(false, stack, metaStack);
          break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '-':
          parsedNum = '';
          i--;
          while (true) {
            numChar = str[i++];
            if (/[\d\.\-e\+]/.test(numChar)) {
              parsedNum += numChar;
            } else {
              i--;
              break;
            }
          }
          pop(parseFloat(parsedNum), stack, metaStack);
          break;
        case '"':
          parsedString = '';
          lastCh = void 0;
          numConsecutiveSlashes = 0;
          while (true) {
            ch = str[i++];
            if (ch !== '"' || (lastCh === '\\' &&
                numConsecutiveSlashes % 2 === 1)) {
              parsedString += ch;
              lastCh = ch;
              if (lastCh === '\\') {
                numConsecutiveSlashes++;
              } else {
                numConsecutiveSlashes = 0;
              }
            } else {
              break;
            }
          }
          pop(JSON.parse('"' + parsedString + '"'), stack, metaStack);
          break;
        case '[':
          arrayElement = { element: [], index: stack.length };
          stack.push(arrayElement.element);
          metaStack.push(arrayElement);
          break;
        case '{':
          objElement = { element: {}, index: stack.length };
          stack.push(objElement.element);
          metaStack.push(objElement);
          break;
        default:
          throw new Error(
            'unexpectedly reached end of input: ' + collationIndex);
      }
    }
  };
  
  },{}]},{},[1]);
  