123456789_123456789_123456789_123456789_123456789_

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

Instance Attribute Summary

Instance Method Summary

Constructor Details

.newStructLayoutBuilder

[ GitHub ]

  
# 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.

Parameters:

  • align (Integer)
[ GitHub ]

  
# File 'lib/ffi/struct_layout_builder.rb', line 56

def alignment=(align)
  @alignment = align if align > @alignment
  @min_alignment = align
end

#packed=(packed) Set alignment and packed attributes to) ⇒ packed (writeonly) #packed=(packed) Set packed attribute.) ⇒ 0, 1

Set packed attribute

[ GitHub ]

  
# 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)

Set size attribute with #size only if #size is greater than attribute value.

Parameters:

  • size (Integer)
[ GitHub ]

  
# File 'lib/ffi/struct_layout_builder.rb', line 50

def size=(size)
  @size = size if size > @size
end

#union=(is_union) ⇒ is_union (rw)

Set union attribute. Set to true to build a Union instead of a Struct.

Parameters:

  • is_union (Boolean)
[ GitHub ]

  
# File 'lib/ffi/struct_layout_builder.rb', line 65

def union=(is_union)
  @union = is_union
end

#union?Boolean (rw)

Building a Union or a Struct ?

[ 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.

Parameters:

[ GitHub ]

  
# 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.

Parameters:

  • count (Integer)

    array length

[ GitHub ]

  
# 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)

Same as #add.

See Also:

[ GitHub ]

  
# 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.

[ GitHub ]

  
# 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)

Parameters:

  • offset (Integer)
  • align (Integer)
[ GitHub ]

  
# File 'lib/ffi/struct_layout_builder.rb', line 181

def align(offset, align)
  align + ((offset - 1) & ~(align - 1));
end

#buildStructLayout

Build and return the struct layout.

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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