Skip to content

Commit 750adfe

Browse files
committed
Add spanEnd and breakEnd to Data.Text
1 parent 853471c commit 750adfe

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/Data/Text.hs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ module Data.Text
152152
, breakOn
153153
, breakOnEnd
154154
, break
155+
, breakEnd
155156
, span
157+
, spanEnd
156158
, group
157159
, groupBy
158160
, inits
@@ -233,7 +235,7 @@ import qualified Data.Text.Internal.Fusion as S
233235
import qualified Data.Text.Internal.Fusion.Common as S
234236
import Data.Text.Encoding (decodeUtf8', encodeUtf8)
235237
import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
236-
import Data.Text.Internal.Private (span_)
238+
import Data.Text.Internal.Private (span_, spanEnd_)
237239
import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
238240
import Data.Text.Show (singleton, unpack, unpackCString#)
239241
import qualified Prelude as P
@@ -1367,6 +1369,15 @@ span p t = case span_ p t of
13671369
(# hd,tl #) -> (hd,tl)
13681370
{-# INLINE span #-}
13691371

1372+
-- | /O(n)/ Similar to 'span', but searches from the end of the
1373+
-- string.
1374+
--
1375+
-- >>> T.spanEnd (=='0') "AB000"
1376+
-- ("AB", "000")
1377+
spanEnd :: (Char -> Bool) -> Text -> (Text, Text)
1378+
spanEnd p t = case spanEnd_ p t of (# hd, tl #) -> (hd, tl)
1379+
{-# inline spanEnd #-}
1380+
13701381
-- | /O(n)/ 'break' is like 'span', but the prefix returned is
13711382
-- over elements that fail the predicate @p@.
13721383
--
@@ -1376,6 +1387,15 @@ break :: (Char -> Bool) -> Text -> (Text, Text)
13761387
break p = span (not . p)
13771388
{-# INLINE break #-}
13781389

1390+
-- | /O(n)/ Similar to 'break', but searches from the end of the
1391+
-- string.
1392+
--
1393+
-- >>> T.breakEnd (=='0') "180cm"
1394+
-- ("180","cm")
1395+
breakEnd :: (Char -> Bool) -> Text -> (Text, Text)
1396+
breakEnd p = spanEnd (not . p)
1397+
{-# inline breakEnd #-}
1398+
13791399
-- | /O(n)/ Group characters in a string according to a predicate.
13801400
groupBy :: (Char -> Char -> Bool) -> Text -> [Text]
13811401
groupBy p = loop

src/Data/Text/Internal/Private.hs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ module Data.Text.Internal.Private
1313
(
1414
runText
1515
, span_
16+
, spanEnd_
1617
) where
1718

1819
import Control.Monad.ST (ST, runST)
1920
import Data.Text.Internal (Text(..), text)
20-
import Data.Text.Unsafe (Iter(..), iter)
21+
import Data.Text.Unsafe (Iter(..), iter, reverseIter)
2122
import qualified Data.Text.Array as A
2223

2324
span_ :: (Char -> Bool) -> Text -> (# Text, Text #)
@@ -30,6 +31,16 @@ span_ p t@(Text arr off len) = (# hd,tl #)
3031
where Iter c d = iter t i
3132
{-# INLINE span_ #-}
3233

34+
spanEnd_ :: (Char -> Bool) -> Text -> (# Text, Text #)
35+
spanEnd_ p t@(Text arr off len) = (# hd, tl #)
36+
where hd = text arr off (k+1)
37+
tl = text arr (off+k+1) (len-k-1)
38+
!k = loop (len-1)
39+
loop !i | i >= off && p c = loop (i+d)
40+
| otherwise = i
41+
where (c, d) = reverseIter t i
42+
{-# INLINE spanEnd_ #-}
43+
3344
runText :: (forall s. (A.MArray s -> Int -> ST s Text) -> ST s Text) -> Text
3445
runText act = runST (act $ \ !marr !len -> do
3546
arr <- A.unsafeFreeze marr

0 commit comments

Comments
 (0)