aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2013-01-08 10:56:27 +0100
committerBjörn Gustavsson <[email protected]>2013-01-23 15:22:56 +0100
commit74cee7dc1cc5b0332cd851da4953ebbb98224b5f (patch)
treeff539fdce7055f51fb437bc906358f073d77a620 /lib/asn1/src
parent625d2b01dcaa0b15cc9ff7f98438bcd81a5bddc8 (diff)
downloadotp-74cee7dc1cc5b0332cd851da4953ebbb98224b5f.tar.gz
otp-74cee7dc1cc5b0332cd851da4953ebbb98224b5f.tar.bz2
otp-74cee7dc1cc5b0332cd851da4953ebbb98224b5f.zip
By default, encode BIT STRING to bitstrings
Add the option 'legacy_bit_string' to decode to the old list format.
Diffstat (limited to 'lib/asn1/src')
-rw-r--r--lib/asn1/src/asn1ct.erl31
-rw-r--r--lib/asn1/src/asn1ct_gen.erl13
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl9
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl51
-rw-r--r--lib/asn1/src/asn1ct_value.erl43
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl11
6 files changed, 111 insertions, 47 deletions
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index 0aa6c4c6a6..46602a3071 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -41,6 +41,7 @@
maybe_rename_function/3,latest_sindex/0,current_sindex/0,
set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2,
parse_and_save/2,verbose/3,warning/3,warning/4,error/3]).
+-export([get_bit_string_format/0]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -766,12 +767,9 @@ check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
check({false,M},_,_,_,_,_,_,_) ->
{false,M}.
-generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
+generate({true,{M,_Module,GenTOrV}}, OutFile, EncodingRule, Options) ->
debug_on(Options),
- case lists:member(compact_bit_string,Options) of
- true -> put(compact_bit_string,true);
- _ -> ok
- end,
+ setup_bit_string_format(Options),
put(encoding_options,Options),
asn1ct_table:new(check_functions),
@@ -793,8 +791,8 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
ok
end,
debug_off(Options),
- put(compact_bit_string,false),
erase(encoding_options),
+ cleanup_bit_string_format(),
erase(tlv_format), % used in ber
erase(class_default_type),% used in ber
asn1ct_table:delete(check_functions),
@@ -812,6 +810,26 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
generate({false,M},_,_,_) ->
{false,M}.
+setup_bit_string_format(Opts) ->
+ Format = case {lists:member(compact_bit_string, Opts),
+ lists:member(legacy_bit_string, Opts)} of
+ {false,false} -> bitstring;
+ {true,false} -> compact;
+ {false,true} -> legacy;
+ {true,true} ->
+ Message = "Contradicting options given: "
+ "compact_bit_string and legacy_bit_string",
+ exit({error,{asn1,Message}})
+ end,
+ put(bit_string_format, Format).
+
+cleanup_bit_string_format() ->
+ erase(bit_string_format).
+
+get_bit_string_format() ->
+ get(bit_string_format).
+
+
%% parse_and_save parses an asn1 spec and saves the unchecked parse
%% tree in a data base file.
%% Does not support multifile compilation files
@@ -1067,6 +1085,7 @@ remove_asn_flags(Options) ->
X /= get_rule(Options),
X /= optimize,
X /= compact_bit_string,
+ X /= legacy_bit_string,
X /= debug,
X /= asn1config,
X /= record_name_prefix].
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 5181ed1fce..c2590d1e44 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -808,7 +808,7 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) ->
pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
- emit({"-export([encoding_rule/0]).",nl}),
+ emit(["-export([encoding_rule/0,bit_string_format/0]).",nl]),
case Types of
[] -> ok;
_ ->
@@ -918,12 +918,10 @@ gen_selected_decode_exports1([{FuncName,_}|Rest]) ->
gen_selected_decode_exports1(Rest).
pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
- emit(["encoding_rule() ->",nl]),
- emit([{asis,Erules},".",nl,nl]);
+ gen_info_functions(Erules);
pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
emit(["-export([encode/2,decode/2,encode_disp/2,decode_disp/2]).",nl,nl]),
- emit(["encoding_rule() ->",nl]),
- emit([" ",{asis,Erules},".",nl,nl]),
+ gen_info_functions(Erules),
NoFinalPadding = lists:member(no_final_padding,get(encoding_options)),
{Call,BytesAsBinary} =
case Erules of
@@ -1028,6 +1026,11 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
emit([nl]),
emit({nl,nl}).
+gen_info_functions(Erules) ->
+ emit(["encoding_rule() -> ",
+ {asis,Erules},".",nl,nl,
+ "bit_string_format() -> ",
+ {asis,asn1ct:get_bit_string_format()},".",nl,nl]).
gen_decode_partial_incomplete(ber) ->
case {asn1ct:read_config_data(partial_incomplete_decode),
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index fe5b5031b6..121f452da8 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -628,12 +628,15 @@ 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 ->
+ case asn1ct:get_bit_string_format() of
+ compact ->
call(decode_compact_bit_string,
[BytesVar,{asis,Constraint},TagStr]);
- _ ->
+ legacy ->
call(decode_legacy_bit_string,
+ [BytesVar,{asis,Constraint},TagStr]);
+ bitstring ->
+ call(decode_native_bit_string,
[BytesVar,{asis,Constraint},TagStr])
end.
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index a43975a308..b38af3306a 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1099,25 +1099,26 @@ gen_dec_imm_1('ANY', _Constraint, 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};
+ case NNL of
+ [] ->
+ case asn1ct:get_bit_string_format() of
+ compact ->
+ gen_dec_bit_string(decode_compact_bit_string,
+ Imm);
+ legacy ->
+ gen_dec_bit_string(decode_legacy_bit_string,
+ Imm);
+ bitstring ->
+ gen_dec_copy_bitstring(Imm)
+ end;
+ [_|_] ->
+ D = fun(V, Buf) ->
+ As = [V,{asis,NNL}],
+ Call = {call,per_common,decode_named_bit_string,As},
+ emit(["{",Call,com,Buf,"}"])
+ end,
+ {call,D,Imm}
+ end;
gen_dec_imm_1('BOOLEAN', _Constr, _Aligned) ->
asn1ct_imm:per_dec_boolean();
gen_dec_imm_1({'ENUMERATED',{Base,Ext}}, _Constr, Aligned) ->
@@ -1138,6 +1139,18 @@ gen_dec_imm_1('REAL', _Constraint, Aligned) ->
asn1ct_imm:per_dec_real(Aligned);
gen_dec_imm_1(_, _, _) -> no.
+gen_dec_bit_string(F, Imm) ->
+ D = fun(V, Buf) ->
+ emit(["{",{call,per_common,F,[V]},com,Buf,"}"])
+ end,
+ {call,D,Imm}.
+
+gen_dec_copy_bitstring(Imm) ->
+ D = fun(V, Buf) ->
+ emit(["{list_to_bitstring([",V,"]),",Buf,"}"])
+ end,
+ {call,D,Imm}.
+
gen_dec_prim(Erule, Type, BytesVar) ->
case gen_dec_imm(Erule, Type) of
no ->
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index ed1deec2aa..8f3dc1d8b8 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -54,7 +54,7 @@ from_type(M,Typename,Type) when is_record(Type,type) ->
{notype,_} ->
true;
{primitive,bif} ->
- from_type_prim(Type);
+ from_type_prim(M, Type);
'ASN1_OPEN_TYPE' ->
case Type#type.constraint of
[#'Externaltypereference'{type=TrefConstraint}] ->
@@ -164,7 +164,7 @@ gen_list(_,_,_,0) ->
gen_list(M,Typename,Oftype,N) ->
[from_type(M,Typename,Oftype)|gen_list(M,Typename,Oftype,N-1)].
-from_type_prim(D) ->
+from_type_prim(M, D) ->
C = D#type.constraint,
case D#type.def of
'INTEGER' ->
@@ -212,18 +212,7 @@ from_type_prim(D) ->
NN = [X||{X,_} <- NamedNumberList],
case NN of
[] ->
- Bl1 =lists:reverse(adjust_list(size_random(C),[1,0,1,1])),
- Bl2 = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,Bl1)),
- case {length(Bl2),get_constraint(C,'SizeConstraint')} of
- {Len,Len} ->
- Bl2;
- {_Len,Int} when is_integer(Int) ->
- Bl1;
- {Len,{Min,_}} when Min > Len ->
- Bl1;
- _ ->
- Bl2
- end;
+ random_unnamed_bit_string(M, C);
_ ->
[lists:nth(random(length(NN)),NN)]
end;
@@ -320,6 +309,32 @@ c_string(C,Default) ->
Default
end.
+random_unnamed_bit_string(M, C) ->
+ Bl1 = lists:reverse(adjust_list(size_random(C), [1,0,1,1])),
+ Bl2 = lists:reverse(lists:dropwhile(fun(0)-> true;
+ (1) -> false
+ end,Bl1)),
+ Val = case {length(Bl2),get_constraint(C, 'SizeConstraint')} of
+ {Len,Len} ->
+ Bl2;
+ {_Len,Int} when is_integer(Int) ->
+ Bl1;
+ {Len,{Min,_}} when Min > Len ->
+ Bl1;
+ _ ->
+ Bl2
+ end,
+ case M:bit_string_format() of
+ legacy ->
+ Val;
+ bitstring ->
+ << <<B:1>> || B <- Val >>;
+ compact ->
+ BitString = << <<B:1>> || B <- Val >>,
+ PadLen = (8 - (bit_size(BitString) band 7)) band 7,
+ {PadLen,<<BitString/bitstring,0:PadLen>>}
+ end.
+
%% FIXME:
%% random_sign(integer) ->
%% case random(2) of
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
index 7998c24465..889a421e4f 100644
--- a/lib/asn1/src/asn1rtt_ber.erl
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -33,6 +33,7 @@
decode_named_bit_string/3,
decode_compact_bit_string/3,
decode_legacy_bit_string/3,
+ decode_native_bit_string/3,
encode_null/2,decode_null/2,
encode_relative_oid/2,decode_relative_oid/2,
encode_object_identifier/2,decode_object_identifier/2,
@@ -1068,6 +1069,16 @@ decode_legacy_bit_string(Buffer, Range, Tags) ->
end,
check_restricted_string(Val, length(Val), Range).
+decode_native_bit_string(Buffer, Range, Tags) ->
+ case match_and_collect(Buffer, Tags) of
+ <<0>> ->
+ check_restricted_string(<<>>, 0, Range);
+ <<Unused,Bits/binary>> ->
+ Size = bit_size(Bits) - Unused,
+ <<Val:Size/bitstring,_:Unused/bitstring>> = Bits,
+ check_restricted_string(Val, Size, Range)
+ end.
+
decode_named_bit_string(Buffer, NamedNumberList, Tags) ->
case match_and_collect(Buffer, Tags) of
<<0>> ->