ffi-bitmask 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/LICENSE +22 -0
- data/ffi-bitmask.gemspec +14 -0
- data/lib/ffi/bitmask.rb +187 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3681418ee2db1b007487476afed2485816a6cc14
|
4
|
+
data.tar.gz: 5f298ec2fe516b944cd2bc673d5d25432e15244a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17e1f79c5d59626aa3c79940934f4faa575944744c0a1ddd215113c660b0ae7cbe09ef669b29dc3a8cf8676ed10a29ce8ea94d269ccf26d40318bcd93b4710b7
|
7
|
+
data.tar.gz: 6dc63fc275382adeedb11f46aa70e47b256820d552a237e041e7964fe580909e638550ec6c7dca529fe18485199fe851253eda488ee0d6db6e0978d3d6ef8c49
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017, Brice Videau <brice.videau@imag.fr>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
20
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/ffi-bitmask.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ffi-bitmask'
|
3
|
+
s.version = "0.1.0"
|
4
|
+
s.author = "Brice Videau"
|
5
|
+
s.email = "brice.videau@imag.fr"
|
6
|
+
s.homepage = "https://github.com/Nanosim-LIG/ffi-bitmask"
|
7
|
+
s.summary = "bitmask support for ffi"
|
8
|
+
s.description = "bitmask support for ffi heavily relying on FFI internals"
|
9
|
+
s.files = Dir['ffi-bitmask.gemspec', 'LICENSE', 'lib/**/*']
|
10
|
+
s.has_rdoc = true
|
11
|
+
s.license = 'BSD-2-Clause'
|
12
|
+
s.required_ruby_version = '>= 1.9.3'
|
13
|
+
s.add_dependency 'ffi', '~> 1.9', '>=1.9.3'
|
14
|
+
end
|
data/lib/ffi/bitmask.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
|
5
|
+
module Library
|
6
|
+
|
7
|
+
# @overload bitmask(name, values)
|
8
|
+
# Create a named bitmask
|
9
|
+
# @example
|
10
|
+
# bitmask :foo, [:red, :green, :blue] # bits 0,1,2 are used
|
11
|
+
# bitmask :foo, [:red, :green, 5, :blue] # bits 0,5,6 are used
|
12
|
+
# @param [Symbol] name for new bitmask
|
13
|
+
# @param [Array<Symbol, Integer>] values for new bitmask
|
14
|
+
# @overload bitmask(*args)
|
15
|
+
# Create an unamed bitmask
|
16
|
+
# @example
|
17
|
+
# bm = bitmask :red, :green, :blue # bits 0,1,2 are used
|
18
|
+
# bm = bitmask :red, :green, 5, blue # bits 0,5,6 are used
|
19
|
+
# @param [Symbol, Integer] args values for new bitmask
|
20
|
+
# @overload bitmask(values)
|
21
|
+
# Create an unamed bitmask
|
22
|
+
# @example
|
23
|
+
# bm = bitmask [:red, :green, :blue] # bits 0,1,2 are used
|
24
|
+
# bm = bitmask [:red, :green, 5, blue] # bits 0,5,6 are used
|
25
|
+
# @param [Array<Symbol, Integer>] values for new bitmask
|
26
|
+
# @overload bitmask(native_type, name, values)
|
27
|
+
# Create a named enum and specify the native type.
|
28
|
+
# @example
|
29
|
+
# bitmask FFI::Type::UINT64, :foo, [:red, :green, :blue]
|
30
|
+
# @param [FFI::Type] native_type native type for new bitmask
|
31
|
+
# @param [Symbol] name for new bitmask
|
32
|
+
# @param [Array<Symbol, Integer>] values for new bitmask
|
33
|
+
# @overload bitmask(native_type, *args)
|
34
|
+
# @example
|
35
|
+
# bitmask FFI::Type::UINT64, :red, :green, :blue
|
36
|
+
# @param [FFI::Type] native_type native type for new bitmask
|
37
|
+
# @param [Symbol, Integer] args values for new bitmask
|
38
|
+
# @overload bitmask(native_type, values)
|
39
|
+
# Create a named enum and specify the native type.
|
40
|
+
# @example
|
41
|
+
# bitmask FFI::Type::UINT64, [:red, :green, :blue]
|
42
|
+
# @param [FFI::Type] native_type native type for new bitmask
|
43
|
+
# @param [Array<Symbol, Integer>] values for new bitmask
|
44
|
+
# @return [FFI::Bitmask]
|
45
|
+
# Create a new FFI::Bitmask
|
46
|
+
def bitmask(*args)
|
47
|
+
native_type = args.first.kind_of?(FFI::Type) ? args.shift : nil
|
48
|
+
name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array)
|
49
|
+
[ args[0], args[1] ]
|
50
|
+
elsif args[0].kind_of?(Array)
|
51
|
+
[ nil, args[0] ]
|
52
|
+
else
|
53
|
+
[ nil, args ]
|
54
|
+
end
|
55
|
+
@ffi_enums = FFI::Enums.new unless defined?(@ffi_enums)
|
56
|
+
@ffi_enums << (e = native_type ? FFI::Bitmask.new(native_type, values, name) : FFI::Bitmask.new(values, name))
|
57
|
+
|
58
|
+
typedef(e, name) if name
|
59
|
+
e
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Represents a C enum whose values are power of 2
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# enum {
|
68
|
+
# red = (1<<0),
|
69
|
+
# green = (1<<1),
|
70
|
+
# blue = (1<<2)
|
71
|
+
# }
|
72
|
+
#
|
73
|
+
# Contrary to classical enums, bitmask values are usually combined
|
74
|
+
# when used.
|
75
|
+
class Bitmask < Enum
|
76
|
+
|
77
|
+
# @overload initialize(info, tag=nil)
|
78
|
+
# @param [nil, Enumerable] info symbols and bit rank for new Bitmask
|
79
|
+
# @param [nil, Symbol] tag name of new Bitmask
|
80
|
+
# @overload initialize(native_type, info, tag=nil)
|
81
|
+
# @param [FFI::Type] native_type Native type for new Bitmask
|
82
|
+
# @param [nil, Enumerable] info symbols and bit rank for new Bitmask
|
83
|
+
# @param [nil, Symbol] tag name of new Bitmask
|
84
|
+
def initialize(*args)
|
85
|
+
@native_type = args.first.kind_of?(FFI::Type) ? args.shift : Type::INT
|
86
|
+
info, @tag = *args
|
87
|
+
@kv_map = Hash.new
|
88
|
+
unless info.nil?
|
89
|
+
last_cst = nil
|
90
|
+
value = 0
|
91
|
+
info.each do |i|
|
92
|
+
case i
|
93
|
+
when Symbol
|
94
|
+
raise ArgumentError, "duplicate bitmask key" if @kv_map.has_key?(i)
|
95
|
+
@kv_map[i] = 1 << value
|
96
|
+
last_cst = i
|
97
|
+
value += 1
|
98
|
+
when Integer
|
99
|
+
raise ArgumentError, "bitmask index should be positive" if i<0
|
100
|
+
@kv_map[last_cst] = 1 << i
|
101
|
+
value = i+1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@vk_map = @kv_map.invert
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get a symbol list or a value from the bitmask
|
109
|
+
# @overload [](*query)
|
110
|
+
# Get bitmask value from symbol list
|
111
|
+
# @param [Symbol] query
|
112
|
+
# @return [Integer]
|
113
|
+
# @overload [](query)
|
114
|
+
# Get bitmaks value from symbol array
|
115
|
+
# @param [Array<Symbol>] query
|
116
|
+
# @return [Integer]
|
117
|
+
# @overload [](*query)
|
118
|
+
# Get a list of bitmask symbols corresponding to
|
119
|
+
# the or reduction of a list of integer
|
120
|
+
# @param [Integer] query
|
121
|
+
# @return [Array<Symbol>]
|
122
|
+
# @overload [](query)
|
123
|
+
# Get a list of bitmask symbols corresponding to
|
124
|
+
# the or reduction of a list of integer
|
125
|
+
# @param [Array<Integer>] query
|
126
|
+
# @return [Array<Symbol>]
|
127
|
+
def [](*query)
|
128
|
+
flat_query = query.flatten
|
129
|
+
raise ArgumentError, "query should be homogeneous, #{query.inspect}" unless flat_query.all? { |o| o.is_a?(Symbol) } || flat_query.all? { |o| o.is_a?(Integer) || o.respond_to?(:to_int) }
|
130
|
+
case flat_query[0]
|
131
|
+
when Symbol
|
132
|
+
flat_query.inject(0) do |val, o|
|
133
|
+
v = @kv_map[o]
|
134
|
+
if v then val |= v else val end
|
135
|
+
end
|
136
|
+
when Integer, ->(o) { o.respond_to?(:to_int) }
|
137
|
+
val = flat_query.inject(0) { |mask, o| mask |= o.to_int }
|
138
|
+
@kv_map.select { |_, v| v & val != 0 }.keys
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get the native value of a bitmask
|
143
|
+
# @overload to_native(query, ctx)
|
144
|
+
# @param [Symbol, Integer, #to_int] query
|
145
|
+
# @param ctx unused
|
146
|
+
# @return [Integer] value of a bitmask
|
147
|
+
# @overload to_native(query, ctx)
|
148
|
+
# @param [Array<Symbol, Integer, #to_int>] query
|
149
|
+
# @param ctx unused
|
150
|
+
# @return [Integer] value of a bitmask
|
151
|
+
def to_native(query, ctx)
|
152
|
+
return 0 if query.nil?
|
153
|
+
flat_query = [query].flatten
|
154
|
+
flat_query.inject(0) do |val, o|
|
155
|
+
case o
|
156
|
+
when Symbol
|
157
|
+
v = @kv_map[o]
|
158
|
+
raise ArgumentError, "invalid bitmask value, #{o.inspect}" unless v
|
159
|
+
val |= v
|
160
|
+
when Integer
|
161
|
+
val |= o
|
162
|
+
when ->(obj) { obj.respond_to?(:to_int) }
|
163
|
+
val |= o.to_int
|
164
|
+
else
|
165
|
+
raise ArgumentError, "invalid bitmask value, #{o.inspect}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# @param [Integer] val
|
171
|
+
# @param ctx unused
|
172
|
+
# @return [Array<Symbol, Integer>] list of symbol names corresponding to val, plus an optional remainder if some bits don't match any constant
|
173
|
+
def from_native(val, ctx)
|
174
|
+
list = @kv_map.select { |_, v| v & val != 0 }.keys
|
175
|
+
# If there are unmatch flags,
|
176
|
+
# return them in an integer,
|
177
|
+
# else information can be lost.
|
178
|
+
# Similar to Enum behavior.
|
179
|
+
remainder = val ^ list.inject(0) do |tmp, o|
|
180
|
+
v = @kv_map[o]
|
181
|
+
if v then tmp |= v else tmp end
|
182
|
+
end
|
183
|
+
list.push remainder unless remainder == 0
|
184
|
+
return list
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-bitmask
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brice Videau
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-26 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.9'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.9.3
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.9'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.9.3
|
33
|
+
description: bitmask support for ffi heavily relying on FFI internals
|
34
|
+
email: brice.videau@imag.fr
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- LICENSE
|
40
|
+
- ffi-bitmask.gemspec
|
41
|
+
- lib/ffi/bitmask.rb
|
42
|
+
homepage: https://github.com/Nanosim-LIG/ffi-bitmask
|
43
|
+
licenses:
|
44
|
+
- BSD-2-Clause
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.9.3
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.5.2
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: bitmask support for ffi
|
66
|
+
test_files: []
|