PageRenderTime 36ms CodeModel.GetById 23ms app.highlight 5ms RepoModel.GetById 0ms app.codeStats 0ms

/run Torrent client/parser.erl

http://github.com/anonymous-admin/anonymous
Erlang | 73 lines | 52 code | 9 blank | 12 comment | 1 complexity | 052e0cab887b57fdd2868309cf9f1d87 MD5 | raw file
 1-module(parser).
 2
 3-export([decode/1, encode/1]).
 4-define(DICT, dict).
 5
 6decode(Data) ->
 7    dec(Data).
 8    % case catch dec(Data) of
 9    %     {'EXIT', _} ->
10    %         {error, unparsed};
11    %     {Res, _} ->
12    %         {ok, Res}
13    % end.
14
15encode(Struct) ->
16    iolist_to_binary(enc(Struct)).
17
18%%--------------------------------------------------------------------
19%% Decoding
20%%--------------------------------------------------------------------
21dec(<<$l, Tail/binary>>) ->
22    dec_list(Tail, []);
23dec(<<$d, Tail/binary>>) ->
24    dec_dict(Tail, ?DICT:new());
25dec(<<$i, Tail/binary>>) ->
26    dec_int(Tail, []);
27dec(Data) ->
28    dec_string(Data, []).
29
30dec_int(<<$e, Tail/binary>>, Acc) ->
31    {list_to_integer(lists:reverse(Acc)), Tail};
32dec_int(<<X, Tail/binary>>, Acc) ->
33    dec_int(Tail, [X|Acc]).
34
35dec_string(<<$:, Tail/binary>>, Acc) ->
36    Int = list_to_integer(lists:reverse(Acc)),
37    <<Str:Int/binary, Rest/binary>> = Tail,
38    {Str, Rest};
39dec_string(<<X, Tail/binary>>, Acc) ->
40    dec_string(Tail, [X|Acc]).
41
42dec_list(<<$e, Tail/binary>>, Acc) ->
43    {{list, lists:reverse(Acc)}, Tail};
44dec_list(Data, Acc) ->
45    {Res, Tail} = dec(Data),
46    dec_list(Tail, [Res|Acc]).
47
48dec_dict(<<$e, Tail/binary>>, Acc) ->
49    {{dict, Acc}, Tail};
50dec_dict(Data, Acc) ->
51    {Key, Tail1} = dec(Data),
52    {Val, Tail2} = dec(Tail1),
53    dec_dict(Tail2, ?DICT:store(Key, Val, Acc)).
54
55%%--------------------------------------------------------------------
56%% Encoding
57%%--------------------------------------------------------------------
58enc(Int) when is_integer(Int) ->
59    IntBin = list_to_binary(integer_to_list(Int)),
60    [$i, IntBin, $e];
61enc(Str) when is_list(Str) ->
62    enc(list_to_binary(Str));
63enc(Str) when is_binary(Str) ->
64    IntBin = list_to_binary(integer_to_list(size(Str))),
65    [IntBin, $:, Str];
66enc({list, List}) when is_list(List) ->
67    [$l, [enc(Elem) || Elem <- List], $e];
68enc({dict, Dict}) ->
69    Data = lists:map(
70	     fun({Key, Val}) when is_list(Key) or is_binary(Key) ->
71		     [enc(Key), enc(Val)]
72	     end, lists:keysort(1, ?DICT:to_list(Dict))),
73    [$d, Data, $e].