1%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*- 2%% vim: ts=4 sw=4 ft=erlang noet 3%%%------------------------------------------------------------------- 4%%% @author Andrew Bennett <andrew@pixid.com> 5%%% @copyright 2014-2015, Andrew Bennett 6%%% @doc 7%%% 8%%% @end 9%%% Created : 12 Aug 2015 by Andrew Bennett <andrew@pixid.com> 10%%%------------------------------------------------------------------- 11-module(fips_testvector). 12 13%% API 14-export([from_binary/1]). 15-export([from_file/1]). 16-export([to_binary/1]). 17-export([to_file/2]). 18 19%%==================================================================== 20%% API functions 21%%==================================================================== 22 23from_binary(Binary) -> 24 Lines = binary:split(Binary, [<< $\n >>, << $\r >>], [global, trim]), 25 parse_lines(Lines, []). 26 27from_file(File) -> 28 case file:read_file(File) of 29 {ok, Binary} -> 30 from_binary(Binary); 31 ReadError -> 32 ReadError 33 end. 34 35to_binary(Vectors) when is_list(Vectors) -> 36 << 37 << 38 (case Vector of 39 {flag, Flag} -> 40 << $[, Flag/binary, $], $\n >>; 41 {option, {Key, Val}} -> 42 << $[, Key/binary, $\s, $=, $\s, Val/binary, $], $\n >>; 43 {token, Token} -> 44 << Token/binary, $\n >>; 45 {vector, {Key, Val}, hex} -> 46 << Key/binary, $\s, $=, $\s, (hex:bin_to_hex(Val))/binary, $\n >>; 47 {vector, {Key, Val}, int} -> 48 << Key/binary, $\s, $=, $\s, (integer_to_binary(Val))/binary, $\n >>; 49 {vector, {Key, Val}, raw} -> 50 << Key/binary, $\s, $=, $\s, Val/binary, $\n >> 51 end)/binary 52 >> 53 || Vector <- Vectors 54 >>. 55 56to_file(File, State={_, _, _}) -> 57 Binary = to_binary(State), 58 file:write_file(File, Binary). 59 60%%%------------------------------------------------------------------- 61%%% Internal functions 62%%%------------------------------------------------------------------- 63 64%% @private 65parse_lines([], Acc) -> 66 lists:reverse(Acc); 67parse_lines([Line | Lines], Acc) -> 68 case parse_line(Line) of 69 skip -> 70 parse_lines(Lines, Acc); 71 Term -> 72 parse_lines(Lines, [Term | Acc]) 73 end. 74 75%% @private 76parse_line(<< $#, _/binary >>) -> 77 skip; 78parse_line(<< $\s, Rest/binary >>) -> 79 parse_line(Rest); 80parse_line(<< $\t, Rest/binary >>) -> 81 parse_line(Rest); 82parse_line(<< $[, Rest/binary >>) -> 83 parse_option(Rest); 84parse_line(<<>>) -> 85 skip; 86parse_line(Rest) -> 87 parse_vector(Rest). 88 89%% @private 90parse_option(Rest) -> 91 case binary:match(Rest, << $] >>) of 92 {OptionEndPos, 1} -> 93 case binary:match(Rest, << $= >>) of 94 {EqualPos, 1} when EqualPos < OptionEndPos -> 95 Key = parse_option_key(binary:part(Rest, 0, EqualPos), <<>>), 96 Val = parse_option_val(binary:part(Rest, EqualPos + 1, OptionEndPos - EqualPos - 1), <<>>), 97 {option, {Key, Val}}; 98 _ -> 99 Flag = binary:part(Rest, 0, OptionEndPos), 100 {flag, Flag} 101 end; 102 _ -> 103 erlang:error({badarg, [Rest]}) 104 end. 105 106%% @private 107parse_option_key(<< $\s, Rest/binary >>, Key) -> 108 parse_option_key(Rest, Key); 109parse_option_key(<< $\t, Rest/binary >>, Key) -> 110 parse_option_key(Rest, Key); 111parse_option_key(<< C, Rest/binary >>, Key) -> 112 parse_option_key(Rest, << Key/binary, C >>); 113parse_option_key(<<>>, Key) -> 114 Key. 115 116%% @private 117parse_option_val(<< $\s, Rest/binary >>, Val) -> 118 parse_option_val(Rest, Val); 119parse_option_val(<< $\t, Rest/binary >>, Val) -> 120 parse_option_val(Rest, Val); 121parse_option_val(<< C, Rest/binary >>, Val) -> 122 parse_option_val(Rest, << Val/binary, C >>); 123parse_option_val(<<>>, Val) -> 124 Val. 125 126%% @private 127parse_vector(<< C, Rest/binary >>) 128 when (C >= $A andalso C =< $Z) 129 orelse (C >= $a andalso C =< $z) 130 orelse (C >= $0 andalso C =< $9) -> 131 parse_vector_key(Rest, << C >>); 132parse_vector(Rest) -> 133 erlang:error({badarg, [Rest]}). 134 135%% @private 136parse_vector_key(<< $=, Rest/binary >>, Key) -> 137 parse_vector_val(Rest, Key, <<>>, true); 138parse_vector_key(<< $\s, Rest/binary >>, Key) -> 139 parse_vector_key(Rest, Key); 140parse_vector_key(<< $\t, Rest/binary >>, Key) -> 141 parse_vector_key(Rest, Key); 142parse_vector_key(<< C, Rest/binary >>, Key) 143 when (C >= $A andalso C =< $Z) 144 orelse (C >= $a andalso C =< $z) 145 orelse (C >= $0 andalso C =< $9) -> 146 parse_vector_key(Rest, << Key/binary, C >>); 147parse_vector_key(<<>>, Key) -> 148 {token, Key}; 149parse_vector_key(Rest, Key) -> 150 erlang:error({badarg, [Rest, Key]}). 151 152%% @private 153parse_vector_val(<< $#, _/binary >>, Key = << C, O, U, N, T >>, Bin, true) 154 when (C =:= $C orelse C =:= $c) 155 andalso (O =:= $O orelse O =:= $o) 156 andalso (U =:= $U orelse U =:= $u) 157 andalso (N =:= $N orelse N =:= $n) 158 andalso (T =:= $T orelse T =:= $t) -> 159 Val = binary_to_integer(Bin), 160 {vector, {Key, Val}, int}; 161parse_vector_val(<< $#, _/binary >>, Key, Hex, true) -> 162 Val = hex:hex_to_bin(Hex), 163 {vector, {Key, Val}, hex}; 164parse_vector_val(<< $#, _/binary >>, Key, Val, false) -> 165 {vector, {Key, Val}, raw}; 166parse_vector_val(<< $\s, Rest/binary >>, Key, Val, true) -> 167 parse_vector_val(Rest, Key, Val, true); 168parse_vector_val(<< $\t, Rest/binary >>, Key, Val, true) -> 169 parse_vector_val(Rest, Key, Val, true); 170parse_vector_val(<< C, Rest/binary >>, Key, Val, true) 171 when (C >= $A andalso C =< $F) 172 orelse (C >= $a andalso C =< $f) 173 orelse (C >= $0 andalso C =< $9) -> 174 parse_vector_val(Rest, Key, << Val/binary, C >>, true); 175parse_vector_val(<< C, Rest/binary >>, Key, Val, _Hex) -> 176 parse_vector_val(Rest, Key, << Val/binary, C >>, false); 177parse_vector_val(<<>>, Key = << C, O, U, N, T >>, Bin, true) 178 when (C =:= $C orelse C =:= $c) 179 andalso (O =:= $O orelse O =:= $o) 180 andalso (U =:= $U orelse U =:= $u) 181 andalso (N =:= $N orelse N =:= $n) 182 andalso (T =:= $T orelse T =:= $t) -> 183 Val = binary_to_integer(Bin), 184 {vector, {Key, Val}, int}; 185parse_vector_val(<<>>, Key = << L, E, N >>, Bin, true) 186 when (L =:= $L orelse L =:= $l) 187 andalso (E =:= $E orelse E =:= $e) 188 andalso (N =:= $N orelse N =:= $n) -> 189 Val = binary_to_integer(Bin), 190 {vector, {Key, Val}, int}; 191parse_vector_val(<<>>, Key, Hex, true) -> 192 Val = hex:hex_to_bin(Hex), 193 {vector, {Key, Val}, hex}; 194parse_vector_val(<<>>, Key, Val, false) -> 195 {vector, {Key, Val}, raw}; 196parse_vector_val(Rest, Key, Val, Hex) -> 197 erlang:error({badarg, [Rest, Key, Val, Hex]}). 198