aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-12-04 07:23:15 +0100
committerBjörn Gustavsson <[email protected]>2012-12-06 14:22:37 +0100
commitb38a42c5eacceee57333e26948216d199c123e84 (patch)
tree27d2dab58bf90738ab3d7415df45d837f8725035 /lib/asn1/src
parent9f83121db1cea3f9b3a8f87435b1767285556ab6 (diff)
downloadotp-b38a42c5eacceee57333e26948216d199c123e84.tar.gz
otp-b38a42c5eacceee57333e26948216d199c123e84.tar.bz2
otp-b38a42c5eacceee57333e26948216d199c123e84.zip
Optimize decoding of OCTET STRINGs
Decoding of fragmented OCTET STRINGs was only implemented when the size was constrained to a single value. While at it, support decoding fragmented OCTET STRINGS in all circumstances.
Diffstat (limited to 'lib/asn1/src')
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl16
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl13
-rw-r--r--lib/asn1/src/asn1ct_imm.erl55
-rw-r--r--lib/asn1/src/asn1rt_per_bin_rt2ct.erl21
-rw-r--r--lib/asn1/src/asn1rt_uper_bin.erl19
5 files changed, 108 insertions, 16 deletions
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index eab0f62ecf..79cff2eae2 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -297,6 +297,16 @@ emit_enc_enumerated_case(_Per,C, {0,EnumName}, Count) ->
emit_enc_enumerated_case(_Erule, C, EnumName, Count) ->
emit(["'",EnumName,"' -> ?RT_PER:encode_integer(",{asis,C},", ",Count,")"]).
+get_constraint([{Key,V}], Key) ->
+ V;
+get_constraint([], _) ->
+ no;
+get_constraint(C, Key) ->
+ case lists:keyfind(Key, 1, C) of
+ false -> no;
+ {Key,V} -> V
+ end.
+
%% Object code generating for encoding and decoding
%% ------------------------------------------------
@@ -1181,8 +1191,10 @@ gen_dec_prim(Erules,Att,BytesVar) ->
Imm = asn1ct_imm:per_dec_boolean(),
asn1ct_imm:dec_code_gen(Imm, BytesVar);
'OCTET STRING' ->
- emit({"?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,Constraint},")"});
+ SzConstr = get_constraint(Constraint, 'SizeConstraint'),
+ Imm0 = asn1ct_imm:per_dec_octet_string(SzConstr, Aligned),
+ Imm = {convert,binary_to_list,Imm0},
+ asn1ct_imm:dec_code_gen(Imm, BytesVar);
'NumericString' ->
emit({"?RT_PER:decode_NumericString(",BytesVar,",",
{asis,Constraint},")"});
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 00faa805e5..ecd212c3e3 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -450,17 +450,6 @@ emit_enc_octet_string(_Erules,Constraint,Value) ->
emit({" ?RT_PER:encode_octet_string(",{asis,C},",false,",Value,")",nl})
end.
-emit_dec_octet_string(Constraint,BytesVar) ->
- case get_constraint(Constraint,'SizeConstraint') of
- 0 ->
- emit({" {[],",BytesVar,"}",nl});
- {_,0} ->
- emit({" {[],",BytesVar,"}",nl});
- C ->
- emit({" ?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,C},",false)",nl})
- end.
-
emit_enc_integer_case(Value) ->
case get(component_type) of
{true,#'ComponentType'{prop=Prop}} ->
@@ -1543,7 +1532,7 @@ gen_dec_prim(Erules,Att,BytesVar) ->
asn1ct_gen_per:gen_dec_prim(Erules, Att, BytesVar);
'OCTET STRING' ->
- emit_dec_octet_string(Constraint,BytesVar);
+ asn1ct_gen_per:gen_dec_prim(Erules, Att, BytesVar);
'NumericString' ->
emit_dec_known_multiplier_string('NumericString',
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index 9cb4677ce3..1d1013b0a9 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -20,6 +20,7 @@
-module(asn1ct_imm).
-export([per_dec_boolean/0,per_dec_enumerated/2,per_dec_enumerated/3,
per_dec_integer/2,per_dec_length/3,per_dec_named_integer/3,
+ per_dec_octet_string/2,
dec_slim_cg/2,dec_code_gen/2]).
-export([effective_constraint/2]).
-import(asn1ct_gen, [emit/1]).
@@ -85,10 +86,47 @@ per_dec_named_integer(Constraint, NamedList0, Aligned) ->
NamedList = [{K,V} || {V,K} <- NamedList0] ++ [integer_default],
{map,Int,NamedList}.
+per_dec_octet_string(Constraint, Aligned) ->
+ dec_string(Constraint, 8, Aligned).
+
%%%
%%% Local functions.
%%%
+
+dec_string(Sv, U, _Aligned) when is_integer(Sv), U*Sv =< 16 ->
+ {get_bits,Sv,[U,binary]};
+dec_string(Sv, U, Aligned) when is_integer(Sv), Sv < 16#10000 ->
+ {get_bits,Sv,[U,binary,{align,Aligned}]};
+dec_string(C, U, Aligned) when is_list(C) ->
+ dec_string({hd(C),lists:max(C)}, U, Aligned);
+dec_string({Sv,Sv}, U, Aligned) ->
+ dec_string(Sv, U, Aligned);
+dec_string({{_,_}=C,_}, U, Aligned) ->
+ bit_case(dec_string(C, U, Aligned),
+ dec_string(no, U, Aligned));
+dec_string({Lb,Ub}, U, Aligned) when Ub < 16#10000 ->
+ Len = per_dec_constrained(Lb, Ub, Aligned),
+ {get_bits,Len,[U,binary,{align,Aligned}]};
+dec_string(_, U, Aligned) ->
+ Al = [{align,Aligned}],
+ DecRest = fun(V, Buf) ->
+ emit(["?RT_PER:decode_fragmented(",V,", ",
+ Buf,", ",U,")"])
+ end,
+ {'case',[{test,{get_bits,1,[1|Al]},0,
+ {value,{get_bits,
+ {get_bits,7,[1]},
+ [U,binary]}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},0,
+ {value,{get_bits,
+ {get_bits,14,[1]},
+ [U,binary]}}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},1,
+ {value,{call,DecRest,{get_bits,6,[1]}}}}}]}.
+
per_dec_enumerated_fix_list([{V,_}|T], Tail, N) ->
[{N,V}|per_dec_enumerated_fix_list(T, Tail, N+1)];
per_dec_enumerated_fix_list([], Tail, _) -> Tail.
@@ -208,7 +246,15 @@ flatten({map,E0,Cs0}, Buf0, St0) ->
flatten({value,V0}, Buf0, St0) when is_integer(V0) ->
{{V0,Buf0},[],St0};
flatten({value,V0}, Buf0, St0) ->
- flatten(V0, Buf0, St0).
+ flatten(V0, Buf0, St0);
+flatten({convert,Op,E0}, Buf0, St0) ->
+ {{E,Buf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var("Conv", St1),
+ {{Dst,Buf},Pre++[{convert,Op,E,Dst}],St2};
+flatten({call,Fun,E0}, Buf0, St0) ->
+ {Src,Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var_pair(St1),
+ {Dst,Pre++[{call,Fun,Src,Dst}],St2}.
flatten_cs([C0|Cs0], Buf, St0) ->
{C,Pre,St1} = flatten(C0, Buf, St0),
@@ -295,6 +341,13 @@ dcg_list_outside([{add,S1,S2,Dst}|T]) ->
dcg_list_outside([{return,{V,Buf}}|T]) ->
emit(["{",V,",",Buf,"}"]),
iter_dcg_list_outside(T);
+dcg_list_outside([{call,Fun,{V,Buf},{Dst,DstBuf}}|T]) ->
+ emit(["{",Dst,",",DstBuf,"} = "]),
+ Fun(V, Buf),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{convert,Op,V,Dst}|T]) ->
+ emit([Dst," = ",Op,"(",V,")"]),
+ iter_dcg_list_outside(T);
dcg_list_outside([{get_bits,{_,Buf0},_,_}|_]=L0) ->
emit("<<"),
{L,Buf} = dcg_list_inside(L0, buf),
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
index a7536ee88b..e035ca49d1 100644
--- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
+++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
@@ -22,6 +22,7 @@
-include("asn1_records.hrl").
+-export([decode_fragmented/3]).
-export([dec_fixup/3]).
-export([setchoiceext/1, setext/1, fixoptionals/3, fixextensions/2,
getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
@@ -39,7 +40,6 @@
encode_relative_oid/1, decode_relative_oid/1,
complete/1]).
-
-export([encode_open_type/2, decode_open_type/2]).
-export([encode_GeneralString/2, decode_GeneralString/2,
@@ -1392,6 +1392,25 @@ decode_octet_string(Bytes,no,false) ->
%% Bytes3 = align(Bytes2),
getoctets_as_list(Bytes2,Len).
+decode_fragmented(SegSz0, Buf0, Unit) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Res:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ decode_fragmented_1(Buf, Unit, Res).
+
+decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Frag:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ Res = <<Res0/bitstring,Frag/bitstring>>,
+ decode_fragmented_1(Buf, Unit, Res).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Restricted char string types
diff --git a/lib/asn1/src/asn1rt_uper_bin.erl b/lib/asn1/src/asn1rt_uper_bin.erl
index 2cd68c62a0..afb3cb28d9 100644
--- a/lib/asn1/src/asn1rt_uper_bin.erl
+++ b/lib/asn1/src/asn1rt_uper_bin.erl
@@ -25,6 +25,7 @@
%%-compile(export_all).
+-export([decode_fragmented/3]).
-export([setext/1, fixoptionals/3,
fixextensions/2,
getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
@@ -1119,6 +1120,24 @@ decode_octet_string1(Bytes,no) ->
{Len,Bytes2} = decode_length(Bytes,undefined),
getoctets_as_list(Bytes2,Len).
+decode_fragmented(SegSz0, Buf0, Unit) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Res:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ decode_fragmented_1(Buf, Unit, Res).
+
+decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Frag:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ Res = <<Res0/bitstring,Frag/bitstring>>,
+ decode_fragmented_1(Buf, Unit, Res).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%