struct_packing 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|