perf(topic): use tail recursive to joining a topic
This commit is contained in:
parent
b0e18f5e75
commit
4ea3483083
|
@ -39,6 +39,11 @@
|
||||||
-type word() :: emqx_types:word().
|
-type word() :: emqx_types:word().
|
||||||
-type words() :: emqx_types:words().
|
-type words() :: emqx_types:words().
|
||||||
|
|
||||||
|
%% Guards
|
||||||
|
-define(MULTI_LEVEL_WILDCARD_NOT_LAST(C, REST),
|
||||||
|
((C =:= '#' orelse C =:= <<"#">>) andalso REST =/= [])
|
||||||
|
).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% APIs
|
%% APIs
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -110,7 +115,8 @@ validate2([]) ->
|
||||||
% end with '#'
|
% end with '#'
|
||||||
validate2(['#']) ->
|
validate2(['#']) ->
|
||||||
true;
|
true;
|
||||||
validate2(['#' | Words]) when length(Words) > 0 ->
|
%% MQTT-5.0 [MQTT-4.7.1-1]
|
||||||
|
validate2([C | Words]) when ?MULTI_LEVEL_WILDCARD_NOT_LAST(C, Words) ->
|
||||||
error('topic_invalid_#');
|
error('topic_invalid_#');
|
||||||
validate2(['' | Words]) ->
|
validate2(['' | Words]) ->
|
||||||
validate2(Words);
|
validate2(Words);
|
||||||
|
@ -213,20 +219,16 @@ feed_var(Var, Val, [W | Words], Acc) ->
|
||||||
-spec join(list(word())) -> binary().
|
-spec join(list(word())) -> binary().
|
||||||
join([]) ->
|
join([]) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
join([W]) ->
|
join([Word | Words]) ->
|
||||||
bin(W);
|
do_join(bin(Word), Words).
|
||||||
join(Words) ->
|
|
||||||
{_, Bin} = lists:foldr(
|
do_join(TopicAcc, []) ->
|
||||||
fun
|
TopicAcc;
|
||||||
(W, {true, Tail}) ->
|
%% MQTT-5.0 [MQTT-4.7.1-1]
|
||||||
{false, <<W/binary, Tail/binary>>};
|
do_join(_TopicAcc, [C | Words]) when ?MULTI_LEVEL_WILDCARD_NOT_LAST(C, Words) ->
|
||||||
(W, {false, Tail}) ->
|
error('topic_invalid_#');
|
||||||
{false, <<W/binary, "/", Tail/binary>>}
|
do_join(TopicAcc, [Word | Words]) ->
|
||||||
end,
|
do_join(<<TopicAcc/binary, "/", (bin(Word))/binary>>, Words).
|
||||||
{true, <<>>},
|
|
||||||
[bin(W) || W <- Words]
|
|
||||||
),
|
|
||||||
Bin.
|
|
||||||
|
|
||||||
-spec parse(topic() | {topic(), map()}) -> {topic(), #{share => binary()}}.
|
-spec parse(topic() | {topic(), map()}) -> {topic(), #{share => binary()}}.
|
||||||
parse(TopicFilter) when is_binary(TopicFilter) ->
|
parse(TopicFilter) when is_binary(TopicFilter) ->
|
||||||
|
|
|
@ -199,7 +199,10 @@ t_join(_) ->
|
||||||
?assertEqual(<<"+//#">>, join(['+', '', '#'])),
|
?assertEqual(<<"+//#">>, join(['+', '', '#'])),
|
||||||
?assertEqual(<<"x/y/z/+">>, join([<<"x">>, <<"y">>, <<"z">>, '+'])),
|
?assertEqual(<<"x/y/z/+">>, join([<<"x">>, <<"y">>, <<"z">>, '+'])),
|
||||||
?assertEqual(<<"/ab/cd/ef/">>, join(words(<<"/ab/cd/ef/">>))),
|
?assertEqual(<<"/ab/cd/ef/">>, join(words(<<"/ab/cd/ef/">>))),
|
||||||
?assertEqual(<<"ab/+/#">>, join(words(<<"ab/+/#">>))).
|
?assertEqual(<<"ab/+/#">>, join(words(<<"ab/+/#">>))),
|
||||||
|
%% MQTT-5.0 [MQTT-4.7.1-1]
|
||||||
|
?assertError('topic_invalid_#', join(['+', <<"a">>, '#', <<"b">>, '', '+'])),
|
||||||
|
?assertError('topic_invalid_#', join(['+', <<"c">>, <<"#">>, <<"d">>, '', '+'])).
|
||||||
|
|
||||||
t_systop(_) ->
|
t_systop(_) ->
|
||||||
SysTop1 = iolist_to_binary(["$SYS/brokers/", atom_to_list(node()), "/xyz"]),
|
SysTop1 = iolist_to_binary(["$SYS/brokers/", atom_to_list(node()), "/xyz"]),
|
||||||
|
|
Loading…
Reference in New Issue