{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module HaskellWorks.Data.Json.Simd.Index.Standard
( makeStandardJsonIbBps
, makeStandardJsonIbBpsUnsafe
, enabledMakeStandardJsonIbBps
) where
import Control.Monad
import Data.Word
import HaskellWorks.Data.Json.Simd.Internal.Index.Standard
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BSI
import qualified Data.ByteString.Lazy as LBS
import qualified Foreign.ForeignPtr as F
import qualified Foreign.ForeignPtr.Unsafe as F
import qualified Foreign.Marshal.Unsafe as F
import qualified Foreign.Ptr as F
import qualified Foreign.Storable as F
import qualified HaskellWorks.Data.Json.Simd.Capabilities as C
import qualified HaskellWorks.Data.Json.Simd.Internal.Foreign as F
import qualified System.IO.Unsafe as IO
{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
{-# ANN module ("HLint: ignore Redundant do" :: String) #-}
makeStandardJsonIbBps :: LBS.ByteString -> Either String [(BS.ByteString, BS.ByteString)]
makeStandardJsonIbBps lbs = if enabledMakeStandardJsonIbBps
then Right (makeStandardJsonIbBpsUnsafe lbs)
else Left "makeStandardJsonIbBps function is disabled"
makeStandardJsonIbBpsUnsafe :: LBS.ByteString -> [(BS.ByteString, BS.ByteString)]
makeStandardJsonIbBpsUnsafe lbs = F.unsafeLocalState $ do
wb <- allocWorkBuffers (32 * 1024 * 1204)
ws <- newWorkState 0
fptrState :: F.ForeignPtr F.UInt32 <- F.mallocForeignPtr
fptrRemBits :: F.ForeignPtr F.UInt64 <- F.mallocForeignPtr
fptrRemBitsLen :: F.ForeignPtr F.Size <- F.mallocForeignPtr
let ptrState = F.unsafeForeignPtrToPtr fptrState
let ptrRemBits = F.unsafeForeignPtrToPtr fptrRemBits
let ptrRemBitsLen = F.unsafeForeignPtrToPtr fptrRemBitsLen
F.poke ptrState 0
F.poke ptrRemBits 0
F.poke ptrRemBitsLen 0
IO.unsafeInterleaveIO $ go wb ws fptrState fptrRemBits fptrRemBitsLen (LBS.toChunks lbs)
where go :: ()
=> WorkBuffers
-> WorkState
-> F.ForeignPtr F.UInt32
-> F.ForeignPtr F.UInt64
-> F.ForeignPtr F.Size
-> [BS.ByteString]
-> IO [(BS.ByteString, BS.ByteString)]
go _ _ _ fptrRemBits fptrRemBitsLen [] = do
resBpFptr <- F.mallocForeignPtrBytes 8
let resBpPtr = F.castPtr (F.unsafeForeignPtrToPtr resBpFptr )
let ptrRemBits = F.unsafeForeignPtrToPtr fptrRemBits
let ptrRemBitsLen = F.unsafeForeignPtrToPtr fptrRemBitsLen
remBits <- F.peek ptrRemBits
remBitsLen <- F.peek ptrRemBitsLen
bpByteLen <- F.smWriteBpChunkFinal
remBits
remBitsLen
resBpPtr
return [ ( BS.empty
, BSI.fromForeignPtr resBpFptr 0 (fromIntegral bpByteLen * 8)
)
]
go wb ws fptrState fptrRemBits fptrRemBitsLen (bs:bss) = do
let (!bsFptr, !bsOff, !bsLen) = BSI.toForeignPtr bs
let !idxByteLen = (bsLen + 7) `div` 8
resIbFptr <- F.mallocForeignPtrBytes idxByteLen
resBpFptr <- F.mallocForeignPtrBytes idxByteLen
let resIbPtr = F.castPtr (F.unsafeForeignPtrToPtr resIbFptr )
let resBpPtr = F.castPtr (F.unsafeForeignPtrToPtr resBpFptr )
let bsPtr = F.castPtr (F.unsafeForeignPtrToPtr bsFptr)
let ptrState = F.unsafeForeignPtrToPtr fptrState
let ptrRemBits = F.unsafeForeignPtrToPtr fptrRemBits
let ptrRemBitsLen = F.unsafeForeignPtrToPtr fptrRemBitsLen
s :: Word8 <- fromIntegral <$> F.peek ptrState
void $ F.smProcessChunk
(F.plusPtr bsPtr bsOff)
(fromIntegral bsLen)
ptrState
(workBuffersP wb)
void $ F.smMakeIbOpClChunks
(fromIntegral s)
(workBuffersP wb)
(fromIntegral bsLen)
resIbPtr
(workBuffersO wb)
(workBuffersC wb)
bpByteLen <- F.smWriteBpChunk
(workBuffersO wb)
(workBuffersC wb)
(fromIntegral idxByteLen)
ptrRemBits
ptrRemBitsLen
resBpPtr
let !r =
( BSI.fromForeignPtr resIbFptr 0 idxByteLen
, BSI.fromForeignPtr resBpFptr 0 (fromIntegral bpByteLen * 8)
)
rs <- IO.unsafeInterleaveIO $ go wb ws fptrState fptrRemBits fptrRemBitsLen bss
return (r:rs)
enabledMakeStandardJsonIbBps :: Bool
enabledMakeStandardJsonIbBps = C.avx_2 && C.sse_4_2 && C.bmi_2