@@ -177,6 +177,7 @@ import qualified Data.Text.Internal as T
177177import qualified Data.Text.Fusion.Common as S
178178import qualified Data.Text.Unsafe as T
179179import qualified Data.Text.Lazy.Fusion as S
180+import Data.Text.Fusion.Internal (PairS(..))
180181import Data.Text.Lazy.Fusion (stream, unstream)
181182import Data.Text.Lazy.Internal (Text(..), chunk, empty, foldlChunks, foldrChunks)
182183import Data.Text.Internal (textP)
@@ -813,6 +814,18 @@ splitAt = loop
813814 in (Chunk t ts', ts'')
814815 where len = fromIntegral (T.length t)
815816
817+-- | /O(n)/ 'splitAtWord' @n t@ returns a strict pair whose first
818+-- element is a prefix of @t@ whose chunks contain @n@ 'Word16'
819+-- values, and whose second is the remainder of the string.
820+splitAtWord :: Int64 -> Text -> PairS Text Text
821+splitAtWord _ Empty = empty :*: empty
822+splitAtWord x (Chunk c@(T.Text arr off len) cs)
823+ | y >= len = let h :*: t = splitAtWord (x-fromIntegral len) cs
824+ in Chunk c h :*: t
825+ | otherwise = chunk (textP arr off y) empty :*:
826+ chunk (textP arr (off+y) (len-y)) cs
827+ where y = fromIntegral x
828+
816829-- | /O(n+m)/ Find the first instance of @needle@ (which must be
817830-- non-'null') in @haystack@. The first element of the returned tuple
818831-- is the prefix of @haystack@ before @needle@ is matched. The second
@@ -839,15 +852,8 @@ break pat src
839852 | null pat = emptyError "break"
840853 | otherwise = case indices pat src of
841854 [] -> (src, empty)
842− (x:_) -> go x src
843− where
844− go _ Empty = (empty, empty)
845− go x (Chunk c@(T.Text arr off len) cs)
846− | y >= len = let (h,t) = go (x-fromIntegral len) cs
847− in (Chunk c h, t)
848− | otherwise = (chunk (textP arr off y) empty,
849− chunk (textP arr (off+y) (len-y)) cs)
850− where y = fromIntegral x
855+ (x:_) -> let h :*: t = splitAtWord x src
856+ in (h, t)
851857
852858-- | /O(n)/ 'breakBy' is like 'spanBy', but the prefix returned is over
853859-- elements that fail the predicate @p@.