cbetta/json-bloomfilter

View on GitHub
coffee/bloomfilter.coffee

Summary

Maintainability
Test Coverage
JsonBloomfilter = (options = {}) ->
  @options =
    size: 100,
    hashes: 4,
    seed: (new Date().getTime() / 1000),
    bits: null

  items = delete options["items"]
  @options[key] = value for key, value of options
  @bits = new JsonBloomfilter.BitArray(@options["size"], @options["bits"])
  @add(items) if items
  this

JsonBloomfilter.build = (capacity_or_items, error_rate) ->
  capacity = JsonBloomfilter.capacity_for(capacity_or_items)
  items = JsonBloomfilter.items_for(capacity_or_items)
  throw new Error("Capacity needs to be a positive integer") if capacity <= 0
  new JsonBloomfilter({size: JsonBloomfilter.size_for(capacity, error_rate), hashes: JsonBloomfilter.hashes_for(capacity, error_rate), items: items})

JsonBloomfilter.capacity_for = (capacity_or_items) ->
  if capacity_or_items instanceof Array
    capacity_or_items.length
  else
    capacity_or_items

JsonBloomfilter.items_for = (capacity_or_items) ->
  if capacity_or_items instanceof Array
    capacity_or_items
  else
    null

JsonBloomfilter.size_for = (capacity, error_rate) ->
  Math.ceil(capacity * Math.log(error_rate) / Math.log(1.0 / Math.pow(2,Math.log(2))))

JsonBloomfilter.hashes_for = (capacity, error_rate) ->
  Math.round(Math.log(2) * @size_for(capacity, error_rate) / capacity)

JsonBloomfilter.prototype.add = (keys) ->
  for key in [].concat(keys)
    @bits.add(index) for index in @indexesFor(key)
  return

JsonBloomfilter.prototype.test = (keys) ->
  for key in [].concat(keys)
    for index in @indexesFor(key)
      return false if @bits.get(index) == 0
  true

JsonBloomfilter.prototype.clear = ->
  @bits = new JsonBloomfilter.BitArray(@options["size"])
  return

JsonBloomfilter.prototype.toHash = ->
  hash = {}
  hash[key] = value for key, value of @options
  hash["bits"] = @bits.field
  hash

JsonBloomfilter.prototype.toJson = ->
  JSON.stringify @toHash()

JsonBloomfilter.prototype.indexesFor = (key) ->
  indexes = []
  for index in [0..@options["hashes"]-1]
    indexes.push (JsonBloomfilter.Zlib.crc32("#{key}:#{index+@options["seed"]}") % @options["size"])
  indexes