Class: FFI::Bitmask
- Inherits:
-
Enum
- Object
- Enum
- FFI::Bitmask
- Defined in:
- lib/ffi/bitmask.rb
Overview
Represents a C enum whose values are power of 2
Contrary to classical enums, bitmask values are usually combined when used.
Instance Method Summary collapse
-
#[](*query) ⇒ Object
Get a symbol list or a value from the bitmask.
-
#from_native(val, ctx) ⇒ Array<Symbol, Integer>
List of symbol names corresponding to val, plus an optional remainder if some bits don’t match any constant.
-
#initialize(*args) ⇒ Bitmask
constructor
A new instance of Bitmask.
-
#to_native(query, ctx) ⇒ Object
Get the native value of a bitmask.
Constructor Details
#initialize(info, tag = nil) ⇒ Bitmask #initialize(native_type, info, tag = nil) ⇒ Bitmask
Returns a new instance of Bitmask.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ffi/bitmask.rb', line 84 def initialize(*args) @native_type = args.first.kind_of?(FFI::Type) ? args.shift : Type::INT info, @tag = *args @kv_map = Hash.new unless info.nil? last_cst = nil value = 0 info.each do |i| case i when Symbol raise ArgumentError, "duplicate bitmask key" if @kv_map.has_key?(i) @kv_map[i] = 1 << value last_cst = i value += 1 when Integer raise ArgumentError, "bitmask index should be positive" if i<0 @kv_map[last_cst] = 1 << i value = i+1 end end end @vk_map = @kv_map.invert end |
Instance Method Details
#[](*query) ⇒ Integer #[](query) ⇒ Integer #[](*query) ⇒ Array<Symbol> #[](query) ⇒ Array<Symbol>
Get a symbol list or a value from the bitmask
127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/ffi/bitmask.rb', line 127 def [](*query) flat_query = query.flatten 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) } case flat_query[0] when Symbol flat_query.inject(0) do |val, o| v = @kv_map[o] if v then val |= v else val end end when Integer, ->(o) { o.respond_to?(:to_int) } val = flat_query.inject(0) { |mask, o| mask |= o.to_int } @kv_map.select { |_, v| v & val != 0 }.keys end end |
#from_native(val, ctx) ⇒ Array<Symbol, Integer>
Returns list of symbol names corresponding to val, plus an optional remainder if some bits don’t match any constant.
173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/ffi/bitmask.rb', line 173 def from_native(val, ctx) list = @kv_map.select { |_, v| v & val != 0 }.keys # If there are unmatch flags, # return them in an integer, # else information can be lost. # Similar to Enum behavior. remainder = val ^ list.inject(0) do |tmp, o| v = @kv_map[o] if v then tmp |= v else tmp end end list.push remainder unless remainder == 0 return list end |
#to_native(query, ctx) ⇒ Integer #to_native(query, ctx) ⇒ Integer
Get the native value of a bitmask
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/ffi/bitmask.rb', line 151 def to_native(query, ctx) return 0 if query.nil? flat_query = [query].flatten flat_query.inject(0) do |val, o| case o when Symbol v = @kv_map[o] raise ArgumentError, "invalid bitmask value, #{o.inspect}" unless v val |= v when Integer val |= o when ->(obj) { obj.respond_to?(:to_int) } val |= o.to_int else raise ArgumentError, "invalid bitmask value, #{o.inspect}" end end end |