From fbcb7fe589edbfe79d10d7fe01be8a9f77926b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 19 Dec 2012 15:46:53 +0100 Subject: Optimize encoding of ENUMERATED in per and uper Always pre-encode the values for the enumeration. Clean up the code and let the per and uper back-ends share the code. --- lib/asn1/src/Makefile | 3 +- lib/asn1/src/asn1ct_eval_per.funcs | 3 +- lib/asn1/src/asn1ct_eval_uper.funcs | 2 + lib/asn1/src/asn1ct_gen_per.erl | 84 ++++++++++++++++------------------- lib/asn1/src/asn1ct_gen_per_rt2ct.erl | 76 +------------------------------ lib/asn1/src/asn1rtt_per.erl | 1 + lib/asn1/src/asn1rtt_uper.erl | 3 +- lib/asn1/test/asn1_app_test.erl | 2 +- 8 files changed, 51 insertions(+), 123 deletions(-) create mode 100644 lib/asn1/src/asn1ct_eval_uper.funcs (limited to 'lib') diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile index b1500d9ea6..4bf6eabce6 100644 --- a/lib/asn1/src/Makefile +++ b/lib/asn1/src/Makefile @@ -44,7 +44,8 @@ RELSYSDIR = $(RELEASE_PATH)/lib/asn1-$(VSN) EBIN = ../ebin EVAL_CT_MODULES = asn1ct_eval_ext \ - asn1ct_eval_per + asn1ct_eval_per \ + asn1ct_eval_uper CT_MODULES= \ asn1ct \ diff --git a/lib/asn1/src/asn1ct_eval_per.funcs b/lib/asn1/src/asn1ct_eval_per.funcs index 353424c231..a1ea5cd043 100644 --- a/lib/asn1/src/asn1ct_eval_per.funcs +++ b/lib/asn1/src/asn1ct_eval_per.funcs @@ -1 +1,2 @@ -{per,encode_integer,2}. +{per,encode_constrained_number,2}. +{per,encode_small_number,1}. diff --git a/lib/asn1/src/asn1ct_eval_uper.funcs b/lib/asn1/src/asn1ct_eval_uper.funcs new file mode 100644 index 0000000000..884a486f40 --- /dev/null +++ b/lib/asn1/src/asn1ct_eval_uper.funcs @@ -0,0 +1,2 @@ +{uper,encode_constrained_number,2}. +{uper,encode_small_number,1}. diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 08b65d466d..5dda5e9c5d 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -143,28 +143,16 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) -> Value,{asis,NamedNumberList}], call(Erules, encode_integer, Args); {'ENUMERATED',{Nlist1,Nlist2}} -> - NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]), - NewC = [{'ValueRange',{0,length(Nlist1)-1}}], - case Erules of - uper -> - emit(["case ",Value," of",nl]); - _ -> - emit(["case (case ",Value," of {_,",{curr,enumval},"}-> ", - {curr,enumval},";_->", Value," end) of",nl]), - asn1ct_name:new(enumval) - end, - emit_enc_enumerated_cases(Erules,NewC, NewList, 0); + NewList = [{0,X} || {X,_} <- Nlist1] ++ ['EXT_MARK'] ++ + [{1,X} || {X,_} <- Nlist2], + NewC = {0,length(Nlist1)-1}, + emit(["case ",Value," of",nl]), + emit_enc_enumerated_cases(Erules, NewC, NewList, 0); {'ENUMERATED',NamedNumberList} -> - NewList = [X||{X,_} <- NamedNumberList], - NewC = [{'ValueRange',{0,length(NewList)-1}}], - case Erules of - uper -> - emit(["case ",Value," of",nl]); - _ -> - emit(["case (case ",Value," of {_,",{curr,enumval}, - "}->",{curr,enumval},";_->",Value," end) of",nl]) - end, - emit_enc_enumerated_cases(Erules,NewC, NewList, 0); + NewList = [X || {X,_} <- NamedNumberList], + NewC = {0,length(NewList)-1}, + emit(["case ",Value," of",nl]), + emit_enc_enumerated_cases(Erules, NewC, NewList, 0); 'REAL' -> emit_enc_real(Erules, Value); @@ -250,34 +238,37 @@ emit_enc_real(Erules, Real) -> {curr,tmpval},"]",nl, "end"]). -emit_enc_enumerated_cases(Erule,C, [H], Count) -> - emit_enc_enumerated_case(Erule,C, H, Count), - case H of - 'EXT_MARK' -> ok; - _ -> - emit([";",nl]) - end, - emit([nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]), - emit([nl,"end"]); -emit_enc_enumerated_cases(Erule, C, ['EXT_MARK'|T], _Count) -> - emit_enc_enumerated_cases(Erule, C, T, 0); -emit_enc_enumerated_cases(Erule, C, [H1,H2|T], Count) -> - emit_enc_enumerated_case(Erule, C, H1, Count), +emit_enc_enumerated_cases(Erules, C, ['EXT_MARK'|T], _Count) -> + %% Reset enumeration counter. + emit_enc_enumerated_cases(Erules, C, T, 0); +emit_enc_enumerated_cases(Erules, C, [H|T], Count) -> + emit_enc_enumerated_case(Erules, C, H, Count), emit([";",nl]), - emit_enc_enumerated_cases(Erule, C, [H2|T], Count+1). + emit_enc_enumerated_cases(Erules, C, T, Count+1); +emit_enc_enumerated_cases(_Erules, _, [], _Count) -> + emit(["EnumVal -> " + "exit({error,{asn1,{enumerated_not_in_range, EnumVal}}})",nl, + "end"]). - -emit_enc_enumerated_case(_Erule, _C, 'EXT_MARK', _Count) -> - true; -emit_enc_enumerated_case(uper=Erules,_C, {1,EnumName}, Count) -> - emit(["'",EnumName,"' -> [<<1:1>>,", - {call,Erules,encode_small_number,[Count]},"]"]); -emit_enc_enumerated_case(uper=Erules, C, {0,EnumName}, Count) -> - emit(["'",EnumName,"' -> [<<0:1>>,", - {call,Erules,encode_integer,[{asis,C},Count]},"]"]); +emit_enc_enumerated_case(Erules, C, {0,EnumName}, Count) -> + %% ENUMERATED with extensionmark; the value lies within then extension root + Enc = enc_ext_and_val(Erules, 0, encode_constrained_number, [C,Count]), + emit(["'",EnumName,"' -> ",{asis,Enc}]); +emit_enc_enumerated_case(Erules, _C, {1,EnumName}, Count) -> + %% ENUMERATED with extensionmark; the value is higher than extension root + Enc = enc_ext_and_val(Erules, 1, encode_small_number, [Count]), + emit(["'",EnumName,"' -> ",{asis,Enc}]); emit_enc_enumerated_case(Erules, C, EnumName, Count) -> + %% ENUMERATED without extension + EvalMod = eval_module(Erules), emit(["'",EnumName,"' -> ", - {call,Erules,encode_integer,[{asis,C},Count]}]). + {asis,EvalMod:encode_constrained_number(C, Count)}]). + +enc_ext_and_val(per, E, F, Args) -> + [E|apply(asn1ct_eval_per, F, Args)]; +enc_ext_and_val(uper, E, F, Args) -> + <>. + get_constraint([{Key,V}], Key) -> V; @@ -1262,3 +1253,6 @@ imm_dec_open_type_1(Type, Aligned) -> "end"]) end, {call,D,asn1ct_imm:per_dec_open_type(Aligned)}. + +eval_module(per) -> asn1ct_eval_per; +eval_module(uper) -> asn1ct_eval_uper. diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl index 7d00f2e817..88e9bc6020 100644 --- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl +++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl @@ -138,20 +138,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) -> emit([" %%INTEGER with effective constraint: ", {asis,EffectiveConstr},nl]), emit_enc_integer_NNL(Erules,EffectiveConstr,Value,NamedNumberList); - {'ENUMERATED',{Nlist1,Nlist2}} -> - NewList = lists:append([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]), - NewC = [{'ValueRange',{0,length(Nlist1)-1}}], - emit(["case ",Value," of",nl]), -%% emit_enc_enumerated_cases(Erules,NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0); - emit_enc_enumerated_cases(Erules,NewC, NewList, 0); - {'ENUMERATED',NamedNumberList} -> - NewList = [X||{X,_} <- NamedNumberList], - NewC = effective_constraint(integer, - [{'ValueRange', - {0,length(NewList)-1}}]), - NewVal = enc_enum_cases(Value,NewList), - emit_enc_integer(Erules,NewC,NewVal); - + {'ENUMERATED',_} -> + asn1ct_gen_per:gen_encode_prim(Erules, D, DoTag, Value); 'REAL' -> emit_enc_real(Erules, Value); @@ -551,66 +539,6 @@ emit_enc_integer(Erule, C, Value) -> call(Erule, encode_integer, [{asis,C},Value]). - -enc_enum_cases(Value,NewList) -> - asn1ct_name:new(tmpval), - TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)), - Cases=enc_enum_cases1(NewList), - lists:flatten(io_lib:format("(case ~s of "++Cases++ - "~s ->exit({error," - "{asn1,{enumerated,~s}}})" - " end)", - [Value,TmpVal,TmpVal])). -enc_enum_cases1(NNL) -> - enc_enum_cases1(NNL,0). -enc_enum_cases1([H|T],Index) -> - io_lib:format("~w->~w;",[H,Index])++enc_enum_cases1(T,Index+1); -enc_enum_cases1([],_) -> - "". - - -emit_enc_enumerated_cases(Erule, C, [H], Count) -> - emit_enc_enumerated_case(Erule, C, H, Count), - case H of - 'EXT_MARK' -> - ok; - _ -> - emit([";",nl]) - end, - emit([nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]), - emit([nl,"end"]); -emit_enc_enumerated_cases(Erule, C, ['EXT_MARK'|T], _Count) -> - emit_enc_enumerated_cases(Erule, C, T, 0); -emit_enc_enumerated_cases(Erule, C, [H1,H2|T], Count) -> - emit_enc_enumerated_case(Erule, C, H1, Count), - emit([";",nl]), - emit_enc_enumerated_cases(Erule, C, [H2|T], Count+1). - - -%% The function clauses matching on tuples with first element -%% asn1_enum, 1 or 0 and the atom 'EXT_MARK' are for ENUMERATED -%% with extension mark. -%% emit_enc_enumerated_case(_Erule,_C, {asn1_enum,High}, _) -> -%% %% ENUMERATED with extensionmark -%% %% value higher than the extension base and not -%% %% present in the extension range. -emit_enc_enumerated_case(Erule,_C, {1,EnumName}, Count) -> - %% ENUMERATED with extensionmark - %% values higher than extension root - emit(["'",EnumName,"' -> [1,"]), - call(Erule, encode_small_number, [Count]), - emit("]"); -emit_enc_enumerated_case(_Erule,C, {0,EnumName}, Count) -> - %% ENUMERATED with extensionmark - %% values within extension root - emit(["'",EnumName,"' -> ",{asis,[0|asn1ct_eval_per:encode_integer(C, Count)]}]); -emit_enc_enumerated_case(_Erule, _C, 'EXT_MARK', _Count) -> - true. -%% %% This clause is invoked in case of an ENUMERATED without extension mark -%% emit_enc_enumerated_case(_Erule,_C, EnumName, Count) -> -%% emit(["'",EnumName,"' -> ",Count]). - - get_constraint([{Key,V}],Key) -> V; get_constraint([],_) -> diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl index 8234121934..a7bbc33a19 100644 --- a/lib/asn1/src/asn1rtt_per.erl +++ b/lib/asn1/src/asn1rtt_per.erl @@ -22,6 +22,7 @@ skipextensions/3, getbit/1, getchoice/3, set_choice/3,encode_integer/2, encode_small_number/1, + encode_constrained_number/2, encode_length/1, encode_length/2, decode_compact_bit_string/3, diff --git a/lib/asn1/src/asn1rtt_uper.erl b/lib/asn1/src/asn1rtt_uper.erl index bcc11da63a..d4e2fece67 100644 --- a/lib/asn1/src/asn1rtt_uper.erl +++ b/lib/asn1/src/asn1rtt_uper.erl @@ -23,7 +23,8 @@ fixextensions/2, skipextensions/3, getbit/1, getchoice/3 ]). -export([set_choice/3, encode_integer/2, encode_integer/3]). --export([encode_small_number/1, encode_boolean/1, +-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]). diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl index e4ae61f983..1225e36778 100644 --- a/lib/asn1/test/asn1_app_test.erl +++ b/lib/asn1/test/asn1_app_test.erl @@ -140,7 +140,7 @@ check_asn1ct_modules(Extra) -> asn1ct_gen_ber_bin_v2,asn1ct_value, asn1ct_tok,asn1ct_parser2,asn1ct_table, asn1ct_imm,asn1ct_func,asn1ct_rtt, - asn1ct_eval_ext,asn1ct_eval_per], + asn1ct_eval_ext,asn1ct_eval_per,asn1ct_eval_uper], case Extra -- ASN1CTMods of [] -> ok; -- cgit v1.2.3