%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(asn1rtt_check).
-export([check_fail/1,
check_int/3,
check_legacy_bitstring/2,
check_legacy_named_bitstring/3,
check_legacy_named_bitstring/4,
check_named_bitstring/3,
check_named_bitstring/4,
check_literal_sof/2,
check_octetstring/2,
check_objectidentifier/2,
check_objectdescriptor/2,
check_real/2,
check_restrictedstring/2]).
check_fail(_) ->
throw(false).
check_int(Value, Value, _) when is_integer(Value) ->
true;
check_int(Value, DefValue, NNL) when is_atom(Value) ->
case lists:keyfind(Value, 1, NNL) of
{_,DefValue} ->
true;
_ ->
throw(false)
end;
check_int(_, _, _) ->
throw(false).
check_legacy_bitstring(Value, Default) ->
check_bitstring(Default, Value).
%% check_bitstring(Default, UserBitstring) -> true|false
%% Default = bitstring()
%% UserBitstring = integeger() | list(0|1) | {Unused,binary()} | bitstring()
check_bitstring(DefVal, {Unused,Binary}) ->
%% User value in compact format.
Sz = bit_size(Binary) - Unused,
<<Val:Sz/bitstring,_:Unused>> = Binary,
check_bitstring(DefVal, Val);
check_bitstring(DefVal, Val) when is_bitstring(Val) ->
case Val =:= DefVal of
false -> throw(false);
true -> true
end;
check_bitstring(Def, Val) when is_list(Val) ->
check_bitstring_list(Def, Val);
check_bitstring(Def, Val) when is_integer(Val) ->
check_bitstring_integer(Def, Val).
check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) ->
check_bitstring_list(T1, T2);
check_bitstring_list(<<>>, []) ->
true;
check_bitstring_list(_, _) ->
throw(false).
check_bitstring_integer(<<H:1,T1/bitstring>>, Int) when H =:= Int band 1 ->
check_bitstring_integer(T1, Int bsr 1);
check_bitstring_integer(<<>>, 0) ->
true;
check_bitstring_integer(_, _) ->
throw(false).
check_legacy_named_bitstring([Int|_]=Val, Bs, BsSize) when is_integer(Int) ->
check_named_bitstring(<< <<B:1>> || B <- Val >>, Bs, BsSize);
check_legacy_named_bitstring({Unused,Val0}, Bs, BsSize) ->
Sz = bit_size(Val0) - Unused,
<<Val:Sz/bits,_/bits>> = Val0,
check_named_bitstring(Val, Bs, BsSize);
check_legacy_named_bitstring(Val, Bs, BsSize) when is_integer(Val) ->
L = legacy_int_to_bitlist(Val),
check_named_bitstring(<< <<B:1>> || B <- L >>, Bs, BsSize);
check_legacy_named_bitstring(Val, Bs, BsSize) ->
check_named_bitstring(Val, Bs, BsSize).
check_legacy_named_bitstring([Int|_]=Val, Names, Bs, BsSize) when is_integer(Int) ->
check_named_bitstring(<< <<B:1>> || B <- Val >>, Names, Bs, BsSize);
check_legacy_named_bitstring({Unused,Val0}, Names, Bs, BsSize) ->
Sz = bit_size(Val0) - Unused,
<<Val:Sz/bits,_/bits>> = Val0,
check_named_bitstring(Val, Names, Bs, BsSize);
check_legacy_named_bitstring(Val, Names, Bs, BsSize) when is_integer(Val) ->
L = legacy_int_to_bitlist(Val),
check_named_bitstring(<< <<B:1>> || B <- L >>, Names, Bs, BsSize);
check_legacy_named_bitstring(Val, Names, Bs, BsSize) ->
check_named_bitstring(Val, Names, Bs, BsSize).
legacy_int_to_bitlist(0) ->
[];
legacy_int_to_bitlist(Int) ->
[Int band 1|legacy_int_to_bitlist(Int bsr 1)].
check_named_bitstring(Bs, Bs, _) ->
true;
check_named_bitstring(Val, Bs, BsSize) ->
Rest = bit_size(Val) - BsSize,
case Val of
<<Bs:BsSize/bits,0:Rest>> ->
true;
_ ->
throw(false)
end.
check_named_bitstring([_|_]=Val, Names, _, _) ->
case lists:sort(Val) of
Names -> true;
_ -> throw(false)
end;
check_named_bitstring(Bs, _, Bs, _) ->
true;
check_named_bitstring(Val, _, Bs, BsSize) ->
Rest = bit_size(Val) - BsSize,
case Val of
<<Bs:BsSize/bits,0:Rest>> ->
true;
_ ->
throw(false)
end.
check_octetstring(V, V) ->
true;
check_octetstring(V, Def) when is_list(V) ->
case list_to_binary(V) of
Def -> true;
_ -> throw(false)
end;
check_octetstring(_, _) ->
throw(false).
check_objectidentifier(Value, {Prefix,Tail}) when is_tuple(Value) ->
check_oid(tuple_to_list(Value), Prefix, Tail);
check_objectidentifier(_, _) ->
throw(false).
check_oid([H|T], [K|Ks], Tail) ->
case lists:member(H, K) of
false -> throw(false);
true -> check_oid(T, Ks, Tail)
end;
check_oid(Tail, [], Tail) ->
true;
check_oid(_, _, _) ->
throw(false).
check_objectdescriptor(_, asn1_DEFAULT) ->
true;
check_objectdescriptor(OD, OD) ->
true;
check_objectdescriptor(OD, OD) ->
throw({error,{not_implemented_yet,check_objectdescriptor}}).
check_real(_, asn1_DEFAULT) ->
true;
check_real(R, R) ->
true;
check_real(_, _) ->
throw({error,{not_implemented_yet,check_real}}).
check_restrictedstring(Val, Val) ->
true;
check_restrictedstring([V|Rest1], [V|Rest2]) ->
check_restrictedstring(Rest1, Rest2);
check_restrictedstring([V1|Rest1], [V2|Rest2]) ->
check_restrictedstring(V1, V2),
check_restrictedstring(Rest1, Rest2);
%% tuple format of value
check_restrictedstring({V1,V2}, [V1,V2]) ->
true;
check_restrictedstring([V1,V2], {V1,V2}) ->
true;
%% quadruple format of value
check_restrictedstring({V1,V2,V3,V4}, [V1,V2,V3,V4]) ->
true;
check_restrictedstring([V1,V2,V3,V4], {V1,V2,V3,V4}) ->
true;
%% character string list
check_restrictedstring(V1, V2) when is_tuple(V1) ->
check_restrictedstring(tuple_to_list(V1), V2);
check_restrictedstring(_, _) ->
throw(false).
check_literal_sof(Value, Default) ->
case lists:sort(Value) of
Default ->
true;
_ ->
throw(false)
end.