diff --git a/lib/stampede.ex b/lib/stampede.ex index 24eb448..917bb39 100644 --- a/lib/stampede.ex +++ b/lib/stampede.ex @@ -138,57 +138,43 @@ defmodule Stampede do end @doc """ - If passed a text prefix, will match the start of the string. If passed a - regex, it will match whatever was given and return the first match group. - """ - @spec! strip_prefix(String.t() | Regex.t(), String.t()) :: false | String.t() - def strip_prefix(prefix, text) - ## here comes the "smart" """optimized""" solution - when is_binary(prefix) and - binary_part(text, 0, floor(bit_size(prefix) / 8)) == prefix do - binary_part(text, floor(bit_size(prefix) / 8), floor((bit_size(text) - bit_size(prefix)) / 8)) - end + Takes a prefix and a string. Returns the matched part, and the rest of the string. The prefix can be a single string, or a list of strings. - def strip_prefix(prefix, text) - when is_binary(prefix) and - binary_part(text, 0, floor(bit_size(prefix) / 8)) != prefix, - do: false + Here is a single prefix. - def strip_prefix(rex, text) when is_struct(rex, Regex) do - case Regex.run(rex, text) do - nil -> false - [_p, body] -> body - end - end + iex> alias Stampede, as: S + iex> S.split_prefix("!ping", "!") + {"!", "ping"} + iex> S.split_prefix("ping", "!") + {false, "ping"} + iex> S.split_prefix("!", "!") + {false, "!"} - def split_prefix(text, prefix) when is_struct(prefix, Regex) and is_binary(text) do - case Regex.split(prefix, text, include_captures: true, capture: :first, trim: true) do - [p, b] -> - {p, b} + Here is a binary list, which is more performant than the Regex module. - [^text] -> - {false, text} - - [] -> - {false, text} - end - end + iex> bl = ["S, ", "S ", "s, ", "s "] + iex> S.split_prefix("S, ping", bl) + {"S, ", "ping"} + """ def split_prefix(text, prefix) when is_binary(prefix) and is_binary(text) do case text do - # don't match prefix without message - <<^prefix::binary-size(floor(bit_size(prefix) / 8)), ""::binary>> -> - {false, text} - - # don't match prefix without message - <<^prefix::binary-size(floor(bit_size(prefix) / 8)), " "::binary>> -> - {false, text} - <<^prefix::binary-size(floor(bit_size(prefix) / 8)), _::binary>> -> - { - binary_part(text, 0, byte_size(prefix)), - binary_part(text, byte_size(prefix), byte_size(text) - byte_size(prefix)) - } + prefix_part = binary_part(text, 0, byte_size(prefix)) + msg_part = binary_part(text, byte_size(prefix), byte_size(text) - byte_size(prefix)) + + # final whitespace check + # TODO: benchmark with/without + case String.trim(msg_part) do + "" -> + {false, text} + + _ -> + { + prefix_part, + msg_part + } + end _ -> {false, text} diff --git a/test/stampede_stateless_test.exs b/test/stampede_stateless_test.exs index b6ac537..e7cf1d0 100644 --- a/test/stampede_stateless_test.exs +++ b/test/stampede_stateless_test.exs @@ -62,6 +62,12 @@ defmodule StampedeStatelessTest do assert_value SiteConfig.check_prefixes_for_conflicts(bl) == :no_conflict end + test "split_prefix whitespace sanity" do + assert S.split_prefix("! ", "!") == {false, "! "} + assert S.split_prefix("! ", "!") == {false, "! "} + assert S.split_prefix("S, ", "S, ") == {false, "S, "} + end + test "cfg prefix conflict sorting" do rev = ["a", "b", "c", "aa", "ab", "ba", "bc", "aaa", "aba", "bbc", "cac", "aaaa", "ddddd"] diff --git a/test/stampede_test.exs b/test/stampede_test.exs index 9a40c30..2506cc9 100644 --- a/test/stampede_test.exs +++ b/test/stampede_test.exs @@ -4,7 +4,6 @@ defmodule StampedeTest do alias Stampede, as: S alias Services.Dummy, as: D import AssertValue - doctest Stampede @confused_response S.confused_response() |> TxtBlock.to_binary(Services.Dummy)