@@ -144,8 +144,8 @@ module Data.Text
144 -- * Searching
144 -- * Searching
149 , partition
149 , partition
151 -- , findSubstring
151 -- , findSubstring
@@ -916,14 +916,14 @@ tails t | null t = [empty]
916-- In (unlikely) bad cases, this function's time complexity
916-- In (unlikely) bad cases, this function's time complexity
917-- degenerates towards /O(n*m)/.
917-- degenerates towards /O(n*m)/.
918split :: Text -> Text -> [Text]
918split :: Text -> Text -> [Text]
919−split pat src@(Text arr _off len)
919+split pat src@(Text arr off len)
920 | null pat = emptyError "split"
920 | null pat = emptyError "split"
921 | l == 1 = splitWith (== unsafeHead pat) src
921 | l == 1 = splitWith (== unsafeHead pat) src
922− | otherwise = chomp 0 (indices pat src)
922+ | otherwise = go 0 (indices pat src)
924− l = length pat
924+ l = length pat
925− chomp s (x:xs) = textP arr s (x-s) : chomp (x+l) xs
925+ go !s (x:xs) = textP arr (s+off) (x-s) : go (x+l) xs
926− chomp s [] = [textP arr s (len-s)]
926+ go s _ = [textP arr (s+off) (len-s)]
927{-# INLINE [1] split #-}
927{-# INLINE [1] split #-}
@@ -931,7 +931,7 @@ split pat src@(Text arr _off len)
931 split (singleton c) t = splitWith (==c) t
931 split (singleton c) t = splitWith (==c) t
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,
935-- treating the first 'Text' argument as the delimiter to break on,
935-- treating the first 'Text' argument as the delimiter to break on,
936-- and consuming the delimiter. The last element of the list contains
936-- and consuming the delimiter. The last element of the list contains
937-- the remaining text after the number of times to split has been
937-- the remaining text after the number of times to split has been
@@ -948,25 +948,24 @@ split pat src@(Text arr _off len)
950-- > intercalate s . splitTimes k s == id
950-- > intercalate s . splitTimes k s == id
952+-- In (unlikely) bad cases, this function's time complexity
953+-- degenerates towards /O(n*m)/.
951splitTimes :: Int -- ^ Maximum number of times to split
954splitTimes :: Int -- ^ Maximum number of times to split
952 -> Text -- ^ Text to split on
955 -> Text -- ^ Text to split on
953 -> Text -- ^ Input text
956 -> Text -- ^ Input text
954 -> [Text]
957 -> [Text]
955−splitTimes k pat src0
958+splitTimes k pat src@(Text arr off len)
957 | null pat = emptyError "splitTimes"
959 | null pat = emptyError "splitTimes"
958− | otherwise = go k src0
960+ | otherwise = go 0 0 (indices pat src)
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
960− l = length pat
965+ l = length pat
961− go !i src = search 0 src
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)
967{-# INLINE splitTimes #-}
966{-# INLINE splitTimes #-}
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
970-- 'splitTimes', but start from the end of the input and work towards
969-- 'splitTimes', but start from the end of the input and work towards
971-- the start.
970-- the start.
@@ -974,6 +973,9 @@ splitTimes k pat src0
975-- > splitTimes 2 "::" "a::b::c::d::e" == ["a","b","c::d::e"]
974-- > splitTimes 2 "::" "a::b::c::d::e" == ["a","b","c::d::e"]
976-- > splitTimesEnd 2 "::" "a::b::c::d::e" == ["a::b::c","d","e"]
975-- > splitTimesEnd 2 "::" "a::b::c::d::e" == ["a::b::c","d","e"]
977+-- In (unlikely) bad cases, this function's time complexity
978+-- degenerates towards /O(n*m)/.
977splitTimesEnd :: Int -- ^ Maximum number of times to split
979splitTimesEnd :: Int -- ^ Maximum number of times to split
978 -> Text -- ^ Text to split on
980 -> Text -- ^ Text to split on
979 -> Text -- ^ Input text
981 -> Text -- ^ Input text
@@ -1025,12 +1027,12 @@ elem c t = S.elem c (stream t)
1025-------------------------------------------------------------------------------
1027-------------------------------------------------------------------------------
1026-- ** Searching with a predicate
1028-- ** Searching with a predicate
1028−-- | /O(n)/ The 'find' function takes a predicate and a 'Text',
1030+-- | /O(n)/ The 'findBy' function takes a predicate and a 'Text', and
1029−-- and returns the first element in matching the predicate, or 'Nothing'
1031+-- returns the first element in matching the predicate, or 'Nothing'
1030-- if there is no such element.
1032-- if there is no such element.
1031−find :: (Char -> Bool) -> Text -> Maybe Char
1033+findBy :: (Char -> Bool) -> Text -> Maybe Char
1032−find p t = S.find p (stream t)
1034+findBy p t = S.findBy p (stream t)
1033−{-# INLINE find #-}
1035+{-# INLINE findBy #-}
1035-- | /O(n)/ The 'partition' function takes a predicate and a 'Text',
1037-- | /O(n)/ The 'partition' function takes a predicate and a 'Text',
1036-- and returns the pair of 'Text's with elements which do and do not
1038-- 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))
1059-- Examples:
1061-- Examples:
1061−-- > findAll "::" "a::b::c" ==> ("a", ["::b", "::c"])
1063+-- > find "::" "a::b::c" ==> ("a", ["::b", "::c"])
1062−-- > findAll "/" "foobar" ==> ("foobar", [])
1064+-- > find "/" "foobar" ==> ("foobar", [])
1066-- > concat (prefix : matches) == haystack
1068-- > concat (prefix : matches) == haystack
1067-- > where (prefix, matches) = findAll needle haystack
1069-- > where (prefix, matches) = findAll needle haystack
1068−findAll :: Text -> Text -> (Text, [Text])
1070+find :: Text -> Text -> (Text, [Text])
1069−findAll pat@(Text _ _ plen) src@(Text sarr soff slen)
1071+find pat@(Text _ _ plen) src@(Text sarr soff slen)
1070 | plen <= 0 = emptyError "findAll"
1072 | plen <= 0 = emptyError "findAll"
1071 | otherwise = (h,t)
1073 | otherwise = (h,t)
@@ -1079,7 +1081,7 @@ findAll pat@(Text _ _ plen) src@(Text sarr soff slen)
1079 | otherwise = search (i+d)
1081 | otherwise = search (i+d)
1080 where d = iter_ src i
1082 where d = iter_ src i
1081 s = Text sarr (soff+i) (slen-i)
1083 s = Text sarr (soff+i) (slen-i)
1082−{-# INLINE findAll #-}
1084+{-# INLINE find #-}
1084-------------------------------------------------------------------------------
1086-------------------------------------------------------------------------------
1085-- ** Indexing 'Text's
1087-- ** Indexing 'Text's