@@ -180,16 +180,15 @@ import qualified Data.List as L
180180import Data.Monoid (Monoid(..))
181181import Data.Word (Word16)
182182import Data.String (IsString(..))
183−
184183import qualified Data.Text.Fusion as S
185184import qualified Data.Text.Fusion.Common as S
186185import Data.Text.Fusion (stream, reverseStream, unstream)
187−
188186import Data.Text.Internal (Text(..), empty, text, textP)
189187import qualified Prelude as P
190188import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
191189import Data.Text.UnsafeChar (unsafeChr)
192190import qualified Data.Text.Encoding.Utf16 as U16
191+import Data.Text.Search (indices)
193192
194193-- $fusion
195194--
@@ -899,7 +898,7 @@ tails t | null t = [empty]
899898-- copies to create substrings; they just construct new 'Text's that
900899-- are slices of the original.
901900
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
903902-- 'Text' argument, consuming the delimiter. An empty delimiter is
904903-- invalid, and will cause an error to be raised.
905904--
@@ -913,21 +912,18 @@ tails t | null t = [empty]
913912--
914913-- > intercalate s . split s == id
915914-- > split (singleton c) == splitWith (==c)
916−split :: Text -- ^ Text to split on
917− -> Text -- ^ Input text
918− -> [Text]
919−split pat src0
915+--
916+-- In (unlikely) bad cases, this function's time complexity
917+-- degenerates towards /O(n*m)/.
918+split :: Text -> Text -> [Text]
919+split pat src@(Text arr _off len)
920920 | null pat = emptyError "split"
921− | l == 1 = splitWith (== (unsafeHead pat)) src0
922− | otherwise = go src0
921+ | l == 1 = splitWith (== unsafeHead pat) src
922+ | otherwise = chomp 0 (indices pat src)
923923 where
924− l = length pat
925− go src = search 0 src
926− where
927− search !n !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)
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)]
931927{-# INLINE [1] split #-}
932928
933929{-# RULES