codec 0.0.12 → 1.0.0
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/.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
|