codec 0.0.12 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Rakefile +6 -0
- data/codec.gemspec +1 -1
- data/lib/codec.rb +8 -0
- data/lib/codec/base.rb +8 -47
- data/lib/codec/bitmap.rb +42 -36
- data/lib/codec/composed.rb +39 -66
- data/lib/codec/field.rb +1 -1
- data/lib/codec/fix.rb +83 -65
- data/lib/codec/logger.rb +2 -2
- data/lib/codec/packed.rb +40 -91
- data/lib/codec/prefix.rb +71 -71
- data/lib/codec/tlv.rb +116 -111
- data/lib/codec/version.rb +1 -1
- data/test/lib/codec/bitmap_test.rb +29 -20
- data/test/lib/codec/composed_test.rb +37 -23
- data/test/lib/codec/eightbits_test.rb +18 -14
- data/test/lib/codec/fix_test.rb +47 -35
- data/test/lib/codec/pckd_test.rb +33 -37
- data/test/lib/codec/prefix_test.rb +45 -67
- data/test/lib/codec/tlv_test.rb +41 -36
- data/test/test_helper.rb +3 -0
- metadata +14 -14
data/lib/codec/logger.rb
CHANGED
data/lib/codec/packed.rb
CHANGED
@@ -1,109 +1,58 @@
|
|
1
1
|
module Codec
|
2
2
|
class Packed < Base
|
3
|
-
def
|
4
|
-
|
3
|
+
def initialize(length, isNumeric = true, isLeftPadded=false, isFPadded = false)
|
4
|
+
@length = length
|
5
|
+
@isNum = isNumeric
|
6
|
+
@fPad = isFPadded
|
7
|
+
@lPad = isLeftPadded
|
5
8
|
end
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def encode_with_length(field)
|
16
|
-
return get_length(field),encode(field)
|
17
|
-
end
|
18
|
-
|
19
|
-
def decode_with_length(buf,length)
|
20
|
-
l = eval_length(buf,get_pck_length(length))
|
21
|
-
return build_field(buf,l),buf[l,buf.length]
|
22
|
-
end
|
23
|
-
|
24
|
-
def decode(buf)
|
25
|
-
return decode_with_length(buf,@length)
|
26
|
-
end
|
27
|
-
end
|
10
|
+
# No more required encode return the field length for upper codec layer
|
11
|
+
# def get_length(field)
|
12
|
+
# if @length > 0
|
13
|
+
# return @length
|
14
|
+
# else
|
15
|
+
# return field.get_value.to_s.length
|
16
|
+
# end
|
17
|
+
# end
|
28
18
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
19
|
+
def check_length(buf,length)
|
20
|
+
raise "Length is nil" if length.nil?
|
21
|
+
if(length != 0)
|
22
|
+
if buf.length < length
|
23
|
+
raise BufferUnderflow, "Not enough data for decoding (#{length}/#{buf.length})"
|
24
|
+
end
|
25
|
+
return length
|
36
26
|
else
|
37
|
-
|
27
|
+
return buf.length
|
38
28
|
end
|
39
|
-
|
40
|
-
return f,buf[l,buf.length]
|
41
|
-
end
|
29
|
+
end
|
42
30
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
out = [out].pack("H*")
|
52
|
-
return out
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class Strpck < Packed
|
57
|
-
def decode_with_length(buf,length)
|
58
|
-
l = eval_length(buf,get_pck_length(length))
|
59
|
-
f = Field.new(@id)
|
60
|
-
val = buf[0,l].unpack("H*").first
|
61
|
-
if @length.odd?
|
62
|
-
val.chop!
|
63
|
-
else
|
64
|
-
val.chop! if length.odd?
|
65
|
-
end
|
66
|
-
f.set_value(val)
|
67
|
-
return f,buf[l,buf.length]
|
31
|
+
def decode(buf,f, length = nil)
|
32
|
+
length ||= @length
|
33
|
+
l = check_length(buf,(length + 1) / 2)
|
34
|
+
val = buf.slice!(0...l).unpack("H*").first
|
35
|
+
# remove padding if odd length
|
36
|
+
( @lPad ? val.chop! : val.slice!(0) ) if @length.odd? || length.odd?
|
37
|
+
val = val.to_i if @isNum
|
38
|
+
f.set_value(val)
|
68
39
|
end
|
69
|
-
|
70
|
-
def encode(field)
|
40
|
+
|
41
|
+
def encode(buf, field)
|
71
42
|
out = field.get_value.to_s
|
43
|
+
Logger.debug{ "Encode packed #{out} on #{@length} [#{@isNum}|#{@fPad}|#{@lPad}]" }
|
44
|
+
padding = (@fPad ? "F" : "0")
|
72
45
|
if @length > 0
|
73
|
-
out = out.ljust(@length,
|
74
|
-
raise TooLongDataException if out.length > @length
|
75
|
-
end
|
76
|
-
l = out.length
|
77
|
-
out += "F" if out.length.odd?
|
78
|
-
out = [out].pack("H*")
|
79
|
-
return out
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
class Nstpck < Packed
|
84
|
-
def decode_with_length(buf,length)
|
85
|
-
l = eval_length(buf,get_pck_length(length))
|
86
|
-
f = Field.new(@id)
|
87
|
-
val = buf[0,l].unpack("H*").first
|
88
|
-
if @length.odd?
|
89
|
-
val = val[1,val.length]
|
90
|
-
else
|
91
|
-
val = val[1,val.length] if length.odd?
|
92
|
-
end
|
93
|
-
f.set_value(val)
|
94
|
-
return f,buf[l,buf.length]
|
95
|
-
end
|
96
|
-
|
97
|
-
def encode(field)
|
98
|
-
out = field.get_value
|
99
|
-
if @length > 0
|
100
|
-
out = out.rjust(@length,"0")
|
46
|
+
out = (@lPad ? out.ljust(@length,padding) : out.rjust(@length,padding))
|
101
47
|
raise TooLongDataException if out.length > @length
|
102
48
|
end
|
103
49
|
l = out.length
|
104
|
-
|
50
|
+
# handle padding if odd length
|
51
|
+
(@lPad ? out << padding : out.prepend(padding) )if out.length.odd?
|
52
|
+
Logger.debug{ "before packing : #{out}" }
|
105
53
|
out = [out].pack("H*")
|
106
|
-
|
54
|
+
buf << out
|
55
|
+
return l
|
107
56
|
end
|
108
57
|
end
|
109
58
|
|
data/lib/codec/prefix.rb
CHANGED
@@ -1,60 +1,51 @@
|
|
1
1
|
module Codec
|
2
2
|
class Prefixedlength < Base
|
3
|
-
def initialize(
|
3
|
+
def initialize(length,content)
|
4
4
|
# TODO : Check that value_codec has a null length attribute
|
5
5
|
@length_codec = length
|
6
6
|
@value_codec = content
|
7
|
-
@id = id
|
8
7
|
end
|
9
8
|
|
10
9
|
def get_length(length_field)
|
11
10
|
length_field.get_value.to_i
|
12
11
|
end
|
13
12
|
|
14
|
-
def decode(buffer)
|
15
|
-
|
16
|
-
|
13
|
+
def decode(buffer, f, length=nil)
|
14
|
+
Logger.warn {"Call decode with length on Prefixedlength codec should never happen"} unless length.nil?
|
15
|
+
len_field = Field.new
|
16
|
+
@length_codec.decode(buffer,len_field)
|
17
|
+
len = get_length(len_field)
|
17
18
|
if len == 0
|
18
|
-
|
19
|
-
f.set_id(@id)
|
20
|
-
f.set_value(nil)
|
21
|
-
return f,buf
|
19
|
+
f.set_value("")
|
22
20
|
else
|
23
21
|
begin
|
24
|
-
|
22
|
+
@value_codec.decode(buffer, f, len)
|
25
23
|
rescue => e
|
26
|
-
Logger.error "Error
|
24
|
+
Logger.error "Error when decoding field #{f.get_id} \n #{e.message}\n#{e.backtrace.join(10.chr)}"
|
27
25
|
raise ParsingException.new e.message
|
28
26
|
end
|
29
|
-
|
30
|
-
f.set_id(@id)
|
31
|
-
return f,remain
|
32
27
|
end
|
33
28
|
end
|
34
|
-
|
35
|
-
def build_field(buf,length)
|
36
|
-
begin
|
37
|
-
f,r = decode(buf[0,length])
|
38
|
-
rescue BufferUnderflow => e
|
39
|
-
raise ParsingException.new e.message
|
40
|
-
end
|
41
|
-
Logger.error "Error remain data in Prefixedlength" if r != ""
|
42
|
-
return f
|
43
|
-
end
|
44
29
|
|
45
|
-
def encode(field)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
30
|
+
def encode(buf, field)
|
31
|
+
out = ""
|
32
|
+
content_buf = ""
|
33
|
+
len = @value_codec.encode(content_buf, field)
|
34
|
+
@length_codec.encode(out, Field.new.set_value(len))
|
35
|
+
out << content_buf
|
36
|
+
buf << out
|
37
|
+
return out.length
|
50
38
|
end
|
51
39
|
end
|
52
40
|
|
53
41
|
class Headerlength < Prefixedlength
|
54
|
-
def initialize(
|
42
|
+
def initialize(header,header_id,content,content_id,length_path,total_length = false)
|
43
|
+
@header_id = header_id
|
44
|
+
@content_id = content_id
|
55
45
|
@path = length_path # length attribute contain the path for length field in header
|
56
46
|
@separator = @path.slice!(0).chr # first character contain the separator
|
57
|
-
|
47
|
+
@total_length = total_length # indicate that length in header is equal to (header + content) length
|
48
|
+
super(header,content)
|
58
49
|
end
|
59
50
|
|
60
51
|
def get_length(header_field)
|
@@ -66,68 +57,77 @@ module Codec
|
|
66
57
|
length_field.get_value.to_i
|
67
58
|
end
|
68
59
|
end
|
69
|
-
|
70
|
-
def decode(buffer)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
|
61
|
+
def decode(buffer, f, length=nil)
|
62
|
+
f.set_value("") # reinit field value
|
63
|
+
buffer = buffer.slice!(0...length) if length && length > 0
|
64
|
+
initial_len = buffer.size
|
65
|
+
head = Field.new(@header_id)
|
66
|
+
content = Field.new(@content_id)
|
67
|
+
@length_codec.decode(buffer,head)
|
68
|
+
h_len = initial_len - buffer.size
|
75
69
|
f.add_sub_field(head)
|
76
70
|
len = get_length(head)
|
77
|
-
if len
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
val,remain = @value_codec.decode_with_length(buf,len)
|
82
|
-
val.set_id(@value_codec.id)
|
83
|
-
f.add_sub_field(val)
|
84
|
-
return f,remain
|
71
|
+
if len > 0
|
72
|
+
len -= h_len if @total_length
|
73
|
+
@value_codec.decode(buffer, content, len)
|
74
|
+
f.add_sub_field(content)
|
85
75
|
end
|
86
76
|
end
|
87
77
|
|
88
|
-
def encode(field)
|
78
|
+
def encode(buf, field)
|
89
79
|
# encode content
|
90
|
-
|
91
|
-
length
|
92
|
-
|
93
|
-
|
80
|
+
content_buf = ""
|
81
|
+
length = 0
|
82
|
+
content = field.get_sub_field(@content_id)
|
83
|
+
length = @value_codec.encode(content_buf, content) unless content.nil?
|
84
|
+
head = field.get_sub_field(@header_id)
|
85
|
+
raise EncodingException.new "Missing header for encoding #{@id}" if head.empty?
|
94
86
|
# update length field in header if length !=0
|
95
|
-
|
87
|
+
head.set_value(length,@path,@separator) if length !=0
|
96
88
|
# encode header
|
97
|
-
|
98
|
-
|
89
|
+
head_buf = ""
|
90
|
+
h_len = @length_codec.encode(head_buf,head)
|
91
|
+
# TODO : optimize computation for header length
|
92
|
+
if length != 0 && @total_length # re-encode header with total length
|
93
|
+
length = head_buf.length + content_buf.length
|
94
|
+
head.set_value(length,@path,@separator)
|
95
|
+
head_buf = ""
|
96
|
+
@length_codec.encode(head_buf,head)
|
97
|
+
end
|
98
|
+
buf << head_buf
|
99
|
+
buf << content_buf
|
100
|
+
return head_buf.length + content_buf.length
|
99
101
|
end
|
100
102
|
end
|
101
|
-
|
102
|
-
class Headerfulllength < Headerlength
|
103
|
-
# TODO : to implement
|
104
|
-
end
|
105
103
|
|
106
104
|
class Tagged < Base
|
107
|
-
def initialize(
|
105
|
+
def initialize(tag_codec)
|
108
106
|
@subCodecs = {}
|
109
107
|
@tag_codec = tag_codec
|
110
|
-
@id = id
|
111
108
|
end
|
112
|
-
|
113
|
-
def decode(buffer)
|
114
|
-
|
109
|
+
|
110
|
+
def decode(buffer, field, length = nil)
|
111
|
+
buffer = buffer.slice!(0...length) if length && length > 0
|
112
|
+
tag = Field.new("TAG")
|
113
|
+
@tag_codec.decode(buffer,tag)
|
114
|
+
field.set_id(tag.get_value.to_s)
|
115
115
|
if @subCodecs[tag.get_value.to_s].nil?
|
116
|
-
raise ParsingException.new "Unknown tag #{tag.get_value.to_s}
|
116
|
+
raise ParsingException.new "Unknown tag #{tag.get_value.to_s} when decoding #{field.get_id}"
|
117
117
|
end
|
118
|
-
|
119
|
-
f.set_id(tag.get_value.to_s)
|
120
|
-
return f,buf
|
118
|
+
@subCodecs[tag.get_value.to_s].decode(buffer,field)
|
121
119
|
end
|
122
120
|
|
123
|
-
def encode(field)
|
124
|
-
head = Field.new(
|
125
|
-
out =
|
121
|
+
def encode(buffer, field)
|
122
|
+
head = Field.new("tag", field.get_id)
|
123
|
+
out = ""
|
124
|
+
@tag_codec.encode(out, head)
|
126
125
|
if @subCodecs[field.get_id].nil?
|
127
126
|
raise EncodingException.new "Unknown tag #{field.get_id} for #{@id} encoder"
|
128
127
|
end
|
129
|
-
|
130
|
-
|
128
|
+
@subCodecs[field.get_id].encode(out, field)
|
129
|
+
buffer << out
|
130
|
+
return out.length
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
data/lib/codec/tlv.rb
CHANGED
@@ -1,120 +1,162 @@
|
|
1
1
|
module Codec
|
2
2
|
class Tlv < Prefixedlength
|
3
|
-
def initialize(
|
4
|
-
super(
|
5
|
-
unless header.kind_of?(Codec::Base)
|
6
|
-
raise InitializeException," Invalid tag codec for Tlv class"
|
7
|
-
end
|
3
|
+
def initialize(length,header,content)
|
4
|
+
super(length,content)
|
8
5
|
@tag_codec = header
|
9
6
|
@subCodecs = {}
|
10
7
|
end
|
11
|
-
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
|
9
|
+
def check_length(buf,length)
|
10
|
+
raise "Length is nil" if length.nil?
|
11
|
+
if(length != 0)
|
12
|
+
if buf.length < length
|
13
|
+
raise BufferUnderflow, "Not enough data for decoding (#{length}/#{buf.length})"
|
14
|
+
end
|
15
|
+
return length
|
16
|
+
else
|
17
|
+
return buf.length
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
|
-
def encode(field)
|
21
|
+
def encode(buf, field)
|
20
22
|
out = ""
|
21
23
|
fields = field.get_value
|
22
24
|
fields.each do |sf|
|
23
|
-
|
25
|
+
@tag_codec.encode(out, Field.new('*',sf.get_id))
|
24
26
|
if @subCodecs[sf.get_id]
|
25
|
-
content =
|
26
|
-
|
27
|
-
out
|
27
|
+
content = ""
|
28
|
+
len = @subCodecs[sf.get_id].encode(content, sf)
|
29
|
+
@length_codec.encode(out, Field.new('*',len))
|
30
|
+
out << content
|
28
31
|
else
|
29
|
-
out
|
32
|
+
super(out, sf)
|
30
33
|
end
|
31
34
|
end
|
32
|
-
|
35
|
+
buf << out
|
36
|
+
return out.length
|
33
37
|
end
|
34
|
-
|
35
|
-
def decode(buffer)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
38
|
+
|
39
|
+
def decode(buffer, msg, length = nil)
|
40
|
+
unless length.nil?
|
41
|
+
l = check_length(buffer,length)
|
42
|
+
buffer = buffer.slice!(0...l)
|
43
|
+
end
|
44
|
+
|
45
|
+
tag = Field.new
|
46
|
+
begin
|
47
|
+
until buffer.empty?
|
48
|
+
begin
|
49
|
+
@tag_codec.decode(buffer,tag)
|
50
|
+
rescue
|
51
|
+
raise ParsingException, "Tlv Codec still remaining data but failed to decode tag when decoding field #{msg.get_id}"
|
52
|
+
end
|
53
|
+
Logger.debug { "Decoding tag #{tag.get_value.to_s}"}
|
54
|
+
sf = Field.new(tag.get_value.to_s)
|
55
|
+
subcodec = @subCodecs[tag.get_value.to_s]
|
56
|
+
if subcodec.nil?
|
57
|
+
Logger.debug { "using default codec for tag #{tag.get_value.to_s}"}
|
58
|
+
super(buffer,sf)
|
51
59
|
else
|
52
|
-
|
53
|
-
|
60
|
+
Logger.debug { "using predefined codec for tag #{tag.get_value.to_s}"}
|
61
|
+
len_field = Field.new("len")
|
62
|
+
@length_codec.decode(buffer,len_field)
|
63
|
+
subcodec.decode(buffer,sf,len_field.get_value.to_i)
|
54
64
|
end
|
55
|
-
|
56
|
-
|
57
|
-
val.set_value("Buffer underflow when parsing this tag : #{e.message} [#{buffer.unpack("H*").first}]")
|
58
|
-
buffer = ""
|
59
|
-
rescue
|
60
|
-
val = Field.new
|
61
|
-
val.set_value("Parsing error [#{buffer.unpack("H*").first}]")
|
62
|
-
buffer = ""
|
65
|
+
Logger.debug { "Add field #{sf} to tlv"}
|
66
|
+
msg.add_sub_field(sf)
|
63
67
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
68
|
+
rescue BufferUnderflow => e
|
69
|
+
raise ParsingException, "Tlv Codec failed to decode field #{msg.get_id}"
|
70
|
+
val = Field.new
|
71
|
+
val.set_value("Buffer underflow when parsing tlv #{msg.get_id} [#{buffer.unpack("H*").first}]")
|
72
|
+
buffer.clear
|
73
|
+
end
|
74
|
+
unless buffer.empty? || length.nil?
|
75
|
+
Logger.warn("Remain data in a tlv buffer :[#{buffer.unpack("H*").first}]")
|
67
76
|
end
|
68
|
-
return msg,buffer
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
72
80
|
class Bertlv < Base
|
73
|
-
|
74
|
-
|
81
|
+
|
82
|
+
def initialize
|
75
83
|
@length = 0
|
76
84
|
end
|
85
|
+
|
86
|
+
def decode(buf,msg,length=nil)
|
87
|
+
length ||= buf.length
|
88
|
+
buffer = buf.slice!(0...length)
|
89
|
+
until buffer.empty?
|
90
|
+
sf = Field.new(tag_decode(buffer))
|
91
|
+
val = value_decode(buffer, length_decode(buffer))
|
92
|
+
sf.set_value(val)
|
93
|
+
msg.add_sub_field(sf)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def encode(buf, field)
|
98
|
+
out = ""
|
99
|
+
subfields = field.get_value
|
100
|
+
unless subfields.kind_of?(Array)
|
101
|
+
raise EncodingException, "Invalid field #{field.to_yaml} for BER Tlv encoding"
|
102
|
+
end
|
103
|
+
|
104
|
+
while subfields.size > 0
|
105
|
+
subfield = subfields.shift
|
106
|
+
out << tag_encode(subfield.get_id)
|
107
|
+
# TODO : Handle value that is not String
|
108
|
+
value = value_encode(subfield.get_value)
|
109
|
+
out << length_encode(value.length)
|
110
|
+
out << value
|
111
|
+
end
|
112
|
+
buf << out
|
113
|
+
return out.length
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
77
117
|
|
78
|
-
def tag_decode(
|
79
|
-
buf = buffer.dup
|
118
|
+
def tag_decode(buf)
|
80
119
|
# removing trailling bytes
|
81
|
-
|
120
|
+
b = 0
|
121
|
+
while (b == 0 || b == 255)
|
122
|
+
b = buf.slice!(0).bytes.first
|
123
|
+
end
|
82
124
|
tag = b.chr
|
83
125
|
if (b & 0x1F == 0x1F)
|
84
126
|
begin
|
85
|
-
nb = buf.slice!(0).
|
86
|
-
tag
|
127
|
+
nb = buf.slice!(0).bytes.first
|
128
|
+
tag << nb.chr
|
87
129
|
end while nb & 0x80 == 0x80
|
88
130
|
end
|
89
|
-
return tag.unpack("H*").first.upcase
|
131
|
+
return tag.unpack("H*").first.upcase
|
90
132
|
end
|
91
133
|
|
92
134
|
def tag_encode(tag)
|
93
135
|
buf = [tag].pack("H*")
|
94
|
-
|
95
|
-
|
136
|
+
pack_tag = buf.dup
|
137
|
+
check_tag = tag_decode(buf)
|
138
|
+
unless tag == check_tag && buf.empty?
|
96
139
|
raise EncodingException, "Invalid BER tag [#{tag}]"
|
97
140
|
end
|
98
|
-
return
|
141
|
+
return pack_tag
|
99
142
|
end
|
100
143
|
|
101
|
-
def length_decode(
|
102
|
-
|
103
|
-
b = buf.slice!(0).getbyte(0)
|
144
|
+
def length_decode(buf)
|
145
|
+
b = buf.slice!(0).bytes.first
|
104
146
|
if b & 0x80 == 0x80
|
105
|
-
# Compute lenght of encoding length
|
147
|
+
# Compute lenght of encoding length
|
148
|
+
# Sample if first byte is 83 then lenth is encode
|
106
149
|
# on 3 bytes
|
107
150
|
loencl = b & 0x7F
|
108
|
-
lb = buf
|
109
|
-
buf = buf[loencl,buf.length]
|
151
|
+
lb = buf.slice!(0...loencl)
|
110
152
|
length = 0
|
111
|
-
|
153
|
+
lb.bytes.each do |len_byte|
|
112
154
|
length *= 256
|
113
|
-
length +=
|
155
|
+
length += len_byte
|
114
156
|
end
|
115
|
-
return length
|
157
|
+
return length
|
116
158
|
else
|
117
|
-
return b
|
159
|
+
return b
|
118
160
|
end
|
119
161
|
end
|
120
162
|
|
@@ -123,59 +165,22 @@ module Codec
|
|
123
165
|
if out.length > 127
|
124
166
|
raise EncodingException,"Invalid length for BER Tlv #{length}"
|
125
167
|
elsif out.length > 1
|
126
|
-
out
|
168
|
+
out.prepend((128 + out.length).chr)
|
127
169
|
end
|
128
170
|
return out
|
129
171
|
end
|
130
172
|
|
131
|
-
def value_decode(buf,length)
|
173
|
+
def value_decode(buf, length)
|
132
174
|
if length > buf.length
|
133
175
|
raise BufferUnderflow.new "Not enough data for parsing BER TLV
|
134
176
|
#{@id} length value #{length} remaining only #{buf.length}"
|
135
177
|
end
|
136
|
-
value = buf
|
137
|
-
|
138
|
-
return value.unpack("H*").first.upcase,buf
|
178
|
+
value = buf.slice!(0...length)
|
179
|
+
return value.unpack("H*").first.upcase
|
139
180
|
end
|
140
181
|
|
141
182
|
def value_encode(unpack_buffer)
|
142
183
|
[unpack_buffer].pack("H*")
|
143
184
|
end
|
144
|
-
|
145
|
-
def build_field(buf,length)
|
146
|
-
msg = Field.new(@id)
|
147
|
-
buffer = buf[0,length]
|
148
|
-
while buffer.length > 0
|
149
|
-
tag,buffer = tag_decode(buffer)
|
150
|
-
f = Field.new(tag)
|
151
|
-
value_length,buffer = length_decode(buffer)
|
152
|
-
value, buffer = value_decode(buffer,value_length)
|
153
|
-
f.set_value(value)
|
154
|
-
msg.add_sub_field(f)
|
155
|
-
end
|
156
|
-
return msg
|
157
|
-
end
|
158
|
-
|
159
|
-
def decode(buffer)
|
160
|
-
return build_field(buffer,buffer.length),""
|
161
|
-
end
|
162
|
-
|
163
|
-
def encode(field)
|
164
|
-
out = ""
|
165
|
-
subfields = field.get_value
|
166
|
-
unless subfields.kind_of?(Array)
|
167
|
-
raise EncodingException, "Invalid field #{field.to_yaml} for BER Tlv encoding"
|
168
|
-
end
|
169
|
-
|
170
|
-
while subfields.size > 0
|
171
|
-
subfield = subfields.shift
|
172
|
-
out += tag_encode(subfield.get_id)
|
173
|
-
# TODO : Handle value that is not String
|
174
|
-
value = value_encode(subfield.get_value)
|
175
|
-
out += length_encode(value.length)
|
176
|
-
out += value
|
177
|
-
end
|
178
|
-
return out
|
179
|
-
end
|
180
185
|
end
|
181
186
|
end
|