1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
16
%% $Id: asn1ct_value.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
18
-module(asn1ct_value).
20
%% Generate Erlang values for ASN.1 types.
21
%% The value is randomized within it's constraints
23
-include("asn1_records.hrl").
24
%-compile(export_all).
26
-export([get_type/3]).
30
%% Generate examples of values ******************************
31
%%****************************************x
34
get_type(M,Typename,Tellname) ->
35
case asn1_db:dbget(M,Typename) of
37
{asn1_error,{not_found,{M,Typename}}};
38
Tdef when record(Tdef,typedef) ->
39
Type = Tdef#typedef.typespec,
40
get_type(M,[Typename],Type,Tellname);
42
{asn1_error,{other,Err}}
45
get_type(M,Typename,Type,Tellname) when record(Type,type) ->
46
InnerType = get_inner(Type#type.def),
47
case asn1ct_gen:type(InnerType) of
48
#'Externaltypereference'{module=Emod,type=Etype} ->
49
get_type(Emod,Etype,Tellname);
52
yes -> {Typename,get_type(M,InnerType,no)};
53
no -> get_type(M,InnerType,no)
60
case Type#type.constraint of
61
[#'Externaltypereference'{type=TrefConstraint}] ->
62
get_type(M,TrefConstraint,no);
67
get_type_constructed(M,Typename,InnerType,Type)
69
get_type(M,Typename,#'ComponentType'{name = Name,typespec = Type},_) ->
70
get_type(M,[Name|Typename],Type,no);
71
get_type(_,_,_,_) -> % 'EXTENSIONMARK'
74
get_inner(A) when atom(A) -> A;
75
get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;
76
get_inner({typereference,_Pos,Name}) -> Name;
77
get_inner(T) when tuple(T) ->
78
case asn1ct_gen:get_inner(T) of
79
{fixedtypevaluefield,_,Type} ->
81
{typefield,_FieldName} ->
86
%%get_inner(T) when tuple(T) -> element(1,T).
90
get_type_constructed(M,Typename,InnerType,D) when record(D,type) ->
93
get_sequence(M,Typename,D);
95
get_sequence(M,Typename,D);
97
get_choice(M,Typename,D);
99
{_,Type} = D#type.def,
100
NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
101
get_sequence_of(M,Typename,D,NameSuffix);
103
{_,Type} = D#type.def,
104
NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
105
get_sequence_of(M,Typename,D,NameSuffix);
107
exit({nyi,InnerType})
110
get_sequence(M,Typename,Type) ->
111
{_SEQorSET,CompList} =
112
case Type#type.def of
113
#'SEQUENCE'{components=Cl} -> {'SEQUENCE',Cl};
114
#'SET'{components=Cl} -> {'SET',Cl}
116
case get_components(M,Typename,CompList) of
118
{list_to_atom(asn1ct_gen:list2rname(Typename))};
120
list_to_tuple([list_to_atom(asn1ct_gen:list2rname(Typename))|C])
123
get_components(M,Typename,{Root,Ext}) ->
124
get_components(M,Typename,Root++Ext);
126
%% Should enhance this *** HERE *** with proper handling of extensions
128
get_components(M,Typename,[H|T]) ->
129
[get_type(M,Typename,H,no)|
130
get_components(M,Typename,T)];
131
get_components(_,_,[]) ->
134
get_choice(M,Typename,Type) ->
135
{'CHOICE',TCompList} = Type#type.def,
138
{asn1_EMPTY,asn1_EMPTY};
139
{CompList,ExtList} -> % Should be enhanced to handle extensions too
140
CList = CompList ++ ExtList,
141
C = lists:nth(random(length(CList)),CList),
142
{C#'ComponentType'.name,get_type(M,Typename,C,no)};
143
CompList when list(CompList) ->
144
C = lists:nth(random(length(CompList)),CompList),
145
{C#'ComponentType'.name,get_type(M,Typename,C,no)}
148
get_sequence_of(M,Typename,Type,TypeSuffix) ->
149
%% should generate length according to constraints later
150
{_,Oftype} = Type#type.def,
151
C = Type#type.constraint,
153
NewTypeName = [TypeSuffix|Typename],
154
gen_list(M,NewTypeName,Oftype,no,S).
156
gen_list(_,_,_,_,0) ->
158
gen_list(M,Typename,Oftype,Tellname,N) ->
159
[get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)].
162
C = D#type.constraint,
166
{'INTEGER',NamedNumberList} ->
167
NN = [X||{X,_} <- NamedNumberList],
172
lists:nth(random(length(NN)),NN)
174
Enum when tuple(Enum),element(1,Enum)=='ENUMERATED' ->
181
case NamedNumberList of
187
NN = [X||{X,_} <- NNew],
192
lists:nth(random(length(NN)),NN)
194
{'BIT STRING',NamedNumberList} ->
195
%% io:format("get_type_prim 1: ~w~n",[NamedNumberList]),
196
NN = [X||{X,_} <- NamedNumberList],
199
Bl1 =lists:reverse(adjust_list(size_random(C),[1,0,1,1])),
200
lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,Bl1));
202
%% io:format("get_type_prim 2: ~w~n",[NN]),
203
[lists:nth(random(length(NN)),NN)]
206
exit({asn1_error,nyi,'ANY'});
209
'OBJECT IDENTIFIER' ->
211
Olist = [(random(1000)-1)||_X <-lists:seq(1,Len)],
212
list_to_tuple([random(3)-1,random(40)-1|Olist]);
213
'ObjectDescriptor' ->
214
object_descriptor_nyi;
218
adjust_list(size_random(C),c_string(C,"OCTET STRING"));
220
adjust_list(size_random(C),c_string(C,"0123456789"));
222
adjust_list(size_random(C),c_string(C,"TeletexString"));
224
adjust_list(size_random(C),c_string(C,"VideotexString"));
230
adjust_list(size_random(C),c_string(C,"GraphicString"));
232
adjust_list(size_random(C),c_string(C,"VisibleString"));
234
adjust_list(size_random(C),c_string(C,"GeneralString"));
236
adjust_list(size_random(C),c_string(C,"PrintableString"));
238
adjust_list(size_random(C),c_string(C,"IA5String"));
240
adjust_list(size_random(C),c_string(C,"BMPString"));
242
adjust_list(size_random(C),c_string(C,"UniversalString"));
244
exit({asn1_error,nyi,XX})
247
c_string(undefined,Default) ->
249
c_string(C,Default) ->
250
case get_constraint(C,'PermittedAlphabet') of
251
{'SingleValue',Sv} when list(Sv) ->
253
{'SingleValue',V} when integer(V) ->
260
{A1,A2,A3} = erlang:now(),
261
random:seed(A1,A2,A3),
262
random:uniform(Upper).
265
case get_constraint(C,'SizeConstraint') of
268
{Lb,Ub} when Ub-Lb =< 4 ->
269
c_random({Lb,Ub},no);
271
c_random({Lb,Lb+4},no);
277
c_random(get_constraint(C,'ValueRange'),get_constraint(C,'SingleValue')).
279
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280
%% c_random(Range,SingleValue)
281
%% only called from other X_random functions
283
c_random(VRange,Single) ->
284
case {VRange,Single} of
286
random(16#fffffff) - (16#fffffff bsr 1);
289
{Lb,Ub} when integer(Lb),integer(Ub) ->
291
Lb + (random(Range)-1);
293
Lb + random(16#fffffff)-1;
295
Ub - random(16#fffffff)-1;
298
A + (random(Range)-1)
300
{_,S} when integer(S) ->
302
{_,S} when list(S) ->
303
lists:nth(random(length(S)),S)
305
%% io:format("asn1ct_value: hejsan hoppsan~n");
307
%% io:format("asn1ct_value: hejsan hoppsan 2~n")
308
%% io:format("asn1ct_value: c_random/2: S1 = ~w~n"
309
%% "S2 = ~w,~n",[S1,S2])
310
%% exit(self(),goodbye)
313
adjust_list(Len,Orig) ->
314
adjust_list1(Len,Orig,Orig,[]).
316
adjust_list1(0,_Orig,[_Oh|_Ot],Acc) ->
318
adjust_list1(Len,Orig,[],Acc) ->
319
adjust_list1(Len,Orig,Orig,Acc);
320
adjust_list1(Len,Orig,[Oh|Ot],Acc) ->
321
adjust_list1(Len-1,Orig,Ot,[Oh|Acc]).
324
get_constraint(C,Key) ->
325
case lists:keysearch(Key,1,C) of