diff --git a/src/emqttd_base62.erl b/src/emqttd_base62.erl new file mode 100644 index 000000000..1e9d0a1a2 --- /dev/null +++ b/src/emqttd_base62.erl @@ -0,0 +1,58 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2016 Feng Lee . +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqttd_base62). + +-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 -> + [char(I) | Acc]; +encode(I, Acc) -> + encode(I div 62, [char(I rem 62) | Acc]). + +char(I) when I < 10 -> + $0 + I; + +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(binary_to_list(B)); +decode(S) when is_list(S) -> + decode(S, 0). + +decode([], I) -> + I; +decode([C|S], I) -> + decode(S, I * 62 + byte(C)). + +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. + diff --git a/test/emqttd_lib_SUITE.erl b/test/emqttd_lib_SUITE.erl index 33a5e3547..1a3b1aef6 100644 --- a/test/emqttd_lib_SUITE.erl +++ b/test/emqttd_lib_SUITE.erl @@ -28,9 +28,11 @@ -define(PQ, priority_queue). +-define(BASE62, emqttd_base62). + all() -> [{group, guid}, {group, opts}, {group, ?PQ}, {group, time}, - {group, node}]. + {group, node}, {group, base62}]. groups() -> [{guid, [], [guid_gen]}, @@ -38,7 +40,8 @@ groups() -> {?PQ, [], [priority_queue_plen, priority_queue_out2]}, {time, [], [time_now_to_]}, - {node, [], [node_is_aliving, node_parse_name]}]. + {node, [], [node_is_aliving, node_parse_name]}, + {base62, [], [base62_encode]}]. %%-------------------------------------------------------------------- %% emqttd_guid @@ -144,3 +147,17 @@ node_parse_name(_) -> 'a@127.0.0.1' = emqttd_node:parse_name("a@127.0.0.1"), 'b@127.0.0.1' = emqttd_node:parse_name("b"). +%%-------------------------------------------------------------------- +%% base62 encode decode +%%-------------------------------------------------------------------- + +base62_encode(_) -> + 10 = ?BASE62:decode(?BASE62:encode(10)), + 100 = ?BASE62:decode(?BASE62:encode(100)), + 9999 = ?BASE62:decode(?BASE62:encode(9999)), + 65535 = ?BASE62:decode(?BASE62:encode(65535)), + <> = emqttd_guid:gen(), + <> = emqttd_guid:gen(), + X = ?BASE62:decode(?BASE62:encode(X)), + Y = ?BASE62:decode(?BASE62:encode(Y)). +