Guest User

Untitled

a guest
Apr 26th, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.08 KB | None | 0 0
  1. -module (bencode).
  2. -export ([encode/1, decode/1]).
  3.  
  4. %% Simple bencoding definition:
  5. %% byte strings: <ascii number in base 10>:contents
  6. %% integers: i<ascii number in base 10>e
  7. %% lists: l<contents>e
  8. %% dictionaries: d<contents>e, contents are string keyed in lexographic order
  9.  
  10. %% ============
  11. %% = Exported =
  12. %% ============
  13.  
  14. %% encode a Term
  15. encode({dictionary, Entries}) when is_list(Entries) ->
  16. SortedEntries = lists:keysort(1, Entries),
  17. EncodedEntries = encode_dictionary_entries(SortedEntries),
  18. <<$d, EncodedEntries/bytes, $e>>;
  19. encode(Data) when is_list(Data) ->
  20. EncodedList = encode_list(Data),
  21. <<$l, EncodedList/bytes, $e>>;
  22. encode(Data) when is_binary(Data) ->
  23. SizeByteString = integer_to_binary_string(size(Data)),
  24. <<SizeByteString/binary, $:, Data/binary>>;
  25. encode(Data) when is_integer(Data) ->
  26. Bin = integer_to_binary_string(Data),
  27. <<$i, Bin/binary, $e>>.
  28.  
  29. %% decode a Term
  30. decode(<<$d, Rest/binary>>)->
  31. {dictionary, decode_dictionary(Rest)};
  32. decode(<<$l, Rest/bits>>) ->
  33. decode_list(Rest);
  34. decode(<<$i, Rest/bits>>) ->
  35. String = extract_list_from_binary(Rest, $e),
  36. list_to_integer(String);
  37. decode(<<Byte, Rest/bits>>) when Byte >= $0, Byte =< $9 ->
  38. Bin = <<Byte, Rest/bits>>,
  39. SizeString = extract_list_from_binary(Bin, $:),
  40. Offset = length(SizeString) * 8,
  41. Size = list_to_integer(SizeString),
  42. BitsToRead = Size * 8,
  43. try
  44. <<_SizeBytes:Offset, $:, BString:BitsToRead/bits, _MoreBin/bits>> = Bin,
  45. BString
  46. catch
  47. error:{badmatch, Bin} ->
  48. io:format("error in bencoded integer near ~p~n", [binary_to_list(Bin)])
  49. end.
  50.  
  51. %% ===========
  52. %% = Helpers =
  53. %% ===========
  54.  
  55. %% decode a dictionary
  56. decode_dictionary(<<$e, _Rest/bits>>) -> [];
  57. decode_dictionary(Bin) ->
  58. {Key, Rest1} = unshift_term(Bin),
  59. {Value, Rest2} = unshift_term(Rest1),
  60. [{Key, Value}|decode_dictionary(Rest2)].
  61.  
  62. %% decode a list
  63. decode_list(<<$e, _Rest/bits>>) -> [];
  64. decode_list(Bin) ->
  65. {Term, Rest} = unshift_term(Bin),
  66. [Term|decode_list(Rest)].
  67.  
  68. %% decode one term from a bencoded binary string
  69. unshift_term(Bin) ->
  70. Term = decode(Bin),
  71. EncodedTerm = encode(Term),
  72. Size = size(EncodedTerm),
  73. <<EncodedTerm:Size/bytes, Rest/bits>> = Bin,
  74. {Term, Rest}.
  75.  
  76. %% extract a list of bytes from a binary stopping at Delimiter
  77. extract_list_from_binary(<<Byte, Delimiter, _Rest/bits>>, Delimiter) -> [Byte];
  78. extract_list_from_binary(<<Byte, Rest/bits>>, Delimiter) ->
  79. [Byte|extract_list_from_binary(Rest, Delimiter)].
  80.  
  81. %% return a binary string representation of an integer in binary form
  82. integer_to_binary_string(N) -> list_to_binary(integer_to_list(N)).
  83.  
  84. %% encode a list of terms
  85. encode_list([H|T]) ->
  86. EncodedHead = encode(H),
  87. EncodedTail = encode_list(T),
  88. <<EncodedHead/binary, EncodedTail/binary>>;
  89. encode_list([]) -> <<>>.
  90.  
  91. %% encode a list of of {binary, Data}
  92. encode_dictionary_entries([{Name, Value}|Rest]) ->
  93. EncodedName = encode(Name),
  94. EncodedValue = encode(Value),
  95. EncodedRest = encode_dictionary_entries(Rest),
  96. <<EncodedName/binary, EncodedValue/binary, EncodedRest/binary>>;
  97. encode_dictionary_entries([]) -> <<>>.
Add Comment
Please, Sign In to add comment