ffi-bitfield 0.0.2 → 0.0.6

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: a8718e2b995e05ebbbfc068b45acef79a24b371905ec0afc4fe828d608f56a32
4
- data.tar.gz: e303e6e22a0927d312934fd9085f6b4e7a19ee10361fafe90c465462d8b1de9d
3
+ metadata.gz: 8e2586353fd6f53337bf3ffef8019d477c279c0284642165fad4d592315ccc1a
4
+ data.tar.gz: 2772a6b9ef73faeccc105c501494d6fe82079614b6e23bab14de3954d1f1d1f2
5
5
  SHA512:
6
- metadata.gz: 54b27c548d1f4d1ec0373f7f0d60a6079b9b3c471be0e773aabe8d5c8dfabee6cdaaa6a2a8982fdec4b3d34cc301817b329e32d734187c1b8bb8dfa44cd427cd
7
- data.tar.gz: 163eb57089a2b6f88ada99a2ff9909a7c7bf34dc1bf56afa1665441de7232117df779107250ea66086024689a32c5fabb8e611c8d53af53552208f6cac9818bb
6
+ metadata.gz: 911015a3478c323f4469076489e68d7634d12188200dea1e8ae76263af368b992fb424c6f086cc46cb30aa501ca12326039a8a6a184524e2f54b6cb35f2495c1
7
+ data.tar.gz: 82951de5f89c776408d35e656a8ce100c1306899e808569dd181cd5c56bfbee961329ac989455b9814e5815928227e732d4ea1e8d21a09141fadcb00cce49760
data/README.md CHANGED
@@ -5,8 +5,6 @@
5
5
 
6
6
  Bit field for [Ruby-FFI](https://github.com/ffi/ffi)
7
7
 
8
- :construction: alpha ー Supports reading bit fields only.
9
-
10
8
  ## Installation
11
9
 
12
10
  ```sh
@@ -61,15 +59,7 @@ require 'ffi/managed_bit_struct'
61
59
  ```md
62
60
  * module FFI
63
61
  * class BitStruct < FFI::Struct
64
- * include BitFieldSupporter
65
-
66
62
  * class ManagedBitStruct < FFI::ManagedStruct
67
- * include BitFieldSupporter
68
-
69
- * module BitField
70
- * module BitFieldSupporter
71
- * bit_fields
72
- * bit_field <- alias of bit_fields
73
63
  ```
74
64
 
75
65
  ## Development
@@ -83,6 +73,7 @@ bundle exec rake test
83
73
 
84
74
  ## Contributing
85
75
 
76
+ ffi-bitfield is a library under development, so even small improvements like typofix are welcome! Please feel free to send us your pull requests.
86
77
  Bug reports and pull requests are welcome on GitHub at https://github.com/kojix2/bitstruct.
87
78
 
88
79
  ## License
data/lib/ffi/bit_field.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'bit_field/version'
4
- require_relative 'bit_field/bit_field_supporter'
5
4
  require_relative 'bit_struct'
6
5
  require_relative 'managed_bit_struct'
7
6
 
8
7
  module FFI
8
+ # This module is just a namespace.
9
9
  module BitField
10
10
  end
11
11
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FFI
4
+ module BitField
5
+ # Layout provides the `bit_fields` method for registering field members.
6
+ module Layout
7
+ # @param [Array] layout_args
8
+ # @return [Symbol] parent_name
9
+ def bit_fields(*layout_args)
10
+ # The reason for using class instance variable here instead of class variable
11
+ # is not because class instance variables are clean,
12
+ # but because sub-class of FFI::Struct cannot be inherited again.
13
+ @bit_field_hash_table = {} unless instance_variable_defined?(:@bit_field_hash_table)
14
+
15
+ parent_name = layout_args.shift.to_sym
16
+ member_names = []
17
+ widths = []
18
+ layout_args.each_slice(2) do |name, width|
19
+ member_names << name.to_sym
20
+ widths << width.to_i
21
+ end
22
+ starts = widths.inject([0]) do |result, width|
23
+ result << (result.last + width)
24
+ end
25
+ member_names.zip(starts, widths).each do |name, start, width|
26
+ @bit_field_hash_table[name] = [parent_name, start, width]
27
+ end
28
+
29
+ parent_name
30
+ end
31
+ alias bit_field bit_fields
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FFI
4
+ module BitField
5
+ # Properties provides methods to read and write bit fields.
6
+ module Property
7
+ # @param [Symbol] member_name
8
+ # @return [Integer] value
9
+ def [](member_name)
10
+ parent_name, start, width = member_value_info(member_name)
11
+ if parent_name
12
+ value = get_member_value(parent_name)
13
+ value[start, width]
14
+ else
15
+ get_member_value(member_name)
16
+ end
17
+ end
18
+
19
+ def []=(member_name, value)
20
+ parent_name, start, width = member_value_info(member_name)
21
+ if parent_name
22
+ raise "Value #{value} is larger than bit_length: #{width}" if value.bit_length > width
23
+
24
+ parent_value = get_member_value(parent_name)
25
+ new_value = (((1 << width) - 1 << start) & parent_value ^ parent_value) |
26
+ (value << start)
27
+ set_member_value(parent_name, new_value)
28
+ else
29
+ set_member_value(member_name, value)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def member_value_info(member_name)
36
+ self.class.instance_variable_get(:@bit_field_hash_table)[member_name]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FFI
2
4
  module BitField
3
- VERSION="0.0.2"
5
+ VERSION = '0.0.6'
4
6
  end
5
- end
7
+ end
@@ -2,10 +2,22 @@
2
2
 
3
3
  require 'ffi'
4
4
  require_relative 'bit_field/version'
5
- require_relative 'bit_field/bit_field_supporter'
5
+ require_relative 'bit_field/layout'
6
+ require_relative 'bit_field/property'
6
7
 
7
8
  module FFI
9
+ # Subclass of FFI::Struct that support bit fields.
8
10
  class BitStruct < Struct
9
- extend BitField::BitFiledSupporter
11
+ # [] is defined in FFI::Struct
12
+ alias get_member_value []
13
+ alias set_member_value []=
14
+ extend BitField::Layout
15
+ # The Property module included in the FFI::ManagedBitStruct class is
16
+ # * behind the FFI::ManagedBitStruct class, but is
17
+ # * in FRONT of the FFI::Struct class.
18
+ # `MStruct.ancestors`
19
+ # # => [MStruct, FFI::ManagedBitStruct, FFI::BitField::Property, FFI::ManagedStruct, FFI::Struct...]
20
+ # So you do not need to use `prepend` instead of `include`.
21
+ include BitField::Property
10
22
  end
11
23
  end
@@ -1,11 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ffi'
4
- require_relative 'bit_struct/version'
5
- require_relative 'bit_field_supporter'
4
+ require_relative 'bit_field/version'
5
+ require_relative 'bit_field/layout'
6
+ require_relative 'bit_field/property'
6
7
 
7
8
  module FFI
9
+ # Subclass of FFI::ManagedStruct that support bit fields.
8
10
  class ManagedBitStruct < ManagedStruct
9
- extend BitFiledSupporter
11
+ # [] is defined in FFI::Struct
12
+ alias get_member_value []
13
+ alias set_member_value []=
14
+ extend BitField::Layout
15
+ # The Property module included in the FFI::BitStruct class is
16
+ # * behind the FFI::BitStruct class, but is
17
+ # * in FRONT of the FFI::Struct class.
18
+ # `YourStruct.ancestors`
19
+ # # => [YourStruct, FFI::BitStruct, FFI::BitField::Property, FFI::Struct...]
20
+ # So you do not need to use `prepend` instead of `include`.
21
+ include BitField::Property
10
22
  end
11
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-bitfield
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - kojix2
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-16 00:00:00.000000000 Z
11
+ date: 2021-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -104,7 +104,8 @@ files:
104
104
  - LICENSE.txt
105
105
  - README.md
106
106
  - lib/ffi/bit_field.rb
107
- - lib/ffi/bit_field/bit_field_supporter.rb
107
+ - lib/ffi/bit_field/layout.rb
108
+ - lib/ffi/bit_field/property.rb
108
109
  - lib/ffi/bit_field/version.rb
109
110
  - lib/ffi/bit_struct.rb
110
111
  - lib/ffi/managed_bit_struct.rb
@@ -120,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
121
  requirements:
121
122
  - - ">="
122
123
  - !ruby/object:Gem::Version
123
- version: '2.4'
124
+ version: '2.7'
124
125
  required_rubygems_version: !ruby/object:Gem::Requirement
125
126
  requirements:
126
127
  - - ">="
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FFI
4
- module BitField
5
- module BitFiledSupporter
6
- module BitFieldModule
7
- def [](name)
8
- bit_fields = self.class.bit_fields_hash_table
9
- parent, start, width = bit_fields[name]
10
- if parent
11
- (super(parent) >> start) & ((1 << width) - 1)
12
- else
13
- super(name)
14
- end
15
- end
16
- end
17
- private_constant :BitFieldModule
18
-
19
- attr_reader :bit_fields_hash_table
20
-
21
- def bit_fields(*args)
22
- unless instance_variable_defined?(:@bit_fields_hash_table)
23
- @bit_fields_hash_table = {}
24
- prepend BitFieldModule
25
- end
26
-
27
- parent = args.shift
28
- labels = []
29
- widths = []
30
- args.each_slice(2) do |l, w|
31
- labels << l
32
- widths << w
33
- end
34
- starts = widths.inject([0]) do |result, w|
35
- result << (result.last + w)
36
- end
37
- labels.zip(starts, widths).each do |l, s, w|
38
- @bit_fields_hash_table[l] = [parent, s, w]
39
- end
40
- end
41
- alias bit_field bit_fields
42
- end
43
- end
44
- end