struct_packing 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/struct_packing.rb +1 -1
- data/lib/struct_packing/base.rb +97 -39
- data/lib/struct_packing/packable.rb +30 -10
- data/lib/struct_packing/unpackable.rb +69 -9
- data/lib/struct_packing/util.rb +50 -11
- data/struct_packing.gemspec +2 -2
- data/test/struct_packing/test_base.rb +38 -10
- data/test/struct_packing/test_packable.rb +56 -0
- data/test/struct_packing/test_unpackable.rb +47 -0
- data/test/struct_packing/test_util.rb +43 -0
- metadata +3 -3
data/History.txt
CHANGED
@@ -2,3 +2,17 @@
|
|
2
2
|
|
3
3
|
* 1 major enhancement:
|
4
4
|
* Initial release
|
5
|
+
|
6
|
+
=== 0.0.2 2013-02-17
|
7
|
+
|
8
|
+
* 3 major enhancement:
|
9
|
+
* Support array type.
|
10
|
+
* Use jeweler for gem build.
|
11
|
+
* A lot of BUG FIX.
|
12
|
+
|
13
|
+
=== 0.0.2 2013-03-02
|
14
|
+
|
15
|
+
* 2 major enhancement:
|
16
|
+
* Support struct.
|
17
|
+
* Support hash-style field access.
|
18
|
+
* Some BUG FIX.
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/lib/struct_packing.rb
CHANGED
data/lib/struct_packing/base.rb
CHANGED
@@ -10,30 +10,36 @@ module StructPacking
|
|
10
10
|
|
11
11
|
def self.included(base)
|
12
12
|
base.extend ClassMethods
|
13
|
+
base.attr_mapped_struct
|
14
|
+
|
15
|
+
base.instance_eval { @selfclass = base }
|
16
|
+
base.instance_eval { def selfclass ; @selfclass ; end }
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
# get self class or eign class.
|
22
|
+
def selfclass
|
23
|
+
if defined?(self.class.selfclass)
|
24
|
+
self.class.selfclass
|
25
|
+
else
|
26
|
+
eign = (class << self; self ; end)
|
27
|
+
eign.selfclass
|
28
|
+
end
|
13
29
|
end
|
14
|
-
|
15
|
-
public
|
16
30
|
|
17
31
|
# Get structure format string used in packing this object.
|
18
32
|
#
|
19
33
|
# This method work as just wrapper to same name class-method.
|
20
34
|
def internal_format
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# Get field name list of this class.
|
25
|
-
def field_names
|
26
|
-
self.class.field_names
|
27
|
-
end
|
28
|
-
|
29
|
-
# Get field type list of this class.
|
30
|
-
def field_types
|
31
|
-
self.class.field_types
|
35
|
+
selfclass.send(:internal_format)
|
32
36
|
end
|
37
|
+
|
38
|
+
public
|
33
39
|
|
34
|
-
# Get Ruby's pack
|
40
|
+
# Get Ruby's pack template string for this class.
|
35
41
|
def pack_template
|
36
|
-
|
42
|
+
selfclass.pack_template
|
37
43
|
end
|
38
44
|
|
39
45
|
# Common extending methods for Packable and Unpackable.
|
@@ -42,49 +48,101 @@ module StructPacking
|
|
42
48
|
module ClassMethods
|
43
49
|
|
44
50
|
private
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
|
52
|
+
def self.extended(base)
|
53
|
+
base.class_eval do
|
54
|
+
begin
|
55
|
+
@struct_field_getter = superclass.class_eval { @struct_field_getter }
|
56
|
+
rescue
|
57
|
+
@struct_field_getter = nil
|
58
|
+
end
|
59
|
+
begin
|
60
|
+
@struct_field_setter = superclass.class_eval { @struct_field_setter }
|
61
|
+
rescue
|
62
|
+
@struct_field_setter = nil
|
63
|
+
end
|
64
|
+
begin
|
65
|
+
@struct_internal_format = superclass.class_eval { @struct_internal_format }
|
66
|
+
if @struct_internal_format == nil
|
67
|
+
@struct_internal_format = ""
|
68
|
+
end
|
69
|
+
rescue
|
70
|
+
@struct_internal_format = ""
|
71
|
+
end
|
50
72
|
end
|
51
73
|
end
|
52
74
|
|
53
|
-
|
75
|
+
protected
|
54
76
|
|
55
77
|
# Get internal structure format used to pack a object of this class.
|
56
78
|
def internal_format
|
57
|
-
|
58
|
-
|
59
|
-
Util.internal_format_from( self.class_variable_get(:@@struct_internal_format) )
|
79
|
+
Util.internal_format_from( @struct_internal_format)
|
60
80
|
end
|
81
|
+
|
82
|
+
public
|
61
83
|
|
62
84
|
# Set structure format for this class by string.
|
63
85
|
def byte_format=(text)
|
64
|
-
|
65
|
-
|
66
|
-
self.class_variable_set(:@@struct_internal_format, text)
|
86
|
+
@struct_internal_format = text
|
67
87
|
|
68
88
|
true
|
69
89
|
end
|
70
90
|
|
71
|
-
|
72
|
-
|
73
|
-
|
91
|
+
public
|
92
|
+
|
93
|
+
# Get Ruby's pack template string for this class.
|
94
|
+
def pack_template
|
95
|
+
if self.to_s =~ /^.*<(.*):0x.*/
|
96
|
+
clsname = $1
|
97
|
+
else
|
98
|
+
clsname = self.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
Util.pack_template_from( @struct_internal_format, clsname )
|
74
102
|
end
|
75
|
-
|
76
|
-
#
|
77
|
-
def
|
78
|
-
|
103
|
+
|
104
|
+
# Call getter procedure to get field of target object.
|
105
|
+
def get_field_value(obj, name)
|
106
|
+
begin
|
107
|
+
@struct_field_getter.call(obj, name)
|
108
|
+
rescue
|
109
|
+
0
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Call setter procedure to set value to the field of target object.
|
114
|
+
def set_field_value(obj, name, value)
|
115
|
+
begin
|
116
|
+
@struct_field_setter.call(obj, name, value)
|
117
|
+
rescue
|
118
|
+
end
|
79
119
|
end
|
80
120
|
|
81
|
-
#
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
121
|
+
# Set gettter procedure.
|
122
|
+
def set_field_getter(&block)
|
123
|
+
@struct_field_getter = block
|
124
|
+
end
|
125
|
+
|
126
|
+
# Set settter procedure.
|
127
|
+
def set_field_setter(&block)
|
128
|
+
@struct_field_setter = block
|
129
|
+
end
|
130
|
+
|
131
|
+
# Declare this struct as accessible by hash-style-access(access by [] operator).
|
132
|
+
def hash_mapped_struct
|
133
|
+
set_field_getter {|obj, name| obj[name.to_sym] }
|
134
|
+
set_field_setter {|obj, name, value| obj[name.to_sym] = value }
|
135
|
+
end
|
136
|
+
|
137
|
+
# Declare this struct as accessible by attr-style-access(access by {name}= operator).
|
138
|
+
# This is default behavior.
|
139
|
+
def attr_mapped_struct
|
140
|
+
set_field_getter {|obj, name| obj.send(name) }
|
141
|
+
set_field_setter {|obj, name, value| obj.send("#{name}=", value) }
|
86
142
|
end
|
87
143
|
|
144
|
+
alias :define_struct :byte_format=
|
145
|
+
|
88
146
|
end
|
89
147
|
end
|
90
148
|
|
@@ -23,25 +23,45 @@ module StructPacking
|
|
23
23
|
include Base
|
24
24
|
|
25
25
|
def self.included(base)
|
26
|
-
base.send(
|
26
|
+
base.send(:include, Base)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
def value_or_zero(&block)
|
30
|
+
begin
|
31
|
+
instance_eval &block
|
32
|
+
rescue
|
33
|
+
0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def struct_values
|
40
|
+
internal_format.collect do |name, type|
|
41
|
+
if type =~ /^struct\s*\w*\s*(?:\s*\[(\d+)\s*\])?\s*$/
|
42
|
+
arynum = $1
|
43
|
+
if $1 == nil
|
44
|
+
value_or_zero { send(:selfclass).get_field_value(self, name).struct_values }
|
45
|
+
else
|
46
|
+
(0..(arynum.to_i-1)).each.collect do |i|
|
47
|
+
value_or_zero { send(:selfclass).get_field_value(self, name)[i].struct_values }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
value_or_zero { send(:selfclass).get_field_value(self, name) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
30
55
|
|
56
|
+
public
|
57
|
+
|
31
58
|
# Pack this object to byte array.
|
32
59
|
#
|
33
60
|
# If attribute defined in byte_format,
|
34
61
|
# but object has no attr_getter, treat as the attribute is zero.
|
35
62
|
def pack()
|
36
|
-
values =
|
37
|
-
begin
|
38
|
-
instance_eval { send(n) }
|
39
|
-
rescue NoMethodError
|
40
|
-
0
|
41
|
-
end
|
42
|
-
end
|
63
|
+
values = struct_values
|
43
64
|
values.flatten!
|
44
|
-
|
45
65
|
values.pack( pack_template )
|
46
66
|
end
|
47
67
|
|
@@ -12,7 +12,7 @@ module StructPacking
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def self.included(base)
|
15
|
-
base.send(
|
15
|
+
base.send(:include, Base)
|
16
16
|
base.extend ClassMethods
|
17
17
|
end
|
18
18
|
|
@@ -37,32 +37,92 @@ module StructPacking
|
|
37
37
|
|
38
38
|
alias :from_data :unpack
|
39
39
|
|
40
|
+
protected
|
41
|
+
|
42
|
+
|
43
|
+
# Instantiate and initialize object by value-array.
|
44
|
+
def from_values(values)
|
45
|
+
obj = self.new
|
46
|
+
set_values_from_values_to_object(values, obj)
|
47
|
+
end
|
48
|
+
|
40
49
|
private
|
41
50
|
|
42
51
|
def set_values_from_byte_to_object(bytes, obj)
|
43
|
-
|
44
52
|
values = bytes.unpack( pack_template )
|
53
|
+
set_values_from_values_to_object(values, obj)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get field name list of this class.
|
57
|
+
def field_names
|
58
|
+
internal_format.keys
|
59
|
+
end
|
45
60
|
|
61
|
+
def set_values_from_values_to_object(values, obj)
|
62
|
+
|
46
63
|
field_names.zip(gather_array_field(values) ).each do |name,value|
|
47
64
|
begin
|
48
|
-
obj.
|
49
|
-
send("#{name}=", value)
|
50
|
-
}
|
65
|
+
obj.send(:selfclass).set_field_value(obj, name, value)
|
51
66
|
rescue NoMethodError
|
52
67
|
end
|
53
68
|
end
|
54
69
|
obj
|
55
70
|
end
|
56
|
-
|
57
|
-
def gather_array_field(
|
58
|
-
|
59
|
-
|
71
|
+
|
72
|
+
def gather_array_field(value_array)
|
73
|
+
values = value_array.dup
|
74
|
+
|
75
|
+
internal_format.collect do |name, type|
|
76
|
+
|
77
|
+
if type =~ /^struct\s*(\w*)\s*(?:\s*\[(\d+)\s*\])?\s*$/
|
78
|
+
struct_name = $1
|
79
|
+
arylen = $2
|
80
|
+
cls = Util.find_hier_mod(self, struct_name)
|
81
|
+
if arylen == nil
|
82
|
+
obj = cls.from_values( values[0, cls.send(:num_of_value)] )
|
83
|
+
values = values[cls.send(:num_of_value), values.length]
|
84
|
+
else
|
85
|
+
obj = []
|
86
|
+
|
87
|
+
arylen.to_i.times do
|
88
|
+
obj.push( cls.from_values( values[0, cls.send(:num_of_value)] ) )
|
89
|
+
values = values[cls.send(:num_of_value), values.length]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
obj
|
94
|
+
elsif type =~ /.*\[\w*(\d+)\w*\]\w*/
|
60
95
|
[0..$1.to_i].to_a.collect { values.shift }
|
61
96
|
else
|
62
97
|
values.shift
|
63
98
|
end
|
64
99
|
end
|
65
100
|
end
|
101
|
+
|
102
|
+
def num_of_value
|
103
|
+
|
104
|
+
nums = internal_format.collect do |name, type|
|
105
|
+
if type =~ /^struct\s*(\w*)\s*(?:\s*\[(\d+)\s*\])?\s*$/
|
106
|
+
struct_name = $1
|
107
|
+
arylen = $2
|
108
|
+
cls = Util.find_hier_mod(self, struct_name)
|
109
|
+
|
110
|
+
if arylen == nil
|
111
|
+
cls.num_of_value
|
112
|
+
else
|
113
|
+
cls.num_of_value * arylen.to_i
|
114
|
+
end
|
115
|
+
else
|
116
|
+
1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
nums.inject(0) do |sum, num|
|
121
|
+
sum + num
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
66
126
|
end
|
67
127
|
|
68
128
|
public
|
data/lib/struct_packing/util.rb
CHANGED
@@ -7,16 +7,37 @@ module StructPacking
|
|
7
7
|
class Util
|
8
8
|
|
9
9
|
private
|
10
|
+
|
11
|
+
def self.struct_template(type, arraylen, mod=nil)
|
12
|
+
type =~ /struct\s*(\w*)\s*/
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
if arraylen != ""
|
15
|
+
find_hier_mod(mod, $1).pack_template * arraylen.to_i
|
16
|
+
else
|
17
|
+
find_hier_mod(mod, $1).pack_template
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse_ctype_decl(decl, mod=nil)
|
23
|
+
decl =~ /^\s*(unsigned|signed)?\s*(ascii|utf8|byte|char|short|(?:u?int)(?:(?:8|16|32|64)_t)?|(?:big|little)?(?:16|32)|(?:big|little)?\s*(?:float|double)?|long(?:\s*long)|struct\s*\w*)\s*([\s\*]*)\s*(?:\[\s*(\d+)\s*\])?\s*$/
|
24
|
+
|
25
|
+
sign = !("unsigned" == $1) #sign modifier
|
26
|
+
type = $2
|
27
|
+
ptr = $3
|
28
|
+
arraylen = $4
|
13
29
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
30
|
+
if arraylen == nil or arraylen == "1"
|
31
|
+
arraylen = ""
|
32
|
+
end
|
33
|
+
|
34
|
+
if ptr != nil and ptr != "" #pointer operator
|
35
|
+
'P' + arraylen
|
36
|
+
elsif "struct" == type[0..5]
|
37
|
+
struct_template(type, arraylen, mod)
|
38
|
+
else
|
39
|
+
template_of(sign, type) + arraylen
|
18
40
|
end
|
19
|
-
template
|
20
41
|
end
|
21
42
|
|
22
43
|
def self.template_of(sign, type)
|
@@ -82,15 +103,33 @@ module StructPacking
|
|
82
103
|
end
|
83
104
|
end
|
84
105
|
|
85
|
-
def self.types_to_template(types)
|
86
|
-
types.collect {|t| parse_ctype_decl(t)}.join
|
106
|
+
def self.types_to_template(types, mod=nil)
|
107
|
+
types.collect {|t| parse_ctype_decl(t,mod)}.join
|
87
108
|
end
|
88
109
|
|
110
|
+
|
111
|
+
def self.find_hier_mod(context_mod, sym)
|
112
|
+
nesthier = context_mod.to_s.split("::")
|
113
|
+
|
114
|
+
parent = Kernel
|
115
|
+
mods = nesthier.collect {|m| x = parent.const_get(m); parent = x; x }
|
116
|
+
mods.unshift Kernel
|
117
|
+
|
118
|
+
finded = mods.reverse.collect {|m| m.const_defined?(sym) ? m.const_get(sym) : nil }
|
119
|
+
targetmod = finded.select {|f| f != nil }.first
|
120
|
+
|
121
|
+
if targetmod == nil
|
122
|
+
raise NameError
|
123
|
+
end
|
124
|
+
targetmod
|
125
|
+
end
|
126
|
+
|
127
|
+
|
89
128
|
public
|
90
129
|
# Parse declaration string into pack template.
|
91
|
-
def self.pack_template_from(text)
|
130
|
+
def self.pack_template_from(text,mod=nil)
|
92
131
|
internal = internal_format_from(text)
|
93
|
-
types_to_template(internal.values)
|
132
|
+
types_to_template(internal.values,mod)
|
94
133
|
end
|
95
134
|
|
96
135
|
# Parse declaration string into internal format.
|
data/struct_packing.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "struct_packing"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["TOKITA Hiroshi"]
|
12
|
-
s.date = "2013-02
|
12
|
+
s.date = "2013-03-02"
|
13
13
|
s.description = "* Read/Write ruby object to byte array with C-like struct declarations."
|
14
14
|
s.email = ["tokita.hiroshi@gmail.com"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -13,7 +13,7 @@ class TestBase < Test::Unit::TestCase
|
|
13
13
|
|
14
14
|
def test_null_internal_format
|
15
15
|
obj = ClassIncludeOnly.new
|
16
|
-
assert_equal({}, obj.internal_format
|
16
|
+
assert_equal({}, obj.send(:internal_format) )
|
17
17
|
end
|
18
18
|
|
19
19
|
|
@@ -23,7 +23,7 @@ class TestBase < Test::Unit::TestCase
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def test_single_int_internal_format
|
26
|
-
assert_equal("int" , SingleIntStruct.internal_format[:hoge])
|
26
|
+
assert_equal("int" , SingleIntStruct.send(:internal_format)[:hoge])
|
27
27
|
end
|
28
28
|
|
29
29
|
class MultiFieldStruct
|
@@ -32,17 +32,45 @@ class TestBase < Test::Unit::TestCase
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_multi_field_internal_format
|
35
|
-
assert_equal("int" , MultiFieldStruct.internal_format[:fuga])
|
36
|
-
assert_equal("char" , MultiFieldStruct.internal_format[:piyo])
|
35
|
+
assert_equal("int" , MultiFieldStruct.send(:internal_format)[:fuga])
|
36
|
+
assert_equal("char" , MultiFieldStruct.send(:internal_format)[:piyo])
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_class_macro
|
40
|
+
eval <<-EOF
|
41
|
+
class TestClassMacro
|
42
|
+
include StructPacking::Base
|
43
|
+
define_struct "int foo;"
|
44
|
+
end
|
45
|
+
EOF
|
46
|
+
|
47
|
+
assert_equal({:foo=>"int"}, TestClassMacro.send(:internal_format) )
|
37
48
|
end
|
38
49
|
|
39
|
-
|
50
|
+
class NotModifiableFormat
|
51
|
+
include StructPacking::Base
|
52
|
+
self.byte_format = "int xxx;"
|
53
|
+
end
|
54
|
+
|
40
55
|
def test_internal_format_not_modifiable
|
41
|
-
assert_equal(
|
42
|
-
|
43
|
-
assert_equal(
|
44
|
-
|
56
|
+
assert_equal("int", NotModifiableFormat.send(:internal_format)[:xxx])
|
57
|
+
SingleIntStruct.send(:internal_format)[:xxx] = "byte"
|
58
|
+
assert_equal("int", (NotModifiableFormat.send(:internal_format)[:xxx]))
|
59
|
+
end
|
60
|
+
|
61
|
+
class InnerModuleClass
|
62
|
+
include StructPacking::Base
|
63
|
+
self.byte_format = "int inner; char mod;"
|
64
|
+
end
|
65
|
+
|
66
|
+
class InnerModuleTest
|
67
|
+
include StructPacking::Base
|
68
|
+
self.byte_format = "struct InnerModuleClass imc;"
|
45
69
|
end
|
46
|
-
|
70
|
+
|
71
|
+
def test_inner_struct_class
|
72
|
+
assert_equal("ic", InnerModuleTest.pack_template)
|
73
|
+
end
|
74
|
+
|
47
75
|
|
48
76
|
end
|
@@ -22,6 +22,7 @@ class TestPackable < Test::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
class ClsInt < ClsIntNoAttr
|
25
|
+
include TEST_MOD
|
25
26
|
attr_accessor :packtestint
|
26
27
|
end
|
27
28
|
|
@@ -42,6 +43,7 @@ class TestPackable < Test::Unit::TestCase
|
|
42
43
|
end
|
43
44
|
|
44
45
|
class ClsChar < ClsCharNoAttr
|
46
|
+
include TEST_MOD
|
45
47
|
attr_accessor :packtestchar
|
46
48
|
end
|
47
49
|
|
@@ -85,5 +87,59 @@ class TestPackable < Test::Unit::TestCase
|
|
85
87
|
|
86
88
|
assert_equal([1, 0, 0, 0, 2, 0, 0, 0, 8].pack("C*"), ba)
|
87
89
|
end
|
90
|
+
|
91
|
+
class ClsNested < OpenStruct
|
92
|
+
include TEST_MOD
|
93
|
+
self.byte_format = "int ho; char ge;"
|
94
|
+
end
|
95
|
+
|
96
|
+
class ClsNesting < OpenStruct
|
97
|
+
include TEST_MOD
|
98
|
+
self.byte_format = "struct ClsNested nst;"
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_struct
|
102
|
+
obj = ClsNesting.new
|
103
|
+
nst = ClsNested.new
|
104
|
+
obj.nst = nst
|
105
|
+
obj.nst.ho = 1
|
106
|
+
obj.nst.ge = 10
|
107
|
+
|
108
|
+
assert_equal([1,0,0,0, 10].pack("C*"), obj.pack )
|
109
|
+
end
|
110
|
+
|
111
|
+
class ClsArray < OpenStruct
|
112
|
+
include TEST_MOD
|
113
|
+
self.byte_format = "struct ClsNested ary[2];"
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_struct_array
|
117
|
+
obj = ClsArray.new
|
118
|
+
|
119
|
+
nst1 = ClsNested.new
|
120
|
+
nst1.ho = 1
|
121
|
+
nst1.ge = 10
|
122
|
+
nst2 = ClsNested.new
|
123
|
+
nst2.ho = 2
|
124
|
+
nst2.ge = 20
|
125
|
+
obj.ary = [nst1, nst2]
|
126
|
+
|
127
|
+
assert_equal([1,0,0,0,10,2,0,0,0,20].pack("C*"), obj.pack )
|
128
|
+
end
|
129
|
+
|
130
|
+
class HashMapped < Hash
|
131
|
+
include TEST_MOD
|
132
|
+
define_struct "int hashhoge; char hashfuga;"
|
133
|
+
hash_mapped_struct
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_hash_struct
|
137
|
+
obj = HashMapped.new
|
88
138
|
|
139
|
+
obj[:hashhoge] = 1
|
140
|
+
obj[:hashfuga] = 2
|
141
|
+
|
142
|
+
assert_equal([1,0,0,0,2].pack("C*"), obj.pack)
|
143
|
+
end
|
144
|
+
|
89
145
|
end
|
@@ -24,6 +24,7 @@ class TestUnpackable < Test::Unit::TestCase
|
|
24
24
|
end
|
25
25
|
|
26
26
|
class ClsInt < ClsIntNoAttr
|
27
|
+
include TEST_MOD
|
27
28
|
attr_accessor :packtestint
|
28
29
|
end
|
29
30
|
|
@@ -45,6 +46,7 @@ class TestUnpackable < Test::Unit::TestCase
|
|
45
46
|
end
|
46
47
|
|
47
48
|
class ClsChar < ClsCharNoAttr
|
49
|
+
include TEST_MOD
|
48
50
|
attr_accessor :packtestchar
|
49
51
|
end
|
50
52
|
|
@@ -83,5 +85,50 @@ class TestUnpackable < Test::Unit::TestCase
|
|
83
85
|
assert_equal(2, ud.fuga)
|
84
86
|
assert_equal([8], ud.piyo)
|
85
87
|
end
|
88
|
+
|
89
|
+
class ClsNested < OpenStruct
|
90
|
+
include TEST_MOD
|
91
|
+
self.byte_format = "int ho; char ge;"
|
92
|
+
end
|
93
|
+
|
94
|
+
class ClsNesting < OpenStruct
|
95
|
+
include TEST_MOD
|
96
|
+
self.byte_format = "struct ClsNested nst;"
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_struct
|
100
|
+
obj = ClsNesting.from_data([1,0,0,0, 10].pack("C*"))
|
101
|
+
assert_equal(1, obj.nst.ho)
|
102
|
+
assert_equal(10, obj.nst.ge)
|
103
|
+
end
|
104
|
+
|
105
|
+
class ClsArray < OpenStruct
|
106
|
+
include TEST_MOD
|
107
|
+
self.byte_format = "struct ClsNested ary[2];"
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_struct_array
|
111
|
+
obj = ClsArray.from_data([1,0,0,0,10,2,0,0,0,20].pack("C*"))
|
112
|
+
|
113
|
+
assert_equal(1, obj.ary[0].ho)
|
114
|
+
assert_equal(10, obj.ary[0].ge)
|
115
|
+
assert_equal(2, obj.ary[1].ho)
|
116
|
+
assert_equal(20, obj.ary[1].ge)
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
class HashMapped < Hash
|
121
|
+
include TEST_MOD
|
122
|
+
define_struct "int hashhoge; char hashfuga;"
|
123
|
+
hash_mapped_struct
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_hash_struct
|
127
|
+
obj = HashMapped.from_data([1,0,0,0,2].pack("C*") )
|
86
128
|
|
129
|
+
|
130
|
+
assert_equal(1, obj[:hashhoge])
|
131
|
+
assert_equal(2, obj[:hashfuga])
|
132
|
+
end
|
133
|
+
|
87
134
|
end
|
@@ -2,6 +2,12 @@ require File.dirname(__FILE__) + '/../test_helper.rb'
|
|
2
2
|
|
3
3
|
require 'ostruct'
|
4
4
|
|
5
|
+
|
6
|
+
class Hoge
|
7
|
+
include StructPacking::Packable
|
8
|
+
define_struct "int ho; char ge;"
|
9
|
+
end
|
10
|
+
|
5
11
|
class TestUtil < Test::Unit::TestCase
|
6
12
|
|
7
13
|
def setup
|
@@ -11,7 +17,44 @@ class TestUtil < Test::Unit::TestCase
|
|
11
17
|
tpl = StructPacking::Util.types_to_template(["int", "char"])
|
12
18
|
|
13
19
|
assert_equal("ic", tpl)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_array_type
|
23
|
+
tpl = StructPacking::Util.types_to_template(["int", "char"])
|
14
24
|
|
25
|
+
assert_equal("ic", tpl)
|
15
26
|
end
|
16
27
|
|
28
|
+
|
29
|
+
def test_pointer
|
30
|
+
tpl = StructPacking::Util.types_to_template(["int*", "char*[4]"])
|
31
|
+
|
32
|
+
assert_equal("PP4", tpl)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_struct
|
36
|
+
tpl = StructPacking::Util.types_to_template(["struct Hoge"])
|
37
|
+
|
38
|
+
assert_equal("ic", tpl)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def test_struct_array
|
43
|
+
tpl = StructPacking::Util.types_to_template(["struct Hoge[4]"])
|
44
|
+
|
45
|
+
assert_equal("icicicic", tpl)
|
46
|
+
end
|
47
|
+
|
48
|
+
class TestInnerClass
|
49
|
+
include StructPacking::Packable
|
50
|
+
define_struct "int fu; char ga;"
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_inner_module
|
54
|
+
tpl = StructPacking::Util.types_to_template(["struct TestInnerClass[4]"], self.class)
|
55
|
+
|
56
|
+
assert_equal("icicicic", tpl)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
17
60
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: struct_packing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02
|
12
|
+
date: 2013-03-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|
@@ -127,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
127
|
version: '0'
|
128
128
|
segments:
|
129
129
|
- 0
|
130
|
-
hash: -
|
130
|
+
hash: -170055565
|
131
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
132
|
none: false
|
133
133
|
requirements:
|