Bryan O'Sullivan avatar Bryan O'Sullivan committed 4ebfd30

Write a dropAfter function.

Comments (0)

Files changed (2)

     , drop
     , takeWhile
     , dropWhile
+    , dropAfter
     , splitAt
     , span
     , break
 
 import Data.Text.Internal (Text(..), empty, text, textP)
 import qualified Prelude as P
-import Data.Text.Unsafe (iter, iter_, unsafeHead, unsafeTail)
+import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
 import Data.Text.UnsafeChar (unsafeChr)
 import qualified Data.Text.Encoding.Utf16 as U16
 
     unstream (S.dropWhile p (stream t)) = dropWhile p t
   #-}
 
+-- | /O(n)/ 'dropAfter' @p@ @t@ returns the prefix remaining after
+-- dropping characters that fail the predicate @p@ from the end of
+-- @t@.  This function is subject to array fusion.
+dropAfter :: (Char -> Bool) -> Text -> Text
+dropAfter p t@(Text arr off len) = loop (len-1) len
+  where loop !i !l | l <= 0    = empty
+                   | p c       = loop (i+d) (l+d)
+                   | otherwise = Text arr off l
+            where (c,d)        = reverseIter t i
+{-# INLINE [1] dropAfter #-}
+
+{-# RULES
+"TEXT dropAfter -> fused" [~1] forall p t.
+    dropAfter p t = S.reverse (S.dropWhile p (S.reverseStream t))
+"TEXT dropAfter -> unfused" [1] forall p t.
+    S.reverse (S.dropWhile p (S.reverseStream t)) = dropAfter p t
+  #-}
+
 -- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
 -- prefix of @t@ of length @n@, and whose second is the remainder of
 -- the string. It is equivalent to @('take' n t, 'drop' n t)@.

tests/Properties.hs

 prop_S_dropWhile p     = L.dropWhile p `eqP` (unpackS . S.dropWhile p)
 prop_T_dropWhile p     = L.dropWhile p `eqP` (unpackS . T.dropWhile p)
 prop_TL_dropWhile p    = L.dropWhile p `eqP` (unpackS . S.dropWhile p)
+prop_S_dropAfter p     = T.dropAfter p `eq` (S.reverse . S.dropWhile p . S.reverseStream)
+prop_T_dropAfter p     = (T.reverse . T.dropWhile p . T.reverse) `eq` T.dropAfter p
 prop_T_splitAt n       = L.splitAt n   `eqP` (unpack2 . T.splitAt n)
 prop_TL_splitAt n      = L.splitAt n   `eqP` (unpack2 . TL.splitAt (fromIntegral n))
 prop_T_span p          = L.span p      `eqP` (unpack2 . T.span p)
   ("prop_S_dropWhile", mytest prop_S_dropWhile),
   ("prop_T_dropWhile", mytest prop_T_dropWhile),
   ("prop_TL_dropWhile", mytest prop_TL_dropWhile),
+  ("prop_S_dropAfter", mytest prop_S_dropAfter),
+  ("prop_T_dropAfter", mytest prop_T_dropAfter),
   ("prop_T_splitAt", mytest prop_T_splitAt),
   ("prop_T_span", mytest prop_T_span),
   ("prop_TL_span", mytest prop_TL_span),
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.