1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(asn1rtt_check).
21
22-export([check_fail/1,
23	 check_int/3,
24	 check_legacy_bitstring/2,
25	 check_legacy_named_bitstring/3,
26	 check_legacy_named_bitstring/4,
27	 check_named_bitstring/3,
28	 check_named_bitstring/4,
29	 check_literal_sof/2,
30	 check_octetstring/2,
31	 check_objectidentifier/2,
32	 check_objectdescriptor/2,
33	 check_real/2,
34	 check_restrictedstring/2]).
35
36check_fail(_) ->
37    throw(false).
38
39check_int(Value, Value, _) when is_integer(Value) ->
40    true;
41check_int(Value, DefValue, NNL) when is_atom(Value) ->
42    case lists:keyfind(Value, 1, NNL) of
43	{_,DefValue} ->
44	    true;
45	_ ->
46	    throw(false)
47    end;
48check_int(_, _, _) ->
49    throw(false).
50
51check_legacy_bitstring(Value, Default) ->
52    check_bitstring(Default, Value).
53
54%% check_bitstring(Default, UserBitstring) -> true|false
55%%  Default = bitstring()
56%%  UserBitstring = integeger() | list(0|1) | {Unused,binary()} | bitstring()
57check_bitstring(DefVal, {Unused,Binary}) ->
58    %% User value in compact format.
59    Sz = bit_size(Binary) - Unused,
60    <<Val:Sz/bitstring,_:Unused>> = Binary,
61    check_bitstring(DefVal, Val);
62check_bitstring(DefVal, Val) when is_bitstring(Val) ->
63    case Val =:= DefVal of
64	false -> throw(false);
65	true -> true
66    end;
67check_bitstring(Def, Val) when is_list(Val) ->
68    check_bitstring_list(Def, Val);
69check_bitstring(Def, Val) when is_integer(Val) ->
70    check_bitstring_integer(Def, Val).
71
72check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) ->
73    check_bitstring_list(T1, T2);
74check_bitstring_list(<<>>, []) ->
75    true;
76check_bitstring_list(_, _) ->
77    throw(false).
78
79check_bitstring_integer(<<H:1,T1/bitstring>>, Int) when H =:= Int band 1 ->
80    check_bitstring_integer(T1, Int bsr 1);
81check_bitstring_integer(<<>>, 0) ->
82    true;
83check_bitstring_integer(_, _) ->
84    throw(false).
85
86check_legacy_named_bitstring([Int|_]=Val, Bs, BsSize) when is_integer(Int) ->
87    check_named_bitstring(<< <<B:1>> || B <- Val >>, Bs, BsSize);
88check_legacy_named_bitstring({Unused,Val0}, Bs, BsSize) ->
89    Sz = bit_size(Val0) - Unused,
90    <<Val:Sz/bits,_/bits>> = Val0,
91    check_named_bitstring(Val, Bs, BsSize);
92check_legacy_named_bitstring(Val, Bs, BsSize) when is_integer(Val) ->
93    L = legacy_int_to_bitlist(Val),
94    check_named_bitstring(<< <<B:1>> || B <- L >>, Bs, BsSize);
95check_legacy_named_bitstring(Val, Bs, BsSize) ->
96    check_named_bitstring(Val, Bs, BsSize).
97
98check_legacy_named_bitstring([Int|_]=Val, Names, Bs, BsSize) when is_integer(Int) ->
99    check_named_bitstring(<< <<B:1>> || B <- Val >>, Names, Bs, BsSize);
100check_legacy_named_bitstring({Unused,Val0}, Names, Bs, BsSize) ->
101    Sz = bit_size(Val0) - Unused,
102    <<Val:Sz/bits,_/bits>> = Val0,
103    check_named_bitstring(Val, Names, Bs, BsSize);
104check_legacy_named_bitstring(Val, Names, Bs, BsSize) when is_integer(Val) ->
105    L = legacy_int_to_bitlist(Val),
106    check_named_bitstring(<< <<B:1>> || B <- L >>, Names, Bs, BsSize);
107check_legacy_named_bitstring(Val, Names, Bs, BsSize) ->
108    check_named_bitstring(Val, Names, Bs, BsSize).
109
110legacy_int_to_bitlist(0) ->
111    [];
112legacy_int_to_bitlist(Int) ->
113    [Int band 1|legacy_int_to_bitlist(Int bsr 1)].
114
115check_named_bitstring(Bs, Bs, _) ->
116    true;
117check_named_bitstring(Val, Bs, BsSize) ->
118    Rest = bit_size(Val) - BsSize,
119    case Val of
120	<<Bs:BsSize/bits,0:Rest>> ->
121	    true;
122	_ ->
123	    throw(false)
124    end.
125
126check_named_bitstring([_|_]=Val, Names, _, _) ->
127    case lists:sort(Val) of
128	Names -> true;
129	_ -> throw(false)
130    end;
131check_named_bitstring(Bs, _, Bs, _) ->
132    true;
133check_named_bitstring(Val, _, Bs, BsSize) ->
134    Rest = bit_size(Val) - BsSize,
135    case Val of
136	<<Bs:BsSize/bits,0:Rest>> ->
137	    true;
138	_ ->
139	    throw(false)
140    end.
141
142check_octetstring(V, V) ->
143    true;
144check_octetstring(V, Def) when is_list(V) ->
145    case list_to_binary(V) of
146	Def -> true;
147	_ -> throw(false)
148    end;
149check_octetstring(_, _) ->
150    throw(false).
151
152check_objectidentifier(Value, {Prefix,Tail}) when is_tuple(Value) ->
153    check_oid(tuple_to_list(Value), Prefix, Tail);
154check_objectidentifier(_, _) ->
155    throw(false).
156
157check_oid([H|T], [K|Ks], Tail) ->
158    case lists:member(H, K) of
159	false -> throw(false);
160	true -> check_oid(T, Ks, Tail)
161    end;
162check_oid(Tail, [], Tail) ->
163    true;
164check_oid(_, _, _) ->
165    throw(false).
166
167check_objectdescriptor(_, asn1_DEFAULT) ->
168    true;
169check_objectdescriptor(OD, OD) ->
170    true;
171check_objectdescriptor(OD, OD) ->
172    throw({error,{not_implemented_yet,check_objectdescriptor}}).
173
174check_real(_, asn1_DEFAULT) ->
175    true;
176check_real(R, R) ->
177    true;
178check_real(_, _) ->
179    throw({error,{not_implemented_yet,check_real}}).
180
181check_restrictedstring(Val, Val) ->
182    true;
183check_restrictedstring([V|Rest1], [V|Rest2]) ->
184    check_restrictedstring(Rest1, Rest2);
185check_restrictedstring([V1|Rest1], [V2|Rest2]) ->
186    check_restrictedstring(V1, V2),
187    check_restrictedstring(Rest1, Rest2);
188%% tuple format of value
189check_restrictedstring({V1,V2}, [V1,V2]) ->
190    true;
191check_restrictedstring([V1,V2], {V1,V2}) ->
192    true;
193%% quadruple format of value
194check_restrictedstring({V1,V2,V3,V4}, [V1,V2,V3,V4]) ->
195    true;
196check_restrictedstring([V1,V2,V3,V4], {V1,V2,V3,V4}) ->
197    true;
198%% character string list
199check_restrictedstring(V1, V2) when is_tuple(V1) ->
200    check_restrictedstring(tuple_to_list(V1), V2);
201check_restrictedstring(_, _) ->
202    throw(false).
203
204check_literal_sof(Value, Default) ->
205    case lists:sort(Value) of
206	Default ->
207	    true;
208	_ ->
209	    throw(false)
210    end.
211