@@ -180,16 +180,15 @@ import qualified Data.List as L
180import Data.Monoid (Monoid(..))
180import Data.Monoid (Monoid(..))
181import Data.Word (Word16)
181import Data.Word (Word16)
182import Data.String (IsString(..))
182import Data.String (IsString(..))
184import qualified Data.Text.Fusion as S
183import qualified Data.Text.Fusion as S
185import qualified Data.Text.Fusion.Common as S
184import qualified Data.Text.Fusion.Common as S
186import Data.Text.Fusion (stream, reverseStream, unstream)
185import Data.Text.Fusion (stream, reverseStream, unstream)
188import Data.Text.Internal (Text(..), empty, text, textP)
186import Data.Text.Internal (Text(..), empty, text, textP)
189import qualified Prelude as P
187import qualified Prelude as P
190import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
188import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
191import Data.Text.UnsafeChar (unsafeChr)
189import Data.Text.UnsafeChar (unsafeChr)
192import qualified Data.Text.Encoding.Utf16 as U16
190import qualified Data.Text.Encoding.Utf16 as U16
191+import Data.Text.Search (indices)
194-- $fusion
193-- $fusion
@@ -899,7 +898,7 @@ tails t | null t = [empty]
899-- copies to create substrings; they just construct new 'Text's that
898-- copies to create substrings; they just construct new 'Text's that
900-- are slices of the original.
899-- are slices of the original.
902−-- | /O(m*n)/ Break a 'Text' into pieces separated by the first
901+-- | /O(m+n)/ Break a 'Text' into pieces separated by the first
903-- 'Text' argument, consuming the delimiter. An empty delimiter is
902-- 'Text' argument, consuming the delimiter. An empty delimiter is
904-- invalid, and will cause an error to be raised.
903-- invalid, and will cause an error to be raised.
@@ -913,21 +912,18 @@ tails t | null t = [empty]
914-- > intercalate s . split s == id
913-- > intercalate s . split s == id
915-- > split (singleton c) == splitWith (==c)
914-- > split (singleton c) == splitWith (==c)
916+-- In (unlikely) bad cases, this function's time complexity
917+-- degenerates towards /O(n*m)/.
916−split :: Text -- ^ Text to split on
918+split :: Text -> Text -> [Text]
917− -> Text -- ^ Input text
919−split pat src0
919+split pat src@(Text arr _off len)
920 | null pat = emptyError "split"
920 | null pat = emptyError "split"
921− | l == 1 = splitWith (== (unsafeHead pat)) src0
921+ | l == 1 = splitWith (== unsafeHead pat) src
922− | otherwise = go src0
922+ | otherwise = chomp 0 (indices pat src)
924− l = length pat
924+ l = length pat
925− go src = search 0 src
925+ chomp s (x:xs) = textP arr s (x-s) : chomp (x+l) xs
926− where
926+ chomp s [] = [textP arr s (len-s)]
928− | null s = [src] -- not found
929− | pat `isPrefixOf` s = take n src : go (drop l s)
930− | otherwise = search (n+1) (unsafeTail s)
931{-# INLINE [1] split #-}
927{-# INLINE [1] split #-}