1. Bryan O'Sullivan
  2. text

Commits

Bryan O'Sullivan  committed 165a235

Implement dropEnd

  • Participants
  • Parent commits bc2b9f4
  • Branches default

Comments (0)

Files changed (3)

File Data/Text.hs

View file
  • Ignore whitespace
     -- ** Breaking strings
     , take
     , drop
+    , dropEnd
     , takeWhile
     , dropWhile
     , dropWhileEnd
 import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
 import qualified Prelude as P
 import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
-                         unsafeHead, unsafeTail)
+                         reverseIter_, unsafeHead, unsafeTail)
 import Data.Text.Internal.Unsafe.Char (unsafeChr)
 import qualified Data.Text.Internal.Functions as F
 import qualified Data.Text.Internal.Encoding.Utf16 as U16
     unstream (S.drop n (stream t)) = drop n t
   #-}
 
+-- | /O(n)/ 'dropEnd' @n@ @t@ returns the prefix remaining after
+-- dropping @n@ characters from the end of @t@.
+--
+-- Examples:
+--
+-- > dropEnd 3 "foobar" == "foo"
+dropEnd :: Int -> Text -> Text
+dropEnd n t@(Text arr off len)
+    | n <= 0    = t
+    | n >= len  = empty
+    | otherwise = loop (len-1) n
+  where loop i !m
+          | i <= 0    = empty
+          | m <= 1    = Text arr off i
+          | otherwise = loop (i+d) (m-1)
+          where d = reverseIter_ t i
+
 -- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text',
 -- returns the longest prefix (possibly empty) of elements that
 -- satisfy @p@.  Subject to fusion.

File Data/Text/Unsafe.hs

View file
  • Ignore whitespace
     , iter
     , iter_
     , reverseIter
+    , reverseIter_
     , unsafeHead
     , unsafeTail
     , lengthWord16
         k = j - 1
 {-# INLINE reverseIter #-}
 
+-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
+-- returning the delta to add (i.e. a negative number) to give the
+-- next offset to iterate at.
+reverseIter_ :: Text -> Int -> Int
+reverseIter_ (Text arr off _len) i
+    | m < 0xDC00 || m > 0xDFFF = -1
+    | otherwise                = -2
+  where m = A.unsafeIndex arr (off+i)
+{-# INLINE reverseIter_ #-}
+
 -- | /O(1)/ Return the length of a 'Text' in units of 'Word16'.  This
 -- is useful for sizing a target array appropriately before using
 -- 'unsafeCopyToPtr'.

File tests/Tests/Properties.hs

View file
  • Ignore whitespace
 sf_drop p n       = (L.drop n . L.filter p) `eqP`
                     (unpackS . S.drop n . S.filter p)
 t_drop n          = L.drop n      `eqP` (unpackS . T.drop n)
+t_dropEnd n       = (L.reverse . L.drop n . L.reverse) `eqP`
+                    (unpackS . T.dropEnd n)
 tl_drop n         = L.drop n      `eqP` (unpackS . TL.drop (fromIntegral n))
+--tl_dropEnd n      = (L.reverse . L.drop n . L.reverse) `eqP`
+--                    (unpackS . TL.dropEnd n)
 s_take_drop m     = (L.take n . L.drop n) `eqP` (unpackS . S.take n . S.drop n)
   where n = small m
 s_take_drop_s m   = (L.take n . L.drop n) `eqP`
         testProperty "s_drop_s" s_drop_s,
         testProperty "sf_drop" sf_drop,
         testProperty "t_drop" t_drop,
+        testProperty "t_dropEnd" t_dropEnd,
         testProperty "tl_drop" tl_drop,
+        -- testProperty "tl_dropEnd" tl_dropEnd,
         testProperty "s_take_drop" s_take_drop,
         testProperty "s_take_drop_s" s_take_drop_s,
         testProperty "s_takeWhile" s_takeWhile,