json-bloomfilter 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json-bloomfilter (0.0.2)
4
+ json-bloomfilter (0.0.3)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -4,6 +4,8 @@ A bloomfilter implementation in both Ruby and Javascript that can be serialised
4
4
 
5
5
  ## Release notes
6
6
 
7
+ * **0.0.3** Added Ruby tests
8
+ * **0.0.2** First implementation of both Ruby and JS filters
7
9
  * **0.0.1** Skeleton
8
10
 
9
11
  ## License
data/Rakefile CHANGED
@@ -54,7 +54,7 @@ namespace :js do
54
54
  coffee_script += File.read(filename) + "\n"
55
55
  end
56
56
 
57
- js_file = "js/bloomfilter.js"
57
+ js_file = "js/json-bloomfilter.js"
58
58
  directory_name = File.dirname js_file
59
59
  FileUtils.mkdir_p(directory_name) unless File.exists? directory_name
60
60
  puts "\t\t->#{js_file}"
@@ -68,8 +68,8 @@ namespace :js do
68
68
  filename = args[:filename]
69
69
  compressor = YUI::JavaScriptCompressor.new
70
70
 
71
- js_file = "js/bloomfilter.js"
72
- min_file = "js/bloomfilter.min.js"
71
+ js_file = "js/json-bloomfilter.js"
72
+ min_file = "js/json-bloomfilter.min.js"
73
73
 
74
74
  puts "\t\t->#{min_file}"
75
75
  directory_name = File.dirname min_file
@@ -1,46 +1,43 @@
1
- JsonBloomfilter.BitArray =
2
- size: null
3
- field: null
4
-
5
- ELEMENT_WIDTH: 32
6
-
7
- new: (size, field = null) ->
8
- @size = size
9
- arrayLength = Math.floor(((size - 1) / @ELEMENT_WIDTH) + 1)
10
- @field = field || []
11
- @field[i] = 0 for i in [0..arrayLength] unless field
12
- this
13
-
14
- add: (position) ->
15
- @set(position, 1)
16
-
17
- remove: (position) ->
18
- @set(position, 0)
19
-
20
- set: (position, value) ->
21
- aPos = @arrayPosition(position)
22
- bChange = @bitChange(position)
23
- if value == 1
24
- @field[aPos] |= bChange
25
- else if @field[aPos] & bChange != 0
26
- @field[aPos] ^= bChange
27
- true
28
-
29
- get: (position) ->
30
- aPos = @arrayPosition(position)
31
- bChange = @bitChange(position)
32
- if (@field[aPos] & bChange) > 0
33
- return 1
34
- else
35
- return 0
36
-
37
- arrayPosition: (position) ->
38
- Math.floor(position / @ELEMENT_WIDTH)
39
-
40
- bitChange: (position) ->
41
- Math.abs(1 << position % @ELEMENT_WIDTH)
42
-
43
- toString: ->
44
- output = ""
45
- output += @get(i) for i in [0..@size-1]
46
- output
1
+ JsonBloomfilter.BitArray = (size, field = null) ->
2
+ @ELEMENT_WIDTH = 32
3
+ @size = size
4
+ @field = field || []
5
+
6
+ arrayLength = Math.floor(((size - 1) / @ELEMENT_WIDTH) + 1)
7
+ @field[i] = 0 for i in [0..arrayLength] unless field
8
+
9
+ this
10
+
11
+ JsonBloomfilter.BitArray.prototype.add = (position) ->
12
+ @set(position, 1)
13
+
14
+ JsonBloomfilter.BitArray.prototype.remove = (position) ->
15
+ @set(position, 0)
16
+
17
+ JsonBloomfilter.BitArray.prototype.set = (position, value) ->
18
+ aPos = @arrayPosition(position)
19
+ bChange = @bitChange(position)
20
+ if value == 1
21
+ @field[aPos] |= bChange
22
+ else if @field[aPos] & bChange != 0
23
+ @field[aPos] ^= bChange
24
+ true
25
+
26
+ JsonBloomfilter.BitArray.prototype.get = (position) ->
27
+ aPos = @arrayPosition(position)
28
+ bChange = @bitChange(position)
29
+ if (@field[aPos] & bChange) > 0
30
+ return 1
31
+ else
32
+ return 0
33
+
34
+ JsonBloomfilter.BitArray.prototype.arrayPosition = (position) ->
35
+ Math.floor(position / @ELEMENT_WIDTH)
36
+
37
+ JsonBloomfilter.BitArray.prototype.bitChange = (position) ->
38
+ Math.abs(1 << position % @ELEMENT_WIDTH)
39
+
40
+ JsonBloomfilter.BitArray.prototype.toString = ->
41
+ output = ""
42
+ output += @get(i) for i in [0..@size-1]
43
+ output
@@ -1,40 +1,38 @@
1
- JsonBloomfilter =
2
- bits: null
3
- options:
1
+ JsonBloomfilter = (options = {}) ->
2
+ @options =
4
3
  size: 100,
5
4
  hashes: 4,
6
5
  seed: (new Date().getTime() / 1000),
7
6
  bits: null
8
7
 
9
- new: (options = {}) ->
10
- @options[key] = value for key, value of options
11
- @bits = @BitArray.new(@options["size"], @options["bits"])
12
- this
8
+ @options[key] = value for key, value of options
9
+ @bits = new JsonBloomfilter.BitArray(@options["size"], @options["bits"])
10
+ this
13
11
 
14
- add: (key) ->
15
- @bits.add(index) for index in @indexesFor(key)
16
- return
12
+ JsonBloomfilter.prototype.add = (key) ->
13
+ @bits.add(index) for index in @indexesFor(key)
14
+ return
17
15
 
18
- test: (key) ->
19
- for index in @indexesFor(key)
20
- return false if @bits.get(index) == 0
21
- true
16
+ JsonBloomfilter.prototype.test = (key) ->
17
+ for index in @indexesFor(key)
18
+ return false if @bits.get(index) == 0
19
+ true
22
20
 
23
- clear: ->
24
- @bits = @BitArray.new(@options["size"], null)
25
- return
21
+ JsonBloomfilter.prototype.clear = ->
22
+ @bits = @BitArray.new(@options["size"], null)
23
+ return
26
24
 
27
- toHash: ->
28
- hash = {}
29
- hash[key] = value for key, value of @options
30
- hash["bits"] = @bits.field
31
- hash
25
+ JsonBloomfilter.prototype.toHash = ->
26
+ hash = {}
27
+ hash[key] = value for key, value of @options
28
+ hash["bits"] = @bits.field
29
+ hash
32
30
 
33
- toJson: ->
34
- JSON.stringify @toHash()
31
+ JsonBloomfilter.prototype.toJson = ->
32
+ JSON.stringify @toHash()
35
33
 
36
- indexesFor: (key) ->
37
- indexes = []
38
- for index in [0..@options["hashes"]-1]
39
- indexes.push (@Zlib.crc32("#{key}:#{index+@options["seed"]}") % @options["size"])
40
- indexes
34
+ JsonBloomfilter.prototype.indexesFor = (key) ->
35
+ indexes = []
36
+ for index in [0..@options["hashes"]-1]
37
+ indexes.push (JsonBloomfilter.Zlib.crc32("#{key}:#{index+@options["seed"]}") % @options["size"])
38
+ indexes
data/coffee/zlib.coffee CHANGED
@@ -28,4 +28,4 @@ JsonBloomfilter.Zlib =
28
28
  while i < string.length
29
29
  bytes.push string.charCodeAt(i)
30
30
  ++i
31
- bytes
31
+ bytes
@@ -0,0 +1 @@
1
+ var JsonBloomfilter;JsonBloomfilter=function(options){var key,value;if(options==null){options={}}this.options={size:100,hashes:4,seed:new Date().getTime()/1000,bits:null};for(key in options){value=options[key];this.options[key]=value}this.bits=new JsonBloomfilter.BitArray(this.options.size,this.options.bits);return this};JsonBloomfilter.prototype.add=function(key){var index,_i,_len,_ref;_ref=this.indexesFor(key);for(_i=0,_len=_ref.length;_i<_len;_i++){index=_ref[_i];this.bits.add(index)}};JsonBloomfilter.prototype.test=function(key){var index,_i,_len,_ref;_ref=this.indexesFor(key);for(_i=0,_len=_ref.length;_i<_len;_i++){index=_ref[_i];if(this.bits.get(index)===0){return false}}return true};JsonBloomfilter.prototype.clear=function(){this.bits=this.BitArray["new"](this.options.size,null)};JsonBloomfilter.prototype.toHash=function(){var hash,key,value,_ref;hash={};_ref=this.options;for(key in _ref){value=_ref[key];hash[key]=value}hash.bits=this.bits.field;return hash};JsonBloomfilter.prototype.toJson=function(){return JSON.stringify(this.toHash())};JsonBloomfilter.prototype.indexesFor=function(key){var index,indexes,_i,_ref;indexes=[];for(index=_i=0,_ref=this.options.hashes-1;0<=_ref?_i<=_ref:_i>=_ref;index=0<=_ref?++_i:--_i){indexes.push(JsonBloomfilter.Zlib.crc32(""+key+":"+(index+this.options.seed))%this.options.size)}return indexes};JsonBloomfilter.BitArray=function(size,field){var arrayLength,i,_i;if(field==null){field=null}this.ELEMENT_WIDTH=32;this.size=size;this.field=field||[];arrayLength=Math.floor(((size-1)/this.ELEMENT_WIDTH)+1);if(!field){for(i=_i=0;0<=arrayLength?_i<=arrayLength:_i>=arrayLength;i=0<=arrayLength?++_i:--_i){this.field[i]=0}}return this};JsonBloomfilter.BitArray.prototype.add=function(position){return this.set(position,1)};JsonBloomfilter.BitArray.prototype.remove=function(position){return this.set(position,0)};JsonBloomfilter.BitArray.prototype.set=function(position,value){var aPos,bChange;aPos=this.arrayPosition(position);bChange=this.bitChange(position);if(value===1){this.field[aPos]|=bChange}else{if(this.field[aPos]&bChange!==0){this.field[aPos]^=bChange}}return true};JsonBloomfilter.BitArray.prototype.get=function(position){var aPos,bChange;aPos=this.arrayPosition(position);bChange=this.bitChange(position);if((this.field[aPos]&bChange)>0){return 1}else{return 0}};JsonBloomfilter.BitArray.prototype.arrayPosition=function(position){return Math.floor(position/this.ELEMENT_WIDTH)};JsonBloomfilter.BitArray.prototype.bitChange=function(position){return Math.abs(1<<position%this.ELEMENT_WIDTH)};JsonBloomfilter.BitArray.prototype.toString=function(){var i,output,_i,_ref;output="";for(i=_i=0,_ref=this.size-1;0<=_ref?_i<=_ref:_i>=_ref;i=0<=_ref?++_i:--_i){output+=this.get(i)}return output};JsonBloomfilter.Zlib={CRC32_TABLE:new Array(0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918000,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117),crc32:function(string){var bytes,crc,i,iTop,n;bytes=this.bytesFor(string);crc=0;n=0;crc=crc^(-1);i=0;iTop=bytes.length;while(i<iTop){n=(crc^bytes[i])&255;crc=(crc>>>8)^this.CRC32_TABLE[n];i++}crc=crc^(-1);if(crc<0){crc+=4294967296}return crc},bytesFor:function(string){var bytes,i;bytes=[];i=0;while(i<string.length){bytes.push(string.charCodeAt(i));++i}return bytes}};
@@ -1,28 +1,28 @@
1
- require_relative "bitarray"
1
+ require_relative "bloomfilter/bitarray"
2
2
  require "json"
3
3
 
4
4
  class JsonBloomfilter
5
5
  DEFAULTS = { "size" => 100, "hashes" => 4, "seed" => Time.new.to_i, "bits" => nil }
6
6
 
7
7
  def initialize options = {}
8
- @options = DEFAULTS.merge options
8
+ @options = merge_defaults_with options
9
9
  @bits = BitArray.new(@options["size"], @options["bits"])
10
10
  end
11
11
 
12
12
  def add key
13
- indexes_for(key).each { |index| @bits[index] = 1 }
13
+ indexes_for(key).each { |index| @bits.add(index) }
14
14
  nil
15
15
  end
16
16
 
17
17
  def test key
18
18
  indexes_for(key).each do |index|
19
- return false if @bits[index] == 0
19
+ return false if @bits.get(index) == 0
20
20
  end
21
21
  true
22
22
  end
23
23
 
24
24
  def clear
25
- @bits = BitArray.new(@options["size"], 0)
25
+ @bits = BitArray.new(@options["size"])
26
26
  end
27
27
 
28
28
  def to_hash
@@ -40,4 +40,8 @@ class JsonBloomfilter
40
40
  Zlib.crc32("#{key}:#{index+@options["seed"]}") % @options["size"]
41
41
  end
42
42
  end
43
+
44
+ def merge_defaults_with options
45
+ DEFAULTS.merge Hash[options.map {|k, v| ["#{k}", v] }]
46
+ end
43
47
  end
@@ -0,0 +1,51 @@
1
+ # Adapted from
2
+ # https://github.com/peterc/bitarray
3
+
4
+ class JsonBloomfilter
5
+ class BitArray
6
+ attr_reader :size
7
+ attr_reader :field
8
+ include Enumerable
9
+
10
+ ELEMENT_WIDTH = 32
11
+
12
+ def initialize(size, field = nil)
13
+ @size = size
14
+ @field = field || Array.new(((size - 1) / ELEMENT_WIDTH) + 1, 0)
15
+ end
16
+
17
+ def add position
18
+ self[position] = 1
19
+ end
20
+
21
+ def remove position
22
+ self[position] = 0
23
+ end
24
+
25
+ # Set a bit (1/0)
26
+ def []=(position, value)
27
+ raise ArgumentError.new("Position out of bound (#{position} for max #{@size})") if position >= @size
28
+ if value == 1
29
+ @field[position / ELEMENT_WIDTH] |= 1 << (position % ELEMENT_WIDTH)
30
+ elsif (@field[position / ELEMENT_WIDTH]) & (1 << (position % ELEMENT_WIDTH)) != 0
31
+ @field[position / ELEMENT_WIDTH] ^= 1 << (position % ELEMENT_WIDTH)
32
+ end
33
+ end
34
+
35
+ # Read a bit (1/0)
36
+ def get position
37
+ raise ArgumentError.new("Position out of bound (#{position} for max #{@size})") if position >= @size
38
+ @field[position / ELEMENT_WIDTH] & 1 << (position % ELEMENT_WIDTH) > 0 ? 1 : 0
39
+ end
40
+
41
+ # Iterate over each bit
42
+ def each(&block)
43
+ @size.times { |position| yield self.get(position) }
44
+ end
45
+
46
+ # Returns the field as a string like "0101010100111100," etc.
47
+ def to_s
48
+ inject("") { |a, b| a + b.to_s }
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  class JsonBloomfilter
2
- VERSION = "0.0.2" unless defined? Trifle::VERSION
2
+ VERSION = "0.0.3" unless defined? Trifle::VERSION
3
3
  end
Binary file
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonBloomfilter::BitArray do
4
+
5
+ describe "#initialize" do
6
+ it "should require a size" do
7
+ expect(->{JsonBloomfilter::BitArray.new}).to raise_error(ArgumentError)
8
+ expect(->{JsonBloomfilter::BitArray.new(100)}).not_to raise_error(ArgumentError)
9
+ end
10
+ it "should take an optional bit field" do
11
+ field = [0,0,0,2]
12
+ ba = JsonBloomfilter::BitArray.new(100, field)
13
+ expect(ba.field).to be == field
14
+ end
15
+ end
16
+
17
+ describe "add" do
18
+ it "should set the bit to 1" do
19
+ ba = JsonBloomfilter::BitArray.new(10)
20
+ ba.add(9)
21
+ expect(ba.to_s).to be == "0000000001"
22
+ end
23
+
24
+ it "should throw an error on out of bound" do
25
+ ba = JsonBloomfilter::BitArray.new(10)
26
+ expect(->{ba.add(10)}).to raise_error
27
+ end
28
+ end
29
+
30
+ describe "remove" do
31
+ it "should set the bit to 0" do
32
+ ba = JsonBloomfilter::BitArray.new(10)
33
+ ba.add(9)
34
+ ba.remove(9)
35
+ expect(ba.to_s).to be == "0000000000"
36
+ end
37
+
38
+ it "should throw an error on out of bound" do
39
+ ba = JsonBloomfilter::BitArray.new(10)
40
+ expect(->{ba.remove(10)}).to raise_error
41
+ end
42
+ end
43
+
44
+ describe "get" do
45
+ it "should return the bit set" do
46
+ ba = JsonBloomfilter::BitArray.new(10)
47
+ ba.add(9)
48
+ expect(ba.get(9)).to be == 1
49
+ expect(ba.get(8)).to be == 0
50
+ end
51
+
52
+ it "should throw an error on out of bound" do
53
+ ba = JsonBloomfilter::BitArray.new(10)
54
+ expect(->{ba.get(10)}).to raise_error
55
+ end
56
+ end
57
+
58
+ describe "#to_s" do
59
+ it "should output the bit string" do
60
+ ba = JsonBloomfilter::BitArray.new(10)
61
+ ba.add(3)
62
+ ba.add(9)
63
+ expect(ba.to_s).to be == "0001000001"
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,78 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonBloomfilter do
4
+
5
+ describe "#initialize" do
6
+ it "should take the appropriate options" do
7
+ seed = Time.now.to_i - 24*60*60
8
+ bf = JsonBloomfilter.new size: 200, hashes: 10, seed: seed
9
+ expect(bf.to_hash["size"]).to be == 200
10
+ expect(bf.to_hash["hashes"]).to be == 10
11
+ expect(bf.to_hash["seed"]).to be == seed
12
+ end
13
+
14
+ it "should be initializable with a field serialized by another bloom filter" do
15
+ bf1 = JsonBloomfilter.new
16
+ bf1.add "foo"
17
+ bf2 = JsonBloomfilter.new bf1.to_hash
18
+ expect(bf2.test "foo").to be_true
19
+ end
20
+ end
21
+
22
+ context "with an instance" do
23
+ before :each do
24
+ @bf = JsonBloomfilter.new
25
+ @bf.add("foobar")
26
+ end
27
+
28
+ describe "#add, #test" do
29
+ it "should add a key" do
30
+ expect(@bf.test "foo").to be_false
31
+ @bf.add "foo"
32
+ expect(@bf.test "foo").to be_true
33
+ end
34
+
35
+ it "should not change anything if added twice" do
36
+ expect(@bf.test "foobar").to be_true
37
+ bits = @bf.to_hash["bits"]
38
+ @bf.add "foobar"
39
+ expect(@bf.test "foobar").to be_true
40
+ expect(@bf.to_hash["bits"]).to be == bits
41
+ end
42
+ end
43
+
44
+ describe "#clear" do
45
+ it "should clear the bit array" do
46
+ expect(@bf.to_hash["bits"]).not_to be == [0,0,0,0]
47
+ @bf.clear
48
+ expect(@bf.to_hash["bits"]).to be == [0,0,0,0]
49
+ end
50
+ end
51
+
52
+ describe "#to_hash" do
53
+ it "should return the serialisable hash" do
54
+ hash = @bf.to_hash
55
+ expect(hash).to be_a(Hash)
56
+
57
+ expect(hash).to have_key("seed")
58
+ expect(hash["seed"]).to be_a(Integer)
59
+
60
+ expect(hash).to have_key("hashes")
61
+ expect(hash["hashes"]).to be_a(Integer)
62
+
63
+ expect(hash).to have_key("size")
64
+ expect(hash["size"]).to be_a(Integer)
65
+
66
+ expect(hash).to have_key("bits")
67
+ expect(hash["bits"]).to be_a(Array)
68
+ end
69
+ end
70
+
71
+ describe "#to_json" do
72
+ it "should return the hash serialised" do
73
+ expect(@bf.to_json).to be == JSON.generate(@bf.to_hash)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,2 @@
1
1
  require "json/bloomfilter"
2
+ require "json/bloomfilter/bitarray"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-bloomfilter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -116,6 +116,7 @@ executables: []
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
+ - .rspec
119
120
  - .rvmrc
120
121
  - Gemfile
121
122
  - Gemfile.lock
@@ -125,14 +126,15 @@ files:
125
126
  - coffee/bitarray.coffee
126
127
  - coffee/bloomfilter.coffee
127
128
  - coffee/zlib.coffee
128
- - js/bloomfilter.min.js
129
+ - js/json-bloomfilter.min.js
129
130
  - json-bloomfilter.gemspec
130
- - lib/json/bitarray.rb
131
131
  - lib/json/bloomfilter.rb
132
+ - lib/json/bloomfilter/bitarray.rb
132
133
  - lib/json/bloomfilter/version.rb
133
134
  - pkg/json-bloomfilter-0.0.1.gem
134
135
  - pkg/json-bloomfilter-0.0.2.gem
135
- - spec/json-bloomfilter_spec.rb
136
+ - spec/json/bloomfilter/bitarray_spec.rb
137
+ - spec/json/bloomfilter_spec.rb
136
138
  - spec/spec_helper.rb
137
139
  homepage: http://github.com/cbetta/json-bloomfilter
138
140
  licenses:
@@ -155,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
157
  version: '0'
156
158
  segments:
157
159
  - 0
158
- hash: 1888125834509649748
160
+ hash: 2570443821793762265
159
161
  requirements: []
160
162
  rubyforge_project:
161
163
  rubygems_version: 1.8.24
@@ -163,5 +165,6 @@ signing_key:
163
165
  specification_version: 3
164
166
  summary: A bloomfilter implementation in both Ruby and Javascript.
165
167
  test_files:
166
- - spec/json-bloomfilter_spec.rb
168
+ - spec/json/bloomfilter/bitarray_spec.rb
169
+ - spec/json/bloomfilter_spec.rb
167
170
  - spec/spec_helper.rb
@@ -1 +0,0 @@
1
- var JsonBloomfilter;JsonBloomfilter={bits:null,options:{size:100,hashes:4,seed:new Date().getTime()/1000,bits:null},"new":function(options){var key,value;if(options==null){options={}}for(key in options){value=options[key];this.options[key]=value}this.bits=this.BitArray["new"](this.options.size,this.options.bits);return this},add:function(key){var index,_i,_len,_ref;_ref=this.indexesFor(key);for(_i=0,_len=_ref.length;_i<_len;_i++){index=_ref[_i];this.bits.add(index)}},test:function(key){var index,_i,_len,_ref;_ref=this.indexesFor(key);for(_i=0,_len=_ref.length;_i<_len;_i++){index=_ref[_i];if(this.bits.get(index)===0){return false}}return true},clear:function(){this.bits=this.BitArray["new"](this.options.size,null)},toHash:function(){var hash,key,value,_ref;hash={};_ref=this.options;for(key in _ref){value=_ref[key];hash[key]=value}hash.bits=this.bits.field;return hash},toJson:function(){return JSON.stringify(this.toHash())},indexesFor:function(key){var index,indexes,_i,_ref;indexes=[];for(index=_i=0,_ref=this.options.hashes-1;0<=_ref?_i<=_ref:_i>=_ref;index=0<=_ref?++_i:--_i){indexes.push(this.Zlib.crc32(""+key+":"+(index+this.options.seed))%this.options.size)}return indexes}};JsonBloomfilter.BitArray={size:null,field:null,ELEMENT_WIDTH:32,"new":function(size,field){var arrayLength,i,_i;if(field==null){field=null}this.size=size;arrayLength=Math.floor(((size-1)/this.ELEMENT_WIDTH)+1);this.field=field||[];if(!field){for(i=_i=0;0<=arrayLength?_i<=arrayLength:_i>=arrayLength;i=0<=arrayLength?++_i:--_i){this.field[i]=0}}return this},add:function(position){return this.set(position,1)},remove:function(position){return this.set(position,0)},set:function(position,value){var aPos,bChange;aPos=this.arrayPosition(position);bChange=this.bitChange(position);if(value===1){this.field[aPos]|=bChange}else{if(this.field[aPos]&bChange!==0){this.field[aPos]^=bChange}}return true},get:function(position){var aPos,bChange;aPos=this.arrayPosition(position);bChange=this.bitChange(position);if((this.field[aPos]&bChange)>0){return 1}else{return 0}},arrayPosition:function(position){return Math.floor(position/this.ELEMENT_WIDTH)},bitChange:function(position){return Math.abs(1<<position%this.ELEMENT_WIDTH)},toString:function(){var i,output,_i,_ref;output="";for(i=_i=0,_ref=this.size-1;0<=_ref?_i<=_ref:_i>=_ref;i=0<=_ref?++_i:--_i){output+=this.get(i)}return output}};JsonBloomfilter.Zlib={CRC32_TABLE:new Array(0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918000,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117),crc32:function(string){var bytes,crc,i,iTop,n;bytes=this.bytesFor(string);crc=0;n=0;crc=crc^(-1);i=0;iTop=bytes.length;while(i<iTop){n=(crc^bytes[i])&255;crc=(crc>>>8)^this.CRC32_TABLE[n];i++}crc=crc^(-1);if(crc<0){crc+=4294967296}return crc},bytesFor:function(string){var bytes,i;bytes=[];i=0;while(i<string.length){bytes.push(string.charCodeAt(i));++i}return bytes}};
data/lib/json/bitarray.rb DELETED
@@ -1,45 +0,0 @@
1
- # Adapted from
2
- # https://github.com/peterc/bitarray
3
-
4
- class BitArray
5
- attr_reader :size
6
- attr_reader :field
7
- include Enumerable
8
-
9
- ELEMENT_WIDTH = 32
10
-
11
- def initialize(size, field = nil)
12
- @size = size
13
- @field = field || Array.new(((size - 1) / ELEMENT_WIDTH) + 1, 0)
14
- end
15
-
16
- # Set a bit (1/0)
17
- def []=(position, value)
18
- if value == 1
19
- @field[position / ELEMENT_WIDTH] |= 1 << (position % ELEMENT_WIDTH)
20
- elsif (@field[position / ELEMENT_WIDTH]) & (1 << (position % ELEMENT_WIDTH)) != 0
21
- @field[position / ELEMENT_WIDTH] ^= 1 << (position % ELEMENT_WIDTH)
22
- end
23
- end
24
-
25
- # Read a bit (1/0)
26
- def [](position)
27
- @field[position / ELEMENT_WIDTH] & 1 << (position % ELEMENT_WIDTH) > 0 ? 1 : 0
28
- end
29
-
30
- # Iterate over each bit
31
- def each(&block)
32
- @size.times { |position| yield self[position] }
33
- end
34
-
35
- # Returns the field as a string like "0101010100111100," etc.
36
- def to_s
37
- inject("") { |a, b| a + b.to_s }
38
- end
39
-
40
- # Returns the total number of bits that are set
41
- # (The technique used here is about 6 times faster than using each or inject direct on the bitfield)
42
- def total_set
43
- @field.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
44
- end
45
- end
@@ -1,9 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe JsonBloomfilter do
4
-
5
- it "should pass" do
6
- bf = JsonBloomfilter.new
7
- end
8
-
9
- end