libbin 1.0.4 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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