{-# LANGUAGE BangPatterns #-}
module Data.ByteString.Lazy.Search.DFA (
indices
, nonOverlappingIndices
, breakOn
, breakAfter
, breakFindAfter
, replace
, split
, splitKeepEnd
, splitKeepFront
) where
import Data.ByteString.Search.Internal.Utils (automaton, keep, ldrop, lsplit)
import Data.ByteString.Search.Substitution
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Internal as LI
import Data.ByteString.Unsafe (unsafeIndex)
import Data.Array.Base (unsafeAt)
import Data.Bits
import Data.Int (Int64)
{-# INLINE indices #-}
indices :: S.ByteString
-> L.ByteString
-> [Int64]
indices :: ByteString -> ByteString -> [Int64]
indices !ByteString
pat = Bool -> ByteString -> [ByteString] -> [Int64]
lazySearcher Bool
True ByteString
pat ([ByteString] -> [Int64])
-> (ByteString -> [ByteString]) -> ByteString -> [Int64]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
{-# INLINE nonOverlappingIndices #-}
nonOverlappingIndices :: S.ByteString
-> L.ByteString
-> [Int64]
nonOverlappingIndices :: ByteString -> ByteString -> [Int64]
nonOverlappingIndices !ByteString
pat = Bool -> ByteString -> [ByteString] -> [Int64]
lazySearcher Bool
False ByteString
pat ([ByteString] -> [Int64])
-> (ByteString -> [ByteString]) -> ByteString -> [Int64]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
breakOn :: S.ByteString
-> L.ByteString
-> (L.ByteString, L.ByteString)
breakOn :: ByteString -> ByteString -> (ByteString, ByteString)
breakOn pat :: ByteString
pat = [ByteString] -> (ByteString, ByteString)
breaker ([ByteString] -> (ByteString, ByteString))
-> (ByteString -> [ByteString])
-> ByteString
-> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
lbrk :: [ByteString] -> ([ByteString], [ByteString])
lbrk = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
True ByteString
pat
breaker :: [ByteString] -> (ByteString, ByteString)
breaker strs :: [ByteString]
strs = let (f :: [ByteString]
f, b :: [ByteString]
b) = [ByteString] -> ([ByteString], [ByteString])
lbrk [ByteString]
strs
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
f, [ByteString] -> ByteString
L.fromChunks [ByteString]
b)
breakAfter :: S.ByteString
-> L.ByteString
-> (L.ByteString, L.ByteString)
breakAfter :: ByteString -> ByteString -> (ByteString, ByteString)
breakAfter pat :: ByteString
pat = [ByteString] -> (ByteString, ByteString)
breaker ([ByteString] -> (ByteString, ByteString))
-> (ByteString -> [ByteString])
-> ByteString
-> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
lbrk :: [ByteString] -> ([ByteString], [ByteString])
lbrk = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
False ByteString
pat
breaker :: [ByteString] -> (ByteString, ByteString)
breaker strs :: [ByteString]
strs = let (f :: [ByteString]
f, b :: [ByteString]
b) = [ByteString] -> ([ByteString], [ByteString])
lbrk [ByteString]
strs
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
f, [ByteString] -> ByteString
L.fromChunks [ByteString]
b)
breakFindAfter :: S.ByteString
-> L.ByteString
-> ((L.ByteString, L.ByteString), Bool)
breakFindAfter :: ByteString -> ByteString -> ((ByteString, ByteString), Bool)
breakFindAfter pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = \str :: ByteString
str -> ((ByteString
L.empty, ByteString
str), Bool
True)
breakFindAfter pat :: ByteString
pat = [ByteString] -> ((ByteString, ByteString), Bool)
breaker ([ByteString] -> ((ByteString, ByteString), Bool))
-> (ByteString -> [ByteString])
-> ByteString
-> ((ByteString, ByteString), Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
!patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
lbrk :: [ByteString] -> ([ByteString], [ByteString])
lbrk = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
True ByteString
pat
breaker :: [ByteString] -> ((ByteString, ByteString), Bool)
breaker strs :: [ByteString]
strs = let (f :: [ByteString]
f, b :: [ByteString]
b) = [ByteString] -> ([ByteString], [ByteString])
lbrk [ByteString]
strs
(f1 :: [ByteString]
f1, b1 :: [ByteString]
b1) = Int -> [ByteString] -> ([ByteString], [ByteString])
lsplit Int
patLen [ByteString]
b
mbpat :: ByteString
mbpat = [ByteString] -> ByteString
L.fromChunks [ByteString]
f1
in (((ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ByteString -> ByteString -> ByteString
LI.chunk ByteString
mbpat [ByteString]
f, [ByteString] -> ByteString
L.fromChunks [ByteString]
b1), Bool -> Bool
not ([ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
b))
replace :: Substitution rep
=> S.ByteString
-> rep
-> L.ByteString
-> L.ByteString
replace :: ByteString -> rep -> ByteString -> ByteString
replace pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = \sub :: rep
sub -> rep -> ByteString -> ByteString
forall a. Substitution a => a -> ByteString -> ByteString
prependCycle rep
sub
| Bool
otherwise =
let !patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
breaker :: [ByteString] -> ([ByteString], [ByteString])
breaker = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
True ByteString
pat
repl :: ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
repl subst :: [ByteString] -> [ByteString]
subst strs :: [ByteString]
strs
| [ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
strs = []
| Bool
otherwise =
let (pre :: [ByteString]
pre, mtch :: [ByteString]
mtch) = [ByteString] -> ([ByteString], [ByteString])
breaker [ByteString]
strs
in [ByteString]
pre [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ case [ByteString]
mtch of
[] -> []
_ -> [ByteString] -> [ByteString]
subst (([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
repl [ByteString] -> [ByteString]
subst (Int -> [ByteString] -> [ByteString]
ldrop Int
patLen [ByteString]
mtch))
in \sub :: rep
sub -> let {-# NOINLINE subst #-}
!subst :: [ByteString] -> [ByteString]
subst = rep -> [ByteString] -> [ByteString]
forall a. Substitution a => a -> [ByteString] -> [ByteString]
substitution rep
sub
repl1 :: [ByteString] -> [ByteString]
repl1 = ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
repl [ByteString] -> [ByteString]
subst
in [ByteString] -> ByteString
L.fromChunks ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [ByteString]
repl1 ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
split :: S.ByteString
-> L.ByteString
-> [L.ByteString]
split :: ByteString -> ByteString -> [ByteString]
split pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = [ByteString] -> ByteString -> [ByteString]
forall a b. a -> b -> a
const (ByteString -> [ByteString]
forall a. a -> [a]
repeat ByteString
L.empty)
split pat :: ByteString
pat = ([ByteString] -> ByteString) -> [[ByteString]] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map [ByteString] -> ByteString
L.fromChunks ([[ByteString]] -> [ByteString])
-> (ByteString -> [[ByteString]]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [[ByteString]]
splitter ([ByteString] -> [[ByteString]])
-> (ByteString -> [ByteString]) -> ByteString -> [[ByteString]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
!patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
breaker :: [ByteString] -> ([ByteString], [ByteString])
breaker = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
True ByteString
pat
splitter :: [ByteString] -> [[ByteString]]
splitter strs :: [ByteString]
strs
| [ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
strs = []
| Bool
otherwise = [ByteString] -> [[ByteString]]
splitter' [ByteString]
strs
splitter' :: [ByteString] -> [[ByteString]]
splitter' strs :: [ByteString]
strs
| [ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
strs = [[]]
| Bool
otherwise =
case [ByteString] -> ([ByteString], [ByteString])
breaker [ByteString]
strs of
(pre :: [ByteString]
pre, mtch :: [ByteString]
mtch) ->
[ByteString]
pre [ByteString] -> [[ByteString]] -> [[ByteString]]
forall a. a -> [a] -> [a]
: case [ByteString]
mtch of
[] -> []
_ -> [ByteString] -> [[ByteString]]
splitter' (Int -> [ByteString] -> [ByteString]
ldrop Int
patLen [ByteString]
mtch)
splitKeepEnd :: S.ByteString
-> L.ByteString
-> [L.ByteString]
splitKeepEnd :: ByteString -> ByteString -> [ByteString]
splitKeepEnd pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = [ByteString] -> ByteString -> [ByteString]
forall a b. a -> b -> a
const (ByteString -> [ByteString]
forall a. a -> [a]
repeat ByteString
L.empty)
splitKeepEnd pat :: ByteString
pat = ([ByteString] -> ByteString) -> [[ByteString]] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map [ByteString] -> ByteString
L.fromChunks ([[ByteString]] -> [ByteString])
-> (ByteString -> [[ByteString]]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [[ByteString]]
splitter ([ByteString] -> [[ByteString]])
-> (ByteString -> [ByteString]) -> ByteString -> [[ByteString]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
breaker :: [ByteString] -> ([ByteString], [ByteString])
breaker = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
False ByteString
pat
splitter :: [ByteString] -> [[ByteString]]
splitter [] = []
splitter strs :: [ByteString]
strs =
case [ByteString] -> ([ByteString], [ByteString])
breaker [ByteString]
strs of
(pre :: [ByteString]
pre, mtch :: [ByteString]
mtch) -> [ByteString]
pre [ByteString] -> [[ByteString]] -> [[ByteString]]
forall a. a -> [a] -> [a]
: [ByteString] -> [[ByteString]]
splitter [ByteString]
mtch
splitKeepFront :: S.ByteString
-> L.ByteString
-> [L.ByteString]
splitKeepFront :: ByteString -> ByteString -> [ByteString]
splitKeepFront pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = [ByteString] -> ByteString -> [ByteString]
forall a b. a -> b -> a
const (ByteString -> [ByteString]
forall a. a -> [a]
repeat ByteString
L.empty)
splitKeepFront pat :: ByteString
pat = ([ByteString] -> ByteString) -> [[ByteString]] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map [ByteString] -> ByteString
L.fromChunks ([[ByteString]] -> [ByteString])
-> (ByteString -> [[ByteString]]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [[ByteString]]
splitter ([ByteString] -> [[ByteString]])
-> (ByteString -> [ByteString]) -> ByteString -> [[ByteString]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks
where
!patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
breaker :: [ByteString] -> ([ByteString], [ByteString])
breaker = Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker Bool
True ByteString
pat
splitter :: [ByteString] -> [[ByteString]]
splitter strs :: [ByteString]
strs = case [ByteString] -> [[ByteString]]
splitter' [ByteString]
strs of
([] : rst :: [[ByteString]]
rst) -> [[ByteString]]
rst
other :: [[ByteString]]
other -> [[ByteString]]
other
splitter' :: [ByteString] -> [[ByteString]]
splitter' [] = []
splitter' strs :: [ByteString]
strs =
case [ByteString] -> ([ByteString], [ByteString])
breaker [ByteString]
strs of
(pre :: [ByteString]
pre, mtch :: [ByteString]
mtch) ->
[ByteString]
pre [ByteString] -> [[ByteString]] -> [[ByteString]]
forall a. a -> [a] -> [a]
: case [ByteString]
mtch of
[] -> []
_ -> case Int -> [ByteString] -> ([ByteString], [ByteString])
lsplit Int
patLen [ByteString]
mtch of
(pt :: [ByteString]
pt, rst :: [ByteString]
rst) ->
if [ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
rst
then [[ByteString]
pt]
else let (h :: [ByteString]
h : t :: [[ByteString]]
t) = [ByteString] -> [[ByteString]]
splitter' [ByteString]
rst
in ([ByteString]
pt [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ [ByteString]
h) [ByteString] -> [[ByteString]] -> [[ByteString]]
forall a. a -> [a] -> [a]
: [[ByteString]]
t
lazySearcher :: Bool -> S.ByteString -> [S.ByteString] -> [Int64]
lazySearcher :: Bool -> ByteString -> [ByteString] -> [Int64]
lazySearcher _ !ByteString
pat
| ByteString -> Bool
S.null ByteString
pat =
let zgo :: t -> [ByteString] -> [t]
zgo _ [] = []
zgo !t
prior (!str :: ByteString
str : rest :: [ByteString]
rest) =
let !l :: Int
l = ByteString -> Int
S.length ByteString
str
!prior' :: t
prior' = t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l
in [t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i | Int
i <- [1 .. Int
l]] [t] -> [t] -> [t]
forall a. [a] -> [a] -> [a]
++ t -> [ByteString] -> [t]
zgo t
prior' [ByteString]
rest
in (0Int64 -> [Int64] -> [Int64]
forall a. a -> [a] -> [a]
:) ([Int64] -> [Int64])
-> ([ByteString] -> [Int64]) -> [ByteString] -> [Int64]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> [ByteString] -> [Int64]
forall t. Num t => t -> [ByteString] -> [t]
zgo 0
| ByteString -> Int
S.length ByteString
pat Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 =
let !w :: Word8
w = ByteString -> Word8
S.head ByteString
pat
ixes :: ByteString -> [Int]
ixes = Word8 -> ByteString -> [Int]
S.elemIndices Word8
w
go :: t -> [ByteString] -> [t]
go _ [] = []
go !t
prior (!str :: ByteString
str : rest :: [ByteString]
rest)
= let !prior' :: t
prior' = t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
str)
in (Int -> t) -> [Int] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map ((t -> t -> t
forall a. Num a => a -> a -> a
+ t
prior) (t -> t) -> (Int -> t) -> Int -> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (ByteString -> [Int]
ixes ByteString
str) [t] -> [t] -> [t]
forall a. [a] -> [a] -> [a]
++ t -> [ByteString] -> [t]
go t
prior' [ByteString]
rest
in Int64 -> [ByteString] -> [Int64]
forall t. Num t => t -> [ByteString] -> [t]
go 0
lazySearcher !Bool
overlap pat :: ByteString
pat = Int64 -> Int -> [ByteString] -> [Int64]
forall t. Num t => t -> Int -> [ByteString] -> [t]
search 0 0
where
!patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
!auto :: UArray Int Int
auto = ByteString -> UArray Int Int
automaton ByteString
pat
!p0 :: Word8
p0 = ByteString -> Int -> Word8
unsafeIndex ByteString
pat 0
!ams :: Int
ams = if Bool
overlap then Int
patLen else 0
search :: t -> Int -> [ByteString] -> [t]
search _ _ [] = []
search !t
prior st :: Int
st (!str :: ByteString
str:rest :: [ByteString]
rest) = Int -> Int -> [t]
match Int
st 0
where
!strLen :: Int
strLen = ByteString -> Int
S.length ByteString
str
{-# INLINE strAt #-}
strAt :: Int -> Int
strAt :: Int -> Int
strAt i :: Int
i = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString
str ByteString -> Int -> Word8
`unsafeIndex` Int
i)
match :: Int -> Int -> [t]
match 0 !Int
idx
| Int
idx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen = t -> Int -> [ByteString] -> [t]
search (t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
strLen) 0 [ByteString]
rest
| ByteString -> Int -> Word8
unsafeIndex ByteString
str Int
idx Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
p0 = Int -> Int -> [t]
match 1 (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1)
| Bool
otherwise = Int -> Int -> [t]
match 0 (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1)
match state :: Int
state idx :: Int
idx
| Int
idx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen = t -> Int -> [ByteString] -> [t]
search (t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
strLen) Int
state [ByteString]
rest
| Bool
otherwise =
let nstate :: Int
nstate = UArray Int Int -> Int -> Int
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> Int -> e
unsafeAt UArray Int Int
auto ((Int
state Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftL` 8) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
strAt Int
idx)
!nxtIdx :: Int
nxtIdx = Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1
in if Int
nstate Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
patLen
then (t
prior t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
nxtIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
patLen)) t -> [t] -> [t]
forall a. a -> [a] -> [a]
:
Int -> Int -> [t]
match Int
ams Int
nxtIdx
else Int -> Int -> [t]
match Int
nstate Int
nxtIdx
lazyBreaker :: Bool -> S.ByteString -> [S.ByteString]
-> ([S.ByteString], [S.ByteString])
lazyBreaker :: Bool -> ByteString -> [ByteString] -> ([ByteString], [ByteString])
lazyBreaker before :: Bool
before pat :: ByteString
pat
| ByteString -> Bool
S.null ByteString
pat = \strs :: [ByteString]
strs -> ([], [ByteString]
strs)
| ByteString -> Int
S.length ByteString
pat Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 =
let !w :: Word8
w = ByteString -> Word8
S.head ByteString
pat
!a :: Int
a = if Bool
before then 0 else 1
ixes :: ByteString -> [Int]
ixes = Word8 -> ByteString -> [Int]
S.elemIndices Word8
w
scan :: [ByteString] -> ([ByteString], [ByteString])
scan [] = ([], [])
scan (!str :: ByteString
str:rest :: [ByteString]
rest) =
let !strLen :: Int
strLen = ByteString -> Int
S.length ByteString
str
in case ByteString -> [Int]
ixes ByteString
str of
[] -> let (fr :: [ByteString]
fr, bk :: [ByteString]
bk) = [ByteString] -> ([ByteString], [ByteString])
scan [ByteString]
rest in (ByteString
str ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
fr, [ByteString]
bk)
(i :: Int
i:_) -> let !j :: Int
j = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
a
in if Int
j Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen
then ([ByteString
str],[ByteString]
rest)
else ([Int -> ByteString -> ByteString
S.take Int
j ByteString
str], Int -> ByteString -> ByteString
S.drop Int
j ByteString
str ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
rest)
in [ByteString] -> ([ByteString], [ByteString])
scan
lazyBreaker !Bool
before pat :: ByteString
pat = [ByteString] -> Int -> [ByteString] -> ([ByteString], [ByteString])
bscan [] 0
where
!patLen :: Int
patLen = ByteString -> Int
S.length ByteString
pat
!auto :: UArray Int Int
auto = ByteString -> UArray Int Int
automaton ByteString
pat
!p0 :: Word8
p0 = ByteString -> Int -> Word8
unsafeIndex ByteString
pat 0
bscan :: [ByteString] -> Int -> [ByteString] -> ([ByteString], [ByteString])
bscan _ _ [] = ([], [])
bscan ![ByteString]
past !Int
sta (!str :: ByteString
str:rest :: [ByteString]
rest) = Int -> Int -> ([ByteString], [ByteString])
match Int
sta 0
where
!strLen :: Int
strLen = ByteString -> Int
S.length ByteString
str
{-# INLINE strAt #-}
strAt :: Int -> Int
strAt :: Int -> Int
strAt i :: Int
i = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString
str ByteString -> Int -> Word8
`unsafeIndex` Int
i)
match :: Int -> Int -> ([ByteString], [ByteString])
match 0 idx :: Int
idx
| Int
idx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen =
let (fr :: [ByteString]
fr, bk :: [ByteString]
bk) = [ByteString] -> Int -> [ByteString] -> ([ByteString], [ByteString])
bscan [] 0 [ByteString]
rest
in ((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
past (ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
fr), [ByteString]
bk)
| ByteString -> Int -> Word8
unsafeIndex ByteString
str Int
idx Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
p0 = Int -> Int -> ([ByteString], [ByteString])
match 1 (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1)
| Bool
otherwise = Int -> Int -> ([ByteString], [ByteString])
match 0 (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1)
match state :: Int
state idx :: Int
idx
| Int
idx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen =
let (kp :: [ByteString]
kp, ![ByteString]
rl) = if Bool
before
then Int -> [ByteString] -> ([ByteString], [ByteString])
keep Int
state (ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
past)
else ([], ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
past)
(fr :: [ByteString]
fr, bk :: [ByteString]
bk) = [ByteString] -> Int -> [ByteString] -> ([ByteString], [ByteString])
bscan [ByteString]
kp Int
state [ByteString]
rest
in ((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
rl [ByteString]
fr, [ByteString]
bk)
| Bool
otherwise =
let !nstate :: Int
nstate = UArray Int Int -> Int -> Int
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> Int -> e
unsafeAt UArray Int Int
auto ((Int
state Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftL` 8) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
strAt Int
idx)
!nxtIdx :: Int
nxtIdx = Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1
in if Int
nstate Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
patLen
then case if Bool
before then Int
nxtIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
patLen else Int
nxtIdx of
0 -> ((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
past [], ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
rest)
stIx :: Int
stIx | Int
stIx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 0 -> Int -> [ByteString] -> [ByteString] -> ([ByteString], [ByteString])
rgo (-Int
stIx) (ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
rest) [ByteString]
past
| Int
stIx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
strLen ->
((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
past [ByteString
str],[ByteString]
rest)
| Bool
otherwise ->
((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
past
[Int -> ByteString -> ByteString
S.take Int
stIx ByteString
str], Int -> ByteString -> ByteString
S.drop Int
stIx ByteString
str ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
rest)
else Int -> Int -> ([ByteString], [ByteString])
match Int
nstate Int
nxtIdx
{-# INLINE rgo #-}
rgo :: Int -> [S.ByteString] -> [S.ByteString]
-> ([S.ByteString], [S.ByteString])
rgo :: Int -> [ByteString] -> [ByteString] -> ([ByteString], [ByteString])
rgo !Int
kp acc :: [ByteString]
acc (!str :: ByteString
str:more :: [ByteString]
more)
| Int
sl Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
kp = ([ByteString] -> [ByteString]
forall a. [a] -> [a]
reverse [ByteString]
more, ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc)
| Int
sl Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
kp = Int -> [ByteString] -> [ByteString] -> ([ByteString], [ByteString])
rgo (Int
kp Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
sl) (ByteString
strByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc) [ByteString]
more
| Bool
otherwise = case Int -> ByteString -> (ByteString, ByteString)
S.splitAt (Int
sl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
kp) ByteString
str of
(fr :: ByteString
fr, bk :: ByteString
bk) ->
((ByteString
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
-> [ByteString]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (([ByteString] -> [ByteString])
-> ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString])
-> (ByteString -> [ByteString] -> [ByteString])
-> ByteString
-> ([ByteString] -> [ByteString])
-> [ByteString]
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)) [ByteString] -> [ByteString]
forall a. a -> a
id [ByteString]
more [ByteString
fr], ByteString
bkByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc)
where
!sl :: Int
sl = ByteString -> Int
S.length ByteString
str
rgo _ _ [] = [Char] -> ([ByteString], [ByteString])
forall a. HasCallStack => [Char] -> a
error "Not enough past!"