ffi-bitfield 0.0.2 → 0.0.6
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 +4 -4
- data/README.md +1 -10
- data/lib/ffi/bit_field.rb +1 -1
- data/lib/ffi/bit_field/layout.rb +34 -0
- data/lib/ffi/bit_field/property.rb +40 -0
- data/lib/ffi/bit_field/version.rb +4 -2
- data/lib/ffi/bit_struct.rb +14 -2
- data/lib/ffi/managed_bit_struct.rb +15 -3
- metadata +5 -4
- data/lib/ffi/bit_field/bit_field_supporter.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e2586353fd6f53337bf3ffef8019d477c279c0284642165fad4d592315ccc1a
|
4
|
+
data.tar.gz: 2772a6b9ef73faeccc105c501494d6fe82079614b6e23bab14de3954d1f1d1f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/ffi/bit_struct.rb
CHANGED
@@ -2,10 +2,22 @@
|
|
2
2
|
|
3
3
|
require 'ffi'
|
4
4
|
require_relative 'bit_field/version'
|
5
|
-
require_relative 'bit_field/
|
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
|
-
|
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 '
|
5
|
-
require_relative '
|
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
|
-
|
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.
|
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-
|
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/
|
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.
|
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
|