<commit_before>var util = require('util')
var thunky = require('thunky')
var Readable = require('readable-stream').Readable

var Cursor = function (getCursor) {
  Readable.call(this, {objectMode: true, highWaterMark: 0})

  this._opts = {}

  var self = this
  this._get = thunky(function (cb) {
    getCursor(function (err, cursor) {
      if (err) { return cb(err) }

      // Apply all opts
      for (var key in self._opts) {
        if (self._opts.hasOwnProperty(key)) {
          cursor = cursor[key](self._opts[key])
        }
      }

      cb(null, cursor)
    })
  })
}

util.inherits(Cursor, Readable)

Cursor.prototype.next = function (cb) {
  this._get(function (err, cursor) {
    if (err) return cb(err)

    if (cursor.cursorState.dead || cursor.cursorState.killed) {
      return cb(null, null)
    } else {
      cursor.next(cb)
    }
  })

  return this
}

Cursor.prototype.rewind = function (cb) {
  this._get(function (err, cursor) {
    if (err) return cb(err)
    cursor.rewind(cb)
  })

  return this
}

Cursor.prototype.toArray = function (cb) {
  var array = []
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return cb(err)
      if (!obj) return cb(null, array)
      array.push(obj)

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      process.nextTick(loop)
    })
  }

  loop()
}

Cursor.prototype.map = function (mapfn, cb) {
  var array = []
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return cb(err)
      if (!obj) return cb(null, array)
      array.push(mapfn(obj))

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      process.nextTick(loop)
    })
  }

  loop()
}

Cursor.prototype.forEach = function (fn) {
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return fn(err)
      fn(err, obj)

      if (!obj) return

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      process.nextTick(loop)
    })
  }

  loop()
}

// Missing mongodb cursor methods are addOption, hasNext, itcount, readPref, showDiskLoc
var opts = ['batchSize', 'hint', 'limit', 'maxTimeMS', 'max', 'min', 'skip', 'snapshot', 'sort']

opts.forEach(function (opt) {
  Cursor.prototype[opt] = function (obj, cb) {
    this._opts[opt] = obj
    if (cb) return this.toArray(cb)
    return this
  }
})

Cursor.prototype.count = function (cb) {
  var self = this

  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.count(false, self.opts, cb)
  })
}

Cursor.prototype.size = function (cb) {
  var self = this

  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.count(true, self.opts, cb)
  })
}

Cursor.prototype.explain = function (cb) {
  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.explain(cb)
  })
}

Cursor.prototype.destroy = function () {
  var self = this
  this._get(function (err, cursor) {
    if (err) return self.emit('error', err)
    if (cursor.close) {
      cursor.close(function (err) {
        if (err) { self.emit('error', err) }
      })
    }
  })
}

Cursor.prototype._read = function () {
  var self = this
  this.next(function (err, data) {
    if (err) return self.emit('error', err)
    self.push(data)
  })
}

module.exports = Cursor
<commit_msg>Use setImmediate(loop) instead of process.nextTick(loop) to please node 0.10<commit_after>var util = require('util')
var thunky = require('thunky')
var Readable = require('readable-stream').Readable

var Cursor = function (getCursor) {
  Readable.call(this, {objectMode: true, highWaterMark: 0})

  this._opts = {}

  var self = this
  this._get = thunky(function (cb) {
    getCursor(function (err, cursor) {
      if (err) { return cb(err) }

      // Apply all opts
      for (var key in self._opts) {
        if (self._opts.hasOwnProperty(key)) {
          cursor = cursor[key](self._opts[key])
        }
      }

      cb(null, cursor)
    })
  })
}

util.inherits(Cursor, Readable)

Cursor.prototype.next = function (cb) {
  this._get(function (err, cursor) {
    if (err) return cb(err)

    if (cursor.cursorState.dead || cursor.cursorState.killed) {
      return cb(null, null)
    } else {
      cursor.next(cb)
    }
  })

  return this
}

Cursor.prototype.rewind = function (cb) {
  this._get(function (err, cursor) {
    if (err) return cb(err)
    cursor.rewind(cb)
  })

  return this
}

Cursor.prototype.toArray = function (cb) {
  var array = []
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return cb(err)
      if (!obj) return cb(null, array)
      array.push(obj)

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      setImmediate(loop)
    })
  }

  loop()
}

Cursor.prototype.map = function (mapfn, cb) {
  var array = []
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return cb(err)
      if (!obj) return cb(null, array)
      array.push(mapfn(obj))

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      setImmediate(loop)
    })
  }

  loop()
}

Cursor.prototype.forEach = function (fn) {
  var self = this

  var loop = function () {
    self.next(function (err, obj) {
      if (err) return fn(err)
      fn(err, obj)

      if (!obj) return

      // Fix for #270 RangeError: Maximum call stack size exceeded using Collection.find
      setImmediate(loop)
    })
  }

  loop()
}

// Missing mongodb cursor methods are addOption, hasNext, itcount, readPref, showDiskLoc
var opts = ['batchSize', 'hint', 'limit', 'maxTimeMS', 'max', 'min', 'skip', 'snapshot', 'sort']

opts.forEach(function (opt) {
  Cursor.prototype[opt] = function (obj, cb) {
    this._opts[opt] = obj
    if (cb) return this.toArray(cb)
    return this
  }
})

Cursor.prototype.count = function (cb) {
  var self = this

  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.count(false, self.opts, cb)
  })
}

Cursor.prototype.size = function (cb) {
  var self = this

  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.count(true, self.opts, cb)
  })
}

Cursor.prototype.explain = function (cb) {
  this._get(function (err, cursor) {
    if (err) { return cb(err) }
    cursor.explain(cb)
  })
}

Cursor.prototype.destroy = function () {
  var self = this
  this._get(function (err, cursor) {
    if (err) return self.emit('error', err)
    if (cursor.close) {
      cursor.close(function (err) {
        if (err) { self.emit('error', err) }
      })
    }
  })
}

Cursor.prototype._read = function () {
  var self = this
  this.next(function (err, data) {
    if (err) return self.emit('error', err)
    self.push(data)
  })
}

module.exports = Cursor

{'fraction_non_alphanumeric': 0.14520547945205478, 'fraction_numerical': 0.0033165104542177363, 'mean_word_length': 2.765472312703583, 'pattern_counts': {'":': 0, '<': 3, '<?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': '1491240', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2344, 'n_words': 618}