bitary 0.1.0 → 0.1.2

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
  SHA256:
3
- metadata.gz: ac785e04cdffcc47ba24323144ee8a7c28337fe337e5d21e3e915409e261eea9
4
- data.tar.gz: 764c93d304bc84137e3e1e2af4db62411503e65a14a397330b04d4eaa3b209d8
3
+ metadata.gz: 80cd57b662219349dc57edd47612599f95f5aeca086dbec30af067adb10fe587
4
+ data.tar.gz: dc630c61a13c74a20e3472a90f244dd995f4c7196fb6146ca15973efe02e310d
5
5
  SHA512:
6
- metadata.gz: de516b045c571f67e33cc9d377c6602837edfc70fd0191c18edd0ff7777e37acafce24fb5e104c54f0ab4ea6f21dd20e40b3693cd560c658089b401f9323b635
7
- data.tar.gz: b826149418b68db29efe5a9a87ccfbe287ccfc3e8632da8abd8e834ea622561dddb3250fdf69de5b9519daee02fb67e4f246ce8bca348d8b19fdb6261468ff94
6
+ metadata.gz: 9adf435f35e798c71a3a81213f408da0c178b2d3137ecae3619c84e3c95d564e060a4985d24a4746b93a0fb8e2d73fc4a209a38908c7dad25d87dfd728e575da
7
+ data.tar.gz: a6f136e8e5f140ad9455c14b13d94232d40bfc37e09e62b6827857888d03dacbc53fb027a9da1901dfa2d2f966144680a3e2d0a5dd57c4af563d4bd09af99326
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
- ## [Unreleased]
1
+ ## [0.1.1] - 2024-03-26
2
+
3
+ - Change root namespace to a class, instead of a module
2
4
 
3
5
  ## [0.1.0] - 2024-03-26
4
6
 
5
7
  - Initial release
8
+ - Basic implementation to set/unset/get bits from the bit array
9
+ - Ability to traverse each byte of the structure
10
+ - Increase/decrease the number of bits used internally per element
data/README.md CHANGED
@@ -24,10 +24,8 @@ Documentation still needs to be written, but here is a breakdown
24
24
  of the main capabilities brought by the current bit array implementation:
25
25
 
26
26
  ```ruby
27
- include Bitary
28
-
29
- bit_array_sz = BitArray.new(128) # give an explicit size. Defaults to 64 bits used per item
30
- bit_array_ar = BitArray.new(
27
+ bit_array_sz = Bitary.new(128) # give an explicit size. Defaults to 64 bits used per item
28
+ bit_array_ar = Bitary.new(
31
29
  [255, 10, 20],
32
30
  bits_per_item: 8
33
31
  ) # create based on some integer array
@@ -53,18 +51,18 @@ bit_array_sz.each_byte do |byte|
53
51
  end
54
52
 
55
53
  # convert
56
- bit_array_ar.to_a # [255, 10, 20]
57
- bit_array_ar.to_s # "11111111 00001010 00010100"
54
+ bit_array_ar.to_a # [127, 10, 20]
55
+ bit_array_ar.to_s # "01111111 00001010 00010100"
58
56
 
59
57
  # increase/decrease bits used per item
60
58
  bit_array_ar.bits_per_item = 64
61
- bit_array_ar.to_a # [16_714_260]
62
- bit_array_ar.to_s # "0000000000000000000000000000000000000000111111110000101000010100"
59
+ bit_array_ar.to_a # [8_325_652]
60
+ bit_array_ar.to_s # "0000000000000000000000000000000000000000011111110000101000010100"
63
61
 
64
62
  bit_array_sz.bits_per_item # 64
65
63
  bit_array_sz.to_a # [1_099_511_627_776, 0]
66
64
  bit_array_sz.bits_per_item = 32
67
- bit_array_sz.to_a # [256, 0, 0, 1]
65
+ bit_array_sz.to_a # [256, 0, 0, 0]
68
66
  ```
69
67
 
70
68
  ## Development
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bitary
4
+ class Handler
5
+ class Append < Bitary::Handler
6
+ def execute(**kwargs)
7
+ raise ArgumentError unless kwargs.all? do |key, _value|
8
+ %i[offset value].include?(key)
9
+ end
10
+
11
+ offset = kwargs[:offset] or raise KeyError
12
+ value = kwargs[:value] or raise KeyError
13
+ raise ArgumentError unless offset.is_a?(Integer)
14
+ raise ArgumentError unless value.is_a?(Integer)
15
+
16
+ (@value << offset) | value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bitary
4
+ class Handler
5
+ class Get < Bitary::Handler
6
+ def execute(**kwargs)
7
+ raise ArgumentError unless kwargs.all? do |key, _value|
8
+ %i[index size].include?(key)
9
+ end
10
+
11
+ index = kwargs[:index] or raise KeyError
12
+ size = kwargs[:size] or raise KeyError
13
+ raise ArgumentError unless index.is_a?(Integer)
14
+ raise ArgumentError unless size.is_a?(Integer)
15
+
16
+ raise IndexError if index.negative? || index >= size
17
+
18
+ (@value >> (size - index - 1)) & 0x1
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bitary
4
+ class Handler
5
+ class Set < Bitary::Handler
6
+ def execute(**kwargs)
7
+ raise ArgumentError unless kwargs.all? do |key, _value|
8
+ %i[index size].include?(key)
9
+ end
10
+
11
+ index = kwargs[:index] or raise KeyError
12
+ size = kwargs[:size] or raise KeyError
13
+ raise ArgumentError unless index.is_a?(Integer)
14
+ raise ArgumentError unless size.is_a?(Integer)
15
+
16
+ raise IndexError if index.negative? || index >= size
17
+
18
+ @value | (2**(size - index - 1))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bitary
4
+ class Handler
5
+ class Unset < Bitary::Handler
6
+ def execute(**kwargs)
7
+ raise ArgumentError unless kwargs.all? do |key, _value|
8
+ %i[index size].include?(key)
9
+ end
10
+
11
+ index = kwargs[:index] or raise KeyError
12
+ size = kwargs[:size] or raise KeyError
13
+ raise ArgumentError unless index.is_a?(Integer)
14
+ raise ArgumentError unless size.is_a?(Integer)
15
+
16
+ raise IndexError if index.negative? || index >= size
17
+
18
+ @value & (((2**size) - 1) - (2**(size - index - 1)))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'handler/set'
4
+
5
+ class Bitary
6
+ class Handler
7
+ attr_reader :value
8
+
9
+ def initialize(value)
10
+ raise ArgumentError unless value.is_a?(Integer)
11
+
12
+ @value = value
13
+ end
14
+
15
+ def execute(**kwargs)
16
+ raise NotImplementedError
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bitary
4
+ module Size
5
+ BYTE = 8
6
+ SHORT = 16
7
+ INT = 32
8
+ LONG = 64
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bitary
4
- VERSION = '0.1.0'
3
+ class Bitary
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/bitary.rb CHANGED
@@ -1,171 +1,164 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'bitary/size'
3
4
  require_relative 'bitary/version'
4
5
 
5
- module Bitary
6
- class BitArray
7
- attr_reader :size, :bits_per_item
6
+ class Bitary
7
+ include Size
8
8
 
9
- def initialize(initial_data, bits_per_item: 64)
10
- raise ArgumentError unless [8, 16, 32, 64].include?(bits_per_item)
9
+ attr_reader :size, :bits_per_item
11
10
 
12
- @size = init_size(initial_data, bits_per_item)
13
- @internal_array = init_internal_array(initial_data, @size, bits_per_item)
14
- @bits_per_item = bits_per_item
15
- end
11
+ def initialize(initial_data, bits_per_item: LONG)
12
+ raise ArgumentError unless [BYTE, SHORT, INT, LONG].include?(bits_per_item)
16
13
 
17
- def [](index)
18
- raise IndexError if index.negative? || index >= @size
14
+ @size = init_size(initial_data, bits_per_item)
15
+ @internal_array = init_internal_array(initial_data, @size, bits_per_item)
16
+ @bits_per_item = bits_per_item
17
+ end
19
18
 
20
- item_index = compute_item_index(index)
21
- item_bit_size = compute_item_bit_size(item_index)
22
- offset = compute_relative_offset(index, item_bit_size)
19
+ def [](index)
20
+ raise IndexError if index.negative? || index >= @size
23
21
 
24
- get_bit(@internal_array[item_index], offset)
25
- end
22
+ item_index = compute_item_index(index)
23
+ item_bit_size = compute_item_bit_size(item_index)
24
+ item = @internal_array[item_index]
26
25
 
27
- def []=(index, value)
28
- raise IndexError if index.negative? || index >= @size
29
-
30
- bit = map_to_bit(value)
31
- item_index = compute_item_index(index)
32
- item_bit_size = compute_item_bit_size(item_index)
33
- offset = compute_relative_offset(index, item_bit_size)
34
-
35
- @internal_array[item_index] =
36
- if bit == 1
37
- set_bit(@internal_array[item_index], offset)
38
- else
39
- unset_bit(
40
- @internal_array[item_index],
41
- offset,
42
- item_bit_size
43
- )
44
- end
45
- end
26
+ Handler::Get.new(item).execute(
27
+ index: index % @bits_per_item,
28
+ size: item_bit_size
29
+ )
30
+ end
46
31
 
47
- def each_byte(&proc)
48
- res = decrease_items_size(@internal_array, 8, @bits_per_item)
49
- proc ? res.each { |byte| proc.call(byte) } : res.each
50
- end
32
+ def []=(index, value)
33
+ raise IndexError if index.negative? || index >= @size
51
34
 
52
- def to_a
53
- @internal_array.clone
54
- end
35
+ bit = map_to_bit(value)
36
+ item_index = compute_item_index(index)
37
+ item_bit_size = compute_item_bit_size(item_index)
38
+ item = @internal_array[item_index]
55
39
 
56
- def to_s
57
- @internal_array.map do |item|
58
- format("%0#{@bits_per_item}d", item.to_s(2))
59
- end.join(' ')
60
- end
40
+ @internal_array[item_index] =
41
+ if bit == 1
42
+ Handler::Set.new(item).execute(
43
+ index: index % @bits_per_item,
44
+ size: item_bit_size
45
+ )
46
+ else
47
+ Handler::Unset.new(item).execute(
48
+ index: index % @bits_per_item,
49
+ size: item_bit_size
50
+ )
51
+ end
52
+ end
61
53
 
62
- def bits_per_item=(value)
63
- raise ArgumentError unless [8, 16, 32, 64].include?(value)
54
+ def set(index)
55
+ self[index] = 1
56
+ end
64
57
 
65
- @internal_array =
66
- if value > @bits_per_item
67
- increase_items_size(@internal_array, value, @bits_per_item)
68
- else
69
- decrease_items_size(@internal_array, value, @bits_per_item)
70
- end
58
+ def unset(index)
59
+ self[index] = 0
60
+ end
71
61
 
72
- @bits_per_item = value
73
- end
62
+ def each_byte(&proc)
63
+ res = decrease_items_size(@internal_array, BYTE, @bits_per_item)
64
+ proc ? res.each { |byte| proc.call(byte) } : res.each
65
+ end
74
66
 
75
- private
67
+ def to_a
68
+ @internal_array.clone
69
+ end
76
70
 
77
- def init_size(initial_data, bits_per_item)
78
- if initial_data.is_a?(Array)
79
- bits_per_item * initial_data.length
80
- else
81
- initial_data
82
- end
83
- end
71
+ def to_s
72
+ @internal_array.map do |item|
73
+ format("%0#{@bits_per_item}d", item.to_s(2))
74
+ end.join(' ')
75
+ end
84
76
 
85
- def init_internal_array(initial_data, size, bits_per_item)
86
- res = [0] * (size / bits_per_item.to_f).ceil
87
- initial_data.is_a?(Array) ? initial_data.clone : res
88
- end
77
+ def bits_per_item=(value)
78
+ raise ArgumentError unless [BYTE, SHORT, INT, LONG].include?(value)
89
79
 
90
- def map_to_bit(value)
91
- if value
92
- if value.is_a?(Integer)
93
- value.zero? ? 0 : 1
94
- else
95
- 1
96
- end
80
+ @internal_array =
81
+ if value > @bits_per_item
82
+ increase_items_size(@internal_array, value, @bits_per_item)
97
83
  else
98
- 0
84
+ decrease_items_size(@internal_array, value, @bits_per_item)
99
85
  end
100
- end
101
86
 
102
- def compute_item_bit_size(index)
103
- if index == @internal_array.length - 1
104
- size - ((@internal_array.length - 1) * @bits_per_item)
105
- else
106
- @bits_per_item
107
- end
108
- end
87
+ @bits_per_item = value
88
+ end
109
89
 
110
- def compute_item_index(index)
111
- index / @bits_per_item
112
- end
90
+ private
113
91
 
114
- def compute_relative_offset(index, size)
115
- size - (index % @bits_per_item) - 1
92
+ def init_size(initial_data, bits_per_item)
93
+ if initial_data.is_a?(Array)
94
+ bits_per_item * initial_data.length
95
+ else
96
+ initial_data
116
97
  end
98
+ end
117
99
 
118
- def set_bit(value, offset)
119
- value | (2**offset)
120
- end
100
+ def init_internal_array(initial_data, size, bits_per_item)
101
+ res = [0] * (size / bits_per_item.to_f).ceil
102
+ initial_data.is_a?(Array) ? initial_data.clone : res
103
+ end
121
104
 
122
- def unset_bit(value, offset, size)
123
- value & (((2**size) - 1) - (2**offset))
105
+ def map_to_bit(value)
106
+ if value
107
+ if value.is_a?(Integer)
108
+ value.zero? ? 0 : 1
109
+ else
110
+ 1
111
+ end
112
+ else
113
+ 0
124
114
  end
115
+ end
125
116
 
126
- def get_bit(value, offset)
127
- (value >> offset) & 0x1
117
+ def compute_item_bit_size(index)
118
+ if index == @internal_array.length - 1
119
+ size - ((@internal_array.length - 1) * @bits_per_item)
120
+ else
121
+ @bits_per_item
128
122
  end
123
+ end
129
124
 
130
- def append_bits(value, offset, bits)
131
- (value << offset) | bits
132
- end
125
+ def compute_item_index(index)
126
+ index / @bits_per_item
127
+ end
133
128
 
134
- def increase_items_size(array, new_size, bpi)
135
- processed_bits = 0
136
- array.each_with_object([0]) do |item, acc|
137
- offset = bpi
138
- if processed_bits >= new_size
139
- offset = 0
140
- acc << 0
141
- processed_bits = 0
142
- end
143
-
144
- acc[-1] = append_bits(acc[-1], offset, item)
145
- processed_bits += bpi
129
+ def increase_items_size(array, new_size, bpi)
130
+ processed_bits = 0
131
+ array.each_with_object([0]) do |value, acc|
132
+ offset = bpi
133
+ if processed_bits >= new_size
134
+ offset = 0
135
+ acc << 0
136
+ processed_bits = 0
146
137
  end
147
- end
148
138
 
149
- def decrease_items_size(array, new_size, bpi)
150
- array.each_with_object([]) do |item, acc|
151
- acc.concat(explode_item(item, new_size, bpi))
152
- end
139
+ acc[-1] = Handler::Append.new(acc[-1]).execute(offset:, value:)
140
+ processed_bits += bpi
153
141
  end
142
+ end
154
143
 
155
- def explode_item(item, new_size, bpi)
156
- res = []
157
- offset = bpi
158
- mask = (2**new_size) - 1
144
+ def decrease_items_size(array, new_size, bpi)
145
+ array.each_with_object([]) do |item, acc|
146
+ acc.concat(explode_item(item, new_size, bpi))
147
+ end
148
+ end
159
149
 
160
- while offset.positive?
161
- offset -= new_size
162
- res << ((item >> offset) & mask)
163
- end
150
+ def explode_item(item, new_size, bpi)
151
+ res = []
152
+ offset = bpi
153
+ mask = (2**new_size) - 1
164
154
 
165
- res
155
+ while offset.positive?
156
+ offset -= new_size
157
+ res << ((item >> offset) & mask)
166
158
  end
167
159
 
168
- alias at []
169
- alias set []=
160
+ res
170
161
  end
162
+
163
+ alias at []
171
164
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maximilien Ballesteros
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-26 00:00:00.000000000 Z
11
+ date: 2024-03-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby-based implementation of the bit array data structure
14
14
  email:
@@ -24,6 +24,12 @@ files:
24
24
  - README.md
25
25
  - Rakefile
26
26
  - lib/bitary.rb
27
+ - lib/bitary/handler.rb
28
+ - lib/bitary/handler/append.rb
29
+ - lib/bitary/handler/get.rb
30
+ - lib/bitary/handler/set.rb
31
+ - lib/bitary/handler/unset.rb
32
+ - lib/bitary/size.rb
27
33
  - lib/bitary/version.rb
28
34
  - sig/bitary.rbs
29
35
  homepage: https://github.com/Patacode/bitary