diff options
author | Björn Gustavsson <[email protected]> | 2012-12-20 12:13:47 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2013-01-22 19:20:12 +0100 |
commit | 76ad80f52981449af3c79fdf5b298e4c8d817788 (patch) | |
tree | e717f03e019d2a8089e9adfe424b8700067a98bc | |
parent | fbcb7fe589edbfe79d10d7fe01be8a9f77926b89 (diff) | |
download | otp-76ad80f52981449af3c79fdf5b298e4c8d817788.tar.gz otp-76ad80f52981449af3c79fdf5b298e4c8d817788.tar.bz2 otp-76ad80f52981449af3c79fdf5b298e4c8d817788.zip |
Refactor decoding of BIT STRINGs
Refactor decoding of BIT STRINGs so that the run-time code does
not spend testing conditions that are known already at compile-time
(which wastes time and produces unnecessary Dialyzer warnings).
There are three ways to decode BIT STRINGs:
1) To a list of bit names (and {bit,Position} for unnamed positions)
if the BIT STRING type has any bit names.
2a) To a list of ones and zeros if there are no named bits, and the
compact_bit_string option was NOT given.
2b) To a {Unused,Bin} tuple if there are no named bits compact_bit_string
option WAS given.
Structure the decoding functions in the same way.
-rw-r--r-- | lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 31 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_per.erl | 30 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_imm.erl | 16 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_ber.erl | 140 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_per.erl | 198 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_per_common.erl | 33 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_uper.erl | 147 |
7 files changed, 145 insertions, 450 deletions
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 0826384365..e7414a2040 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -518,19 +518,8 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) -> need(decode_enumerated, 3); 'REAL' -> ok; - {'BIT STRING',NamedNumberList} -> - case get(compact_bit_string) of - true -> - emit(["decode_compact_bit_string(", - BytesVar,",",{asis,Constraint},",", - {asis,NamedNumberList},","]), - need(decode_compact_bit_string, 4); - _ -> - emit(["decode_bit_string(",BytesVar,",", - {asis,Constraint},",", - {asis,NamedNumberList},","]), - need(decode_bit_string, 4) - end; + {'BIT STRING',_NamedNumberList} -> + ok; 'NULL' -> emit(["decode_null(",BytesVar,","]), need(decode_null, 2); @@ -634,6 +623,8 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) -> _ when is_list(DoTag) -> {asis,DoTag} end, case NewTypeName of + {'BIT STRING',NNL} -> + gen_dec_bit_string(BytesVar, Constraint, NNL, TagStr); 'REAL' -> asn1ct_name:new(tmpbuf), emit(["begin",nl, @@ -660,6 +651,20 @@ int_constr(SingleValue,[]) -> SingleValue; int_constr(SV,VR) -> [SV,VR]. + +gen_dec_bit_string(BytesVar, _Constraint, [_|_]=NNL, TagStr) -> + call(decode_named_bit_string, + [BytesVar,{asis,NNL},TagStr]); +gen_dec_bit_string(BytesVar, Constraint, [], TagStr) -> + case get(compact_bit_string) of + true -> + call(decode_compact_bit_string, + [BytesVar,{asis,Constraint},TagStr]); + _ -> + call(decode_legacy_bit_string, + [BytesVar,{asis,Constraint},TagStr]) + end. + %% Object code generating for encoding and decoding %% ------------------------------------------------ diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 5dda5e9c5d..b7f3a12040 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -1088,6 +1088,28 @@ gen_dec_imm_1('ASN1_OPEN_TYPE', Constraint, Aligned) -> imm_decode_open_type(Constraint, Aligned); gen_dec_imm_1('ANY', _Constraint, Aligned) -> imm_decode_open_type([], Aligned); +gen_dec_imm_1({'BIT STRING',NNL}, Constr0, Aligned) -> + Constr = get_constraint(Constr0, 'SizeConstraint'), + Imm = asn1ct_imm:per_dec_raw_bitstring(Constr, Aligned), + {F,A} = case NNL of + [] -> + case get(compact_bit_string) of + true -> + {decode_compact_bit_string,1}; + _ -> + {decode_legacy_bit_string,1} + end; + [_|_] -> + {decode_named_bit_string,2} + end, + Dec = fun(V, Buf) -> + As = case A of + 1 -> [V]; + 2 -> [V,{asis,NNL}] + end, + emit(["{",{call,per_common,F,As},com,Buf,"}"]) + end, + {call,Dec,Imm}; gen_dec_imm_1('BOOLEAN', _Constr, _Aligned) -> asn1ct_imm:per_dec_boolean(); gen_dec_imm_1({'ENUMERATED',{Base,Ext}}, _Constr, Aligned) -> @@ -1120,14 +1142,6 @@ gen_dec_prim_1(Erule, #type{def=Typename,constraint=Constraint}=Att, BytesVar) -> case Typename of - {'BIT STRING',NamedNumberList} -> - Func = case get(compact_bit_string) of - true -> decode_compact_bit_string; - _ -> decode_bit_string - end, - call(Erule, Func, - [BytesVar,{asis,Constraint}, - {asis,NamedNumberList}]); 'NULL' -> emit({"{'NULL',",BytesVar,"}"}); 'OBJECT IDENTIFIER' -> diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index 384d4a86bb..7eb807aa5e 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -18,7 +18,8 @@ %% %% -module(asn1ct_imm). --export([per_dec_boolean/0,per_dec_enumerated/2,per_dec_enumerated/3, +-export([per_dec_raw_bitstring/2, + per_dec_boolean/0,per_dec_enumerated/2,per_dec_enumerated/3, per_dec_extension_map/1, per_dec_integer/2,per_dec_length/3,per_dec_named_integer/3, per_dec_octet_string/2,per_dec_open_type/1,per_dec_real/1]). @@ -103,6 +104,9 @@ per_dec_named_integer(Constraint, NamedList0, Aligned) -> per_dec_octet_string(Constraint, Aligned) -> dec_string(Constraint, 8, Aligned). +per_dec_raw_bitstring(Constraint, Aligned) -> + dec_string(Constraint, 1, Aligned). + per_dec_open_type(Aligned) -> {get_bits,decode_unconstrained_length(true, Aligned), [8,binary,{align,Aligned}]}. @@ -124,7 +128,7 @@ 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([_|_]=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); @@ -524,8 +528,6 @@ dcg_list_inside([{get_bits,{Sz,_},Fl0,{Dst,DstBuf}}|T], _) -> dcg_list_inside(T, DstBuf); dcg_list_inside(L, Dst) -> {L,Dst}. -bit_flags([1|T], Acc) -> - bit_flags(T, Acc); bit_flags([{align,_}|T], Acc) -> bit_flags(T, Acc); bit_flags([non_zero|T], Acc) -> @@ -537,7 +539,11 @@ bit_flags([H|T], Acc) -> bit_flags([], []) -> ""; bit_flags([], Acc) -> - "/" ++ bit_flags_1(Acc, ""). + case "/" ++ bit_flags_1(Acc, "") of + "/unit:1" -> []; + Opts -> Opts + end. + bit_flags_1([H|T], Sep) -> Sep ++ H ++ bit_flags_1(T, "-"); diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index f3f6875eb3..e086612818 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -29,8 +29,10 @@ encode_integer/2,encode_integer/3, decode_integer/3,decode_integer/4, encode_enumerated/2,decode_enumerated/3, - encode_bit_string/4,decode_bit_string/4, - decode_compact_bit_string/4, + encode_bit_string/4, + decode_named_bit_string/3, + decode_compact_bit_string/3, + decode_legacy_bit_string/3, decode_octet_string/3, encode_null/2,decode_null/2, encode_relative_oid/2,decode_relative_oid/2, @@ -1041,35 +1043,32 @@ unused_bitlist([Bit | Rest], Trail, Ack) -> %%============================================================================ %% decode bitstring value -%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} %%============================================================================ -decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags) -> - decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, - NamedNumberList, bin). - -decode_bit_string(Buffer, Range, NamedNumberList, Tags) -> - decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, - NamedNumberList, old). - +decode_compact_bit_string(Buffer, Range, Tags) -> + case match_and_collect(Buffer, Tags) of + <<0>> -> + check_restricted_string({0,<<>>}, 0, Range); + <<Unused,Bits/binary>> -> + Val = {Unused,Bits}, + Len = bit_size(Bits) - Unused, + check_restricted_string(Val, Len, Range) + end. -decode_bit_string2(<<0>>, _NamedNumberList, BinOrOld) -> - case BinOrOld of - bin -> - {0,<<>>}; - _ -> - [] - end; -decode_bit_string2(<<Unused,Bits/binary>>, NamedNumberList, BinOrOld) -> - case NamedNumberList of - [] -> - case BinOrOld of - bin -> - {Unused,Bits}; - _ -> - decode_bitstring2(byte_size(Bits), Unused, Bits) - end; - _ -> +decode_legacy_bit_string(Buffer, Range, Tags) -> + Val = case match_and_collect(Buffer, Tags) of + <<0>> -> + []; + <<Unused,Bits/binary>> -> + decode_bitstring2(byte_size(Bits), Unused, Bits) + end, + check_restricted_string(Val, length(Val), Range). + +decode_named_bit_string(Buffer, NamedNumberList, Tags) -> + case match_and_collect(Buffer, Tags) of + <<0>> -> + []; + <<Unused,Bits/binary>> -> BitString = decode_bitstring2(byte_size(Bits), Unused, Bits), decode_bitstring_NNL(BitString, NamedNumberList) end. @@ -1114,8 +1113,7 @@ decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) -> %% Octet string is decoded as a restricted string %%============================================================================ decode_octet_string(Buffer, Range, Tags) -> - decode_restricted_string(Buffer, Range, ?N_OCTET_STRING, - Tags, [], old). + decode_restricted_string(Buffer, Range, ?N_OCTET_STRING, Tags). %%============================================================================ %% Null value, ITU_T X.690 Chapter 8.8 @@ -1252,33 +1250,15 @@ encode_restricted_string(OctetList, TagIn) when is_list(OctetList) -> %%============================================================================ %% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings -%% (Buffer, Range, StringType, HasTag, TotalLen) -> -%% {String, Remain, RemovedBytes} %%============================================================================ -decode_restricted_string(Buffer, Range, StringType, Tags) -> - decode_restricted_string(Buffer, Range, StringType, Tags, [], old). - -decode_restricted_string(Tlv, Range, StringType, TagsIn, - NamedNumberList, BinOrOld) -> - Val = match_tags(Tlv, TagsIn), - Val2 = - case Val of - [_|_]=PartList -> % constructed val - Bin = collect_parts(PartList), - decode_restricted(Bin, StringType, - NamedNumberList, BinOrOld); - Bin -> - decode_restricted(Bin, StringType, - NamedNumberList, BinOrOld) - end, - check_and_convert_restricted_string(Val2, StringType, Range, - NamedNumberList, BinOrOld). +decode_restricted_string(Tlv, Range, StringType, TagsIn) -> + Bin = match_and_collect(Tlv, TagsIn), + Val = decode_restricted(Bin, StringType), + check_and_convert_restricted_string(Val, Range). -decode_restricted(Bin, StringType, NamedNumberList, BinOrOld) -> +decode_restricted(Bin, StringType) -> case StringType of - ?N_BIT_STRING -> - decode_bit_string2(Bin, NamedNumberList, BinOrOld); ?N_UniversalString -> mk_universal_string(binary_to_list(Bin)); ?N_BMPString -> @@ -1287,42 +1267,35 @@ decode_restricted(Bin, StringType, NamedNumberList, BinOrOld) -> Bin end. +check_and_convert_restricted_string(Val0, Range) -> + {Len,Val} = if is_binary(Val0) -> + {byte_size(Val0),binary_to_list(Val0)}; + is_list(Val0) -> + {length(Val0),Val0} + end, + check_restricted_string(Val, Len, Range). -check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) -> - {StrLen,NewVal} = case StringType of - ?N_BIT_STRING when NamedNumberList =/= [] -> - {no_check,Val}; - ?N_BIT_STRING when is_list(Val) -> - {length(Val),Val}; - ?N_BIT_STRING when is_tuple(Val) -> - {(byte_size(element(2,Val))*8) - element(1,Val),Val}; - _ when is_binary(Val) -> - {byte_size(Val),binary_to_list(Val)}; - _ when is_list(Val) -> - {length(Val), Val} - end, +check_restricted_string(Val, StrLen, Range) -> case Range of - _ when StrLen =:= no_check -> - NewVal; - [] -> % No length constraint - NewVal; + [] -> % No length constraint + Val; {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint - NewVal; + Val; {{Lb,_Ub},[]} when StrLen >= Lb -> - NewVal; + Val; {{Lb,_Ub},_Ext=[Min|_]} when StrLen >= Lb; StrLen >= Min -> - NewVal; + Val; {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1; StrLen =< Ub2, StrLen >= Lb2 -> - NewVal; + Val; StrLen -> % fixed length constraint - NewVal; + Val; {_,_} -> exit({error,{asn1,{length,Range,Val}}}); _Len when is_integer(_Len) -> exit({error,{asn1,{length,Range,Val}}}); _ -> % some strange constraint that we don't support yet - NewVal + Val end. @@ -1351,8 +1324,7 @@ mk_uni_list([H|T],List) -> %%=========================================================================== decode_universal_string(Buffer, Range, Tags) -> - decode_restricted_string(Buffer, Range, ?N_UniversalString, - Tags, [], old). + decode_restricted_string(Buffer, Range, ?N_UniversalString, Tags). mk_universal_string(In) -> @@ -1414,8 +1386,7 @@ mk_BMP_list([H|T], List) -> %% {String, Remain, RemovedBytes} %%============================================================================ decode_BMP_string(Buffer, Range, Tags) -> - decode_restricted_string(Buffer, Range, ?N_BMPString, - Tags, [], old). + decode_restricted_string(Buffer, Range, ?N_BMPString, Tags). mk_BMP_string(In) -> mk_BMP_string(In,[]). @@ -1563,6 +1534,15 @@ dynsort_decode_tag(<<_:1,PartialTag:7,Buffer/binary>>, TagAcc0) -> %% INTERNAL HELPER FUNCTIONS (not exported) %%------------------------------------------------------------------------- +match_and_collect(Tlv, TagsIn) -> + Val = match_tags(Tlv, TagsIn), + case Val of + [_|_]=PartList -> % constructed val + collect_parts(PartList); + Bin when is_binary(Bin) -> + Bin + end. + get_constraint(C, Key) -> case lists:keyfind(Key, 1, C) of false -> diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl index a7bbc33a19..d0a4de65e0 100644 --- a/lib/asn1/src/asn1rtt_per.erl +++ b/lib/asn1/src/asn1rtt_per.erl @@ -25,8 +25,7 @@ encode_constrained_number/2, encode_length/1, encode_length/2, - decode_compact_bit_string/3, - encode_bit_string/3, decode_bit_string/3, + encode_bit_string/3, encode_object_identifier/1, decode_object_identifier/1, encode_relative_oid/1, decode_relative_oid/1, complete/1, @@ -99,20 +98,6 @@ getchoice(Bytes, NumChoices, 0) -> decode_constrained_number(Bytes, {0,NumChoices-1}). -%% getbits_as_binary(Num,Bytes) -> {Bin,Rest} -%% Num = integer(), -%% Bytes = bitstring(), -%% Bin = bitstring(), -%% Rest = bitstring() -getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) -> - <<BS:Num/bitstring,Rest/bitstring>> = Bytes, - {BS,Rest}. - -getbits_as_list(Num,Bytes) when is_bitstring(Bytes) -> - <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes, - {[ B || <<B:1>> <= BitStr],Rest}. - - getbit(Buffer) -> <<B:1,Rest/bitstring>> = Buffer, {B,Rest}. @@ -201,42 +186,6 @@ set_choice_tag(Alt,[_H|Rest],Tag) -> set_choice_tag(_Alt,[],_Tag) -> false. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% decode_fragmented_XXX; decode of values encoded fragmented according -%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets, -%% characters or number of components (in a choice,sequence or similar). -%% Buffer is a buffer binary(). -%% C is the constrained length. -%% If the buffer is not aligned, this function does that. -decode_fragmented_bits(Buffer, C) when is_binary(Buffer) -> - decode_fragmented_bits(Buffer, C, []); -decode_fragmented_bits(Buffer,C) when is_bitstring(Buffer) -> - AlignBits = bit_size(Buffer) rem 8, - <<_:AlignBits,Rest/binary>> = Buffer, - decode_fragmented_bits(Rest,C,[]). - -decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>, C, Acc) -> - {Value,Bin2} = split_binary(Bin, Len * ?'16K'), % Len = 1 | 2 | 3 | 4 - decode_fragmented_bits(Bin2,C,[Value|Acc]); -decode_fragmented_bits(<<0:1,0:7,Bin/binary>>, C, Acc) -> - BinBits = erlang:list_to_bitstring(lists:reverse(Acc)), - case C of - Int when is_integer(Int), C =:= bit_size(BinBits) -> - {BinBits,Bin}; - Int when is_integer(Int) -> - exit({error,{asn1,{illegal_value,C,BinBits}}}) - end; -decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>, C, Acc) -> - <<Value:Len/bitstring,Rest/bitstring>> = Bin, - BinBits = erlang:list_to_bitstring([Value|Acc]), - case C of - Int when is_integer(Int), C =:= bit_size(BinBits) -> - {BinBits,Rest}; - Int when is_integer(Int) -> - exit({error,{asn1,{illegal_value,C,BinBits}}}) - end. - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% encode_open_type(Constraint, Value) -> CompleteList %% Value = list of bytes of an already encoded value (the list must be flat) @@ -793,138 +742,6 @@ trailingZeroesInNibble(14) -> trailingZeroesInNibble(15) -> 0. -%%%%%%%%%%%%%%% -%% The result is presented as a list of named bits (if possible) -%% else as a tuple {Unused,Bits}. Unused is the number of unused -%% bits, least significant bits in the last byte of Bits. Bits is -%% the BIT STRING represented as a binary. -%% -decode_compact_bit_string(Buffer, C, NamedNumberList) -> - case get_constraint(C,'SizeConstraint') of - 0 -> % fixed length - {{8,0},Buffer}; - V when is_integer(V),V=<16 -> %fixed length 16 bits or less - compact_bit_string(Buffer,V,NamedNumberList); - V when is_integer(V),V=<65536 -> %fixed length > 16 bits - Bytes2 = align(Buffer), - compact_bit_string(Bytes2,V,NamedNumberList); - V when is_integer(V) -> % V > 65536 => fragmented value - {BitStr,Buffer2} = decode_fragmented_bits(Buffer,V), - case bit_size(BitStr) band 7 of - 0 -> {{0,BitStr},Buffer2}; - N -> {{8-N,<<BitStr/bitstring,0:(8-N)>>},Buffer2} - end; - {Lb,Ub} when is_integer(Lb),is_integer(Ub) -> - %% This case may demand decoding of fragmented length/value - {Len,Bytes2} = decode_length(Buffer, {Lb,Ub}), - Bytes3 = align(Bytes2), - compact_bit_string(Bytes3,Len,NamedNumberList); - no -> - %% This case may demand decoding of fragmented length/value - {Len,Bytes2} = decode_length(Buffer, undefined), - Bytes3 = align(Bytes2), - compact_bit_string(Bytes3,Len,NamedNumberList); - {{Fix,Fix},Ext} = Sc when is_integer(Fix), is_list(Ext) -> - case decode_length(Buffer,Sc) of - {Len,Bytes2} when Len > Fix -> - Bytes3 = align(Bytes2), - compact_bit_string(Bytes3,Len,NamedNumberList); - {Len,Bytes2} when Len > 16 -> - Bytes3 = align(Bytes2), - compact_bit_string(Bytes3,Len,NamedNumberList); - {Len,Bytes2} -> - compact_bit_string(Bytes2,Len,NamedNumberList) - end; - Sc -> - {Len,Bytes2} = decode_length(Buffer,Sc), - Bytes3 = align(Bytes2), - compact_bit_string(Bytes3,Len,NamedNumberList) - end. - - -%%%%%%%%%%%%%%% -%% The result is presented as a list of named bits (if possible) -%% else as a list of 0 and 1. -%% -decode_bit_string(Buffer, C, NamedNumberList) -> - case get_constraint(C,'SizeConstraint') of - {Lb,Ub} when is_integer(Lb),is_integer(Ub) -> - {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}), - Bytes3 = align(Bytes2), - bit_list_or_named(Bytes3,Len,NamedNumberList); - no -> - {Len,Bytes2} = decode_length(Buffer,undefined), - Bytes3 = align(Bytes2), - bit_list_or_named(Bytes3,Len,NamedNumberList); - 0 -> % fixed length - {[],Buffer}; % nothing to encode - V when is_integer(V),V=<16 -> % fixed length 16 bits or less - bit_list_or_named(Buffer,V,NamedNumberList); - V when is_integer(V),V=<65536 -> - Bytes2 = align(Buffer), - bit_list_or_named(Bytes2,V,NamedNumberList); - V when is_integer(V) -> - Bytes2 = align(Buffer), - {BinBits,_Bytes3} = decode_fragmented_bits(Bytes2,V), - bit_list_or_named(BinBits,V,NamedNumberList); - {{Fix,Fix},Ext} =Sc when is_integer(Fix), is_list(Ext) -> - case decode_length(Buffer,Sc) of - {Len,Bytes2} when Len > Fix -> - Bytes3 = align(Bytes2), - bit_list_or_named(Bytes3,Len,NamedNumberList); - {Len,Bytes2} when Len > 16 -> - Bytes3 = align(Bytes2), - bit_list_or_named(Bytes3,Len,NamedNumberList); - {Len,Bytes2} -> - bit_list_or_named(Bytes2,Len,NamedNumberList) - end; - Sc -> % extension marker - {Len,Bytes2} = decode_length(Buffer,Sc), - Bytes3 = align(Bytes2), - bit_list_or_named(Bytes3,Len,NamedNumberList) - end. - - -%% if no named bits are declared we will return a -%% {Unused,Bits}. Unused = integer(), -%% Bits = binary(). -compact_bit_string(Buffer,Len,[]) -> - {BitStr,Rest} = getbits_as_binary(Len,Buffer), % {{Unused,BinBits},NewBuffer} - PadLen = (8 - (bit_size(BitStr) rem 8)) rem 8, - {{PadLen,<<BitStr/bitstring,0:PadLen>>},Rest}; -compact_bit_string(Buffer,Len,NamedNumberList) -> - bit_list_or_named(Buffer,Len,NamedNumberList). - - -%% if no named bits are declared we will return a -%% BitList = [0 | 1] - -bit_list_or_named(Buffer,Len,[]) -> - getbits_as_list(Len,Buffer); - -%% if there are named bits declared we will return a named -%% BitList where the names are atoms and unnamed bits represented -%% as {bit,Pos} -%% BitList = [atom() | {bit,Pos}] -%% Pos = integer() - -bit_list_or_named(Buffer,Len,NamedNumberList) -> - {BitList,Rest} = getbits_as_list(Len,Buffer), - {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}. - -bit_list_or_named1(Pos,[0|Bt],Names,Acc) -> - bit_list_or_named1(Pos+1,Bt,Names,Acc); -bit_list_or_named1(Pos,[1|Bt],Names,Acc) -> - case lists:keyfind(Pos, 2, Names) of - {Name,_} -> - bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]); - false -> - bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc]) - end; -bit_list_or_named1(_Pos,[],_Names,Acc) -> - lists:reverse(Acc). - - %%%%%%%%%%%%%%% %% @@ -1292,19 +1109,6 @@ decode_relative_oid(Bytes) -> {list_to_tuple(ObjVals),Bytes3}. -get_constraint([{Key,V}],Key) -> - V; -get_constraint([],_) -> - no; -get_constraint(C,Key) -> - case lists:keyfind(Key, 1, C) of - false -> - no; - {_,V} -> - V - end. - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% complete(InList) -> ByteList %% Takes a coded list with bits and bytes and converts it to a list of bytes diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl index 926f0fe228..2edd240baf 100644 --- a/lib/asn1/src/asn1rtt_per_common.erl +++ b/lib/asn1/src/asn1rtt_per_common.erl @@ -21,7 +21,11 @@ -include("asn1_records.hrl"). --export([decode_fragmented/3]). +-export([decode_fragmented/3, + decode_compact_bit_string/1, + decode_legacy_bit_string/1, + decode_named_bit_string/2]). + -define('16K',16384). decode_fragmented(SegSz0, Buf0, Unit) -> @@ -42,3 +46,30 @@ decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) -> <<Frag:SegSz/bitstring,Buf/bitstring>> = Buf0, Res = <<Res0/bitstring,Frag/bitstring>>, decode_fragmented_1(Buf, Unit, Res). + +decode_named_bit_string(Val, NNL) -> + Bits = [B || <<B:1>> <= Val], + decode_named_bit_string_1(0, Bits, NNL, []). + +decode_legacy_bit_string(Val) -> + [B || <<B:1>> <= Val]. + +decode_compact_bit_string(Val) -> + PadLen = (8 - (bit_size(Val) band 7)) band 7, + {PadLen,<<Val/bitstring,0:PadLen>>}. + +%%% +%%% Internal functions. +%%% + +decode_named_bit_string_1(Pos, [0|Bt], Names, Acc) -> + decode_named_bit_string_1(Pos+1, Bt, Names, Acc); +decode_named_bit_string_1(Pos, [1|Bt], Names, Acc) -> + case lists:keyfind(Pos, 2, Names) of + {Name,_} -> + decode_named_bit_string_1(Pos+1, Bt, Names, [Name|Acc]); + false -> + decode_named_bit_string_1(Pos+1, Bt, Names, [{bit,Pos}|Acc]) + end; +decode_named_bit_string_1(_Pos, [], _Names, Acc) -> + lists:reverse(Acc). diff --git a/lib/asn1/src/asn1rtt_uper.erl b/lib/asn1/src/asn1rtt_uper.erl index d4e2fece67..34971f09e3 100644 --- a/lib/asn1/src/asn1rtt_uper.erl +++ b/lib/asn1/src/asn1rtt_uper.erl @@ -26,8 +26,7 @@ -export([encode_small_number/1, encode_constrained_number/2, encode_boolean/1, encode_length/1, encode_length/2, - decode_compact_bit_string/3]). --export([encode_bit_string/3, decode_bit_string/3]). + encode_bit_string/3]). -export([encode_octet_string/2, encode_relative_oid/1, decode_relative_oid/1, encode_object_identifier/1, decode_object_identifier/1, @@ -132,20 +131,6 @@ getchoice(Bytes,NumChoices,0) -> decode_constrained_number(Bytes,{0,NumChoices-1}). -%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes}, -%% Num = integer(), -%% Bytes = list() | tuple(), -%% Unused = integer(), -%% BinBits = binary(), -%% RestBytes = tuple() -getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) -> - <<BS:Num/bitstring,Rest/bitstring>> = Bytes, - {BS,Rest}. - -getbits_as_list(Num, Bytes) when is_bitstring(Bytes) -> - <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes, - {[B || <<B:1>> <= BitStr],Rest}. - getbit(Buffer) -> <<B:1,Rest/bitstring>> = Buffer, {B,Rest}. @@ -217,37 +202,6 @@ set_choice_tag(Alt,[_H|Rest],Tag) -> set_choice_tag(_Alt,[],_Tag) -> false. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% decode_fragmented_XXX; decode of values encoded fragmented according -%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets, -%% characters or number of components (in a choice,sequence or similar). -%% Buffer is a buffer {Used, Bin}. -%% C is the constrained length. -%% If the buffer is not aligned, this function does that. -decode_fragmented_bits(Buffer,C) -> - decode_fragmented_bits(Buffer,C,[]). -decode_fragmented_bits(<<3:2,Len:6,BitStr/bitstring>>,C,Acc) -> - FragLen = (Len*?'16K') div 8, - <<Value:FragLen/binary,BitStr2/bitstring>> = BitStr, - decode_fragmented_bits(BitStr2,C,[Value|Acc]); -decode_fragmented_bits(<<0:1,0:7,BitStr/bitstring>>,C,Acc) -> - BinBits = list_to_binary(lists:reverse(Acc)), - case C of - Int when is_integer(Int),C =:= byte_size(BinBits) -> - {BinBits,BitStr}; - Int when is_integer(Int) -> - exit({error,{asn1,{illegal_value,C,BinBits}}}) - end; -decode_fragmented_bits(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) -> - <<Val:Len/bitstring,Rest/bitstring>> = BitStr, - ResBitStr = list_to_bitstring(lists:reverse([Val|Acc])), - case C of - Int when is_integer(Int),C == bit_size(ResBitStr) -> - {ResBitStr,Rest}; - Int when is_integer(Int) -> - exit({error,{asn1,{illegal_value,C,ResBitStr}}}) - end. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% encode_open_type(Constraint, Value) -> CompleteList @@ -708,105 +662,6 @@ trailingZeroesInNibble(14) -> trailingZeroesInNibble(15) -> 0. -%%%%%%%%%%%%%%% -%% The result is presented as a list of named bits (if possible) -%% else as a tuple {Unused,Bits}. Unused is the number of unused -%% bits, least significant bits in the last byte of Bits. Bits is -%% the BIT STRING represented as a binary. -%% -decode_compact_bit_string(Buffer, C, NamedNumberList) -> - case get_constraint(C, 'SizeConstraint') of - 0 -> % fixed length - {{8,0},Buffer}; - V when is_integer(V),V=<16 -> %fixed length 16 bits or less - compact_bit_string(Buffer,V,NamedNumberList); - V when is_integer(V),V=<65536 -> %fixed length > 16 bits - compact_bit_string(Buffer,V,NamedNumberList); - V when is_integer(V) -> % V > 65536 => fragmented value - {Bin,Buffer2} = decode_fragmented_bits(Buffer,V), - PadLen = (8 - (bit_size(Bin) rem 8)) rem 8, - {{PadLen,<<Bin/bitstring,0:PadLen>>},Buffer2}; - {Lb,Ub} when is_integer(Lb),is_integer(Ub) -> - %% This case may demand decoding of fragmented length/value - {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}), - compact_bit_string(Bytes2,Len,NamedNumberList); - no -> - %% This case may demand decoding of fragmented length/value - {Len,Bytes2} = decode_length(Buffer,undefined), - compact_bit_string(Bytes2,Len,NamedNumberList); - Sc -> - {Len,Bytes2} = decode_length(Buffer,Sc), - compact_bit_string(Bytes2,Len,NamedNumberList) - end. - - -%%%%%%%%%%%%%%% -%% The result is presented as a list of named bits (if possible) -%% else as a list of 0 and 1. -%% -decode_bit_string(Buffer, C, NamedNumberList) -> - case get_constraint(C,'SizeConstraint') of - {Lb,Ub} when is_integer(Lb),is_integer(Ub) -> - {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}), - bit_list_or_named(Bytes2,Len,NamedNumberList); - no -> - {Len,Bytes2} = decode_length(Buffer,undefined), - bit_list_or_named(Bytes2,Len,NamedNumberList); - 0 -> % fixed length - {[],Buffer}; % nothing to encode - V when is_integer(V),V=<16 -> % fixed length 16 bits or less - bit_list_or_named(Buffer,V,NamedNumberList); - V when is_integer(V),V=<65536 -> - bit_list_or_named(Buffer,V,NamedNumberList); - V when is_integer(V) -> - {BinBits,_} = decode_fragmented_bits(Buffer,V), - bit_list_or_named(BinBits,V,NamedNumberList); - Sc -> % extension marker - {Len,Bytes2} = decode_length(Buffer,Sc), - bit_list_or_named(Bytes2,Len,NamedNumberList) - end. - - -%% if no named bits are declared we will return a -%% {Unused,Bits}. Unused = integer(), -%% Bits = binary(). -compact_bit_string(Buffer, Len, []) -> - {BitStr,Rest} = getbits_as_binary(Len,Buffer), % {{Unused,BinBits},NewBuffer} - PadLen = (8 - (bit_size(BitStr) rem 8)) rem 8, - {{PadLen,<<BitStr/bitstring,0:PadLen>>},Rest}; -compact_bit_string(Buffer, Len, NamedNumberList) -> - bit_list_or_named(Buffer, Len, NamedNumberList). - - -%% if no named bits are declared we will return a -%% BitList = [0 | 1] - -bit_list_or_named(Buffer,Len,[]) -> - getbits_as_list(Len,Buffer); - -%% if there are named bits declared we will return a named -%% BitList where the names are atoms and unnamed bits represented -%% as {bit,Pos} -%% BitList = [atom() | {bit,Pos}] -%% Pos = integer() - -bit_list_or_named(Buffer,Len,NamedNumberList) -> - {BitList,Rest} = getbits_as_list(Len,Buffer), - {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}. - -bit_list_or_named1(Pos,[0|Bt],Names,Acc) -> - bit_list_or_named1(Pos+1,Bt,Names,Acc); -bit_list_or_named1(Pos,[1|Bt],Names,Acc) -> - case lists:keyfind(Pos, 2, Names) of - {Name,_} -> - bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]); - false -> - bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc]) - end; -bit_list_or_named1(_,[],_,Acc) -> - lists:reverse(Acc). - - %%%%%%%%%%%%%%% %% |