Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 7th, 2012  |  syntax: None  |  size: 3.03 KB  |  hits: 12  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.  
  2. -module(uleb128).
  3.  
  4. -export([encode/1, encode/2, decode/1, decode/2]).
  5.  
  6. % For property tests
  7. -include_lib("proper/include/proper.hrl").
  8. -export([prop_encode_decode/0]).
  9.  
  10. -spec encode(non_neg_integer()) -> binary().
  11. encode(I) when I >= 0 -> encode_1(I, 0).
  12.  
  13. -spec encode(non_neg_integer(), binary()) -> binary().
  14. encode(I, Acc) -> <<Acc/binary, (encode_1(I, 0))/binary>>.
  15.  
  16. -spec encode_1(non_neg_integer(),
  17.                non_neg_integer()) -> binary().
  18. encode_1(I, Acc) when I > 16#7f ->
  19.     Val = I band 16#7f bor 16#80,
  20.     encode_1(I bsr 7, Acc bsl 8 bor Val);
  21. encode_1(I, Acc) ->
  22.     binary:encode_unsigned(Acc bsl 8 bor I).
  23.  
  24. -type decode_cont() :: {cont,
  25.                         non_neg_integer(),
  26.                         non_neg_integer(),
  27.                         non_neg_integer()}.
  28. -type decode_ret() :: non_neg_integer()
  29.                       | {non_neg_integer(), binary()}
  30.                       | decode_cont().
  31. -spec decode(binary()) -> decode_ret().
  32. decode(<<0:1, A:7>>) -> A;
  33. decode(<<0:1, A:7, Rest/binary>>) -> {A, Rest};
  34. decode(<<1:1, A:7, 0:1, B:7>>) -> B bsl 7 bor A;
  35. decode(<<1:1, A:7, 0:1, B:7, Rest/binary>>) ->
  36.     {B bsl 7 bor A, Rest};
  37. decode(<<1:1, A:7, 1:1, B:7, 0:1, C:7>>) ->
  38.     (C bsl 14) bor (B bsl 7) bor A;
  39. decode(<<1:1, A:7, 1:1, B:7, 0:1, C:7, Rest/binary>>) ->
  40.     {(C bsl 14) bor (B bsl 7) bor A, Rest};
  41. decode(<<1:1, A:7, 1:1, B:7, 1:1, C:7, 0:1, D:7>>) ->
  42.     (D bsl 21) bor (C bsl 14) bor (B bsl 7) bor A;
  43. decode(<<1:1, A:7, 1:1, B:7, 1:1, C:7, 0:1, D:7, Rest/binary>>) ->
  44.     {(D bsl 21) bor (C bsl 14) bor (B bsl 7) bor A, Rest};
  45. decode(<<1:1, A:7, 1:1, B:7, 1:1, C:7, 1:1, D:7, _/binary>> = Bin) ->
  46.     Acc = (D bsl 21) bor (C bsl 14) bor (B bsl 7) bor A,
  47.     decode(Bin, {cont, Acc, 4, 4});
  48. decode(Bin) ->
  49.     decode(Bin, {cont, 0, 0, 0}).
  50.  
  51. -spec decode(binary(), decode_cont()) -> decode_ret().
  52. decode(Bin, {cont, Acc, X, Offset}) ->
  53.     case Bin of
  54.         <<_:Offset/bytes, 0:1, I:7>> ->
  55.             Acc bor (I bsl (X * 7));
  56.         <<_:Offset/bytes, 0:1, I:7, Rest/binary>> ->
  57.             Result = Acc bor (I bsl (X * 7)),
  58.             {Result, Rest};
  59.         <<_:Offset/bytes, 1:1, I:7>> ->
  60.             {cont, Acc bor (I bsl (X * 7)), X + 1, 0};
  61.         <<_:Offset/bytes, 1:1, I:7, _/binary>> ->
  62.             Acc1 = Acc bor (I bsl (X * 7)),
  63.             decode(Bin, {cont, Acc1, X + 1, Offset + 1})
  64.     end.
  65.  
  66. large_non_neg_integer() ->
  67.     union([integer(0, inf),
  68.            integer(16#7f, inf),
  69.            integer(16#3fff, inf),
  70.            integer(16#1fffff, inf),
  71.            integer(16#fffffff, inf)]).
  72.  
  73. % Properties for testing
  74. prop_encode_decode() ->
  75.     ?FORALL(I, large_non_neg_integer(), begin I =:= decode(encode(I)) end).
  76.  
  77. prop_encode_decode_long() ->
  78.     ?FORALL(I, large_non_neg_integer(),
  79.             begin
  80.                 Bin = encode(I),
  81.                 Cont = decode(<<(binary:at(Bin, 0))>>),
  82.                 I =:=
  83.                     lists:foldl(
  84.                       fun(X, Acc) ->
  85.                               decode(<<(binary:at(Bin, X))>>, Acc)
  86.                       end, Cont, lists:seq(1, byte_size(Bin) - 1))
  87.             end).