{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeApplications #-}
module Data.ByteString.Base64.Internal.W8.Loop
( innerLoop
, innerLoopNopad
) where
import Data.Bits
import Data.ByteString.Internal
import Data.ByteString.Base64.Internal.Utils
import Foreign.Ptr
import Foreign.Storable
import GHC.Word
innerLoop
:: Ptr Word16
-> Ptr Word8
-> Ptr Word16
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> IO ())
-> IO ()
innerLoop etable sptr dptr end finish = go sptr dptr
where
go !src !dst
| plusPtr src 2 >= end = finish src (castPtr dst)
| otherwise = do
!i <- w32 <$> peek src
!j <- w32 <$> peek (plusPtr src 1)
!k <- w32 <$> peek (plusPtr src 2)
let !w = (shiftL i 16) .|. (shiftL j 8) .|. k
!x <- peekElemOff etable (fromIntegral (shiftR w 12))
!y <- peekElemOff etable (fromIntegral (w .&. 0xfff))
poke dst x
poke (plusPtr dst 2) y
go (plusPtr src 3) (plusPtr dst 4)
innerLoopNopad
:: Ptr Word16
-> Ptr Word8
-> Ptr Word16
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> Int -> IO ByteString)
-> IO ByteString
innerLoopNopad etable sptr dptr end finish = go sptr dptr 0
where
go !src !dst !n
| plusPtr src 2 >= end = finish src (castPtr dst) n
| otherwise = do
!i <- w32 <$> peek src
!j <- w32 <$> peek (plusPtr src 1)
!k <- w32 <$> peek (plusPtr src 2)
let !w = (shiftL i 16) .|. (shiftL j 8) .|. k
!x <- peekElemOff etable (fromIntegral (shiftR w 12))
!y <- peekElemOff etable (fromIntegral (w .&. 0xfff))
poke dst x
poke (plusPtr dst 2) y
go (plusPtr src 3) (plusPtr dst 4) (n + 4)