bitarray 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab9407668ddd315a33ed9cdee09c9fb26e8a7ad5
4
- data.tar.gz: a9001387330d54c1285409ad9b6ae95a5c0325cc
3
+ metadata.gz: 6fcf6acdc1a14446a50e3cca4c8f96da1f36ab10
4
+ data.tar.gz: dc2cc9af844024134c930ab9678be08731458a7a
5
5
  SHA512:
6
- metadata.gz: 944947fd82afbc27f2c2d1266875193fde0058f0409290bdc82b4fc57633749b0d486bcd306710f62b77c89b3f00b1b60b7bcdd99b9f9c67dcacc085e73532e3
7
- data.tar.gz: 0b9a68f76af9b1ddcd81a6ea2949ef1a1080923b8977b713aae59982fd325e14b4fdf56025a68aee16744e6c817bd18b7a88b30f17abf9a6a496ca9328304aee
6
+ metadata.gz: 3ed10001a59707f9837e62727cf3fbd338c7d5c14af834862d04338800a69639a178a824d0ab629883451f89cdda006d27d9c8116b5751fc351dd17c33878d6a
7
+ data.tar.gz: 446232b243b040be2e7627b042ff5dc03db7c8ebd13ce4060ac2400299954d940c9aa97349a906a73170f5a1f401e3f7b5505d0d1f680c71781f114f1fa5d94e
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # BitArray: A simple bit-array/bitfield library in pure Ruby
2
2
 
3
- Basic, pure Ruby bit field. Works well for Bloom filters (the use case for which I originally wrote it).
3
+ A simple, pure-Ruby 'bit field' object. Works well for Bloom filters (the use case for which I originally wrote it).
4
4
 
5
5
  Originally written in 2007 and left without significant update until 2017, it has now been updated to work within a typical, modern Ruby environment while maintaining the same API.
6
6
 
@@ -47,7 +47,23 @@ ba.total_set
47
47
  #=> 7
48
48
  ```
49
49
 
50
+ Initializing `BitArray` with a custom field value:
51
+
52
+ ```ruby
53
+ ba = BitArray.new(16, ["0000111111110000"].pack('B*'))
54
+ ba.to_s # "1111000000001111"
55
+ ```
56
+
57
+ `BitArray` by default stores the bits in reverse order for each byte. If for example, you are initializing `BitArray` with Redis raw value manipulated with `setbit` / `getbit` operations, you will need to tell `BitArray` to not reverse the bits in each byte using the `reverse_byte: false` option:
58
+
59
+ ```ruby
60
+ ba = BitArray.new(16, ["0000111111110000"].pack('B*'), reverse_byte: false)
61
+ ba.to_s # "0000111111110000"
62
+ ```
63
+
64
+
50
65
  ## History
66
+ - 1.2 in 2018 (Added option to skip reverse the bits for each byte by @dalibor)
51
67
  - 1.1 in 2018 (fixed a significant bug)
52
68
  - 1.0 in 2017 (updated for modern Ruby, more efficient storage, and 10th birthday)
53
69
  - 0.0.1 in 2012 (original v5 released on GitHub)
@@ -61,7 +77,7 @@ ba.total_set
61
77
 
62
78
  Thanks to Michael Slade for encouraging me to update this library on its 10th birthday and for suggesting finally using String's getbyte and setbyte methods now that we're all on 1.9+ compatible implementations.
63
79
 
64
- Further thanks to @tdeo, @JoshuaSP, and @m1lt0n for pull requests.
80
+ Further thanks to @tdeo, @JoshuaSP, @dalibor and @m1lt0n for pull requests.
65
81
 
66
82
  ## License
67
83
 
data/Rakefile CHANGED
@@ -2,4 +2,10 @@ require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new
5
+
5
6
  task :default => :test
7
+
8
+ desc "Open an irb session to work with bitarray"
9
+ task :console do
10
+ sh "irb -rubygems -I lib -r bitarray"
11
+ end
@@ -3,7 +3,7 @@ class BitArray
3
3
  attr_reader :field
4
4
  include Enumerable
5
5
 
6
- VERSION = "1.1.0"
6
+ VERSION = "1.2.0"
7
7
  ELEMENT_WIDTH = 32
8
8
 
9
9
  def initialize(size, field = nil)
@@ -3,25 +3,26 @@ class BitArray
3
3
  attr_reader :field
4
4
  include Enumerable
5
5
 
6
- VERSION = "1.1.0"
6
+ VERSION = "1.2.0"
7
7
 
8
- def initialize(size, field = nil)
8
+ def initialize(size, field = nil, reverse_byte: true)
9
9
  @size = size
10
10
  @field = field || "\0" * (size / 8 + 1)
11
+ @reverse_byte = reverse_byte
11
12
  end
12
13
 
13
14
  # Set a bit (1/0)
14
15
  def []=(position, value)
15
16
  if value == 1
16
- @field.setbyte(position >> 3, @field.getbyte(position >> 3) | (1 << (position % 8)))
17
+ @field.setbyte(position >> 3, @field.getbyte(position >> 3) | (1 << (byte_position(position) % 8)))
17
18
  else
18
- @field.setbyte(position >> 3, @field.getbyte(position >> 3) & ~(1 << (position % 8)))
19
+ @field.setbyte(position >> 3, @field.getbyte(position >> 3) & ~(1 << (byte_position(position) % 8)))
19
20
  end
20
21
  end
21
22
 
22
23
  # Read a bit (1/0)
23
24
  def [](position)
24
- (@field.getbyte(position >> 3) & (1 << (position % 8))) > 0 ? 1 : 0
25
+ (@field.getbyte(position >> 3) & (1 << (byte_position(position) % 8))) > 0 ? 1 : 0
25
26
  end
26
27
 
27
28
  # Iterate over each bit
@@ -31,7 +32,11 @@ class BitArray
31
32
 
32
33
  # Returns the field as a string like "0101010100111100," etc.
33
34
  def to_s
34
- @field.bytes.collect{|ea| ("%08b" % ea).reverse}.join[0, @size]
35
+ if @reverse_byte
36
+ @field.bytes.collect { |ea| ("%08b" % ea).reverse }.join[0, @size]
37
+ else
38
+ @field.bytes.collect { |ea| ("%08b" % ea) }.join[0, @size]
39
+ end
35
40
  end
36
41
 
37
42
  # Returns the total number of bits that are set
@@ -39,4 +44,8 @@ class BitArray
39
44
  def total_set
40
45
  @field.bytes.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
41
46
  end
47
+
48
+ def byte_position(position)
49
+ @reverse_byte ? position : 7 - position
50
+ end
42
51
  end
@@ -52,10 +52,26 @@ class TestBitArray < Minitest::Test
52
52
 
53
53
  def test_to_s
54
54
  ba = BitArray.new(35)
55
- [1, 5, 6, 7, 10, 16, 33].each{|i|ba[i] = 1}
55
+ [1, 5, 6, 7, 10, 16, 33].each { |i| ba[i] = 1}
56
56
  assert_equal "01000111001000001000000000000000010", ba.to_s
57
57
  end
58
58
 
59
+ def test_field
60
+ ba = BitArray.new(35)
61
+ [1, 5, 6, 7, 10, 16, 33].each { |i| ba[i] = 1}
62
+ assert_equal "1110001000000100000000010000000000000010", ba.field.unpack('B*')[0]
63
+ end
64
+
65
+ def test_initialize_with_field
66
+ ba = BitArray.new(15, ["0100011100100001"].pack('B*'))
67
+
68
+ assert_equal [0, 1, 2, 6, 8, 13], 0.upto(15).select { |i| ba[i] == 1 }
69
+
70
+ ba[2] = 1
71
+ ba[12] = 1
72
+ assert_equal [0, 1, 2, 6, 8, 12, 13], 0.upto(15).select { |i| ba[i] == 1 }
73
+ end
74
+
59
75
  def test_total_set
60
76
  ba = BitArray.new(10)
61
77
  ba[1] = 1
@@ -64,3 +80,27 @@ class TestBitArray < Minitest::Test
64
80
  assert_equal 3, ba.total_set
65
81
  end
66
82
  end
83
+
84
+ class TestBitArrayWhenNonReversedByte < Minitest::Test
85
+ def test_to_s
86
+ ba = BitArray.new(35, nil, reverse_byte: true)
87
+ [1, 5, 6, 7, 10, 16, 33].each { |i| ba[i] = 1}
88
+ assert_equal "01000111001000001000000000000000010", ba.to_s
89
+ end
90
+
91
+ def test_field
92
+ ba = BitArray.new(35, nil, reverse_byte: false)
93
+ [1, 5, 6, 7, 10, 16, 33].each { |i| ba[i] = 1}
94
+ assert_equal "0100011100100000100000000000000001000000", ba.field.unpack('B*')[0]
95
+ end
96
+
97
+ def test_initialize_with_field
98
+ ba = BitArray.new(15, ["0100011100100001"].pack('B*'), reverse_byte: false)
99
+
100
+ assert_equal [1, 5, 6, 7, 10, 15], 0.upto(15).select { |i| ba[i] == 1 }
101
+
102
+ ba[2] = 1
103
+ ba[12] = 1
104
+ assert_equal [1, 2, 5, 6, 7, 10, 12, 15], 0.upto(15).select { |i| ba[i] == 1 }
105
+ end
106
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitarray
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Cooper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-14 00:00:00.000000000 Z
11
+ date: 2018-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake