json-bloomfilter 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json-bloomfilter (0.0.3)
4
+ json-bloomfilter (0.0.4)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -10,6 +10,9 @@ GEM
10
10
  Platform (>= 0.4.0)
11
11
  open4
12
12
  Platform (0.4.0)
13
+ addressable (2.3.2)
14
+ childprocess (0.3.6)
15
+ ffi (~> 1.0, >= 1.0.6)
13
16
  coffee-script (2.2.0)
14
17
  coffee-script-source
15
18
  execjs
@@ -17,10 +20,21 @@ GEM
17
20
  diff-lcs (1.1.3)
18
21
  execjs (1.4.0)
19
22
  multi_json (~> 1.0)
23
+ ffi (1.3.1)
20
24
  fssm (0.2.9)
25
+ jasmine (1.3.1)
26
+ jasmine-core (~> 1.3.1)
27
+ rack (~> 1.0)
28
+ rspec (>= 1.3.1)
29
+ selenium-webdriver (>= 0.1.3)
30
+ jasmine-core (1.3.1)
21
31
  libv8 (3.11.8.13)
32
+ libwebsocket (0.1.7.1)
33
+ addressable
34
+ websocket
22
35
  multi_json (1.5.0)
23
36
  open4 (1.3.0)
37
+ rack (1.4.4)
24
38
  rake (10.0.3)
25
39
  rb-fsevent (0.9.3)
26
40
  ref (1.0.2)
@@ -32,9 +46,16 @@ GEM
32
46
  rspec-expectations (2.12.1)
33
47
  diff-lcs (~> 1.1.3)
34
48
  rspec-mocks (2.12.1)
49
+ rubyzip (0.9.9)
50
+ selenium-webdriver (2.27.2)
51
+ childprocess (>= 0.2.5)
52
+ libwebsocket (~> 0.1.3)
53
+ multi_json (~> 1.0)
54
+ rubyzip
35
55
  therubyracer (0.11.3)
36
56
  libv8 (~> 3.11.8.12)
37
57
  ref
58
+ websocket (1.0.6)
38
59
  yui-compressor (0.9.6)
39
60
  POpen4 (>= 0.1.4)
40
61
 
@@ -44,6 +65,7 @@ PLATFORMS
44
65
  DEPENDENCIES
45
66
  coffee-script
46
67
  fssm
68
+ jasmine
47
69
  json-bloomfilter!
48
70
  rake
49
71
  rb-fsevent
data/README.md CHANGED
@@ -1,9 +1,88 @@
1
1
  # JSON Bloomfilter
2
2
 
3
- A bloomfilter implementation in both Ruby and Javascript that can be serialised to and loaded from JSON. Very useful when needing to train a bloom filter in one language and using it in the other.
3
+ A BloomFilter implementation that is serialisable to JSON and compatible between both Ruby and Javascript. Very useful when needing to train a bloom filter in one language and using it in the other.
4
+
5
+ ## Usage
6
+
7
+ ### Installation
8
+
9
+ ```shell
10
+ gem install json-bloomfilter
11
+ ```
12
+
13
+ or
14
+
15
+ ```ruby
16
+ gem 'json-bloomfilter'
17
+ ```
18
+
19
+ in your Gemfile
20
+
21
+ ### Ruby
22
+
23
+ ```ruby
24
+ # create a new BloomFilter and add entries
25
+ filter = JsonBloomFilter.new size: 100
26
+ filter.add "foo"
27
+ filter.add "bar"
28
+ filter.test "foo" #=> true
29
+ filter.test "bar" #=> true
30
+ filter.test "doh" #=> probably false
31
+
32
+ # export the filter to a hash or json
33
+ filter.to_json #=> hash as JSON
34
+ config = filter.to_hash #=> { "size" => 100, "hashes" => 4, "seed" => 1234567890, "bits" => [...] }
35
+
36
+ # use the hash to generate a new BloomFilter with the same config
37
+ filter2 = JsonBloomFilter.new config
38
+ filter2.test "foo" #=> true
39
+ filter2.test "bar" #=> true
40
+ filter2.test "doh" #=> probably false
41
+ ```
42
+
43
+ ### Javascript
44
+
45
+ ```javascript
46
+ # create a new BloomFilter and add entries
47
+ filter = new JsonBloomFilter({ size: 100 });
48
+ filter.add("foo");
49
+ filter.add("bar");
50
+ filter.test("foo"); #=> true
51
+ filter.test("bar"); #=> true
52
+ filter.test("doh"); #=> probably false
53
+
54
+ # export the filter to a hash or json
55
+ filter.toJson(); #=> hash as JSON
56
+ config = filter.toHash(); #=> { "size" => 100, "hashes" => 4, "seed" => 1234567890, "bits" => [...] }
57
+
58
+ # use the hash to generate a new BloomFilter with the same config
59
+ filter2 = new JsonBloomFilter(config);
60
+ filter2.test("foo"); #=> true
61
+ filter2.test("bar"); #=> true
62
+ filter2.test("doh") #=> probably false
63
+ ```
64
+
65
+ ### Options
66
+
67
+ Valid options for constructor are:
68
+
69
+ * `size` (default: 100), the number of items intended to store in the
70
+ * `hashes` (default: 4), the number of hashes used to calculate the bit positions in the bit field
71
+ * `seed` (default: current UNIX time), the seed for the hashing method
72
+
73
+ Additionally you can pass along:
74
+
75
+ * `bits` (default: null), an array with the bitfield in non-bit format. Use `#to_hash` to create these for your active BloomFilter.
76
+
77
+ ## Credits
78
+
79
+ * bitarray.rb and bitarray.coffee based on [version by Peter Cooper](https://github.com/peterc/bitarray).
80
+ * bloomfilter.rb and bloomfilter.coffee inspired by [Ilya Grigorik's Redis Bloomfilter](https://github.com/igrigorik/bloomfilter-rb/blob/master/lib/bloomfilter/redis.rb)
81
+ * zlib.coffee crc32 method based on the [node-crc32](https://github.com/mikepulaski/node-crc32) library and [this snippet](http://stackoverflow.com/questions/6226189/how-to-convert-a-string-to-bytearray/10132540#10132540)
4
82
 
5
83
  ## Release notes
6
84
 
85
+ * **0.0.4** Added JS tests
7
86
  * **0.0.3** Added Ruby tests
8
87
  * **0.0.2** First implementation of both Ruby and JS filters
9
88
  * **0.0.1** Skeleton
data/Rakefile CHANGED
@@ -80,4 +80,12 @@ namespace :js do
80
80
  File.delete js_file
81
81
  end
82
82
 
83
- end
83
+ end
84
+ begin
85
+ require 'jasmine'
86
+ load 'jasmine/tasks/jasmine.rake'
87
+ rescue LoadError
88
+ task :jasmine do
89
+ abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
90
+ end
91
+ end
@@ -1,10 +1,12 @@
1
1
  JsonBloomfilter.BitArray = (size, field = null) ->
2
+ throw new Error("Missing argument: size") unless size
3
+
2
4
  @ELEMENT_WIDTH = 32
3
5
  @size = size
4
6
  @field = field || []
5
7
 
6
8
  arrayLength = Math.floor(((size - 1) / @ELEMENT_WIDTH) + 1)
7
- @field[i] = 0 for i in [0..arrayLength] unless field
9
+ @field[i] = 0 for i in [0..arrayLength-1] unless field
8
10
 
9
11
  this
10
12
 
@@ -15,15 +17,17 @@ JsonBloomfilter.BitArray.prototype.remove = (position) ->
15
17
  @set(position, 0)
16
18
 
17
19
  JsonBloomfilter.BitArray.prototype.set = (position, value) ->
20
+ throw new Error("BitArray index out of bounds") if position >= @size
18
21
  aPos = @arrayPosition(position)
19
22
  bChange = @bitChange(position)
20
23
  if value == 1
21
24
  @field[aPos] |= bChange
22
- else if @field[aPos] & bChange != 0
25
+ else if (@field[aPos] & bChange) != 0
23
26
  @field[aPos] ^= bChange
24
27
  true
25
28
 
26
29
  JsonBloomfilter.BitArray.prototype.get = (position) ->
30
+ throw new Error("BitArray index out of bounds") if position >= @size
27
31
  aPos = @arrayPosition(position)
28
32
  bChange = @bitChange(position)
29
33
  if (@field[aPos] & bChange) > 0
@@ -19,7 +19,7 @@ JsonBloomfilter.prototype.test = (key) ->
19
19
  true
20
20
 
21
21
  JsonBloomfilter.prototype.clear = ->
22
- @bits = @BitArray.new(@options["size"], null)
22
+ @bits = new JsonBloomfilter.BitArray(@options["size"])
23
23
  return
24
24
 
25
25
  JsonBloomfilter.prototype.toHash = ->
data/coffee/zlib.coffee CHANGED
@@ -1,7 +1,3 @@
1
- # Based of:
2
- # https://github.com/mikepulaski/node-crc32
3
- # http://stackoverflow.com/questions/6226189/how-to-convert-a-string-to-bytearray/10132540#10132540
4
-
5
1
  JsonBloomfilter.Zlib =
6
2
  CRC32_TABLE: new Array(0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D)
7
3
 
@@ -1 +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
+ 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=new JsonBloomfilter.BitArray(this.options.size)};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,_ref;if(field==null){field=null}if(!size){throw new Error("Missing argument: size")}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,_ref=arrayLength-1;0<=_ref?_i<=_ref:_i>=_ref;i=0<=_ref?++_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;if(position>=this.size){throw new Error("BitArray index out of bounds")}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;if(position>=this.size){throw new Error("BitArray index out of bounds")}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}};
@@ -23,4 +23,5 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'coffee-script'
24
24
  s.add_development_dependency 'fssm'
25
25
  s.add_development_dependency 'rb-fsevent'
26
+ s.add_development_dependency 'jasmine'
26
27
  end
@@ -1,6 +1,3 @@
1
- # Adapted from
2
- # https://github.com/peterc/bitarray
3
-
4
1
  class JsonBloomfilter
5
2
  class BitArray
6
3
  attr_reader :size
@@ -1,3 +1,3 @@
1
1
  class JsonBloomfilter
2
- VERSION = "0.0.3" unless defined? Trifle::VERSION
2
+ VERSION = "0.0.4" unless defined? Trifle::VERSION
3
3
  end
Binary file
@@ -0,0 +1,70 @@
1
+ describe("JsonBloomfilter.BitArray", function() {
2
+
3
+ describe("#initialize", function() {
4
+ it("should require a size", function() {
5
+ expect(function(){new JsonBloomfilter.BitArray()}).toThrow("Missing argument: size")
6
+ });
7
+
8
+ it("should take an optional bit field", function() {
9
+ field = [0,0,0,2];
10
+ ba = new JsonBloomfilter.BitArray(100, field);
11
+ expect(ba.field).toBe(field);
12
+ });
13
+
14
+ it("should create the right size field"), function() {
15
+ ba = new JsonBloomfilter.BitArray(100);
16
+ expect(ba.field.length).toBe(4);
17
+ });
18
+ });
19
+
20
+ describe("#add", function() {
21
+ it("should set the bit to 1", function() {
22
+ ba = new JsonBloomfilter.BitArray(10);
23
+ ba.add(9);
24
+ expect(ba.toString()).toBe("0000000001");
25
+ });
26
+
27
+ it("should throw an error on out of bound", function() {
28
+ ba = new JsonBloomfilter.BitArray(10);
29
+ ba.add(9);
30
+ expect(function(){ba.add(10);}).toThrow("BitArray index out of bounds");
31
+ });
32
+ });
33
+
34
+ describe("#remove", function() {
35
+ it("should set the bit to 0", function() {
36
+ ba = new JsonBloomfilter.BitArray(10);
37
+ ba.add(9);
38
+ ba.remove(9);
39
+ expect(ba.toString()).toBe("0000000000");
40
+ });
41
+
42
+ it("should throw an error on out of bound", function() {
43
+ ba = new JsonBloomfilter.BitArray(10);
44
+ expect(function(){ba.remove(10);}).toThrow("BitArray index out of bounds");
45
+ });
46
+ });
47
+
48
+ describe("#get", function() {
49
+ it("should return the bit set", function() {
50
+ ba = new JsonBloomfilter.BitArray(10);
51
+ ba.add(9);
52
+ expect(ba.get(9)).toBe(1);
53
+ expect(ba.get(8)).toBe(0);
54
+ });
55
+
56
+ it("should throw an error on out of bound", function() {
57
+ ba = new JsonBloomfilter.BitArray(10);
58
+ expect(function(){ba.get(10);}).toThrow("BitArray index out of bounds");
59
+ });
60
+ });
61
+
62
+ describe("#toString", function() {
63
+ it("should output the bit string", function() {
64
+ ba = new JsonBloomfilter.BitArray(10);
65
+ ba.add(3);
66
+ ba.add(9);
67
+ expect(ba.toString()).toBe("0001000001");
68
+ });
69
+ });
70
+ });
@@ -0,0 +1,75 @@
1
+ describe("JsonBloomfilter", function() {
2
+
3
+ describe("#initialize", function() {
4
+ it("should take the appropriate options", function() {
5
+ seed = (new Date().getTime()/1000) - 24*60*60;
6
+ bf = new JsonBloomfilter({ size: 200, hashes: 10, seed: seed });
7
+ expect(bf.toHash()["size"]).toBe(200);
8
+ expect(bf.toHash()["hashes"]).toBe(10);
9
+ expect(bf.toHash()["seed"]).toBe(seed);
10
+ });
11
+
12
+ it("should be initializable with a field serialized by another bloom filter", function() {
13
+ bf1 = new JsonBloomfilter();
14
+ bf1.add("foo");
15
+ bf2 = new JsonBloomfilter(bf1.toHash());
16
+ expect(bf2.test("foo")).toBe(true);
17
+ });
18
+
19
+ it("should initialize the field with the right size", function() {
20
+ bf = new JsonBloomfilter({size: 100});
21
+ expect(bf.toHash()["bits"].length).toBe(4);
22
+ });
23
+ });
24
+
25
+ describe("with an instance", function() {
26
+ var bf;
27
+
28
+ beforeEach(function() {
29
+ bf = new JsonBloomfilter();
30
+ bf.add("foobar");
31
+ });
32
+
33
+ describe("#add, #test", function() {
34
+ it("should add a key", function() {
35
+ expect(bf.test("foo")).toBe(false);
36
+ bf.add("foo");
37
+ expect(bf.test("foo")).toBe(true);
38
+ });
39
+
40
+ it("should not change anything if added twice", function() {
41
+ expect(bf.test("foobar")).toBe(true);
42
+ bits = bf.toHash()["bits"];
43
+ bf.add("foobar");
44
+ expect(bf.test("foobar")).toBe(true);
45
+ expect(bf.toHash()["bits"]).toBe(bits);
46
+ });
47
+ });
48
+
49
+ describe("#clear", function() {
50
+ it("should clear the bit array", function() {
51
+ expect(bf.bits.toString()).not.toBe("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
52
+ bf.clear();
53
+ expect(bf.bits.toString()).toBe("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
54
+ });
55
+ });
56
+
57
+ describe("#toHash", function() {
58
+ it("should return the serialisable hash", function() {
59
+ hash = bf.toHash();
60
+ expect(hash instanceof Object).toBe(true);
61
+ expect(hash["seed"]).not.toBeUndefined();
62
+ expect(hash["hashes"]).not.toBeUndefined();
63
+ expect(hash["size"]).not.toBeUndefined();
64
+ expect(hash["bits"]).not.toBeUndefined();
65
+ });
66
+ });
67
+
68
+ describe("#toJson", function() {
69
+ it("should return the hash serialised", function() {
70
+ expect(bf.toJson()).toBe(JSON.stringify(bf.toHash()));
71
+ });
72
+ });
73
+
74
+ });
75
+ });
@@ -0,0 +1,8 @@
1
+ src_files:
2
+ - js/json-bloomfilter.min.js
3
+
4
+ helpers:
5
+ - 'helpers/**/*.js'
6
+
7
+ spec_files:
8
+ - '**/*spec.js'
@@ -0,0 +1,10 @@
1
+ describe("JsonBloomfilter.Zlib", function() {
2
+
3
+ describe("#crc32", function() {
4
+ it("should hash the input correctly", function() {
5
+ expect(JsonBloomfilter.Zlib.crc32("foobar")).toBe(2666930069);
6
+ expect(JsonBloomfilter.Zlib.crc32("Magna Pellentesque Egestas Nibh Ultricies")).toBe(1920919084);
7
+ });
8
+
9
+ });
10
+ });
@@ -14,7 +14,7 @@ describe JsonBloomfilter::BitArray do
14
14
  end
15
15
  end
16
16
 
17
- describe "add" do
17
+ describe "#add" do
18
18
  it "should set the bit to 1" do
19
19
  ba = JsonBloomfilter::BitArray.new(10)
20
20
  ba.add(9)
@@ -27,7 +27,7 @@ describe JsonBloomfilter::BitArray do
27
27
  end
28
28
  end
29
29
 
30
- describe "remove" do
30
+ describe "#remove" do
31
31
  it "should set the bit to 0" do
32
32
  ba = JsonBloomfilter::BitArray.new(10)
33
33
  ba.add(9)
@@ -41,7 +41,7 @@ describe JsonBloomfilter::BitArray do
41
41
  end
42
42
  end
43
43
 
44
- describe "get" do
44
+ describe "#get" do
45
45
  it "should return the bit set" do
46
46
  ba = JsonBloomfilter::BitArray.new(10)
47
47
  ba.add(9)
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.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-18 00:00:00.000000000 Z
12
+ date: 2013-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -107,6 +107,22 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: jasmine
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
110
126
  description: A bloomfilter implementation in both Ruby and Javascript that can be
111
127
  serialised to and loaded from JSON. Very useful when needing to train a bloom filter
112
128
  in one language and using it in the other.
@@ -133,6 +149,11 @@ files:
133
149
  - lib/json/bloomfilter/version.rb
134
150
  - pkg/json-bloomfilter-0.0.1.gem
135
151
  - pkg/json-bloomfilter-0.0.2.gem
152
+ - pkg/json-bloomfilter-0.0.3.gem
153
+ - spec/javascripts/bitarray_spec.js
154
+ - spec/javascripts/bloomfilter_spec.js
155
+ - spec/javascripts/support/jasmine.yml
156
+ - spec/javascripts/zlib_spec.js
136
157
  - spec/json/bloomfilter/bitarray_spec.rb
137
158
  - spec/json/bloomfilter_spec.rb
138
159
  - spec/spec_helper.rb
@@ -157,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
178
  version: '0'
158
179
  segments:
159
180
  - 0
160
- hash: 2570443821793762265
181
+ hash: -4107655990555845610
161
182
  requirements: []
162
183
  rubyforge_project:
163
184
  rubygems_version: 1.8.24
@@ -165,6 +186,10 @@ signing_key:
165
186
  specification_version: 3
166
187
  summary: A bloomfilter implementation in both Ruby and Javascript.
167
188
  test_files:
189
+ - spec/javascripts/bitarray_spec.js
190
+ - spec/javascripts/bloomfilter_spec.js
191
+ - spec/javascripts/support/jasmine.yml
192
+ - spec/javascripts/zlib_spec.js
168
193
  - spec/json/bloomfilter/bitarray_spec.rb
169
194
  - spec/json/bloomfilter_spec.rb
170
195
  - spec/spec_helper.rb