on master help sign in
Add the beginnings of the lazy search code.

--HG-- extra : convert_revision : 10631d828be66a014a8353ca882869f2dde197cb

commitfa33b758c0c83b387919055fac3016efc4471b06 authorBryan O'Sullivan <bos@serpentine.com> dateTue 6 Oct 2009, 22:50 (17 years ago) parentcd3c522
2 files changed+80
Data/Text/Lazy/Search.hs+79 text.cabal+1
Data/Text/Lazy/Search.hsnew file+79
@@ -0,0 +1,79 @@
1+{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
2+
3+-- |
4+-- Module : Data.Text.Lazy.Search
5+-- Copyright : (c) Bryan O'Sullivan 2009
6+--
7+-- License : BSD-style
8+-- Maintainer : bos@serpentine.com, rtharper@aftereternity.co.uk,
9+-- duncan@haskell.org
10+-- Stability : experimental
11+-- Portability : GHC
12+--
13+-- Fast substring search for 'Text', based on work by Boyer, Moore,
14+-- Horspool, Sunday, and Lundh.
15+--
16+-- References:
17+--
18+-- * R. S. Boyer, J. S. Moore: A Fast String Searching Algorithm.
19+-- Communications of the ACM, 20, 10, 762-772 (1977)
20+--
21+-- * R. N. Horspool: Practical Fast Searching in Strings. Software -
22+-- Practice and Experience 10, 501-506 (1980)
23+--
24+-- * D. M. Sunday: A Very Fast Substring Search Algorithm.
25+-- Communications of the ACM, 33, 8, 132-142 (1990)
26+--
27+-- * F. Lundh: The Fast Search Algorithm.
28+-- <http://effbot.org/zone/stringlib.htm> (2006)
29+
30+module Data.Text.Lazy.Search
31+ (
32+ indices
33+ ) where
34+
35+import qualified Data.Text.Array as A
36+import Data.Int (Int64)
37+import Data.Word (Word64)
38+import qualified Data.Text.Internal as T
39+import Data.Text.Fusion.Internal (PairS(..))
40+import Data.Text.Lazy.Internal (Text(..))
41+import Data.Bits ((.|.), (.&.))
42+import Data.Text.UnsafeShift (shiftL)
43+
44+-- | /O(n+m)/ Find the offsets of all non-overlapping indices of
45+-- @needle@ within @haystack@.
46+--
47+-- In (unlikely) bad cases, this algorithm's complexity degrades
48+-- towards /O(n*m)/.
49+indices :: Text -- ^ Substring to search for (@needle@)
50+ -> Text -- ^ Text to search in (@haystack@)
51+ -> [Int64]
52+indices = undefined
53+
54+foldChunks :: (a -> T.Text -> a) -> a -> Text -> a
55+foldChunks _ z Empty = z
56+foldChunks f z (Chunk c cs) = let z' = f z c
57+ in z' `seq` foldChunks f z' cs
58+
59+wordLength = foldChunks sumLength 0
60+ where sumLength i (T.Text _ _ l) = i + fromIntegral l
61+
62+buildTable :: Text -> PairS Word64 Int64
63+buildTable Empty = 0 :*: 0
64+buildTable needle@(Chunk c cs) = outer c cs 0 0 (nlen-2)
65+ where
66+ outer x@(T.Text xarr xoff xlen) xs = go
67+ where
68+ go !i !mask !skip
69+ | i >= xlen = case xs of
70+ Empty -> (mask .|. swizzle z) :*: skip
71+ Chunk y ys -> outer y ys 0 mask skip
72+ | otherwise = go (i+1) (mask .|. swizzle c) skip'
73+ where c = A.unsafeIndex xarr (xoff+i)
74+ skip' | c == z = nlen - fromIntegral i - 2
75+ | otherwise = skip
76+ swizzle k = 1 `shiftL` (fromIntegral k .&. 0x3f)
77+ nlen = wordLength needle
78+ z = foldChunks fin 0 needle
79+ where fin _ (T.Text narr noff nlen) = A.unsafeIndex narr (noff+nlen-1)
text.cabal+1
@@ -38,6 +38,7 @@ library
3838 Data.Text.Lazy.Encoding.Fusion
3939 Data.Text.Lazy.Fusion
4040 Data.Text.Lazy.Internal
41+ Data.Text.Lazy.Search
4142 Data.Text.Search
4243 Data.Text.Unsafe
4344 Data.Text.UnsafeChar