aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/asn1ct_constructed_per.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src/asn1ct_constructed_per.erl')
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl1125
1 files changed, 538 insertions, 587 deletions
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index d279e9697f..8d4afc0a0b 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -43,10 +43,13 @@ gen_encode_set(Erules,TypeName,D) ->
gen_encode_sequence(Erules,TypeName,D) ->
gen_encode_constructed(Erules,TypeName,D).
-gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
+gen_encode_constructed(Erule, Typename, #type{}=D) ->
asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
+ Imm = gen_encode_constructed_imm(Erule, Typename, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
+
+gen_encode_constructed_imm(Erule, Typename, #type{}=D) ->
{ExtAddGroup,TmpCompList,TableConsInfo} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} ->
@@ -65,74 +68,36 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
[Comp#'ComponentType'{textual_order=undefined}||
Comp<-TmpCompList]
end,
- case Typename of
- ['EXTERNAL'] ->
- emit([{next,val}," = ",
- {call,ext,transform_to_EXTERNAL1990,
- [{curr,val}]},com,nl]),
- asn1ct_name:new(val);
- _ ->
- ok
- end,
- case {Optionals = optionals(to_textual_order(CompList)),CompList,
- is_optimized(Erule)} of
- {[],EmptyCL,_} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
- ok;
- {[],_,_} ->
- emit([{next,val}," = ",{curr,val},",",nl]);
- {_,_,true} ->
- gen_fixoptionals(Optionals),
- FixOpts = param_map(fun(Var) ->
- {var,Var}
- end,asn1ct_name:all(fixopt)),
- emit({"{",{next,val},",Opt} = {",{curr,val},",[",FixOpts,"]},",nl});
- {_,_,false} ->
- asn1ct_func:need({Erule,fixoptionals,3}),
- Fixoptcall = ",Opt} = fixoptionals(",
- emit({"{",{next,val},Fixoptcall,
- {asis,Optionals},",",length(Optionals),
- ",",{curr,val},"),",nl})
- end,
- asn1ct_name:new(val),
+ ExternalImm =
+ case Typename of
+ ['EXTERNAL'] ->
+ Next = asn1ct_gen:mk_var(asn1ct_name:next(val)),
+ Curr = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ asn1ct_name:new(val),
+ [{call,ext,transform_to_EXTERNAL1990,[{var,Curr}],{var,Next}}];
+ _ ->
+ []
+ end,
+ Aligned = is_aligned(Erule),
+ Value0 = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ Optionals = optionals(to_textual_order(CompList)),
+ ImmOptionals = [asn1ct_imm:per_enc_optional(Value0, Opt, Aligned) ||
+ Opt <- Optionals],
Ext = extensible_enc(CompList),
- case Ext of
- {ext,_,NumExt} when NumExt > 0 ->
- case extgroup_pos_and_length(CompList) of
- {extgrouppos,[]} -> % no extenstionAdditionGroup
- ok;
- {extgrouppos,ExtGroupPosLenList} ->
- ExtGroupFun =
- fun({ExtActualGroupPos,ExtGroupVirtualPos,ExtGroupLen}) ->
- Elements =
- make_elements(ExtGroupVirtualPos+1,
- "Val1",
- lists:seq(1,ExtGroupLen)),
- emit([
- {next,val}," = case [X || X <- [",Elements,
- "],X =/= asn1_NOVALUE] of",nl,
- "[] -> setelement(",
- {asis,ExtActualGroupPos+1},",",
- {curr,val},",",
- "asn1_NOVALUE);",nl,
- "_ -> setelement(",{asis,ExtActualGroupPos+1},",",
- {curr,val},",",
- "{extaddgroup,", Elements,"})",nl,
- "end,",nl]),
- asn1ct_name:new(val)
- end,
- lists:foreach(ExtGroupFun,ExtGroupPosLenList)
- end,
- asn1ct_name:new(tmpval),
- emit(["Extensions = ",
- {call,Erule,fixextensions,[{asis,Ext},{curr,val}]},
- com,nl]);
- _ -> true
- end,
- EncObj =
+ ExtImm = case Ext of
+ {ext,ExtPos,NumExt} when NumExt > 0 ->
+ gen_encode_extaddgroup(CompList),
+ Value = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ asn1ct_imm:per_enc_extensions(Value, ExtPos,
+ NumExt, Aligned);
+ _ ->
+ []
+ end,
+ {EncObj,ObjSetImm} =
case TableConsInfo of
#simpletableattributes{usedclassfield=Used,
uniqueclassfield=Unique} when Used /= Unique ->
- false;
+ {false,[]};
%% ObjectSet, name of the object set in constraints
%%
%%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
@@ -152,13 +117,10 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
El = make_element(N+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))),
ValueMatch = value_match(ValueIndex, El),
- emit([ObjectEncode," =",nl,
- " ",{asis,Module},":'getenc_",ObjSetName,"'(",
- {asis,UniqueFieldName},", ",nl,
- " ",ValueMatch,"),",nl]),
- {AttrN,ObjectEncode};
+ ObjSetImm0 = [{assign,{var,ObjectEncode},ValueMatch}],
+ {{AttrN,ObjectEncode},ObjSetImm0};
false ->
- false
+ {false,[]}
end;
_ ->
case D#type.tablecinf of
@@ -166,34 +128,52 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
%% when the simpletableattributes was at an outer
%% level and the objfun has been passed through the
%% function call
- {"got objfun through args","ObjFun"};
+ {{"got objfun through args","ObjFun"},[]};
_ ->
- false
+ {false,[]}
end
end,
- emit({"[",nl}),
- MaybeComma1 =
+ ImmSetExt =
case Ext of
- {ext,_Pos,NumExt2} when NumExt2 > 0 ->
- call(Erule, setext, ["Extensions =/= []"]),
- ", ";
- {ext,_Pos,_} ->
- call(Erule, setext, ["false"]),
- ", ";
- _ ->
- ""
- end,
- MaybeComma2 =
- case optionals(CompList) of
- [] -> MaybeComma1;
- _ ->
- emit(MaybeComma1),
- emit("Opt"),
- {",",nl}
+ {ext,_Pos,NumExt2} when NumExt2 > 0 ->
+ asn1ct_imm:per_enc_extension_bit('Extensions', Aligned);
+ {ext,_Pos,_} ->
+ asn1ct_imm:per_enc_extension_bit([], Aligned);
+ _ ->
+ []
end,
- gen_enc_components_call(Erule,Typename,CompList,MaybeComma2,EncObj,Ext),
- emit({"].",nl}).
+ ImmBody = gen_enc_components_call(Erule, Typename, CompList, EncObj, Ext),
+ ExternalImm ++ ExtImm ++ ObjSetImm ++
+ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody).
+
+gen_encode_extaddgroup(CompList) ->
+ case extgroup_pos_and_length(CompList) of
+ {extgrouppos,[]} ->
+ ok;
+ {extgrouppos,ExtGroupPosLenList} ->
+ _ = [do_gen_encode_extaddgroup(G) || G <- ExtGroupPosLenList],
+ ok
+ end.
+do_gen_encode_extaddgroup({ActualGroupPos,GroupVirtualPos,GroupLen}) ->
+ Val = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ Elements = make_elements(GroupVirtualPos+1,
+ Val,
+ lists:seq(1, GroupLen)),
+ Expr = any_non_value(GroupVirtualPos+1, Val, GroupLen, ""),
+ emit([{next,val}," = case ",Expr," of",nl,
+ "false -> setelement(",{asis,ActualGroupPos+1},", ",
+ {curr,val},", asn1_NOVALUE);",nl,
+ "true -> setelement(",{asis,ActualGroupPos+1},", ",
+ {curr,val},", {extaddgroup,", Elements,"})",nl,
+ "end,",nl]),
+ asn1ct_name:new(val).
+
+any_non_value(_, _, 0, _) ->
+ [];
+any_non_value(Pos, Val, N, Sep) ->
+ Sep ++ [make_element(Pos, Val)," =/= asn1_NOVALUE"] ++
+ any_non_value(Pos+1, Val, N-1, [" orelse",nl]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% generate decode function for SEQUENCE and SET
@@ -328,28 +308,29 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) ->
EmitComp = gen_dec_components_call(Erule, Typename, CompList,
DecObjInf, Ext, length(Optionals)),
EmitRest = fun({AccTerm,AccBytes}) ->
- gen_dec_constructed_imm_2(Typename, CompList,
+ gen_dec_constructed_imm_2(Erule, Typename,
+ CompList,
ObjSetInfo,
AccTerm, AccBytes)
end,
[EmitExt,EmitOpt|EmitComp++[{safe,EmitRest}]].
-gen_dec_constructed_imm_2(Typename, CompList,
+gen_dec_constructed_imm_2(Erule, Typename, CompList,
ObjSetInfo, AccTerm, AccBytes) ->
- {_,UniqueFName,ValueIndex} = ObjSetInfo,
+ {_,_UniqueFName,ValueIndex} = ObjSetInfo,
case {AccTerm,AccBytes} of
{[],[]} ->
ok;
{_,[]} ->
ok;
{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} = ObjSet,
- emit([DecObj," =",nl,
- " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
- gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
+ ValueMatch = value_match(ValueIndex, Term),
+ _ = [begin
+ gen_dec_open_type(Erule, ValueMatch, ObjSet,
+ LeadingAttr, T),
+ emit([com,nl])
+ end || T <- ListOfOpenTypes],
+ ok
end,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
@@ -423,67 +404,143 @@ to_textual_order(Cs) when is_list(Cs) ->
to_textual_order(Cs) ->
Cs.
-gen_dec_listofopentypes(_,[],_) ->
- emit(nl);
-gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
-
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
-
- emit([Term," = ",nl]),
+gen_dec_open_type(Erule, Val, {Xmod,Xtype}, LeadingAttr,
+ {_,{Name,RestFieldNames},Term,TmpTerm,Prop}) ->
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({decode,ObjSet,RestFieldNames,
+ Prop,Extensible})),
+ Typename = [Name,ClType],
+ Gen = fun(_Fd, N) ->
+ dec_objset_optional(N, Prop),
+ dec_objset(Erule, N, ObjSet, RestFieldNames, Typename),
+ dec_objset_default(N, Name, LeadingAttr, Extensible)
+ end,
+ Prefix = lists:concat(["dec_os_",Name]),
+ F = asn1ct_func:call_gen(Prefix, Key, Gen),
+ emit([Term," = ",{asis,F},"(",TmpTerm,", ",Val,")"]).
+
+dec_objset_optional(N, {'DEFAULT',Val}) ->
+ dec_objset_optional_1(N, Val),
+ dec_objset_optional_1(N, asn1_DEFAULT);
+dec_objset_optional(N, 'OPTIONAL') ->
+ dec_objset_optional_1(N, asn1_NOVALUE);
+dec_objset_optional(_N, mandatory) -> ok.
+
+dec_objset_optional_1(N, Val) ->
+ emit([{asis,N},"(",{asis,Val},", _Id) ->",nl,
+ {asis,Val},";",nl]).
+
+dec_objset(_Erule, _N, [], _, _) ->
+ ok;
+dec_objset(Erule, N, [Obj|Objs], RestFields, Cl) ->
+ dec_objset_1(Erule, N, Obj, RestFields, Cl),
+ emit([";",nl]),
+ dec_objset(Erule, N, Objs, RestFields, Cl).
+
+dec_objset_default(N, C, LeadingAttr, false) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl,
+ "exit({'Type not compatible with table constraint',"
+ "{{component,",{asis,C},"},"
+ "{value,Bytes},"
+ "{unique_name_and_value,",{asis,LeadingAttr},",Id}}}).",nl,nl]);
+dec_objset_default(N, _, _, true) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl,
+ "Bytes.",nl,nl]).
+
+dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) ->
+ emit([{asis,N},"(Bytes, ",{asis,Id},") ->",nl]),
+ dec_objset_2(Erule, Obj, RestFields, Typename).
+
+dec_objset_2(Erule, Obj, RestFields0, Typename) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Type} ->
+ Imm = asn1ct_gen_per:gen_dec_imm(Erule, Type),
+ {Term,_} = asn1ct_imm:dec_slim_cg(Imm, 'Bytes'),
+ emit([com,nl,Term]);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ {'CHOICE',CompList} = Def#type.def,
+ Ext = extensible_enc(CompList),
+ emit(["{Result,_} = begin",nl]),
+ gen_dec_choice(Erule, Typename, CompList, Ext),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SET OF',
+ Def, false);
+ 'SEQUENCE' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SEQUENCE OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SEQUENCE OF',
+ Def, false)
+ end;
+ #typedef{name=Type} ->
+ emit(["{Result,_} = ",{asis,enc_func("dec_", Type)},"(Bytes),",nl,
+ "Result"]);
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ emit("{Term,_} = "),
+ Func = enc_func("dec_", Type),
+ case get(currmod) of
+ Mod ->
+ emit([{asis,Func},"(Bytes)"]);
+ _ ->
+ emit([{asis,Mod},":",{asis,Func},"(Bytes)"])
+ end,
+ emit([com,nl,
+ "Term"]);
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFields] = RestFields0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ dec_objset_2(Erule, Typedef, RestFields, Typename)
+ end
+ end.
- N = case Prop of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
+gen_encode_choice(Erule, TopType, D) ->
+ asn1ct_name:start(),
+ Imm = gen_encode_choice_imm(Erule, TopType, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
- emit([indent(N+3),"case (catch ",DecObj,"(",
- {asis,FirstPFN},", ",TmpTerm,", telltype,",{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 Prop of
- mandatory ->
- emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
- gen_dec_listofopentypes(DecObj,Rest,true).
-
-
-emit_opt_or_mand_check(Val,Term) ->
- emit([indent(3),"case ",Term," of",nl,
- indent(6),{asis,Val}," ->",{asis,Val},";",nl,
- indent(6),"_ ->",nl]).
-
-%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
-%% assume Val = {Alternative,AltType}
-%% generate
-%%[
-%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
-%%case element(1,Val) of
-%% alt1 ->
-%% encode_alt1(element(2,Val));
-%% alt2 ->
-%% encode_alt2(element(2,Val))
-%%end
-%%].
-
-gen_encode_choice(Erule,Typename,D) when is_record(D,type) ->
- {'CHOICE',CompList} = D#type.def,
- emit({"[",nl}),
+gen_encode_choice_imm(Erule, TopType, #type{def={'CHOICE',CompList}}) ->
Ext = extensible_enc(CompList),
- gen_enc_choice(Erule,Typename,CompList,Ext),
- emit({nl,"].",nl}).
+ Aligned = is_aligned(Erule),
+ Cs = gen_enc_choice(Erule, TopType, CompList, Ext),
+ [{assign,{expr,"{ChoiceTag,ChoiceVal}"},"Val"}|
+ asn1ct_imm:per_enc_choice('ChoiceTag', Cs, Aligned)].
gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
@@ -496,72 +553,48 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Encode generator for SEQUENCE OF type
-
-gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_encode_sof(Erule, Typename, SeqOrSetOf, D) ->
asn1ct_name:start(),
- {_SeqOrSetOf,ComponentType} = D#type.def,
- emit({"[",nl}),
- SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
- D#type.constraint),
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _->
- ""
- end,
- gen_encode_length(Erule, SizeConstraint),
- emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",ObjFun,", [])"}),
- emit({nl,"].",nl}),
- gen_encode_sof_components(Erule, Typename, SeqOrSetOf, ComponentType).
-
-
-%% Logic copied from asn1_per_bin_rt2ct:encode_constrained_number
-gen_encode_length(per, {Lb,Ub}) when Ub =< 65535, Lb >= 0 ->
- Range = Ub - Lb + 1,
- V2 = ["(length(Val) - ",Lb,")"],
- Encode = if
- Range == 1 ->
- "[]";
- Range == 2 ->
- {"[",V2,"]"};
- Range =< 4 ->
- {"[10,2,",V2,"]"};
- Range =< 8 ->
- {"[10,3,",V2,"]"};
- Range =< 16 ->
- {"[10,4,",V2,"]"};
- Range =< 32 ->
- {"[10,5,",V2,"]"};
- Range =< 64 ->
- {"[10,6,",V2,"]"};
- Range =< 128 ->
- {"[10,7,",V2,"]"};
- Range =< 255 ->
- {"[10,8,",V2,"]"};
- Range =< 256 ->
- {"[20,1,",V2,"]"};
- Range =< 65536 ->
- {"[20,2,<<",V2,":16>>]"};
- true ->
- {call,per,encode_length,
- [{asis,{Lb,Ub}},"length(Val)"]}
- end,
- emit({nl,Encode,",",nl});
-gen_encode_length(Erules, SizeConstraint) ->
- emit([nl,indent(3),
- case SizeConstraint of
- no ->
- {call,Erules,encode_length,["length(Val)"]};
- _ ->
- {call,Erules,encode_length,
- [{asis,SizeConstraint},"length(Val)"]}
- end,
- com,nl]).
+ Imm = gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl,nl]).
-gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) ->
+ {_SeqOrSetOf,ComponentType} = D#type.def,
+ Aligned = is_aligned(Erule),
+ Constructed_Suffix =
+ asn1ct_gen:constructed_suffix(SeqOrSetOf,
+ ComponentType#type.def),
+ Conttype = asn1ct_gen:get_inner(ComponentType#type.def),
+ Currmod = get(currmod),
+ Imm0 = case asn1ct_gen:type(Conttype) of
+ {primitive,bif} ->
+ asn1ct_gen_per:gen_encode_prim_imm('Comp', ComponentType, Aligned);
+ {constructed,bif} ->
+ TypeName = [Constructed_Suffix|Typename],
+ Enc = enc_func(asn1ct_gen:list2name(TypeName)),
+ ObjArg = case D#type.tablecinf of
+ [{objfun,_}|_] -> [{var,"ObjFun"}];
+ _ -> []
+ end,
+ [{apply,Enc,[{var,"Comp"}|ObjArg]}];
+ #'Externaltypereference'{module=Currmod,type=Ename} ->
+ [{apply,enc_func(Ename),[{var,"Comp"}]}];
+ #'Externaltypereference'{module=EMod,type=Ename} ->
+ [{apply,{EMod,enc_func(Ename)},[{var,"Comp"}]}];
+ 'ASN1_OPEN_TYPE' ->
+ asn1ct_gen_per:gen_encode_prim_imm('Comp',
+ #type{def='ASN1_OPEN_TYPE'},
+ Aligned)
+ end,
+ asn1ct_imm:per_enc_sof('Val', D#type.constraint, 'Comp', Imm0, Aligned).
+
+gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) ->
asn1ct_name:start(),
+ do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, true),
+ emit([".",nl,nl]).
+
+do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, NeedRest) ->
{_SeqOrSetOf,ComponentType} = D#type.def,
SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
D#type.constraint),
@@ -573,10 +606,16 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
""
end,
{Num,Buf} = gen_decode_length(SizeConstraint, Erules),
+ Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,
+ ComponentType,NeedRest})),
+ Gen = fun(_Fd, Name) ->
+ gen_decode_sof_components(Erules, Name,
+ Typename, SeqOrSetOf,
+ ComponentType, NeedRest)
+ end,
+ F = asn1ct_func:call_gen("dec_components", Key, Gen),
emit([",",nl,
- "'dec_",asn1ct_gen:list2name(Typename),
- "_components'(",Num,", ",Buf,ObjFun,", []).",nl,nl]),
- gen_decode_sof_components(Erules, Typename, SeqOrSetOf, ComponentType).
+ {asis,F},"(",Num,", ",Buf,ObjFun,", [])"]).
is_aligned(per) -> true;
is_aligned(uper) -> false.
@@ -586,7 +625,7 @@ gen_decode_length(Constraint, Erule) ->
Imm = asn1ct_imm:per_dec_length(Constraint, true, is_aligned(Erule)),
asn1ct_imm:dec_slim_cg(Imm, "Bytes").
-gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
+gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont, NeedRest) ->
{ObjFun,ObjFun_Var} =
case Cont#type.tablecinf of
[{objfun,_}|_R] ->
@@ -594,76 +633,38 @@ gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
_ ->
{"",""}
end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
- ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
- ObjFun,", Acc) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
- emit({ObjFun,", ["}),
- %% the component encoder
- Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
- Cont#type.def),
-
- Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Currmod = get(currmod),
- case asn1ct_gen:type(Conttype) of
- {primitive,bif} ->
- asn1ct_gen_per:gen_encode_prim(Erule, Cont, "H");
- {constructed,bif} ->
- NewTypename = [Constructed_Suffix|Typename],
- emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
- ObjFun,")",nl,nl});
- #'Externaltypereference'{module=Currmod,type=Ename} ->
- emit({"'enc_",Ename,"'(H)",nl,nl});
- #'Externaltypereference'{module=EMod,type=EType} ->
- emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
- 'ASN1_OPEN_TYPE' ->
- asn1ct_gen_per:gen_encode_prim(Erule,
- #type{def='ASN1_OPEN_TYPE'},
- "H");
- _ ->
- emit({"'enc_",Conttype,"'(H)",nl,nl})
+ case NeedRest of
+ false ->
+ emit([{asis,Name},"(0, _Bytes",ObjFun_Var,", Acc) ->",nl,
+ "lists:reverse(Acc);",nl]);
+ true ->
+ emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl,
+ "{lists:reverse(Acc),Bytes};",nl])
end,
- emit({" | Acc]).",nl}).
-
-gen_decode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
- {ObjFun,ObjFun_Var} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _"};
- _ ->
- {"",""}
- end,
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(0, Bytes",ObjFun_Var,", Acc) ->",nl,
- indent(3),"{lists:reverse(Acc), Bytes};",nl}),
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num, Bytes",ObjFun,", Acc) ->",nl}),
- emit({indent(3),"{Term,Remain} = "}),
+ emit([{asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl,
+ "{Term,Remain} = "]),
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
Cont#type.def),
Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Ctgenmod = asn1ct_gen:ct_gen_module(Erule),
case asn1ct_gen:type(Conttype) of
{primitive,bif} ->
- Ctgenmod:gen_dec_prim(Erule,Cont,"Bytes"),
+ asn1ct_gen_per:gen_dec_prim(Erule, Cont, "Bytes"),
emit({com,nl});
{constructed,bif} ->
NewTypename = [Constructed_Suffix|Typename],
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(Bytes, telltype",ObjFun,"),",nl});
+ "'(Bytes",ObjFun,"),",nl});
#'Externaltypereference'{}=Etype ->
asn1ct_gen_per:gen_dec_external(Etype, "Bytes"),
emit([com,nl]);
'ASN1_OPEN_TYPE' ->
- Ctgenmod:gen_dec_prim(Erule,#type{def='ASN1_OPEN_TYPE'},
- "Bytes"),
+ asn1ct_gen_per:gen_dec_prim(Erule, #type{def='ASN1_OPEN_TYPE'},
+ "Bytes"),
emit({com,nl});
_ ->
- emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
+ emit({"'dec_",Conttype,"'(Bytes),",nl})
end,
- emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num-1, Remain",ObjFun,", [Term|Acc]).",nl}).
+ emit([{asis,Name},"(Num-1, Remain",ObjFun,", [Term|Acc]).",nl]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -754,27 +755,6 @@ gen_dec_optionals(Optionals) ->
end,
{imm,Imm0,E}.
-gen_fixoptionals([{Pos,Def}|R]) ->
- asn1ct_name:new(fixopt),
- emit({{curr,fixopt}," = case element(",{asis,Pos},",",{curr,val},") of",nl,
- "asn1_DEFAULT -> 0;",nl,
- {asis,Def}," -> 0;",nl,
- "_ -> 1",nl,
- "end,",nl}),
- gen_fixoptionals(R);
-gen_fixoptionals([Pos|R]) ->
- gen_fixoptionals([{Pos,asn1_NOVALUE}|R]);
-gen_fixoptionals([]) ->
- ok.
-
-
-param_map(Fun, [H]) ->
- [Fun(H)];
-param_map(Fun, [H|T]) ->
- [Fun(H),","|param_map(Fun,T)].
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Produce a list with positions (in the Value record) where
%% there are optional components, start with 2 because first element
@@ -788,15 +768,13 @@ optionals({L1,Ext,L2}) ->
optionals({L,_Ext}) -> optionals(L,[],2);
optionals(L) -> optionals(L,[],2).
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[Pos|Acc],Pos+1);
-optionals([#'ComponentType'{prop={'DEFAULT',Val}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Pos,Val}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
+optionals([#'ComponentType'{prop='OPTIONAL'}|Rest], Acc, Pos) ->
+ optionals(Rest, [Pos|Acc], Pos+1);
+optionals([#'ComponentType'{prop={'DEFAULT',Val}}|Rest], Acc, Pos) ->
+ optionals(Rest, [{Pos,Val}|Acc], Pos+1);
+optionals([#'ComponentType'{}|Rest], Acc, Pos) ->
+ optionals(Rest, Acc, Pos+1);
+optionals([], Acc, _) ->
lists:reverse(Acc).
%%%%%%%%%%%%%%%%%%%%%%
@@ -858,33 +836,32 @@ add_textual_order1(Cs,NumIn) ->
end,
NumIn,Cs).
-gen_enc_components_call(Erule,TopType,{Root,ExtList},MaybeComma,DynamicEnc,Ext) ->
- gen_enc_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2},MaybeComma,DynamicEnc,Ext) ->
+gen_enc_components_call(Erule,TopType,{Root,ExtList}, DynamicEnc,Ext) ->
+ gen_enc_components_call(Erule,TopType,{Root,ExtList,[]}, DynamicEnc,Ext);
+gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2}, DynamicEnc,Ext) ->
%% The type has extensionmarker
- Rpos = gen_enc_components_call1(Erule,TopType,Root++Root2,1,MaybeComma,DynamicEnc,noext),
- case Ext of
- {ext,_,ExtNum} when ExtNum > 0 ->
- emit([nl,
- ",Extensions",nl]);
-
- _ -> true
- end,
+ {Imm0,Rpos} = gen_enc_components_call1(Erule,TopType,Root++Root2,1, DynamicEnc,noext,[]),
+ ExtImm = case Ext of
+ {ext,_,ExtNum} when ExtNum > 0 ->
+ [{var,"Extensions"}];
+ _ ->
+ []
+ end,
%handle extensions
{extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
- gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(Erule,TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
+ {Imm1,_} = gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,DynamicEnc,Ext,[]),
+ Imm0 ++ [ExtImm|Imm1];
+gen_enc_components_call(Erule,TopType, CompList, DynamicEnc, Ext) ->
%% The type has no extensionmarker
- gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
+ {Imm,_} = gen_enc_components_call1(Erule,TopType,CompList,1,DynamicEnc,Ext,[]),
+ Imm.
gen_enc_components_call1(Erule,TopType,
[C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
Tpos,
- MaybeComma, DynamicEnc, Ext) ->
+ DynamicEnc, Ext, Acc) ->
- put(component_type,{true,C}),
- %% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
TermNo =
case C#'ComponentType'.textual_order of
undefined ->
@@ -892,90 +869,48 @@ gen_enc_components_call1(Erule,TopType,
CanonicalNum ->
CanonicalNum
end,
- emit(MaybeComma),
- case Prop of
- 'OPTIONAL' ->
- gen_enc_component_optional(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext);
- {'DEFAULT',DefVal} ->
- gen_enc_component_default(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext,DefVal);
+ Element0 = make_element(TermNo+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))),
+ {Imm0,Element} = asn1ct_imm:enc_bind_var(Element0),
+ Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext),
+ Category = case {Prop,Ext} of
+ {'OPTIONAL',_} ->
+ optional;
+ {{'DEFAULT',DefVal},_} ->
+ {default,DefVal};
+ {_,{ext,ExtPos,_}} when Tpos >= ExtPos ->
+ optional;
+ {_,_} ->
+ mandatory
+ end,
+ Imm2 = case Category of
+ mandatory ->
+ Imm1;
+ optional ->
+ asn1ct_imm:enc_absent(Element, [asn1_NOVALUE], Imm1);
+ {default,Def} ->
+ asn1ct_imm:enc_absent(Element, [asn1_DEFAULT,Def], Imm1)
+ end,
+ Imm = case Imm2 of
+ [] -> [];
+ _ -> Imm0 ++ Imm2
+ end,
+ gen_enc_components_call1(Erule, TopType, Rest, Tpos+1, DynamicEnc, Ext, [Imm|Acc]);
+gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_, Acc) ->
+ ImmList = lists:reverse(Acc),
+ {ImmList,Pos}.
+
+gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext) ->
+ Imm0 = gen_enc_line_imm_1(Erule, TopType, Cname, Type,
+ Element, DynamicEnc),
+ Aligned = is_aligned(Erule),
+ case Ext of
+ {ext,_Ep2,_} ->
+ asn1ct_imm:per_enc_open_type(Imm0, Aligned);
_ ->
- case Ext of
- {ext,ExtPos,_} when Tpos >= ExtPos ->
- gen_enc_component_optional(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext);
- _ ->
- gen_enc_component_mandatory(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext)
- end
- end,
-
- erase(component_type),
+ Imm0
+ end.
- case Rest of
- [] ->
- Tpos+1;
- _ ->
- emit({com,nl}),
- gen_enc_components_call1(Erule,TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
- end;
-gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_,_) ->
- Pos.
-
-gen_enc_component_default(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext,DefaultVal) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
- emit({"case ",Element," of",nl}),
-% emit({"asn1_DEFAULT -> [];",nl}),
- emit({"DFLT when DFLT == asn1_DEFAULT; DFLT == ",{asis,DefaultVal}," -> [];",nl}),
-
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_optional(Erule,TopType,Cname,
- Type=#type{def=#'SEQUENCE'{
- extaddgroup=Number,
- components=_ExtGroupCompList}},
- Pos,DynamicEnc,Ext) when is_integer(Number) ->
-
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
- emit({"case ",Element," of",nl}),
-
- emit({"asn1_NOVALUE -> [];",nl}),
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"});
-gen_enc_component_optional(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
- emit({"case ",Element," of",nl}),
-
- emit({"asn1_NOVALUE -> [];",nl}),
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_mandatory(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- gen_enc_line(Erule,TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
-
-gen_enc_line(Erule,TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
- gen_enc_line(Erule,TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
-gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
+gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) ->
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
@@ -983,81 +918,157 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
_ ->
asn1ct_gen:get_inner(Type#type.def)
end,
-
- case Ext of
- {ext,_Ep1,_} ->
- asn1ct_func:need({Erule,encode_open_type,1}),
- asn1ct_func:need({Erule,complete,1}),
- emit(["encode_open_type(complete("]);
- _ -> true
- end,
-
+ Aligned = is_aligned(Erule),
case Atype of
{typefield,_} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
- case (Type#type.def)#'ObjectClassFieldType'.fieldname of
- {Name,RestFieldNames} when is_atom(Name) ->
- asn1ct_func:need({Erule,complete,1}),
- asn1ct_func:need({Erule,encode_open_type,1}),
- emit({"encode_open_type(complete(",nl}),
- emit({" ",Fun,"(",{asis,Name},", ",
- Element,", ",{asis,RestFieldNames},")))"});
- Other ->
- throw({asn1,{'internal error',Other}})
- end
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
- asn1ct_func:need({Erule,complete,1}),
- asn1ct_func:need({Erule,encode_open_type,1}),
- emit({"encode_open_type("
- "complete(",nl}),
- emit({" ",Fun,"(",{asis,PrimFieldName1},
- ", ",Element,", ",{asis,PFNList},")))"})
+ {_LeadingAttrName,Fun} = DynamicEnc,
+ case (Type#type.def)#'ObjectClassFieldType'.fieldname of
+ {Name,RestFieldNames} when is_atom(Name) ->
+ Imm = enc_var_type_call(Erule, Name, RestFieldNames,
+ Type, Fun, Element),
+ asn1ct_imm:per_enc_open_type(Imm, Aligned)
end;
_ ->
CurrMod = get(currmod),
case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=Mod,type=EType} when
- (CurrMod==Mod) ->
- emit({"'enc_",EType,"'(",Element,")"});
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ [{apply,enc_func(EType),[{expr,Element}]}];
#'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'enc_",
- EType,"'(",Element,")"});
+ [{apply,{Mod,enc_func(EType)},[{expr,Element}]}];
{primitive,bif} ->
- asn1ct_gen_per:gen_encode_prim(Erule, Type, Element);
+ asn1ct_gen_per:gen_encode_prim_imm(Element, Type, Aligned);
'ASN1_OPEN_TYPE' ->
case Type#type.def of
#'ObjectClassFieldType'{type=OpenType} ->
- asn1ct_gen_per:gen_encode_prim(Erule,
- #type{def=OpenType},
- Element);
+ asn1ct_gen_per:gen_encode_prim_imm(Element,
+ #type{def=OpenType},
+ Aligned);
_ ->
- asn1ct_gen_per:gen_encode_prim(Erule, Type,
- Element)
+ asn1ct_gen_per:gen_encode_prim_imm(Element,
+ Type,
+ Aligned)
end;
{constructed,bif} ->
NewTypename = [Cname|TopType],
+ Enc = enc_func(asn1ct_gen:list2name(NewTypename)),
case {Type#type.tablecinf,DynamicEnc} of
{[{objfun,_}|_R],{_,EncFun}} ->
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,", ",EncFun,")"});
+ [{apply,Enc,[{expr,Element},{var,EncFun}]}];
_ ->
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,")"})
+ [{apply,Enc,[{expr,Element}]}]
end
end
- end,
- case Ext of
- {ext,_Ep2,_} ->
- emit("))");
- _ -> true
end.
+enc_func(Type) ->
+ enc_func("enc_", Type).
+
+enc_func(Prefix, Name) ->
+ list_to_atom(lists:concat([Prefix,Name])).
+
+enc_var_type_call(Erule, Name, RestFieldNames,
+ #type{tablecinf=TCI}, Fun, Val) ->
+ [{objfun,#'Externaltypereference'{module=Xmod,type=Xtype}}] = TCI,
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({encode,ObjSet,RestFieldNames,Extensible})),
+ Gen = fun(_Fd, N) ->
+ enc_objset(Erule, Name, N, ObjSet,
+ RestFieldNames, Extensible)
+ end,
+ Prefix = lists:concat(["enc_os_",Name]),
+ F = asn1ct_func:call_gen(Prefix, Key, Gen),
+ [{apply,F,[{var,atom_to_list(Val)},{var,Fun}]}].
+
+fix_object_code(Name, [{Name,B}|_], _ClassFields) ->
+ B;
+fix_object_code(Name, [_|T], ClassFields) ->
+ fix_object_code(Name, T, ClassFields);
+fix_object_code(Name, [], ClassFields) ->
+ case lists:keyfind(Name, 2, ClassFields) of
+ {typefield,Name,'OPTIONAL'} ->
+ none;
+ {objectfield,Name,_,_,'OPTIONAL'} ->
+ none;
+ {typefield,Name,{'DEFAULT',#type{}=Type}} ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ #typedef{name={primitive,bif},typespec=Type};
+ {constructed,bif} ->
+ #typedef{name={constructed,bif},typespec=Type}
+ end
+ end.
+
+
+enc_objset(Erule, Component, Name, ObjSet, RestFieldNames, Extensible) ->
+ asn1ct_name:start(),
+ Aligned = is_aligned(Erule),
+ E = {error,
+ fun() ->
+ emit(["exit({'Type not compatible with table constraint',"
+ "{component,",{asis,Component},"},"
+ "{value,Val},"
+ "{unique_name_and_value,'_'}})",nl])
+ end},
+ Imm = [{'cond',
+ [[{eq,{var,"Id"},Key}|
+ enc_obj(Erule, Obj, RestFieldNames, Aligned)] ||
+ {Key,Obj} <- ObjSet] ++
+ [['_',case Extensible of
+ false -> E;
+ true -> {put_bits,{var,"Val"},binary,[1]}
+ end]]}],
+ emit([{asis,Name},"(Val, Id) ->",nl]),
+ asn1ct_imm:enc_cg(Imm, Aligned),
+ emit([".",nl]).
+
+enc_obj(Erule, Obj, RestFieldNames0, Aligned) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Def} ->
+ asn1ct_gen_per:gen_encode_prim_imm('Val', Def, Aligned);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ gen_encode_choice_imm(Erule, name, Def);
+ 'SET' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SET OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def);
+ 'SEQUENCE' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SEQUENCE OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def)
+ end;
+ #typedef{name=Type} ->
+ [{apply,enc_func(Type),[{var,"Val"}]}];
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFieldNames] = RestFieldNames0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ enc_obj(Erule, Typedef, RestFieldNames, Aligned)
+ end;
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ Func = enc_func(Type),
+ case get(currmod) of
+ Mod ->
+ [{apply,Func,[{var,"Val"}]}];
+ _ ->
+ [{apply,{Mod,Func},[{var,"Val"}]}]
+ end
+ end.
+
+
gen_dec_components_call(Erule, TopType, {Root,ExtList},
DecInfObj, Ext, NumberOfOptionals) ->
gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},
@@ -1163,14 +1174,6 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj,
emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
St
end;
- %%{objectfield,_,_} when Ext == noext, Prop == mandatory ->
- {{objectfield,_,_},true} ->
- fun(St) ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
- St
- end;
_ ->
case Type of
#type{def=#'SEQUENCE'{
@@ -1350,25 +1353,19 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
false -> % This is in a choice with typefield components
{Name,RestFieldNames} =
(Type#type.def)#'ObjectClassFieldType'.fieldname,
-
- asn1ct_name:new(reason),
Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
{TmpTerm,TempBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([com,nl]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ 'Result',TmpTerm,mandatory}),
emit([com,nl,
- {next,bytes}," = ",TempBuf,com,nl,
- indent(2),"case (catch ObjFun(",
- {asis,Name},",",TmpTerm,",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),"{",{asis,Cname},", {",{curr,tmpterm},", ",
- {next,bytes},"}}",nl]),
- emit([indent(2),"end"]),
+ "{",{asis,Cname},",{Result,",TempBuf,"}}"]),
{[],PrevSt};
{"got objfun through args","ObjFun"} ->
%% this is when the generated code gots the
@@ -1388,27 +1385,22 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
asn1ct_imm:dec_code_gen(Imm, BytesVar),
emit([com,nl]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ TmpTerm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
if
Prop =:= mandatory ->
- emit([{curr,term}," =",nl," "]);
- true ->
- emit([" {"])
- end,
- emit(["case (catch ObjFun(",{asis,Name},",",
- {curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([" {'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),{curr,tmpterm},nl]),
- emit([indent(2),"end"]),
- if
- Prop =:= mandatory ->
- ok;
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ Term,TmpTerm,Prop});
true ->
+ emit([" {"]),
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ '_',TmpTerm,Prop}),
emit([",",nl,{curr,tmpbytes},"}"])
end,
{[],PrevSt};
@@ -1425,19 +1417,6 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
Prop}],PrevSt}
end
end;
-gen_dec_line_special(Erule, {objectfield,PrimFieldName1,PFNList}, _TopType,
- Comp, _DecInfObj) ->
- fun({_BytesVar,PrevSt}) ->
- Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- asn1ct_imm:dec_code_gen(Imm, BytesVar),
- #'ComponentType'{name=Cname,prop=Prop} = Comp,
- SaveBytes = [{Cname,{PrimFieldName1,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- Prop}],
- {SaveBytes,PrevSt}
- end;
gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) ->
case gen_dec_line_other(Erule, Atype, TopType, Comp) of
Fun when is_function(Fun, 1) ->
@@ -1458,14 +1437,11 @@ gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) ->
gen_dec_line_dec_inf(Comp, DecInfObj) ->
#'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ {Cname,{_,_OSet,_UniqueFName,ValIndex}} ->
Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} = OSet,
emit([",",nl,
- "ObjFun = ",{asis,ObjSetMod},
- ":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"]);
+ "ObjFun = ",ValueMatch]);
_ ->
ok
end.
@@ -1492,63 +1468,35 @@ gen_dec_line_other(Erule, Atype, TopType, Comp) ->
[{objfun,_}|_R] ->
fun(BytesVar) ->
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype, ObjFun)"})
+ "'(",BytesVar,", ObjFun)"})
end;
_ ->
fun(BytesVar) ->
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype)"})
+ "'(",BytesVar,")"})
end
end
end.
-gen_enc_choice(Erule,TopType,CompList,Ext) ->
- gen_enc_choice_tag(Erule, CompList, [], Ext),
- emit({com,nl}),
- emit({"case element(1,Val) of",nl}),
- gen_enc_choice2(Erule,TopType, CompList, Ext),
- emit({nl,"end"}).
-
-gen_enc_choice_tag(Erule, {C1,C2}, _, _) ->
- N1 = get_name_list(C1),
- N2 = get_name_list(C2),
- call(Erule,set_choice,
- ["element(1, Val)",
- {asis,{N1,N2}},
- {asis,{length(N1),length(N2)}}]);
-gen_enc_choice_tag(Erule, {C1,C2,C3}, _, _) ->
- N1 = get_name_list(C1),
- N2 = get_name_list(C2),
- N3 = get_name_list(C3),
- Root = N1 ++ N3,
- call(Erule,set_choice,
- ["element(1, Val)",
- {asis,{Root,N2}},
- {asis,{length(Root),length(N2)}}]);
-gen_enc_choice_tag(Erule, C, _, _) ->
- N = get_name_list(C),
- call(Erule,set_choice,
- ["element(1, Val)",
- {asis,N},{asis,length(N)}]).
-
-get_name_list(L) ->
- get_name_list(L,[]).
-
-get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
- get_name_list(T,[Name|Acc]);
-get_name_list([], Acc) ->
- lists:reverse(Acc).
-
-
-gen_enc_choice2(Erule,TopType, {L1,L2}, Ext) ->
- gen_enc_choice2(Erule, TopType, L1 ++ L2, 0, [], Ext);
-gen_enc_choice2(Erule, TopType, {L1,L2,L3}, Ext) ->
- gen_enc_choice2(Erule, TopType, L1 ++ L3 ++ L2, 0, [], Ext);
-gen_enc_choice2(Erule,TopType, L, Ext) ->
- gen_enc_choice2(Erule,TopType, L, 0, [], Ext).
+gen_enc_choice(Erule, TopType, {Root,Exts}, Ext) ->
+ Constr = choice_constraint(Root),
+ gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext) ++
+ gen_enc_choices(Exts, Erule, TopType, 0, ext, Ext);
+gen_enc_choice(Erule, TopType, {Root,Exts,[]}, Ext) ->
+ gen_enc_choice(Erule, TopType, {Root,Exts}, Ext);
+gen_enc_choice(Erule, TopType, Root, Ext) when is_list(Root) ->
+ Constr = choice_constraint(Root),
+ gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext).
+
+choice_constraint(L) ->
+ case length(L) of
+ 0 -> [{'SingleValue',0}];
+ Len -> [{'ValueRange',{0,Len-1}}]
+ end.
-gen_enc_choice2(Erule, TopType, [H|T], Pos, Sep0, Ext) ->
+gen_enc_choices([H|T], Erule, TopType, Pos, Constr, Ext) ->
#'ComponentType'{name=Cname,typespec=Type} = H,
+ Aligned = is_aligned(Erule),
EncObj =
case asn1ct_gen:get_constraint(Type#type.constraint,
componentrelation) of
@@ -1562,16 +1510,25 @@ gen_enc_choice2(Erule, TopType, [H|T], Pos, Sep0, Ext) ->
_ ->
{no_attr,"ObjFun"}
end,
- emit([Sep0,{asis,Cname}," ->",nl]),
- DoExt = case Ext of
- {ext,ExtPos,_} when Pos + 1 < ExtPos -> noext;
- _ -> Ext
+ DoExt = case Constr of
+ ext -> Ext;
+ _ -> noext
end,
- gen_enc_line(Erule, TopType, Cname, Type, "element(2, Val)",
- Pos+1, EncObj, DoExt),
- Sep = [";",nl],
- gen_enc_choice2(Erule, TopType, T, Pos+1, Sep, Ext);
-gen_enc_choice2(_, _, [], _, _, _) -> ok.
+ Tag = case {Ext,Constr} of
+ {noext,_} ->
+ asn1ct_imm:per_enc_integer(Pos, Constr, Aligned);
+ {{ext,_,_},ext} ->
+ [{put_bits,1,1,[1]}|
+ asn1ct_imm:per_enc_small_number(Pos, Aligned)];
+ {{ext,_,_},_} ->
+ [{put_bits,0,1,[1]}|
+ asn1ct_imm:per_enc_integer(Pos, Constr, Aligned)]
+ end,
+ Body = gen_enc_line_imm(Erule, TopType, Cname, Type, 'ChoiceVal',
+ EncObj, DoExt),
+ Imm = Tag ++ Body,
+ [{Cname,Imm}|gen_enc_choices(T, Erule, TopType, Pos+1, Constr, Ext)];
+gen_enc_choices([], _, _, _, _, _) -> [].
%% Generate the code for CHOICE. If the CHOICE is extensible,
%% the structure of the generated code is as follows:
@@ -1704,9 +1661,6 @@ gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) ->
gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre);
gen_dec_choice2(_, _, [], _, _, _) -> ok.
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
make_elements(I,Val,ExtCnames) ->
make_elements(I,Val,ExtCnames,[]).
@@ -1720,7 +1674,7 @@ make_elements(_I,_,[],Acc) ->
lists:reverse(Acc).
make_element(I, Val) ->
- io_lib:format("element(~w,~s)", [I,Val]).
+ lists:flatten(io_lib:format("element(~w, ~s)", [I,Val])).
emit_extaddgroupTerms(VarSeries,[_]) ->
asn1ct_name:new(VarSeries),
@@ -1787,6 +1741,3 @@ value_match1(Value,[],Acc,Depth) ->
Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
-
-is_optimized(per) -> true;
-is_optimized(uper) -> false.