on master help sign in
Reimplement splitTimes to use the new indices function.

--HG-- extra : convert_revision : 95c73a2c066306285e124ac3abb0e69d1ff0cfa8

commit710ae2832feba28d326d5a9fac2541d30e6f6655 authorBryan O'Sullivan <bos@serpentine.com> dateTue 6 Oct 2009, 17:15 (17 years ago) parent949120b
1 file changed+30−28
Data/Text.hs+30−28
Data/Text.hs+30−28
@@ -144,8 +144,8 @@ module Data.Text
144144 -- * Searching
145145 , elem
146146 , filter
147− , findAll
148147 , find
148+ , findBy
149149 , partition
150150
151151 -- , findSubstring
@@ -916,14 +916,14 @@ tails t | null t = [empty]
916916-- In (unlikely) bad cases, this function's time complexity
917917-- degenerates towards /O(n*m)/.
918918split :: Text -> Text -> [Text]
919−split pat src@(Text arr _off len)
919+split pat src@(Text arr off len)
920920 | null pat = emptyError "split"
921921 | l == 1 = splitWith (== unsafeHead pat) src
922− | otherwise = chomp 0 (indices pat src)
922+ | otherwise = go 0 (indices pat src)
923923 where
924− l = length pat
925− chomp s (x:xs) = textP arr s (x-s) : chomp (x+l) xs
926− chomp s [] = [textP arr s (len-s)]
924+ l = length pat
925+ go !s (x:xs) = textP arr (s+off) (x-s) : go (x+l) xs
926+ go s _ = [textP arr (s+off) (len-s)]
927927{-# INLINE [1] split #-}
928928
929929{-# RULES
@@ -931,7 +931,7 @@ split pat src@(Text arr _off len)
931931 split (singleton c) t = splitWith (==c) t
932932 #-}
933933
934−-- | /O(m*n)/ Break a 'Text' into pieces at most @k@ times,
934+-- | /O(m+n)/ Break a 'Text' into pieces at most @k@ times,
935935-- treating the first 'Text' argument as the delimiter to break on,
936936-- and consuming the delimiter. The last element of the list contains
937937-- the remaining text after the number of times to split has been
@@ -948,25 +948,24 @@ split pat src@(Text arr _off len)
948948-- and
949949--
950950-- > intercalate s . splitTimes k s == id
951+--
952+-- In (unlikely) bad cases, this function's time complexity
953+-- degenerates towards /O(n*m)/.
951954splitTimes :: Int -- ^ Maximum number of times to split
952955 -> Text -- ^ Text to split on
953956 -> Text -- ^ Input text
954957 -> [Text]
955−splitTimes k pat src0
956− | k <= 0 = [src0]
958+splitTimes k pat src@(Text arr off len)
957959 | null pat = emptyError "splitTimes"
958− | otherwise = go k src0
960+ | otherwise = go 0 0 (indices pat src)
959961 where
960− l = length pat
961− go !i src = search 0 src
962− where
963− search !n !s
964− | i == 0 || null s = [src] -- not found or limit reached
965− | pat `isPrefixOf` s = take n src : go (i-1) (drop l s)
966− | otherwise = search (n+1) (unsafeTail s)
962+ go !s !i _ | i >= k = [textP arr (s+off) (len-s)]
963+ go !s _ [] = [textP arr (s+off) (len-s)]
964+ go !s !i (x:xs) = textP arr (s+off) (x-s) : go (x+l) (i+1) xs
965+ l = length pat
967966{-# INLINE splitTimes #-}
968967
969−-- | /O(m*n)/ Break a 'Text' into pieces at most @k@ times, like
968+-- | /O(m+n)/ Break a 'Text' into pieces at most @k@ times, like
970969-- 'splitTimes', but start from the end of the input and work towards
971970-- the start.
972971--
@@ -974,6 +973,9 @@ splitTimes k pat src0
974973--
975974-- > splitTimes 2 "::" "a::b::c::d::e" == ["a","b","c::d::e"]
976975-- > splitTimesEnd 2 "::" "a::b::c::d::e" == ["a::b::c","d","e"]
976+--
977+-- In (unlikely) bad cases, this function's time complexity
978+-- degenerates towards /O(n*m)/.
977979splitTimesEnd :: Int -- ^ Maximum number of times to split
978980 -> Text -- ^ Text to split on
979981 -> Text -- ^ Input text
@@ -1025,12 +1027,12 @@ elem c t = S.elem c (stream t)
10251027-------------------------------------------------------------------------------
10261028-- ** Searching with a predicate
10271029
1028−-- | /O(n)/ The 'find' function takes a predicate and a 'Text',
1029−-- and returns the first element in matching the predicate, or 'Nothing'
1030+-- | /O(n)/ The 'findBy' function takes a predicate and a 'Text', and
1031+-- returns the first element in matching the predicate, or 'Nothing'
10301032-- if there is no such element.
1031−find :: (Char -> Bool) -> Text -> Maybe Char
1032−find p t = S.find p (stream t)
1033−{-# INLINE find #-}
1033+findBy :: (Char -> Bool) -> Text -> Maybe Char
1034+findBy p t = S.findBy p (stream t)
1035+{-# INLINE findBy #-}
10341036
10351037-- | /O(n)/ The 'partition' function takes a predicate and a 'Text',
10361038-- and returns the pair of 'Text's with elements which do and do not
@@ -1058,15 +1060,15 @@ filter p t = unstream (S.filter p (stream t))
10581060--
10591061-- Examples:
10601062--
1061−-- > findAll "::" "a::b::c" ==> ("a", ["::b", "::c"])
1062−-- > findAll "/" "foobar" ==> ("foobar", [])
1063+-- > find "::" "a::b::c" ==> ("a", ["::b", "::c"])
1064+-- > find "/" "foobar" ==> ("foobar", [])
10631065--
10641066-- Laws:
10651067--
10661068-- > concat (prefix : matches) == haystack
10671069-- > where (prefix, matches) = findAll needle haystack
1068−findAll :: Text -> Text -> (Text, [Text])
1069−findAll pat@(Text _ _ plen) src@(Text sarr soff slen)
1070+find :: Text -> Text -> (Text, [Text])
1071+find pat@(Text _ _ plen) src@(Text sarr soff slen)
10701072 | plen <= 0 = emptyError "findAll"
10711073 | otherwise = (h,t)
10721074 where
@@ -1079,7 +1081,7 @@ findAll pat@(Text _ _ plen) src@(Text sarr soff slen)
10791081 | otherwise = search (i+d)
10801082 where d = iter_ src i
10811083 s = Text sarr (soff+i) (slen-i)
1082−{-# INLINE findAll #-}
1084+{-# INLINE find #-}
10831085
10841086-------------------------------------------------------------------------------
10851087-- ** Indexing 'Text's