on master help sign in
Expose and fix a bug in lazy split.
af2fdf7Bryan O'Sullivan
Data/Text/Lazy.hs+18−2
@@ -716,6 +716,21 @@ drop i t0
716 unstream (S.drop n (stream t)) = drop n t
716 unstream (S.drop n (stream t)) = drop n t
717 #-}
717 #-}
718
718
719+-- | /O(n)/ 'dropWords' @n@ returns the suffix with @n@ 'Word16'
720+-- values dropped, or the empty 'Text' if @n@ is greater than the
721+-- number of 'Word16' values present.
722+dropWords :: Int64 -> Text -> Text
723+dropWords i t0
724+ | i <= 0 = t0
725+ | otherwise = drop' i t0
726+ where drop' 0 ts = ts
727+ drop' _ Empty = Empty
728+ drop' n (Chunk (T.Text arr off len) ts)
729+ | n < len' = chunk (textP arr (off+n') (len-n')) ts
730+ | otherwise = drop' (n - len') ts
731+ where len' = fromIntegral len
732+ n' = fromIntegral n
733+
719-- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text', returns
734-- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text', returns
720-- the longest prefix (possibly empty) of elements that satisfy @p@.
735-- the longest prefix (possibly empty) of elements that satisfy @p@.
721-- This function is subject to array fusion.
736-- This function is subject to array fusion.
@@ -945,8 +960,9 @@ split pat src
945 | otherwise = go 0 (indices pat src) src
960 | otherwise = go 0 (indices pat src) src
946 where
961 where
947 go _ [] cs = [cs]
962 go _ [] cs = [cs]
948− go !s (x:xs) cs = let h :*: t = splitAtWord (x-s) cs
963+ go !i (x:xs) cs = let h :*: t = splitAtWord (x-i) cs
949− in h : go (s+x) xs t
964+ in h : go (x+l) xs (dropWords l t)
965+ l = foldlChunks (\a (T.Text _ _ b) -> a + fromIntegral b) 0 pat
950{-# INLINE [1] split #-}
966{-# INLINE [1] split #-}
951
967
952{-# RULES
968{-# RULES
tests/Properties.hs+9−2
@@ -411,7 +411,11 @@ tl_tails = L.tails `eqP` (map unpackS . TL.tails)
411t_findSplit s = T.split s `eq` splitty
411t_findSplit s = T.split s `eq` splitty
412 where splitty t = case T.find s t of
412 where splitty t = case T.find s t of
413 (x,xs) -> x : L.map (T.drop (T.length s) . fst) xs
413 (x,xs) -> x : L.map (T.drop (T.length s) . fst) xs
414−t_split_split s = T.split s `eq` Slow.split s
414+t_split_split s = unsquare ((T.split s `eq` Slow.split s) .
415+ T.intercalate s)
416+tl_split_split s = unsquare (((TL.split (chunkify s) . chunkify) `eq`
417+ (map chunkify . T.split s)) .
418+ T.intercalate s)
415t_split_i (NotEmpty t) = id `eq` (T.intercalate t . T.split t)
419t_split_i (NotEmpty t) = id `eq` (T.intercalate t . T.split t)
416tl_split_i (NotEmpty t) = id `eq` (TL.intercalate t . TL.split t)
420tl_split_i (NotEmpty t) = id `eq` (TL.intercalate t . TL.split t)
417
421
@@ -434,7 +438,9 @@ t_chunksOf_same_lengths k = all ((==k) . T.length) . ini . T.chunksOf k
434t_chunksOf_length k t = len == T.length t || (k <= 0 && len == 0)
438t_chunksOf_length k t = len == T.length t || (k <= 0 && len == 0)
435 where len = L.sum . L.map T.length $ T.chunksOf k t
439 where len = L.sum . L.map T.length $ T.chunksOf k t
436
440
441+chunkify = TL.fromChunks . (:[])
442+
437−tl_chunksOf k = T.chunksOf k `eq` (map (T.concat . TL.toChunks) . TL.chunksOf (fromIntegral k) . TL.fromChunks . (:[]))
443+tl_chunksOf k = T.chunksOf k `eq` (map (T.concat . TL.toChunks) . TL.chunksOf (fromIntegral k) . chunkify)
438
444
439t_lines = L.lines `eqP` (map unpackS . T.lines)
445t_lines = L.lines `eqP` (map unpackS . T.lines)
440tl_lines = L.lines `eqP` (map unpackS . TL.lines)
446tl_lines = L.lines `eqP` (map unpackS . TL.lines)
@@ -793,6 +799,7 @@ tests = [
793 testGroup "breaking many" [
799 testGroup "breaking many" [
794 testProperty "t_findSplit" t_findSplit,
800 testProperty "t_findSplit" t_findSplit,
795 testProperty "t_split_split" t_split_split,
801 testProperty "t_split_split" t_split_split,
802+ testProperty "tl_split_split" tl_split_split,
796 testProperty "t_split_i" t_split_i,
803 testProperty "t_split_i" t_split_i,
797 testProperty "tl_split_i" tl_split_i,
804 testProperty "tl_split_i" tl_split_i,
798 testProperty "t_splitBy" t_splitBy,
805 testProperty "t_splitBy" t_splitBy,