Convenience tweaks to FFI::Struct
This commit is contained in:
@@ -6,13 +6,15 @@ require 'ffi'
|
|||||||
# - robust pre-existing code
|
# - robust pre-existing code
|
||||||
# - good handling of nested structures and nested arrays
|
# - good handling of nested structures and nested arrays
|
||||||
# Bad things about FFI::Struct:
|
# Bad things about FFI::Struct:
|
||||||
# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2)
|
# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2) [*]
|
||||||
# - no accessor methods m.foo = 1
|
# - no accessor methods m.foo = 1 [*]
|
||||||
# - can't do zero size array at end of struct: layout :foo, [Foo, 0]
|
# - can't do zero size array at end of struct: layout :foo, [Foo, 0]
|
||||||
# - no network-order fields? (in_addr)
|
# - no network-order fields? (in_addr)
|
||||||
# - no decent inspect (fix this below)
|
# - no decent inspect [*]
|
||||||
|
# [*] Fixed below in FFI::AStruct
|
||||||
|
|
||||||
class FFI::Struct
|
class FFI::AStruct < FFI::Struct
|
||||||
|
# https://github.com/ffi/ffi/issues/102
|
||||||
def inspect
|
def inspect
|
||||||
res = "#<#{self.class}"
|
res = "#<#{self.class}"
|
||||||
members.zip(values).each do |m,v|
|
members.zip(values).each do |m,v|
|
||||||
@@ -20,8 +22,34 @@ class FFI::Struct
|
|||||||
end
|
end
|
||||||
res << ">"
|
res << ">"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# https://github.com/ffi/ffi/issues/106
|
||||||
|
def initialize(*args)
|
||||||
|
if args.first.is_a? Hash
|
||||||
|
super(nil, *args[1..-1])
|
||||||
|
src.each { |k,v| self[k] = v }
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/ffi/ffi/issues/107
|
||||||
|
def self.layout(*fields)
|
||||||
|
super
|
||||||
|
fields.each_slice(2) do |name,type|
|
||||||
|
# Structure building is screwed up if there's a 'size' member!
|
||||||
|
next if instance_methods.find { |m| m.to_sym == name }
|
||||||
|
define_method name do
|
||||||
|
self[name]
|
||||||
|
end
|
||||||
|
define_method "#{name}=" do |v|
|
||||||
|
self[name] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# https://github.com/ffi/ffi/issues/102
|
||||||
class FFI::StructLayout::CharArray
|
class FFI::StructLayout::CharArray
|
||||||
def inspect
|
def inspect
|
||||||
to_s.inspect
|
to_s.inspect
|
||||||
|
@@ -7,7 +7,7 @@ module Linux
|
|||||||
#+
|
#+
|
||||||
|
|
||||||
# struct ipt_getinfo
|
# struct ipt_getinfo
|
||||||
class IPTGetInfo < FFI::Struct
|
class IPTGetInfo < FFI::AStruct
|
||||||
layout :name, [:char, IPT_TABLE_MAXNAMELEN],
|
layout :name, [:char, IPT_TABLE_MAXNAMELEN],
|
||||||
:valid_hooks, :uint,
|
:valid_hooks, :uint,
|
||||||
:hook_entry, [:uint, NF_INET_NUMHOOKS],
|
:hook_entry, [:uint, NF_INET_NUMHOOKS],
|
||||||
@@ -16,7 +16,7 @@ module Linux
|
|||||||
:size, :uint
|
:size, :uint
|
||||||
end
|
end
|
||||||
|
|
||||||
class IPTIP < FFI::Struct
|
class IPTIP < FFI::AStruct
|
||||||
layout :src, :int32, # FIXME: needs ntohl
|
layout :src, :int32, # FIXME: needs ntohl
|
||||||
:dst, :int32,
|
:dst, :int32,
|
||||||
:smsk, :int32,
|
:smsk, :int32,
|
||||||
@@ -31,13 +31,13 @@ module Linux
|
|||||||
end
|
end
|
||||||
|
|
||||||
# struct xt_counters (netfilter/x_tables.h)
|
# struct xt_counters (netfilter/x_tables.h)
|
||||||
class XTCounters < FFI::Struct
|
class XTCounters < FFI::AStruct
|
||||||
layout :pcnt, :uint64,
|
layout :pcnt, :uint64,
|
||||||
:bcnt, :uint64
|
:bcnt, :uint64
|
||||||
end
|
end
|
||||||
|
|
||||||
# struct ipt_entry
|
# struct ipt_entry
|
||||||
class IPTEntry < FFI::Struct
|
class IPTEntry < FFI::AStruct
|
||||||
layout :ip, IPTIP,
|
layout :ip, IPTIP,
|
||||||
:nfcache, :uint,
|
:nfcache, :uint,
|
||||||
:target_offset, :uint16, # size of ipt_entry + matches
|
:target_offset, :uint16, # size of ipt_entry + matches
|
||||||
@@ -48,7 +48,7 @@ module Linux
|
|||||||
end
|
end
|
||||||
|
|
||||||
# struct ipt_get_entries
|
# struct ipt_get_entries
|
||||||
class IPTGetEntries < FFI::Struct
|
class IPTGetEntries < FFI::AStruct
|
||||||
layout :name, [:uchar, IPT_TABLE_MAXNAMELEN],
|
layout :name, [:uchar, IPT_TABLE_MAXNAMELEN],
|
||||||
:size, :uint,
|
:size, :uint,
|
||||||
:entrytable, [IPTEntry, 1] # should be [IPTEntry, 0]
|
:entrytable, [IPTEntry, 1] # should be [IPTEntry, 0]
|
||||||
|
Reference in New Issue
Block a user