@@ -34,7 +34,7 @@ module Data.Text.Lazy.Search
35import qualified Data.Text.Array as A
35import qualified Data.Text.Array as A
36import Data.Int (Int64)
36import Data.Int (Int64)
37−import Data.Word (Word64)
37+import Data.Word (Word16, Word64)
38import qualified Data.Text.Internal as T
38import qualified Data.Text.Internal as T
39import Data.Text.Fusion.Internal (PairS(..))
39import Data.Text.Fusion.Internal (PairS(..))
40import Data.Text.Lazy.Internal (Text(..))
40import Data.Text.Lazy.Internal (Text(..))
@@ -49,7 +49,48 @@ import Data.Text.UnsafeShift (shiftL)
49indices :: Text -- ^ Substring to search for (@needle@)
49indices :: Text -- ^ Substring to search for (@needle@)
50 -> Text -- ^ Text to search in (@haystack@)
50 -> Text -- ^ Text to search in (@haystack@)
51 -> [Int64]
51 -> [Int64]
52−indices = undefined
52+indices needle Empty = []
53+indices needle@(Chunk n ns) haystack@(Chunk c cs)
54+ | nlen <= 0 || ldiff < 0 = []
55+ | otherwise = scan 0 0 c cs
57+ scan !g !i x@(T.Text harr hoff l) xs
59+ | i >= m = case xs of
61+ Chunk y ys -> scan g (i-m) y ys
62+ | c == z && candidateMatch 0 = g : scan (g+nlen) (i+nlen) x xs
63+ | otherwise = scan (g+delta) (i+delta) x xs
66+ c = hindex (i + nlast)
67+ delta | nextInPattern = nlen + 1
70+ nextInPattern = mask .&. swizzle (hindex (i+nlen)) == 0
73+ | hindex (i+j) /= nindex j = False
74+ | otherwise = candidateMatch (j+1)
77+ hlen = wordLength haystack
78+ nlen = wordLength needle
81+ z = foldChunks fin 0 needle
82+ where fin _ (T.Text narr noff nlen) = A.unsafeIndex narr (noff+nlen-1)
83+ mask :*: skip = buildTable needle
85+index :: T.Text -> Text -> Int64 -> Word16
86+index (T.Text arr off len) xs i
87+ | j <= len = A.unsafeIndex arr (off+j)
88+ | otherwise = case xs of
89+ Empty -> error "empty"
90+ Chunk c cs -> index c cs (i-fromIntegral len)
91+ where j = fromIntegral i
93+swizzle k = 1 `shiftL` (fromIntegral k .&. 0x3f)
54foldChunks :: (a -> T.Text -> a) -> a -> Text -> a
95foldChunks :: (a -> T.Text -> a) -> a -> Text -> a
55foldChunks _ z Empty = z
96foldChunks _ z Empty = z
@@ -73,7 +114,6 @@ buildTable needle@(Chunk c cs) = outer c cs 0 0 (nlen-2)
73 where c = A.unsafeIndex xarr (xoff+i)
114 where c = A.unsafeIndex xarr (xoff+i)
74 skip' | c == z = nlen - fromIntegral i - 2
115 skip' | c == z = nlen - fromIntegral i - 2
75 | otherwise = skip
116 | otherwise = skip
76− swizzle k = 1 `shiftL` (fromIntegral k .&. 0x3f)
77 nlen = wordLength needle
117 nlen = wordLength needle
78 z = foldChunks fin 0 needle
118 z = foldChunks fin 0 needle
79 where fin _ (T.Text narr noff nlen) = A.unsafeIndex narr (noff+nlen-1)
119 where fin _ (T.Text narr noff nlen) = A.unsafeIndex narr (noff+nlen-1)