aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-12-19 15:46:53 +0100
committerBjörn Gustavsson <[email protected]>2013-01-22 19:20:12 +0100
commitfbcb7fe589edbfe79d10d7fe01be8a9f77926b89 (patch)
treea7e5a695db24fb32d2baff4eb35baa795aa5be1e /lib/asn1
parenta822c4a25d9855381632c124ed8ca0882a792e96 (diff)
downloadotp-fbcb7fe589edbfe79d10d7fe01be8a9f77926b89.tar.gz
otp-fbcb7fe589edbfe79d10d7fe01be8a9f77926b89.tar.bz2
otp-fbcb7fe589edbfe79d10d7fe01be8a9f77926b89.zip
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.
Diffstat (limited to 'lib/asn1')
-rw-r--r--lib/asn1/src/Makefile3
-rw-r--r--lib/asn1/src/asn1ct_eval_per.funcs3
-rw-r--r--lib/asn1/src/asn1ct_eval_uper.funcs2
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl84
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl76
-rw-r--r--lib/asn1/src/asn1rtt_per.erl1
-rw-r--r--lib/asn1/src/asn1rtt_uper.erl3
-rw-r--r--lib/asn1/test/asn1_app_test.erl2
8 files changed, 51 insertions, 123 deletions
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) ->
+ <<E:1,(apply(asn1ct_eval_uper, F, Args))/bitstring>>.
+
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;