Class: FFI::StructLayoutBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/ffi/struct_layout_builder.rb

Constant Summary

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,
]

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (StructLayoutBuilder) initialize

A new instance of StructLayoutBuilder



25
26
27
28
29
30
31
32
# File 'lib/ffi/struct_layout_builder.rb', line 25

def initialize
  @size = 0
  @alignment = 1
  @min_alignment = 1
  @packed = false
  @union = false
  @fields = Array.new
end

Instance Attribute Details

- (Object) alignment

Returns the value of attribute alignment



23
24
25
# File 'lib/ffi/struct_layout_builder.rb', line 23

def alignment
  @alignment
end

- (Object) size

Returns the value of attribute size



23
24
25
# File 'lib/ffi/struct_layout_builder.rb', line 23

def size
  @size
end

Instance Method Details

- (Object) add(name, type, offset = nil)



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/ffi/struct_layout_builder.rb', line 78

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

- (Object) add_array(name, type, count, offset = nil)



103
104
105
# File 'lib/ffi/struct_layout_builder.rb', line 103

def add_array(name, type, count, offset = nil)
  add(name, Type::Array.new(type, count), offset)
end

- (Object) add_field(name, type, offset = nil)



95
96
97
# File 'lib/ffi/struct_layout_builder.rb', line 95

def add_field(name, type, offset = nil)
  add(name, type, offset)
end

- (Object) add_struct(name, type, offset = nil)



99
100
101
# File 'lib/ffi/struct_layout_builder.rb', line 99

def add_struct(name, type, offset = nil)
  add(name, Type::Struct.new(type), offset)
end

- (Object) align(offset, align) (private)



118
119
120
# File 'lib/ffi/struct_layout_builder.rb', line 118

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

- (Object) build



107
108
109
110
111
112
113
114
# File 'lib/ffi/struct_layout_builder.rb', line 107

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

- (Object) field_for_type(name, offset, type) (private)



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ffi/struct_layout_builder.rb', line 122

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

- (Object) packed=(packed)



51
52
53
54
55
56
57
58
# File 'lib/ffi/struct_layout_builder.rb', line 51

def packed=(packed)
  if packed.is_a?(Fixnum)
    @alignment = packed
    @packed = packed
  else
    @packed = packed ? 1 : 0
  end
end

- (Object) union=(is_union)



43
44
45
# File 'lib/ffi/struct_layout_builder.rb', line 43

def union=(is_union)
  @union = is_union
end

- (Boolean) union?

Returns:

  • (Boolean)


47
48
49
# File 'lib/ffi/struct_layout_builder.rb', line 47

def union?
  @union
end