feat(topic): avoid `lists:reverse` when intersecting

This commit is contained in:
Andrew Mayorov 2024-05-29 13:00:29 +02:00 committed by Serge Tupchii
parent 24be189728
commit 7b8f466adf
1 changed files with 28 additions and 25 deletions

View File

@ -112,37 +112,40 @@ match(_, _) ->
TopicOrFilter :: emqx_types:topic(). TopicOrFilter :: emqx_types:topic().
intersection(Topic1, Topic2) when is_binary(Topic1), is_binary(Topic2) -> intersection(Topic1, Topic2) when is_binary(Topic1), is_binary(Topic2) ->
case intersect_start(words(Topic1), words(Topic2)) of case intersect_start(words(Topic1), words(Topic2)) of
[] -> false; false -> false;
Intersection -> join(lists:reverse(Intersection)) Intersection -> join(Intersection)
end. end.
intersect_start([<<"$", _/bytes>> | _], [W | _]) when ?IS_WILDCARD(W) -> intersect_start([<<"$", _/bytes>> | _], [W | _]) when ?IS_WILDCARD(W) ->
[]; false;
intersect_start([W | _], [<<"$", _/bytes>> | _]) when ?IS_WILDCARD(W) -> intersect_start([W | _], [<<"$", _/bytes>> | _]) when ?IS_WILDCARD(W) ->
[]; false;
intersect_start(Words1, Words2) -> intersect_start(Words1, Words2) ->
intersection(Words1, Words2, []). intersect(Words1, Words2).
intersection(Words1, ['#'], Acc) -> intersect(Words1, ['#']) ->
lists:reverse(Words1, Acc); Words1;
intersection(['#'], Words2, Acc) -> intersect(['#'], Words2) ->
lists:reverse(Words2, Acc); Words2;
intersection([W1], ['+'], Acc) -> intersect([W1], ['+']) ->
[W1 | Acc]; [W1];
intersection(['+'], [W2], Acc) -> intersect(['+'], [W2]) ->
[W2 | Acc]; [W2];
intersection([W1 | T1], [W2 | T2], Acc) when ?IS_WILDCARD(W1), ?IS_WILDCARD(W2) -> intersect([W1 | T1], [W2 | T2]) when ?IS_WILDCARD(W1), ?IS_WILDCARD(W2) ->
intersection(T1, T2, [wildcard_intersection(W1, W2) | Acc]); intersect_join(wildcard_intersection(W1, W2), intersect(T1, T2));
intersection([W | T1], [W | T2], Acc) -> intersect([W | T1], [W | T2]) ->
intersection(T1, T2, [W | Acc]); intersect_join(W, intersect(T1, T2));
intersection([W1 | T1], [W2 | T2], Acc) when ?IS_WILDCARD(W1) -> intersect([W1 | T1], [W2 | T2]) when ?IS_WILDCARD(W1) ->
intersection(T1, T2, [W2 | Acc]); intersect_join(W2, intersect(T1, T2));
intersection([W1 | T1], [W2 | T2], Acc) when ?IS_WILDCARD(W2) -> intersect([W1 | T1], [W2 | T2]) when ?IS_WILDCARD(W2) ->
intersection(T1, T2, [W1 | Acc]); intersect_join(W1, intersect(T1, T2));
intersection([], [], Acc) -> intersect([], []) ->
Acc; [];
intersection(_, _, _) -> intersect(_, _) ->
[]. false.
intersect_join(_, false) -> false;
intersect_join(W, Words) -> [W | Words].
wildcard_intersection(W, W) -> W; wildcard_intersection(W, W) -> W;
wildcard_intersection(_, _) -> '+'. wildcard_intersection(_, _) -> '+'.