Skip to content

Commit

Permalink
Implement pure-Haskell reverse
Browse files Browse the repository at this point in the history
  • Loading branch information
chreekat committed Aug 27, 2023
1 parent fd2d9e1 commit b56356c
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions src/Data/Text/Internal/Reverse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ module Data.Text.Internal.Reverse where

#if !defined(PURE_HASKELL)
import GHC.Exts as Exts
import Control.Monad.ST (ST, runST)
import Control.Monad.ST.Unsafe (unsafeIOToST)
import Foreign.C.Types (CSize(..))
#else
import Data.Text.Internal (Text(..))
import qualified Data.Text.Array as A
import Data.Word (Word8)
#endif
import Control.Monad.ST (ST, runST)
import qualified Data.Text.Array as A

-- | /O(n)/ Reverse the characters of a string.
--
Expand All @@ -27,7 +28,36 @@ reverse ::
#endif
Text -> Text
#if defined(PURE_HASKELL)
reverse t@(Text ba off len) = t
reverse (Text ba off len) = runST $ do
dest <- A.new len
let bytes = A.toList ba off len
_ <- reversePoints bytes (len - 1) dest
result <- A.unsafeFreeze dest
pure $ Text result 0 len

reversePoints :: [Word8] -> Int -> A.MArray s -> ST s ()
reversePoints bytes off dest =
case bytes of
[] -> pure ()
(leadByte:rest) | leadByte < 0x80 -> do
A.unsafeWrite dest (off - 0) leadByte
reversePoints rest (off - 1) dest
(leadByte:b2:rest) | leadByte < 0xe0 -> do
A.unsafeWrite dest (off - 1) leadByte
A.unsafeWrite dest (off - 0) b2
reversePoints rest (off - 2) dest
(leadByte:b2:b3:rest) | leadByte < 0xf0 -> do
A.unsafeWrite dest (off - 2) leadByte
A.unsafeWrite dest (off - 1) b2
A.unsafeWrite dest (off - 0) b3
reversePoints rest (off - 3) dest
(leadByte:b2:b3:b4:rest) -> do
A.unsafeWrite dest (off - 3) leadByte
A.unsafeWrite dest (off - 2) b2
A.unsafeWrite dest (off - 1) b3
A.unsafeWrite dest (off - 0) b4
reversePoints rest (off - 4) dest
_ -> error ("Not valid UTF-8: " <> show bytes)
#else
reverse (Text (A.ByteArray ba) off len) = runST $ do
marr@(A.MutableByteArray mba) <- A.new len
Expand Down

0 comments on commit b56356c

Please sign in to comment.