libbin 1.0.4 → 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
@@ -3,9 +3,10 @@ module LibBin
3
3
  module RangeRefinement
4
4
  refine Range do
5
5
  def +(other)
6
- Range::new(first <= other.first ? first : other.first,
7
- last >= other.last ? last : other.last,
8
- exclude_end?)
6
+ return other.dup unless min
7
+ return self.dup unless other.min
8
+ Range::new(min <= other.min ? min : other.min,
9
+ max >= other.max ? max : other.max)
9
10
  end
10
11
  end
11
12
  end
@@ -26,7 +27,11 @@ module LibBin
26
27
  @members = nil
27
28
  else
28
29
  @members = args[0]
29
- @range = @members.values.flatten.compact.collect(&:range).reduce { |memo, obj| memo + obj }
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
30
35
  end
31
36
  end
32
37
 
@@ -52,7 +57,11 @@ module LibBin
52
57
  if args.length == 2
53
58
  @range = Range::new(args[0], args[1])
54
59
  else
55
- @range = args[0].values.flatten.compact.collect(&:range).reduce { |memo, obj| memo + obj }
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
56
65
  end
57
66
  end
58
67
 
@@ -70,48 +79,38 @@ module LibBin
70
79
 
71
80
  end
72
81
 
73
- class Field
74
- attr_reader :name,
75
- :type,
76
- :count,
77
- :offset,
78
- :sequence,
79
- :condition
80
-
81
- def sequence?
82
- @sequence
83
- end
84
-
85
- def relative_offset?
86
- @relative_offset
87
- end
88
-
89
- def initialize(name, type, count, offset, sequence, condition, relative_offset)
90
- @name = name
91
- @type = type
92
- @count = count
93
- @offset = offset
94
- @sequence = sequence
95
- @condition = condition
96
- @relative_offset = relative_offset
97
- end
98
-
99
- 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
100
111
 
101
112
  class DataConverter
102
113
 
103
- rl = lambda { |type, str|
104
- str.unpack(type.to_s).first
105
- }
106
-
107
- sl = lambda { |type, value|
108
- [value].pack(type.to_s)
109
- }
110
-
111
- l = lambda { |type|
112
- [rl.curry[type], sl.curry[type]]
113
- }
114
-
115
114
  SCALAR_TYPES = {
116
115
  :c => [:Int8, :int8],
117
116
  :C => [:UInt8, :uint8],
@@ -149,296 +148,52 @@ module LibBin
149
148
  :pghalf => [:PGHalf, :pghalf],
150
149
  :pghalf_le => [:PGHalf_LE, :pghalf_le],
151
150
  :pghalf_be => [:PGHalf_BE, :pghalf_be]
152
- }
153
-
154
- DATA_SIZES = Hash::new { |h,k|
155
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
156
- m[1].to_i
157
- else
158
- nil
159
- end
160
151
  }
161
- DATA_SIZES.merge!( {
162
- :c => 1,
163
- :C => 1,
164
- :s => 2,
165
- :"s<" => 2,
166
- :"s>" => 2,
167
- :S => 2,
168
- :"S<" => 2,
169
- :"S>" => 2,
170
- :v => 2,
171
- :n => 2,
172
- :l => 4,
173
- :"l<" => 4,
174
- :"l>" => 4,
175
- :L => 4,
176
- :"L<" => 4,
177
- :"L>" => 4,
178
- :V => 4,
179
- :N => 4,
180
- :q => 8,
181
- :"q<" => 8,
182
- :"q>" => 8,
183
- :Q => 8,
184
- :"Q<" => 8,
185
- :"Q>" => 8,
186
- :F => 4,
187
- :e => 4,
188
- :g => 4,
189
- :D => 8,
190
- :E => 8,
191
- :G => 8,
192
- :"a*" => -1,
193
- :half => 2,
194
- :half_le => 2,
195
- :half_be => 2,
196
- :pghalf => 2,
197
- :pghalf_le => 2,
198
- :pghalf_be => 2
199
- } )
200
- DATA_ENDIAN = {
201
- true => Hash::new { |h,k|
202
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
203
- l[k]
204
- else
205
- nil
206
- end
207
- },
208
- false => Hash::new { |h,k|
209
- if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
210
- l[k]
211
- else
212
- nil
213
- end
214
- }
215
- }
216
-
217
- DATA_ENDIAN[true].merge!( {
218
- :c => l["c"],
219
- :C => l["C"],
220
- :s => l["s>"],
221
- :"s<" => l["s<"],
222
- :"s>" => l["s>"],
223
- :S => l["S>"],
224
- :"S<" => l["S<"],
225
- :"S>" => l["S>"],
226
- :v => l["v"],
227
- :n => l["n"],
228
- :l => l["l>"],
229
- :"l<" => l["l<"],
230
- :"l>" => l["l>"],
231
- :L => l["L>"],
232
- :"L<" => l["L<"],
233
- :"L>" => l["L>"],
234
- :V => l["V"],
235
- :N => l["N"],
236
- :q => l["q>"],
237
- :"q<" => l["q<"],
238
- :"q>" => l["q>"],
239
- :Q => l["Q>"],
240
- :"Q<" => l["Q<"],
241
- :"Q>" => l["Q>"],
242
- :F => l["g"],
243
- :e => l["e"],
244
- :g => l["g"],
245
- :D => l["G"],
246
- :E => l["E"],
247
- :G => l["G"],
248
- :"a*" => l["a*"],
249
- :half => [ lambda { |str| LibBin::half_from_string(str, "S>") },
250
- lambda { |v| LibBin::half_to_string(v, "S>") } ],
251
- :half_le => [ lambda { |str| LibBin::half_from_string(str, "S<") },
252
- lambda { |v| LibBin::half_to_string(v, "S<") } ],
253
- :half_be => [ lambda { |str| LibBin::half_from_string(str, "S>") },
254
- lambda { |v| LibBin::half_to_string(v, "S>") } ],
255
- :pghalf => [ lambda { |str| LibBin::pghalf_from_string(str, "S>") },
256
- lambda { |v| LibBin::pghalf_to_string(v, "S>") } ],
257
- :pghalf_le => [ lambda { |str| LibBin::pghalf_from_string(str, "S<") },
258
- lambda { |v| LibBin::pghalf_to_string(v, "S<") } ],
259
- :pghalf_be => [ lambda { |str| LibBin::pghalf_from_string(str, "S>") },
260
- lambda { |v| LibBin::pghalf_to_string(v, "S>") } ]
261
- } )
262
- DATA_ENDIAN[false].merge!( {
263
- :c => l["c"],
264
- :C => l["C"],
265
- :s => l["s<"],
266
- :"s<" => l["s<"],
267
- :"s>" => l["s>"],
268
- :S => l["S<"],
269
- :"S<" => l["S<"],
270
- :"S>" => l["S>"],
271
- :v => l["v"],
272
- :n => l["n"],
273
- :l => l["l<"],
274
- :"l<" => l["l<"],
275
- :"l>" => l["l>"],
276
- :L => l["L<"],
277
- :"L<" => l["L<"],
278
- :"L>" => l["L>"],
279
- :V => l["V"],
280
- :N => l["N"],
281
- :q => l["q<"],
282
- :"q<" => l["q<"],
283
- :"q>" => l["q>"],
284
- :Q => l["Q<"],
285
- :"Q<" => l["Q<"],
286
- :"Q>" => l["Q>"],
287
- :F => l["e"],
288
- :e => l["e"],
289
- :g => l["g"],
290
- :D => l["E"],
291
- :E => l["E"],
292
- :G => l["G"],
293
- :"a*" => l["a*"],
294
- :half => [ lambda { |str| LibBin::half_from_string(str, "S<") },
295
- lambda { |v| LibBin::half_to_string(v, "S<") } ],
296
- :half_le => [ lambda { |str| LibBin::half_from_string(str, "S<") },
297
- lambda { |v| LibBin::half_to_string(v, "S<") } ],
298
- :half_be => [ lambda { |str| LibBin::half_from_string(str, "S>") },
299
- lambda { |v| LibBin::half_to_string(v, "S>") } ],
300
- :pghalf => [ lambda { |str| LibBin::pghalf_from_string(str, "S<") },
301
- lambda { |v| LibBin::pghalf_to_string(v, "S<") } ],
302
- :pghalf_le => [ lambda { |str| LibBin::pghalf_from_string(str, "S<") },
303
- lambda { |v| LibBin::pghalf_to_string(v, "S<") } ],
304
- :pghalf_be => [ lambda { |str| LibBin::pghalf_from_string(str, "S>") },
305
- lambda { |v| LibBin::pghalf_to_string(v, "S>") } ]
306
- } )
307
152
 
308
-
309
- class Scalar
310
-
311
- def self.size(*args)
312
- @size
313
- end
314
-
315
- def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape)
316
- kind::new(previous_offset, previous_offset + @size - 1)
317
- end
318
-
319
- def self.init(symbol)
320
- @symbol = symbol
321
- @size = DATA_SIZES[symbol]
322
- @rl_be, @sl_be = DATA_ENDIAN[true][symbol]
323
- @rl_le, @sl_le = DATA_ENDIAN[false][symbol]
324
- end
325
-
326
- def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil)
327
- str = input.read(@size)
328
- input_big ? @rl_be[str] : @rl_le[str]
329
- end
330
-
331
- def self.dump(value, output, output_big = LibBin::default_big?, _ = nil, _ = nil)
332
- str = (output_big ? @sl_be[value] : @sl_le[value])
333
- output.write(str)
334
- end
335
-
336
- def self.convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, _ = nil, _ = nil)
337
- str = input.read(@size)
338
- value = (input_big ? @rl_be[str] : @rl_le[str])
339
- str = (output_big ? @sl_be[value] : @sl_le[value])
340
- output.write(str)
341
- value
342
- end
343
-
344
- end
345
-
346
- class Str < Scalar
347
-
348
- def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil)
349
- str = (@size < 0 ? input.readline("\x00") : input.read(@size))
350
- input_big ? @rl_be[str] : @rl_le[str]
351
- end
352
-
353
- def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big, _ = nil, _ = nil)
354
- str = (@size < 0 ? input.readline("\x00") : input.read(@size))
355
- value = (input_big ? @rl_be[str] : @rl_le[str])
356
- str = (output_big ? @sl_be[value] : @sl_le[value])
357
- output.write(str)
358
- value
359
- end
360
-
361
- def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape)
362
- if @size < 0
363
- kind::new(previous_offset, previous_offset + value.size - 1)
364
- else
365
- kind::new(previous_offset, previous_offset + @size - 1)
366
- end
367
- end
368
-
369
- end
370
-
371
- def self.register_field(field, type, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
153
+ def self.register_field(field, type, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
372
154
  if type.kind_of?(Symbol)
373
155
  if type[0] == 'a'
374
- real_type = Class::new(Str) do init(sym) end
156
+ real_type = Str
375
157
  else
376
158
  real_type = const_get(SCALAR_TYPES[type][0])
377
159
  end
378
160
  else
379
161
  real_type = type
380
162
  end
381
- @fields.push(Field::new(field, real_type, count, offset, sequence, condition, relative_offset))
163
+ @fields.push(Field::new(field, real_type, length, count, offset, sequence, condition, relative_offset))
382
164
  attr_accessor field
383
165
  end
384
166
 
385
- def self.create_scalar_type(symbol)
167
+ def self.create_scalar_accessor(symbol)
386
168
  klassname, name = SCALAR_TYPES[symbol]
387
169
  eval <<EOF
388
- class #{klassname} < Scalar
389
- init(#{symbol.inspect})
390
- end
391
-
392
- def self.#{name}(field, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
393
- @fields.push(Field::new(field, #{klassname}, count, offset, sequence, condition, relative_offset))
170
+ def self.#{name}(field, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
171
+ @fields.push(Field::new(field, #{klassname}, length, count, offset, sequence, condition, relative_offset))
394
172
  attr_accessor field
395
173
  end
396
174
  EOF
397
175
  end
398
176
 
399
- create_scalar_type(:c)
400
- create_scalar_type(:C)
401
- create_scalar_type(:s)
402
- create_scalar_type(:"s<")
403
- create_scalar_type(:"s>")
404
- create_scalar_type(:S)
405
- create_scalar_type(:"S<")
406
- create_scalar_type(:"S>")
407
- create_scalar_type(:l)
408
- create_scalar_type(:"l<")
409
- create_scalar_type(:"l>")
410
- create_scalar_type(:L)
411
- create_scalar_type(:"L<")
412
- create_scalar_type(:"L>")
413
- create_scalar_type(:q)
414
- create_scalar_type(:"q<")
415
- create_scalar_type(:"q>")
416
- create_scalar_type(:Q)
417
- create_scalar_type(:"Q<")
418
- create_scalar_type(:"Q>")
419
- create_scalar_type(:F)
420
- create_scalar_type(:e)
421
- create_scalar_type(:g)
422
- create_scalar_type(:D)
423
- create_scalar_type(:E)
424
- create_scalar_type(:G)
425
- create_scalar_type(:half)
426
- create_scalar_type(:half_le)
427
- create_scalar_type(:half_be)
428
- create_scalar_type(:pghalf)
429
- create_scalar_type(:pghalf_le)
430
- 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
+ }
431
191
 
432
192
  def self.string( field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
433
- sym = (length ? :"a#{length}" : :"a*")
434
- c = Class::new(Str) do
435
- init(sym)
436
- end
437
- @fields.push(Field::new(field, c, count, offset, sequence, condition, relative_offset))
193
+ @fields.push(Field::new(field, Str, length, count, offset, sequence, condition, relative_offset))
438
194
  attr_accessor field
439
195
  end
440
196
 
441
-
442
197
  end
443
198
 
444
199
  end