asn1ct_constructed_ber.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,497 行 · 第 1/4 页

ERL
1,497
字号
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(asn1ct_constructed_ber).-export([gen_encode_sequence/3]).-export([gen_decode_sequence/3]).-export([gen_encode_set/3]).-export([gen_decode_set/3]).-export([gen_encode_sof/4]).-export([gen_decode_sof/4]).-export([gen_encode_choice/3]).-export([gen_decode_choice/3]).%%%% Application internal exports -export([match_tag/2]).-include("asn1_records.hrl").-import(asn1ct_gen, [emit/1,demit/1]).% the encoding of class of tag bits 8 and 7-define(UNIVERSAL,   0).-define(APPLICATION, 16#40).-define(CONTEXT,     16#80).-define(PRIVATE,     16#C0).% primitive or constructed encoding % bit 6-define(PRIMITIVE,   0).-define(CONSTRUCTED, 2#00100000).%%===============================================================================%%===============================================================================%%===============================================================================%%  Encode/decode SEQUENCE%%===============================================================================%%===============================================================================%%===============================================================================gen_encode_sequence(Erules,Typename,D) when record(D,type) ->    asn1ct_name:start(),    asn1ct_name:new(term),    asn1ct_name:new(bytes),        %% if EXTERNAL type the input value must be transformed to     %% ASN1 1990 format    case Typename of	['EXTERNAL'] ->	    emit(["   NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",		  nl]);	_ ->	    ok    end,    {SeqOrSet,TableConsInfo,CompList} = 	case D#type.def of	    #'SEQUENCE'{tablecinf=TCI,components=CL} -> 		{'SEQUENCE',TCI,CL};	    #'SET'{tablecinf=TCI,components=CL} -> 		{'SET',TCI,CL}	end,    Ext = extensible(CompList),    CompList1 = case CompList of		    {Rl,El} -> Rl ++ El;		    _ -> CompList		end,    EncObj =	case TableConsInfo of	    #simpletableattributes{usedclassfield=Used,				   uniqueclassfield=Unique} when Used /= Unique ->		false;	    %% ObjectSet, name of the object set in constraints	    %% 	    %%{ObjectSet,AttrN,N,UniqueFieldName}	    #simpletableattributes{objectsetname=ObjectSet,				   c_name=AttrN,				   c_index=N,				   usedclassfield=UniqueFieldName,				   uniqueclassfield=UniqueFieldName,				   valueindex=ValueIndex				  } ->		OSDef =		    case ObjectSet of			{Module,OSName} ->			    asn1_db:dbget(Module,OSName);			OSName ->			    asn1_db:dbget(get(currmod),OSName)		    end,%		io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",%			  [get(currmod),OSName,AttrN,N,UniqueFieldName]),		case (OSDef#typedef.typespec)#'ObjectSet'.gen of		    true ->% 			Val = lists:concat(["?RT_BER:cindex(",% 					    N+1,",Val,"]),			ObjectEncode = 			    asn1ct_gen:un_hyphen_var(lists:concat(['Obj',								   AttrN])),			emit({ObjectEncode," = ",nl}),			emit({"  'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},			      ", ",nl}),%			emit({indent(35),"?RT_BER:cindex(",N+1,", Val,",%			      {asis,AttrN},")),",nl}),			emit([indent(10+length(atom_to_list(ObjectSet))),			      "value_match(",{asis,ValueIndex},",",			      "?RT_BER:cindex(",N+1,",Val,",			      {asis,AttrN},"))),",nl]),			notice_value_match(),			{AttrN,ObjectEncode};		    _ ->			false		end;	    _ ->		case D#type.tablecinf of		    [{objfun,_}|_] ->			%% when the simpletableattributes was at an			%% outer level and the objfun has been passed			%% through the function call			{"got objfun through args","ObjFun"};		    _ ->			false		end	end,    gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]	++ 	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),	      number = asn1ct_gen_ber:decode_type(SeqOrSet),	      form = ?CONSTRUCTED,	      type = 'IMPLICIT'}],    emit([nl,"   BytesSoFar = "]),    case SeqOrSet of	'SET' when (D#type.def)#'SET'.sorted == dynamic ->	    emit("asn1rt_check:dynamicsort_SET_components(["),	    mkvlist(asn1ct_name:all(encBytes)),	    emit(["]),",nl]);	_ ->	    emit("["),	    mkvlist(asn1ct_name:all(encBytes)),	    emit(["],",nl])    end,    emit("  LenSoFar = "),    case asn1ct_name:all(encLen) of	[] -> emit("0");	AllLengths -> 	    mkvplus(AllLengths)    end,    emit([",",nl]),% emit(["{TagBytes,Len} = ?RT_BER:encode_tags(TagIn ++ ", emit(["  ?RT_BER:encode_tags(TagIn ++ ", 		  {asis,MyTag},", BytesSoFar, LenSoFar).",nl]).gen_decode_sequence(Erules,Typename,D) when record(D,type) ->    asn1ct_name:start(),%    asn1ct_name:new(term),    asn1ct_name:new(tag),    #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,    Ext = extensible(CList),    CompList = case CList of		   {Rl,El}  -> Rl ++ El;		   _ -> CList	       end,    emit({"   %%-------------------------------------------------",nl}),    emit({"   %% decode tag and length ",nl}),    emit({"   %%-------------------------------------------------",nl}),    asn1ct_name:new(rb),    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]	++ 	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),	      number = asn1ct_gen_ber:decode_type('SEQUENCE'),	      form = ?CONSTRUCTED,	      type = 'IMPLICIT'}],    emit(["   {{_,",asn1ct_gen_ber:unused_var("Len",D#type.def),"},",{next,bytes},",",{curr,rb},	  "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",	  {curr,bytes},", OptOrMand), ",nl]),    asn1ct_name:new(bytes),    asn1ct_name:new(len),    case CompList of	[] -> true;	_ ->	    emit({"{",{next,bytes},		  ",RemBytes} = ?RT_BER:split_list(",		  {curr,bytes},		  ",", {prev,len},"),",nl}),	    asn1ct_name:new(bytes)    end,        {DecObjInf,UniqueFName,ValueIndex} =	case TableConsInfo of	    #simpletableattributes{objectsetname=ObjectSet,				   c_name=AttrN,				   usedclassfield=UniqueFieldName,				   uniqueclassfield=UniqueFieldName,				   valueindex=ValIndex				  } ->		F = fun(#'ComponentType'{typespec=CT})->			    case {asn1ct_gen:get_constraint(CT#type.constraint,componentrelation),CT#type.tablecinf} of%			    case {CT#type.constraint,CT#type.tablecinf} of				{no,[{objfun,_}|_R]} -> true;				_ -> false			    end		    end,		case lists:any(F,CompList) of		    %%AttributeName = asn1ct_gen:un_hyphen_var(AttrN),		    true -> % when component relation constraint establish			%% relation from a component to another components			%% subtype component			{{AttrN,{deep,ObjectSet,UniqueFieldName,					 ValIndex}},			 UniqueFieldName,ValIndex};		    false ->			{{AttrN,ObjectSet},UniqueFieldName,ValIndex}		end;	    _ ->		{false,false,false}	end,    case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of	no_terms -> % an empty sequence	    	    emit([nl,nl]),	    demit({"Result = "}), %dbg	    %% return value as record	    asn1ct_name:new(rb),	    emit(["   {{'",asn1ct_gen:list2rname(Typename),"'}, ",{curr,bytes},",",nl,"    "]),	    asn1ct_gen_ber:add_removed_bytes(),	    emit(["}.",nl]);	{LeadingAttrTerm,PostponedDecArgs} ->	    emit([com,nl,nl]),	    case {LeadingAttrTerm,PostponedDecArgs} of		{[],[]} ->		    ok;		{_,[]} ->		    ok;		{[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->		    DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),		    ValueMatch = value_match(ValueIndex,Term),		    emit([DecObj," =",nl,"   'getdec_",ObjSet,"'(",%			  {asis,UniqueFName},", ",Term,"),",nl}),			  {asis,UniqueFName},", ",ValueMatch,"),",nl]),		    gen_dec_postponed_decs(DecObj,PostponedDecArgs)	    end,	    demit({"Result = "}), %dbg	    %% return value as record	    asn1ct_name:new(rb),	    asn1ct_name:new(bytes),	    ExtStatus = case Ext of			    {ext,_,_} -> ext;			    noext -> noext			end,	    emit(["   {",{next,bytes},",",{curr,rb},"} = ?RT_BER:restbytes2(RemBytes, ",		  {curr,bytes},",",ExtStatus,"),",nl]),	    asn1ct_name:new(rb),	    case Typename of		['EXTERNAL'] ->		    emit(["   OldFormat={'",asn1ct_gen:list2rname(Typename),			  "', "]),		    mkvlist(asn1ct_name:all(term)),		    emit(["},",nl]),		    emit(["   ASN11994Format =",nl,			  "      asn1rt_check:transform_to_EXTERNAL1994",			  "(OldFormat),",nl]),		    emit(["   {ASN11994Format,",{next,bytes},", "]);		_ ->		    emit(["   {{'",asn1ct_gen:list2rname(Typename),"', "]),		    mkvlist(asn1ct_name:all(term)),		    emit(["}, ",{next,bytes},", "])	    end,	    asn1ct_gen_ber:add_removed_bytes(),	    emit(["}.",nl])    end.gen_dec_postponed_decs(_,[]) ->    emit(nl);gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->%    asn1ct_name:new(term),    asn1ct_name:new(tmpterm),    asn1ct_name:new(reason),    emit({"{",Term,", _, _} = ",nl}),    N = case OptOrMand of	    mandatory -> 0;	    'OPTIONAL' -> 		emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),		6;	    {'DEFAULT',Val} ->		emit_opt_or_mand_check(Val,TmpTerm),		6	end,    emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},%	  ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),	  ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),    emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),    emit({indent(N+9),"exit({'Type not compatible with table constraint',",	  {curr,reason},"});",nl}),    emit({indent(N+6),{curr,tmpterm}," ->",nl}),    emit({indent(N+9),{curr,tmpterm},nl}),    case OptOrMand of 	mandatory -> emit([indent(N+3),"end,",nl]);	_ ->	    emit([indent(N+3),"end",nl,		  indent(3),"end,",nl])    end,%    emit({indent(3),"end,",nl}),    gen_dec_postponed_decs(DecObj,Rest).emit_opt_or_mand_check(Value,TmpTerm) ->    emit([indent(3),"case ",TmpTerm," of",nl,	  indent(6),{asis,Value}," -> {",{asis,Value},",[],[]};",nl,	  indent(6),"_ ->",nl]).%%============================================================================%%  Encode/decode SET%%%%============================================================================gen_encode_set(Erules,Typename,D) when record(D,type) ->    gen_encode_sequence(Erules,Typename,D).gen_decode_set(Erules,Typename,D) when record(D,type) ->    asn1ct_name:start(),    asn1ct_name:new(term),    asn1ct_name:new(tag),    #'SET'{components=TCompList} = D#type.def,    Ext = extensible(TCompList),    CompList = case TCompList of		   {Rl,El} -> Rl ++ El;		   _ -> TCompList	       end,    emit(["   %%-------------------------------------------------",nl]),    emit(["   %% decode tag and length ",nl]),    emit(["   %%-------------------------------------------------",nl]),    asn1ct_name:new(rb),    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]	++ 	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),	      number = asn1ct_gen_ber:decode_type('SET'),	      form = ?CONSTRUCTED,	      type = 'IMPLICIT'}],    emit(["   {{_,Len},",{next,bytes},",",{curr,rb},	  "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",	  {curr,bytes},", OptOrMand), ",nl]),    asn1ct_name:new(bytes),    asn1ct_name:new(len),    asn1ct_name:new(rb),    emit(["   {SetTerm, SetBytes, ",{curr,rb},"} = ?RT_BER:decode_set(0, Len, ",	  {curr,bytes},", OptOrMand, ",	  "fun 'dec_",asn1ct_gen:list2name(Typename),"_fun'/2, []),",nl]),        asn1ct_name:new(rb),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?