depix 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/DPX_HEADER_STRUCTURE.rdoc +5 -5
- data/Gemfile +13 -0
- data/History.txt +14 -0
- data/README.rdoc +15 -3
- data/Rakefile +28 -14
- data/bin/{depix-describe → depix_describe} +5 -4
- data/bin/depix_fix_headers +39 -0
- data/depix.gemspec +93 -0
- data/lib/depix.rb +2 -12
- data/lib/depix/binary/fields.rb +74 -32
- data/lib/depix/binary/{descriptor.rb → rdoc_generator.rb} +5 -1
- data/lib/depix/binary/structure.rb +9 -4
- data/lib/depix/describe.rb +53 -0
- data/lib/depix/reader.rb +15 -40
- data/lib/depix/structs.rb +5 -5
- data/lib/depix/synthetics.rb +12 -2
- data/test/samples/scratch.dpx +0 -0
- data/test/{test_dict.rb → test_binary.rb} +35 -18
- data/test/test_depix.rb +21 -12
- data/test/test_describe.rb +26 -0
- data/test/test_fix_headers.rb +19 -0
- metadata +113 -63
- data/Manifest.txt +0 -28
- data/lib/depix/struct_explainer.rb +0 -59
data/.travis.yml
ADDED
data/DPX_HEADER_STRUCTURE.rdoc
CHANGED
@@ -21,7 +21,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
|
|
21
21
|
* <tt>project</tt> (String) Project name
|
22
22
|
* <tt>copyright</tt> (String) Copyright
|
23
23
|
* <tt>encrypt_key</tt> Encryption key
|
24
|
-
* <tt>reserve</tt> (
|
24
|
+
* <tt>reserve</tt> (NilClass)
|
25
25
|
* <tt>image</tt> (Depix::ImageInfo) Image information - required:
|
26
26
|
* <tt>orientation</tt> (Integer) Orientation descriptor - required
|
27
27
|
* <tt>number_elements</tt> (Integer) How many elements to scan - required
|
@@ -43,7 +43,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
|
|
43
43
|
* <tt>end_of_line_padding</tt> End-of-line padding for this image element
|
44
44
|
* <tt>end_of_image_padding</tt> End-of-line padding for this image element
|
45
45
|
* <tt>description</tt> (String)
|
46
|
-
* <tt>reserve</tt> (
|
46
|
+
* <tt>reserve</tt> (NilClass)
|
47
47
|
* <tt>orientation</tt> (Depix::OrientationInfo) Orientation - required:
|
48
48
|
* <tt>x_offset</tt>
|
49
49
|
* <tt>y_offset</tt>
|
@@ -57,7 +57,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
|
|
57
57
|
* <tt>serial</tt> (String) Input device serial number
|
58
58
|
* <tt>border</tt> (Array of 4 Integer fields) Border validity: XL, XR, YT, YB:
|
59
59
|
* <tt>aspect_ratio</tt> (Array of 2 fields) Aspect (H:V):
|
60
|
-
* <tt>reserve</tt> (
|
60
|
+
* <tt>reserve</tt> (NilClass)
|
61
61
|
* <tt>film</tt> (Depix::FilmInfo) Film industry info - required:
|
62
62
|
* <tt>id</tt> (String) Film mfg. ID code (2 digits from film edge code)
|
63
63
|
* <tt>type</tt> (String) Film type (2 digits from film edge code)
|
@@ -72,7 +72,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
|
|
72
72
|
* <tt>shutter_angle</tt> (Float) Shutter angle
|
73
73
|
* <tt>frame_id</tt> (String) Frame identification (keyframe)
|
74
74
|
* <tt>slate</tt> (String) Slate information
|
75
|
-
* <tt>reserve</tt> (
|
75
|
+
* <tt>reserve</tt> (NilClass)
|
76
76
|
* <tt>television</tt> (Depix::TelevisionInfo) TV industry info - required:
|
77
77
|
* <tt>time_code</tt> Timecode, formatted as HH:MM:SS:FF in the 4 higher bits of each 8bit group
|
78
78
|
* <tt>user_bits</tt> Timecode UBITs
|
@@ -90,7 +90,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
|
|
90
90
|
* <tt>break_point</tt> (Float) Break point (?)
|
91
91
|
* <tt>white_level</tt> (Float) White level
|
92
92
|
* <tt>integration_times</tt> (Float) Integration times (S)
|
93
|
-
* <tt>reserve</tt> (
|
93
|
+
* <tt>reserve</tt> (NilClass)
|
94
94
|
* <tt>user</tt> (Depix::UserInfo) User info - required:
|
95
95
|
* <tt>id</tt> (String) Name of the user data tag
|
96
96
|
* <tt>user_data_ptr</tt>
|
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
=== 3.0.0 / 2011-11-29
|
2
|
+
|
3
|
+
* Use jeweler for gem builds
|
4
|
+
* depix-describe renamed with a dash. Sorry folks.
|
5
|
+
* Adds depix_fix_headers to fix wonky headers with, for instance, improper null-termination
|
6
|
+
* Multiple bug fixes
|
7
|
+
* Padded reserved fields not shown anymore
|
8
|
+
* More fields that have invalid values resolve to nil now
|
9
|
+
* fixed that Synthetics#aspect would return pixel aspect and not image aspect
|
10
|
+
|
11
|
+
=== 2.0.1 / 2011-11-09
|
12
|
+
|
13
|
+
* Fix the errors in depix-describe
|
14
|
+
|
1
15
|
=== 2.0.0 / 2011-06-14
|
2
16
|
|
3
17
|
* Depix::Binary is now public, and it's a nice library. Check it out.
|
data/README.rdoc
CHANGED
@@ -27,17 +27,29 @@ have the same name as the specified fields.
|
|
27
27
|
|
28
28
|
The gem also contains an executable called depix-desribe which can be used from the command line
|
29
29
|
|
30
|
-
$
|
30
|
+
$depix_describe 001_PTAPE_001.001.dpx
|
31
31
|
|
32
32
|
for a long description or
|
33
33
|
|
34
|
-
$
|
34
|
+
$depix_describe -s 001_PTAPE_001.001.dpx
|
35
|
+
|
36
|
+
for a short description.
|
37
|
+
|
38
|
+
If you have a file that does not import into some application you could run "fix headers" on it to comb
|
39
|
+
out invalid data (or data some systems do not approve of). To do so, run depix_fix_headers. Note that the files
|
40
|
+
will be modified in-place
|
41
|
+
|
42
|
+
$depix_fix_headers 001_PTAPE_001.001.dpx
|
43
|
+
|
44
|
+
or for a whole sequence - just supply the -s flag and pass one file
|
45
|
+
|
46
|
+
$depix_fix_headers -s 001_PTAPE_001.001.dpx
|
35
47
|
|
36
|
-
for a short description
|
37
48
|
|
38
49
|
== NOTES:
|
39
50
|
|
40
51
|
Autodesk IFFS systems write the reel name for the file to the orientation.device field, some scanners write it into user data.
|
52
|
+
Currently unpacking slots which contain invalid reals and ints will yield the maximum possible value for the type
|
41
53
|
|
42
54
|
== REQUIREMENTS:
|
43
55
|
|
data/Rakefile
CHANGED
@@ -1,20 +1,34 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
2
|
require './lib/depix'
|
3
|
+
require 'jeweler'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.version = Depix::VERSION
|
7
|
+
gem.name = "depix"
|
8
|
+
gem.summary = "Read and write DPX file headers"
|
9
|
+
gem.description = "Allos you to edit headers and read their contents parsed into Ruby objects"
|
10
|
+
gem.email = "me@julik.nl"
|
11
|
+
gem.homepage = "http://guerilla-di.org/depix"
|
12
|
+
gem.authors = ["Julik Tarkhanov"]
|
13
|
+
gem.extra_rdoc_files << "DEVELOPER_DOCS.rdoc"
|
14
|
+
gem.license = 'MIT'
|
15
|
+
gem.executables = ["depix_describe", "depix_fix_headers"]
|
16
|
+
gem.extra_rdoc_files = FileList['*.rdoc']
|
15
17
|
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
Jeweler::RubygemsDotOrgTasks.new
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
desc "Run all tests"
|
23
|
+
Rake::TestTask.new("test") do |t|
|
24
|
+
t.libs << "test"
|
25
|
+
t.pattern = 'test/**/test_*.rb'
|
26
|
+
t.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
task :default => [ :test ]
|
30
|
+
|
31
|
+
task :document_structs do
|
32
|
+
require './lib/depix/binary/descriptor'
|
33
|
+
File.open('DPX_HEADER_STRUCTURE.rdoc', 'w') {|f| f << Depix::Binary::RdocGenerator.new.get_rdoc_for(Depix::DPX) }
|
20
34
|
end
|
@@ -5,7 +5,7 @@ require 'optparse'
|
|
5
5
|
|
6
6
|
options = {}
|
7
7
|
OptionParser.new do |opts|
|
8
|
-
opts.banner = "Usage:
|
8
|
+
opts.banner = "Usage: depix_describe somefile.dpx anotherfile.dpx [options]"
|
9
9
|
|
10
10
|
opts.on("-c", "--compact", "Compact output (only fields that change per frame)") do |v|
|
11
11
|
options[:compact] = true
|
@@ -18,15 +18,16 @@ OptionParser.new do |opts|
|
|
18
18
|
end.parse!
|
19
19
|
|
20
20
|
ARGV.each do | file |
|
21
|
+
puts "\n"
|
21
22
|
puts "Describing DPX #{file}. Empty elements are omitted."
|
22
23
|
puts "===================================================\n"
|
23
24
|
begin
|
24
25
|
if options[:synthetics]
|
25
|
-
puts Depix.describe_brief(file)
|
26
|
+
puts Depix::Describe.new.describe_brief(file)
|
26
27
|
elsif options[:compact]
|
27
|
-
puts Depix.
|
28
|
+
puts Depix::Describe.new.describe(file, true)
|
28
29
|
else
|
29
|
-
puts Depix.
|
30
|
+
puts Depix::Describe.new.describe(file)
|
30
31
|
end
|
31
32
|
rescue Depix::InvalidHeader
|
32
33
|
puts " - Invalid header data"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/depix'
|
4
|
+
require "rubygems"
|
5
|
+
require 'optparse'
|
6
|
+
require "progressbar"
|
7
|
+
require "sequencer"
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.banner = "Usage: depix_fix_headers somefile.dpx anotherfile.dpx" + "\n" +
|
12
|
+
"For sequences: depix_fix_headers -s one_file_from_the_sequence.dpx"
|
13
|
+
|
14
|
+
opts.on("-s", "--sequence", "Detect a sequence instead (pass one file from the sequence)") do |v|
|
15
|
+
$sequence = true
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
files = if $sequence
|
20
|
+
paths = []
|
21
|
+
Sequencer.from_single_file(ARGV.shift).each_path do | p |
|
22
|
+
paths.push(p)
|
23
|
+
end
|
24
|
+
paths
|
25
|
+
else
|
26
|
+
ARGV
|
27
|
+
end
|
28
|
+
|
29
|
+
raise "No files provided" unless files.any?
|
30
|
+
|
31
|
+
header = "Fixing headers in %d files" % files.length
|
32
|
+
pbar = ProgressBar.new(header, files.length)
|
33
|
+
pbar.format = "%-#{header.length}s %3d%% %s %s"
|
34
|
+
|
35
|
+
files.each do | file |
|
36
|
+
pbar.inc
|
37
|
+
Depix::Editor.new(file).commit!
|
38
|
+
end
|
39
|
+
puts ""
|
data/depix.gemspec
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "depix"
|
8
|
+
s.version = "3.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Julik Tarkhanov"]
|
12
|
+
s.date = "2011-11-29"
|
13
|
+
s.description = "Allos you to edit headers and read their contents parsed into Ruby objects"
|
14
|
+
s.email = "me@julik.nl"
|
15
|
+
s.executables = ["depix_describe", "depix_fix_headers"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"DPX_HEADER_STRUCTURE.rdoc",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gemtest",
|
22
|
+
".travis.yml",
|
23
|
+
"DPX_HEADER_STRUCTURE.rdoc",
|
24
|
+
"Gemfile",
|
25
|
+
"History.txt",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"bin/depix_describe",
|
29
|
+
"bin/depix_fix_headers",
|
30
|
+
"depix.gemspec",
|
31
|
+
"lib/depix.rb",
|
32
|
+
"lib/depix/binary/fields.rb",
|
33
|
+
"lib/depix/binary/rdoc_generator.rb",
|
34
|
+
"lib/depix/binary/structure.rb",
|
35
|
+
"lib/depix/compact_structs.rb",
|
36
|
+
"lib/depix/describe.rb",
|
37
|
+
"lib/depix/editor.rb",
|
38
|
+
"lib/depix/enums.rb",
|
39
|
+
"lib/depix/reader.rb",
|
40
|
+
"lib/depix/structs.rb",
|
41
|
+
"lib/depix/synthetics.rb",
|
42
|
+
"test/samples/026_FROM_HERO_TAPE_5-3-1_MOV.0029.dpx",
|
43
|
+
"test/samples/E012_P001_L000002_lin.0001.dpx",
|
44
|
+
"test/samples/E012_P001_L000002_lin.0002.dpx",
|
45
|
+
"test/samples/E012_P001_L000002_log.0001.dpx",
|
46
|
+
"test/samples/E012_P001_L000002_log.0002.dpx",
|
47
|
+
"test/samples/from_nuke_no_TC_meta.dpx",
|
48
|
+
"test/samples/gluetools_file_header.dpx",
|
49
|
+
"test/samples/little_endian.dpx",
|
50
|
+
"test/samples/northlight_tc_mode_mismatch.dpx",
|
51
|
+
"test/samples/scratch.dpx",
|
52
|
+
"test/test_binary.rb",
|
53
|
+
"test/test_depix.rb",
|
54
|
+
"test/test_describe.rb",
|
55
|
+
"test/test_fix_headers.rb"
|
56
|
+
]
|
57
|
+
s.homepage = "http://guerilla-di.org/depix"
|
58
|
+
s.licenses = ["MIT"]
|
59
|
+
s.require_paths = ["lib"]
|
60
|
+
s.rubygems_version = "1.8.11"
|
61
|
+
s.summary = "Read and write DPX file headers"
|
62
|
+
|
63
|
+
if s.respond_to? :specification_version then
|
64
|
+
s.specification_version = 3
|
65
|
+
|
66
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
|
+
s.add_runtime_dependency(%q<timecode>, ["~> 1.0"])
|
68
|
+
s.add_runtime_dependency(%q<progressbar>, ["~> 0.9"])
|
69
|
+
s.add_runtime_dependency(%q<sequencer>, ["~> 1.0"])
|
70
|
+
s.add_runtime_dependency(%q<term-ansicolor>, [">= 0"])
|
71
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
72
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
73
|
+
s.add_development_dependency(%q<cli_test>, ["~> 1.0"])
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<timecode>, ["~> 1.0"])
|
76
|
+
s.add_dependency(%q<progressbar>, ["~> 0.9"])
|
77
|
+
s.add_dependency(%q<sequencer>, ["~> 1.0"])
|
78
|
+
s.add_dependency(%q<term-ansicolor>, [">= 0"])
|
79
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
80
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
81
|
+
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
82
|
+
end
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<timecode>, ["~> 1.0"])
|
85
|
+
s.add_dependency(%q<progressbar>, ["~> 0.9"])
|
86
|
+
s.add_dependency(%q<sequencer>, ["~> 1.0"])
|
87
|
+
s.add_dependency(%q<term-ansicolor>, [">= 0"])
|
88
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
89
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
90
|
+
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
data/lib/depix.rb
CHANGED
@@ -12,9 +12,10 @@ require File.expand_path(File.dirname(__FILE__)) + '/depix/synthetics'
|
|
12
12
|
require File.expand_path(File.dirname(__FILE__)) + '/depix/reader'
|
13
13
|
require File.expand_path(File.dirname(__FILE__)) + '/depix/editor'
|
14
14
|
|
15
|
+
require File.expand_path(File.dirname(__FILE__)) + '/depix/describe'
|
15
16
|
|
16
17
|
module Depix
|
17
|
-
VERSION = '
|
18
|
+
VERSION = '3.0.0'
|
18
19
|
|
19
20
|
class InvalidHeader < RuntimeError; end
|
20
21
|
|
@@ -31,15 +32,4 @@ module Depix
|
|
31
32
|
def self.from_string(string, compact = false)
|
32
33
|
Reader.new.parse(string, compact)
|
33
34
|
end
|
34
|
-
|
35
|
-
# Retrurn a formatted description of the DPX file at path. Empty values are omitted.
|
36
|
-
def self.describe_file(path, compact = false)
|
37
|
-
Reader.new.describe_file(path, compact)
|
38
|
-
end
|
39
|
-
|
40
|
-
# Return a formatted description of the DPX file at path, showing only synthetic attributes
|
41
|
-
def self.describe_brief(path)
|
42
|
-
Reader.new.describe_synthetics_of_struct(from_file(path))
|
43
|
-
end
|
44
|
-
|
45
35
|
end
|
data/lib/depix/binary/fields.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Fields
|
1
|
+
# coding: ASCII-8BIT
|
2
|
+
module Depix; module Binary; module Fields
|
4
3
|
|
5
4
|
# Base class for a padded field in a struct
|
6
5
|
class Field
|
7
|
-
attr_accessor :name
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
attr_accessor :name # Field name
|
7
|
+
attr_accessor :length # Field length in bytes, including any possible padding
|
8
|
+
attr_accessor :pattern # The unpack pattern that defines the field
|
9
|
+
attr_accessor :req # Is the field required?
|
10
|
+
attr_accessor :desc # Field description
|
11
|
+
attr_accessor :rtype # To which Ruby type this has to be cast (and which type is accepted as value)
|
12
|
+
|
13
13
|
alias_method :req?, :req
|
14
14
|
|
15
15
|
# Hash init
|
@@ -53,6 +53,11 @@ module Depix
|
|
53
53
|
[value].pack(pattern)
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def blanking?(blob)
|
59
|
+
blob.nil? || blob.empty? || blob == (0xFF.chr * length)
|
60
|
+
end
|
56
61
|
end
|
57
62
|
|
58
63
|
# unit32 field
|
@@ -84,7 +89,7 @@ module Depix
|
|
84
89
|
# uint8 field
|
85
90
|
class U8Field < Field
|
86
91
|
undef :length=, :pattern=
|
87
|
-
|
92
|
+
|
88
93
|
BLANK = 0xFF
|
89
94
|
|
90
95
|
def pattern
|
@@ -144,26 +149,36 @@ module Depix
|
|
144
149
|
end
|
145
150
|
|
146
151
|
def clean(v)
|
147
|
-
v == BLANK ? nil : v
|
152
|
+
(v == BLANK || v == -1) ? nil : v
|
148
153
|
end
|
149
154
|
|
150
155
|
def validate!(value)
|
151
156
|
super(value)
|
152
157
|
raise "#{name} value #{value} out of bounds for 16bit unsigned int" if (value < 0 || value >= BLANK)
|
153
158
|
end
|
159
|
+
|
154
160
|
end
|
155
161
|
|
156
|
-
# real32 field
|
162
|
+
# real32 field. Now, there is some lap dancing to be done here.
|
163
|
+
# The DPX files in the wild define nonexistant data as a charfield with all
|
164
|
+
# it's bits set (four times 0xFF byte). This is easy to verify with a string
|
165
|
+
# but practically useless once the charfield has been unpacked into a float.
|
166
|
+
# Therefore we first unpack the value as a charfield, then we check whether it's all
|
167
|
+
# blanking, and if it is we return nil. If it's not "all bits set" though what we will do
|
168
|
+
# is try to decode it again using the real float unpack pattern. The same dance
|
169
|
+
# happens reciprocally when repacking the data.
|
157
170
|
class R32Field < Field
|
158
171
|
undef :length=, :pattern=
|
159
|
-
BLANK =
|
172
|
+
BLANK = (0xFF.chr * 4)
|
173
|
+
PATTERN_BE = "g"
|
174
|
+
PATTERN_LE = "n"
|
160
175
|
|
161
176
|
def pattern
|
162
177
|
"g"
|
163
178
|
end
|
164
179
|
|
165
180
|
def clean(v)
|
166
|
-
v.nan? ? nil : v
|
181
|
+
(v.nil? || v.nan?) ? nil : v
|
167
182
|
end
|
168
183
|
|
169
184
|
def length
|
@@ -173,34 +188,35 @@ module Depix
|
|
173
188
|
def rtype
|
174
189
|
Float
|
175
190
|
end
|
191
|
+
|
192
|
+
# The packing of NaN
|
193
|
+
# [12] pry(main)> value = 0 / 0.0
|
194
|
+
# => NaN
|
195
|
+
# [13] pry(main)> [value].pack("g")
|
196
|
+
# => "\xFF\xC0\x00\x00"
|
197
|
+
# [14] pry(main)> [value].pack("g")
|
198
|
+
def pack(value)
|
199
|
+
(value.nil? || value.nan? ) ? BLANK : [value].pack("g")
|
200
|
+
end
|
176
201
|
end
|
177
202
|
|
178
203
|
# null-terminated string field with fixed padding
|
179
204
|
class CharField < Field
|
180
|
-
BLANK = "\0"
|
181
205
|
undef :pattern=
|
182
206
|
|
183
|
-
BLANKING_VALUES = [0x00.chr, 0xFF.chr]
|
184
|
-
BLANKING_PATTERNS = BLANKING_VALUES.inject([]) do | p, char |
|
185
|
-
p << /^([#{char}]+)/ << /([#{char}]+)$/mu
|
186
|
-
end
|
187
|
-
|
188
207
|
def initialize(opts = {})
|
189
208
|
super({:length => 1}.merge(opts))
|
190
209
|
end
|
191
210
|
|
192
211
|
def pattern
|
193
|
-
"
|
212
|
+
"Z#{length}"
|
194
213
|
end
|
195
214
|
|
196
215
|
def clean(v)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
upto_nulb = v.split(0x00.chr).shift
|
202
|
-
(upto_nulb.nil? || upto_nulb.empty?) ? nil : upto_nulb
|
203
|
-
end
|
216
|
+
# Use the pack->unpack trick to remove null-termination
|
217
|
+
v = pack(v.to_s).unpack(pattern)[0]
|
218
|
+
# Blanked fields are 0xFF all the way
|
219
|
+
blanking?(v) ? nil : v
|
204
220
|
end
|
205
221
|
|
206
222
|
def rtype
|
@@ -213,7 +229,35 @@ module Depix
|
|
213
229
|
end
|
214
230
|
|
215
231
|
def pack(value)
|
216
|
-
|
232
|
+
unless blanking?(value)
|
233
|
+
[value].pack(pattern)
|
234
|
+
else
|
235
|
+
0xFF.chr * length
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# For reserved fields and blanking
|
241
|
+
class BlankingField < CharField
|
242
|
+
|
243
|
+
def validate!(value)
|
244
|
+
raise "The value of this field should be nil" unless value.nil?
|
245
|
+
end
|
246
|
+
|
247
|
+
def pattern
|
248
|
+
"Z#{length}"
|
249
|
+
end
|
250
|
+
|
251
|
+
def clean(v)
|
252
|
+
nil
|
253
|
+
end
|
254
|
+
|
255
|
+
def rtype
|
256
|
+
NilClass
|
257
|
+
end
|
258
|
+
|
259
|
+
def pack(value)
|
260
|
+
0xFF.chr * length
|
217
261
|
end
|
218
262
|
end
|
219
263
|
|
@@ -297,6 +341,4 @@ module Depix
|
|
297
341
|
cast.pack(value)
|
298
342
|
end
|
299
343
|
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
344
|
+
end; end; end
|