{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE TypeApplications #-}
module Data.ByteString.Base64.Internal.W32.Loop
( innerLoop
, decodeLoop
, lenientLoop
) where
import Data.Bits
import Data.ByteString.Internal
import Data.ByteString.Base64.Internal.Utils
import qualified Data.ByteString.Base64.Internal.W16.Loop as W16
import Data.Text (Text)
import Foreign.ForeignPtr
import Foreign.Ptr
import Foreign.Storable
import GHC.Word
innerLoop
:: Ptr Word16
-> Ptr Word32
-> Ptr Word32
-> Ptr Word32
-> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
-> IO ByteString
innerLoop !etable !sptr !dptr !end finish = go sptr dptr
where
go !src !dst
| plusPtr src 3 >= end =
W16.innerLoop etable (castPtr src) (castPtr dst) (castPtr end) finish
| otherwise = do
!w <- peekWord32BE src
let !a = unsafeShiftR w 20
!b = unsafeShiftR w 8
!x <- w32_16 <$> peekElemOff etable (fromIntegral a)
!y <- w32_16 <$> peekElemOff etable (fromIntegral b)
let !z = x .|. (unsafeShiftL y 16)
poke dst (fromIntegral z)
go (plusPtr src 3) (plusPtr dst 4)
{-# INLINE go #-}
{-# INLINE innerLoop #-}
decodeLoop
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> IO (Either Text ByteString))
-> IO (Either Text ByteString)
decodeLoop = W16.decodeLoop
{-# INLINE decodeLoop #-}
lenientLoop
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO ByteString
lenientLoop = W16.lenientLoop