Class: FFI::StructLayoutBuilder
- Inherits:
-
Object
- Object
- FFI::StructLayoutBuilder
- Defined in:
- lib/ffi/struct_layout_builder.rb
Overview
Build a struct layout.
Constant Summary collapse
- NUMBER_TYPES =
List of number types
[ Type::INT8, Type::UINT8, Type::INT16, Type::UINT16, Type::INT32, Type::UINT32, Type::LONG, Type::ULONG, Type::INT64, Type::UINT64, Type::FLOAT32, Type::FLOAT64, Type::LONGDOUBLE, Type::BOOL, ].freeze
Instance Attribute Summary collapse
-
#alignment ⇒ Object
Returns the value of attribute alignment.
-
#size ⇒ Object
Returns the value of attribute size.
Instance Method Summary collapse
-
#add(name, type, offset = nil) ⇒ self
Add a field to the builder.
-
#add_array(name, type, count, offset = nil) ⇒ self
Add an array as a field to the builder.
-
#add_field(name, type, offset = nil) ⇒ self
Same as #add.
-
#add_struct(name, type, offset = nil) ⇒ self
Add a struct as a field to the builder.
- #align(offset, align) ⇒ Integer private
-
#build ⇒ StructLayout
Build and return the struct layout.
- #field_for_type(name, offset, type) ⇒ StructLayout::Field private
-
#initialize ⇒ StructLayoutBuilder
constructor
A new instance of StructLayoutBuilder.
-
#packed=(packed) ⇒ Object
Set packed attribute.
-
#union=(is_union) ⇒ is_union
Set union attribute.
- #union? ⇒ Boolean
Constructor Details
#initialize ⇒ StructLayoutBuilder
Returns a new instance of StructLayoutBuilder.
39 40 41 42 43 44 45 46 |
# File 'lib/ffi/struct_layout_builder.rb', line 39 def initialize @size = 0 @alignment = 1 @min_alignment = 1 @packed = false @union = false @fields = Array.new end |
Instance Attribute Details
#alignment ⇒ Object
Returns the value of attribute alignment.
37 38 39 |
# File 'lib/ffi/struct_layout_builder.rb', line 37 def alignment @alignment end |
#size ⇒ Object
Returns the value of attribute size.
36 37 38 |
# File 'lib/ffi/struct_layout_builder.rb', line 36 def size @size end |
Instance Method Details
#add(name, type, offset = nil) ⇒ self
Setting offset
to nil
or -1
is equivalent to 0
.
Add a field to the builder.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/ffi/struct_layout_builder.rb', line 123 def add(name, type, offset = nil) if offset.nil? || offset == -1 offset = @union ? 0 : align(@size, @packed ? [ @packed, type.alignment ].min : [ @min_alignment, type.alignment ].max) end # # If a FFI::Type type was passed in as the field arg, try and convert to a StructLayout::Field instance # field = type.is_a?(StructLayout::Field) ? type : field_for_type(name, offset, type) @fields << field @alignment = [ @alignment, field.alignment ].max unless @packed @size = [ @size, field.size + (@union ? 0 : field.offset) ].max return self end |
#add_array(name, type, count, offset = nil) ⇒ self
Add an array as a field to the builder.
161 162 163 |
# File 'lib/ffi/struct_layout_builder.rb', line 161 def add_array(name, type, count, offset = nil) add(name, Type::Array.new(type, count), offset) end |
#add_field(name, type, offset = nil) ⇒ self
Same as #add.
144 145 146 |
# File 'lib/ffi/struct_layout_builder.rb', line 144 def add_field(name, type, offset = nil) add(name, type, offset) end |
#add_struct(name, type, offset = nil) ⇒ self
Add a struct as a field to the builder.
151 152 153 |
# File 'lib/ffi/struct_layout_builder.rb', line 151 def add_struct(name, type, offset = nil) add(name, Type::Struct.new(type), offset) end |
#align(offset, align) ⇒ Integer (private)
181 182 183 |
# File 'lib/ffi/struct_layout_builder.rb', line 181 def align(offset, align) align + ((offset - 1) & ~(align - 1)); end |
#build ⇒ StructLayout
Build and return the struct layout.
167 168 169 170 171 172 173 174 |
# File 'lib/ffi/struct_layout_builder.rb', line 167 def build # Add tail padding if the struct is not packed size = @packed ? @size : align(@size, @alignment) layout = StructLayout.new(@fields, size, @alignment) layout.__union! if @union layout end |
#field_for_type(name, offset, type) ⇒ StructLayout::Field (private)
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/ffi/struct_layout_builder.rb', line 187 def field_for_type(name, offset, type) field_class = case when type.is_a?(Type::Function) StructLayout::Function when type.is_a?(Type::Struct) StructLayout::InnerStruct when type.is_a?(Type::Array) StructLayout::Array when type.is_a?(FFI::Enum) StructLayout::Enum when NUMBER_TYPES.include?(type) StructLayout::Number when type == Type::POINTER StructLayout::Pointer when type == Type::STRING StructLayout::String when type.is_a?(Class) && type < StructLayout::Field type when type.is_a?(DataConverter) return StructLayout::Mapped.new(name, offset, Type::Mapped.new(type), field_for_type(name, offset, type.native_type)) when type.is_a?(Type::Mapped) return StructLayout::Mapped.new(name, offset, type, field_for_type(name, offset, type.native_type)) else raise TypeError, "invalid struct field type #{type.inspect}" end field_class.new(name, offset, type) end |
#packed=(packed) ⇒ packed #packed=(packed) ⇒ 0, 1
Set packed attribute
89 90 91 92 93 94 95 96 |
# File 'lib/ffi/struct_layout_builder.rb', line 89 def packed=(packed) if packed.is_a?(0.class) @alignment = packed @packed = packed else @packed = packed ? 1 : 0 end end |
#union=(is_union) ⇒ is_union
Set union attribute. Set to true
to build a Union instead of a FFI::Struct.
65 66 67 |
# File 'lib/ffi/struct_layout_builder.rb', line 65 def union=(is_union) @union = is_union end |
#union? ⇒ Boolean
Building a Union or a FFI::Struct ?
73 74 75 |
# File 'lib/ffi/struct_layout_builder.rb', line 73 def union? @union end |