ffi-bit_masks 0.1.0
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 +7 -0
- data/.document +3 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +43 -0
- data/Rakefile +40 -0
- data/ffi-bit_masks.gemspec +60 -0
- data/gemspec.yml +17 -0
- data/lib/ffi/bit_masks.rb +31 -0
- data/lib/ffi/bit_masks/bit_mask.rb +187 -0
- data/lib/ffi/bit_masks/version.rb +6 -0
- data/spec/bit_mask_spec.rb +157 -0
- data/spec/bit_masks_spec.rb +28 -0
- data/spec/spec_helper.rb +5 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 297221cec74737fc8f7bb7979a4e0d1bac269816
|
4
|
+
data.tar.gz: ac741bdecf847e163e07e008cce18d795b635787
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a8180e2b600f5c91cd9aeacc30f0cc6de01a0f5cf8636dc0f73300a1fec87d434f07c2d2d700440decd80eee997d4f6acbeaa593356a7ec75963a8886d0ca8d
|
7
|
+
data.tar.gz: dde56b83e995fe73ba6d38f1fe85fb40733309c2e5267089792edb18c6e8518faaedd2f69f1ff03a499124c48ce38fb0807d8feb1e216ac893d104298c4d7236
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title "ffi-bit_masks Documentation" --protected
|
data/ChangeLog.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012-2013 Hal Brodigan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# ffi-bit_masks
|
2
|
+
|
3
|
+
* [Homepage](https://github.com/postmodern/ffi-bit_masks#readme)
|
4
|
+
* [Issues](https://github.com/postmodern/ffi-bit_masks/issues)
|
5
|
+
* [Documentation](http://rubydoc.info/gems/ffi-bit_masks/frames)
|
6
|
+
* [Email](mailto:postmodern.mod3 at gmail.com)
|
7
|
+
|
8
|
+
## Description
|
9
|
+
|
10
|
+
FFI plugin which adds support for bitmasked types (or flags) to FFI.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* Can map a Hash of flags to their bitmask value.
|
15
|
+
* Can map an Integer bitmask to a Hash of flags.
|
16
|
+
|
17
|
+
## Examples
|
18
|
+
|
19
|
+
require 'ffi/bit_masks'
|
20
|
+
|
21
|
+
module MyLibrary
|
22
|
+
extend FFI::Library
|
23
|
+
|
24
|
+
ffi_lib 'foo'
|
25
|
+
|
26
|
+
bit_mask :flags, {foo: 0x1, bar: 0x2, baz: 0x4}
|
27
|
+
|
28
|
+
attach_function :my_func, [:pointer, :size_t, :flags], :int
|
29
|
+
end
|
30
|
+
|
31
|
+
## Requirements
|
32
|
+
|
33
|
+
* [ffi](https://github.com/ffi/ffi#readme) ~> 1.0
|
34
|
+
|
35
|
+
## Install
|
36
|
+
|
37
|
+
$ gem install ffi-bit_masks
|
38
|
+
|
39
|
+
## Copyright
|
40
|
+
|
41
|
+
Copyright (c) 2012-2013 Hal Brodigan
|
42
|
+
|
43
|
+
See {file:LICENSE.txt} for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
begin
|
7
|
+
gem 'rubygems-tasks', '~> 0.2'
|
8
|
+
require 'rubygems/tasks'
|
9
|
+
|
10
|
+
Gem::Tasks.new
|
11
|
+
rescue LoadError => e
|
12
|
+
warn e.message
|
13
|
+
warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
gem 'rspec', '~> 2.4'
|
18
|
+
require 'rspec/core/rake_task'
|
19
|
+
|
20
|
+
RSpec::Core::RakeTask.new
|
21
|
+
rescue LoadError => e
|
22
|
+
task :spec do
|
23
|
+
abort "Please run `gem install rspec` to install RSpec."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
task :test => :spec
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
begin
|
31
|
+
gem 'yard', '~> 0.8'
|
32
|
+
require 'yard'
|
33
|
+
|
34
|
+
YARD::Rake::YardocTask.new
|
35
|
+
rescue LoadError => e
|
36
|
+
task :yard do
|
37
|
+
abort "Please run `gem install yard` to install YARD."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
task :doc => :yard
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gemspec = YAML.load_file('gemspec.yml')
|
7
|
+
|
8
|
+
gem.name = gemspec.fetch('name')
|
9
|
+
gem.version = gemspec.fetch('version') do
|
10
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
|
+
|
13
|
+
require 'ffi/bit_masks/version'
|
14
|
+
FFI::BitMasks::VERSION
|
15
|
+
end
|
16
|
+
|
17
|
+
gem.summary = gemspec['summary']
|
18
|
+
gem.description = gemspec['description']
|
19
|
+
gem.licenses = Array(gemspec['license'])
|
20
|
+
gem.authors = Array(gemspec['authors'])
|
21
|
+
gem.email = gemspec['email']
|
22
|
+
gem.homepage = gemspec['homepage']
|
23
|
+
|
24
|
+
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
25
|
+
|
26
|
+
gem.files = `git ls-files`.split($/)
|
27
|
+
gem.files = glob[gemspec['files']] if gemspec['files']
|
28
|
+
|
29
|
+
gem.executables = gemspec.fetch('executables') do
|
30
|
+
glob['bin/*'].map { |path| File.basename(path) }
|
31
|
+
end
|
32
|
+
gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
|
33
|
+
|
34
|
+
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
35
|
+
gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
|
36
|
+
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
37
|
+
|
38
|
+
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
39
|
+
%w[ext lib].select { |dir| File.directory?(dir) }
|
40
|
+
})
|
41
|
+
|
42
|
+
gem.requirements = gemspec['requirements']
|
43
|
+
gem.required_ruby_version = gemspec['required_ruby_version']
|
44
|
+
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
45
|
+
gem.post_install_message = gemspec['post_install_message']
|
46
|
+
|
47
|
+
split = lambda { |string| string.split(/,\s*/) }
|
48
|
+
|
49
|
+
if gemspec['dependencies']
|
50
|
+
gemspec['dependencies'].each do |name,versions|
|
51
|
+
gem.add_dependency(name,split[versions])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if gemspec['development_dependencies']
|
56
|
+
gemspec['development_dependencies'].each do |name,versions|
|
57
|
+
gem.add_development_dependency(name,split[versions])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/gemspec.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
name: ffi-bit_masks
|
2
|
+
summary: Adds support for bit-masked types in FFI.
|
3
|
+
description:
|
4
|
+
FFI plugin which adds support for bitmasked types (or flags) to FFI.
|
5
|
+
|
6
|
+
license: MIT
|
7
|
+
authors: Postmodern
|
8
|
+
email: postmodern.mod3@gmail.com
|
9
|
+
homepage: https://github.com/postmodern/ffi-bit_masks#readme
|
10
|
+
|
11
|
+
dependencies:
|
12
|
+
ffi: ~> 1.0
|
13
|
+
|
14
|
+
development_dependencies:
|
15
|
+
rspec: ~> 2.4
|
16
|
+
rubygems-tasks: ~> 0.2
|
17
|
+
yard: ~> 0.8
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'ffi/bit_masks/bit_mask'
|
2
|
+
require 'ffi/bit_masks/version'
|
3
|
+
|
4
|
+
module FFI
|
5
|
+
#
|
6
|
+
# Adds bitmask types to FFI libraries.
|
7
|
+
#
|
8
|
+
module BitMasks
|
9
|
+
#
|
10
|
+
# Defines a new bitmask.
|
11
|
+
#
|
12
|
+
# @param [Symbol] name
|
13
|
+
# The name of the bitmask.
|
14
|
+
#
|
15
|
+
# @param [Hash{Symbol => Integer}] flags
|
16
|
+
# The flags and their masks.
|
17
|
+
#
|
18
|
+
# @param [Symbol] type
|
19
|
+
# The underlying type.
|
20
|
+
#
|
21
|
+
# @return [BitMask]
|
22
|
+
# The new bitmask.
|
23
|
+
#
|
24
|
+
def bit_mask(name,flags,type=:uint)
|
25
|
+
bit_mask = BitMask.new(flags,type)
|
26
|
+
|
27
|
+
typedef(bit_mask,name)
|
28
|
+
return bit_mask
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
module BitMasks
|
5
|
+
#
|
6
|
+
# The bitmask data converter.
|
7
|
+
#
|
8
|
+
class BitMask
|
9
|
+
|
10
|
+
include DataConverter
|
11
|
+
|
12
|
+
#
|
13
|
+
# Flags of the bitmask.
|
14
|
+
#
|
15
|
+
# @return [Hash{Symbol => Integer}]
|
16
|
+
# The mapping of bit-flags to bitmasks.
|
17
|
+
#
|
18
|
+
attr_reader :flags
|
19
|
+
|
20
|
+
#
|
21
|
+
# The masks of the bitmask.
|
22
|
+
#
|
23
|
+
# @return [Hash{Integer => Symbol}]
|
24
|
+
# The mapping of bitmasks to bit-flags.
|
25
|
+
#
|
26
|
+
attr_reader :bitmasks
|
27
|
+
|
28
|
+
#
|
29
|
+
# The underlying native type.
|
30
|
+
#
|
31
|
+
# @return [FFI::Type]
|
32
|
+
# The FFI primitive.
|
33
|
+
#
|
34
|
+
attr_reader :native_type
|
35
|
+
|
36
|
+
#
|
37
|
+
# Initializes a new bitmask.
|
38
|
+
#
|
39
|
+
# @param [Hash{Symbol => Integer}] flags
|
40
|
+
# The flags and their masks.
|
41
|
+
#
|
42
|
+
# @param [Symbol] type
|
43
|
+
# The underlying type.
|
44
|
+
#
|
45
|
+
def initialize(flags,type=:uint)
|
46
|
+
@flags = flags
|
47
|
+
@bitmasks = flags.invert
|
48
|
+
@native_type = FFI.find_type(type)
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# The Symbols that can be passed to the data converter.
|
53
|
+
#
|
54
|
+
# @return [Array<Symbol>]
|
55
|
+
# The Array of Symbols.
|
56
|
+
#
|
57
|
+
# @note For compatibility with `FFI::Enum`.
|
58
|
+
#
|
59
|
+
def symbols
|
60
|
+
@flags.keys
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# The mapping of acceptable Symbols to their Integer equivalents.
|
65
|
+
#
|
66
|
+
# @return [Hash{Symbol => Integer}]
|
67
|
+
# The mapping of Symbols.
|
68
|
+
#
|
69
|
+
# @note For compatibility with `FFI::Enum`.
|
70
|
+
#
|
71
|
+
def symbol_map
|
72
|
+
@flags
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# @note For compatibility with `FFI::Enum`.
|
77
|
+
#
|
78
|
+
alias to_h symbol_map
|
79
|
+
|
80
|
+
#
|
81
|
+
# @note For compatibility with `FFI::Enum`.
|
82
|
+
#
|
83
|
+
alias to_hash symbol_map
|
84
|
+
|
85
|
+
#
|
86
|
+
# Maps flags to masks and vice versa.
|
87
|
+
#
|
88
|
+
# @overload [](query)
|
89
|
+
#
|
90
|
+
# @param [Symbol] query
|
91
|
+
# The flag name.
|
92
|
+
#
|
93
|
+
# @return [Integer]
|
94
|
+
# The mask for the flag.
|
95
|
+
#
|
96
|
+
# @overload [](query)
|
97
|
+
#
|
98
|
+
# @param [Integer] query
|
99
|
+
# The mask.
|
100
|
+
#
|
101
|
+
# @return [Symbol]
|
102
|
+
# The flag for the mask.
|
103
|
+
#
|
104
|
+
def [](query)
|
105
|
+
case query
|
106
|
+
when Symbol then @flags[query]
|
107
|
+
when Integer then @bitmasks[query]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# @note For compatibility with `FFI::Enum`.
|
113
|
+
#
|
114
|
+
alias find []
|
115
|
+
|
116
|
+
#
|
117
|
+
# Converts flags to a bitmask.
|
118
|
+
#
|
119
|
+
# @overload to_native(value)
|
120
|
+
#
|
121
|
+
# @param [Hash{Symbol => Boolean}] value
|
122
|
+
# The flags and their values.
|
123
|
+
#
|
124
|
+
# @return [Integer]
|
125
|
+
# The bitmask for the given flags.
|
126
|
+
#
|
127
|
+
# @overload to_native(value)
|
128
|
+
#
|
129
|
+
# @param [#to_int] value
|
130
|
+
# The raw bitmask.
|
131
|
+
#
|
132
|
+
# @return [Integer]
|
133
|
+
# The bitmask.
|
134
|
+
#
|
135
|
+
# @raise [ArgumentError]
|
136
|
+
#
|
137
|
+
def to_native(value,ctx=nil)
|
138
|
+
uint = 0
|
139
|
+
|
140
|
+
case value
|
141
|
+
when Hash
|
142
|
+
uint = 0
|
143
|
+
|
144
|
+
value.each do |flag,value|
|
145
|
+
if (@flags.has_key?(flag) && value)
|
146
|
+
uint |= @flags[flag]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
return uint
|
151
|
+
else
|
152
|
+
if value.respond_to?(:to_int)
|
153
|
+
int = value.to_int
|
154
|
+
|
155
|
+
@bitmasks.each_key do |mask|
|
156
|
+
uint |= (int & mask)
|
157
|
+
end
|
158
|
+
|
159
|
+
return uint
|
160
|
+
else
|
161
|
+
raise(ArgumentError,"invalid bitmask value #{value.inspect}")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Converts a bitmask into multiple flags.
|
168
|
+
#
|
169
|
+
# @param [Integer] value
|
170
|
+
# The raw bitmask.
|
171
|
+
#
|
172
|
+
# @return [Hash{Symbol => Boolean}]
|
173
|
+
# The flags for the bitmask.
|
174
|
+
#
|
175
|
+
def from_native(value,ctx=nil)
|
176
|
+
flags = {}
|
177
|
+
|
178
|
+
@flags.each do |flag,bitmask|
|
179
|
+
flags[flag] ||= ((value & bitmask) == bitmask)
|
180
|
+
end
|
181
|
+
|
182
|
+
return flags
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ffi/bit_masks/bit_mask'
|
3
|
+
|
4
|
+
describe FFI::BitMasks::BitMask do
|
5
|
+
let(:flags) { {:foo => 0x1, :bar => 0x2, :baz => 0x4} }
|
6
|
+
|
7
|
+
subject { described_class.new(flags) }
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
subject { described_class.new(flags) }
|
11
|
+
|
12
|
+
it "should initialize the flags" do
|
13
|
+
subject.flags.should == flags
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should invert the flags into bitmasks" do
|
17
|
+
subject.bitmasks.should == flags.invert
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should default type to uint" do
|
21
|
+
subject.native_type.should == FFI::Type::UINT
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when given a custom type" do
|
25
|
+
subject { described_class.new(flags,:ushort) }
|
26
|
+
|
27
|
+
it "should set native type" do
|
28
|
+
subject.native_type.should == FFI::Type::USHORT
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#symbols" do
|
34
|
+
it "should return the names of the flags" do
|
35
|
+
subject.symbols.should == flags.keys
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#symbol_map" do
|
40
|
+
it "should return the flags" do
|
41
|
+
subject.symbol_map.should == flags
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#to_h" do
|
46
|
+
it "should return the flags" do
|
47
|
+
subject.to_h.should == flags
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#to_hash" do
|
52
|
+
it "should return the flags" do
|
53
|
+
subject.to_hash.should == flags
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#[]" do
|
58
|
+
context "when given a Symbol" do
|
59
|
+
it "should lookup the bitmask" do
|
60
|
+
subject[:bar].should == flags[:bar]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when given an Integer" do
|
65
|
+
it "should lookup the flag" do
|
66
|
+
subject[flags[:bar]].should == :bar
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "otherwise" do
|
71
|
+
it "should return nil" do
|
72
|
+
subject[Object.new].should be_nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#to_native" do
|
78
|
+
context "when given a Hash" do
|
79
|
+
let(:hash) { {:foo => true, :bar => true, :baz => false} }
|
80
|
+
|
81
|
+
it "should bitwise or together the flag masks" do
|
82
|
+
subject.to_native(hash).should == (flags[:foo] | flags[:bar])
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when one of the keys does not correspond to a flag" do
|
86
|
+
let(:hash) { {:foo => true, :bug => true, :baz => true} }
|
87
|
+
|
88
|
+
it "should ignore the key" do
|
89
|
+
subject.to_native(hash).should == (flags[:foo] | flags[:baz])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when an Object that respnds to #to_int" do
|
95
|
+
let(:int) { 0x3 }
|
96
|
+
|
97
|
+
it "should call #to_int" do
|
98
|
+
subject.to_native(int).should == 0x3
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when given a bitmask that contains unknown masks" do
|
102
|
+
let(:int) { flags[:foo] | flags[:bar] | 0x8 | 0x10 }
|
103
|
+
|
104
|
+
it "should filter out the unknown masks" do
|
105
|
+
subject.to_native(int).should == (
|
106
|
+
flags[:foo] | flags[:bar]
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when given an Object that does not respond to #to_int" do
|
113
|
+
it "should raise an ArgumentError" do
|
114
|
+
lambda {
|
115
|
+
subject.to_native(Object.new)
|
116
|
+
}.should raise_error(ArgumentError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#from_native" do
|
122
|
+
let(:value) { flags[:foo] | flags[:baz] }
|
123
|
+
|
124
|
+
it "should set the flags from the value" do
|
125
|
+
subject.from_native(value).should == {
|
126
|
+
:foo => true,
|
127
|
+
:bar => false,
|
128
|
+
:baz => true
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when one flag is a combination of other flags" do
|
133
|
+
let(:flags) { {:foo => 0x1, :bar => 0x2, :baz => 0x3} }
|
134
|
+
let(:value) { flags[:foo] | flags[:bar] }
|
135
|
+
|
136
|
+
it "should set all flags whose bitmasks are present" do
|
137
|
+
subject.from_native(value).should == {
|
138
|
+
:foo => true,
|
139
|
+
:bar => true,
|
140
|
+
:baz => true
|
141
|
+
}
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when given a value that contains unknown masks" do
|
146
|
+
let(:value) { flags[:foo] | flags[:baz] | 0x8 | 0x10 }
|
147
|
+
|
148
|
+
it "should ignore the unknown flags" do
|
149
|
+
subject.from_native(value).should == {
|
150
|
+
:foo => true,
|
151
|
+
:bar => false,
|
152
|
+
:baz => true
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ffi/bit_masks'
|
3
|
+
|
4
|
+
describe FFI::BitMasks do
|
5
|
+
it "should have a VERSION constant" do
|
6
|
+
subject.const_get('VERSION').should_not be_empty
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#bit_mask" do
|
10
|
+
subject do
|
11
|
+
mod = Module.new
|
12
|
+
mod.extend FFI::Library
|
13
|
+
mod.extend FFI::BitMasks
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:flags) { {:foo => 0x1, :bar => 0x2, :baz => 0x4} }
|
17
|
+
|
18
|
+
it "should return a BitMask object" do
|
19
|
+
subject.bit_mask(:flags,flags).flags.should == flags
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should define a typedef for the bitmask" do
|
23
|
+
bitmask = subject.bit_mask(:flags,flags)
|
24
|
+
|
25
|
+
subject.find_type(:flags).should be_kind_of(FFI::Type::Mapped)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-bit_masks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Postmodern
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubygems-tasks
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
description: FFI plugin which adds support for bitmasked types (or flags) to FFI.
|
70
|
+
email: postmodern.mod3@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files:
|
74
|
+
- ChangeLog.md
|
75
|
+
- LICENSE.txt
|
76
|
+
- README.md
|
77
|
+
files:
|
78
|
+
- .document
|
79
|
+
- .gitignore
|
80
|
+
- .rspec
|
81
|
+
- .yardopts
|
82
|
+
- ChangeLog.md
|
83
|
+
- LICENSE.txt
|
84
|
+
- README.md
|
85
|
+
- Rakefile
|
86
|
+
- ffi-bit_masks.gemspec
|
87
|
+
- gemspec.yml
|
88
|
+
- lib/ffi/bit_masks.rb
|
89
|
+
- lib/ffi/bit_masks/bit_mask.rb
|
90
|
+
- lib/ffi/bit_masks/version.rb
|
91
|
+
- spec/bit_mask_spec.rb
|
92
|
+
- spec/bit_masks_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
homepage: https://github.com/postmodern/ffi-bit_masks#readme
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.0.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Adds support for bit-masked types in FFI.
|
118
|
+
test_files: []
|