<commit_before>var _ = require('underscore');
var async = require('async');
var stream = require('stream');

var Client = require('./client');

/**
 * Stack Class
 *
 * Manages a set of middlewares.
 *
 * @param {Function} errorHandler - function that handles all errors
 */
var Stack = function(errorHandler){
  this.middlewares = [];
  this.errorHandler = errorHandler;
};

/**
 * Add a middleware to the stack.
 *
 * @param middleware - and already instantiated middleware or object
 */
Stack.prototype.use = function(middleware) {
  middleware.stack = this;
  this.middlewares.push(middleware);
};

/**
 * Generates handler that takes streams as an input.
 *
 * @returns {Function}
 */
Stack.prototype.handler = function(){
  var self = this;

  return function(stream) {
    new Client(self, stream);
  }
};

/**
 * Install a client on all middlewares.
 *
 * @param client - the client that should be installed
 */
Stack.prototype.install = function(client) {
  _.each(this.middlewares, function(m){
    if(m.install) {
      m.install(client);
    }
  });
};

/**
 * Run the stack against a client and a single packet. This will be
 * automatically called with data from the underlying stream.
 *
 * @param client - the stream emitted the packet
 * @param packet - the packet that should be handled
 * @param done - to be called on finish
 */
Stack.prototype.process = function(client, packet, done) {
  var self = this;
  var l = this.middlewares.length;
  var i = -1;
  function next(err) {
    if(err) {
      return self.errorHandler(err, client, packet);
    } else {
      i++;
      if(i < l) {
        if(self.middlewares[i].handle) {
          return self.middlewares[i].handle(client, packet, next, done);
        } else {
          return next();
        }
      }
    }
  }
  next();
};

/**
 * Execute a function on all middlewares.
 *
 * @param fn - the name of the function
 * @param [data] - object passed as first argument
 * @param [store] - object passes as second argument (usefull to collect data)
 * @param [callback] - function to be called after finish
 */
Stack.prototype.execute = function(fn, data, store, callback){
  if(typeof store === 'function') {
    callback = store;
    store = null;
  }

  async.mapSeries(this.middlewares, function(m, cb){
    if(m[fn]) {
      if(store) {
        return m[fn](data, store, cb);
      } else {
        return m[fn](data, cb);
      }
    } else {
      return cb();
    }
  }, callback);
};

module.exports = Stack;<commit_msg>no anonymous function = faster execution<commit_after>var _ = require('underscore');
var async = require('async');
var stream = require('stream');

var Client = require('./client');

/**
 * Stack Class
 *
 * Manages a set of middlewares.
 *
 * @param {Function} errorHandler - function that handles all errors
 */
var Stack = function(errorHandler){
  this.middlewares = [];
  this.errorHandler = errorHandler;
};

/**
 * Add a middleware to the stack.
 *
 * @param middleware - and already instantiated middleware or object
 */
Stack.prototype.use = function(middleware) {
  middleware.stack = this;
  this.middlewares.push(middleware);
};

/**
 * Generates handler that takes streams as an input.
 *
 * @returns {Function}
 */
Stack.prototype.handler = function(){
  var self = this;

  return function(stream) {
    new Client(self, stream);
  }
};

/**
 * Install a client on all middlewares.
 *
 * @param client - the client that should be installed
 */
Stack.prototype.install = function(client) {
  _.each(this.middlewares, function(m){
    if(m.install) {
      m.install(client);
    }
  });
};

/**
 * Run the stack against a client and a single packet. This will be
 * automatically called with data from the underlying stream.
 *
 * @param client - the stream emitted the packet
 * @param packet - the packet that should be handled
 * @param done - to be called on finish
 */
Stack.prototype.process = function(client, packet, done) {
  var self = this;
  var l = this.middlewares.length;
  var i = -1;
  function next(err) {
    if(err) {
      return self.errorHandler(err, client, packet);
    } else {
      i++;
      if(i < l) {
        if(self.middlewares[i].handle) {
          return self.middlewares[i].handle(client, packet, next, done);
        } else {
          return next();
        }
      }
    }
  }
  next();
};

/**
 * Execute a function on all middlewares.
 *
 * @param fn - the name of the function
 * @param [data] - object passed as first argument
 * @param [store] - object passes as second argument (usefull to collect data)
 * @param [callback] - function to be called after finish
 */
Stack.prototype.execute = function(fn, data, store, callback){
  if(typeof store === 'function') {
    callback = store;
    store = null;
  }

  this._execute_fn = fn;
  this._execute_data = data;
  this._execute_store = store;

  async.mapSeries(this.middlewares, this._execute.bind(this), callback);
};

/**
 * Exeucte a single task on a middleware
 *
 * @param m
 * @param cb
 * @private
 */
Stack.prototype._execute = function(m, cb) {
  if(m[this._execute_fn]) {
    if(this._execute_store) {
      return m[this._execute_fn](this._execute_data, this._execute_store, cb);
    } else {
      return m[this._execute_fn](this._execute_data, cb);
    }
  } else {
    return cb();
  }
};

module.exports = Stack;
{'fraction_non_alphanumeric': 0.13358278765201123, 'fraction_numerical': 0.00037418147801683815, 'mean_word_length': 2.995515695067265, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1010680', 'n_tokens_mistral': 1650, 'n_tokens_neox': 1639, 'n_words': 499}