diff options
author | Björn Gustavsson <[email protected]> | 2012-12-04 07:23:15 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2012-12-06 14:22:37 +0100 |
commit | b38a42c5eacceee57333e26948216d199c123e84 (patch) | |
tree | 27d2dab58bf90738ab3d7415df45d837f8725035 /lib/asn1/src/asn1ct_imm.erl | |
parent | 9f83121db1cea3f9b3a8f87435b1767285556ab6 (diff) | |
download | otp-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.erl | 55 |
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), |