From 74cee7dc1cc5b0332cd851da4953ebbb98224b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Jan 2013 10:56:27 +0100 Subject: By default, encode BIT STRING to bitstrings Add the option 'legacy_bit_string' to decode to the old list format. --- lib/asn1/src/asn1ct.erl | 31 +++++++++++++++++---- lib/asn1/src/asn1ct_gen.erl | 13 +++++---- lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 9 ++++-- lib/asn1/src/asn1ct_gen_per.erl | 51 +++++++++++++++++++++------------- lib/asn1/src/asn1ct_value.erl | 43 ++++++++++++++++++---------- lib/asn1/src/asn1rtt_ber.erl | 11 ++++++++ 6 files changed, 111 insertions(+), 47 deletions(-) (limited to 'lib/asn1/src') 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 <- Val >>; + compact -> + BitString = << <> || B <- Val >>, + PadLen = (8 - (bit_size(BitString) band 7)) band 7, + {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); + <> -> + Size = bit_size(Bits) - Unused, + <> = Bits, + check_restricted_string(Val, Size, Range) + end. + decode_named_bit_string(Buffer, NamedNumberList, Tags) -> case match_and_collect(Buffer, Tags) of <<0>> -> -- cgit v1.2.3