From c2ec5589d5eaf9ef791932a187b4527ab737e3c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Fri, 8 Mar 2013 15:11:05 +0100
Subject: BER: Optimize handling of constraints for INTEGERs

This slight optimization will also eliminate some Dialyzer warnings.
---
 lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 73 ++++++++++++++++++----------------
 lib/asn1/src/asn1rtt_ber.erl           | 31 +++++++--------
 2 files changed, 53 insertions(+), 51 deletions(-)

diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 4073643f9e..c57bb6a335 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -458,16 +458,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
 %%    Constraint = Att#type.constraint,
 %% Constraint = [],
     Constraint = get_size_constraint(Att#type.constraint),
-    ValueRange = 
-	case get_constraint(Att#type.constraint,'ValueRange') of
-	    no -> [];
-	    Tv -> Tv
-	end,
-    SingleValue = 
-	case get_constraint(Att#type.constraint,'SingleValue') of
-	    no -> [];
-	    Sv -> Sv
-	end,
+    IntConstr = int_constr(Att#type.constraint),
     AsBin = case get(binary_strings) of
 		true -> "_as_bin";
 		_ -> ""
@@ -490,14 +481,27 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
 	    emit(["decode_boolean(",BytesVar,","]),
 	    need(decode_boolean, 2);
 	'INTEGER' ->
-	    emit(["decode_integer(",BytesVar,",",
-		  {asis,int_constr(SingleValue,ValueRange)},","]),
-	    need(decode_integer, 3);
+	    case IntConstr of
+		[] ->
+		    emit(["decode_integer(",BytesVar,","]),
+		    need(decode_integer, 2);
+		{_,_} ->
+		    emit(["decode_integer(",BytesVar,",",
+			  {asis,IntConstr},","]),
+		    need(decode_integer, 3)
+	    end;
 	{'INTEGER',NamedNumberList} ->
-	    emit(["decode_integer(",BytesVar,",",
-		  {asis,int_constr(SingleValue,ValueRange)},",",
-		  {asis,NamedNumberList},","]),
-	    need(decode_integer, 4);
+	    case IntConstr of
+		[] ->
+		    emit(["decode_named_integer(",BytesVar,",",
+			  {asis,NamedNumberList},","]),
+		    need(decode_named_integer, 3);
+		{_,_} ->
+		    emit(["decode_named_integer(",BytesVar,",",
+			  {asis,IntConstr},",",
+			  {asis,NamedNumberList},","]),
+		    need(decode_named_integer, 4)
+	    end;
 	{'ENUMERATED',NamedNumberList} ->
 	    emit(["decode_enumerated(",BytesVar,",",
 		  {asis,NamedNumberList},","]),
@@ -591,15 +595,23 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
 	    emit([TagStr,")"])
     end.
 
-
-int_constr([],[]) ->
-    [];
-int_constr([],ValueRange) ->
-    ValueRange;
-int_constr(SingleValue,[]) ->
-    SingleValue;
-int_constr(SV,VR) ->
-    [SV,VR].
+%% Simplify an integer constraint so that we can efficiently test it.
+-spec int_constr(term()) -> [] | {integer(),integer()|'MAX'}.
+int_constr(C) ->
+    case asn1ct_imm:effective_constraint(integer, C) of
+	[{_,[]}] ->
+	    %% Extension - ignore constraint.
+	    [];
+	[{'ValueRange',{'MIN',_}}] ->
+	    %% Tricky to implement efficiently - ignore it.
+	    [];
+	[{'ValueRange',{_,_}=Range}] ->
+	    Range;
+	[{'SingleValue',Sv}] ->
+	    {Sv,Sv};
+	[] ->
+	    []
+    end.
 
 gen_dec_bit_string(BytesVar, _Constraint, [_|_]=NNL, TagStr) ->
     call(decode_named_bit_string,
@@ -1481,15 +1493,6 @@ get_size_constraint(C) ->
 	{_,{_,_}=Tc} -> Tc
     end.
 
-get_constraint(C,Key) ->
-    case lists:keysearch(Key,1,C) of
-	false ->
-	     no;
-	{value,{_,V}} -> 
-	    V
-    end.
-
-
 get_class_fields(#classdef{typespec=ObjClass}) ->
     ObjClass#objectclass.fields;
 get_class_fields(#objectclass{fields=Fields}) ->
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
index 509c091355..499db701d9 100644
--- a/lib/asn1/src/asn1rtt_ber.erl
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -27,7 +27,8 @@
 	 skip_ExtensionAdditions/2]).
 -export([encode_boolean/2,decode_boolean/2,
 	 encode_integer/2,encode_integer/3,
-	 decode_integer/3,decode_integer/4,
+	 decode_integer/2,decode_integer/3,
+	 decode_named_integer/3,decode_named_integer/4,
 	 encode_enumerated/2,decode_enumerated/3,
 	 encode_bit_string/4,
 	 decode_named_bit_string/3,
@@ -700,11 +701,20 @@ encode_integer_neg(N, Acc) ->
 %%    (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
 %%===============================================================================
 
-decode_integer(Tlv, Range, NamedNumberList, TagIn) ->
+decode_named_integer(Tlv, NamedNumberList, TagIn) ->
+    V = match_tags(Tlv, TagIn),
+    Int = decode_integer(V),
+    number2name(Int, NamedNumberList).
+
+decode_named_integer(Tlv, Range, NamedNumberList, TagIn) ->
     V = match_tags(Tlv, TagIn),
     Int = range_check_integer(decode_integer(V), Range),
     number2name(Int, NamedNumberList).
 
+decode_integer(Tlv, TagIn) ->
+    V = match_tags(Tlv, TagIn),
+    decode_integer(V).
+
 decode_integer(Tlv, Range, TagIn) ->
     V = match_tags(Tlv, TagIn),
     Int = decode_integer(V),
@@ -715,21 +725,10 @@ decode_integer(Bin) ->
     <<Int:Len/signed-unit:8>> = Bin,
     Int.
 
+range_check_integer(Int, {Lb,Ub}) when Lb =< Int, Int =< Ub ->
+    Int;
 range_check_integer(Int, Range) ->
-    case Range of
-	[] -> % No length constraint
-	    Int;
-	{Lb,Ub} when Int >= Lb, Ub >= Int -> % variable length constraint
-	    Int;
-	{_,_} ->
-	    exit({error,{asn1,{integer_range,Range,Int}}});
-	Int -> % fixed value constraint
-	    Int;
-	SingleValue when is_integer(SingleValue) ->
-	    exit({error,{asn1,{integer_range,Range,Int}}});
-	_ -> % some strange constraint that we don't support yet
-	    Int
-    end.
+    exit({error,{asn1,{integer_range,Range,Int}}}).
 
 number2name(Int, []) ->
     Int;
-- 
cgit v1.2.3