Enhance base62 encode/decode Funs

This commit is contained in:
Gilbert Wong 2018-08-06 23:45:27 +08:00
parent 645c971a07
commit 79481db659
3 changed files with 86 additions and 40 deletions

View File

@ -16,41 +16,86 @@
-export([encode/1, decode/1]). -export([encode/1, decode/1]).
%% @doc Encode an integer to base62 string
-spec(encode(non_neg_integer()) -> binary()).
encode(I) when is_integer(I) andalso I > 0 ->
list_to_binary(encode(I, [])).
encode(I, Acc) when I < 62 -> %% @doc Encode any data to base62 binary
[char(I) | Acc]; -spec encode(string()
encode(I, Acc) -> | integer()
encode(I div 62, [char(I rem 62) | Acc]). | binary()) -> float().
encode(I) when is_integer(I) ->
encode(integer_to_binary(I));
encode(S) when is_list(S)->
encode(list_to_binary(S));
encode(B) when is_binary(B) ->
encode(B, <<>>).
char(I) when I < 10 -> %% @doc Decode base62 binary to origin data binary
$0 + I; decode(L) when is_list(L) ->
decode(list_to_binary(L));
char(I) when I < 36 ->
$A + I - 10;
char(I) when I < 62 ->
$a + I - 36.
%% @doc Decode base62 string to an integer
-spec(decode(string() | binary()) -> integer()).
decode(B) when is_binary(B) -> decode(B) when is_binary(B) ->
decode(binary_to_list(B)); decode(B, <<>>).
decode(S) when is_list(S) ->
decode(S, 0).
decode([], I) -> %% encode_base62(<<H:24, Rest/binary>>, Acc) ->
I; %% encode_byte_group(H, Acc);
decode([C|S], I) -> %% encode_base62(<<H:16, Rest/binary>>, Acc) ->
decode(S, I * 62 + byte(C)). %% encode_byte_group(H, Acc);
byte(C) when $0 =< C andalso C =< $9 ->
C - $0;
byte(C) when $A =< C andalso C =< $Z ->
C - $A + 10;
byte(C) when $a =< C andalso C =< $z ->
C - $a + 36.
encode(<<Index1:6, Index2:6, Index3:6, Index4:6, Rest/binary>>, Acc) ->
CharList = [encode_char(Index1), encode_char(Index2), encode_char(Index3), encode_char(Index4)],
NewAcc = <<Acc/binary,(iolist_to_binary(CharList))/binary>>,
encode(Rest, NewAcc);
encode(<<Index1:6, Index2:6, Index3:4>>, Acc) ->
CharList = [encode_char(Index1), encode_char(Index2), encode_char(Index3)],
NewAcc = <<Acc/binary,(iolist_to_binary(CharList))/binary>>,
encode(<<>>, NewAcc);
encode(<<Index1:6, Index2:2>>, Acc) ->
CharList = [encode_char(Index1), encode_char(Index2)],
NewAcc = <<Acc/binary,(iolist_to_binary(CharList))/binary>>,
encode(<<>>, NewAcc);
encode(<<>>, Acc) ->
Acc.
decode(<<Head:8, Rest/binary>>, Acc)
when bit_size(Rest) >= 8->
case Head == $9 of
true ->
<<Head1:8, Rest1/binary>> = Rest,
DecodeChar = decode_char(9, Head1),
<<_:2, RestBit:6>> = <<DecodeChar>>,
NewAcc = <<Acc/bitstring, RestBit:6>>,
decode(Rest1, NewAcc);
false ->
DecodeChar = decode_char(Head),
<<_:2, RestBit:6>> = <<DecodeChar>>,
NewAcc = <<Acc/bitstring, RestBit:6>>,
decode(Rest, NewAcc)
end;
decode(<<Head:8, Rest/binary>>, Acc) ->
DecodeChar = decode_char(Head),
LeftBitSize = bit_size(Acc) rem 8,
RightBitSize = 8 - LeftBitSize,
<<_:LeftBitSize, RestBit:RightBitSize>> = <<DecodeChar>>,
NewAcc = <<Acc/bitstring, RestBit:RightBitSize>>,
decode(Rest, NewAcc);
decode(<<>>, Acc) ->
Acc.
encode_char(I) when I < 26 ->
$A + I;
encode_char(I) when I < 52 ->
$a + I - 26;
encode_char(I) when I < 61 ->
$0 + I - 52;
encode_char(I) ->
[$9, $A + I - 61].
decode_char(I) when I >= $a andalso I =< $z ->
I + 26 - $a;
decode_char(I) when I >= $0 andalso I =< $8->
I + 52 - $0;
decode_char(I) when I >= $A andalso I =< $Z->
I - $A.
decode_char(9, I) ->
I + 61 - $A.

View File

@ -126,8 +126,9 @@ from_hexstr(S) ->
I = list_to_integer(binary_to_list(S), 16), <<I:128>>. I = list_to_integer(binary_to_list(S), 16), <<I:128>>.
to_base62(<<I:128>>) -> to_base62(<<I:128>>) ->
emqx_base62:encode(I). binary_to_list(emqx_base62:encode(I)).
from_base62(S) -> from_base62(S) ->
I = emqx_base62:decode(S), <<I:128>>. I = binary_to_integer(emqx_base62:decode(S)),
<<I:128>>.

View File

@ -26,11 +26,11 @@
all() -> [t_base62_encode]. all() -> [t_base62_encode].
t_base62_encode(_) -> t_base62_encode(_) ->
10 = ?BASE62:decode(?BASE62:encode(10)), <<"10">> = ?BASE62:decode(?BASE62:encode(<<"10">>)),
100 = ?BASE62:decode(?BASE62:encode(100)), <<"100">> = ?BASE62:decode(?BASE62:encode(<<"100">>)),
9999 = ?BASE62:decode(?BASE62:encode(9999)), <<"9999">> = ?BASE62:decode(?BASE62:encode(<<"9999">>)),
65535 = ?BASE62:decode(?BASE62:encode(65535)), <<"65535">> = ?BASE62:decode(?BASE62:encode(<<"65535">>)),
<<X:128/unsigned-big-integer>> = emqx_guid:gen(), <<X:128/unsigned-big-integer>> = emqx_guid:gen(),
<<Y:128/unsigned-big-integer>> = emqx_guid:gen(), <<Y:128/unsigned-big-integer>> = emqx_guid:gen(),
X = ?BASE62:decode(?BASE62:encode(X)), X = erlang:binary_to_integer(?BASE62:decode(?BASE62:encode(X))),
Y = ?BASE62:decode(?BASE62:encode(Y)). Y = erlang:binary_to_integer(?BASE62:decode(?BASE62:encode(Y))).