libbin 1.0.5 → 2.0.0
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 +4 -4
- data/ext/libbin/data_types.c +557 -0
- data/ext/libbin/data_types.h +16 -0
- data/ext/libbin/libbin_c.c +1916 -41
- data/ext/libbin/libbin_c.h +12 -0
- data/ext/libbin/libbin_endian.h +126 -0
- data/lib/libbin/data_types.rb +629 -398
- data/lib/libbin.rb +77 -355
- data/libbin.gemspec +2 -3
- metadata +8 -6
- data/lib/libbin/alignment.rb +0 -14
data/lib/libbin.rb
CHANGED
@@ -1,391 +1,113 @@
|
|
1
|
-
module LibBin
|
2
|
-
end
|
3
1
|
require "libbin_c.so"
|
4
2
|
|
5
|
-
require_relative 'libbin/alignment'
|
6
3
|
require_relative 'libbin/data_types'
|
7
4
|
|
5
|
+
# Container module, handles the global state default endianness and error output.
|
8
6
|
module LibBin
|
9
7
|
|
10
|
-
@
|
11
|
-
@
|
8
|
+
@big = [0x12345678].pack("i") == "\x12\x34\x56\x78"
|
9
|
+
@output = $stderr
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
else
|
17
|
-
@__big
|
18
|
-
end
|
11
|
+
class << self
|
12
|
+
attr_accessor :big
|
13
|
+
attr_accessor :output
|
19
14
|
end
|
20
15
|
|
21
|
-
|
22
|
-
|
16
|
+
# Returns true the default endianness is big
|
17
|
+
def self.default_big?
|
18
|
+
@big
|
19
|
+
end
|
23
20
|
|
21
|
+
class Structure
|
22
|
+
|
23
|
+
# @!parse
|
24
|
+
# attr_accessor :__parent
|
25
|
+
# attr_accessor :__index
|
26
|
+
# attr_accessor :__position
|
27
|
+
# attr_accessor :__cur_position
|
28
|
+
# attr_accessor :__input
|
29
|
+
# attr_accessor :__output
|
30
|
+
# attr_accessor :__input_big
|
31
|
+
# attr_accessor :__output_big
|
32
|
+
#
|
33
|
+
# attr_accessor :__offset
|
34
|
+
# attr_accessor :__condition
|
35
|
+
# attr_accessor :__type
|
36
|
+
# attr_accessor :__length
|
37
|
+
# attr_accessor :__count
|
38
|
+
# attr_accessor :__iterator
|
39
|
+
# attr_accessor :__value
|
40
|
+
#
|
41
|
+
# # @method __dump_fields
|
42
|
+
# # Dump fields according to the internal state of +self+
|
43
|
+
# # @return [Structure] self
|
44
|
+
|
45
|
+
# @!visibility private
|
24
46
|
def inspect
|
25
47
|
to_s
|
26
48
|
end
|
27
49
|
|
28
|
-
|
29
|
-
attr_reader :__index
|
30
|
-
attr_reader :__iterator
|
31
|
-
attr_reader :__position
|
32
|
-
def __set_convert_type(input, output, input_big, output_big, parent, index)
|
33
|
-
@__input_big = input_big
|
34
|
-
@__output_big = output_big
|
35
|
-
@__input = input
|
36
|
-
@__output = output
|
37
|
-
@__parent = parent
|
38
|
-
@__index = index
|
39
|
-
@__position = input.tell
|
40
|
-
@__cur_position = @__position
|
41
|
-
end
|
42
|
-
|
43
|
-
def __set_size_type(position, parent, index)
|
44
|
-
@__parent = parent
|
45
|
-
@__index = index
|
46
|
-
@__position = position
|
47
|
-
@__cur_position = @__position
|
48
|
-
end
|
49
|
-
|
50
|
-
def __set_load_type(input, input_big, parent, index)
|
51
|
-
@__input_big = input_big
|
52
|
-
@__input = input
|
53
|
-
@__parent = parent
|
54
|
-
@__index = index
|
55
|
-
@__position = input.tell
|
56
|
-
@__cur_position = @__position
|
57
|
-
end
|
58
|
-
|
59
|
-
def __set_dump_type(output, output_big, parent, index)
|
60
|
-
@__output_big = output_big
|
61
|
-
@__output = output
|
62
|
-
@__parent = parent
|
63
|
-
@__index = index
|
64
|
-
@__position = output.tell
|
65
|
-
@__cur_position = @__position
|
66
|
-
end
|
67
|
-
|
68
|
-
def __unset_convert_type
|
69
|
-
@__input_big = nil
|
70
|
-
@__output_big = nil
|
71
|
-
@__input = nil
|
72
|
-
@__output = nil
|
73
|
-
@__parent = nil
|
74
|
-
@__index = nil
|
75
|
-
@__position = nil
|
76
|
-
@__cur_position = nil
|
77
|
-
end
|
78
|
-
|
79
|
-
def __unset_size_type
|
80
|
-
@__parent = nil
|
81
|
-
@__index = nil
|
82
|
-
@__position = nil
|
83
|
-
@__cur_position = nil
|
84
|
-
end
|
85
|
-
|
86
|
-
def __unset_load_type
|
87
|
-
@__input_big = nil
|
88
|
-
@__input = nil
|
89
|
-
@__parent = nil
|
90
|
-
@__index = nil
|
91
|
-
@__position = nil
|
92
|
-
@__cur_position = nil
|
93
|
-
end
|
94
|
-
|
95
|
-
def __unset_dump_type
|
96
|
-
@__output_big = nil
|
97
|
-
@__output = nil
|
98
|
-
@__parent = nil
|
99
|
-
@__index = nil
|
100
|
-
@__position = nil
|
101
|
-
@__cur_position = nil
|
102
|
-
end
|
103
|
-
|
50
|
+
# @!visibility private
|
104
51
|
def self.inherited(subclass)
|
105
52
|
subclass.instance_variable_set(:@fields, [])
|
106
53
|
end
|
107
54
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
else
|
116
|
-
return sym
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def __decode_seek_offset(offset, relative_offset)
|
121
|
-
return nil unless offset
|
122
|
-
offset = __decode_expression(offset)
|
123
|
-
return false if offset == 0x0
|
124
|
-
offset += @__position if relative_offset
|
125
|
-
@__cur_position = offset
|
126
|
-
@__input.seek(offset) if @__input
|
127
|
-
@__output.seek(offset) if @__output
|
128
|
-
offset
|
129
|
-
end
|
130
|
-
|
131
|
-
def __decode_condition(condition)
|
132
|
-
return true unless condition
|
133
|
-
__decode_expression(condition)
|
134
|
-
end
|
135
|
-
|
136
|
-
def __decode_count(count)
|
137
|
-
return 1 unless count
|
138
|
-
__decode_expression(count)
|
139
|
-
end
|
140
|
-
|
141
|
-
def __decode_type(type)
|
142
|
-
return __decode_expression(type)
|
143
|
-
end
|
144
|
-
|
145
|
-
def __decode_length(length)
|
146
|
-
__decode_expression(length)
|
147
|
-
end
|
148
|
-
|
149
|
-
def __decode_static_conditions(field)
|
150
|
-
@__offset = nil
|
151
|
-
@__condition = nil
|
152
|
-
@__type = nil
|
153
|
-
@__length = nil
|
154
|
-
@__count = nil
|
155
|
-
unless field.sequence?
|
156
|
-
@__offset = __decode_seek_offset(field.offset, field.relative_offset?)
|
157
|
-
throw :ignored, nil if @__offset == false
|
158
|
-
@__condition = __decode_condition(field.condition)
|
159
|
-
throw :ignored, nil unless @__condition
|
160
|
-
@__type = __decode_type(field.type)
|
161
|
-
@__length = __decode_length(field.length)
|
162
|
-
end
|
163
|
-
@__count = __decode_count(field.count)
|
164
|
-
end
|
165
|
-
|
166
|
-
def __decode_dynamic_conditions(field)
|
167
|
-
return true unless field.sequence?
|
168
|
-
@__offset = nil
|
169
|
-
@__condition = nil
|
170
|
-
@__type = nil
|
171
|
-
@__length = nil
|
172
|
-
@__offset = __decode_seek_offset(field.offset, field.relative_offset?)
|
173
|
-
return false if @__offset == false
|
174
|
-
@__condition = __decode_condition(field.condition)
|
175
|
-
return false unless @__condition
|
176
|
-
@__type = __decode_type(field.type)
|
177
|
-
@__length = __decode_length(field.length)
|
178
|
-
return true
|
55
|
+
# Returns the size of the structure
|
56
|
+
# @param offset [Integer] position in the stream
|
57
|
+
# @param parent [Structure] if given, parent structure
|
58
|
+
# @param index [Integer] index if part of a repeated field inside parent
|
59
|
+
# @return [Integer] size of the structure
|
60
|
+
def __size(offset = 0, parent = nil, index = nil)
|
61
|
+
__shape(offset, parent, index, DataRange).size
|
179
62
|
end
|
180
63
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
@
|
185
|
-
|
186
|
-
|
187
|
-
|
64
|
+
# Returns the alignement of the structure
|
65
|
+
# @return [Integer] alignment of the structure
|
66
|
+
def self.align
|
67
|
+
return @always_align if @always_align
|
68
|
+
align = @fields.collect(&:align).select { |v| v }.max
|
69
|
+
align = 0 unless align
|
70
|
+
align
|
188
71
|
end
|
189
72
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
nil
|
198
|
-
end
|
199
|
-
end
|
200
|
-
__restore_context
|
201
|
-
vs = vs.first unless field.count
|
202
|
-
vs
|
203
|
-
end
|
204
|
-
|
205
|
-
def __load_field(field)
|
206
|
-
__decode_static_conditions(field)
|
207
|
-
vs = @__count.times.collect do |it|
|
208
|
-
@__iterator = it
|
209
|
-
if __decode_dynamic_conditions(field)
|
210
|
-
@__type::load(@__input, @__input_big, self, it, @__length)
|
211
|
-
else
|
212
|
-
nil
|
213
|
-
end
|
214
|
-
end
|
215
|
-
__restore_context
|
216
|
-
vs = vs.first unless field.count
|
217
|
-
vs
|
218
|
-
end
|
219
|
-
|
220
|
-
def __dump_field(vs, field)
|
221
|
-
__decode_static_conditions(field)
|
222
|
-
vs = [vs] unless field.count
|
223
|
-
vs.each_with_index do |v, it|
|
224
|
-
@__iterator = it
|
225
|
-
if __decode_dynamic_conditions(field)
|
226
|
-
@__type::dump(v, @__output, @__output_big, self, it, @__length)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
__restore_context
|
230
|
-
end
|
231
|
-
|
232
|
-
def __shape_field(vs, previous_offset, kind, field)
|
233
|
-
__decode_static_conditions(field)
|
234
|
-
vs = [vs] unless field.count
|
235
|
-
vs = vs.each_with_index.collect do |v, it|
|
236
|
-
@__iterator = it
|
237
|
-
if __decode_dynamic_conditions(field)
|
238
|
-
sh = @__type::shape(v, @__cur_position, self, it, kind, @__length)
|
239
|
-
@__cur_position = sh.last + 1 if sh.last && sh.last >= 0
|
240
|
-
sh
|
241
|
-
end
|
242
|
-
end
|
243
|
-
__restore_context
|
244
|
-
vs = vs.first unless field.count
|
245
|
-
vs
|
246
|
-
end
|
247
|
-
|
248
|
-
def __size(previous_offset = 0, parent = nil, index = nil)
|
249
|
-
__shape(previous_offset, parent, index, DataRange).size
|
250
|
-
end
|
251
|
-
|
252
|
-
def __shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape)
|
253
|
-
__set_size_type(previous_offset, parent, index)
|
254
|
-
members = {}
|
255
|
-
self.class.instance_variable_get(:@fields).each { |field|
|
256
|
-
begin
|
257
|
-
vs = send(field.name)
|
258
|
-
member = catch(:ignored) do
|
259
|
-
__shape_field(vs, previous_offset, kind, field)
|
260
|
-
end
|
261
|
-
members[field.name] = member
|
262
|
-
rescue
|
263
|
-
STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
264
|
-
raise
|
265
|
-
end
|
266
|
-
}
|
267
|
-
__unset_size_type
|
268
|
-
return nil if members.values.flatten.compact.size <= 0
|
269
|
-
kind::new(members)
|
270
|
-
end
|
271
|
-
|
272
|
-
def __convert_fields
|
273
|
-
self.class.instance_variable_get(:@fields).each { |field|
|
274
|
-
begin
|
275
|
-
vs = catch(:ignored) do
|
276
|
-
__convert_field(field)
|
277
|
-
end
|
278
|
-
send("#{field.name}=", vs)
|
279
|
-
rescue
|
280
|
-
STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
281
|
-
raise
|
282
|
-
end
|
283
|
-
}
|
284
|
-
self
|
285
|
-
end
|
286
|
-
|
287
|
-
def __load_fields
|
288
|
-
self.class.instance_variable_get(:@fields).each { |field|
|
289
|
-
begin
|
290
|
-
vs = catch(:ignored) do
|
291
|
-
__load_field(field)
|
292
|
-
end
|
293
|
-
send("#{field.name}=", vs)
|
294
|
-
rescue
|
295
|
-
STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
296
|
-
raise
|
297
|
-
end
|
298
|
-
}
|
299
|
-
self
|
300
|
-
end
|
301
|
-
|
302
|
-
def __dump_fields
|
303
|
-
self.class.instance_variable_get(:@fields).each { |field|
|
304
|
-
begin
|
305
|
-
vs = send(field.name)
|
306
|
-
catch(:ignored) do
|
307
|
-
__dump_field(vs, field)
|
308
|
-
end
|
309
|
-
rescue
|
310
|
-
STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
311
|
-
raise
|
312
|
-
end
|
313
|
-
}
|
314
|
-
self
|
315
|
-
end
|
316
|
-
|
317
|
-
def __convert(input, output, input_big, output_big, parent = nil, index = nil)
|
318
|
-
__set_convert_type(input, output, input_big, output_big, parent, index)
|
319
|
-
__convert_fields
|
320
|
-
__unset_convert_type
|
321
|
-
self
|
322
|
-
end
|
323
|
-
|
324
|
-
def __load(input, input_big, parent = nil, index = nil)
|
325
|
-
__set_load_type(input, input_big, parent, index)
|
326
|
-
__load_fields
|
327
|
-
__unset_load_type
|
328
|
-
self
|
329
|
-
end
|
330
|
-
|
331
|
-
def __dump(output, output_big, parent = nil, index = nil)
|
332
|
-
__set_dump_type(output, output_big, parent, index)
|
333
|
-
__dump_fields
|
334
|
-
__unset_dump_type
|
335
|
-
self
|
336
|
-
end
|
337
|
-
|
338
|
-
def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big?, parent = nil, index = nil, length = nil)
|
339
|
-
if length
|
340
|
-
length.times.collect {
|
341
|
-
h = self::new
|
342
|
-
h.__load(input, input_big, parent, index)
|
343
|
-
}
|
73
|
+
# Set the structure as needing to always be aligned
|
74
|
+
# @param align [true, Integer] if true use the fields' maximum alignment
|
75
|
+
# @return align
|
76
|
+
def self.set_always_align(align)
|
77
|
+
if align == true
|
78
|
+
@always_align = @fields.collect(&:align).select { |v| v }.max
|
79
|
+
@always_align = 0 unless align
|
344
80
|
else
|
345
|
-
|
346
|
-
|
81
|
+
raise "alignement must be a power of 2" if align && (align - 1) & align != 0
|
82
|
+
@always_align = align
|
347
83
|
end
|
84
|
+
align
|
348
85
|
end
|
349
86
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
h.__load(input, input_big, parent, index)
|
355
|
-
}
|
356
|
-
else
|
357
|
-
h = self::new
|
358
|
-
h.__load(input, input_big, parent, index)
|
359
|
-
end
|
87
|
+
class << self
|
88
|
+
alias always_align= set_always_align
|
89
|
+
attr_reader :always_align
|
90
|
+
attr_reader :fields
|
360
91
|
end
|
361
92
|
|
362
|
-
|
93
|
+
# Returns the size of a structure
|
94
|
+
# @param value [Structure,Array<Structure>] field or array of field to get the size of
|
95
|
+
# @param offset [Integer] position in the stream
|
96
|
+
# @param parent [Structure] if given, parent structure
|
97
|
+
# @param index [Integer] index if part of a repeated field inside parent
|
98
|
+
# @param length [Integer] if given, the length of the vector
|
99
|
+
def self.size(value, offset = 0, parent = nil, index = nil, length = nil)
|
363
100
|
if length
|
364
|
-
length.
|
365
|
-
value[i].__dump(output, output_big, parent, index)
|
366
|
-
}
|
367
|
-
value
|
101
|
+
shape(value, offset, parent, index, length).size
|
368
102
|
else
|
369
|
-
value.
|
103
|
+
value.__shape(offset, parent, index).size
|
370
104
|
end
|
371
105
|
end
|
372
106
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
value.__shape(previous_offset, parent, index).size
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
def self.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
|
382
|
-
if length
|
383
|
-
kind::new(length.times.collect { |i|
|
384
|
-
value[i].__shape(previous_offset, parent, index, kind)
|
385
|
-
})
|
386
|
-
else
|
387
|
-
value.__shape(previous_offset, parent, index, kind)
|
388
|
-
end
|
107
|
+
# Return the structure class fields
|
108
|
+
# @return [Array<Field>]
|
109
|
+
def __fields
|
110
|
+
return self.class.fields
|
389
111
|
end
|
390
112
|
|
391
113
|
end
|
data/libbin.gemspec
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'libbin'
|
3
|
-
s.version = "
|
3
|
+
s.version = "2.0.0"
|
4
4
|
s.author = "Brice Videau"
|
5
|
-
s.email = "brice.videau@
|
5
|
+
s.email = "brice.videau@gmail.com"
|
6
6
|
s.homepage = "https://github.com/kerilk/libbin"
|
7
7
|
s.summary = "Library for loading and converting binary files"
|
8
8
|
s.description = "Read, write and convert Binary data in Ruby."
|
9
9
|
s.files = Dir[ 'libbin.gemspec', 'LICENSE', 'lib/**/*.rb', 'ext/libbin/extconf.rb', 'ext/libbin/*.c', 'ext/libbin/*.h' ]
|
10
10
|
s.extensions << 'ext/libbin/extconf.rb'
|
11
|
-
s.has_rdoc = false
|
12
11
|
s.license = 'BSD-2-Clause'
|
13
12
|
s.required_ruby_version = '>= 2.0.0'
|
14
13
|
s.add_dependency 'float-formats', '~> 0.3', '>=0.3.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libbin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brice Videau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: float-formats
|
@@ -31,21 +31,24 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 0.3.0
|
33
33
|
description: Read, write and convert Binary data in Ruby.
|
34
|
-
email: brice.videau@
|
34
|
+
email: brice.videau@gmail.com
|
35
35
|
executables: []
|
36
36
|
extensions:
|
37
37
|
- ext/libbin/extconf.rb
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
40
|
- LICENSE
|
41
|
+
- ext/libbin/data_types.c
|
42
|
+
- ext/libbin/data_types.h
|
41
43
|
- ext/libbin/extconf.rb
|
42
44
|
- ext/libbin/half.c
|
43
45
|
- ext/libbin/half.h
|
44
46
|
- ext/libbin/libbin_c.c
|
47
|
+
- ext/libbin/libbin_c.h
|
48
|
+
- ext/libbin/libbin_endian.h
|
45
49
|
- ext/libbin/pghalf.c
|
46
50
|
- ext/libbin/pghalf.h
|
47
51
|
- lib/libbin.rb
|
48
|
-
- lib/libbin/alignment.rb
|
49
52
|
- lib/libbin/data_types.rb
|
50
53
|
- libbin.gemspec
|
51
54
|
homepage: https://github.com/kerilk/libbin
|
@@ -67,8 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '0'
|
69
72
|
requirements: []
|
70
|
-
|
71
|
-
rubygems_version: 2.7.6
|
73
|
+
rubygems_version: 3.1.2
|
72
74
|
signing_key:
|
73
75
|
specification_version: 4
|
74
76
|
summary: Library for loading and converting binary files
|