{-# LANGUAGE GADTs      #-}
{-# LANGUAGE RankNTypes #-}

module HaskellWorks.Data.Json.Simd.Internal.Index.Standard where

import Data.Word
import Foreign

import qualified Foreign                                      as F
import qualified Foreign.ForeignPtr.Unsafe                    as F
import qualified HaskellWorks.Data.Json.Simd.Internal.Foreign as F
import qualified HaskellWorks.Foreign                         as F

{- HLINT ignore "Reduce duplication"  -}
{- HLINT ignore "Redundant do"        -}

data WorkBuffers = WorkBuffers
  { WorkBuffers -> ForeignPtr UInt8
workBuffersF :: !(ForeignPtr F.UInt8)
  , WorkBuffers -> Ptr UInt32
workBuffersP :: !(Ptr F.UInt32)
  , WorkBuffers -> Ptr UInt8
workBuffersO :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersC :: !(Ptr F.UInt8)
  }

data WorkState = WorkState
  { WorkState -> ForeignPtr Word8
workStateFptr       :: !(ForeignPtr Word8)
  , WorkState -> Ptr UInt64
workStateRemBits    :: !(Ptr F.UInt64)
  , WorkState -> Ptr UInt64
workStateRemBitsLen :: !(Ptr F.Size)
  , WorkState -> Ptr UInt32
workStateState      :: !(Ptr F.UInt32)
  }

allocWorkBuffers :: Int -> IO WorkBuffers
allocWorkBuffers :: Int -> IO WorkBuffers
allocWorkBuffers Int
n = do
  (ForeignPtr UInt8
fptr, Ptr Any
ptr) <- forall a b. Storable a => Int -> Int -> IO (ForeignPtr a, Ptr b)
F.mallocForeignPtrBytesWithAlignedCastPtr Int
32 (Int
3 forall a. Num a => a -> a -> a
* Int
n)
  forall (m :: * -> *) a. Monad m => a -> m a
return WorkBuffers
    { workBuffersF :: ForeignPtr UInt8
workBuffersF = ForeignPtr UInt8
fptr
    , workBuffersP :: Ptr UInt32
workBuffersP = Ptr Any
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
0
    , workBuffersO :: Ptr UInt8
workBuffersO = Ptr Any
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
n
    , workBuffersC :: Ptr UInt8
workBuffersC = Ptr Any
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
n forall a. Num a => a -> a -> a
* Int
2)
    }

newWorkState :: Word32 -> IO WorkState
newWorkState :: Word32 -> IO WorkState
newWorkState Word32
initialValue = do
  ForeignPtr Word8
fptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
256
  let ptr :: Ptr Word8
ptr = forall a. ForeignPtr a -> Ptr a
F.unsafeForeignPtrToPtr ForeignPtr Word8
fptr
  let ws :: WorkState
ws = WorkState
        { workStateState :: Ptr UInt32
workStateState      = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
0
        , workStateRemBits :: Ptr UInt64
workStateRemBits    = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
8
        , workStateRemBitsLen :: Ptr UInt64
workStateRemBitsLen = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
16
        , workStateFptr :: ForeignPtr Word8
workStateFptr       = ForeignPtr Word8
fptr
        }
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr UInt32
workStateState      WorkState
ws) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
initialValue)
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr UInt64
workStateRemBits    WorkState
ws) UInt64
0
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr UInt64
workStateRemBitsLen WorkState
ws) UInt64
0
  forall (m :: * -> *) a. Monad m => a -> m a
return WorkState
ws