{-# 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 :: Ptr Word16
-> Ptr Word32
-> Ptr Word32
-> Ptr Word32
-> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
-> IO ByteString
innerLoop !Ptr Word16
etable !Ptr Word32
sptr !Ptr Word32
dptr !Ptr Word32
end Ptr Word8 -> Ptr Word8 -> IO ByteString
finish = Ptr Word32 -> Ptr Word32 -> IO ByteString
forall {b}.
(Storable b, Num b) =>
Ptr Word32 -> Ptr b -> IO ByteString
go Ptr Word32
sptr Ptr Word32
dptr
where
go :: Ptr Word32 -> Ptr b -> IO ByteString
go !Ptr Word32
src !Ptr b
dst
| Ptr Word32 -> Int -> Ptr Word32
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word32
src Int
3 Ptr Word32 -> Ptr Word32 -> Bool
forall a. Ord a => a -> a -> Bool
>= Ptr Word32
end =
Ptr Word16
-> Ptr Word8
-> Ptr Word16
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
-> IO ByteString
W16.innerLoop Ptr Word16
etable (Ptr Word32 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word32
src) (Ptr b -> Ptr Word16
forall a b. Ptr a -> Ptr b
castPtr Ptr b
dst) (Ptr Word32 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word32
end) Ptr Word8 -> Ptr Word8 -> IO ByteString
finish
| Bool
otherwise = do
!Word32
w <- Ptr Word32 -> IO Word32
peekWord32BE Ptr Word32
src
let !a :: Word32
a = Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
unsafeShiftR Word32
w Int
20
!b :: Word32
b = Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
unsafeShiftR Word32
w Int
8
!Word32
x <- Word16 -> Word32
w32_16 (Word16 -> Word32) -> IO Word16 -> IO Word32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word16 -> Int -> IO Word16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word16
etable (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
a)
!Word32
y <- Word16 -> Word32
w32_16 (Word16 -> Word32) -> IO Word16 -> IO Word32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word16 -> Int -> IO Word16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word16
etable (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
b)
let !z :: Word32
z = Word32
x Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
unsafeShiftL Word32
y Int
16)
Ptr b -> b -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr b
dst (Word32 -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
z)
Ptr Word32 -> Ptr b -> IO ByteString
go (Ptr Word32 -> Int -> Ptr Word32
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word32
src Int
3) (Ptr b -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr b
dst Int
4)
{-# INLINE go #-}
{-# INLINE innerLoop #-}
decodeLoop
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO (Either Text ByteString)
decodeLoop :: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO (Either Text ByteString)
decodeLoop = Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO (Either Text ByteString)
W16.decodeLoop
{-# INLINE decodeLoop #-}
lenientLoop
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO ByteString
lenientLoop :: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO ByteString
lenientLoop = Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> ForeignPtr Word8
-> IO ByteString
W16.lenientLoop