on master help sign in
Implement the new find function for lazy text

--HG-- extra : convert_revision : c2ae70c108c1e078cf1e6abec0bcb8cc5c298f55

commitbe36392d4d294bdce4ae8e34b5d3165203c7eb8d authorBryan O'Sullivan <bos@serpentine.com> dateSat 3 Jul 2010, 19:14 (16 years ago) parent1a839c4
2 files changed+20−24
Data/Text/Lazy.hs+13−18 tests/Properties.hs+7−6
Data/Text/Lazy.hs+13−18
@@ -915,38 +915,33 @@ breakEnd pat src = let (a,b) = break (reverse pat) (reverse src)
915915{-# INLINE breakEnd #-}
916916
917917-- | /O(n+m)/ Find all non-overlapping instances of @needle@ in
918−-- @haystack@. The first element of the returned pair is the prefix
919−-- of @haystack@ prior to any matches of @needle@. The second is a
920−-- list of pairs.
918+-- @haystack@. Each element of the returned list consists of a triple:
921919--
922−-- The first element of each pair in the list is a span from the
923−-- beginning of a match to the beginning of the next match, while the
924−-- second is a span from the beginning of the match to the end of the
925−-- input.
920+-- * The entire string prior to the /k/th match
921+--
922+-- * The /k/th match
923+--
924+-- * The entire string following the /k/th match
926925--
927926-- Examples:
928927--
929928-- > find "::" ""
930−-- > ==> ("", [])
931−-- > find "/" "a/b/c/d"
932−-- > ==> ("a", [("/b","/b/c/d"), ("/c","/c/d"), ("/d","/d")])
929+-- > ==> []
930+-- > find "/" "a/b/c/"
931+-- > ==> [("a", "/", "b/c/"), ("a/b", "/", "c/"), ("a/b/c", "/", "")]
933932--
934933-- This function is strict in its first argument, and lazy in its
935934-- second.
936935--
937936-- In (unlikely) bad cases, this function's time complexity degrades
938937-- towards /O(n*m)/.
939−find :: Text -> Text -> (Text, [(Text, Text)])
938+find :: Text -> Text -> [(Text, Text, Text)]
940939find pat src
941940 | null pat = emptyError "find"
942− | otherwise = case indices pat src of
943− [] -> (src, [])
944− (x:xs) -> let h :*: t = splitAtWord x src
945− in (h, go x xs t)
941+ | otherwise = L.map step (indices pat src)
946942 where
947− go !i (x:xs) cs = let h :*: t = splitAtWord (x-i) cs
948− in (h, cs) : go x xs t
949− go _ _ cs = [(cs,cs)]
943+ step x = (take x src, pat, drop (x + l) pat)
944+ l = length pat
950945
951946-- | /O(n)/ 'breakBy' is like 'spanBy', but the prefix returned is over
952947-- elements that fail the predicate @p@.
tests/Properties.hs+7−6
@@ -408,13 +408,13 @@ t_inits = L.inits `eqP` (map unpackS . T.inits)
408408tl_inits = L.inits `eqP` (map unpackS . TL.inits)
409409t_tails = L.tails `eqP` (map unpackS . T.tails)
410410tl_tails = L.tails `eqP` (map unpackS . TL.tails)
411−t_findConcat (NotEmpty s) t = all (==t) $ map conc (T.find s t)
411+t_findConcat (NotEmpty s) t = all (==t) $ map conc (T.find s t)
412412 where conc (a,b,c) = T.concat [a,b,c]
413413t_findCount s = (L.length . T.find s) `eq` T.count s
414−tl_findSplit s t = (TL.split s `eq` splitty) u
415− where splitty v = case TL.find s v of
416− (x,xs) -> x : L.map (TL.drop (TL.length s) . fst) xs
417− u = TL.concat [t,s,t]
414+tl_findConcat (NotEmpty s) t = all (==t) $ map conc (TL.find s t)
415+ where conc (a,b,c) = TL.concat [a,b,c]
416+tl_findCount s = (L.genericLength . TL.find s) `eq` TL.count s
417+
418418t_split_split s = unsquare ((T.split s `eq` Slow.split s) .
419419 T.intercalate s)
420420tl_split_split s = unsquare (((TL.split (chunkify s) . chunkify) `eq`
@@ -812,7 +812,8 @@ tests = [
812812 testGroup "breaking many" [
813813 testProperty "t_findConcat" t_findConcat,
814814 testProperty "t_findCount" t_findCount,
815− testProperty "tl_findSplit" tl_findSplit,
815+ testProperty "tl_findConcat" tl_findConcat,
816+ testProperty "tl_findCount" tl_findCount,
816817 testProperty "t_split_split" t_split_split,
817818 testProperty "tl_split_split" tl_split_split,
818819 testProperty "t_split_i" t_split_i,