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.
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
- @__big_architecture = [0x12345678].pack("i") == "\x12\x34\x56\x78"
11
- @__big = nil
8
+ @big = [0x12345678].pack("i") == "\x12\x34\x56\x78"
9
+ @output = $stderr
12
10
 
13
- def self.default_big?
14
- if @__big.nil?
15
- @__big_architecture
16
- else
17
- @__big
18
- end
11
+ class << self
12
+ attr_accessor :big
13
+ attr_accessor :output
19
14
  end
20
15
 
21
- class DataConverter
22
- include Alignment
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
- attr_reader :__parent
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
- def __decode_expression(sym)
109
- case sym
110
- when Proc
111
- return sym.call
112
- when String
113
- exp = sym.gsub("..","__parent").gsub("\\",".")
114
- return eval(exp)
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
- def __restore_context
182
- @__iterator = nil
183
- @__type = nil
184
- @__length = nil
185
- @__count = nil
186
- @__offset = nil
187
- @__condition = nil
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
- def __convert_field(field)
191
- __decode_static_conditions(field)
192
- vs = @__count.times.collect do |it|
193
- @__iterator = it
194
- if __decode_dynamic_conditions(field)
195
- @__type::convert(@__input, @__output, @__input_big, @__output_big, self, it, @__length)
196
- else
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
- h = self::new
346
- h.__convert(input, output, input_big, output_big, parent, index)
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
- def self.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
351
- if length
352
- length.times.collect {
353
- h = self::new
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
- def self.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
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.times.collect { |i|
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.__dump(output, output_big, parent, index)
103
+ value.__shape(offset, parent, index).size
370
104
  end
371
105
  end
372
106
 
373
- def self.size(value, previous_offset = 0, parent = nil, index = nil, length = nil)
374
- if length
375
- shape(value, previous_offset, parent, index, length).size
376
- else
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 = "1.0.5"
3
+ s.version = "2.0.0"
4
4
  s.author = "Brice Videau"
5
- s.email = "brice.videau@imag.fr"
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: 1.0.5
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: 2019-09-22 00:00:00.000000000 Z
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@imag.fr
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
- rubyforge_project:
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
@@ -1,14 +0,0 @@
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