cauterize 0.0.1.pre13 → 0.0.1.pre14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +33 -33
  3. data/.rspec +1 -1
  4. data/.travisci.yml +4 -4
  5. data/Gemfile +4 -4
  6. data/LICENSE.txt +21 -21
  7. data/README.md +177 -177
  8. data/Rakefile +54 -54
  9. data/bin/cauterize +61 -61
  10. data/cauterize.gemspec +27 -27
  11. data/example/Cauterize +68 -68
  12. data/example/build.sh +25 -25
  13. data/example/c_example_support/empty_main.c +1 -1
  14. data/example/c_example_support/example_project_config.c +11 -11
  15. data/example/c_example_support/example_project_config.h +15 -15
  16. data/example/ruby_ex.rb +14 -14
  17. data/lib/cauterize.rb +117 -117
  18. data/lib/cauterize/base_type.rb +78 -78
  19. data/lib/cauterize/builders.rb +41 -41
  20. data/lib/cauterize/builders/c/buildable.rb +91 -91
  21. data/lib/cauterize/builders/c/builtin.rb +43 -43
  22. data/lib/cauterize/builders/c/composite.rb +57 -57
  23. data/lib/cauterize/builders/c/enumeration.rb +60 -60
  24. data/lib/cauterize/builders/c/fixed_array.rb +74 -74
  25. data/lib/cauterize/builders/c/group.rb +143 -143
  26. data/lib/cauterize/builders/c/scalar.rb +34 -34
  27. data/lib/cauterize/builders/c/variable_array.rb +98 -98
  28. data/lib/cauterize/builders/cs/buildable.rb +59 -59
  29. data/lib/cauterize/builders/cs/builtin.rb +22 -22
  30. data/lib/cauterize/builders/cs/composite.rb +21 -21
  31. data/lib/cauterize/builders/cs/csarray.rb +32 -32
  32. data/lib/cauterize/builders/cs/enumeration.rb +21 -21
  33. data/lib/cauterize/builders/cs/fixed_array.rb +27 -27
  34. data/lib/cauterize/builders/cs/group.rb +32 -32
  35. data/lib/cauterize/builders/cs/scalar.rb +10 -10
  36. data/lib/cauterize/builders/cs/variable_array.rb +40 -34
  37. data/lib/cauterize/builders/doc/buildable.rb +30 -30
  38. data/lib/cauterize/builders/doc/builtin.rb +21 -21
  39. data/lib/cauterize/builders/doc/composite.rb +23 -23
  40. data/lib/cauterize/builders/doc/enumeration.rb +24 -24
  41. data/lib/cauterize/builders/doc/fixed_array.rb +26 -26
  42. data/lib/cauterize/builders/doc/group.rb +29 -29
  43. data/lib/cauterize/builders/doc/scalar.rb +21 -21
  44. data/lib/cauterize/builders/doc/variable_array.rb +26 -26
  45. data/lib/cauterize/builders/ruby/buildable.rb +11 -11
  46. data/lib/cauterize/builders/ruby/builtin.rb +25 -25
  47. data/lib/cauterize/builders/ruby/composite.rb +26 -26
  48. data/lib/cauterize/builders/ruby/enumeration.rb +27 -27
  49. data/lib/cauterize/builders/ruby/fixed_array.rb +20 -20
  50. data/lib/cauterize/builders/ruby/group.rb +35 -35
  51. data/lib/cauterize/builders/ruby/scalar.rb +19 -19
  52. data/lib/cauterize/builders/ruby/variable_array.rb +22 -22
  53. data/lib/cauterize/builtin.rb +62 -62
  54. data/lib/cauterize/c_builder.rb +103 -103
  55. data/lib/cauterize/cauterize.rb +76 -76
  56. data/lib/cauterize/composite.rb +64 -64
  57. data/lib/cauterize/cs_builder.rb +58 -58
  58. data/lib/cauterize/doc_builder.rb +34 -34
  59. data/lib/cauterize/enumeration.rb +98 -98
  60. data/lib/cauterize/fixed_array.rb +50 -50
  61. data/lib/cauterize/formatter.rb +67 -67
  62. data/lib/cauterize/group.rb +81 -81
  63. data/lib/cauterize/representation.rb +32 -32
  64. data/lib/cauterize/ruby_builder.rb +44 -44
  65. data/lib/cauterize/scalar.rb +53 -53
  66. data/lib/cauterize/snake_case.rb +21 -21
  67. data/lib/cauterize/variable_array.rb +55 -55
  68. data/lib/cauterize/version.rb +3 -3
  69. data/spec/base_type_spec.rb +251 -251
  70. data/spec/builders/c/buildable_spec.rb +25 -25
  71. data/spec/builders/c/builtin_spec.rb +22 -22
  72. data/spec/builders/c/composite_spec.rb +50 -50
  73. data/spec/builders/c/enumeration_spec.rb +95 -95
  74. data/spec/builders/c/fixed_array_spec.rb +36 -36
  75. data/spec/builders/c/group_spec.rb +140 -140
  76. data/spec/builders/c/scalar_spec.rb +26 -26
  77. data/spec/builders/c/variable_array_spec.rb +48 -48
  78. data/spec/builders/cs/buildable_spec.rb +8 -8
  79. data/spec/builders/cs/composite_spec.rb +32 -32
  80. data/spec/builders/cs/enumeration_spec.rb +33 -33
  81. data/spec/builders/cs/fixed_array_spec.rb +41 -41
  82. data/spec/builders/cs/group_spec.rb +56 -56
  83. data/spec/builders/cs/scalar_spec.rb +7 -7
  84. data/spec/builders/cs/variable_array_spec.rb +49 -45
  85. data/spec/builders/doc/buildable_spec.rb +25 -25
  86. data/spec/builders_spec.rb +57 -57
  87. data/spec/builtin_spec.rb +43 -43
  88. data/spec/c_builder_spec.rb +176 -176
  89. data/spec/cauterize_spec.rb +15 -15
  90. data/spec/composite_spec.rb +77 -77
  91. data/spec/cs_builder_spec.rb +115 -115
  92. data/spec/doc_builder_spec.rb +260 -260
  93. data/spec/enumeration_spec.rb +145 -145
  94. data/spec/fixed_array_spec.rb +61 -61
  95. data/spec/group_spec.rb +111 -111
  96. data/spec/ruby_builder_spec.rb +83 -83
  97. data/spec/ruby_generated_spec.rb +735 -735
  98. data/spec/scalar_spec.rb +44 -44
  99. data/spec/spec_helper.rb +122 -122
  100. data/spec/support/shared_examples_for_array_buildables.rb +22 -22
  101. data/spec/support/shared_examples_for_c_buildables.rb +103 -103
  102. data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -22
  103. data/spec/support/shared_examples_for_stubbed_functions.rb +18 -18
  104. data/spec/support/spec_sample_model.rb +74 -74
  105. data/spec/test_main.c +13 -13
  106. data/spec/variable_array_spec.rb +73 -73
  107. data/support/c/src/cauterize.c +75 -75
  108. data/support/c/src/cauterize.h +60 -60
  109. data/support/c/src/cauterize_debug.h +29 -29
  110. data/support/c/src/cauterize_util.h +8 -8
  111. data/support/c/test/greatest.h +536 -536
  112. data/support/c/test/test.c +166 -166
  113. data/support/cs/src/CauterizeCompositeFormatter.cs +0 -0
  114. data/support/cs/src/CauterizeContainerFormatter.cs +0 -0
  115. data/support/cs/src/CauterizeEnumFormatter.cs +0 -0
  116. data/support/cs/src/CauterizeException.cs +15 -15
  117. data/support/cs/src/CauterizeFixedArrayFormatter.cs +2 -2
  118. data/support/cs/src/CauterizeFormatter.cs +0 -0
  119. data/support/cs/src/CauterizeGroupFormatter.cs +0 -0
  120. data/support/cs/src/CauterizeTypeFormatterFactory.cs +0 -0
  121. data/support/cs/src/CauterizeTypes.cs +46 -12
  122. data/support/cs/src/CauterizeVariableArrayFormatter.cs +1 -1
  123. data/support/cs/src/ICauterizeTypeFormatter.cs +0 -0
  124. data/support/cs/src/OrderAttribute.cs +0 -0
  125. data/support/cs/src/PrimitiveSupport.cs +12 -0
  126. data/support/cs/test/CauterizeCompositeFormatterTest.cs +0 -0
  127. data/support/cs/test/CauterizeEnumFormatterTest.cs +0 -0
  128. data/support/cs/test/CauterizeFixedArrayFormatterTest.cs +0 -0
  129. data/support/cs/test/CauterizeFormatterTest.cs +0 -0
  130. data/support/cs/test/CauterizeGroupFormatterTest.cs +0 -0
  131. data/support/cs/test/CauterizeIntegrationTest.cs +0 -0
  132. data/support/cs/test/CauterizePrimitiveFormatterTest.cs +0 -0
  133. data/support/cs/test/CauterizeTypeFormatterFactoryTest.cs +0 -0
  134. data/support/cs/test/CauterizeVariableArrayFormatterTest.cs +0 -0
  135. data/support/cs/test/OrderAttributeTest.cs +0 -0
  136. data/support/ruby/src/cauterize_ruby_baseclasses.rb +367 -367
  137. data/support/ruby/src/cauterize_ruby_builtins.rb +148 -148
  138. metadata +20 -20
@@ -29,7 +29,7 @@ namespace Cauterize
29
29
  }
30
30
  else
31
31
  {
32
- var ret = t.GetConstructor(new Type[] {typeof (int)}).Invoke(new object[] {arraySize});
32
+ var ret = t.GetConstructor(new Type[] {typeof (ulong)}).Invoke(new object[] {(ulong)arraySize});
33
33
  var array = (Array)arrayField.GetValue(ret);
34
34
  var subFormatter = _typeFormatterFactory.GetFormatter(arrayType);
35
35
  for (var i = 0; i < arraySize; i++)
File without changes
File without changes
@@ -24,6 +24,18 @@ namespace Cauterize
24
24
  {
25
25
  return 8;
26
26
  }
27
+ else if (t == typeof (Single))
28
+ {
29
+ return 4;
30
+ }
31
+ else if (t == typeof (Double))
32
+ {
33
+ return 8;
34
+ }
35
+ else if (t == typeof (Boolean))
36
+ {
37
+ return 1;
38
+ }
27
39
  else
28
40
  {
29
41
  throw new Exception("Invalid type to get byte size");
File without changes
File without changes
@@ -1,367 +1,367 @@
1
- require 'stringio'
2
-
3
- module CauterizeRuby
4
- class Data
5
- @@specializers = Hash.new { |h, k| k }
6
-
7
- def self.set_specializer(c)
8
- @@specializers[self] = c
9
- end
10
-
11
- def self.do_construct(x)
12
- if x.is_a? Data
13
- raise "Invalid Type: was #{x.class}, expected #{self}" if not x.is_a?(self)
14
- x
15
- else
16
- self.new x
17
- end
18
- end
19
-
20
- def self.construct(x)
21
- @@specializers[self].do_construct(x)
22
- end
23
-
24
- def self.unpackio(x)
25
- @@specializers[self].do_unpackio(x)
26
- end
27
-
28
- def pack
29
- x = ""
30
- packio(x)
31
- x
32
- end
33
-
34
- def self.unpack(x)
35
- self.unpackio(StringIO.new(x))
36
- end
37
-
38
- def ==(other)
39
- (self <=> other) == 0
40
- end
41
-
42
- #this promotes 'other' to a cauterize type if it's not one already
43
- # this way 'cmp' can always assume 'other' is of the same type
44
- def <=>(other)
45
- cmp(self.class.construct(other))
46
- end
47
- end
48
-
49
- class Builtin < Data
50
- def initialize(val)
51
- @val = val
52
- end
53
- def to_ruby
54
- @val
55
- end
56
- # for builtins max_size == min_size
57
- def self.min_size() max_size end
58
- def num_bytes() self.class::max_size end
59
- end
60
-
61
- class BuiltinInteger < Builtin
62
- def initialize(val)
63
- #this will always set @val to a regular ruby Fixnum
64
- super(val.to_i)
65
- end
66
-
67
- def to_i
68
- @val
69
- end
70
-
71
- def to_f
72
- @val.to_f
73
- end
74
- end
75
-
76
- class BuiltinFloat < Builtin
77
- def initialize(val)
78
- #this will always set @val to a regular ruby float
79
- super(val.to_f)
80
- end
81
-
82
- def to_f
83
- @val
84
- end
85
-
86
- def to_i
87
- @val.to_i
88
- end
89
- end
90
-
91
- class BuiltinBool < Builtin
92
- def initialize(val)
93
- #this will always set @val to a regular ruby boolean value
94
- super((val)? true : false)
95
- end
96
- end
97
-
98
-
99
- class Scalar < Data
100
- attr_reader :builtin
101
- def initialize(val)
102
- # @builtin is going to be some form of Builtin
103
- @builtin = self.class.builtin.construct val
104
- raise "#{self.class}: Out of range value: #{@builtin.to_ruby}, for #{self.class}" if not @builtin.in_range(@builtin.to_ruby)
105
- end
106
-
107
- def to_ruby
108
- @builtin.to_ruby
109
- end
110
-
111
- def to_i
112
- @builtin.to_i
113
- end
114
-
115
- def to_f
116
- @builtin.to_f
117
- end
118
-
119
- def packio(x)
120
- @builtin.packio(x)
121
- end
122
-
123
- def self.do_unpackio(str)
124
- self.new self.builtin.unpackio(str)
125
- end
126
-
127
- def cmp(other)
128
- @builtin <=> other.builtin
129
- end
130
-
131
- def num_bytes() @builtin.num_bytes end
132
- def self.max_size() builtin::max_size end
133
- def self.min_size() builtin::min_size end
134
- end
135
-
136
- class Array < Data
137
-
138
- include Enumerable
139
-
140
- def initialize(elems)
141
- if elems.is_a? String
142
- # a special case for strings
143
- initialize_arr(elems.unpack("C*"))
144
- else
145
- initialize_arr(elems)
146
- end
147
- end
148
-
149
- def each
150
- elems.each do |e|
151
- yield e
152
- end
153
- end
154
-
155
- def to_ruby
156
- @elems.map{|e| e.to_ruby}
157
- end
158
-
159
- def to_string
160
- to_ruby.to_a.pack("C*")
161
- end
162
-
163
- def cmp(other)
164
- elems <=> other.elems
165
- end
166
- end
167
-
168
- class FixedArray < Array
169
- attr_reader :elems
170
-
171
- def initialize_arr(elems)
172
- @elems = elems.map { |e| self.class.elem_type.construct(e) }
173
- raise "#{self.class}: Invalid length: #{@elems.length}, expected: #{self.class.length}" if @elems.length != self.class.length
174
- end
175
-
176
- def packio(x)
177
- elems.each do |e|
178
- e.packio(x)
179
- end
180
- end
181
-
182
- def self.do_unpackio(str)
183
- self.new (1..self.length).map { self.elem_type.unpackio(str) }
184
- end
185
-
186
- def num_bytes() elems.reduce(0) {|sum, e| sum + e.num_bytes} end
187
- def self.max_size() length * elem_type::max_size end
188
- def self.min_size() length * elem_type::min_size end
189
- end
190
-
191
-
192
- class VariableArray < Array
193
- attr_reader :length
194
- attr_reader :elems
195
-
196
- def initialize_arr(elems)
197
- @elems = elems.map { |e| self.class.elem_type.construct(e) }
198
- @length = self.class.size_type.new @elems.length
199
- raise "#{self.class}: Invalid length: #{@elems.length}, max length is: #{self.class.max_length}" if @elems.length > self.class.max_length
200
- end
201
-
202
- def packio(x)
203
- @length.packio(x)
204
- @elems.each do |e|
205
- e.packio(x)
206
- end
207
- end
208
-
209
- def self.do_unpackio(str)
210
- length = self.size_type.unpackio(str)
211
- self.new (1..length.to_i).map { self.elem_type.unpackio(str) }
212
- end
213
-
214
- def num_bytes() length.num_bytes + elems.reduce(0) {|sum, e| sum + e.num_bytes} end
215
- def self.max_size() size_type::max_size + (max_length * elem_type::max_size) end
216
- def self.min_size() size_type::min_size end
217
- end
218
-
219
-
220
- class Composite < Data
221
- attr_reader :fields
222
-
223
- def initialize(field_values)
224
- missing_keys = self.class.fields.keys - field_values.keys
225
- extra_keys = field_values.keys - self.class.fields.keys
226
- bad_init = !extra_keys.empty? || !missing_keys.empty?
227
- raise "#{self.class}: Invalid initialization params, missing fields: #{missing_keys}, extra fields: #{extra_keys}" if bad_init
228
- @fields = Hash[self.class.fields.keys.map do |field_name|
229
- [field_name, self.class.fields[field_name].construct(field_values[field_name])]
230
- end]
231
- end
232
-
233
- def to_ruby
234
- Hash[@fields.map{|name, value| [name, value.to_ruby]}]
235
- end
236
-
237
- def packio(x)
238
- @fields.values.each do |v|
239
- v.packio(x)
240
- end
241
- end
242
-
243
- def self.do_unpackio(str)
244
- self.new Hash[self.fields.keys.map do |k|
245
- [k, self.fields[k].unpackio(str)]
246
- end]
247
- end
248
-
249
- def cmp(other)
250
- fields.values <=> other.fields.values
251
- end
252
-
253
- def num_bytes
254
- fields.values.reduce(0) {|sum, v| sum + v.num_bytes}
255
- end
256
-
257
- def self.max_size
258
- fields.values.reduce(0) {|sum, v| sum + v::max_size}
259
- end
260
-
261
- def self.min_size
262
- fields.values.reduce(0) {|sum, v| sum + v::min_size}
263
- end
264
- end
265
-
266
-
267
- class Enumeration < Data
268
- attr_reader :field_name
269
-
270
- def initialize(field_name)
271
- raise "#{self.class}: Invalid field name: #{field_name}, Valid field names are: #{self.class.fields.keys}" if not self.class.fields.keys.include?(field_name)
272
- @field_name = field_name
273
- end
274
-
275
- def to_ruby
276
- @field_name
277
- end
278
-
279
- def to_i() self.class.fields[@field_name] end
280
-
281
- def packio(x)
282
- self.class.repr_type.construct(self.class.fields[@field_name]).packio(x)
283
- end
284
-
285
- def self.from_int(i)
286
- raise "#{self}: Invalid enumeration value: #{i.to_i}" if not self.fields.values.include? i.to_i
287
- self.new(self.fields.invert[i.to_i])
288
- end
289
-
290
- def self.do_unpackio(str)
291
- self.from_int(self.repr_type.unpackio(str).to_i)
292
- end
293
-
294
- def cmp(other)
295
- to_i <=> other.to_i
296
- end
297
-
298
- def num_bytes() self.class.repr_type::max_size end
299
- def self.max_size() repr_type::max_size end
300
- def self.min_size() repr_type::min_size end
301
- end
302
-
303
-
304
- class Group < Data
305
- attr_reader :tag
306
- attr_reader :data
307
-
308
- def to_ruby
309
- if data.nil?
310
- { tag: tag_field_name }
311
- else
312
- { tag: tag_field_name,
313
- data: data.to_ruby }
314
- end
315
- end
316
-
317
- def tag_field_name
318
- self.class.from_tag_field_name(@tag.field_name)
319
- end
320
-
321
- def self.tag_from_field_name(field_name)
322
- self.tag_type.construct((self.tag_prefix + field_name.to_s).to_sym)
323
- end
324
-
325
- def self.from_tag_field_name(tag_name)
326
- t = tag_name.to_s
327
- t.slice!(self.tag_prefix)
328
- t.to_sym
329
- end
330
-
331
- def initialize(h)
332
- @tag = self.class.tag_from_field_name(h[:tag])
333
- field_class = self.class.fields[tag_field_name]
334
- @data = (field_class.nil?) ? nil : field_class.construct(h[:data])
335
- end
336
-
337
- def packio(x)
338
- @tag.packio(x)
339
- @data.packio(x) unless @data.nil?
340
- end
341
-
342
- def self.do_unpackio(str)
343
- tag = self.tag_type.unpackio(str)
344
- field_name = self.from_tag_field_name(tag.field_name)
345
- data_type = self.fields[field_name]
346
- if data_type.nil?
347
- self.new({ tag: field_name })
348
- else
349
- self.new({ tag: field_name, data: data_type.unpackio(str) })
350
- end
351
- end
352
-
353
- def cmp(other)
354
- r = (tag <=> other.tag)
355
- if r == 0
356
- data <=> other.data
357
- else
358
- r
359
- end
360
- end
361
-
362
- def num_bytes() tag.num_bytes + ((data.nil?) ? 0 : data.num_bytes) end
363
-
364
- def self.max_size() tag_type::max_size + fields.values.map{|v| (v.nil?) ? 0 : v::max_size}.max end
365
- def self.min_size() tag_type::min_size + fields.values.map{|v| (v.nil?) ? 0 : v::min_size}.min end
366
- end
367
- end
1
+ require 'stringio'
2
+
3
+ module CauterizeRuby
4
+ class Data
5
+ @@specializers = Hash.new { |h, k| k }
6
+
7
+ def self.set_specializer(c)
8
+ @@specializers[self] = c
9
+ end
10
+
11
+ def self.do_construct(x)
12
+ if x.is_a? Data
13
+ raise "Invalid Type: was #{x.class}, expected #{self}" if not x.is_a?(self)
14
+ x
15
+ else
16
+ self.new x
17
+ end
18
+ end
19
+
20
+ def self.construct(x)
21
+ @@specializers[self].do_construct(x)
22
+ end
23
+
24
+ def self.unpackio(x)
25
+ @@specializers[self].do_unpackio(x)
26
+ end
27
+
28
+ def pack
29
+ x = ""
30
+ packio(x)
31
+ x
32
+ end
33
+
34
+ def self.unpack(x)
35
+ self.unpackio(StringIO.new(x))
36
+ end
37
+
38
+ def ==(other)
39
+ (self <=> other) == 0
40
+ end
41
+
42
+ #this promotes 'other' to a cauterize type if it's not one already
43
+ # this way 'cmp' can always assume 'other' is of the same type
44
+ def <=>(other)
45
+ cmp(self.class.construct(other))
46
+ end
47
+ end
48
+
49
+ class Builtin < Data
50
+ def initialize(val)
51
+ @val = val
52
+ end
53
+ def to_ruby
54
+ @val
55
+ end
56
+ # for builtins max_size == min_size
57
+ def self.min_size() max_size end
58
+ def num_bytes() self.class::max_size end
59
+ end
60
+
61
+ class BuiltinInteger < Builtin
62
+ def initialize(val)
63
+ #this will always set @val to a regular ruby Fixnum
64
+ super(val.to_i)
65
+ end
66
+
67
+ def to_i
68
+ @val
69
+ end
70
+
71
+ def to_f
72
+ @val.to_f
73
+ end
74
+ end
75
+
76
+ class BuiltinFloat < Builtin
77
+ def initialize(val)
78
+ #this will always set @val to a regular ruby float
79
+ super(val.to_f)
80
+ end
81
+
82
+ def to_f
83
+ @val
84
+ end
85
+
86
+ def to_i
87
+ @val.to_i
88
+ end
89
+ end
90
+
91
+ class BuiltinBool < Builtin
92
+ def initialize(val)
93
+ #this will always set @val to a regular ruby boolean value
94
+ super((val)? true : false)
95
+ end
96
+ end
97
+
98
+
99
+ class Scalar < Data
100
+ attr_reader :builtin
101
+ def initialize(val)
102
+ # @builtin is going to be some form of Builtin
103
+ @builtin = self.class.builtin.construct val
104
+ raise "#{self.class}: Out of range value: #{@builtin.to_ruby}, for #{self.class}" if not @builtin.in_range(@builtin.to_ruby)
105
+ end
106
+
107
+ def to_ruby
108
+ @builtin.to_ruby
109
+ end
110
+
111
+ def to_i
112
+ @builtin.to_i
113
+ end
114
+
115
+ def to_f
116
+ @builtin.to_f
117
+ end
118
+
119
+ def packio(x)
120
+ @builtin.packio(x)
121
+ end
122
+
123
+ def self.do_unpackio(str)
124
+ self.new self.builtin.unpackio(str)
125
+ end
126
+
127
+ def cmp(other)
128
+ @builtin <=> other.builtin
129
+ end
130
+
131
+ def num_bytes() @builtin.num_bytes end
132
+ def self.max_size() builtin::max_size end
133
+ def self.min_size() builtin::min_size end
134
+ end
135
+
136
+ class Array < Data
137
+
138
+ include Enumerable
139
+
140
+ def initialize(elems)
141
+ if elems.is_a? String
142
+ # a special case for strings
143
+ initialize_arr(elems.unpack("C*"))
144
+ else
145
+ initialize_arr(elems)
146
+ end
147
+ end
148
+
149
+ def each
150
+ elems.each do |e|
151
+ yield e
152
+ end
153
+ end
154
+
155
+ def to_ruby
156
+ @elems.map{|e| e.to_ruby}
157
+ end
158
+
159
+ def to_string
160
+ to_ruby.to_a.pack("C*")
161
+ end
162
+
163
+ def cmp(other)
164
+ elems <=> other.elems
165
+ end
166
+ end
167
+
168
+ class FixedArray < Array
169
+ attr_reader :elems
170
+
171
+ def initialize_arr(elems)
172
+ @elems = elems.map { |e| self.class.elem_type.construct(e) }
173
+ raise "#{self.class}: Invalid length: #{@elems.length}, expected: #{self.class.length}" if @elems.length != self.class.length
174
+ end
175
+
176
+ def packio(x)
177
+ elems.each do |e|
178
+ e.packio(x)
179
+ end
180
+ end
181
+
182
+ def self.do_unpackio(str)
183
+ self.new (1..self.length).map { self.elem_type.unpackio(str) }
184
+ end
185
+
186
+ def num_bytes() elems.reduce(0) {|sum, e| sum + e.num_bytes} end
187
+ def self.max_size() length * elem_type::max_size end
188
+ def self.min_size() length * elem_type::min_size end
189
+ end
190
+
191
+
192
+ class VariableArray < Array
193
+ attr_reader :length
194
+ attr_reader :elems
195
+
196
+ def initialize_arr(elems)
197
+ @elems = elems.map { |e| self.class.elem_type.construct(e) }
198
+ @length = self.class.size_type.new @elems.length
199
+ raise "#{self.class}: Invalid length: #{@elems.length}, max length is: #{self.class.max_length}" if @elems.length > self.class.max_length
200
+ end
201
+
202
+ def packio(x)
203
+ @length.packio(x)
204
+ @elems.each do |e|
205
+ e.packio(x)
206
+ end
207
+ end
208
+
209
+ def self.do_unpackio(str)
210
+ length = self.size_type.unpackio(str)
211
+ self.new (1..length.to_i).map { self.elem_type.unpackio(str) }
212
+ end
213
+
214
+ def num_bytes() length.num_bytes + elems.reduce(0) {|sum, e| sum + e.num_bytes} end
215
+ def self.max_size() size_type::max_size + (max_length * elem_type::max_size) end
216
+ def self.min_size() size_type::min_size end
217
+ end
218
+
219
+
220
+ class Composite < Data
221
+ attr_reader :fields
222
+
223
+ def initialize(field_values)
224
+ missing_keys = self.class.fields.keys - field_values.keys
225
+ extra_keys = field_values.keys - self.class.fields.keys
226
+ bad_init = !extra_keys.empty? || !missing_keys.empty?
227
+ raise "#{self.class}: Invalid initialization params, missing fields: #{missing_keys}, extra fields: #{extra_keys}" if bad_init
228
+ @fields = Hash[self.class.fields.keys.map do |field_name|
229
+ [field_name, self.class.fields[field_name].construct(field_values[field_name])]
230
+ end]
231
+ end
232
+
233
+ def to_ruby
234
+ Hash[@fields.map{|name, value| [name, value.to_ruby]}]
235
+ end
236
+
237
+ def packio(x)
238
+ @fields.values.each do |v|
239
+ v.packio(x)
240
+ end
241
+ end
242
+
243
+ def self.do_unpackio(str)
244
+ self.new Hash[self.fields.keys.map do |k|
245
+ [k, self.fields[k].unpackio(str)]
246
+ end]
247
+ end
248
+
249
+ def cmp(other)
250
+ fields.values <=> other.fields.values
251
+ end
252
+
253
+ def num_bytes
254
+ fields.values.reduce(0) {|sum, v| sum + v.num_bytes}
255
+ end
256
+
257
+ def self.max_size
258
+ fields.values.reduce(0) {|sum, v| sum + v::max_size}
259
+ end
260
+
261
+ def self.min_size
262
+ fields.values.reduce(0) {|sum, v| sum + v::min_size}
263
+ end
264
+ end
265
+
266
+
267
+ class Enumeration < Data
268
+ attr_reader :field_name
269
+
270
+ def initialize(field_name)
271
+ raise "#{self.class}: Invalid field name: #{field_name}, Valid field names are: #{self.class.fields.keys}" if not self.class.fields.keys.include?(field_name)
272
+ @field_name = field_name
273
+ end
274
+
275
+ def to_ruby
276
+ @field_name
277
+ end
278
+
279
+ def to_i() self.class.fields[@field_name] end
280
+
281
+ def packio(x)
282
+ self.class.repr_type.construct(self.class.fields[@field_name]).packio(x)
283
+ end
284
+
285
+ def self.from_int(i)
286
+ raise "#{self}: Invalid enumeration value: #{i.to_i}" if not self.fields.values.include? i.to_i
287
+ self.new(self.fields.invert[i.to_i])
288
+ end
289
+
290
+ def self.do_unpackio(str)
291
+ self.from_int(self.repr_type.unpackio(str).to_i)
292
+ end
293
+
294
+ def cmp(other)
295
+ to_i <=> other.to_i
296
+ end
297
+
298
+ def num_bytes() self.class.repr_type::max_size end
299
+ def self.max_size() repr_type::max_size end
300
+ def self.min_size() repr_type::min_size end
301
+ end
302
+
303
+
304
+ class Group < Data
305
+ attr_reader :tag
306
+ attr_reader :data
307
+
308
+ def to_ruby
309
+ if data.nil?
310
+ { tag: tag_field_name }
311
+ else
312
+ { tag: tag_field_name,
313
+ data: data.to_ruby }
314
+ end
315
+ end
316
+
317
+ def tag_field_name
318
+ self.class.from_tag_field_name(@tag.field_name)
319
+ end
320
+
321
+ def self.tag_from_field_name(field_name)
322
+ self.tag_type.construct((self.tag_prefix + field_name.to_s).to_sym)
323
+ end
324
+
325
+ def self.from_tag_field_name(tag_name)
326
+ t = tag_name.to_s
327
+ t.slice!(self.tag_prefix)
328
+ t.to_sym
329
+ end
330
+
331
+ def initialize(h)
332
+ @tag = self.class.tag_from_field_name(h[:tag])
333
+ field_class = self.class.fields[tag_field_name]
334
+ @data = (field_class.nil?) ? nil : field_class.construct(h[:data])
335
+ end
336
+
337
+ def packio(x)
338
+ @tag.packio(x)
339
+ @data.packio(x) unless @data.nil?
340
+ end
341
+
342
+ def self.do_unpackio(str)
343
+ tag = self.tag_type.unpackio(str)
344
+ field_name = self.from_tag_field_name(tag.field_name)
345
+ data_type = self.fields[field_name]
346
+ if data_type.nil?
347
+ self.new({ tag: field_name })
348
+ else
349
+ self.new({ tag: field_name, data: data_type.unpackio(str) })
350
+ end
351
+ end
352
+
353
+ def cmp(other)
354
+ r = (tag <=> other.tag)
355
+ if r == 0
356
+ data <=> other.data
357
+ else
358
+ r
359
+ end
360
+ end
361
+
362
+ def num_bytes() tag.num_bytes + ((data.nil?) ? 0 : data.num_bytes) end
363
+
364
+ def self.max_size() tag_type::max_size + fields.values.map{|v| (v.nil?) ? 0 : v::max_size}.max end
365
+ def self.min_size() tag_type::min_size + fields.values.map{|v| (v.nil?) ? 0 : v::min_size}.min end
366
+ end
367
+ end