bitary 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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