libbin 1.0.7 → 1.0.8

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.
@@ -0,0 +1,12 @@
1
+ #ifndef LIBBIN_C_H__
2
+ #define LIBBIN_C_H__
3
+ #include "./half.h"
4
+ #include "./pghalf.h"
5
+ #include "./libbin_endian.h"
6
+ #include "./data_types.h"
7
+
8
+
9
+ extern VALUE mLibBin;
10
+ extern VALUE cField;
11
+
12
+ #endif
@@ -0,0 +1,126 @@
1
+ #ifndef LIBBIN_ENDIAN_H__
2
+ #define LIBBIN_ENDIAN_H__
3
+
4
+ #include <stdint.h>
5
+
6
+ static inline void little_big_swap(void *addr, size_t sz) {
7
+ char *p = (char *)addr;
8
+ for (size_t i = 0, j = sz - 1; i < (sz >> 1); i++, j--) {
9
+ char tmp = p[i];
10
+ p[i] = p[j];
11
+ p[j] = tmp;
12
+ }
13
+ }
14
+ #define LITTLE_BIG_SWAP(val) little_big_swap(&(val), sizeof(val))
15
+
16
+ static inline unsigned is_little_endian(void)
17
+ {
18
+ const union { unsigned u; unsigned char c[4]; } one = { 1 };
19
+ return one.c[0];
20
+ }
21
+
22
+ /* https://stackoverflow.com/a/2182184 */
23
+ static inline uint8_t bswap_uint8(uint8_t x) {
24
+ return x;
25
+ }
26
+
27
+ static inline uint16_t bswap_uint16(uint16_t x) {
28
+ return ((( x & 0xff00u ) >> 8 ) |
29
+ (( x & 0x00ffu ) << 8 ));
30
+ }
31
+
32
+ static inline uint32_t bswap_uint32(uint32_t x) {
33
+ return ((( x & 0xff000000u ) >> 24 ) |
34
+ (( x & 0x00ff0000u ) >> 8 ) |
35
+ (( x & 0x0000ff00u ) << 8 ) |
36
+ (( x & 0x000000ffu ) << 24 ));
37
+ }
38
+
39
+ static inline uint64_t bswap_uint64(uint64_t x) {
40
+ return ((( x & 0xff00000000000000ull ) >> 56 ) |
41
+ (( x & 0x00ff000000000000ull ) >> 40 ) |
42
+ (( x & 0x0000ff0000000000ull ) >> 24 ) |
43
+ (( x & 0x000000ff00000000ull ) >> 8 ) |
44
+ (( x & 0x00000000ff000000ull ) << 8 ) |
45
+ (( x & 0x0000000000ff0000ull ) << 24 ) |
46
+ (( x & 0x000000000000ff00ull ) << 40 ) |
47
+ (( x & 0x00000000000000ffull ) << 56 ));
48
+ }
49
+
50
+
51
+
52
+ #define SWAP_CONVERT(TYPE, MAPPED_NAME, MAPPED_TYPE) \
53
+ do { \
54
+ union { TYPE t; MAPPED_TYPE m; } v = { .m = x }; \
55
+ v.m = bswap_ ## MAPPED_NAME(v.m); \
56
+ return v.t; \
57
+ } while (0)
58
+
59
+ #define CONVERT(TYPE, MAPPED_TYPE) \
60
+ do { \
61
+ union { TYPE t; MAPPED_TYPE m; } v = { .m = x }; \
62
+ return v.t; \
63
+ } while (0)
64
+
65
+ #define CONVERT_SWAP(TYPE, MAPPED_NAME, MAPPED_TYPE) \
66
+ do { \
67
+ union { TYPE t; MAPPED_TYPE m; } v = { .t = x }; \
68
+ v.m = bswap_ ## MAPPED_NAME(v.m); \
69
+ return v.m; \
70
+ } while(0)
71
+
72
+ #define UNPACKER_BE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
73
+ static inline TYPE unpack_ ## NAME ## _be(MAPPED_TYPE x) { \
74
+ if (is_little_endian()) \
75
+ SWAP_CONVERT(TYPE, MAPPED_NAME, MAPPED_TYPE); \
76
+ else \
77
+ CONVERT(TYPE, MAPPED_TYPE); \
78
+ }
79
+
80
+ #define UNPACKER_LE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
81
+ static inline TYPE unpack_ ## NAME ## _le(MAPPED_TYPE x) { \
82
+ if (is_little_endian()) \
83
+ CONVERT(TYPE, MAPPED_TYPE); \
84
+ else \
85
+ SWAP_CONVERT(TYPE, MAPPED_NAME, MAPPED_TYPE); \
86
+ }
87
+
88
+ #define PACKER_BE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
89
+ static inline MAPPED_TYPE pack_ ## NAME ## _be(TYPE x) { \
90
+ if (is_little_endian()) \
91
+ CONVERT_SWAP(TYPE, MAPPED_NAME, MAPPED_TYPE); \
92
+ else \
93
+ CONVERT(MAPPED_TYPE, TYPE); \
94
+ }
95
+
96
+ #define PACKER_LE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
97
+ static inline MAPPED_TYPE pack_ ## NAME ## _le(TYPE x) { \
98
+ if (is_little_endian()) \
99
+ CONVERT(MAPPED_TYPE, TYPE); \
100
+ else \
101
+ CONVERT_SWAP(TYPE, MAPPED_NAME, MAPPED_TYPE); \
102
+ }
103
+
104
+ #define CONVERTER_TYPE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
105
+ UNPACKER_BE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
106
+ UNPACKER_LE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
107
+ PACKER_BE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE) \
108
+ PACKER_LE(NAME, TYPE, MAPPED_NAME, MAPPED_TYPE)
109
+
110
+ #define CONVERTER(NAME, TYPE, SIZE) \
111
+ CONVERTER_TYPE(NAME, TYPE, uint ## SIZE, uint ## SIZE ## _t)
112
+
113
+ CONVERTER(uint8, uint8_t, 8)
114
+ CONVERTER(int8, int8_t, 8)
115
+ CONVERTER(uint16, uint16_t, 16)
116
+ CONVERTER(int16, int16_t, 16)
117
+ CONVERTER(uint32, uint32_t, 32)
118
+ CONVERTER(int32, int32_t, 32)
119
+ CONVERTER(uint64, uint64_t, 64)
120
+ CONVERTER(int64, int64_t, 64)
121
+ CONVERTER(float, float, 32)
122
+ CONVERTER(double, double, 64)
123
+ CONVERTER(half, uint16_t, 16)
124
+ CONVERTER(pghalf, uint16_t, 16)
125
+
126
+ #endif
@@ -27,7 +27,11 @@ module LibBin
27
27
  @members = nil
28
28
  else
29
29
  @members = args[0]
30
- @range = @members.values.flatten.compact.collect(&:range).reduce(:+)
30
+ if @members.kind_of?(Hash)
31
+ @range = @members.values.compact.collect(&:range).reduce(:+)
32
+ else
33
+ @range = @members.compact.collect(&:range).reduce(:+)
34
+ end
31
35
  end
32
36
  end
33
37
 
@@ -53,7 +57,11 @@ module LibBin
53
57
  if args.length == 2
54
58
  @range = Range::new(args[0], args[1])
55
59
  else
56
- @range = args[0].values.flatten.compact.collect(&:range).reduce(:+)
60
+ if args[0].kind_of?(Hash)
61
+ @range = args[0].values.compact.collect(&:range).reduce(:+)
62
+ else
63
+ @range = args[0].compact.collect(&:range).reduce(:+)
64
+ end
57
65
  end
58
66
  end
59
67
 
@@ -71,58 +79,38 @@ module LibBin
71
79
 
72
80
  end
73
81
 
74
- class Field
75
- attr_reader :name,
76
- :type,
77
- :length,
78
- :count,
79
- :offset,
80
- :sequence,
81
- :condition
82
-
83
- def sequence?
84
- @sequence
85
- end
86
-
87
- def relative_offset?
88
- @relative_offset
89
- end
90
-
91
- def initialize(name, type, length, count, offset, sequence, condition, relative_offset)
92
- @name = name
93
- @type = type
94
- @length = length
95
- @count = count
96
- @offset = offset
97
- @sequence = sequence
98
- @condition = condition
99
- @relative_offset = relative_offset
100
- end
101
-
102
- end
82
+ # class Field
83
+ # attr_reader :name,
84
+ # :type,
85
+ # :length,
86
+ # :count,
87
+ # :offset,
88
+ # :sequence,
89
+ # :condition
90
+ #
91
+ # def sequence?
92
+ # @sequence
93
+ # end
94
+ #
95
+ # def relative_offset?
96
+ # @relative_offset
97
+ # end
98
+ #
99
+ # def initialize(name, type, length, count, offset, sequence, condition, relative_offset)
100
+ # @name = name
101
+ # @type = type
102
+ # @length = length
103
+ # @count = count
104
+ # @offset = offset
105
+ # @sequence = sequence
106
+ # @condition = condition
107
+ # @relative_offset = relative_offset
108
+ # end
109
+ #
110
+ # end
103
111
 
104
112
  class DataConverter
105
113
 
106
- rl = lambda { |type, str, number = nil|
107
- if number
108
- str.unpack(type.to_s+number.to_s)
109
- else
110
- str.unpack(type.to_s).first
111
- end
112
- }
113
-
114
- sl = lambda { |type, value, number = nil|
115
- if number
116
- value.pack(type.to_s+number.to_s)
117
- else
118
- [value].pack(type.to_s)
119
- end
120
- }
121
-
122
- l = lambda { |type|
123
- [rl.curry[type], sl.curry[type]]
124
- }
125
-
126
114
  SCALAR_TYPES = {
127
115
  :c => [:Int8, :int8],
128
116
  :C => [:UInt8, :uint8],
@@ -160,271 +148,12 @@ module LibBin
160
148
  :pghalf => [:PGHalf, :pghalf],
161
149
  :pghalf_le => [:PGHalf_LE, :pghalf_le],
162
150
  :pghalf_be => [:PGHalf_BE, :pghalf_be]
163
- }
164
-
165
- DATA_SIZES = Hash::new { |h,k|
166
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
167
- m[1].to_i
168
- else
169
- nil
170
- end
171
- }
172
- DATA_SIZES.merge!( {
173
- :c => 1,
174
- :C => 1,
175
- :s => 2,
176
- :"s<" => 2,
177
- :"s>" => 2,
178
- :S => 2,
179
- :"S<" => 2,
180
- :"S>" => 2,
181
- :v => 2,
182
- :n => 2,
183
- :l => 4,
184
- :"l<" => 4,
185
- :"l>" => 4,
186
- :L => 4,
187
- :"L<" => 4,
188
- :"L>" => 4,
189
- :V => 4,
190
- :N => 4,
191
- :q => 8,
192
- :"q<" => 8,
193
- :"q>" => 8,
194
- :Q => 8,
195
- :"Q<" => 8,
196
- :"Q>" => 8,
197
- :F => 4,
198
- :e => 4,
199
- :g => 4,
200
- :D => 8,
201
- :E => 8,
202
- :G => 8,
203
- :a => 1,
204
- :"a*" => -1,
205
- :half => 2,
206
- :half_le => 2,
207
- :half_be => 2,
208
- :pghalf => 2,
209
- :pghalf_le => 2,
210
- :pghalf_be => 2
211
- } )
212
- DATA_ENDIAN = {
213
- true => Hash::new { |h,k|
214
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
215
- l[k]
216
- else
217
- nil
218
- end
219
- },
220
- false => Hash::new { |h,k|
221
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
222
- l[k]
223
- else
224
- nil
225
- end
226
- }
227
- }
228
-
229
- rhl = lambda { |type, str, number = nil|
230
- if number
231
- number.times.collect { |i| LibBin::half_from_string(str[i*2,2], type) }
232
- else
233
- LibBin::half_from_string(str, type)
234
- end
235
- }
236
-
237
- shl = lambda { |type, value, number = nil|
238
- if number
239
- str = ""
240
- number.times { |i| str << LibBin::half_to_string(value[i], type) }
241
- str
242
- else
243
- LibBin::half_to_string(value, type)
244
- end
245
- }
246
-
247
- hl = lambda { |type|
248
- [rhl.curry[type], shl.curry[type]]
249
- }
250
-
251
- rpghl = lambda { |type, str, number = nil|
252
- if number
253
- number.times.collect { |i| LibBin::pghalf_from_string(str[i*2,2], type) }
254
- else
255
- LibBin::pghalf_from_string(str, type)
256
- end
257
151
  }
258
152
 
259
- spghl = lambda { |type, value, number = nil|
260
- if number
261
- str = ""
262
- number.times { |i| str << LibBin::pghalf_to_string(value[i], type) }
263
- str
264
- else
265
- LibBin::pghalf_to_string(value, type)
266
- end
267
- }
268
-
269
- pghl = lambda { |type|
270
- [rpghl.curry[type], spghl.curry[type]]
271
- }
272
-
273
- DATA_ENDIAN[true].merge!( {
274
- :c => l["c"],
275
- :C => l["C"],
276
- :s => l["s>"],
277
- :"s<" => l["s<"],
278
- :"s>" => l["s>"],
279
- :S => l["S>"],
280
- :"S<" => l["S<"],
281
- :"S>" => l["S>"],
282
- :v => l["v"],
283
- :n => l["n"],
284
- :l => l["l>"],
285
- :"l<" => l["l<"],
286
- :"l>" => l["l>"],
287
- :L => l["L>"],
288
- :"L<" => l["L<"],
289
- :"L>" => l["L>"],
290
- :V => l["V"],
291
- :N => l["N"],
292
- :q => l["q>"],
293
- :"q<" => l["q<"],
294
- :"q>" => l["q>"],
295
- :Q => l["Q>"],
296
- :"Q<" => l["Q<"],
297
- :"Q>" => l["Q>"],
298
- :F => l["g"],
299
- :e => l["e"],
300
- :g => l["g"],
301
- :D => l["G"],
302
- :E => l["E"],
303
- :G => l["G"],
304
- :half => hl["S>"],
305
- :half_le => hl["S<"],
306
- :half_be => hl["S>"],
307
- :pghalf => pghl["S>"],
308
- :pghalf_le => pghl["S<"],
309
- :pghalf_be => pghl["S>"]
310
- } )
311
- DATA_ENDIAN[false].merge!( {
312
- :c => l["c"],
313
- :C => l["C"],
314
- :s => l["s<"],
315
- :"s<" => l["s<"],
316
- :"s>" => l["s>"],
317
- :S => l["S<"],
318
- :"S<" => l["S<"],
319
- :"S>" => l["S>"],
320
- :v => l["v"],
321
- :n => l["n"],
322
- :l => l["l<"],
323
- :"l<" => l["l<"],
324
- :"l>" => l["l>"],
325
- :L => l["L<"],
326
- :"L<" => l["L<"],
327
- :"L>" => l["L>"],
328
- :V => l["V"],
329
- :N => l["N"],
330
- :q => l["q<"],
331
- :"q<" => l["q<"],
332
- :"q>" => l["q>"],
333
- :Q => l["Q<"],
334
- :"Q<" => l["Q<"],
335
- :"Q>" => l["Q>"],
336
- :F => l["e"],
337
- :e => l["e"],
338
- :g => l["g"],
339
- :D => l["E"],
340
- :E => l["E"],
341
- :G => l["G"],
342
- :half => hl["S<"],
343
- :half_le => hl["S<"],
344
- :half_be => hl["S>"],
345
- :pghalf => pghl["S<"],
346
- :pghalf_le => pghl["S<"],
347
- :pghalf_be => pghl["S>"]
348
- } )
349
-
350
-
351
- class Scalar
352
-
353
- def self.size(*args)
354
- @size
355
- end
356
-
357
- def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape, length = nil)
358
- length = 1 unless length
359
- kind::new(previous_offset, previous_offset - 1 + length * @size)
360
- end
361
-
362
- def self.init(symbol)
363
- @symbol = symbol
364
- @size = DATA_SIZES[symbol]
365
- @rl_be, @sl_be = DATA_ENDIAN[true][symbol]
366
- @rl_le, @sl_le = DATA_ENDIAN[false][symbol]
367
- end
368
-
369
- def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil, length = nil)
370
- l = (length ? length : 1)
371
- str = input.read(@size*l)
372
- input_big ? @rl_be[str, length] : @rl_le[str, length]
373
- end
374
-
375
- def self.dump(value, output, output_big = LibBin::default_big?, _ = nil, _ = nil, length = nil)
376
- str = (output_big ? @sl_be[value, length] : @sl_le[value, length])
377
- output.write(str)
378
- end
379
-
380
- def self.convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, _ = nil, _ = nil, length = nil)
381
- l = (length ? length : 1)
382
- str = input.read(@size*l)
383
- value = (input_big ? @rl_be[str, length] : @rl_le[str, length])
384
- str = (output_big ? @sl_be[value, length] : @sl_le[value, length])
385
- output.write(str)
386
- value
387
- end
388
-
389
- end
390
-
391
- class Str < Scalar
392
-
393
- def self.size(value, previous_offset = 0, parent = nil, index = nil, length = nil)
394
- length ? length : value.size
395
- end
396
-
397
- def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil, length = nil)
398
- str = (length ? input.read(length) : input.readline("\x00"))
399
- end
400
-
401
- def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big, _ = nil, _ = nil, length = nil)
402
- str = (length ? input.read(length) : input.readline("\x00"))
403
- output.write(str)
404
- str
405
- end
406
-
407
- def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape, length = nil)
408
- if length
409
- kind::new(previous_offset, previous_offset + length - 1)
410
- else
411
- kind::new(previous_offset, previous_offset + value.size - 1)
412
- end
413
- end
414
-
415
- def self.dump(value, output, output_big = LibBin::default_big?, _ = nil, _ = nil, length = nil)
416
- if length
417
- output.write([value].pack("Z#{length}"))
418
- else
419
- output.write(value)
420
- end
421
- end
422
- end
423
-
424
153
  def self.register_field(field, type, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
425
154
  if type.kind_of?(Symbol)
426
155
  if type[0] == 'a'
427
- real_type = Class::new(Str) do init(sym) end
156
+ real_type = Str
428
157
  else
429
158
  real_type = const_get(SCALAR_TYPES[type][0])
430
159
  end
@@ -435,13 +164,9 @@ module LibBin
435
164
  attr_accessor field
436
165
  end
437
166
 
438
- def self.create_scalar_type(symbol)
167
+ def self.create_scalar_accessor(symbol)
439
168
  klassname, name = SCALAR_TYPES[symbol]
440
169
  eval <<EOF
441
- class #{klassname} < Scalar
442
- init(#{symbol.inspect})
443
- end
444
-
445
170
  def self.#{name}(field, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
446
171
  @fields.push(Field::new(field, #{klassname}, length, count, offset, sequence, condition, relative_offset))
447
172
  attr_accessor field
@@ -449,45 +174,23 @@ module LibBin
449
174
  EOF
450
175
  end
451
176
 
452
- create_scalar_type(:c)
453
- create_scalar_type(:C)
454
- create_scalar_type(:s)
455
- create_scalar_type(:"s<")
456
- create_scalar_type(:"s>")
457
- create_scalar_type(:S)
458
- create_scalar_type(:"S<")
459
- create_scalar_type(:"S>")
460
- create_scalar_type(:l)
461
- create_scalar_type(:"l<")
462
- create_scalar_type(:"l>")
463
- create_scalar_type(:L)
464
- create_scalar_type(:"L<")
465
- create_scalar_type(:"L>")
466
- create_scalar_type(:q)
467
- create_scalar_type(:"q<")
468
- create_scalar_type(:"q>")
469
- create_scalar_type(:Q)
470
- create_scalar_type(:"Q<")
471
- create_scalar_type(:"Q>")
472
- create_scalar_type(:F)
473
- create_scalar_type(:e)
474
- create_scalar_type(:g)
475
- create_scalar_type(:D)
476
- create_scalar_type(:E)
477
- create_scalar_type(:G)
478
- create_scalar_type(:half)
479
- create_scalar_type(:half_le)
480
- create_scalar_type(:half_be)
481
- create_scalar_type(:pghalf)
482
- create_scalar_type(:pghalf_le)
483
- create_scalar_type(:pghalf_be)
177
+ [:c,
178
+ :C,
179
+ :s, :"s<", :"s>",
180
+ :S, :"S<", :"S>",
181
+ :l, :"l<", :"l>",
182
+ :L, :"L<", :"L>",
183
+ :q, :"q<", :"q>",
184
+ :Q, :"Q<", :"Q>",
185
+ :F, :e, :g,
186
+ :D, :E, :G,
187
+ :half, :half_le, :half_be,
188
+ :pghalf, :pghalf_le, :pghalf_be].each { |c|
189
+ create_scalar_accessor(c)
190
+ }
484
191
 
485
192
  def self.string( field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
486
- sym = (length ? :"a" : :"a*")
487
- c = Class::new(Str) do
488
- init(sym)
489
- end
490
- @fields.push(Field::new(field, c, length, count, offset, sequence, condition, relative_offset))
193
+ @fields.push(Field::new(field, Str, length, count, offset, sequence, condition, relative_offset))
491
194
  attr_accessor field
492
195
  end
493
196