-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, <>} = 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).