on master help sign in
Implement takeWhileEnd

This commit adds a takeWhileEnd function to both Data.Text and Data.Text.Lazy, and related QuickCheck properties. takeWhileEnd, applied to a predicate `p' and a Text `t', returns the longest suffix (possibly empty) of elements in `t' that satisfy `p'.

commit7534f3cc81461468d74c587cb36cf5a2ed5d2a19 authorPaul Capron <paul@fragara.com> dateThu 8 Oct 2015, 00:18 (11 years ago) parent93e3705
3 files changed+43
Data/Text.hs+22 Data/Text/Lazy.hs+15 tests/Tests/Properties.hs+6
Data/Text.hs+22
@@ -129,6 +129,7 @@ module Data.Text
129129 , drop
130130 , dropEnd
131131 , takeWhile
132+ , takeWhileEnd
132133 , dropWhile
133134 , dropWhileEnd
134135 , dropAround
@@ -1124,6 +1125,27 @@ takeWhile p t@(Text arr off len) = loop 0
11241125 unstream (S.takeWhile p (stream t)) = takeWhile p t
11251126 #-}
11261127
1128+-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1129+-- returns the longest suffix (possibly empty) of elements that
1130+-- satisfy @p@. Subject to fusion.
1131+-- Examples:
1132+--
1133+-- > takeWhileEnd (=='o') "foo" == "oo"
1134+takeWhileEnd :: (Char -> Bool) -> Text -> Text
1135+takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1136+ where loop !i !l | l <= 0 = t
1137+ | p c = loop (i+d) (l+d)
1138+ | otherwise = text arr (off+l) (len-l)
1139+ where (c,d) = reverseIter t i
1140+{-# INLINE [1] takeWhileEnd #-}
1141+
1142+{-# RULES
1143+"TEXT takeWhileEnd -> fused" [~1] forall p t.
1144+ takeWhileEnd p t = S.reverse (S.takeWhile p (S.reverseStream t))
1145+"TEXT takeWhileEnd -> unfused" [1] forall p t.
1146+ S.reverse (S.takeWhile p (S.reverseStream t)) = takeWhileEnd p t
1147+ #-}
1148+
11271149-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
11281150-- 'takeWhile' @p@ @t@. Subject to fusion.
11291151dropWhile :: (Char -> Bool) -> Text -> Text
Data/Text/Lazy.hs+15
@@ -140,6 +140,7 @@ module Data.Text.Lazy
140140 , drop
141141 , dropEnd
142142 , takeWhile
143+ , takeWhileEnd
143144 , dropWhile
144145 , dropWhileEnd
145146 , dropAround
@@ -1119,6 +1120,20 @@ takeWhile p t0 = takeWhile' t0
11191120"LAZY TEXT takeWhile -> unfused" [1] forall p t.
11201121 unstream (S.takeWhile p (stream t)) = takeWhile p t
11211122 #-}
1123+-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1124+-- returns the longest suffix (possibly empty) of elements that
1125+-- satisfy @p@.
1126+-- Examples:
1127+--
1128+-- > takeWhileEnd (=='o') "foo" == "oo"
1129+takeWhileEnd :: (Char -> Bool) -> Text -> Text
1130+takeWhileEnd p = takeChunk empty . L.reverse . toChunks
1131+ where takeChunk acc [] = acc
1132+ takeChunk acc (t:ts) = if T.length t' < T.length t
1133+ then (Chunk t' acc)
1134+ else takeChunk (Chunk t' acc) ts
1135+ where t' = T.takeWhileEnd p t
1136+{-# INLINE takeWhileEnd #-}
11221137
11231138-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
11241139-- 'takeWhile' @p@ @t@. Subject to fusion.
tests/Tests/Properties.hs+6
@@ -516,6 +516,10 @@ sf_takeWhile q p = (L.takeWhile p . L.filter q) `eqP`
516516 (unpackS . S.takeWhile p . S.filter q)
517517t_takeWhile p = L.takeWhile p `eqP` (unpackS . T.takeWhile p)
518518tl_takeWhile p = L.takeWhile p `eqP` (unpackS . TL.takeWhile p)
519+t_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
520+ (unpackS . T.takeWhileEnd p)
521+tl_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
522+ (unpackS . TL.takeWhileEnd p)
519523s_dropWhile p = L.dropWhile p `eqP` (unpackS . S.dropWhile p)
520524s_dropWhile_s p = L.dropWhile p `eqP` (unpackS . S.unstream . S.dropWhile p)
521525sf_dropWhile q p = (L.dropWhile p . L.filter q) `eqP`
@@ -1142,6 +1146,8 @@ tests =
11421146 testProperty "sf_takeWhile" sf_takeWhile,
11431147 testProperty "t_takeWhile" t_takeWhile,
11441148 testProperty "tl_takeWhile" tl_takeWhile,
1149+ testProperty "t_takeWhileEnd" t_takeWhileEnd,
1150+ testProperty "tl_takeWhileEnd" tl_takeWhileEnd,
11451151 testProperty "sf_dropWhile" sf_dropWhile,
11461152 testProperty "s_dropWhile" s_dropWhile,
11471153 testProperty "s_dropWhile_s" s_dropWhile_s,