Current section
Files
Jump to
Current section
Files
src/boyer_moore.erl
-module(boyer_moore).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([search_bounded/3, search/2, default_equality/2, build_generic_searcher/2, build_byte_searcher/1]).
-export_type([bounds/0, searcher/1, api/2]).
-type bounds() :: {bounds,
gleam@option:option(integer()),
gleam@option:option(integer())}.
-opaque searcher(EYH) :: {searcher,
fun((EYH, bounds()) -> {ok, integer()} | {error, nil})}.
-type api(EYI, EYJ) :: {api,
fun((EYI) -> integer()),
fun((EYJ, EYJ) -> boolean()),
fun((EYI, integer()) -> EYJ)}.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 116).
-spec search_bounded(EYU, searcher(EYU), bounds()) -> {ok, integer()} |
{error, nil}.
search_bounded(Data, Searcher, Bounds) ->
case Bounds of
{bounds, {some, Start}, {some, End}} when Start =:= End ->
{error, nil};
_ ->
(erlang:element(2, Searcher))(Data, Bounds)
end.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 109).
-spec search(EYR, searcher(EYR)) -> {ok, integer()} | {error, nil}.
search(Data, Searcher) ->
search_bounded(Data, Searcher, {bounds, none, none}).
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 131).
-spec default_equality(EYX, EYX) -> boolean().
default_equality(A, B) ->
A =:= B.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 135).
-spec build_bad_chars(
api(EYZ, EZA),
EYZ,
gleam@dict:dict(EZA, integer()),
integer(),
integer()
) -> gleam@dict:dict(EZA, integer()).
build_bad_chars(Api, Pattern, Positions, Pattern_size, I) ->
case I < Pattern_size of
true ->
Piece = (erlang:element(4, Api))(Pattern, I),
Positions@1 = gleam@dict:insert(Positions, Piece, I),
build_bad_chars(Api, Pattern, Positions@1, Pattern_size, I + 1);
false ->
Positions
end.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 191).
-spec calculate_skip(
api(EZO, EZP),
EZO,
EZO,
gleam@dict:dict(EZP, integer()),
integer(),
integer()
) -> integer().
calculate_skip(Api, Data, Pattern, Bad_chars, Current, Current_pattern_index) ->
case Current_pattern_index < 0 of
true ->
0;
false ->
Char = (erlang:element(4, Api))(
Data,
Current + Current_pattern_index
),
Pattern_char = (erlang:element(4, Api))(
Pattern,
Current_pattern_index
),
case (erlang:element(3, Api))(Char, Pattern_char) of
true ->
calculate_skip(
Api,
Data,
Pattern,
Bad_chars,
Current,
Current_pattern_index - 1
);
false ->
Pos = gleam@result:unwrap(
gleam_stdlib:map_get(Bad_chars, Char),
-1
),
gleam@int:max(1, Current_pattern_index - Pos)
end
end.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 152).
-spec do_search_loop(
api(EZH, EZI),
EZH,
EZH,
gleam@dict:dict(EZI, integer()),
integer(),
integer(),
integer()
) -> integer().
do_search_loop(
Api,
Data,
Pattern,
Bad_chars,
Current,
Last_index,
Last_pattern_index
) ->
case Current > Last_index of
true ->
-1;
false ->
case calculate_skip(
Api,
Data,
Pattern,
Bad_chars,
Current,
Last_pattern_index
) of
0 ->
Current;
Skip ->
Current@1 = Current + Skip,
do_search_loop(
Api,
Data,
Pattern,
Bad_chars,
Current@1,
Last_index,
Last_pattern_index
)
end
end.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 59).
-spec build_generic_searcher(EYK, api(EYK, any())) -> {ok, searcher(EYK)} |
{error, nil}.
build_generic_searcher(Pattern, Api) ->
Size = (erlang:element(2, Api))(Pattern),
gleam@bool:guard(
Size =:= 0,
{error, nil},
fun() ->
Bad_chars = maps:new(),
Bad_chars@1 = build_bad_chars(Api, Pattern, Bad_chars, Size, 0),
Fun = fun(Data, Bounds) ->
Data_size = (erlang:element(2, Api))(Data),
case Data_size of
0 ->
{error, nil};
_ ->
Start = gleam@int:clamp(
gleam@option:unwrap(erlang:element(2, Bounds), 0),
0,
Data_size
),
End = gleam@int:clamp(
gleam@option:unwrap(
erlang:element(3, Bounds),
Data_size
),
Start,
Data_size
),
Last_index = End - Size,
Last_pattern_index = Size - 1,
case do_search_loop(
Api,
Data,
Pattern,
Bad_chars@1,
Start,
Last_index,
Last_pattern_index
) of
-1 ->
{error, nil};
I ->
{ok, I}
end
end
end,
{ok, {searcher, Fun}}
end
).
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 245).
-spec bit_array_at(bitstring(), integer()) -> integer().
bit_array_at(Data, I) ->
_assert_subject = gleam_stdlib:bit_array_slice(Data, I, 1),
{ok, <<Byte:8>>} = case _assert_subject of
{ok, <<_:8>>} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"boyer_moore"/utf8>>,
function => <<"bit_array_at"/utf8>>,
line => 246})
end,
Byte.
-file("/Users/nicd/svn/boyer_moore/src/boyer_moore.gleam", 234).
-spec build_byte_searcher(bitstring()) -> {ok, searcher(bitstring())} |
{error, nil}.
build_byte_searcher(Pattern) ->
boyer_moore_ffi:build_pattern(Pattern).