aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-12-20 12:13:47 +0100
committerBjörn Gustavsson <[email protected]>2013-01-22 19:20:12 +0100
commit76ad80f52981449af3c79fdf5b298e4c8d817788 (patch)
treee717f03e019d2a8089e9adfe424b8700067a98bc /lib/asn1/src
parentfbcb7fe589edbfe79d10d7fe01be8a9f77926b89 (diff)
downloadotp-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.
Diffstat (limited to 'lib/asn1/src')
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl31
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl30
-rw-r--r--lib/asn1/src/asn1ct_imm.erl16
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl140
-rw-r--r--lib/asn1/src/asn1rtt_per.erl198
-rw-r--r--lib/asn1/src/asn1rtt_per_common.erl33
-rw-r--r--lib/asn1/src/asn1rtt_uper.erl147
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).
-
-
%%%%%%%%%%%%%%%
%%