<commit_before>'use strict';
var util = require('util');
var fs = require('fs');
var _ = require('lodash');
var Channel = require('./channel');
var Exchange = require('./exchange');
var Message = require('./message');
var debug = require('./debug');
var definitions = require('./definitions');
var methods = definitions.methods;
var classes = definitions.classes;

var Queue = module.exports = function Queue (connection, channel, name, options, callback) {
  Channel.call(this, connection, channel);

  var self = this;
  this.name = name;
  this._bindings = {};
  this.consumerTagListeners = {};
  this.consumerTagOptions = {};

  // route messages to subscribers based on consumerTag
  this.on('rawMessage', function(message) {
    if (message.consumerTag && self.consumerTagListeners[message.consumerTag]) {
      self.consumerTagListeners[message.consumerTag](message);
    }
  });

  this.options = { autoDelete: true, closeChannelOnUnsubscribe: false };
  _.extend(this.options, options || {});

  this._openCallback = callback;
};
util.inherits(Queue, Channel);

Queue.prototype.subscribeRaw = function (options, messageListener) {
  var self = this;

  // multiple method signatures
  if (typeof options === "function") {
    messageListener = options;
    options = {};
  }

  var consumerTag = 'node-amqp-' + process.pid + '-' + Math.random();
  this.consumerTagListeners[consumerTag] = messageListener;

  options = options || {};
  options['state'] = 'opening';
  this.consumerTagOptions[consumerTag] = options;
  if (options.prefetchCount !== undefined) {
    self.connection._sendMethod(self.channel, methods.basicQos,
        { reserved1: 0
        , prefetchSize: 0
        , prefetchCount: options.prefetchCount
        , global: false
        });
  }

  return this._taskPush(methods.basicConsumeOk, function () {
    self.connection._sendMethod(self.channel, methods.basicConsume,
        { reserved1: 0
        , queue: self.name
        , consumerTag: consumerTag
        , noLocal: !!options.noLocal
        , noAck: !!options.noAck
        , exclusive: !!options.exclusive
        , noWait: false
        , "arguments": {}
        });
    self.consumerTagOptions[consumerTag]['state'] = 'open';
  });
};

Queue.prototype.unsubscribe = function(consumerTag) {
  var self = this;
  return this._taskPush(methods.basicCancelOk, function () {
    self.connection._sendMethod(self.channel, methods.basicCancel,
                                { reserved1: 0,
                                  consumerTag: consumerTag,
                                  noWait: false });
  })
  .addCallback(function () {
    if (self.options.closeChannelOnUnsubscribe) {
      self.close();
    }
    delete self.consumerTagListeners[consumerTag];
    delete self.consumerTagOptions[consumerTag];
  });
};

Queue.prototype.subscribe = function (options, messageListener) {
  var self = this;

  // Optional options
  if (typeof options === "function") {
    messageListener = options;
    options = {};
  }

  options = _.defaults(options || {}, {
    ack: false,
    prefetchCount: 1,
    routingKeyInPayload: self.connection.options.routingKeyInPayload,
    deliveryTagInPayload: self.connection.options.deliveryTagInPayload
  });

  // basic consume
  var rawOptions = {
      noAck: !options.ack,
      exclusive: options.exclusive
  };

  if (options.ack) {
    rawOptions['prefetchCount'] = options.prefetchCount;
  }

  return this.subscribeRaw(rawOptions, function (m) {
    var contentType = m.contentType;

    if (contentType == null && m.headers && m.headers.properties) {
      contentType = m.headers.properties.content_type;
    }

    var isJSON = contentType == 'text/json' ||
                 contentType == 'application/json';

    var buffer;

    if (isJSON) {
      buffer = "";
    } else {
      buffer = new Buffer(m.size);
      buffer.used = 0;
    }

    self._lastMessage = m;

    m.addListener('data', function (d) {
      if (isJSON) {
        buffer += d.toString();
      } else {
        d.copy(buffer, buffer.used);
        buffer.used += d.length;
      }
    });

    m.addListener('end', function () {
      var json, deliveryInfo = {}, msgProperties = classes[60].fields, i, l;

      if (isJSON) {
        try {
          json = JSON.parse(buffer);
        } catch (e) {
          json = null;
          deliveryInfo.parseError = e;
          deliveryInfo.rawData = buffer;
        }
      } else {
        json = { data: buffer, contentType: m.contentType };
      }

      for (i = 0, l = msgProperties.length; i<l; i++) {
        if (m[msgProperties[i].name]) {
          deliveryInfo[msgProperties[i].name] = m[msgProperties[i].name];
        }
      }

      deliveryInfo.queue = m.queue ? m.queue.name : null;
      deliveryInfo.deliveryTag = m.deliveryTag;
      deliveryInfo.redelivered = m.redelivered;
      deliveryInfo.exchange = m.exchange;
      deliveryInfo.routingKey = m.routingKey;
      deliveryInfo.consumerTag = m.consumerTag;

      if (options.routingKeyInPayload) json._routingKey = m.routingKey;
      if (options.deliveryTagInPayload) json._deliveryTag = m.deliveryTag;

      var headers = {};
      for (i in this.headers) {
        if (this.headers.hasOwnProperty(i)) {
          if (this.headers[i] instanceof Buffer) {
            headers[i] = this.headers[i].toString();
          } else {
            headers[i] = this.headers[i];
          }
        }
      }

      if (messageListener) messageListener(json, headers, deliveryInfo, m);
      self.emit('message', json, headers, deliveryInfo, m);
    });
  });
};
Queue.prototype.subscribeJSON = Queue.prototype.subscribe;

/* Acknowledges the last message */
Queue.prototype.shift = function (reject, requeue) {
  if (this._lastMessage) {
    if (reject) {
      this._lastMessage.reject(requeue ? true : false);
    } else {
      this._lastMessage.acknowledge();
    }
    this._lastMessage = null;
  }
};

Queue.prototype.bind = function (exchange, routingKey, callback) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the 'amq.topic'
  // exchange.
  if (routingKey === undefined || _.isFunction(routingKey)) {
    callback = routingKey;
    routingKey = exchange;
    exchange = 'amq.topic';
  }

  if (_.isFunction(callback)) this._bindCallback = callback;

  var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;

  if (exchangeName in self.connection.exchanges) {
    this.exchange = self.connection.exchanges[exchangeName];
    this.exchange.binds++;
  }

  // Record this binding so we can restore it upon reconnect.
  if (!this._bindings[exchangeName]) {
    this._bindings[exchangeName] = {};
  }

  if (!this._bindings[exchangeName][routingKey]) {
    this._bindings[exchangeName][routingKey] = 0;
  }

  this._bindings[exchangeName][routingKey]++;

  self.connection._sendMethod(self.channel, methods.queueBind,
      { reserved1: 0
      , queue: self.name
      , exchange: exchangeName
      , routingKey: routingKey
      , noWait: false
      , "arguments": {}
      });

};

Queue.prototype.unbind = function (exchange, routingKey) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.topic'
  // exchange.
  if (routingKey === undefined) {
    routingKey = exchange;
    exchange = 'amq.topic';
  }

  var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;

  // Decrement binding count.
  this._bindings[exchangeName][routingKey]--;
  if (!this._bindings[exchangeName][routingKey]) {
    delete this._bindings[exchangeName][routingKey];
  }

  // If there are no more bindings to this exchange, delete the key for the exchange.
  if (!_.keys(this._bindings[exchangeName]).length){
    delete this._bindings[exchangeName];
  }

  return this._taskPush(methods.queueUnbindOk, function () {
    self.connection._sendMethod(self.channel, methods.queueUnbind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: routingKey
        , noWait: false
        , "arguments": {}
        });
  });
};

Queue.prototype.bind_headers = function (/* [exchange,] matchingPairs */) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.headers'
  // exchange.

  var exchange, matchingPairs;

  if (arguments.length == 2) {
    exchange = arguments[0];
    matchingPairs = arguments[1];
  } else {
    exchange = 'amq.headers';
    matchingPairs = arguments[0];
  }

  return this._taskPush(methods.queueBindOk, function () {
    var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
    self.connection._sendMethod(self.channel, methods.queueBind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: ''
        , noWait: false
        , "arguments": matchingPairs
        });
  });
};

Queue.prototype.unbind_headers = function (/* [exchange,] matchingPairs */) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.topic'
  // exchange.

  var exchange, matchingPairs;

  if (arguments.length === 2) {
    exchange = arguments[0];
    matchingPairs = arguments[1];
  } else {
    exchange = 'amq.headers';
    matchingPairs = arguments[0];
  }

  return this._taskPush(methods.queueUnbindOk, function () {
    var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
    self.connection._sendMethod(self.channel, methods.queueUnbind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: ''
        , noWait: false
        , "arguments": matchingPairs
        });
  });
};

Queue.prototype.destroy = function (options) {
  var self = this;

  options = options || {};
  return this._taskPush(methods.queueDeleteOk, function () {
    self.connection.queueClosed(self.name);
    if ('exchange' in self) {
      self.exchange.binds--;
    }
    self.connection._sendMethod(self.channel, methods.queueDelete,
        { reserved1: 0
        , queue: self.name
        , ifUnused: options.ifUnused ? true : false
        , ifEmpty: options.ifEmpty ? true : false
        , noWait: false
        , "arguments": {}
    });
  });
};

Queue.prototype.purge = function() {
  var self = this;
  return this._taskPush(methods.queuePurgeOk, function () {
    self.connection._sendMethod(self.channel, methods.queuePurge,
                                 { reserved1 : 0,
                                 queue: self.name,
                                 noWait: false});
  });
};

Queue.prototype._onMethod = function (channel, method, args) {
  var self = this;
  this.emit(method.name, args);
  if (this._handleTaskReply.apply(this, arguments)) return;

  switch (method) {
    case methods.channelOpenOk:
      if (this.options.noDeclare) {
        this.state = 'open';

        if (this._openCallback) {
         this._openCallback(this);
         this._openCallback = null;
        }

        this.emit('open');
      } else {
        if (this.name.indexOf('amq.') == 0) {
          this.name = '';
        }
        this.connection._sendMethod(channel, methods.queueDeclare,
            { reserved1: 0
            , queue: this.name
            , passive: !!this.options.passive
            , durable: !!this.options.durable
            , exclusive: !!this.options.exclusive
            , autoDelete: !!this.options.autoDelete
            , noWait: false
            , "arguments": this.options.arguments || {}
            });
        this.state = "declare queue";
      }
      break;

    case methods.queueDeclareOk:
      this.state = 'open';
      this.name = args.queue;
      this.connection.queues[this.name] = this;

      // Rebind to previously bound exchanges, if present.
      // Important this is called *before* openCallback, otherwise bindings will happen twice.
      // Run test-purge to make sure you got this right
      _.each(this._bindings, function(exchange, exchangeName){
        _.each(exchange, function(count, routingKey){
          self.bind(exchangeName, routingKey);
        });
      });

      // Call opening callback (passed in function)
      // FIXME use eventemitter - maybe we call a namespaced event here
      if (this._openCallback) {
        this._openCallback(this, args.messageCount, args.consumerCount);
        this._openCallback = null;
      }

      // TODO this is legacy interface, remove me
      this.emit('open', args.queue, args.messageCount, args.consumerCount);

      // If this is a reconnect, we must re-subscribe our queue listeners.
      var consumerTags = Object.keys(this.consumerTagListeners);
      for (var index in consumerTags) {
        if (consumerTags.hasOwnProperty(index)) {
          if (this.consumerTagOptions[consumerTags[index]]['state'] === 'closed') {
            this.subscribeRaw(this.consumerTagOptions[consumerTags[index]], this.consumerTagListeners[consumerTags[index]]);
            // Having called subscribeRaw, we are now a new consumer with a new consumerTag.
            delete this.consumerTagListeners[consumerTags[index]];
            delete this.consumerTagOptions[consumerTags[index]];
          }
        }
      }
      break;

    case methods.basicConsumeOk:
      debug && debug('basicConsumeOk', util.inspect(args, null));
      break;

    case methods.queueBindOk:
      if (this._bindCallback) {
        // setting this._bindCallback to null before calling the callback allows for a subsequent bind within the callback
        // FIXME use eventemitter
        var cb = this._bindCallback;
        this._bindCallback = null;
        cb(this);
      }
      break;

    case methods.queueUnbindOk:
      break;

    case methods.basicQosOk:
      break;

    case methods.confirmSelectOk:
      this._sequence = 1;
      this.confirm = true;
      break;

    case methods.channelClose:
      this.state = "closed";
      this.closeOK();
      this.connection.queueClosed(this.name);
      var e = new Error(args.replyText);
      e.code = args.replyCode;
      this.emit('error', e);
      this.emit('close');
      break;

    case methods.channelCloseOk:
      this.connection.queueClosed(this.name);
      this.emit('close');
      break;

    case methods.basicDeliver:
      this.currentMessage = new Message(this, args);
      break;

    case methods.queueDeleteOk:
      break;

    case methods.basicCancel:
      this.close("Closed due to basicCancel received on consumer (" + args.consumerTag + ")");
      break;

    default:
      throw new Error("Uncaught method '" + method.name + "' with args " +
          JSON.stringify(args) + "; tasks = " + JSON.stringify(this._tasks));
  }

  this._tasksFlush();
};

Queue.prototype._onContentHeader = function (channel, classInfo, weight, properties, size) {
  _.extend(this.currentMessage, properties);
  this.currentMessage.read = 0;
  this.currentMessage.size = size;

  this.emit('rawMessage', this.currentMessage);
  if (size === 0) {
    // If the message has no body, directly emit 'end'
    this.currentMessage.emit('end');
  }
};

Queue.prototype._onContent = function (channel, data) {
  this.currentMessage.read += data.length;
  this.currentMessage.emit('data', data);
  if (this.currentMessage.read == this.currentMessage.size) {
    this.currentMessage.emit('end');
  }
};

Queue.prototype.flow = function(active) {
  var self = this;
  return this._taskPush(methods.channelFlowOk, function () {
    self.connection._sendMethod(self.channel, methods.channelFlow, {'active': active });
  });
};
<commit_msg>Fix issue with decoding long utf8 data<commit_after>'use strict';
var util = require('util');
var fs = require('fs');
var StringDecoder = require('string_decoder').StringDecoder;
var _ = require('lodash');
var Channel = require('./channel');
var Exchange = require('./exchange');
var Message = require('./message');
var debug = require('./debug');
var definitions = require('./definitions');
var methods = definitions.methods;
var classes = definitions.classes;

var Queue = module.exports = function Queue (connection, channel, name, options, callback) {
  Channel.call(this, connection, channel);

  var self = this;
  this.name = name;
  this._bindings = {};
  this.consumerTagListeners = {};
  this.consumerTagOptions = {};

  // route messages to subscribers based on consumerTag
  this.on('rawMessage', function(message) {
    if (message.consumerTag && self.consumerTagListeners[message.consumerTag]) {
      self.consumerTagListeners[message.consumerTag](message);
    }
  });

  this.options = { autoDelete: true, closeChannelOnUnsubscribe: false };
  _.extend(this.options, options || {});

  this._openCallback = callback;
};
util.inherits(Queue, Channel);

Queue.prototype.subscribeRaw = function (options, messageListener) {
  var self = this;

  // multiple method signatures
  if (typeof options === "function") {
    messageListener = options;
    options = {};
  }

  var consumerTag = 'node-amqp-' + process.pid + '-' + Math.random();
  this.consumerTagListeners[consumerTag] = messageListener;

  options = options || {};
  options['state'] = 'opening';
  this.consumerTagOptions[consumerTag] = options;
  if (options.prefetchCount !== undefined) {
    self.connection._sendMethod(self.channel, methods.basicQos,
        { reserved1: 0
        , prefetchSize: 0
        , prefetchCount: options.prefetchCount
        , global: false
        });
  }

  return this._taskPush(methods.basicConsumeOk, function () {
    self.connection._sendMethod(self.channel, methods.basicConsume,
        { reserved1: 0
        , queue: self.name
        , consumerTag: consumerTag
        , noLocal: !!options.noLocal
        , noAck: !!options.noAck
        , exclusive: !!options.exclusive
        , noWait: false
        , "arguments": {}
        });
    self.consumerTagOptions[consumerTag]['state'] = 'open';
  });
};

Queue.prototype.unsubscribe = function(consumerTag) {
  var self = this;
  return this._taskPush(methods.basicCancelOk, function () {
    self.connection._sendMethod(self.channel, methods.basicCancel,
                                { reserved1: 0,
                                  consumerTag: consumerTag,
                                  noWait: false });
  })
  .addCallback(function () {
    if (self.options.closeChannelOnUnsubscribe) {
      self.close();
    }
    delete self.consumerTagListeners[consumerTag];
    delete self.consumerTagOptions[consumerTag];
  });
};

Queue.prototype.subscribe = function (options, messageListener) {
  var self = this;

  // Optional options
  if (typeof options === "function") {
    messageListener = options;
    options = {};
  }

  options = _.defaults(options || {}, {
    ack: false,
    prefetchCount: 1,
    routingKeyInPayload: self.connection.options.routingKeyInPayload,
    deliveryTagInPayload: self.connection.options.deliveryTagInPayload
  });

  // basic consume
  var rawOptions = {
      noAck: !options.ack,
      exclusive: options.exclusive
  };

  if (options.ack) {
    rawOptions['prefetchCount'] = options.prefetchCount;
  }

  return this.subscribeRaw(rawOptions, function (m) {
    var contentType = m.contentType;
    var decoder = new StringDecoder('utf8');

    if (contentType == null && m.headers && m.headers.properties) {
      contentType = m.headers.properties.content_type;
    }

    var isJSON = contentType == 'text/json' ||
                 contentType == 'application/json';

    var buffer;

    if (isJSON) {
      buffer = "";
    } else {
      buffer = new Buffer(m.size);
      buffer.used = 0;
    }

    self._lastMessage = m;

    m.addListener('data', function (d) {
      if (isJSON) {
        buffer += decoder.write(d);
      } else {
        d.copy(buffer, buffer.used);
        buffer.used += d.length;
      }
    });

    m.addListener('end', function () {
      var json, deliveryInfo = {}, msgProperties = classes[60].fields, i, l;

      if (isJSON) {
        decoder.end();
        try {
          json = JSON.parse(buffer);
        } catch (e) {
          json = null;
          deliveryInfo.parseError = e;
          deliveryInfo.rawData = buffer;
        }
      } else {
        json = { data: buffer, contentType: m.contentType };
      }

      for (i = 0, l = msgProperties.length; i<l; i++) {
        if (m[msgProperties[i].name]) {
          deliveryInfo[msgProperties[i].name] = m[msgProperties[i].name];
        }
      }

      deliveryInfo.queue = m.queue ? m.queue.name : null;
      deliveryInfo.deliveryTag = m.deliveryTag;
      deliveryInfo.redelivered = m.redelivered;
      deliveryInfo.exchange = m.exchange;
      deliveryInfo.routingKey = m.routingKey;
      deliveryInfo.consumerTag = m.consumerTag;

      if (options.routingKeyInPayload) json._routingKey = m.routingKey;
      if (options.deliveryTagInPayload) json._deliveryTag = m.deliveryTag;

      var headers = {};
      for (i in this.headers) {
        if (this.headers.hasOwnProperty(i)) {
          if (this.headers[i] instanceof Buffer) {
            headers[i] = this.headers[i].toString();
          } else {
            headers[i] = this.headers[i];
          }
        }
      }

      if (messageListener) messageListener(json, headers, deliveryInfo, m);
      self.emit('message', json, headers, deliveryInfo, m);
    });
  });
};
Queue.prototype.subscribeJSON = Queue.prototype.subscribe;

/* Acknowledges the last message */
Queue.prototype.shift = function (reject, requeue) {
  if (this._lastMessage) {
    if (reject) {
      this._lastMessage.reject(requeue ? true : false);
    } else {
      this._lastMessage.acknowledge();
    }
    this._lastMessage = null;
  }
};

Queue.prototype.bind = function (exchange, routingKey, callback) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the 'amq.topic'
  // exchange.
  if (routingKey === undefined || _.isFunction(routingKey)) {
    callback = routingKey;
    routingKey = exchange;
    exchange = 'amq.topic';
  }

  if (_.isFunction(callback)) this._bindCallback = callback;

  var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;

  if (exchangeName in self.connection.exchanges) {
    this.exchange = self.connection.exchanges[exchangeName];
    this.exchange.binds++;
  }

  // Record this binding so we can restore it upon reconnect.
  if (!this._bindings[exchangeName]) {
    this._bindings[exchangeName] = {};
  }

  if (!this._bindings[exchangeName][routingKey]) {
    this._bindings[exchangeName][routingKey] = 0;
  }

  this._bindings[exchangeName][routingKey]++;

  self.connection._sendMethod(self.channel, methods.queueBind,
      { reserved1: 0
      , queue: self.name
      , exchange: exchangeName
      , routingKey: routingKey
      , noWait: false
      , "arguments": {}
      });

};

Queue.prototype.unbind = function (exchange, routingKey) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.topic'
  // exchange.
  if (routingKey === undefined) {
    routingKey = exchange;
    exchange = 'amq.topic';
  }

  var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;

  // Decrement binding count.
  this._bindings[exchangeName][routingKey]--;
  if (!this._bindings[exchangeName][routingKey]) {
    delete this._bindings[exchangeName][routingKey];
  }

  // If there are no more bindings to this exchange, delete the key for the exchange.
  if (!_.keys(this._bindings[exchangeName]).length){
    delete this._bindings[exchangeName];
  }

  return this._taskPush(methods.queueUnbindOk, function () {
    self.connection._sendMethod(self.channel, methods.queueUnbind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: routingKey
        , noWait: false
        , "arguments": {}
        });
  });
};

Queue.prototype.bind_headers = function (/* [exchange,] matchingPairs */) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.headers'
  // exchange.

  var exchange, matchingPairs;

  if (arguments.length == 2) {
    exchange = arguments[0];
    matchingPairs = arguments[1];
  } else {
    exchange = 'amq.headers';
    matchingPairs = arguments[0];
  }

  return this._taskPush(methods.queueBindOk, function () {
    var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
    self.connection._sendMethod(self.channel, methods.queueBind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: ''
        , noWait: false
        , "arguments": matchingPairs
        });
  });
};

Queue.prototype.unbind_headers = function (/* [exchange,] matchingPairs */) {
  var self = this;

  // The first argument, exchange is optional.
  // If not supplied the connection will use the default 'amq.topic'
  // exchange.

  var exchange, matchingPairs;

  if (arguments.length === 2) {
    exchange = arguments[0];
    matchingPairs = arguments[1];
  } else {
    exchange = 'amq.headers';
    matchingPairs = arguments[0];
  }

  return this._taskPush(methods.queueUnbindOk, function () {
    var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
    self.connection._sendMethod(self.channel, methods.queueUnbind,
        { reserved1: 0
        , queue: self.name
        , exchange: exchangeName
        , routingKey: ''
        , noWait: false
        , "arguments": matchingPairs
        });
  });
};

Queue.prototype.destroy = function (options) {
  var self = this;

  options = options || {};
  return this._taskPush(methods.queueDeleteOk, function () {
    self.connection.queueClosed(self.name);
    if ('exchange' in self) {
      self.exchange.binds--;
    }
    self.connection._sendMethod(self.channel, methods.queueDelete,
        { reserved1: 0
        , queue: self.name
        , ifUnused: options.ifUnused ? true : false
        , ifEmpty: options.ifEmpty ? true : false
        , noWait: false
        , "arguments": {}
    });
  });
};

Queue.prototype.purge = function() {
  var self = this;
  return this._taskPush(methods.queuePurgeOk, function () {
    self.connection._sendMethod(self.channel, methods.queuePurge,
                                 { reserved1 : 0,
                                 queue: self.name,
                                 noWait: false});
  });
};

Queue.prototype._onMethod = function (channel, method, args) {
  var self = this;
  this.emit(method.name, args);
  if (this._handleTaskReply.apply(this, arguments)) return;

  switch (method) {
    case methods.channelOpenOk:
      if (this.options.noDeclare) {
        this.state = 'open';

        if (this._openCallback) {
         this._openCallback(this);
         this._openCallback = null;
        }

        this.emit('open');
      } else {
        if (this.name.indexOf('amq.') == 0) {
          this.name = '';
        }
        this.connection._sendMethod(channel, methods.queueDeclare,
            { reserved1: 0
            , queue: this.name
            , passive: !!this.options.passive
            , durable: !!this.options.durable
            , exclusive: !!this.options.exclusive
            , autoDelete: !!this.options.autoDelete
            , noWait: false
            , "arguments": this.options.arguments || {}
            });
        this.state = "declare queue";
      }
      break;

    case methods.queueDeclareOk:
      this.state = 'open';
      this.name = args.queue;
      this.connection.queues[this.name] = this;

      // Rebind to previously bound exchanges, if present.
      // Important this is called *before* openCallback, otherwise bindings will happen twice.
      // Run test-purge to make sure you got this right
      _.each(this._bindings, function(exchange, exchangeName){
        _.each(exchange, function(count, routingKey){
          self.bind(exchangeName, routingKey);
        });
      });

      // Call opening callback (passed in function)
      // FIXME use eventemitter - maybe we call a namespaced event here
      if (this._openCallback) {
        this._openCallback(this, args.messageCount, args.consumerCount);
        this._openCallback = null;
      }

      // TODO this is legacy interface, remove me
      this.emit('open', args.queue, args.messageCount, args.consumerCount);

      // If this is a reconnect, we must re-subscribe our queue listeners.
      var consumerTags = Object.keys(this.consumerTagListeners);
      for (var index in consumerTags) {
        if (consumerTags.hasOwnProperty(index)) {
          if (this.consumerTagOptions[consumerTags[index]]['state'] === 'closed') {
            this.subscribeRaw(this.consumerTagOptions[consumerTags[index]], this.consumerTagListeners[consumerTags[index]]);
            // Having called subscribeRaw, we are now a new consumer with a new consumerTag.
            delete this.consumerTagListeners[consumerTags[index]];
            delete this.consumerTagOptions[consumerTags[index]];
          }
        }
      }
      break;

    case methods.basicConsumeOk:
      debug && debug('basicConsumeOk', util.inspect(args, null));
      break;

    case methods.queueBindOk:
      if (this._bindCallback) {
        // setting this._bindCallback to null before calling the callback allows for a subsequent bind within the callback
        // FIXME use eventemitter
        var cb = this._bindCallback;
        this._bindCallback = null;
        cb(this);
      }
      break;

    case methods.queueUnbindOk:
      break;

    case methods.basicQosOk:
      break;

    case methods.confirmSelectOk:
      this._sequence = 1;
      this.confirm = true;
      break;

    case methods.channelClose:
      this.state = "closed";
      this.closeOK();
      this.connection.queueClosed(this.name);
      var e = new Error(args.replyText);
      e.code = args.replyCode;
      this.emit('error', e);
      this.emit('close');
      break;

    case methods.channelCloseOk:
      this.connection.queueClosed(this.name);
      this.emit('close');
      break;

    case methods.basicDeliver:
      this.currentMessage = new Message(this, args);
      break;

    case methods.queueDeleteOk:
      break;

    case methods.basicCancel:
      this.close("Closed due to basicCancel received on consumer (" + args.consumerTag + ")");
      break;

    default:
      throw new Error("Uncaught method '" + method.name + "' with args " +
          JSON.stringify(args) + "; tasks = " + JSON.stringify(this._tasks));
  }

  this._tasksFlush();
};

Queue.prototype._onContentHeader = function (channel, classInfo, weight, properties, size) {
  _.extend(this.currentMessage, properties);
  this.currentMessage.read = 0;
  this.currentMessage.size = size;

  this.emit('rawMessage', this.currentMessage);
  if (size === 0) {
    // If the message has no body, directly emit 'end'
    this.currentMessage.emit('end');
  }
};

Queue.prototype._onContent = function (channel, data) {
  this.currentMessage.read += data.length;
  this.currentMessage.emit('data', data);
  if (this.currentMessage.read == this.currentMessage.size) {
    this.currentMessage.emit('end');
  }
};

Queue.prototype.flow = function(active) {
  var self = this;
  return this._taskPush(methods.channelFlowOk, function () {
    self.connection._sendMethod(self.channel, methods.channelFlow, {'active': active });
  });
};
<|endoftext|>


<commit_before>var $ = require('jquery');
var Element = require('./element');
var getEvtX = require('./evtx');
require('es5-shim');

var Range = Element.extend({
  initialize: function initialize(options) {
    var self = this;
    initialize.super$.call(this,
      '
'
    );
    this.options = options;
    this.parent = options.parent;

    if(this.options.rangeClass) this.$el.addClass(this.options.rangeClass);

    if(!this.options.readonly) {
      this.$el.prepend('
').append('
');
      this.on('mouseenter touchstart', $.proxy(this.removePhantom, this));
      this.on('mousedown touchstart', $.proxy(this.mousedown, this));
      this.on('click', $.proxy(this.click, this));
    } else {
      this.$el.addClass('elessar-readonly');
    }
    if(typeof this.options.label === 'function') {
      this.on('changing', function(ev, range) {
        self.$el.find('.elessar-barlabel').text(
          self.options.label.call(self, range.map($.proxy(self.parent.normalise, self.parent)))
        );
      });
    } else {
      this.$el.find('.elessar-barlabel').text(this.options.label);
    }

    this.range = [];
    this.hasChanged = false;

    if(this.options.value) this.val(this.options.value);

  },

  removePhantom: function() {
    this.parent.removePhantom();
  },

  val: function(range, valOpts) {

    if(typeof range === 'undefined') {
      return this.range;
    }

    valOpts  = $.extend({},{
      dontApplyDelta: false,
      trigger: true
    }, valOpts || {});

    var next = this.parent.nextRange(this.$el),
    prev = this.parent.prevRange(this.$el),
    delta = range[1] - range[0],
    self = this;

    if(this.options.snap) {
      range = range.map(snap);
      delta = snap(delta);
    }
    if (next && next.val()[0] <= range[1] && prev && prev.val()[1] >= range[0]) {
      range[1] = next.val()[0];
      range[0] = prev.val()[1];
    }
    if (next && next.val()[0] < range[1]) {
      range[1] = next.val()[0];
      if(!valOpts.dontApplyDelta) range[0] = range[1] - delta;
    }
    if (prev && prev.val()[1] > range[0]) {
      range[0] = prev.val()[1];
      if(!valOpts.dontApplyDelta) range[1] = range[0] + delta;
    }
    if (range[1] >= 1) {
      range[1] = 1;
      if(!valOpts.dontApplyDelta) range[0] = 1 - delta;
    }
    if (range[0] <= 0) {
      range[0] = 0;
      if(!valOpts.dontApplyDelta) range[1] = delta;
    }

    if(this.options.minSize && range[1] - range[0] < this.options.minSize) {
      range[1] = range[0] + this.options.minSize;
    }

    if(this.range[0] === range[0] && this.range[1] === range[1]) return this.$el;

    this.range = range;
    if(valOpts.trigger) {
      this.$el.triggerHandler('changing', [range, this.$el]);
      hasChanged = true;
    }

    this.draw({
      left: 100*range[0] + '%',
      minWidth: 100*(range[1] - range[0]) + '%'
    });

    return this;

    function snap(val) { return Math.round(val / self.options.snap) * self.options.snap; }
    function sign(x)   { return x ? x < 0 ? -1 : 1 : 0; }
  },

  click: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();

    var self = this;

    if(ev.which !== 2 || !this.parent.options.allowDelete) return;

    if(this.deleteConfirm) {
      this.parent.removeRange(this);
      clearTimeout(this.deleteTimeout);
    } else {
      this.$el.addClass('elessar-delete-confirm');
      this.deleteConfirm = true;

      this.deleteTimeout = setTimeout(function() {
        self.$el.removeClass('elessar-delete-confirm');
        self.deleteConfirm = false;
      }, this.parent.options.deleteTimeout);
    }
  },

  mousedown: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();
    this.hasChanged = false;
    if(ev.which > 1) return;

    if ($(ev.target).is('.elessar-handle:first-child')) {
      $('body').addClass('elessar-resizing');
      $(document).on('mousemove touchmove', this.resizeLeft(ev));
    } else if ($(ev.target).is('.elessar-handle:last-child')) {
      $('body').addClass('elessar-resizing');
      $(document).on('mousemove touchmove', this.resizeRight(ev));
    } else {
      $('body').addClass('elessar-dragging');
      $(document).on('mousemove touchmove', this.drag(ev));
    }

    var self = this;

    $(document).on('mouseup touchend', function(ev) {
      ev.stopPropagation();
      ev.preventDefault();

      if(self.hasChanged) self.trigger('change', [self.range, self.$el]);
      $(document).off('mouseup mousemove touchend touchmove');
      $('body').removeClass('elessar-resizing elessar-dragging');
    });
  },

  drag: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width();

    return function(ev) {
      ev.stopPropagation();
      ev.preventDefault();
      var left = getEvtX('clientX', ev) - parentOffset.left - mouseOffset;

      if (left >= 0 && left <= parentWidth - startWidth) {
        var rangeOffset = left / parentWidth - self.range[0];
        self.val([left / parentWidth, self.range[1] + rangeOffset]);
      } else {
        mouseOffset = getEvtX('clientX', ev) - self.$el.offset().left;
      }
    };
  },

  resizeRight: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width(),
    minWidth = this.options.minSize * parentWidth;

    return function(ev) {
      var opposite = ev.type === 'touchmove' ? 'touchend' : 'mouseup',
      subsequent = ev.type === 'touchmove' ? 'touchstart' : 'mousedown';

      ev.stopPropagation();
      ev.preventDefault();
      var width = getEvtX('clientX', ev) - startLeft;

      if (width > parentWidth - startPosLeft) width = parentWidth - startPosLeft;
      if (width >= minWidth) {
        self.val([self.range[0], self.range[0] + width / parentWidth], {dontApplyDelta: true});
      } else if(width <= 10) {
        $(document).trigger(opposite);
        self.$el.find('.elessar-handle:first-child').trigger(subsequent);
      }
    };
  },

  resizeLeft: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width(),
    minWidth = this.options.minSize * parentWidth;

    return function(ev) {
      var opposite = ev.type === 'touchmove' ? 'touchend' : 'mouseup',
      subsequent = ev.type === 'touchmove' ? 'touchstart' : 'mousedown';

      ev.stopPropagation();
      ev.preventDefault();
      var left = getEvtX('clientX', ev) - parentOffset.left - mouseOffset;
      var width = startPosLeft + startWidth - left;

      if (left < 0) {
        left = 0;
        width = startPosLeft + startWidth;
      }
      if (width >= minWidth) {
        self.val([left / parentWidth, self.range[1]], {dontApplyDelta: true});
      } else if(width <= 10) {
        $(document).trigger(opposite);
        self.$el.find('.elessar-handle:last-child').trigger(subsequent);
      }
    };
  }
});

module.exports = Range;
<commit_msg>fix haschanged<commit_after>var $ = require('jquery');
var Element = require('./element');
var getEvtX = require('./evtx');
require('es5-shim');

var Range = Element.extend({
  initialize: function initialize(options) {
    var self = this;
    initialize.super$.call(this,
      '
'
    );
    this.options = options;
    this.parent = options.parent;

    if(this.options.rangeClass) this.$el.addClass(this.options.rangeClass);

    if(!this.options.readonly) {
      this.$el.prepend('
').append('
');
      this.on('mouseenter touchstart', $.proxy(this.removePhantom, this));
      this.on('mousedown touchstart', $.proxy(this.mousedown, this));
      this.on('click', $.proxy(this.click, this));
    } else {
      this.$el.addClass('elessar-readonly');
    }
    if(typeof this.options.label === 'function') {
      this.on('changing', function(ev, range) {
        self.$el.find('.elessar-barlabel').text(
          self.options.label.call(self, range.map($.proxy(self.parent.normalise, self.parent)))
        );
      });
    } else {
      this.$el.find('.elessar-barlabel').text(this.options.label);
    }

    this.range = [];
    this.hasChanged = false;

    if(this.options.value) this.val(this.options.value);

  },

  removePhantom: function() {
    this.parent.removePhantom();
  },

  val: function(range, valOpts) {

    if(typeof range === 'undefined') {
      return this.range;
    }

    valOpts  = $.extend({},{
      dontApplyDelta: false,
      trigger: true
    }, valOpts || {});

    var next = this.parent.nextRange(this.$el),
    prev = this.parent.prevRange(this.$el),
    delta = range[1] - range[0],
    self = this;

    if(this.options.snap) {
      range = range.map(snap);
      delta = snap(delta);
    }
    if (next && next.val()[0] <= range[1] && prev && prev.val()[1] >= range[0]) {
      range[1] = next.val()[0];
      range[0] = prev.val()[1];
    }
    if (next && next.val()[0] < range[1]) {
      range[1] = next.val()[0];
      if(!valOpts.dontApplyDelta) range[0] = range[1] - delta;
    }
    if (prev && prev.val()[1] > range[0]) {
      range[0] = prev.val()[1];
      if(!valOpts.dontApplyDelta) range[1] = range[0] + delta;
    }
    if (range[1] >= 1) {
      range[1] = 1;
      if(!valOpts.dontApplyDelta) range[0] = 1 - delta;
    }
    if (range[0] <= 0) {
      range[0] = 0;
      if(!valOpts.dontApplyDelta) range[1] = delta;
    }

    if(this.options.minSize && range[1] - range[0] < this.options.minSize) {
      range[1] = range[0] + this.options.minSize;
    }

    if(this.range[0] === range[0] && this.range[1] === range[1]) return this.$el;

    this.range = range;
    if(valOpts.trigger) {
      this.$el.triggerHandler('changing', [range, this.$el]);
      this.hasChanged = true;
    }

    this.draw({
      left: 100*range[0] + '%',
      minWidth: 100*(range[1] - range[0]) + '%'
    });

    return this;

    function snap(val) { return Math.round(val / self.options.snap) * self.options.snap; }
    function sign(x)   { return x ? x < 0 ? -1 : 1 : 0; }
  },

  click: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();

    var self = this;

    if(ev.which !== 2 || !this.parent.options.allowDelete) return;

    if(this.deleteConfirm) {
      this.parent.removeRange(this);
      clearTimeout(this.deleteTimeout);
    } else {
      this.$el.addClass('elessar-delete-confirm');
      this.deleteConfirm = true;

      this.deleteTimeout = setTimeout(function() {
        self.$el.removeClass('elessar-delete-confirm');
        self.deleteConfirm = false;
      }, this.parent.options.deleteTimeout);
    }
  },

  mousedown: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();
    this.hasChanged = false;
    if(ev.which > 1) return;

    if ($(ev.target).is('.elessar-handle:first-child')) {
      $('body').addClass('elessar-resizing');
      $(document).on('mousemove touchmove', this.resizeLeft(ev));
    } else if ($(ev.target).is('.elessar-handle:last-child')) {
      $('body').addClass('elessar-resizing');
      $(document).on('mousemove touchmove', this.resizeRight(ev));
    } else {
      $('body').addClass('elessar-dragging');
      $(document).on('mousemove touchmove', this.drag(ev));
    }

    var self = this;

    $(document).on('mouseup touchend', function(ev) {
      ev.stopPropagation();
      ev.preventDefault();

      if(self.hasChanged) self.trigger('change', [self.range, self.$el]);
      $(document).off('mouseup mousemove touchend touchmove');
      $('body').removeClass('elessar-resizing elessar-dragging');
    });
  },

  drag: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width();

    return function(ev) {
      ev.stopPropagation();
      ev.preventDefault();
      var left = getEvtX('clientX', ev) - parentOffset.left - mouseOffset;

      if (left >= 0 && left <= parentWidth - startWidth) {
        var rangeOffset = left / parentWidth - self.range[0];
        self.val([left / parentWidth, self.range[1] + rangeOffset]);
      } else {
        mouseOffset = getEvtX('clientX', ev) - self.$el.offset().left;
      }
    };
  },

  resizeRight: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width(),
    minWidth = this.options.minSize * parentWidth;

    return function(ev) {
      var opposite = ev.type === 'touchmove' ? 'touchend' : 'mouseup',
      subsequent = ev.type === 'touchmove' ? 'touchstart' : 'mousedown';

      ev.stopPropagation();
      ev.preventDefault();
      var width = getEvtX('clientX', ev) - startLeft;

      if (width > parentWidth - startPosLeft) width = parentWidth - startPosLeft;
      if (width >= minWidth) {
        self.val([self.range[0], self.range[0] + width / parentWidth], {dontApplyDelta: true});
      } else if(width <= 10) {
        $(document).trigger(opposite);
        self.$el.find('.elessar-handle:first-child').trigger(subsequent);
      }
    };
  },

  resizeLeft: function(origEv) {
    var self = this,
    startLeft = this.$el.offset().left,
    startPosLeft = this.$el.position().left,
    mouseOffset = getEvtX('clientX', origEv) ? getEvtX('clientX', origEv) - this.$el.offset().left : 0,
    startWidth = this.$el.width(),
    parent = this.options.parent,
    parentOffset = parent.$el.offset(),
    parentWidth = parent.$el.width(),
    minWidth = this.options.minSize * parentWidth;

    return function(ev) {
      var opposite = ev.type === 'touchmove' ? 'touchend' : 'mouseup',
      subsequent = ev.type === 'touchmove' ? 'touchstart' : 'mousedown';

      ev.stopPropagation();
      ev.preventDefault();
      var left = getEvtX('clientX', ev) - parentOffset.left - mouseOffset;
      var width = startPosLeft + startWidth - left;

      if (left < 0) {
        left = 0;
        width = startPosLeft + startWidth;
      }
      if (width >= minWidth) {
        self.val([left / parentWidth, self.range[1]], {dontApplyDelta: true});
      } else if(width <= 10) {
        $(document).trigger(opposite);
        self.$el.find('.elessar-handle:last-child').trigger(subsequent);
      }
    };
  }
});

module.exports = Range;
<|endoftext|>


<commit_before>var config = require(__dirname + '/../config.js');
var utils  = require(__dirname + '/../utils.js');
var market  = require(__dirname + '/markets/markets.js');

var request = function(url, callback) {
   var request = require("request");
   request(url, function(error, response, body){
      if (error) {
         console.log(error);
         callback(error);
      }
      else {
         var data = JSON.parse(body);
         callback(null, data);
      }
   });
};
exports.request = request;

var addAid = function(rates, mysqlconnection, callback){
   var async = require('async');
   async.eachOfLimit(rates, 1, function(item, key, cb){
      var pair = market.splitPair(item.pair);
      market.getAssetId(pair, mysqlconnection, function(e, row){
         if (e) {
            callback(e);
         }
         else {
            rates[key].aid = row[0].aid;
         }
         cb();
      });
      // after all asset ids are added
   }, function(err){
      callback(null, rates, mysqlconnection);
   });
};
exports.addAid = addAid;

var toDb = function(rates, mysqlconnection, callback){
   var cols = [];
   let pair = new market.pair();
   for (let colName in pair) {
      cols.push(colName);
   }

   var insert = [];
   for (let i in rates) {
      let val = [];
      for (let s in rates[i]) {
         val.push("'" + rates[i][s] + "'");
      }
      insert.push('('+val.join(',')+')');
   }
   var query = 'INSERT INTO rates ('+cols.join(',')+') VALUES ' + insert.join(',');
   if (config.dev) console.log(query);
   mysqlconnection.query(query, function(e) {
      if(e) callback(e)
      else callback(null, rates);
   });
};
exports.toDb = toDb;

var all = function(mode, mysqlconnection, callback) {
   var async = require('async');
   var polo = require(__dirname + '/markets/poloniex.js');
   var bitstamp = require(__dirname + '/markets/bitstamp.js');
   async.parallel({
      poloniex: function(callback) {
         polo.ratesGet(mode, mysqlconnection, function(e, rates) {
            callback(null, rates);
         });
      },
      bitstamp: function(callback) {
         bitstamp.ratesGet(mode, mysqlconnection, function(e, rates) {
            callback(null, rates);
         });
      }
   }, function(e, rates) {
      // TODO: Error handler
      let mergedRates = [];
      for (let i in rates) {
         for (let r in rates[i]) {
            mergedRates.push(rates[i][r]);
         }
      }
      callback(null, mergedRates);
   });
};
exports.all = all;<commit_msg>manual xrb rate<commit_after>var config = require(__dirname + '/../config.js');
var utils  = require(__dirname + '/../utils.js');
var market  = require(__dirname + '/markets/markets.js');

var request = function(url, callback) {
   var request = require("request");
   request(url, function(error, response, body){
      if (error) {
         console.log(error);
         callback(error);
      }
      else {
         var data = JSON.parse(body);
         callback(null, data);
      }
   });
};
exports.request = request;

var addAid = function(rates, mysqlconnection, callback){
   var async = require('async');
   async.eachOfLimit(rates, 1, function(item, key, cb){
      var pair = market.splitPair(item.pair);
      market.getAssetId(pair, mysqlconnection, function(e, row){
         if (e) {
            callback(e);
         }
         else {
            rates[key].aid = row[0].aid;
         }
         cb();
      });
      // after all asset ids are added
   }, function(err){
      callback(null, rates, mysqlconnection);
   });
};
exports.addAid = addAid;

var toDb = function(rates, mysqlconnection, callback){
   var cols = [];
   let pair = new market.pair();
   for (let colName in pair) {
      cols.push(colName);
   }

   var insert = [];
   for (let i in rates) {
      let val = [];
      for (let s in rates[i]) {
         val.push("'" + rates[i][s] + "'");
      }
      insert.push('('+val.join(',')+')');
   }
   var query = 'INSERT INTO rates ('+cols.join(',')+') VALUES ' + insert.join(',');
   if (config.dev) console.log(query);
   mysqlconnection.query(query, function(e) {
      if(e) callback(e)
      else callback(null, rates);
   });
};
exports.toDb = toDb;

var all = function(mode, mysqlconnection, callback) {
   var async = require('async');
   var polo = require(__dirname + '/markets/poloniex.js');
   var bitstamp = require(__dirname + '/markets/bitstamp.js');
   async.parallel({
      poloniex: function(callback) {
         polo.ratesGet(mode, mysqlconnection, function(e, rates) {
            callback(null, rates);
         });
      },
      bitstamp: function(callback) {
         bitstamp.ratesGet(mode, mysqlconnection, function(e, rates) {
            callback(null, rates);
         });
      }
   }, function(e, rates) {
      // TODO: Error handler
      let mergedRates = [];
      for (let i in rates) {
         for (let r in rates[i]) {
            mergedRates.push(rates[i][r]);
         }
      }
      mrgedRates.push({aid:133,pair:'BTC_XRB',mid:6,cid:14,last:0.0000585});
      callback(null, mergedRates);
   });
};
exports.all = all;<|endoftext|>


<commit_before>if (window.React) {
  module.exports = window.React;
} else {
  module.exports = require('react');
}<commit_msg>Test for existance of window<commit_after>if (typeof window !== 'undefined' && window.React) {
  module.exports = window.React;
} else {
  module.exports = require('react');
}<|endoftext|>


<commit_before>"use strict";

function regen(reg) {
    var _patterns = [];

    function strRepeat(s, num) {
	return new Array(num + 1).join(s);
    }

    function exit(msg) {
	console.log("Invalid regex: " + msg);
	process.exit();
    }

    function doRepeat(builder, sub, outStr) {
	var reg_repeat = parseRepeat(builder, sub);
	if (reg_repeat > 0) {
	    for (var it = 0; it < reg_repeat; it++)
		builder.out += outStr();
	} else
	    builder.out += strRepeat(outStr(), -reg_repeat);
    }

    function parseRegex(reg, checkPatterns) {
	if (checkPatterns == undefined)
	    checkPatterns = true;
	var tab = explodeRegex(reg);
	reg = tab[Math.floor(Math.random() * tab.length)];
	var builder = {reg:reg, out:"", i:0, escaped:false};
	while (builder.i < reg.length) {
	    var i = builder.i;
	    if (!builder.escaped && reg[i] == '[')
		parsePool(builder);
	    else if (!builder.escaped && reg[i] == '(') {
		var end = getClosingIdx(builder.reg, i + 1, ')', true);
		end == -1 && exit("Closing character ')' not found");
		checkPatterns && _patterns.push(reg.substring(i + 1, end));
		builder.i = end + 1;
		doRepeat(builder, builder.reg.substr(end + 1), function() {
		    return (parseRegex(reg.substr(i + 1, end - i - 1)));
		});
	    } else if (!builder.escaped && reg[i] == '.') {
		builder.i++;
		doRepeat(builder, builder.reg.substr(builder.i), function() {
		    return (String.fromCharCode(Math.floor(Math.random() * 95) + 32));
		});
	    } else if (builder.escaped && "123456789".indexOf(reg[i]) != -1) {
		builder.i++;
		builder.escaped = false;
		if (parseInt(reg[i]) - 1 < _patterns.length) {
		    doRepeat(builder, builder.reg.substr(i + 1), function() {
			return (parseRegex(_patterns[parseInt(reg[i]) - 1], false));
		    });
		} else
		    exit("the back reference '\\" + reg[i] + "' doesn't exist");
	    } else {
		if (/[^\\]/.test(reg[i]) || builder.escaped)
		    builder.out += strRepeat(reg[i], Math.abs(parseRepeat(builder, reg.substr(i + 1))));
		builder.escaped = (!builder.escaped && reg[i] == '\\');
		builder.i++;
	    }
	}
	return (builder.out);
    }

    function explodeRegex(reg) {
	var regxtab = [];
	var found = 0;
	var beg = 0;
	while (found != -1) {
	    found = getClosingIdx(reg, beg, '|', true);
	    if (found == -1)
		regxtab.push(reg.substr(beg));
	    else
		regxtab.push(reg.substr(beg, found - beg));
	    beg = found + 1;
	}
	return (regxtab);
    }

    function getClosingIdx(str, i, ch, isregex) {
	var escaped = false;
	while (escaped || str[i] != ch) {
	    if (!str[i])
		return (-1);
	    if (isregex && !escaped) {
		var closing = str[i] == '[' ? ']' : ')';
		if (str[i] == '[' || str[i] == '(')
		    i = getClosingIdx(str, i + 1, closing, str[i] == '(');
		i == -1 && exit("Closing character '" + closing + "' not found");
	    }
	    escaped = (!escaped && str[i] == '\\');
	    i++;
	}
	return (i);
    }

    function parsePool(builder) {
	var pool = "";
	builder.i++;
	builder.escaped = false;
	while (builder.escaped || builder.reg[builder.i] != ']') {
	    builder.i >= builder.reg.length && exit("missing ']'");
	    if (builder.escaped || builder.reg[builder.i] != '\\') {
		var match = /^([a-zA-Z0-9])-([a-zA-Z0-9])/.exec(builder.reg.substr(builder.i));
		if (match) {
		    var a = match[1].charCodeAt(0);
		    var b = match[2].charCodeAt(0);
		    a > b && exit("Invalid character range in pool");
		    for (var it = a; it <= b; it++)
			pool += String.fromCharCode(it);
		    builder.i += 2;
		} else {
		    pool += builder.reg[builder.i];
		}
	    }
	    builder.escaped = (!builder.escaped && builder.reg[builder.i] == '\\');
	    builder.i++;
	}
	builder.i++;
	doRepeat(builder, builder.reg.substr(builder.i), function() {
	    return (pool[Math.floor(Math.random() * pool.length)]);
	});
    }

    function parseRepeat(builder, str) {
	if (str[0] == '?') {
	    builder.i++;
	    return (Math.round(Math.random()));
	}
	if (str[0] != '{')
	    return (1);
	var offset = str.search('}') + 1;
	var mult = str[1] == ':' ? -1 : 1;
	str = str.substr((str[1] == ':') + 1);
	var res = /^([0-9]*),?([0-9]*)}/.exec(str);
	(!res || (!res[1] && !res[2])) && exit("bad repeater format");
	var a = parseInt(res[1], 10);
	var b = parseInt(res[2], 10);
	((isNaN(a) && isNaN(b)) || a > b || a < 0 || b < 0) && exit("bad numbers in repeater: " + res[1] + ", " + res[2]);
	builder.i += offset;
	if (a && isNaN(b))
	    return (mult * a);
	if (isNaN(a) && b)
	    return (mult * Math.floor(Math.random() * (b + 1)));
	return (mult * (Math.floor(Math.random() * (b - a + 1)) + a));
    }

    return (parseRegex(reg));
}

if (typeof module !== 'undefined' && module.exports)
    module.exports = regen;
<commit_msg>fix: using stderr for errors<commit_after>"use strict";

function regen(reg) {
    var _patterns = [];

    function strRepeat(s, num) {
	return new Array(num + 1).join(s);
    }

    function exit(msg) {
	console.error("Invalid regex: " + msg);
	process.exit();
    }

    function doRepeat(builder, sub, outStr) {
	var reg_repeat = parseRepeat(builder, sub);
	if (reg_repeat > 0) {
	    for (var it = 0; it < reg_repeat; it++)
		builder.out += outStr();
	} else
	    builder.out += strRepeat(outStr(), -reg_repeat);
    }

    function parseRegex(reg, checkPatterns) {
	if (checkPatterns == undefined)
	    checkPatterns = true;
	var tab = explodeRegex(reg);
	reg = tab[Math.floor(Math.random() * tab.length)];
	var builder = {reg:reg, out:"", i:0, escaped:false};
	while (builder.i < reg.length) {
	    var i = builder.i;
	    if (!builder.escaped && reg[i] == '[')
		parsePool(builder);
	    else if (!builder.escaped && reg[i] == '(') {
		var end = getClosingIdx(builder.reg, i + 1, ')', true);
		end == -1 && exit("Closing character ')' not found");
		checkPatterns && _patterns.push(reg.substring(i + 1, end));
		builder.i = end + 1;
		doRepeat(builder, builder.reg.substr(end + 1), function() {
		    return (parseRegex(reg.substr(i + 1, end - i - 1)));
		});
	    } else if (!builder.escaped && reg[i] == '.') {
		builder.i++;
		doRepeat(builder, builder.reg.substr(builder.i), function() {
		    return (String.fromCharCode(Math.floor(Math.random() * 95) + 32));
		});
	    } else if (builder.escaped && "123456789".indexOf(reg[i]) != -1) {
		builder.i++;
		builder.escaped = false;
		if (parseInt(reg[i]) - 1 < _patterns.length) {
		    doRepeat(builder, builder.reg.substr(i + 1), function() {
			return (parseRegex(_patterns[parseInt(reg[i]) - 1], false));
		    });
		} else
		    exit("the back reference '\\" + reg[i] + "' doesn't exist");
	    } else {
		if (/[^\\]/.test(reg[i]) || builder.escaped)
		    builder.out += strRepeat(reg[i], Math.abs(parseRepeat(builder, reg.substr(i + 1))));
		builder.escaped = (!builder.escaped && reg[i] == '\\');
		builder.i++;
	    }
	}
	return (builder.out);
    }

    function explodeRegex(reg) {
	var regxtab = [];
	var found = 0;
	var beg = 0;
	while (found != -1) {
	    found = getClosingIdx(reg, beg, '|', true);
	    if (found == -1)
		regxtab.push(reg.substr(beg));
	    else
		regxtab.push(reg.substr(beg, found - beg));
	    beg = found + 1;
	}
	return (regxtab);
    }

    function getClosingIdx(str, i, ch, isregex) {
	var escaped = false;
	while (escaped || str[i] != ch) {
	    if (!str[i])
		return (-1);
	    if (isregex && !escaped) {
		var closing = str[i] == '[' ? ']' : ')';
		if (str[i] == '[' || str[i] == '(')
		    i = getClosingIdx(str, i + 1, closing, str[i] == '(');
		i == -1 && exit("Closing character '" + closing + "' not found");
	    }
	    escaped = (!escaped && str[i] == '\\');
	    i++;
	}
	return (i);
    }

    function parsePool(builder) {
	var pool = "";
	builder.i++;
	builder.escaped = false;
	while (builder.escaped || builder.reg[builder.i] != ']') {
	    builder.i >= builder.reg.length && exit("missing ']'");
	    if (builder.escaped || builder.reg[builder.i] != '\\') {
		var match = /^([a-zA-Z0-9])-([a-zA-Z0-9])/.exec(builder.reg.substr(builder.i));
		if (match) {
		    var a = match[1].charCodeAt(0);
		    var b = match[2].charCodeAt(0);
		    a > b && exit("Invalid character range in pool");
		    for (var it = a; it <= b; it++)
			pool += String.fromCharCode(it);
		    builder.i += 2;
		} else {
		    pool += builder.reg[builder.i];
		}
	    }
	    builder.escaped = (!builder.escaped && builder.reg[builder.i] == '\\');
	    builder.i++;
	}
	builder.i++;
	doRepeat(builder, builder.reg.substr(builder.i), function() {
	    return (pool[Math.floor(Math.random() * pool.length)]);
	});
    }

    function parseRepeat(builder, str) {
	if (str[0] == '?') {
	    builder.i++;
	    return (Math.round(Math.random()));
	}
	if (str[0] != '{')
	    return (1);
	var offset = str.search('}') + 1;
	var mult = str[1] == ':' ? -1 : 1;
	str = str.substr((str[1] == ':') + 1);
	var res = /^([0-9]*),?([0-9]*)}/.exec(str);
	(!res || (!res[1] && !res[2])) && exit("bad repeater format");
	var a = parseInt(res[1], 10);
	var b = parseInt(res[2], 10);
	((isNaN(a) && isNaN(b)) || a > b || a < 0 || b < 0) && exit("bad numbers in repeater: " + res[1] + ", " + res[2]);
	builder.i += offset;
	if (a && isNaN(b))
	    return (mult * a);
	if (isNaN(a) && b)
	    return (mult * Math.floor(Math.random() * (b + 1)));
	return (mult * (Math.floor(Math.random() * (b - a + 1)) + a));
    }

    return (parseRegex(reg));
}

if (typeof module !== 'undefined' && module.exports)
    module.exports = regen;
<|endoftext|>


<commit_before>var gpio = require('gpio');
var gpioArr = [];

function Init(){
  var allPins = [3, 5, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 35, 36, 37, 38, 40];

  allPins.forEach(function (el, index, array) {

    gpioArr[p] = gpio.export(el, {
      // When you export a pin, the default direction is out. This allows you to set
      // the pin value to either LOW or HIGH (3.3V) from your program.
      direction: 'out',

      // set the time interval (ms) between each read when watching for value changes
      // note: this is default to 100, setting value too low will cause high CPU usage
      interval: 200,

      // Due to the asynchronous nature of exporting a header, you may not be able to
      // read or write to the header right away. Place your logic in this ready
      // function to guarantee everything will get fired properly
      ready: function() {
        gpioArr[p].set(1);
      }
    });
  }
}

function Relay(p, v) {

  console.log('Set ', p, v);
  gpioArr[p].set(v);
}

module.exports.Init = Init;
module.exports.Relay = Relay;<commit_msg>submit<commit_after>var gpio = require('gpio');
var gpioArr = [];

function Init(){
  var allPins = [3, 5, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 35, 36, 37, 38, 40];

  allPins.forEach(function (el, index, array) {

    gpioArr[p] = gpio.export(el, {
      // When you export a pin, the default direction is out. This allows you to set
      // the pin value to either LOW or HIGH (3.3V) from your program.
      direction: 'out',

      // set the time interval (ms) between each read when watching for value changes
      // note: this is default to 100, setting value too low will cause high CPU usage
      interval: 200,

      // Due to the asynchronous nature of exporting a header, you may not be able to
      // read or write to the header right away. Place your logic in this ready
      // function to guarantee everything will get fired properly
      ready: function() {
        gpioArr[p].set(1);
      }
    });
  });
}

function Relay(p, v) {

  console.log('Set ', p, v);
  gpioArr[p].set(v);
}

module.exports.Init = Init;
module.exports.Relay = Relay;<|endoftext|>


<commit_before>'use strict';

var Remdb = function() {
    this._db = {};
};

// Basic API
Remdb.prototype.SET = (key, value) => {
    this._db[key] = value;
};

Remdb.prototype.GET = key => {
    return this._db[key] || 'NULL';
};

Remdb.prototype.UNSET = key => {
    // TODO
};

Remdb.prototype.NUMEQUALTO = value => {
    // TODO
};

Remdb.prototype.BEGIN = _ => {
    // TODO
};

Remdb.prototype.ROLLBACK = _ => {
    // TODO
};

Remdb.prototype.COMMIT = _ => {
    // TODO
};

module.exports = new Remdb();
<commit_msg>NUMEQUALTO support; needs runtime improvement with BST.<commit_after>'use strict';

var Remdb = () => {
    this._db = {};

    // TODO: Store in BST? For NUMEQUALTO
};

// Basic API
Remdb.prototype.SET = (key, value) => {
    this._db[key] = value;
};

Remdb.prototype.GET = key => {
    return this._db[key] || 'NULL';
};

Remdb.prototype.UNSET = key => {
    delete this._db[key];
};

// O(n)
// TODO: Improve by storing value also in a binary tree.
Remdb.prototype.NUMEQUALTO = value => {
    var numEqualTo = 0;
    for (var key in this._db) {
        if (this._db[key] === value) {
            numEqualTo++;
        }
    }
    return numEqualTo;
};

Remdb.prototype.BEGIN = () => {
    // TODO
};

Remdb.prototype.ROLLBACK = () => {
    // TODO
};

Remdb.prototype.COMMIT = () => {
    // TODO
};

module.exports = new Remdb();
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Scott Beck, all rights reserved
 *
 * Licensed under the MIT license
 *
 */
(function () {
  'use strict';
  var _ = require("lodash");
  function genguid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
  }
  function ReMix(namespace) {
    var args = _.flatten(_.toArray(arguments));
    if (_.isString(namespace) || _.isNull(namespace) || _.isUndefined(namespace))
      args = args.slice(1);
    else
      namespace = undefined;
    this._id           = genguid();
    this._opt          = {};
    this._specs        = [];
    this._matches      = [];
    this._namespace    = namespace;
    this._namestack    = [];
    if (namespace)
      this._namestack.push(namespace);
    _.merge(this._opt, ReMix.defaultOptions);
    if (args.length)
      this.add(args);
  }
  ReMix.registered = {
    hspace:          /[ \t\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]/,
    noHspace:        /[^ \t\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]/,
    vspace:          /[\v\n\r\f]/,
    number:          /0b[01]+|0o[0-7]+|0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?/,
    noVspace:        /[^\v\n\r\f]/,
    space:           /\s/,
    noSpace:         /\S/,
    word:            /\w/,
    noWord:          /\W/,
    any:             /[\S\s]/,
    eol:             /(?:\r\n?|\n|\f)/,
    notEol:          /[^\r\n\f]/,
    end:             /$/,
    begin:           /^/,
    cMultiComment:   /\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//
  };
  ReMix.RE = {
    variable: /^(\w+)([+*?])?$/,
    templates: /\\(?:\\\\)*{|{\s*(\w+[+*?]?)\s*}/g,
    countParen: /(?:\\(?:\\\\)*\()|(\((?!\?))/g
  };
  ReMix.defaultOptions = {
    nsDelimiter: '.',
    defaultFlags: 'g'
  };
  ReMix._countParens = function (str) {
    var cnt = 0, match;
    while ((match = ReMix.RE.countParen.exec(str)))
      if (match[1])
        cnt++;
    return cnt;
  };
  ReMix._resolveVariable = function (match, key) {
    var mod = '';
    if (!key)
      return match;
    var varMatch = ReMix.RE.variable.exec(key);
    if (varMatch) {
      key = varMatch[1] || key;
      mod = varMatch[2] || '';
    }
    return (ReMix.registered[key] ?
      '(?:' + ReMix.registered[key].source + ')' :
        key) + mod;
  };
  ReMix._resolveTemplate = function (str) {
      str = ReMix._resolveVariable(str, str);
      str = str.replace(ReMix.RE.templates, ReMix._resolveVariable);
      return new RegExp(str);
  };

  ReMix.register = function (identifier) {
    if (!_.isString(identifier)) {
      _.forEach(identifier, function(val, key) {
          if (!_.isString(key))
            throw new Error("invalid identifier for registerMatch '" + identifier + "'");
          ReMix.register(key, val);
      });
      return ReMix;
    }
    if (_.has(ReMix.registered, identifier))
      throw new Error(identifier + " already in use");

    ReMix.registered[identifier] = ReMix.render.apply(ReMix, _.toArray(arguments).slice(1));

    return ReMix;
  };
  ReMix.getRegistered = function (identifier) {
    return ReMix.registered[identifier];
  };
  ReMix.prototype._canJoin = function (re1, re2) {
    return (
      (this._flags.i || re1.ignoreCase === re2.ignoreCase) &&
      (this._flags.m ||  re1.multiline === re2.multiline)  &&
      (this._flags.g ||     re1.global === re2.global));
  };
  ReMix.prototype._join = function (regexn) {
    var src = regexn.map(function (re) {
      return re.source;
    }).join(')|(');
    src = '(' + src + ')';
    var flags = '';
    if (regexn[0].ignoreCase && !this._flags.i) flags += 'i';
    if (regexn[0].multiline  && !this._flags.m) flags += 'm';
    if (regexn[0].global     && !this._flags.g) flags += 'g';
    flags += this._opt.defaultFlags;
    return new RegExp(src, flags);
  };
  ReMix.prototype.options = function (opt) {
    if (opt) _.merge(this._opt, opt);
    var flags = this._flags = {};
    _.forEach(this._opt.defaultFlags, function (c) {
      flags[c] = true;
    });
    return this.opt;
  };
  ReMix.prototype._resolveNamed = function (namespace, spec) {
    this._namestack.push(namespace);
    spec = this._resolveSpec(spec);
    this._namestack.pop();
    return spec;
  };
  ReMix.prototype._resolveSpec = function (spec) {
    var namespace = this._namestack.join(this._opt.nsDelimiter);
    if (_.isRegExp(spec)) {
      spec[this._id] = namespace;
      return spec;
    } else if (spec instanceof ReMix) {
      if (spec._namespace) {
        return this._resolveNamed(spec._namespace, spec._specs);
      } else {
        return this._resolveSpec(spec._specs);
      }
    } else  if (_.isString(spec))
      return this._resolveSpec(ReMix._resolveTemplate(spec));
    else if (_.has(spec, 'name') && _.has(spec, 're'))
      return this._resolveNamed(_.result(spec, 'name'), _.result(spec, 're'));
    else if (_.isArray(spec))
      return spec.map(this._resolveSpec.bind(this));
    else if (_.isFunction(spec))
      return this._resolveSpec(spec.call(this, namespace));
    else
      return _.map(spec, function (value, key) {
        return this._resolveNamed(key, _.result(spec, key));
      }.bind(this));
  };
  ReMix.prototype.namespace = function (namespace) {
    if (namespace) {
      this._namespace = namespace;
      this._namestack = [namespace];
      if (this._regexn)
        this._regexn = null;
    }
    return this._namespace;
  };
  ReMix.prototype.clear = function () {
    this._specs = [];
    if (this._regexn)
      this._regexn = null;
    return this;
  };
  ReMix.prototype.add = function () {
    this._specs = this._specs.concat(_.flatten(arguments));
    if (this._regexn)
      this._regexn = null;
    return this;
  };
  ReMix.prototype.addNamed = function (name) {
    var args = _.flatten(arguments).slice(1);
    return this.add({re: args, name: name});
  };
  ReMix.prototype.hasSpecs = function () {
    return this._specs.length > 0;
  };
  ReMix.prototype.compile = function (force) {
    if (!force && this._regexn) return this._regexn;
    var matches = this._matches = [], id = this._id, that = this;
    this._regexn = _.reduce(_.flatten(this._resolveSpec(this._specs)), function (regexn, re, idx) {
      var last = _.last(regexn),
        lastMatch = _.last(matches),
        namespace = re[id],
        parenCnt = ReMix._countParens(re.source);
      if (last && that._canJoin(last[0], re)) {
        lastMatch.push([namespace, parenCnt, idx]);
        last.push(re);
      } else {
        matches.push([[namespace, parenCnt, idx]]);
        regexn.push([re]);
      }
      return regexn;
    }, []).map(function (set) {
      return that._join(set);
    });
    return this._regexn;
  };
  ReMix.prototype.setLastIndex = function (index) {
    this.compile();
    this._regexn.forEach(function (regex) {
      regex.lastIndex = index;
    });
    return this;
  };
  ReMix.prototype.exec = function (string) {
    this.compile();
    var regexn = this._regexn,
      startRe = string[this._id] || 0,
      found = false,
      that = this;
    _.forEach(regexn.slice(startRe), function(re, i) {
      var match = re.exec(string);
      if (match) {
        _.forEach(that._resolveMatch(match, i), function (res) {
          if (_.some(res[0], _.isString)) {
            found = res.concat(re.lastIndex);
            return false;
          }
        });
        if (found) {
          string[that._id] = i;
          return false;
        }
      }
    });

    if (!found)
      delete string[this._id];
    return found;
  };

  ReMix.prototype._resolveMatch = function (matches, index) {

    matches.shift(); // full match
    var lastSet = _.last(this._matches[index]);
    if (matches.length < lastSet[1] + 1)
      _.times(lastSet[1] + 1 - matches.length, function () { matches.push(undefined); });
    return this._matches[index].map(function (set, idx) {
      /*var namespace = set[0],
        cnt = set[1],
        idx = set[2],
        match = matches.splice(0, cnt + 1);
      return [match, namespace, idx];*/
      return [matches.splice(0, set[1] + 1), set[0], set[2]];
    });
  };
  ReMix.prototype.toString = function () {
    return this.compile().map(function (re) {
      return re.source;
    }).join('|');
  };
  module.exports = ReMix;
})();<commit_msg>ensure options are set properly. Add stickyness to matches. This is not optional behaviour currently. When /y flag hits will refactor<commit_after>/*
 * Copyright (C) 2014 Scott Beck, all rights reserved
 *
 * Licensed under the MIT license
 *
 */
(function () {
  'use strict';
  var _ = require("lodash");
  function genguid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
  }
  function ReMix(namespace) {
    var args = _.flatten(_.toArray(arguments));
    if (_.isString(namespace) || _.isNull(namespace) || _.isUndefined(namespace))
      args = args.slice(1);
    else
      namespace = undefined;
    this._id           = genguid();
    this._opt          = {};
    this._specs        = [];
    this._matches      = [];
    this._namespace    = namespace;
    this._namestack    = [];
    if (namespace)
      this._namestack.push(namespace);
    this.options(ReMix.defaultOptions);
    if (args.length)
      this.add(args);
  }
  ReMix.registered = {
    hspace:          /[ \t\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]/,
    noHspace:        /[^ \t\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]/,
    vspace:          /[\v\n\r\f]/,
    number:          /0b[01]+|0o[0-7]+|0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?/,
    noVspace:        /[^\v\n\r\f]/,
    space:           /\s/,
    noSpace:         /\S/,
    word:            /\w/,
    noWord:          /\W/,
    any:             /[\S\s]/,
    eol:             /(?:\r\n?|\n|\f)/,
    notEol:          /[^\r\n\f]/,
    end:             /$/,
    begin:           /^/,
    cMultiComment:   /\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//
  };
  ReMix.RE = {
    variable: /^(\w+)([+*?])?$/,
    templates: /\\(?:\\\\)*{|{\s*(\w+[+*?]?)\s*}/g,
    countParen: /(?:\\(?:\\\\)*\()|(\((?!\?))/g
  };
  ReMix.defaultOptions = {
    nsDelimiter: '.',
    defaultFlags: 'g'
  };
  ReMix._countParens = function (str) {
    var cnt = 0, match;
    while ((match = ReMix.RE.countParen.exec(str)))
      if (match[1])
        cnt++;
    return cnt;
  };
  ReMix._resolveVariable = function (match, key) {
    var mod = '';
    if (!key)
      return match;
    var varMatch = ReMix.RE.variable.exec(key);
    if (varMatch) {
      key = varMatch[1] || key;
      mod = varMatch[2] || '';
    }
    return (ReMix.registered[key] ?
      '(?:' + ReMix.registered[key].source + ')' :
        key) + mod;
  };
  ReMix._resolveTemplate = function (str) {
      str = ReMix._resolveVariable(str, str);
      str = str.replace(ReMix.RE.templates, ReMix._resolveVariable);
      return new RegExp(str);
  };

  ReMix.register = function (identifier) {
    if (!_.isString(identifier)) {
      _.forEach(identifier, function(val, key) {
          if (!_.isString(key))
            throw new Error("invalid identifier for registerMatch '" + identifier + "'");
          ReMix.register(key, val);
      });
      return ReMix;
    }
    if (_.has(ReMix.registered, identifier))
      throw new Error(identifier + " already in use");

    ReMix.registered[identifier] = ReMix.render.apply(ReMix, _.toArray(arguments).slice(1));

    return ReMix;
  };
  ReMix.getRegistered = function (identifier) {
    return ReMix.registered[identifier];
  };
  ReMix.prototype._canJoin = function (re1, re2) {
    return (
      (this._flags.i || re1.ignoreCase === re2.ignoreCase) &&
      (this._flags.m ||  re1.multiline === re2.multiline)  &&
      (this._flags.g ||     re1.global === re2.global));
  };
  ReMix.prototype._join = function (regexn) {
    var src = regexn.map(function (re) {
      return re.source;
    }).join(')|(');
    src = '(' + src + ')';
    var flags = '';
    if (regexn[0].ignoreCase && !this._flags.i) flags += 'i';
    if (regexn[0].multiline  && !this._flags.m) flags += 'm';
    if (regexn[0].global     && !this._flags.g) flags += 'g';
    flags += this._opt.defaultFlags;
    return new RegExp(src, flags);
  };
  ReMix.prototype.options = function (opt) {
    if (opt) _.merge(this._opt, opt);
    var flags = this._flags = {};
    _.forEach(this._opt.defaultFlags, function (c) {
      flags[c] = true;
    });
    return this.opt;
  };
  ReMix.prototype._resolveNamed = function (namespace, spec) {
    this._namestack.push(namespace);
    spec = this._resolveSpec(spec);
    this._namestack.pop();
    return spec;
  };
  ReMix.prototype._resolveSpec = function (spec) {
    var namespace = this._namestack.join(this._opt.nsDelimiter);
    if (_.isRegExp(spec)) {
      spec[this._id] = namespace;
      return spec;
    } else if (spec instanceof ReMix) {
      if (spec._namespace) {
        return this._resolveNamed(spec._namespace, spec._specs);
      } else {
        return this._resolveSpec(spec._specs);
      }
    } else  if (_.isString(spec))
      return this._resolveSpec(ReMix._resolveTemplate(spec));
    else if (_.has(spec, 'name') && _.has(spec, 're'))
      return this._resolveNamed(_.result(spec, 'name'), _.result(spec, 're'));
    else if (_.isArray(spec))
      return spec.map(this._resolveSpec.bind(this));
    else if (_.isFunction(spec))
      return this._resolveSpec(spec.call(this, namespace));
    else
      return _.map(spec, function (value, key) {
        return this._resolveNamed(key, _.result(spec, key));
      }.bind(this));
  };
  ReMix.prototype.namespace = function (namespace) {
    if (namespace) {
      this._namespace = namespace;
      this._namestack = [namespace];
      if (this._regexn)
        this._regexn = null;
    }
    return this._namespace;
  };
  ReMix.prototype.clear = function () {
    this._specs = [];
    if (this._regexn)
      this._regexn = null;
    return this;
  };
  ReMix.prototype.add = function () {
    this._specs = this._specs.concat(_.flatten(arguments));
    if (this._regexn)
      this._regexn = null;
    return this;
  };
  ReMix.prototype.addNamed = function (name) {
    var args = _.flatten(arguments).slice(1);
    return this.add({re: args, name: name});
  };
  ReMix.prototype.hasSpecs = function () {
    return this._specs.length > 0;
  };
  ReMix.prototype.compile = function (force) {
    if (!force && this._regexn) return this._regexn;
    var matches = this._matches = [], id = this._id, that = this;
    this._regexn = _.reduce(_.flatten(this._resolveSpec(this._specs)), function (regexn, re, idx) {
      var last = _.last(regexn),
        lastMatch = _.last(matches),
        namespace = re[id],
        parenCnt = ReMix._countParens(re.source);
      if (last && that._canJoin(last[0], re)) {
        lastMatch.push([namespace, parenCnt, idx]);
        last.push(re);
      } else {
        matches.push([[namespace, parenCnt, idx]]);
        regexn.push([re]);
      }
      return regexn;
    }, []).map(function (set) {
      return that._join(set);
    });
    return this._regexn;
  };
  ReMix.prototype.setLastIndex = function (index) {
    this.compile();
    this._regexn.forEach(function (regex) {
      regex.lastIndex = index;
    });
    return this;
  };
  ReMix.prototype.exec = function (string) {
    this.compile();
    var regexn = this._regexn,
      startRe = string[this._id] || 0,
      found = false,
      that = this;
    _.forEach(regexn.slice(startRe), function(re, i) {
      var lastIndex = re.lastIndex;
      var match = re.exec(string);
      if (match) { /* Not needed once we have /y flag */
        if ((re.lastIndex - match[0].length) === lastIndex)
          _.forEach(that._resolveMatch(match, i), function (res) {
            if (_.some(res[0], _.isString)) {
              found = res.concat(re.lastIndex);
              return false;
            }
          });
        if (found) {
          string[that._id] = i;
          return false;
        }
      }
    });

    if (!found)
      delete string[this._id];
    else
      this.setLastIndex(_.last(found));
    return found;
  };

  ReMix.prototype.reset = function (str) {
    delete str[this._id];
    return this;
  };

  ReMix.prototype._resolveMatch = function (matches, index) {

    matches.shift(); // full match
    var lastSet = _.last(this._matches[index]);
    if (matches.length < lastSet[1] + 1)
      _.times(lastSet[1] + 1 - matches.length, function () { matches.push(undefined); });
    return this._matches[index].map(function (set, idx) {
      /*var namespace = set[0],
        cnt = set[1],
        idx = set[2],
        match = matches.splice(0, cnt + 1);
      return [match, namespace, idx];*/
      return [matches.splice(0, set[1] + 1), set[0], set[2]];
    });
  };
  ReMix.prototype.toString = function () {
    return this.compile().map(function (re) {
      return re.source;
    }).join('|');
  };
  module.exports = ReMix;
})();<|endoftext|>