depix 1.0.2 → 1.0.3

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