depix 1.0.2 → 1.0.3

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/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.0.2 / 2008-12-23
2
+
3
+ * Do not cleanup null bytes and terminators in the middle of char[] attributes (something useful might be in there)
4
+
1
5
  === 1.0.2 / 2008-12-19
2
6
 
3
7
  * refactor struct parsing completely
data/README.txt CHANGED
@@ -8,7 +8,7 @@ Read DPX file metadata
8
8
 
9
9
  == SYNOPSIS:
10
10
 
11
- meta = Depix::Reader.from_file(dpx_file_path)
11
+ meta = Depix.from_file(dpx_file_path)
12
12
  puts meta.time_code #=> 10:00:00:02
13
13
 
14
14
  The data returned is described in the DPX_HEADER_STRUCTURE[link:files/DPX_HEADER_STRUCTURE_txt.html]. It's
data/bin/depix-describe CHANGED
@@ -15,5 +15,9 @@ end.parse!
15
15
  ARGV.each do | file |
16
16
  puts "Describing DPX #{file}. Empty elements are omitted.\n\n"
17
17
  puts "===================================================\n\n"
18
- puts Depix.describe_file(file, options[:compact])
18
+ begin
19
+ puts Depix.describe_file(file, options[:compact])
20
+ rescue Depix::InvalidHeader
21
+ puts " - Invalid header data"
22
+ end
19
23
  end
data/lib/depix.rb CHANGED
@@ -8,7 +8,9 @@ require File.dirname(__FILE__) + '/depix/compact_structs'
8
8
  require File.dirname(__FILE__) + '/depix/enums'
9
9
 
10
10
  module Depix
11
- VERSION = '1.0.2'
11
+ VERSION = '1.0.3'
12
+
13
+ class InvalidHeader < RuntimeError; end
12
14
 
13
15
  # Offers convenience access to a few common attributes bypassing the piecemeal structs
14
16
  module Synthetics
@@ -16,8 +18,10 @@ module Depix
16
18
  [film.id, film.type, film.offset, film.prefix, film.count].compact.join(' ')
17
19
  end
18
20
 
21
+ # Return the flame reel name. The data after the first null byte is not meant to be seen and is used by Flame internally
22
+ # as it seems
19
23
  def flame_reel
20
- orientation.device.to_s.scan(/^(\w+)/).to_s
24
+ orientation.device.split("\000").shift
21
25
  end
22
26
 
23
27
  def time_code
@@ -71,16 +75,38 @@ module Depix
71
75
 
72
76
  def from_file(path, compact)
73
77
  header = File.open(path, 'r') { |f| f.read(DPX.length) }
74
- parse(header, compact)
78
+ begin
79
+ parse(header, compact)
80
+ rescue InvalidHeader => e
81
+ raise InvalidHeader, "Invalid header in file #{path}"
82
+ end
75
83
  end
76
84
 
77
85
  # The hear of Depix
78
86
  def parse(data, compact)
79
87
  magic = data[0..3]
88
+
89
+ raise InvalidHeader unless %w( SDPX XPDS).include?(magic)
90
+
80
91
  struct = compact ? CompactDPX : DPX
81
92
 
82
- template = (magic == "SDPX") ? struct.pattern : make_le(struct.pattern)
83
- struct.consume!(data.unpack(template))
93
+ is_be = (magic == "SDPX")
94
+ version_check = FileInfo.only(:magic, :version)
95
+
96
+ result = begin
97
+ if is_be
98
+ version_check.consume!(data.unpack(version_check.pattern))
99
+ else
100
+ version_check.consume!(data.unpack(make_le(version_check.pattern)))
101
+ end
102
+ rescue ArgumentError
103
+ raise InvalidHeader
104
+ end
105
+
106
+ raise InvalidHeader unless result.version == "V1.0"
107
+
108
+ template = is_be ? DPX.pattern : make_le(DPX.pattern)
109
+ struct.consume!(data.unpack(struct.pattern))
84
110
  end
85
111
 
86
112
  # Describe a filled DPX structure
data/lib/depix/dict.rb CHANGED
@@ -54,6 +54,7 @@ module Depix
54
54
 
55
55
  class U32Field < Field
56
56
  BLANK = 0xFFFFFFFF
57
+ undef :length=, :pattern=
57
58
 
58
59
  def pattern
59
60
  "N"
@@ -69,6 +70,7 @@ module Depix
69
70
  end
70
71
 
71
72
  class U8Field < Field
73
+ undef :length=, :pattern=
72
74
 
73
75
  BLANK = 0xFF
74
76
 
@@ -90,6 +92,7 @@ module Depix
90
92
  end
91
93
 
92
94
  class Filler < Field
95
+ undef :pattern=
93
96
  def pattern
94
97
  "x#{length ? length.to_i : 1}"
95
98
  end
@@ -102,6 +105,7 @@ module Depix
102
105
 
103
106
  class U16Field < Field
104
107
  BLANK = 0xFFFF
108
+ undef :length=, :pattern=
105
109
 
106
110
  def pattern
107
111
  "n"
@@ -121,6 +125,8 @@ module Depix
121
125
  end
122
126
 
123
127
  class R32Field < Field
128
+ undef :length=, :pattern=
129
+
124
130
  def pattern
125
131
  "g"
126
132
  end
@@ -140,6 +146,12 @@ module Depix
140
146
 
141
147
  class CharField < Field
142
148
  BLANK = "\0"
149
+ undef :pattern=
150
+
151
+ BLANKING_VALUES = [0x00.chr, 0xFF.chr]
152
+ BLANKING_PATTERNS = BLANKING_VALUES.inject([]) do | p, char |
153
+ p << /^(#{char}+)/ << /(#{char}+)$/
154
+ end
143
155
 
144
156
  def pattern
145
157
  "A#{(length || 1).to_i}"
@@ -149,8 +161,8 @@ module Depix
149
161
  if v == BLANK
150
162
  nil
151
163
  else
152
- cleansed = v.gsub(0xFF.chr, '').gsub(0x00.chr, '')
153
- cleansed.empty? ? nil : cleansed
164
+ 2.times { BLANKING_PATTERNS.each{|p| v.gsub!(p, '')} }
165
+ v.empty? ? nil : v
154
166
  end
155
167
  end
156
168
 
@@ -320,6 +332,8 @@ module Depix
320
332
 
321
333
  anon = Class.new(self)
322
334
  anon.fields.replace(distillate)
335
+ only_items = distillate.map{|n| n.name }
336
+
323
337
  anon
324
338
  end
325
339
 
data/test/test_depix.rb CHANGED
@@ -4,7 +4,7 @@ require 'test/unit'
4
4
  class ReaderTest < Test::Unit::TestCase
5
5
 
6
6
  SAMPLE_DPX = File.dirname(__FILE__) + '/samples/E012_P001_L000002_lin.0001.dpx'
7
-
7
+
8
8
  def test_parsed_properly
9
9
  file = SAMPLE_DPX
10
10
  parsed = Depix.from_file(file)
@@ -38,8 +38,10 @@ class ReaderTest < Test::Unit::TestCase
38
38
  assert_equal 8192, parsed.image.image_elements[0].data_offset
39
39
  assert_equal 0, parsed.image.image_elements[0].end_of_line_padding
40
40
  assert_equal 0, parsed.image.image_elements[0].end_of_image_padding
41
- assert_equal "IMAGE DESCRIPTION DATA P", parsed.image.image_elements[0].description
42
- assert_equal "E012x\340\264\020\005", parsed.orientation.device #- this is where Flame writes the reel
41
+ assert_equal "IMAGE DESCRIPTION DATA \000P", parsed.image.image_elements[0].description
42
+ assert_equal "E012\000\000\000\000x\340\264\020\000\000\000\000\005",
43
+ parsed.orientation.device #- this is where Flame writes the reel
44
+
43
45
  assert_equal 853, parsed.orientation.aspect_ratio[0]
44
46
  assert_equal 640, parsed.orientation.aspect_ratio[1]
45
47
 
@@ -66,7 +68,7 @@ class ReaderTest < Test::Unit::TestCase
66
68
  assert_equal "01:15:11:18", parsed.time_code.to_s
67
69
  assert_equal :RGB, parsed.component_type
68
70
  assert_equal :Linear, parsed.colorimetric
69
- assert_equal "E012x", parsed.flame_reel
71
+ assert_equal "E012", parsed.flame_reel
70
72
  end
71
73
 
72
74
  def test_parsed_properly_using_compact_structs
@@ -81,4 +83,16 @@ class ReaderTest < Test::Unit::TestCase
81
83
  assert_match(/Offset to data for this image element/, desc)
82
84
  end
83
85
  end
86
+
87
+ def test_parsing_something_else_should_raise
88
+ s = "Mary had a little lamb"
89
+ assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
90
+
91
+ s = "Mary had a little lamb" * 1000
92
+ assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
93
+
94
+ s = "SDPX Mary had a little lamb" * 1000
95
+ assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
96
+
97
+ end
84
98
  end
data/test/test_dict.rb CHANGED
@@ -13,6 +13,10 @@ module FieldConformity
13
13
  assert_respond_to f, :rtype
14
14
  assert_respond_to f, :explain
15
15
  end
16
+
17
+ def assert_method_removed(f, method)
18
+ fail("#{f.inspect} should not respond to #{method}") if f.respond_to?(method)
19
+ end
16
20
  end
17
21
 
18
22
  class FieldExplainsItself < Test::Unit::TestCase
@@ -124,9 +128,15 @@ class TestArrayField < Test::Unit::TestCase
124
128
  conform_field!(f)
125
129
 
126
130
  assert_respond_to f, :name=
127
-
128
- assert_raise(NoMethodError) { f.length = 1 }
129
- assert_raise(NoMethodError) { f.pattern = 'C' }
131
+
132
+ assert_method_removed f, :length=
133
+ assert_method_removed f, :pattern=
134
+ end
135
+
136
+ def test_array_does_not_allow_setting_length
137
+ f = ArrayField.new
138
+ assert_method_removed(f, :length=)
139
+ assert_method_removed(f, :pattern=)
130
140
  end
131
141
 
132
142
  def test_array_field_has_members
@@ -162,8 +172,8 @@ class TestInnerField < Test::Unit::TestCase
162
172
  assert_respond_to f, :cast
163
173
  assert_respond_to f, :cast=
164
174
 
165
- assert_raise(NoMethodError) { f.length = 1 }
166
- assert_raise(NoMethodError) { f.pattern = 'C' }
175
+ assert_method_removed(f, :length=)
176
+ assert_method_removed(f, :pattern=)
167
177
  end
168
178
 
169
179
  def test_inner_field_asks_cast_for_pattern_and_length
@@ -173,6 +183,10 @@ class TestInnerField < Test::Unit::TestCase
173
183
  casted = InnerField.new(:cast => sample)
174
184
  assert_equal 123, casted.length
175
185
  assert_equal 'C123', casted.pattern
186
+
187
+ assert_method_removed(casted, :length=)
188
+ assert_method_removed(casted, :pattern=)
189
+
176
190
  end
177
191
 
178
192
  def test_rtype_for_inner_field_is_cast
@@ -203,6 +217,7 @@ class TestCharField < Test::Unit::TestCase
203
217
  def test_char_field_conforms_to_basics
204
218
  f = CharField.new :name => :foo
205
219
  conform_field!(f)
220
+ assert_method_removed(f, :pattern=)
206
221
  end
207
222
 
208
223
  def test_char_field_pads
@@ -213,14 +228,19 @@ class TestCharField < Test::Unit::TestCase
213
228
  assert_equal String, f.rtype
214
229
  end
215
230
 
216
- def test_char_field_clean_inner_nulls
231
+ def test_char_field_does_not_clean_inner_nulls
217
232
  f = CharField.new :name => :foo, :length => 15
218
- assert_equal "foo", f.clean("\0\0foo")
233
+ assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
234
+ assert_equal "swoop\377\0bla", f.clean("\0\0\0\377\377swoop\377\0bla\0\0\0\377\377\377\377\0\0\0")
219
235
  end
220
236
 
221
237
  def test_char_field_clean_blank
222
238
  f = CharField.new :name => :foo, :length => 15
223
239
  assert_equal nil, f.clean("\0")
240
+ assert_equal nil, f.clean("\0\0\0\0\0\0")
241
+ assert_equal nil, f.clean("\0\0\0\377\377\0\0\0")
242
+ assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
243
+
224
244
  end
225
245
  end
226
246
 
@@ -249,6 +269,10 @@ class TestSmallintField < Test::Unit::TestCase
249
269
  def test_smallint_conformity
250
270
  f = U8Field.new :name => :foo
251
271
  conform_field!(f)
272
+
273
+ assert_method_removed(f, :pattern=)
274
+ assert_method_removed(f, :length=)
275
+
252
276
  end
253
277
 
254
278
  def test_smallint_operation
@@ -274,6 +298,9 @@ class TestDoubleField < Test::Unit::TestCase
274
298
  def test_double_conformity
275
299
  f = U16Field.new :name => :foo
276
300
  conform_field!(f)
301
+
302
+ assert_method_removed(f, :pattern=)
303
+ assert_method_removed(f, :length=)
277
304
  end
278
305
 
279
306
  def test_double_operation
@@ -301,6 +328,10 @@ class TestFillerField < Test::Unit::TestCase
301
328
  assert_equal "x1", f.pattern
302
329
  end
303
330
 
331
+ def test_filler_does_not_allow_setting_pattern
332
+ assert_method_removed(Filler.new, :pattern=)
333
+ end
334
+
304
335
  def test_pattern_discards_value
305
336
  data = [1,2,3].pack("ccc")
306
337
  filler = Filler.new(:length => 3)
@@ -596,11 +627,16 @@ class TestDictCompact < Test::Unit::TestCase
596
627
  assert_equal distill.length, c.length, "The distilled struct should occupy the same space"
597
628
  assert_equal 3, distill.fields.length
598
629
 
630
+ result = distill.apply!("abcdefhjhjkujkdkklsalierioeiore")
631
+
599
632
  assert_kind_of Filler, distill.fields[0]
600
633
  assert_equal 5, distill.fields[0].length
601
634
 
602
635
  assert_kind_of Filler, distill.fields[2]
603
636
  assert_equal 14, distill.fields[2].length
637
+
638
+ assert_nil result.some
639
+ assert_nil result.fourth
604
640
  end
605
641
 
606
642
  def test_get_filler
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: depix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-21 00:00:00 +01:00
12
+ date: 2008-12-23 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency