<commit_before>// Redis client for Node.js
// Author: <NAME> <brian at fictorial dot com>
// Copyright (C) 2009 Fictorial LLC
// License: MIT

var sys = require("sys"), 
    tcp = require("tcp");

var crlf = "\r\n", 
    crlf_len = 2;


var inline_commands = { 
  auth:1, bgsave:1, dbsize:1, decr:1, decrby:1, del:1,
  exists:1, expire:1, flushall:1, flushdb:1, get:1, incr:1, incrby:1, info:1,
  keys:1, lastsave:1, lindex:1, llen:1, lpop:1, lrange:1, ltrim:1, mget:1,
  move:1, randomkey:1, rename:1, renamenx:1, rpop:1, save:1, scard:1, sdiff:1,
  sdiffstore:1, select:1, shutdown:1, sinter:1, sinterstore:1, smembers:1,
  spop:1, srandmember:1, sunion:1, sunionstore:1, ttl:1, type:1, 
  zrange:1, zrevrange:1, zcard:1, zrangebyscore:1
};

var bulk_commands = { 
  getset:1, lpush:1, lrem:1, lset:1, rpush:1, sadd:1, set:1,
  setnx:1, sismember:1, smove:1, srem:1, zadd:1, zrem:1, zscore:1,
  rpoplpush:1
};

var multi_bulk_commands = {
  mset:1, msetnx:1
};

var Client = exports.Client = function (port, host) {
  process.EventEmitter.call(this);

  this.host = host || '127.0.0.1';
  this.port = port || 6379;
  this.callbacks = [];
  this.conn = null;
};

// The client emits "connect" when a connection is established, and emits
// "close" when a connection is closed (passing boolean true if failed in
// error).
//
// Note that calling a Redis client method when the connection is closed will
// automatically attempt to reconnect to Redis first.

sys.inherits(Client, process.EventEmitter);

// Callback a function after we've ensured we're connected to Redis.

Client.prototype.connect = function (callback) {
  if (!this.conn) {
    this.conn = new process.tcp.Connection();
  }
  if (this.conn.readyState === "open" && typeof(callback) === 'function') {
    callback();
  } else {
    var self = this;

    this.conn.addListener("connect", function () {
      this.setEncoding("binary");
      this.setTimeout(0);          // try to stay connected.
      this.setNoDelay();
      self.emit("connect");
      if (typeof(callback) === 'function')
        callback();
    }); 

    this.conn.addListener("receive", function (data) {
      if (!self.buffer)
        self.buffer = "";
      self.buffer += data;
      self.handle_replies();
    });

    this.conn.addListener("eof", function () {
      if (self.conn && self.conn.readyState) {
        self.conn.close();
        self.conn = null;
      }
    });

    this.conn.addListener("close", function (encountered_error) {
      self.conn = null;
      self.emit("close", encountered_error);
    });

    this.conn.connect(this.port, this.host);
  }
};

Client.prototype.close = function () {
  if (this.conn && this.conn.readyState === "open") {
    this.conn.close();
    this.conn = null;
  }
};

// Reply handlers read replies from the current reply buffer.  At the time of
// the call the buffer will start with at least the prefix associated with the
// relevant reply type which is at this time always of length 1.  
//
// Note the buffer may not contain a full reply in which case these reply
// handlers return null.  In this case the buffer is left intact for future
// "receive" events to append onto, and the read-replies process repeats.
// Repeat ad infinitum.  
//
// Each handler returns [ value, next_command_index ] on success, null on
// underflow.

var prefix_len = 1;

// Bulk replies resemble:
// $6\r\nFOOBAR\r\n

Client.prototype.handle_bulk_reply = function (start_at, buf) {
  var buffer = buf || this.buffer;
  start_at = (start_at || 0) + prefix_len;
  var crlf_at = buffer.indexOf(crlf, start_at);
  if (crlf_at === -1) 
    return null;
  var value_len_str = buffer.substring(start_at, crlf_at);
  var value_len = parseInt(value_len_str, 10);
  if (value_len === NaN) 
    throw new Error("invalid bulk value len: " + value_len_str);
  if (value_len === -1)                 // value doesn't exist
    return [ null, crlf_at + crlf_len ];  
  var value_at = crlf_at + crlf_len;
  var next_reply_at = value_at + value_len + crlf_len;
  if (next_reply_at > buffer.length)
    return null;
  var value = buffer.substr(value_at, value_len);
  return [ value, next_reply_at ];
}

// Mult-bulk replies resemble:
// *4\r\n$3\r\nFOO\r\n$3\r\nBAR\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n
// *4 is the number of bulk replies to follow.

Client.prototype.handle_multi_bulk_reply = function (buf) {
  var buffer = buf || this.buffer;
  var crlf_at = buffer.indexOf(crlf, prefix_len);
  if (crlf_at === -1) 
    return null;
  var count_str = buffer.substring(prefix_len, crlf_at);
  var count = parseInt(count_str, 10);
  if (count === NaN) 
    throw new Error("invalid multi-bulk count: " + count_str);
  var next_reply_at = crlf_at + crlf_len;
  if (count === -1)                   // value doesn't exist
    return [ null, next_reply_at ];  
  if (next_reply_at >= buffer.length) 
    return null;
  var results = [];
  for (var i = 0; i < count; ++i) {
    var bulk_reply = this.handle_bulk_reply(next_reply_at, buffer);
    if (bulk_reply === null)             // no full multi-bulk cmd
      return null;
    var bulk_reply_value = bulk_reply[0];
    results.push(bulk_reply_value);
    next_reply_at = bulk_reply[1];
  }
  return [ results, next_reply_at ];<commit_msg>Fixed issue when no keys are returned, byte length is 0, not necessarily -1<commit_after>// Redis client for Node.js
// Author: <NAME> <<EMAIL>>
// Copyright (C) 2009 Fictorial LLC
// License: MIT

var sys = require("sys"), 
    tcp = require("tcp");

var crlf = "\r\n", 
    crlf_len = 2;


var inline_commands = { 
  auth:1, bgsave:1, dbsize:1, decr:1, decrby:1, del:1,
  exists:1, expire:1, flushall:1, flushdb:1, get:1, incr:1, incrby:1, info:1,
  keys:1, lastsave:1, lindex:1, llen:1, lpop:1, lrange:1, ltrim:1, mget:1,
  move:1, randomkey:1, rename:1, renamenx:1, rpop:1, save:1, scard:1, sdiff:1,
  sdiffstore:1, select:1, shutdown:1, sinter:1, sinterstore:1, smembers:1,
  spop:1, srandmember:1, sunion:1, sunionstore:1, ttl:1, type:1, 
  zrange:1, zrevrange:1, zcard:1, zrangebyscore:1
};

var bulk_commands = { 
  getset:1, lpush:1, lrem:1, lset:1, rpush:1, sadd:1, set:1,
  setnx:1, sismember:1, smove:1, srem:1, zadd:1, zrem:1, zscore:1,
  rpoplpush:1
};

var multi_bulk_commands = {
  mset:1, msetnx:1
};

var Client = exports.Client = function (port, host) {
  process.EventEmitter.call(this);

  this.host = host || '127.0.0.1';
  this.port = port || 6379;
  this.callbacks = [];
  this.conn = null;
};

// The client emits "connect" when a connection is established, and emits
// "close" when a connection is closed (passing boolean true if failed in
// error).
//
// Note that calling a Redis client method when the connection is closed will
// automatically attempt to reconnect to Redis first.

sys.inherits(Client, process.EventEmitter);

// Callback a function after we've ensured we're connected to Redis.

Client.prototype.connect = function (callback) {
  if (!this.conn) {
    this.conn = new process.tcp.Connection();
  }
  if (this.conn.readyState === "open" && typeof(callback) === 'function') {
    callback();
  } else {
    var self = this;

    this.conn.addListener("connect", function () {
      this.setEncoding("binary");
      this.setTimeout(0);          // try to stay connected.
      this.setNoDelay();
      self.emit("connect");
      if (typeof(callback) === 'function')
        callback();
    }); 

    this.conn.addListener("receive", function (data) {
      if (!self.buffer)
        self.buffer = "";
      self.buffer += data;
      self.handle_replies();
    });

    this.conn.addListener("eof", function () {
      if (self.conn && self.conn.readyState) {
        self.conn.close();
        self.conn = null;
      }
    });

    this.conn.addListener("close", function (encountered_error) {
      self.conn = null;
      self.emit("close", encountered_error);
    });

    this.conn.connect(this.port, this.host);
  }
};

Client.prototype.close = function () {
  if (this.conn && this.conn.readyState === "open") {
    this.conn.close();
    this.conn = null;
  }
};

// Reply handlers read replies from the current reply buffer.  At the time of
// the call the buffer will start with at least the prefix associated with the
// relevant reply type which is at this time always of length 1.  
//
// Note the buffer may not contain a full reply in which case these reply
// handlers return null.  In this case the buffer is left intact for future
// "receive" events to append onto, and the read-replies process repeats.
// Repeat ad infinitum.  
//
// Each handler returns [ value, next_command_index ] on success, null on
// underflow.

var prefix_len = 1;

// Bulk replies resemble:
// $6\r\nFOOBAR\r\n

Client.prototype.handle_bulk_reply = function (start_at, buf) {
  var buffer = buf || this.buffer;
  start_at = (start_at || 0) + prefix_len;
  var crlf_at = buffer.indexOf(crlf, start_at);
  if (crlf_at === -1) 
    return null;
  var value_len_str = buffer.substring(start_at, crlf_at);
  var value_len = parseInt(value_len_str, 10);
  if (value_len === NaN) 
    throw new Error("invalid bulk value len: " + value_len_str);
  if (value_len === -1)                 // value doesn't exist
    return [ null, crlf_at + crlf_len ];  
  var value_at = crlf_at + crlf_len;
  var next_reply_at = value_at + value_len + crlf_len;
  if (next_reply_at > buffer.length)
    return null;
  var value = buffer.substr(value_at, value_len);
  return [ value, next_reply_at ];
}

// Mult-bulk replies resemble:
// *4\r\n$3\r\nFOO\r\n$3\r\nBAR\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n
// *4 is the number of bulk replies to follow.

Client.prototype.handle_multi_bulk_reply = function (buf) {
  var buffer = buf || this.buffer;
  var crlf_at = buffer.indexOf(crlf, prefix_len);
  if (crlf_at === -1) 
    return null;
  var count_str = buffer.substring(prefix_len, crlf_at);
  var count = parseInt(count_str, 10);
  if (count === NaN) 
    throw new Error("invalid multi-bulk count: " + count_str);
  var next_reply_at = crlf_at + crlf_len;
  if (count === -1)                   // value doesn't exist
    return [ null, next_reply_at ];  
  if (count === 0)
    return [ [], next_reply_at ];
  if (next_reply_at >= buffer.length) 
    return null;
  var results = [];
  for (var i = 0; i < count; ++i) {
    var bulk_reply = this.handle_bulk_reply(next_reply_at, buffer);
    if (bulk_reply === null)             // no full multi-bulk cmd
      return null;
    var bulk_reply_value = bulk_reply[0];
    results.push(bulk_reply_value);
    next_reply_at = bulk_reply[1];
  }
  return [ results, next_reply_at ];
{'fraction_non_alphanumeric': 0.14202187853640136, 'fraction_numerical': 0.01914371935118823, 'mean_word_length': 3.185082872928177, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '4175699', 'n_tokens_mistral': 3893, 'n_tokens_neox': 3743, 'n_words': 1010}