@@ -123,6 +123,7 @@ module Data.Text
123123 -- ** Breaking strings
124124 , take
125125 , drop
126+ , dropEnd
126127 , takeWhile
127128 , dropWhile
128129 , dropWhileEnd
@@ -214,7 +215,7 @@ import Data.Text.Internal.Private (span_)
214215import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
215216import qualified Prelude as P
216217import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
217− unsafeHead, unsafeTail)
218+ reverseIter_, unsafeHead, unsafeTail)
218219import Data.Text.Internal.Unsafe.Char (unsafeChr)
219220import qualified Data.Text.Internal.Functions as F
220221import qualified Data.Text.Internal.Encoding.Utf16 as U16
@@ -1038,6 +1039,23 @@ drop n t@(Text arr off len)
10381039 unstream (S.drop n (stream t)) = drop n t
10391040 #-}
10401041
1042+-- | /O(n)/ 'dropEnd' @n@ @t@ returns the prefix remaining after
1043+-- dropping @n@ characters from the end of @t@.
1044+--
1045+-- Examples:
1046+--
1047+-- > dropEnd 3 "foobar" == "foo"
1048+dropEnd :: Int -> Text -> Text
1049+dropEnd n t@(Text arr off len)
1050+ | n <= 0 = t
1051+ | n >= len = empty
1052+ | otherwise = loop (len-1) n
1053+ where loop i !m
1054+ | i <= 0 = empty
1055+ | m <= 1 = Text arr off i
1056+ | otherwise = loop (i+d) (m-1)
1057+ where d = reverseIter_ t i
1058+
10411059-- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text',
10421060-- returns the longest prefix (possibly empty) of elements that
10431061-- satisfy @p@. Subject to fusion.