aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/asn1ct_imm.erl
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/asn1ct_imm.erl
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/asn1ct_imm.erl')
-rw-r--r--lib/asn1/src/asn1ct_imm.erl55
1 files changed, 54 insertions, 1 deletions
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),