Class: FFI::StructLayoutBuilder
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/ffi/struct_layout_builder.rb |
Overview
Build a struct layout.
Constant Summary
Class Method Summary
- .new ⇒ StructLayoutBuilder constructor
Instance Attribute Summary
- #alignment rw
-
#alignment=(align)
rw
Set alignment attribute with #align only if it is greater than attribute value.
-
#packed=(packed) Set alignment and packed attributes to) ⇒ packed
writeonly
Set packed attribute.
- #size rw
- #size=(size) rw
-
#union=(is_union) ⇒ is_union
rw
Set union attribute.
- #union? ⇒ Boolean rw
Instance Method Summary
-
#add(name, type, offset = nil) ⇒ self
Add a field to the builder.
-
#add_array(name, type, count, offset = nil)
Add an array as a field to the builder.
-
#add_field(name, type, offset = nil)
Same as #add.
-
#add_struct(name, type, offset = nil)
Add a struct as a field to the builder.
-
#build ⇒ StructLayout
Build and return the struct layout.
- #align(offset, align) ⇒ Integer private
- #field_for_type(name, offset, type) ⇒ StructLayout::Field private
Constructor Details
.new ⇒ StructLayoutBuilder
# 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 (rw)
[ GitHub ]# File 'lib/ffi/struct_layout_builder.rb', line 37
attr_reader :alignment
#alignment=(align) (rw)
Set alignment attribute with #align only if it is greater than attribute value.
#packed=(packed) Set alignment and packed attributes to) ⇒ packed
(writeonly)
#packed=(packed) Set packed attribute.) ⇒ 0
, 1
packed
(writeonly)
#packed=(packed) Set packed attribute.) ⇒ 0
, 1
Set packed attribute
# 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
#size (rw)
[ GitHub ]# File 'lib/ffi/struct_layout_builder.rb', line 36
attr_reader :size
#size=(size) (rw)
[ GitHub ]
#union=(is_union) ⇒ is_union
(rw)
[ GitHub ]
# File 'lib/ffi/struct_layout_builder.rb', line 65
def union=(is_union) @union = is_union end
#union? ⇒ Boolean
(rw)
[ GitHub ]
# File 'lib/ffi/struct_layout_builder.rb', line 73
def union? @union end
Instance Method Details
#add(name, type, offset = nil) ⇒ self
Note:
Setting offset
to nil
or -1
is equivalent to 0
.
Add a field to the builder.
# 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)
Add an array as a field to the builder.
#add_field(name, type, offset = nil)
Same as #add.
# 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)
Add a struct as a field to the builder.
#align(offset, align) ⇒ Integer
(private)
# 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.
# 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)
# 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