tlv 0.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/AUTHORS +1 -0
- data/CHANGELOG +10 -0
- data/COPYING +728 -0
- data/LICENSE +58 -0
- data/README +38 -0
- data/Rakefile +163 -0
- data/THANKS +0 -0
- data/TODO +2 -0
- data/bin/parse_dgi +50 -0
- data/bin/parse_tlv +51 -0
- data/lib/tlv.rb +11 -0
- data/lib/tlv/b.rb +32 -0
- data/lib/tlv/constructed.rb +116 -0
- data/lib/tlv/dgi.rb +40 -0
- data/lib/tlv/field.rb +24 -0
- data/lib/tlv/parse.rb +87 -0
- data/lib/tlv/parser/dictionaries/asn.rb +63 -0
- data/lib/tlv/parser/dictionaries/dictionaries.rb +2 -0
- data/lib/tlv/parser/dictionaries/emv_tags.rb +130 -0
- data/lib/tlv/parser/parser.rb +167 -0
- data/lib/tlv/raw.rb +31 -0
- data/lib/tlv/tag.rb +51 -0
- data/lib/tlv/tlv.rb +144 -0
- data/lib/tlv/to_bytes.rb +76 -0
- data/test/constructed_test.rb +106 -0
- data/test/dgi_test.rb +122 -0
- data/test/tlv_tag_test.rb +89 -0
- data/test/tlv_test.rb +217 -0
- metadata +108 -0
data/LICENSE
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
This package is copyrighted free software by Tim Becker <tim@kuriositaet.de>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
3
|
+
(see COPYING.txt file), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) rename any non-standard executables so the names do not conflict
|
21
|
+
with standard executables, which must also be provided.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or executable
|
26
|
+
form, provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the executables and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard executables non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under this terms.
|
43
|
+
|
44
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
45
|
+
files under the ./missing directory. See each file for the copying
|
46
|
+
condition.
|
47
|
+
|
48
|
+
5. The scripts and library files supplied as input to or produced as
|
49
|
+
output from the software do not automatically fall under the
|
50
|
+
copyright of the software, but belong to whomever generated them,
|
51
|
+
and may be sold commercially, and may be aggregated with this
|
52
|
+
software.
|
53
|
+
|
54
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
55
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
56
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
57
|
+
PURPOSE.
|
58
|
+
|
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= tlv -- lib to facilitate working with tlv data
|
2
|
+
|
3
|
+
|
4
|
+
== Installing
|
5
|
+
|
6
|
+
Having a "Installing" section is a bit of a chicken or egg question.
|
7
|
+
Someone reading this README has, in all likelyhood already installed the
|
8
|
+
package.
|
9
|
+
|
10
|
+
You can install the +tlv+ package by executing:
|
11
|
+
|
12
|
+
gem install tlv -r
|
13
|
+
|
14
|
+
alternatively, you can download +.tar.gz+ or +.zip+ archives from
|
15
|
+
Rubyforge[http://rubyforge.org/frs/?group_id=2203].
|
16
|
+
|
17
|
+
|
18
|
+
== Mail
|
19
|
+
|
20
|
+
In case you discover bugs, spelling errors, offer suggestions for
|
21
|
+
improvements or would like to help out with the project, you can contact
|
22
|
+
me directly (tim@kuriositaet.de).
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
=
|
data/Rakefile
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require "rdoc/task"
|
2
|
+
require "rubygems/package_task"
|
3
|
+
require "rake/testtask"
|
4
|
+
require "rake/clean"
|
5
|
+
require "rubygems"
|
6
|
+
|
7
|
+
# Some definitions that you'll need to edit in case you reuse this
|
8
|
+
# Rakefile for your own project.
|
9
|
+
|
10
|
+
SHORTNAME ='tlv' # this should be the rubyforge project name
|
11
|
+
DESC ='lib for handling tlv data'
|
12
|
+
PKG_VERSION ='0.0.3'
|
13
|
+
LONG_DESC = <<END_DESC
|
14
|
+
lib for handling tlv (der) and dgi encoded data
|
15
|
+
END_DESC
|
16
|
+
RUBYFORGE_USER ='a2800276'
|
17
|
+
AUTHOR = "Tim Becker"
|
18
|
+
EMAIL = "tim@kuriositaet.de"
|
19
|
+
HOMEPAGE = "http://github.com/a2800276/tlv"
|
20
|
+
|
21
|
+
|
22
|
+
# Specifies the default task to execute. This is often the "test" task
|
23
|
+
# and we'll change things around as soon as we have some tests.
|
24
|
+
|
25
|
+
task :default => [:test]
|
26
|
+
|
27
|
+
# The directory to generate +rdoc+ in.
|
28
|
+
RDOC_DIR="doc/html"
|
29
|
+
|
30
|
+
# This global variable contains files that will be erased by the `clean` task.
|
31
|
+
# The `clean` task itself is automatically generated by requiring `rake/clean`.
|
32
|
+
|
33
|
+
CLEAN << RDOC_DIR << "pkg"
|
34
|
+
|
35
|
+
|
36
|
+
# This is the task that generates the +rdoc+ documentation from the
|
37
|
+
# source files. Instantiating Rake::RDocTask automatically generates a
|
38
|
+
# task called `rdoc`.
|
39
|
+
|
40
|
+
Rake::RDocTask.new do |rd|
|
41
|
+
# Options for documenation generation are specified inside of
|
42
|
+
# this block. For example the following line specifies that the
|
43
|
+
# content of the README file should be the main page of the
|
44
|
+
# documenation.
|
45
|
+
rd.main = "README"
|
46
|
+
|
47
|
+
# The following line specifies all the files to extract
|
48
|
+
# documenation from.
|
49
|
+
rd.rdoc_files.include( "README", "AUTHORS", "LICENSE", "TODO",
|
50
|
+
"CHANGELOG", "bin/**/*", "lib/**/*.rb",
|
51
|
+
"examples/**/*rb", "doc/*.rdoc")
|
52
|
+
# This one specifies the output directory ...
|
53
|
+
rd.rdoc_dir = "doc/html"
|
54
|
+
|
55
|
+
# Or the HTML title of the generated documentation set.
|
56
|
+
rd.title = "#{SHORTNAME}: #{DESC}"
|
57
|
+
|
58
|
+
# These are options specifiying how source code inlined in the
|
59
|
+
# documentation should be formatted.
|
60
|
+
|
61
|
+
rd.options = ["--line-numbers", "--inline-source"]
|
62
|
+
|
63
|
+
# Check:
|
64
|
+
# `rdoc --help` for more rdoc options
|
65
|
+
# the {rdoc documenation home}[http://www.ruby-doc.org/stdlib/libdoc/rdoc/rdoc/index.html]
|
66
|
+
# or the documentation for the +Rake::RDocTask+ task[http://rake.rubyforge.org/classes/Rake/RDocTask.html]
|
67
|
+
end
|
68
|
+
Rake::RDocTask.new(:rdoc_dev) do |rd|
|
69
|
+
# Options for documenation generation are specified inside of
|
70
|
+
# this block. For example the following line specifies that the
|
71
|
+
# content of the README file should be the main page of the
|
72
|
+
# documenation.
|
73
|
+
rd.main = "README"
|
74
|
+
|
75
|
+
# The following line specifies all the files to extract
|
76
|
+
# documenation from.
|
77
|
+
rd.rdoc_files.include( "README", "AUTHORS", "LICENSE", "TODO",
|
78
|
+
"CHANGELOG", "bin/**/*", "lib/**/*.rb",
|
79
|
+
"examples/**/*rb","test/**/*.rb", "doc/*.rdoc")
|
80
|
+
# This one specifies the output directory ...
|
81
|
+
rd.rdoc_dir = "doc/dev_html"
|
82
|
+
|
83
|
+
# Or the HTML title of the generated documentation set.
|
84
|
+
rd.title = "#{SHORTNAME}: #{DESC}"
|
85
|
+
|
86
|
+
# These are options specifiying how source code inlined in the
|
87
|
+
# documentation should be formatted.
|
88
|
+
|
89
|
+
rd.options = ["--line-numbers", "--inline-source"]
|
90
|
+
|
91
|
+
# Check:
|
92
|
+
# `rdoc --help` for more rdoc options
|
93
|
+
# the {rdoc documenation home}[http://www.ruby-doc.org/stdlib/libdoc/rdoc/rdoc/index.html]
|
94
|
+
# or the documentation for the +Rake::RDocTask+ task[http://rake.rubyforge.org/classes/Rake/RDocTask.html]
|
95
|
+
end
|
96
|
+
|
97
|
+
# The GemPackageTask facilitates getting all your files collected
|
98
|
+
# together into gem archives. You can also use it to generate tarball
|
99
|
+
# and zip archives.
|
100
|
+
|
101
|
+
# First you'll need to assemble a gemspec
|
102
|
+
|
103
|
+
PKG_FILES = FileList['lib/**/*.rb', 'bin/**/*', 'examples/**/*', '[A-Z]*', 'test/**/*'].to_a
|
104
|
+
|
105
|
+
spec = Gem::Specification.new do |s|
|
106
|
+
s.platform = Gem::Platform::RUBY
|
107
|
+
s.summary = "#{SHORTNAME}: #{DESC}"
|
108
|
+
s.add_dependency "hexy"
|
109
|
+
s.name = SHORTNAME
|
110
|
+
s.version = PKG_VERSION
|
111
|
+
s.files = PKG_FILES
|
112
|
+
s.requirements << "none"
|
113
|
+
s.require_path = 'lib'
|
114
|
+
s.description = LONG_DESC
|
115
|
+
s.author = AUTHOR
|
116
|
+
s.email = EMAIL
|
117
|
+
s.homepage = HOMEPAGE
|
118
|
+
s.has_rdoc = true
|
119
|
+
s.executables = ["parse_tlv", "parse_dgi"]
|
120
|
+
end
|
121
|
+
|
122
|
+
# Adding a new GemPackageTask adds a task named `package`, which generates
|
123
|
+
# packages as gems, tarball and zip archives.
|
124
|
+
Gem::PackageTask.new(spec) do |pkg|
|
125
|
+
pkg.need_zip = true
|
126
|
+
pkg.need_tar_gz = true
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# This task is used to demonstrate how to upload files to Rubyforge.
|
131
|
+
# Calling `upload_page` creates a current version of the +rdoc+
|
132
|
+
# documentation and uploads it to the Rubyforge homepage of the project,
|
133
|
+
# assuming it's hosted there and naming conventions haven't changed.
|
134
|
+
#
|
135
|
+
# This task uses `sh` to call the `scp` binary, which is plattform
|
136
|
+
# dependant and may not be installed on your computer if you're using
|
137
|
+
# Windows. I'm currently not aware of any pure ruby way to do scp
|
138
|
+
# transfers.
|
139
|
+
|
140
|
+
RubyForgeProject=SHORTNAME
|
141
|
+
|
142
|
+
desc "Upload the web pages to the web."
|
143
|
+
task :upload_pages => ["rdoc"] do
|
144
|
+
if RubyForgeProject then
|
145
|
+
path = "/var/www/gforge-projects/#{RubyForgeProject}"
|
146
|
+
sh "scp -r doc/html/* #{RUBYFORGE_USER}@rubyforge.org:#{path}"
|
147
|
+
sh "scp doc/images/*.png #{RUBYFORGE_USER}@rubyforge.org:#{path}/images"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# This task will run the unit tests provided in files called
|
152
|
+
# `test/test*.rb`. The task itself can be run with a call to `rake test`
|
153
|
+
|
154
|
+
Rake::TestTask.new do |t|
|
155
|
+
t.libs << "test"
|
156
|
+
t.libs << "lib"
|
157
|
+
t.test_files = FileList['test/*.rb']
|
158
|
+
t.ruby_opts = ["-rubygems"]
|
159
|
+
t.verbose = true
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
|
data/THANKS
ADDED
File without changes
|
data/bin/parse_dgi
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
require 'tlv'
|
5
|
+
require 'tlv/parser/dictionaries/dictionaries'
|
6
|
+
|
7
|
+
USAGE =<<END
|
8
|
+
usage: parse_dgi [-hex] [-dictionaries] [-d dictionary] (file_to_parse | < file_to_parse)
|
9
|
+
-hex interpred input data as hex
|
10
|
+
-dictionaries list available dictionaries
|
11
|
+
END
|
12
|
+
|
13
|
+
hex = ARGV.delete "-hex"
|
14
|
+
list_dictionaries = ARGV.delete "-dictionaries"
|
15
|
+
|
16
|
+
if (i = ARGV.index("-d"))
|
17
|
+
dict = TLV::DICTIONARIES[ARGV[i+1]]
|
18
|
+
ARGV.delete_at i
|
19
|
+
ARGV.delete_at i
|
20
|
+
end
|
21
|
+
file = ARGV.last
|
22
|
+
|
23
|
+
if file
|
24
|
+
unless File.exists?(file) && File.readable?(file)
|
25
|
+
STDERR.puts USAGE
|
26
|
+
exit(1)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if list_dictionaries
|
31
|
+
TLV::DICTIONARIES.each_key{|key|
|
32
|
+
puts key
|
33
|
+
}
|
34
|
+
exit(0)
|
35
|
+
end
|
36
|
+
|
37
|
+
io = file ? File.open(file) : STDIN
|
38
|
+
|
39
|
+
lines = io.readlines
|
40
|
+
#lines.each {|line|
|
41
|
+
# puts TLV.s2b(line)+"<<<<<"
|
42
|
+
# puts line
|
43
|
+
#}
|
44
|
+
if hex
|
45
|
+
puts TLV.parse_dgi_hex(lines.join, dict || {})
|
46
|
+
else
|
47
|
+
puts TLV.parse_dgi(lines.join, dict || {})
|
48
|
+
end
|
49
|
+
|
50
|
+
io.close
|
data/bin/parse_tlv
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
require 'tlv'
|
5
|
+
require 'tlv/parser/dictionaries/dictionaries'
|
6
|
+
|
7
|
+
|
8
|
+
USAGE =<<END
|
9
|
+
usage: parse_tlv [-hex] [-dictionaries] [-d dictionary] (file_to_parse | < file_to_parse)
|
10
|
+
-hex interpred input data as hex
|
11
|
+
-dictionaries list available dictionaries
|
12
|
+
END
|
13
|
+
|
14
|
+
hex = ARGV.delete "-hex"
|
15
|
+
list_dictionaries = ARGV.delete "-dictionaries"
|
16
|
+
|
17
|
+
if (i = ARGV.index("-d"))
|
18
|
+
dict = TLV::DICTIONARIES[ARGV[i+1]]
|
19
|
+
ARGV.delete_at i
|
20
|
+
ARGV.delete_at i
|
21
|
+
end
|
22
|
+
file = ARGV.last
|
23
|
+
|
24
|
+
if file
|
25
|
+
unless File.exists?(file) && File.readable?(file)
|
26
|
+
STDERR.puts USAGE
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if list_dictionaries
|
32
|
+
TLV::DICTIONARIES.each_key{|key|
|
33
|
+
puts key
|
34
|
+
}
|
35
|
+
exit(0)
|
36
|
+
end
|
37
|
+
|
38
|
+
io = file ? File.open(file) : STDIN
|
39
|
+
|
40
|
+
|
41
|
+
lines = io.readlines
|
42
|
+
#lines.each {|line|
|
43
|
+
# puts TLV.s2b(line)
|
44
|
+
#}
|
45
|
+
if hex
|
46
|
+
puts TLV.parse_hex(lines.join, dict)
|
47
|
+
else
|
48
|
+
puts TLV.parse(lines.join,dict)
|
49
|
+
end
|
50
|
+
|
51
|
+
io.close
|
data/lib/tlv.rb
ADDED
data/lib/tlv/b.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module TLV
|
2
|
+
|
3
|
+
class TLV
|
4
|
+
class B < Field
|
5
|
+
def define_accessor clazz
|
6
|
+
super
|
7
|
+
name = @name
|
8
|
+
len = @length
|
9
|
+
clazz.instance_eval{
|
10
|
+
define_method("#{name}="){|val|
|
11
|
+
raise("invalid value nil") unless val
|
12
|
+
raise("must be a String #{val}") unless val.is_a?(String)
|
13
|
+
raise("incorrect length: #{val}") unless (val.length*8) <= len
|
14
|
+
self.instance_variable_set("@#{name}", val)
|
15
|
+
}
|
16
|
+
|
17
|
+
define_method("#{name}") {
|
18
|
+
self.instance_variable_get("@#{name}") || "\x00" * (len/8)
|
19
|
+
}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse tlv, bytes, _len
|
24
|
+
val = bytes[0, length/8]
|
25
|
+
rest = bytes[length/8, bytes.length]
|
26
|
+
# check val...
|
27
|
+
tlv.send("#{name}=", val)
|
28
|
+
rest
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end # module
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module TLV
|
2
|
+
class TLV
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def mand_tags
|
6
|
+
@mand_tags ||= (self == TLV ? [] : superclass.mand_tags.dup)
|
7
|
+
end
|
8
|
+
def opt_tags
|
9
|
+
@opt_tags ||= (self == TLV ? [] : superclass.opt_tags.dup)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Takes either a subclass of TLV or the following options, which are used to
|
13
|
+
# create an subclass.
|
14
|
+
# Options:
|
15
|
+
# :tag
|
16
|
+
# :display_name
|
17
|
+
#
|
18
|
+
# :classname (will be derived from display_name if not given)
|
19
|
+
# :accessor_name (will be derived from display_name if not given)
|
20
|
+
def mandatory tlv, accessor_name=nil
|
21
|
+
handle_subtag mand_tags, tlv, accessor_name
|
22
|
+
end
|
23
|
+
|
24
|
+
# for constructed tlv's, add subtags that may be present
|
25
|
+
def optional tlv, accessor_name=nil
|
26
|
+
handle_subtag opt_tags, tlv, accessor_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def register tlv
|
30
|
+
@tlv_classes ||= {}
|
31
|
+
warn "tag #{TLV.b2s(tlv.tag)} already defined!" if @tlv_classes[tlv.tag]
|
32
|
+
@tlv_classes[tlv.tag] = tlv
|
33
|
+
end
|
34
|
+
|
35
|
+
def lookup tag
|
36
|
+
return self if tag == self.tag
|
37
|
+
@tlv_classes ||= {}
|
38
|
+
tlv = @tlv_classes[tag]
|
39
|
+
if !tlv && ! (self == TLV)
|
40
|
+
warn "looking up tag #{TLV.b2s(tag)} in super!"
|
41
|
+
raise "bla"
|
42
|
+
tlv ||= super
|
43
|
+
end
|
44
|
+
tlv
|
45
|
+
end
|
46
|
+
|
47
|
+
# internal, common functionality for mndatory and optional
|
48
|
+
def handle_subtag arr, tlv, accessor_name
|
49
|
+
tlv = handle_options(tlv) if tlv.is_a? Hash
|
50
|
+
raise "#{tlv} must be a subclass of TLV!" unless tlv.ancestors.include? TLV
|
51
|
+
if accessor_name
|
52
|
+
tlv= tlv.dup
|
53
|
+
tlv.accessor_name= accessor_name
|
54
|
+
end
|
55
|
+
define_accessor(tlv)
|
56
|
+
|
57
|
+
register(tlv)
|
58
|
+
arr << tlv
|
59
|
+
end
|
60
|
+
|
61
|
+
def handle_options options
|
62
|
+
tag = options[:tag]
|
63
|
+
display_name = options[:display_name]
|
64
|
+
classname = options[:classname] || rubify_c(display_name)
|
65
|
+
new_class = self.const_set(classname, Class.new(TLV))
|
66
|
+
new_class.tlv(tag, display_name, options[:accessor_name])
|
67
|
+
new_class.raw
|
68
|
+
new_class
|
69
|
+
end
|
70
|
+
|
71
|
+
def rubify_a display
|
72
|
+
name = display.strip.gsub(/\s+/, "_")
|
73
|
+
name = name.downcase.to_sym
|
74
|
+
end
|
75
|
+
|
76
|
+
def rubify_c display
|
77
|
+
name = display.gsub(/\s+/, "")
|
78
|
+
end
|
79
|
+
|
80
|
+
def define_accessor tlv_class
|
81
|
+
s = tlv_class
|
82
|
+
# check we are actually creating an accessor for an TLV
|
83
|
+
while s = s.superclass
|
84
|
+
break if s == TLV
|
85
|
+
end
|
86
|
+
raise "not a TLV class!" unless s
|
87
|
+
|
88
|
+
# determine the accessor name
|
89
|
+
# currently the call graph of this method ensures the class
|
90
|
+
# will have an accessor name.
|
91
|
+
name = tlv_class.accessor_name
|
92
|
+
|
93
|
+
define_method("#{name}="){ |val|
|
94
|
+
# must either be an instance of tlv_val
|
95
|
+
# or a raw value.
|
96
|
+
if val.is_a? TLV
|
97
|
+
self.instance_variable_set("@#{name}", val)
|
98
|
+
else
|
99
|
+
v = tlv_class.new
|
100
|
+
# _should_ be a String, but we'll bang anything
|
101
|
+
# into value for now...
|
102
|
+
v.value = val.to_s
|
103
|
+
self.instance_variable_set("@#{name}", v)
|
104
|
+
end
|
105
|
+
}
|
106
|
+
|
107
|
+
define_method("#{name}") {
|
108
|
+
self.instance_variable_get("@#{name}")
|
109
|
+
}
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end #module
|