gogyou 0.2.1 → 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1f4c10b0e249b1b9897b5b1c317e0ef5e535830
4
- data.tar.gz: c8ccad916b49f45e18d91bff8538cf1b7e5b6377
3
+ metadata.gz: ff192352d61629b6bcec6f1f4a3ce798c2cab5ff
4
+ data.tar.gz: 244710ba81429d85608ed708424971d5c1bcd843
5
5
  SHA512:
6
- metadata.gz: b73dba83766abfce2f63ba2daad894fdf3b7560ed20bfa613d9d388aa707f053dac67f8133f6fe76002eb0958824d8b6cec23fc1a05b58228244d1ab0cfdb503
7
- data.tar.gz: 93b5fb1d45270650ff47c10746ec94ddf0b44c59751b8f035af841902a0fc807f02e2c39820447ca9d055aeafa1abc4ee1ab78a9e2f72383e5d7db0a7e325fd1
6
+ metadata.gz: b575790ca4b409310f7418dcc4e12220a9dfaeb511f4449756ad9997e83abf1c77953efa2d3dcc33c28e8b5fe92e0f71b66bb65ba296603054ab2639b85904eb
7
+ data.tar.gz: 3cc09af86d7884cca95aa399c912d19963608399273d45dd96cfbedc239c136f718e87ce2d2a8c6918d5757a0e2ddded0d93ff94afe45840f894de9ded4f003c
@@ -77,7 +77,7 @@ end
77
77
  obj = MyRuby::RObject.new
78
78
  # or obj = MyRuby::RObject.new(File.read("sample.bin", MyRuby::RObject.size, mode: "rb"))
79
79
  obj.basic.flags = 0x12345678
80
- (obj.basic.klass = 0xaaaaaaaa) rescue $! # => exception! klass field is immutable type
80
+ (obj.basic.klass = 0xaaaaaaaa) rescue p $! # => exception! klass field is immutable type
81
81
  obj.basic.force_modify.klass = 0xaaaaaaaa
82
82
  obj.as.heap.numiv = 0x55555555
83
83
  p obj.as.ary[0] # => 0x55555555
@@ -97,37 +97,73 @@ p obj.to_buffer # => "xV4\x12\0\0\0\0\xaa\xaa\xaa\xaa\0\0\0\0UUUU\0\0\0\0DDDD\0
97
97
 
98
98
  C に似た構造体・共用体に対応 (入れ子構造も可能)
99
99
 
100
- struct {
101
- struct {
102
- ....
103
- union {
104
- ....
105
- struct {
106
- ....
107
- }
108
- }
109
- ....
110
- }
111
- }
100
+ ``` ruby:ruby
101
+ X = Gogyou.struct {
102
+ int :a
103
+ float :b
104
+ double :c
105
+ union {
106
+ struct -> {
107
+ float :x, y, z
108
+ }, :d
109
+ const struct -> {
110
+ int :x, :y, :z
111
+ }, :e
112
+ }
113
+ }
114
+ ```
112
115
 
113
116
  * Support multidimensional arrays
114
117
 
115
118
  多次元配列に対応
116
119
 
117
- struct {
118
- char :name, 64, 4 # => char name[64][4];
119
- }
120
+ ``` ruby:ruby
121
+ Gogyou.struct {
122
+ char :name, 64, 4 # => char name[64][4];
123
+ }
124
+ ```
120
125
 
121
126
  * Alias types by `typedef` (with array)
122
127
 
123
128
  `typedef` による型の別名定義 (配列も可能)
124
129
 
125
- typedef :float, :vector3f, 3 # => C: typedef float vector3f[3];
130
+ ``` ruby:ruby
131
+ module MyModule
132
+ extend Gogyou
133
+
134
+ typedef :float, :vector3f, 3 # => C: typedef float vector3f[3];
135
+
136
+ X = struct { # struct X {
137
+ vector3f :a # vector3f a;
138
+ vector3f :b, 4 # vector3f b[4];
139
+ } # };
140
+ end
141
+ ```
142
+
143
+ * Support packed struct liked GCC ``__attribute__((packed))``
144
+
145
+ GCC の ``__attribute__((packed))`` に似た、パックされた構造体に対応
146
+
147
+ C 言語での記述
148
+
149
+ ``` c:c
150
+ struct X
151
+ {
152
+ char a;
153
+ int b;
154
+ } __attribute__((packed));
155
+ ```
156
+
157
+ ruby による記述
126
158
 
127
- X = struct { # struct X {
128
- vector3f :a # vector3f a;
129
- vector3f :b, 4 # vector3f b[4];
130
- } # };
159
+ ``` ruby:ruby
160
+ X = Gogyou.struct {
161
+ packed {
162
+ char :a
163
+ int :b
164
+ }
165
+ }
166
+ ```
131
167
 
132
168
  * Appended bit operation for Integer
133
169
 
@@ -284,7 +320,7 @@ struct 内の struct の呼び出し方法を示します。union も同様に
284
320
 
285
321
  例として、MD5 を定義する場合の型情報は次のようになります。
286
322
 
287
- ```ruby:ruby
323
+ ``` ruby:ruby
288
324
  class MD5
289
325
  def self.bytesize
290
326
  16
@@ -308,6 +344,18 @@ class MD5
308
344
  end
309
345
  ```
310
346
 
347
+ これらのメソッドを一つ一つ定義する代わりに、任意のクラス・モジュールの中で ``Gogyou.define_typeinfo`` を用いることでまとめて定義することも出来ます。
348
+
349
+ ``` ruby:ruby
350
+ class MD5
351
+ Gogyou.define_typeinfo(16, # bytesize
352
+ 1, # bytealign
353
+ false, # extensible?
354
+ ->(buffer, offset) { ... snip ... }, # aref
355
+ ->(buffer, offset, data) { ... snip ... }) # aset
356
+ end
357
+ ```
358
+
311
359
  順を追って説明していきます。
312
360
 
313
361
  ### `.bytesize`
@@ -413,6 +461,60 @@ class MD5
413
461
  end
414
462
  ```
415
463
 
464
+ ## Define packed struct
465
+
466
+ GCC の ``__attribute__((packed))`` に似たパックされた構造体のフィールドを定義するには、そのフィールドを ``packed`` メソッドのブロックとして囲うことで行います。
467
+
468
+ 構造体自体をパックするには、その構造体のフィールド全体を ``packed`` することで行います。
469
+
470
+ また、``packed`` の中に ``struct`` や ``union`` を含めることも出来、その入れ子内部で ``packed`` を行うことも出来ます。
471
+
472
+ ただし ``packed`` を直接入れ子にして呼び出すことは出来ません。
473
+
474
+ 構造体全体を ``packed`` する場合:
475
+
476
+ ``` ruby:ruby
477
+ X = Gogyou.struct {
478
+ packed {
479
+ char :a
480
+ int :b
481
+ int :c
482
+ }
483
+ }
484
+
485
+ p X.bytesize # => 9
486
+ ```
487
+
488
+ ``packed`` された入れ子構造体の内部でさらに ``packed`` する場合:
489
+
490
+ ``` ruby:ruby
491
+ Y = Gogyou.struct {
492
+ char :a
493
+ packed {
494
+ struct {
495
+ int :b
496
+ }
497
+ }
498
+ char :c, 3
499
+ int :d
500
+ }
501
+
502
+ p Y.bytesize # => 12
503
+ ```
504
+
505
+ 直接入れ子にして ``packed`` して例外が発生する場合:
506
+
507
+ ``` ruby:ruby
508
+ Z = Gogyou.struct {
509
+ packed {
510
+ packed { ## => EXCEPTION!
511
+ char :a
512
+ int :b
513
+ }
514
+ }
515
+ }
516
+ ```
517
+
416
518
 
417
519
  ## Demerit (短所)
418
520
 
@@ -423,7 +525,3 @@ end
423
525
  * The cost is high for reference/asignment from/to fields
424
526
 
425
527
  フィールドに対する参照・代入のコストが高い
426
-
427
- * Can't be definition for packed struct
428
-
429
- パックされた構造体の定義が出来ない (常にフィールドは型によるバイト境界に強制配置される)
@@ -141,7 +141,7 @@
141
141
  #
142
142
  module Gogyou
143
143
  Gogyou = self
144
- VERSION = Gem::Version.new("0.2.1")
144
+ VERSION = Gem::Version.new("0.2.2")
145
145
 
146
146
  require_relative "gogyou/typespec"
147
147
  require_relative "gogyou/mixin"
@@ -196,6 +196,89 @@ module Gogyou
196
196
  end
197
197
  end
198
198
 
199
+ #
200
+ # call-seq:
201
+ # define_typeinfo(type, bytesize, bytealign, extensible, aref, aset) -> type
202
+ #
203
+ # ``type`` に対して、型情報子とするための特異メソッドである ``#bytesize`` ``#bytealign`` ``#extensible?`` ``#aref`` ``#aset`` を定義します。
204
+ #
205
+ # ``bytesize`` と ``bytealign`` には整数値、文字列、nil を与えます。
206
+ #
207
+ # ``extensible`` には真偽値、文字列、nil を与えます。
208
+ #
209
+ # ``aref`` には、引数として ``(buffer, offset)`` を受け取る Proc オブジェクト、文字列、nil を与えます。
210
+ #
211
+ # ``aset`` には、引数として ``(buffer, offset, value)`` を受け取る Proc オブジェクト、文字列、nil を与えます。
212
+ #
213
+ # これらの引数に文字列を与えた場合、メソッド定義コードとして直接埋め込まれます。
214
+ #
215
+ # ``bytesize`` と ``bytealign``、``extensible`` の引数はありません。
216
+ #
217
+ # ``aref`` の文字列内部で利用できる引数は ``buffer`` ``offset`` です。
218
+ #
219
+ # ``aset`` の文字列内部で利用できる引数は ``buffer`` ``offset`` ``value`` です。
220
+ #
221
+ # また nil を与えた場合は、対応するメソッドの定義を省略します。
222
+ #
223
+ # 常に ``type`` を返します。
224
+ #
225
+ def self.define_typeinfo(type, bytesize, bytealign, extensible, aref, aset)
226
+ type.instance_eval do
227
+ unless bytesize.nil?
228
+ bytesize = bytesize.to_i unless bytesize.kind_of?(String)
229
+ eval <<-EOM
230
+ def bytesize
231
+ #{bytesize}
232
+ end
233
+ EOM
234
+ end
235
+
236
+ unless bytealign.nil?
237
+ bytealign = bytealign.to_i unless bytealign.kind_of?(String)
238
+ eval <<-EOM
239
+ def bytealign
240
+ #{bytealign}
241
+ end
242
+ EOM
243
+ end
244
+
245
+ unless extensible.nil?
246
+ extensible = (!!extensible).inspect unless extensible.kind_of?(String)
247
+ eval <<-EOM
248
+ def extensible?
249
+ #{extensible}
250
+ end
251
+ EOM
252
+ end
253
+
254
+ unless aref.nil?
255
+ if aref.kind_of?(String)
256
+ eval <<-EOM
257
+ def aref(buffer, offset)
258
+ #{aref}
259
+ end
260
+ EOM
261
+ else
262
+ define_singleton_method(:aref, aref)
263
+ end
264
+ end
265
+
266
+ unless aset.nil?
267
+ if aset.kind_of?(String)
268
+ eval <<-EOM
269
+ def aset(buffer, offset, value)
270
+ #{aset}
271
+ end
272
+ EOM
273
+ else
274
+ define_singleton_method(:aset, aset)
275
+ end
276
+ end
277
+ end
278
+
279
+ type
280
+ end
281
+
199
282
  #
200
283
  # 構造体 (もどき) を定義します。
201
284
  #
@@ -90,7 +90,7 @@ module Gogyou
90
90
 
91
91
  def inspect
92
92
  "#<%s buffer=%p, offset=%p>" % [self.class,
93
- buffer__GOGYOU__,
93
+ buffer__GOGYOU__.inspect,
94
94
  offset__GOGYOU__]
95
95
  end
96
96
 
@@ -337,7 +337,7 @@ module Gogyou
337
337
  case value
338
338
  when ::String
339
339
  raise ArgumentError, "buffer size too small" unless value.bytesize < self::BYTESIZE
340
- buffer.setbinary(offset, value, self::BYTESIZE, 0)
340
+ buffer.setbinary(offset, value, 0, self::BYTESIZE)
341
341
  when ::Array
342
342
  raise NotImplementedError
343
343
  when self::SUBTYPE
@@ -231,7 +231,7 @@ module Gogyou
231
231
  self
232
232
  end
233
233
 
234
- def setbinary(index, str, bytesize = str.bytesize, offset = 0)
234
+ def setbinary(index, str, offset = 0, bytesize = str.bytesize)
235
235
  offset = offset.to_i
236
236
  bytesize = bytesize.to_i
237
237
  size1 = str.bytesize - offset
@@ -66,13 +66,14 @@ module Gogyou
66
66
  :name, # field name
67
67
  :vector, # 要素数。任意数配列の場合は 0。配列でないならば nil。
68
68
  :type, # type specification (or model object) of this field
69
- :flags) # 0x01: const / 0x02: packed (not aligned)
69
+ :flags) # LSB-0+8: packed size exponent (not aligned) / LSB-16: const
70
70
  BasicStruct = superclass
71
71
 
72
- FLAG_CONST = 0x01
73
- FLAG_PACKED = 0x02
72
+ CONST_BITMASK = 1 << 16
73
+ PACKSIZE_BITMASK = 0xff
74
+ PACKSIZE_NOTDEFINE = 20 # = (1 << 20) = 1 MiB # 事実上の無限
74
75
 
75
- def initialize(offset, name, vector, type, flags = 0)
76
+ def initialize(offset, name, vector, type, flags = 0 | PACKSIZE_NOTDEFINE)
76
77
  super(offset, name, vector, type, flags)
77
78
  end
78
79
 
@@ -85,25 +86,30 @@ module Gogyou
85
86
  end
86
87
 
87
88
  def const?
88
- ((flags & FLAG_CONST) == FLAG_CONST) ? true : false
89
+ ((flags & CONST_BITMASK) == CONST_BITMASK) ? true : false
89
90
  end
90
91
 
91
92
  def packed?
92
- ((flags & FLAG_PACKED) == FLAG_PACKED) ? true : false
93
+ ((flags & PACKSIZE_BITMASK) == PACKSIZE_NOTDEFINE) ? false : true
93
94
  end
94
95
 
95
- def mark_const
96
- self.flags |= FLAG_CONST
96
+ def set_const
97
+ self.flags |= CONST_BITMASK
97
98
  self
98
99
  end
99
100
 
100
- def mark_packed
101
- self.flags |= FLAGS_PACKED
101
+ def set_packsize(pack_exponent)
102
+ pack_exponent = PACKSIZE_NOTDEFINE if pack_exponent > PACKSIZE_NOTDEFINE
103
+ self.flags = flags.setbit(0, 8, pack_exponent)
102
104
  self
103
105
  end
104
106
 
107
+ def packsize
108
+ 1 << flags.getbit(0, 8)
109
+ end
110
+
105
111
  def strflags
106
- set = [const? ? "const" : nil, packed? ? "packed" : nil]
112
+ set = [const? ? "const" : nil, packed? ? "packed(#{packsize})" : nil]
107
113
  set.compact!
108
114
  return nil if set.empty?
109
115
  set.join(",")
@@ -145,12 +151,12 @@ module Gogyou
145
151
  end
146
152
  end
147
153
 
148
- def self.struct(typemap, &block)
149
- define_container(typemap, Model::Struct, &block)
154
+ def self.struct(typemap, packexp = Field::PACKSIZE_NOTDEFINE, &block)
155
+ define_container(typemap, packexp, Model::Struct, &block)
150
156
  end
151
157
 
152
- def self.union(typemap, &block)
153
- define_container(typemap, Model::Union, &block)
158
+ def self.union(typemap, packexp = Field::PACKSIZE_NOTDEFINE, &block)
159
+ define_container(typemap, packexp, Model::Union, &block)
154
160
  end
155
161
 
156
162
  def self.typedef(typemap, type, aliasname, *elements)
@@ -178,9 +184,9 @@ module Gogyou
178
184
  nil
179
185
  end
180
186
 
181
- def self.define_container(typemap, model_type, &block)
187
+ def self.define_container(typemap, packexp, model_type, &block)
182
188
  creator = model_type::Creator.new(typemap, 0, [])
183
- proxy = model_type::Creator::Proxy.new(creator)
189
+ proxy = model_type::Creator::Proxy.new(creator, packexp)
184
190
  proxy.instance_exec(&block)
185
191
  model = creator.to_model
186
192
  model
@@ -205,7 +211,7 @@ module Gogyou
205
211
 
206
212
  class BasicCreator
207
213
  def maxalign(fields = self.fields)
208
- fields.map { |f| f.type.bytealign }.max
214
+ fields.map { |f| f.packed? ? f.packsize : f.type.bytealign }.max
209
215
  end
210
216
 
211
217
  def maxsize(fields = self.fields)
@@ -223,7 +229,7 @@ module Gogyou
223
229
  else
224
230
  raise "BUG? : field.type is not a Model (%p)" % f.type unless f.type.kind_of?(Model)
225
231
  fs = flatten_field(f.type.fields)
226
- fs.each { |ff| ff.offset += f.offset; ff.mark_const if f.const? }
232
+ fs.each { |ff| ff.offset += f.offset; ff.set_const if f.const? }
227
233
  fields2.concat fs
228
234
  end
229
235
  end
@@ -233,23 +239,42 @@ module Gogyou
233
239
  # :nodoc: all
234
240
  class Proxy < Object
235
241
  #class Proxy < BasicObject
236
- def initialize(creator)
242
+ def initialize(creator, packexp = Field::PACKSIZE_NOTDEFINE)
237
243
  #singleton_class = (class << proxy; self; end)
238
244
  singleton_class.class_eval do
239
245
  latest_fields = nil
240
246
  #define_method(:method_missing, ->(type, *args) { latest_fields = creator.addfield(type, args); nil })
241
247
  creator.typemap.each_key do |t|
242
- define_method(t, ->(*args) { latest_fields = creator.addfield(t, args); nil })
248
+ define_method(t, ->(*args) { latest_fields = creator.addfield(t, packexp, args); nil })
243
249
  end
244
- define_method(:struct, ->(*args, &block) { latest_fields = creator.struct(args, &block); nil })
245
- define_method(:union, ->(*args, &block) { latest_fields = creator.union(args, &block); nil })
250
+ define_method(:struct, ->(*args, &block) { latest_fields = creator.struct(args, packexp, &block); nil })
251
+ define_method(:union, ->(*args, &block) { latest_fields = creator.union(args, packexp, &block); nil })
246
252
  define_method(:const, ->(dummy_fields) { creator.const(latest_fields); latest_fields = nil; nil })
247
253
  define_method(:typedef, ->(*args, &block) { creator.typedef(args, &block) })
254
+ packexp0 = nil
255
+ define_method(:packed, ->(bytealign = 1, &block) {
256
+ raise "wrong nested ``packed''" if packexp0
257
+ exp = Math.log(bytealign, 2)
258
+ # exp が Nan Infinity -Infinity の場合は例外が発生するので、それに対する処置も行う
259
+ unless ((exp = exp.to_i) rescue nil) && (1 << exp) == bytealign
260
+ raise ArgumentError, "shall be given power of two (but #{bytealign})"
261
+ end
262
+
263
+ begin
264
+ packexp0 = packexp
265
+ packexp = exp
266
+ self.instance_exec(&block)
267
+ ensure
268
+ (packexp, packexp0) = packexp0, nil
269
+ end
270
+
271
+ nil
272
+ })
248
273
  if creator.respond_to?(:bytealign)
249
- define_method(:bytealign, ->(bytesize, &block) { creator.bytealign(bytesize, &block) })
274
+ define_method(:bytealign, ->(bytesize, &block) { creator.bytealign(bytesize, &block); nil })
250
275
  end
251
276
  if creator.respond_to?(:padding)
252
- define_method(:padding, ->(bytesize, &block) { creator.padding(bytesize, &block) })
277
+ define_method(:padding, ->(bytesize, &block) { creator.padding(bytesize, &block); nil })
253
278
  end
254
279
  end
255
280
  end
@@ -287,8 +312,8 @@ module Gogyou
287
312
  # }
288
313
  # }
289
314
  #
290
- def struct(args, &block)
291
- define_container(args, block, Model.method(:struct))
315
+ def struct(args, packexp, &block)
316
+ define_container(args, packexp, block, Model.method(:struct))
292
317
  end
293
318
 
294
319
  #
@@ -306,24 +331,24 @@ module Gogyou
306
331
  # この記述ができる唯一の理由は、人間が見てわかりやすくすることを意図しています
307
332
  # (ただし、ミスリードを誘う手口にも利用されてしまうのが最大の欠点です)。
308
333
  #
309
- def union(args, &block)
310
- define_container(args, block, Model.method(:union))
334
+ def union(args, packexp, &block)
335
+ define_container(args, packexp, block, Model.method(:union))
311
336
  end
312
337
 
313
- def define_container(args, anonymblock, container)
338
+ def define_container(args, packexp, anonymblock, container)
314
339
  if anonymblock
315
340
  raise ArgumentError, "given block and arguments" unless args.empty?
316
- model = container.(typemap.dup, &anonymblock)
341
+ model = container.(typemap.dup, packexp, &anonymblock)
317
342
  raise "BUG - object is not a Model (#{model.class})" unless model.kind_of?(Model)
318
343
  #p model: model, superclass: model.superclass
319
344
  self.offset = offset.align_ceil(model.bytealign) unless kind_of?(Model::Union::Creator)
320
- fields << f = Field[offset, nil, nil, model, 0]
345
+ fields << f = Field[offset, nil, nil, model, packexp]
321
346
  self.offset += model.bytesize unless kind_of?(Model::Union::Creator)
322
347
  [f]
323
348
  else
324
349
  type = args.shift
325
- type = container.(typemap.dup, &type) if type.kind_of?(::Proc)
326
- addfield!(type, args)
350
+ type = container.(typemap.dup, packexp, &type) if type.kind_of?(::Proc)
351
+ addfield!(type, packexp, args)
327
352
  end
328
353
  end
329
354
 
@@ -332,7 +357,7 @@ module Gogyou
332
357
  end
333
358
 
334
359
  def const(fields)
335
- fields.each { |f| f.mark_const }
360
+ fields.each { |f| f.set_const }
336
361
  end
337
362
 
338
363
  #
@@ -371,16 +396,16 @@ module Gogyou
371
396
  nil
372
397
  end
373
398
 
374
- def addfield(type, args)
399
+ def addfield(type, packexp, args)
375
400
  typeobj = typemap[type.intern]
376
401
  unless typeobj
377
402
  raise NoMethodError, "typename or method is missing (#{type})"
378
403
  end
379
404
 
380
- addfield!(typeobj, args)
405
+ addfield!(typeobj, packexp, args)
381
406
  end
382
407
 
383
- def addfield!(typeobj, args)
408
+ def addfield!(typeobj, packexp, args)
384
409
  #p typeobj
385
410
  # check extensible field >>> creator.fields[-1].vector[-1]
386
411
  if (x = fields[-1]) && (x = x.vector) && x[-1] == 0
@@ -388,13 +413,13 @@ module Gogyou
388
413
  end
389
414
 
390
415
  typesize = typeobj.bytesize
391
- typealign = typeobj.bytealign
416
+ typealign = [typeobj.bytealign, 1 << packexp].min
392
417
 
393
418
  tmpfields = []
394
419
 
395
420
  parse!(args) do |name, vect|
396
421
  self.offset = offset.align_ceil(typealign) unless kind_of?(Model::Union::Creator)
397
- fields << f = Field[offset, name, vect, typeobj, 0]
422
+ fields << f = Field[offset, name, vect, typeobj, 0 | packexp]
398
423
  tmpfields << f
399
424
  unless kind_of?(Model::Union::Creator)
400
425
  elements = vect ? vect.inject(1, &:*) : 1
@@ -35,8 +35,8 @@ describe Gogyou::Model do
35
35
 
36
36
  reference = Gogyou::Model::Union[
37
37
  4, 4,
38
- Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::INT32_T, 0x00],
39
- Gogyou::Model::Field[0, :b, nil, Gogyou::Primitives::UINT32_T, 0x00]
38
+ Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::INT32_T],
39
+ Gogyou::Model::Field[0, :b, nil, Gogyou::Primitives::UINT32_T]
40
40
  ]
41
41
 
42
42
  expect(x::MODEL).to eq reference
@@ -57,11 +57,11 @@ describe Gogyou::Model do
57
57
 
58
58
  ref = Gogyou::Model::Struct[
59
59
  32, 8,
60
- Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::CHAR, 0],
61
- Gogyou::Model::Field[8, :b, nil, Gogyou::Primitives::INT, 0],
62
- Gogyou::Model::Field[8, :c, nil, Gogyou::Primitives::INT64_T, 0],
63
- Gogyou::Model::Field[16, :d, nil, Gogyou::Primitives::INT32_T, 0],
64
- Gogyou::Model::Field[24, :e, nil, Gogyou::Primitives::CHAR, 0]
60
+ Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::CHAR],
61
+ Gogyou::Model::Field[8, :b, nil, Gogyou::Primitives::INT],
62
+ Gogyou::Model::Field[8, :c, nil, Gogyou::Primitives::INT64_T],
63
+ Gogyou::Model::Field[16, :d, nil, Gogyou::Primitives::INT32_T],
64
+ Gogyou::Model::Field[24, :e, nil, Gogyou::Primitives::CHAR]
65
65
  ]
66
66
 
67
67
  expect(x::MODEL).to eq ref
@@ -81,12 +81,12 @@ describe Gogyou::Model do
81
81
 
82
82
  ref = Gogyou::Model::Struct[
83
83
  72, 8,
84
- Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::CHAR, 0x00],
85
- Gogyou::Model::Field[8, :b, nil, Gogyou::Primitives::INT, 0x00],
84
+ Gogyou::Model::Field[0, :a, nil, Gogyou::Primitives::CHAR],
85
+ Gogyou::Model::Field[8, :b, nil, Gogyou::Primitives::INT],
86
86
  Gogyou::Model::Field[8, :e, [4], Gogyou::Model::Struct[
87
87
  16, 8,
88
- Gogyou::Model::Field[0, :c, nil, Gogyou::Primitives::INT64_T, 0x00],
89
- Gogyou::Model::Field[8, :d, nil, Gogyou::Primitives::INT32_T, 0x00]], 0x00]]
88
+ Gogyou::Model::Field[0, :c, nil, Gogyou::Primitives::INT64_T],
89
+ Gogyou::Model::Field[8, :d, nil, Gogyou::Primitives::INT32_T]]]]
90
90
  expect(x::MODEL).to eq ref
91
91
  end
92
92
 
@@ -108,8 +108,8 @@ describe Gogyou::Model do
108
108
 
109
109
  ref = Gogyou::Model::Union[
110
110
  24, 8,
111
- Gogyou::Model::Field[0, :a, nil, x, 0x00],
112
- Gogyou::Model::Field[0, :b, nil, x, 0x00]]
111
+ Gogyou::Model::Field[0, :a, nil, x],
112
+ Gogyou::Model::Field[0, :b, nil, x]]
113
113
  expect(y::MODEL).to eq ref
114
114
  end
115
115
  end
@@ -163,4 +163,144 @@ describe Gogyou::Accessor do
163
163
  obj = type.new
164
164
  expect(obj.bytesize).to eq 20
165
165
  end
166
+
167
+ it "packed struct" do
168
+ type1 = Gogyou.struct {
169
+ packed(1) {
170
+ char :a
171
+ int32_t :b
172
+ }
173
+ }
174
+
175
+ expect(type1.bytesize).to eq 5
176
+ expect(type1.bytealign).to eq 1
177
+ expect(type1.extensible?).to eq false
178
+ expect(type1.new.bytesize).to eq 5
179
+
180
+ type2 = Gogyou.struct {
181
+ packed(2) {
182
+ char :a
183
+ int32_t :b
184
+ }
185
+ }
186
+
187
+ expect(type2.bytesize).to eq 6
188
+ expect(type2.bytealign).to eq 2
189
+ expect(type2.extensible?).to eq false
190
+ expect(type2.new.bytesize).to eq 6
191
+ end
192
+
193
+ it "packed and nested struct" do
194
+ type1 = Gogyou.struct {
195
+ struct {
196
+ packed(1) {
197
+ char :a
198
+ int32_t :b
199
+ }
200
+ }
201
+ }
202
+
203
+ expect(type1.bytesize).to eq 5
204
+ expect(type1.bytealign).to eq 1
205
+ expect(type1.extensible?).to eq false
206
+ expect(type1.new.bytesize).to eq 5
207
+
208
+ type2 = Gogyou.struct {
209
+ packed(1) {
210
+ struct {
211
+ char :a
212
+ int32_t :b
213
+ }
214
+ }
215
+ }
216
+
217
+ expect(type2.bytesize).to eq 5
218
+ expect(type2.bytealign).to eq 1
219
+ expect(type2.extensible?).to eq false
220
+ expect(type2.new.bytesize).to eq 5
221
+
222
+ type3 = Gogyou.struct {
223
+ packed(1) {
224
+ struct -> {
225
+ char :a
226
+ int32_t :b
227
+ }, :x
228
+ }
229
+ }
230
+
231
+ expect(type3.bytesize).to eq 5
232
+ expect(type3.bytealign).to eq 1
233
+ expect(type3.extensible?).to eq false
234
+ expect(type3.new.bytesize).to eq 5
235
+ end
236
+
237
+ it "packed and nested struct" do
238
+ type1 = Gogyou.struct {
239
+ packed(2) {
240
+ struct {
241
+ packed(1) {
242
+ char :a
243
+ int32_t :b
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ expect(type1.bytesize).to eq 6
250
+ expect(type1.bytealign).to eq 2
251
+ expect(type1.extensible?).to eq false
252
+ expect(type1.new.bytesize).to eq 6
253
+
254
+ expect {
255
+ Gogyou.struct {
256
+ packed(1) {
257
+ packed(2) {
258
+ struct {
259
+ char :a
260
+ int32_t :b
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }.to raise_error RuntimeError
266
+ end
267
+ end
268
+
269
+ describe "user typeinfo" do
270
+ it "definition and use" do
271
+ x1 = Object.new
272
+ Gogyou.define_typeinfo(x1, 8.0, Rational(5, 2), false,
273
+ ->(buffer, offset) { buffer.byteslice(offset, 8) },
274
+ ->(buffer, offset, value) { buffer.setbinary(offset, value, 0, 16) })
275
+ expect(x1.bytesize).to eq 8
276
+ expect(x1.bytealign).to eq 2
277
+ expect(x1.extensible?).to eq false
278
+
279
+ x2 = Object.new
280
+ Gogyou.define_typeinfo(x2, "16", "4", "false",
281
+ "buffer.byteslice(offset, 16)",
282
+ "buffer.setbinary(offset, value.downcase, 0, 16)")
283
+ expect(x2.bytesize).to eq 16
284
+ expect(x2.bytealign).to eq 4
285
+ expect(x2.extensible?).to eq false
286
+
287
+ type = Gogyou.struct {
288
+ struct x1, :a
289
+ struct x2, :b
290
+ }
291
+
292
+ expect(type.bytesize).to eq 24
293
+ expect(type.bytealign).to eq 4
294
+ expect(type.extensible?).to eq false
295
+
296
+ v = type.bind("abcdefghijklmnopqrstuvwx")
297
+ expect(v.bytesize).to eq 24
298
+ expect(v.size).to eq 2
299
+ expect(v.a).to eq "abcdefgh"
300
+ v.a = "ABCDEFGH"
301
+ expect(v.buffer).to eq "ABCDEFGHijklmnopqrstuvwx"
302
+ expect(v.b).to eq "ijklmnopqrstuvwx"
303
+ v.b = "0ijklmnopqrstuv9wx"
304
+ expect(v.buffer).to eq "ABCDEFGH0ijklmnopqrstuv9"
305
+ end
166
306
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gogyou
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - dearblue
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-11 00:00:00.000000000 Z
11
+ date: 2014-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -57,8 +57,8 @@ extra_rdoc_files:
57
57
  - lib/gogyou/accessor.rb
58
58
  - lib/gogyou/mixin.rb
59
59
  - lib/gogyou/model.rb
60
- - lib/gogyou/primitives.rb
61
60
  - lib/gogyou/typespec.rb
61
+ - lib/gogyou/primitives.rb
62
62
  files:
63
63
  - LICENSE.markdown
64
64
  - README.markdown