libbin 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c632bd10fef318615e63edccbebd3b161ce7c9e3ccb5a2efec3b43bda3565cde
4
+ data.tar.gz: cd8853a5ca548a3221710d6388ecbd54f46cf9e3721410af7a1f581d115c738d
5
+ SHA512:
6
+ metadata.gz: bf807641924427087c89d3f3d89fc91c41a91cf2a6729bba0185592752d071fca322c3655b90912c288c7b3ce98a1a46db6d5471e5e4fd403f7a8570980547e9
7
+ data.tar.gz: acd847eb8f52ff55c7c1c92fe86fa6bf11cd20845189f6cd13957333b32feeda29bc620d9e8152d835aba2ba9ff45313357f7f75d54a7de126eb7c3d781ab9e9
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2018, Brice Videau
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/libbin.rb ADDED
@@ -0,0 +1,358 @@
1
+ warn_level = $VERBOSE
2
+ $VERBOSE = nil
3
+ require 'float-formats'
4
+ $VERBOSE = warn_level
5
+
6
+ Flt::IEEE.binary :IEEE_binary16_pg, significand: 9, exponent: 6, bias: 47
7
+ Flt::IEEE.binary :IEEE_binary16_pg_BE, significand: 9, exponent: 6, bias: 47, endianness: :big_endian
8
+
9
+ require_relative 'libbin/alignment'
10
+ require_relative 'libbin/data_types'
11
+
12
+ module LibBin
13
+
14
+ @__big_architecture = [0x12345678].pack("i") == "\x12\x34\x56\x78"
15
+ @__big = nil
16
+
17
+ def self.default_big?
18
+ if @__big.nil?
19
+ @__big_architecture
20
+ else
21
+ @__big
22
+ end
23
+ end
24
+
25
+ class DataConverter
26
+ include Alignment
27
+
28
+ def inspect
29
+ to_s
30
+ end
31
+
32
+ attr_reader :__parent
33
+ attr_reader :__index
34
+ attr_reader :__iterator
35
+ attr_reader :__position
36
+ def __set_convert_type(input, output, input_big, output_big, parent, index)
37
+ @__input_big = input_big
38
+ @__output_big = output_big
39
+ @__input = input
40
+ @__output = output
41
+ @__parent = parent
42
+ @__index = index
43
+ @__position = input.tell
44
+ @__cur_position = @__position
45
+ end
46
+
47
+ def __set_size_type(position, parent, index)
48
+ @__parent = parent
49
+ @__index = index
50
+ @__position = position
51
+ @__cur_position = @__position
52
+ end
53
+
54
+ def __set_load_type(input, input_big, parent, index)
55
+ @__input_big = input_big
56
+ @__input = input
57
+ @__parent = parent
58
+ @__index = index
59
+ @__position = input.tell
60
+ @__cur_position = @__position
61
+ end
62
+
63
+ def __set_dump_type(output, output_big, parent, index)
64
+ @__output_big = output_big
65
+ @__output = output
66
+ @__parent = parent
67
+ @__index = index
68
+ @__position = output.tell
69
+ @__cur_position = @__position
70
+ end
71
+
72
+ def __unset_convert_type
73
+ @__input_big = nil
74
+ @__output_big = nil
75
+ @__input = nil
76
+ @__output = nil
77
+ @__parent = nil
78
+ @__index = nil
79
+ @__position = nil
80
+ @__cur_position = nil
81
+ end
82
+
83
+ def __unset_size_type
84
+ @__parent = nil
85
+ @__index = nil
86
+ @__position = nil
87
+ @__cur_position = nil
88
+ end
89
+
90
+ def __unset_load_type
91
+ @__input_big = nil
92
+ @__input = nil
93
+ @__parent = nil
94
+ @__index = nil
95
+ @__position = nil
96
+ @__cur_position = nil
97
+ end
98
+
99
+ def __unset_dump_type
100
+ @__output_big = nil
101
+ @__output = nil
102
+ @__parent = nil
103
+ @__index = nil
104
+ @__position = nil
105
+ @__cur_position = nil
106
+ end
107
+
108
+ def self.inherited(subclass)
109
+ subclass.instance_variable_set(:@fields, [])
110
+ end
111
+
112
+ def __decode_expression(sym)
113
+ case sym
114
+ when Proc
115
+ return sym.call
116
+ when String
117
+ exp = sym.gsub("..","__parent").gsub("\\",".")
118
+ return eval(exp)
119
+ else
120
+ return sym
121
+ end
122
+ end
123
+
124
+ def __decode_seek_offset(offset)
125
+ return nil unless offset
126
+ offset = __decode_expression(offset)
127
+ return false if offset == 0x0
128
+ @__cur_position = offset
129
+ @__input.seek(offset) if @__input
130
+ @__output.seek(offset) if @__output
131
+ offset
132
+ end
133
+
134
+ def __decode_condition(condition)
135
+ return true unless condition
136
+ __decode_expression(condition)
137
+ end
138
+
139
+ def __decode_count(count)
140
+ return 1 unless count
141
+ __decode_expression(count)
142
+ end
143
+
144
+ def __decode_type(type)
145
+ return __decode_expression(type)
146
+ end
147
+
148
+ def __decode_static_conditions(type, count, offset, sequence, condition)
149
+ @__offset = nil
150
+ @__condition = nil
151
+ @__type = nil
152
+ @__count = nil
153
+ unless sequence
154
+ @__offset = __decode_seek_offset(offset)
155
+ throw :ignored, nil if @__offset == false
156
+ @__condition = __decode_condition(condition)
157
+ throw :ignored, nil unless @__condition
158
+ @__type = __decode_type(type)
159
+ end
160
+ @__count = __decode_count(count)
161
+ end
162
+
163
+ def __decode_dynamic_conditions(type, offset, sequence, condition)
164
+ return true unless sequence
165
+ @__offset = nil
166
+ @__condition = nil
167
+ @__type = nil
168
+ @__offset = __decode_seek_offset(offset)
169
+ return false if @__offset == false
170
+ @__condition = __decode_condition(condition)
171
+ return false unless @__condition
172
+ @__type = __decode_type(type)
173
+ return true
174
+ end
175
+
176
+ def __restore_context
177
+ @__iterator = nil
178
+ @__type = nil
179
+ @__count = nil
180
+ @__offset = nil
181
+ @__condition = nil
182
+ end
183
+
184
+ def __convert_field(field, type, count, offset, sequence, condition)
185
+ __decode_static_conditions(type, count, offset, sequence, condition)
186
+ vs = @__count.times.collect do |it|
187
+ @__iterator = it
188
+ if __decode_dynamic_conditions(type, offset, sequence, condition)
189
+ @__type::convert(@__input, @__output, @__input_big, @__output_big, self, it)
190
+ else
191
+ nil
192
+ end
193
+ end
194
+ __restore_context
195
+ vs = vs.first unless count
196
+ vs
197
+ end
198
+
199
+ def __load_field(field, type, count, offset, sequence, condition)
200
+ __decode_static_conditions(type, count, offset, sequence, condition)
201
+ vs = @__count.times.collect do |it|
202
+ @__iterator = it
203
+ if __decode_dynamic_conditions(type, offset, sequence, condition)
204
+ @__type::load(@__input, @__input_big, self, it)
205
+ else
206
+ nil
207
+ end
208
+ end
209
+ __restore_context
210
+ vs = vs.first unless count
211
+ vs
212
+ end
213
+
214
+ def __dump_field(vs, field, type, count, offset, sequence, condition)
215
+ __decode_static_conditions(type, count, offset, sequence, condition)
216
+ vs = [vs] unless count
217
+ vs.each_with_index do |v, it|
218
+ @__iterator = it
219
+ if __decode_dynamic_conditions(type, offset, sequence, condition)
220
+ @__type::dump(v, @__output, @__output_big, self, it)
221
+ end
222
+ end
223
+ __restore_context
224
+ end
225
+
226
+ def __shape_field(vs, previous_offset, kind, field, type, count, offset, sequence, condition)
227
+ __decode_static_conditions(type, count, offset, sequence, condition)
228
+ vs = [vs] unless count
229
+ vs = vs.each_with_index.collect do |v, it|
230
+ @__iterator = it
231
+ if __decode_dynamic_conditions(type, offset, sequence, condition)
232
+ sh = @__type::shape(v, @__cur_position, self, it, kind)
233
+ @__cur_position = sh.last + 1 if sh.last && sh.last >= 0
234
+ sh
235
+ end
236
+ end
237
+ __restore_context
238
+ vs = vs.first unless count
239
+ vs
240
+ end
241
+
242
+ def __size(previous_offset = 0, parent = nil, index = nil)
243
+ __shape(previous_offset, parent, index, DataRange).size
244
+ end
245
+
246
+ def __shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape)
247
+ __set_size_type(previous_offset, parent, index)
248
+ members = {}
249
+ self.class.instance_variable_get(:@fields).each { |name, type, *args|
250
+ begin
251
+ vs = send(name)
252
+ member = catch(:ignored) do
253
+ __shape_field(vs, previous_offset, kind, name, type, *args)
254
+ end
255
+ members[name] = member
256
+ rescue
257
+ STDERR.puts "#{self.class}: #{name}(#{type})"
258
+ raise
259
+ end
260
+ }
261
+ __unset_size_type
262
+ return nil if members.values.flatten.compact.size <= 0
263
+ kind::new(members)
264
+ end
265
+
266
+ def __convert_fields
267
+ self.class.instance_variable_get(:@fields).each { |name, type, *args|
268
+ begin
269
+ vs = catch(:ignored) do
270
+ __convert_field(name, type, *args)
271
+ end
272
+ send("#{name}=", vs)
273
+ rescue
274
+ STDERR.puts "#{self.class}: #{name}(#{type})"
275
+ raise
276
+ end
277
+ }
278
+ self
279
+ end
280
+
281
+ def __load_fields
282
+ self.class.instance_variable_get(:@fields).each { |name, type, *args|
283
+ begin
284
+ vs = catch(:ignored) do
285
+ __load_field(name, type, *args)
286
+ end
287
+ send("#{name}=", vs)
288
+ rescue
289
+ STDERR.puts "#{self.class}: #{name}(#{type})"
290
+ raise
291
+ end
292
+ }
293
+ self
294
+ end
295
+
296
+ def __dump_fields
297
+ self.class.instance_variable_get(:@fields).each { |name, type, *args|
298
+ begin
299
+ vs = send(name)
300
+ catch(:ignored) do
301
+ __dump_field(vs, name, type, *args)
302
+ end
303
+ rescue
304
+ STDERR.puts "#{self.class}: #{name}(#{type})"
305
+ raise
306
+ end
307
+ }
308
+ self
309
+ end
310
+
311
+ def __convert(input, output, input_big, output_big, parent = nil, index = nil)
312
+ __set_convert_type(input, output, input_big, output_big, parent, index)
313
+ __convert_fields
314
+ __unset_convert_type
315
+ self
316
+ end
317
+
318
+ def __load(input, input_big, parent = nil, index = nil)
319
+ __set_load_type(input, input_big, parent, index)
320
+ __load_fields
321
+ __unset_load_type
322
+ self
323
+ end
324
+
325
+ def __dump(output, output_big, parent = nil, index = nil)
326
+ __set_dump_type(output, output_big, parent, index)
327
+ __dump_fields
328
+ __unset_dump_type
329
+ self
330
+ end
331
+
332
+ def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big?, parent = nil, index = nil)
333
+ h = self::new
334
+ h.__convert(input, output, input_big, output_big, parent, index)
335
+ h
336
+ end
337
+
338
+ def self.load(input, input_big = LibBin::default_big?, parent = nil, index = nil)
339
+ h = self::new
340
+ h.__load(input, input_big, parent, index)
341
+ h
342
+ end
343
+
344
+ def self.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil)
345
+ value.__dump(output, output_big, parent, index)
346
+ end
347
+
348
+ def self.size(value, previous_offset = 0, parent = nil, index = nil)
349
+ value.__shape(previous_offset, parent, index).size
350
+ end
351
+
352
+ def self.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape)
353
+ value.__shape(previous_offset, parent, index, kind = DataShape)
354
+ end
355
+
356
+ end
357
+
358
+ end
@@ -0,0 +1,14 @@
1
+ module LibBin
2
+
3
+ module Alignment
4
+
5
+ def align(val, alignment)
6
+ remainder = val % alignment
7
+ val += alignment - remainder if remainder > 0
8
+ val
9
+ end
10
+ private :align
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,416 @@
1
+ module LibBin
2
+
3
+ module RangeRefinement
4
+ refine Range do
5
+ def +(other)
6
+ Range::new(first <= other.first ? first : other.first,
7
+ last >= other.last ? last : other.last,
8
+ exclude_end?)
9
+ end
10
+ end
11
+ end
12
+
13
+ class DataShape
14
+ using RangeRefinement
15
+ attr_reader :range
16
+ attr_reader :members
17
+
18
+ def method_missing(m, *arg, &block)
19
+ return @members[m] if @members && @members[m]
20
+ super
21
+ end
22
+
23
+ def initialize(*args)
24
+ if args.length == 2
25
+ @range = Range::new(args[0], args[1])
26
+ @members = nil
27
+ else
28
+ @members = args[0]
29
+ @range = @members.values.flatten.compact.collect(&:range).reduce { |memo, obj| memo + obj }
30
+ end
31
+ end
32
+
33
+ def first
34
+ @range.first
35
+ end
36
+
37
+ def last
38
+ @range.last
39
+ end
40
+
41
+ def size
42
+ @range.size
43
+ end
44
+
45
+ end
46
+
47
+ class DataRange
48
+ using RangeRefinement
49
+ attr_reader :range
50
+
51
+ def initialize(*args)
52
+ if args.length == 2
53
+ @range = Range::new(args[0], args[1])
54
+ else
55
+ @range = args[0].values.flatten.compact.collect(&:range).reduce { |memo, obj| memo + obj }
56
+ end
57
+ end
58
+
59
+ def first
60
+ @range.first
61
+ end
62
+
63
+ def last
64
+ @range.last
65
+ end
66
+
67
+ def size
68
+ @range.size
69
+ end
70
+
71
+ end
72
+
73
+ class DataConverter
74
+
75
+ rl = lambda { |type, str|
76
+ str.unpack(type.to_s).first
77
+ }
78
+
79
+ sl = lambda { |type, value|
80
+ [value].pack(type.to_s)
81
+ }
82
+
83
+ l = lambda { |type|
84
+ [rl.curry[type], sl.curry[type]]
85
+ }
86
+
87
+ SCALAR_TYPES = {
88
+ :c => [:Int8, :int8],
89
+ :C => [:UInt8, :uint8],
90
+ :s => [:Int16, :int16],
91
+ :"s<" => [:Int16_LE, :int16_le],
92
+ :"s>" => [:Int16_BE, :int16_be],
93
+ :S => [:UInt16, :uint16],
94
+ :"S<" => [:UInt16_LE, :uint16_le],
95
+ :"S>" => [:UInt16_BE, :uint16_be],
96
+ :v => [:UInt16_LE, :uint16_le],
97
+ :n => [:UInt16_BE, :uint16_be],
98
+ :l => [:Int32, :int32],
99
+ :"l<" => [:Int32_LE, :int32_le],
100
+ :"l>" => [:Int32_BE, :int32_be],
101
+ :L => [:UInt32, :uint32],
102
+ :"L<" => [:UInt32_LE, :uint32_le],
103
+ :"L>" => [:UInt32_BE, :uint32_be],
104
+ :V => [:UInt32_LE, :uint32_le],
105
+ :N => [:UInt32_BE, :uint32_be],
106
+ :q => [:Int64, :int64],
107
+ :"q<" => [:Int64_LE, :int64_le],
108
+ :"q>" => [:Int64_BE, :int64_be],
109
+ :Q => [:UInt64, :uint64],
110
+ :"Q<" => [:UInt64_LE, :uint64_le],
111
+ :"Q>" => [:UInt64_BE, :uint64_be],
112
+ :F => [:Flt, :float],
113
+ :e => [:Flt_LE, :float_le],
114
+ :g => [:Flt_BE, :float_be],
115
+ :D => [:Double, :double],
116
+ :E => [:Double_LE, :double_le],
117
+ :G => [:Double_BE, :double_be],
118
+ :half => [:Half, :half],
119
+ :half_le => [:Half_LE, :half_le],
120
+ :half_be => [:Half_BE, :half_be],
121
+ :pghalf => [:PGHalf, :pghalf],
122
+ :pghalf_le => [:PGHalf_LE, :pghalf_le],
123
+ :pghalf_be => [:PGHalf_BE, :pghalf_be]
124
+ }
125
+
126
+ DATA_SIZES = Hash::new { |h,k|
127
+ if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
128
+ m[1].to_i
129
+ else
130
+ nil
131
+ end
132
+ }
133
+ DATA_SIZES.merge!( {
134
+ :c => 1,
135
+ :C => 1,
136
+ :s => 2,
137
+ :"s<" => 2,
138
+ :"s>" => 2,
139
+ :S => 2,
140
+ :"S<" => 2,
141
+ :"S>" => 2,
142
+ :v => 2,
143
+ :n => 2,
144
+ :l => 4,
145
+ :"l<" => 4,
146
+ :"l>" => 4,
147
+ :L => 4,
148
+ :"L<" => 4,
149
+ :"L>" => 4,
150
+ :V => 4,
151
+ :N => 4,
152
+ :q => 8,
153
+ :"q<" => 8,
154
+ :"q>" => 8,
155
+ :Q => 8,
156
+ :"Q<" => 8,
157
+ :"Q>" => 8,
158
+ :F => 4,
159
+ :e => 4,
160
+ :g => 4,
161
+ :D => 8,
162
+ :E => 8,
163
+ :G => 8,
164
+ :"a*" => -1,
165
+ :half => 2,
166
+ :half_le => 2,
167
+ :half_be => 2,
168
+ :pghalf => 2,
169
+ :pghalf_le => 2,
170
+ :pghalf_be => 2
171
+ } )
172
+ DATA_ENDIAN = {
173
+ true => Hash::new { |h,k|
174
+ if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
175
+ l[k]
176
+ else
177
+ nil
178
+ end
179
+ },
180
+ false => Hash::new { |h,k|
181
+ if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
182
+ l[k]
183
+ else
184
+ nil
185
+ end
186
+ }
187
+ }
188
+
189
+ DATA_ENDIAN[true].merge!( {
190
+ :c => l["c"],
191
+ :C => l["C"],
192
+ :s => l["s>"],
193
+ :"s<" => l["s<"],
194
+ :"s>" => l["s>"],
195
+ :S => l["S>"],
196
+ :"S<" => l["S<"],
197
+ :"S>" => l["S>"],
198
+ :v => l["v"],
199
+ :n => l["n"],
200
+ :l => l["l>"],
201
+ :"l<" => l["l<"],
202
+ :"l>" => l["l>"],
203
+ :L => l["L>"],
204
+ :"L<" => l["L<"],
205
+ :"L>" => l["L>"],
206
+ :V => l["V"],
207
+ :N => l["N"],
208
+ :q => l["q>"],
209
+ :"q<" => l["q<"],
210
+ :"q>" => l["q>"],
211
+ :Q => l["Q>"],
212
+ :"Q<" => l["Q<"],
213
+ :"Q>" => l["Q>"],
214
+ :F => l["g"],
215
+ :e => l["e"],
216
+ :g => l["g"],
217
+ :D => l["G"],
218
+ :E => l["E"],
219
+ :G => l["G"],
220
+ :"a*" => l["a*"],
221
+ :half => [ lambda { |str| Flt::IEEE_binary16_BE::from_bytes(str).to(Float) },
222
+ lambda { |v| Flt::IEEE_binary16_BE::new(v).to_bytes } ],
223
+ :half_le => [ lambda { |str| Flt::IEEE_binary16_LE::from_bytes(str).to(Float) },
224
+ lambda { |v| Flt::IEEE_binary16_LE::new(v).to_bytes } ],
225
+ :half_be => [ lambda { |str| Flt::IEEE_binary16_BE::from_bytes(str).to(Float) },
226
+ lambda { |v| Flt::IEEE_binary16_BE::new(v).to_bytes } ],
227
+ :pghalf => [ lambda { |str| Flt::IEEE_binary16_pg_BE::from_bytes(str).to(Float) },
228
+ lambda { |v| Flt::IEEE_binary16_pg_BE::new(v).to_bytes } ],
229
+ :pghalf_le => [ lambda { |str| Flt::IEEE_binary16_pg_LE::from_bytes(str).to(Float) },
230
+ lambda { |v| Flt::IEEE_binary16_pg_LE::new(v).to_bytes } ],
231
+ :pghalf_be => [ lambda { |str| Flt::IEEE_binary16_pg_BE::from_bytes(str).to(Float) },
232
+ lambda { |v| Flt::IEEE_binary16_pg_BE::new(v).to_bytes } ]
233
+ } )
234
+ DATA_ENDIAN[false].merge!( {
235
+ :c => l["c"],
236
+ :C => l["C"],
237
+ :s => l["s<"],
238
+ :"s<" => l["s<"],
239
+ :"s>" => l["s>"],
240
+ :S => l["S<"],
241
+ :"S<" => l["S<"],
242
+ :"S>" => l["S>"],
243
+ :v => l["v"],
244
+ :n => l["n"],
245
+ :l => l["l<"],
246
+ :"l<" => l["l<"],
247
+ :"l>" => l["l>"],
248
+ :L => l["L<"],
249
+ :"L<" => l["L<"],
250
+ :"L>" => l["L>"],
251
+ :V => l["V"],
252
+ :N => l["N"],
253
+ :q => l["q<"],
254
+ :"q<" => l["q<"],
255
+ :"q>" => l["q>"],
256
+ :Q => l["Q<"],
257
+ :"Q<" => l["Q<"],
258
+ :"Q>" => l["Q>"],
259
+ :F => l["e"],
260
+ :e => l["e"],
261
+ :g => l["g"],
262
+ :D => l["E"],
263
+ :E => l["E"],
264
+ :G => l["G"],
265
+ :"a*" => l["a*"],
266
+ :half => [ lambda { |str| Flt::IEEE_binary16::from_bytes(str).to(Float) },
267
+ lambda { |v| Flt::IEEE_binary16::new(v).to_bytes } ],
268
+ :half_le => [ lambda { |str| Flt::IEEE_binary16_LE::from_bytes(str).to(Float) },
269
+ lambda { |v| Flt::IEEE_binary16_LE::new(v).to_bytes } ],
270
+ :half_be => [ lambda { |str| Flt::IEEE_binary16_BE::from_bytes(str).to(Float) },
271
+ lambda { |v| Flt::IEEE_binary16_BE::new(v).to_bytes } ],
272
+ :pghalf => [ lambda { |str| Flt::IEEE_binary16_pg::from_bytes(str).to(Float) },
273
+ lambda { |v| Flt::IEEE_binary16_pg::new(v).to_bytes } ],
274
+ :pghalf_le => [ lambda { |str| Flt::IEEE_binary16_pg_LE::from_bytes(str).to(Float) },
275
+ lambda { |v| Flt::IEEE_binary16_pg_LE::new(v).to_bytes } ],
276
+ :pghalf_be => [ lambda { |str| Flt::IEEE_binary16_pg_BE::from_bytes(str).to(Float) },
277
+ lambda { |v| Flt::IEEE_binary16_pg_BE::new(v).to_bytes } ]
278
+ } )
279
+
280
+
281
+ class Scalar
282
+
283
+ def self.size(*args)
284
+ @size
285
+ end
286
+
287
+ def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape)
288
+ kind::new(previous_offset, previous_offset + @size - 1)
289
+ end
290
+
291
+ def self.init(symbol)
292
+ @symbol = symbol
293
+ @size = DATA_SIZES[symbol]
294
+ @rl_be, @sl_be = DATA_ENDIAN[true][symbol]
295
+ @rl_le, @sl_be = DATA_ENDIAN[false][symbol]
296
+ end
297
+
298
+ def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil)
299
+ str = input.read(@size)
300
+ input_big ? @rl_be[str] : @rl_le[str]
301
+ end
302
+
303
+ def self.dump(value, output, output_big = LibBin::default_big?, _ = nil, _ = nil)
304
+ str = (output_big ? @sl_be[value] : @sl_le[value])
305
+ output.write(str)
306
+ end
307
+
308
+ def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big, _ = nil, _ = nil)
309
+ str = input.read(@size)
310
+ value = (input_big ? @rl_be[str] : @rl_le[str])
311
+ str = (output_big ? @sl_be[value] : @sl_le[value])
312
+ output.write(str)
313
+ value
314
+ end
315
+
316
+ end
317
+
318
+ class Str < Scalar
319
+
320
+ def self.load(input, input_big = LibBin::default_big?, _ = nil, _ = nil)
321
+ str = (@size < 0 ? input.readline("\x00") : input.read(@size))
322
+ input_big ? @rl_be[str] : @rl_le[str]
323
+ end
324
+
325
+ def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big, _ = nil, _ = nil)
326
+ str = (@size < 0 ? input.readline("\x00") : input.read(@size))
327
+ value = (input_big ? @rl_be[str] : @rl_le[str])
328
+ str = (output_big ? @sl_be[value] : @sl_le[value])
329
+ output.write(str)
330
+ value
331
+ end
332
+
333
+ def self.shape(value, previous_offset = 0, _ = nil, _ = nil, kind = DataShape)
334
+ if @size < 0
335
+ kind::new(previous_offset, previous_offset + value.size - 1)
336
+ else
337
+ kind::new(previous_offset, previous_offset + @size - 1)
338
+ end
339
+ end
340
+
341
+ end
342
+
343
+ def self.register_field(field, type, count: nil, offset: nil, sequence: false, condition: nil)
344
+ if type.kind_of?(Symbol)
345
+ if type[0] == 'a'
346
+ c = Class::new(Str) do init(sym) end
347
+ @fields.push([field, c, count, offset, sequence, condition])
348
+ else
349
+ @fields.push([field, const_get(SCALAR_TYPES[type][0]), count, offset, sequence, condition])
350
+ end
351
+ else
352
+ @fields.push([field, type, count, offset, sequence, condition])
353
+ end
354
+ attr_accessor field
355
+ end
356
+
357
+ def self.create_scalar_type(symbol)
358
+ klassname, name = SCALAR_TYPES[symbol]
359
+ eval <<EOF
360
+ class #{klassname} < Scalar
361
+ init(#{symbol.inspect})
362
+ end
363
+
364
+ def self.#{name}(field, count: nil, offset: nil, sequence: false, condition: nil)
365
+ @fields.push([field, #{klassname}, count, offset, sequence, condition])
366
+ attr_accessor field
367
+ end
368
+ EOF
369
+ end
370
+
371
+ create_scalar_type(:c)
372
+ create_scalar_type(:C)
373
+ create_scalar_type(:s)
374
+ create_scalar_type(:"s<")
375
+ create_scalar_type(:"s>")
376
+ create_scalar_type(:S)
377
+ create_scalar_type(:"S<")
378
+ create_scalar_type(:"S>")
379
+ create_scalar_type(:l)
380
+ create_scalar_type(:"l<")
381
+ create_scalar_type(:"l>")
382
+ create_scalar_type(:L)
383
+ create_scalar_type(:"L<")
384
+ create_scalar_type(:"L>")
385
+ create_scalar_type(:q)
386
+ create_scalar_type(:"q<")
387
+ create_scalar_type(:"q>")
388
+ create_scalar_type(:Q)
389
+ create_scalar_type(:"Q<")
390
+ create_scalar_type(:"Q>")
391
+ create_scalar_type(:F)
392
+ create_scalar_type(:e)
393
+ create_scalar_type(:g)
394
+ create_scalar_type(:D)
395
+ create_scalar_type(:E)
396
+ create_scalar_type(:G)
397
+ create_scalar_type(:half)
398
+ create_scalar_type(:half_le)
399
+ create_scalar_type(:half_be)
400
+ create_scalar_type(:pghalf)
401
+ create_scalar_type(:pghalf_le)
402
+ create_scalar_type(:pghalf_be)
403
+
404
+ def self.string( field, length = nil, count: nil, offset: nil, sequence: false, condition: nil)
405
+ sym = (length ? :"a#{length}" : :"a*")
406
+ c = Class::new(Str) do
407
+ init(sym)
408
+ end
409
+ @fields.push([field, c, count, offset, sequence, condition])
410
+ attr_accessor field
411
+ end
412
+
413
+
414
+ end
415
+
416
+ end
data/libbin.gemspec ADDED
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'libbin'
3
+ s.version = "0.9.0"
4
+ s.author = "Brice Videau"
5
+ s.email = "brice.videau@imag.fr"
6
+ s.homepage = "https://github.com/kerilk/libbin"
7
+ s.summary = "Library for loading and converting binary files"
8
+ s.description = "Read, write and convert Binary data in Ruby."
9
+ s.files = Dir[ 'libbin.gemspec', 'LICENSE', 'lib/**/*.rb' ]
10
+ s.has_rdoc = false
11
+ s.license = 'BSD-2-Clause'
12
+ s.required_ruby_version = '>= 2.0.0'
13
+ s.add_dependency 'float-formats', '~> 0.3', '>=0.3.0'
14
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libbin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Brice Videau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: float-formats
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.3.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.3.0
33
+ description: Read, write and convert Binary data in Ruby.
34
+ email: brice.videau@imag.fr
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - LICENSE
40
+ - lib/libbin.rb
41
+ - lib/libbin/alignment.rb
42
+ - lib/libbin/data_types.rb
43
+ - libbin.gemspec
44
+ homepage: https://github.com/kerilk/libbin
45
+ licenses:
46
+ - BSD-2-Clause
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.0.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.7.6
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Library for loading and converting binary files
68
+ test_files: []