on master help sign in
Simplify code, and ensure that tests are sane.
2e4c79cBryan O'Sullivan
Data/Text/Lazy/Search.hs+4−9
@@ -38,7 +38,7 @@ import Data.Word (Word16, Word64)
38import qualified Data.Text.Internal as T
38import qualified Data.Text.Internal as T
39import qualified Data.Text as T
39import qualified Data.Text as T
40import Data.Text.Fusion.Internal (PairS(..))
40import Data.Text.Fusion.Internal (PairS(..))
41−import Data.Text.Lazy.Internal (Text(..))
41+import Data.Text.Lazy.Internal (Text(..), foldlChunks)
42import Data.Bits ((.|.), (.&.))
42import Data.Bits ((.|.), (.&.))
43import Data.Text.UnsafeShift (shiftL)
43import Data.Text.UnsafeShift (shiftL)
44
44
@@ -79,7 +79,7 @@ indices needle@(Chunk n ns) haystack@(Chunk k ks)
79 nlen = wordLength needle
79 nlen = wordLength needle
80 nlast = nlen - 1
80 nlast = nlen - 1
81 nindex = index n ns
81 nindex = index n ns
82− z = foldChunks fin 0 needle
82+ z = foldlChunks fin 0 needle
83 where fin _ (T.Text farr foff flen) = A.unsafeIndex farr (foff+flen-1)
83 where fin _ (T.Text farr foff flen) = A.unsafeIndex farr (foff+flen-1)
84 mask :*: skip = buildTable needle
84 mask :*: skip = buildTable needle
85 scanOne c i (T.Text oarr ooff olen) os = go 0
85 scanOne c i (T.Text oarr ooff olen) os = go 0
@@ -104,13 +104,8 @@ index (T.Text arr off len) xs i
104swizzle :: Word16 -> Word64
104swizzle :: Word16 -> Word64
105swizzle k = 1 `shiftL` (fromIntegral k .&. 0x3f)
105swizzle k = 1 `shiftL` (fromIntegral k .&. 0x3f)
106
106
107−foldChunks :: (a -> T.Text -> a) -> a -> Text -> a
108−foldChunks _ z Empty = z
109−foldChunks f z (Chunk c cs) = let z' = f z c
110− in z' `seq` foldChunks f z' cs
111−
112wordLength :: Text -> Int64
107wordLength :: Text -> Int64
113−wordLength = foldChunks sumLength 0
108+wordLength = foldlChunks sumLength 0
114 where sumLength i (T.Text _ _ l) = i + fromIntegral l
109 where sumLength i (T.Text _ _ l) = i + fromIntegral l
115
110
116buildTable :: Text -> PairS Word64 Int64
111buildTable :: Text -> PairS Word64 Int64
@@ -129,5 +124,5 @@ buildTable needle@(Chunk k ks) = outer k ks 0 0 0 (nlen-2)
129 | otherwise = skip
124 | otherwise = skip
130 xlast = xlen - 1
125 xlast = xlen - 1
131 nlen = wordLength needle
126 nlen = wordLength needle
132− z = foldChunks fin 0 needle
127+ z = foldlChunks fin 0 needle
133 where fin _ (T.Text farr foff flen) = A.unsafeIndex farr (foff+flen-1)
128 where fin _ (T.Text farr foff flen) = A.unsafeIndex farr (foff+flen-1)
tests/Properties.hs+5−5
@@ -1,5 +1,5 @@
1−{-# LANGUAGE BangPatterns, FlexibleInstances, ScopedTypeVariables,
1+{-# LANGUAGE BangPatterns, FlexibleInstances, OverloadedStrings,
2− TypeSynonymInstances #-}
2+ ScopedTypeVariables, TypeSynonymInstances #-}
3{-# OPTIONS_GHC -fno-enable-rewrite-rules #-}
3{-# OPTIONS_GHC -fno-enable-rewrite-rules #-}
4
4
5import Test.QuickCheck hiding (evaluate)
5import Test.QuickCheck hiding (evaluate)
@@ -487,9 +487,10 @@ sf_zipWith p c s = (L.zipWith c (L.filter p s) . L.filter p) `eqP` (unpackS . S
487t_zipWith c s = L.zipWith c s `eqP` (unpackS . T.zipWith c (packS s))
487t_zipWith c s = L.zipWith c s `eqP` (unpackS . T.zipWith c (packS s))
488tl_zipWith c s = L.zipWith c s `eqP` (unpackS . TL.zipWith c (packS s))
488tl_zipWith c s = L.zipWith c s `eqP` (unpackS . TL.zipWith c (packS s))
489
489
490−slow_indices = unsquare (\s -> (map fromIntegral . Slow.indices (T.pack s)) `eq` (Slow.lazyIndices (TL.pack s) . TL.fromChunks . (:[])))
491t_indices = unsquare (\s -> Slow.indices s `eq` indices s)
490t_indices = unsquare (\s -> Slow.indices s `eq` indices s)
492−tl_indices = unsquare (\s -> Slow.lazyIndices s `eq` S.indices s)
491+tl_indices = unsquare (\s -> lazyIndices s `eq` S.indices s)
492+ where lazyIndices s t = map fromIntegral $ Slow.indices (conc s) (conc t)
493+ conc = T.concat . TL.toChunks
493t_indices_occurs t = unsquare (\ts -> let s = T.intercalate t ts
494t_indices_occurs t = unsquare (\ts -> let s = T.intercalate t ts
494 in Slow.indices t s == indices t s)
495 in Slow.indices t s == indices t s)
495
496
@@ -840,7 +841,6 @@ tests = [
840 testProperty "t_findIndex" t_findIndex,
841 testProperty "t_findIndex" t_findIndex,
841 testProperty "t_count" t_count,
842 testProperty "t_count" t_count,
842 testProperty "tl_count" tl_count,
843 testProperty "tl_count" tl_count,
843− testProperty "slow_indices" slow_indices,
844 testProperty "t_indices" t_indices,
844 testProperty "t_indices" t_indices,
845 testProperty "tl_indices" tl_indices,
845 testProperty "tl_indices" tl_indices,
846 testProperty "t_indices_occurs" t_indices_occurs
846 testProperty "t_indices_occurs" t_indices_occurs
tests/SlowFunctions.hs+5−19
@@ -3,18 +3,15 @@
3module SlowFunctions
3module SlowFunctions
4 (
4 (
5 indices
5 indices
6− , lazyIndices
7 , split
6 , split
8 ) where
7 ) where
9
8
10−import Data.Int (Int64)
11import qualified Data.Text as T
9import qualified Data.Text as T
12−import qualified Data.Text.Lazy as L
13import Data.Text.Internal (Text(..))
10import Data.Text.Internal (Text(..))
14import Data.Text.Unsafe (iter_, unsafeHead, unsafeTail)
11import Data.Text.Unsafe (iter_, unsafeHead, unsafeTail)
15
12
16−indices :: Text -- ^ Substring to search for (@needle@)
13+indices :: T.Text -- ^ Substring to search for (@needle@)
17− -> Text -- ^ Text to search in (@haystack@)
14+ -> T.Text -- ^ Text to search in (@haystack@)
18 -> [Int]
15 -> [Int]
19indices needle@(Text _narr _noff nlen) haystack@(Text harr hoff hlen)
16indices needle@(Text _narr _noff nlen) haystack@(Text harr hoff hlen)
20 | T.null needle = []
17 | T.null needle = []
@@ -26,20 +23,9 @@ indices needle@(Text _narr _noff nlen) haystack@(Text harr hoff hlen)
26 where t = Text harr (hoff+i) (hlen-i)
23 where t = Text harr (hoff+i) (hlen-i)
27 d = iter_ haystack i
24 d = iter_ haystack i
28
25
29−lazyIndices :: L.Text -> L.Text -> [Int64]
30−lazyIndices needle haystack
31− | L.null needle = []
32− | otherwise = scan 0 haystack
33− where
34− scan !i hay
35− | L.null hay = []
36− | needle `L.isPrefixOf` hay = i : scan (i+n) (L.drop n hay)
37− | otherwise = scan (i+1) (L.tail hay)
38− n = L.length needle
39−
40−split :: Text -- ^ Text to split on
26+split :: T.Text -- ^ Text to split on
41− -> Text -- ^ Input text
27+ -> T.Text -- ^ Input text
42− -> [Text]
28+ -> [T.Text]
43split pat src0
29split pat src0
44 | T.null pat = error "split: empty"
30 | T.null pat = error "split: empty"
45 | l == 1 = T.splitBy (== (unsafeHead pat)) src0
31 | l == 1 = T.splitBy (== (unsafeHead pat)) src0