module Data.Digest.XXHash.FFI (
XXHash(..)
, c_xxh64
, c_xxh32
, XXH32State
, c_xxh32_createState
, c_xxh32_freeState
, c_xxh32_copyState
, c_xxh32_reset
, c_xxh32_update
, c_xxh32_digest
, XXH64State
, c_xxh64_createState
, c_xxh64_freeState
, c_xxh64_copyState
, c_xxh64_reset
, c_xxh64_update
, c_xxh64_digest
) where
import Control.Exception (bracket)
import Data.ByteString.Unsafe (unsafeUseAsCString)
import Data.Word (Word32, Word64)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Foreign.C
import Foreign.Ptr
import System.IO.Unsafe (unsafePerformIO)
foreign import ccall unsafe "XXH64" c_xxh64 ::
Ptr a
-> CSize
-> CULLong
-> CULLong
foreign import ccall unsafe "XXH32" c_xxh32 ::
Ptr a
-> CSize
-> CUInt
-> CUInt
data XXH32State
foreign import ccall unsafe "XXH32_createState" c_xxh32_createState ::
IO (Ptr XXH32State)
foreign import ccall unsafe "XXH32_freeState" c_xxh32_freeState ::
Ptr XXH32State
-> IO ()
foreign import ccall unsafe "XXH32_copyState" c_xxh32_copyState ::
Ptr XXH32State
-> Ptr XXH32State
-> IO ()
foreign import ccall unsafe "XXH32_reset" c_xxh32_reset ::
Ptr XXH32State
-> CUInt
-> IO ()
foreign import ccall unsafe "XXH32_update" c_xxh32_update ::
Ptr XXH32State
-> Ptr a
-> CSize
-> IO ()
foreign import ccall unsafe "XXH32_digest" c_xxh32_digest ::
Ptr XXH32State
-> IO CUInt
data XXH64State
foreign import ccall unsafe "XXH64_createState" c_xxh64_createState ::
IO (Ptr XXH64State)
foreign import ccall unsafe "XXH64_freeState" c_xxh64_freeState ::
Ptr XXH64State
-> IO ()
foreign import ccall unsafe "XXH64_copyState" c_xxh64_copyState ::
Ptr XXH64State
-> Ptr XXH64State
-> IO ()
foreign import ccall unsafe "XXH64_reset" c_xxh64_reset ::
Ptr XXH64State
-> CULLong
-> IO ()
foreign import ccall unsafe "XXH64_update" c_xxh64_update ::
Ptr XXH64State
-> Ptr a
-> CSize
-> IO ()
foreign import ccall unsafe "XXH64_digest" c_xxh64_digest ::
Ptr XXH64State
-> IO CULLong
class XXHash t where
xxh32 :: t
-> Word32
-> Word32
xxh64 :: t
-> Word64
-> Word64
instance XXHash BS.ByteString where
xxh32 bs seed = unsafePerformIO $
unsafeUseAsCString bs $ \ptr ->
return . fromIntegral $ c_xxh32 (castPtr ptr) len (fromIntegral seed)
where
len = fromIntegral $ BS.length bs
xxh64 bs seed = unsafePerformIO $
unsafeUseAsCString bs $ \ptr ->
return . fromIntegral $ c_xxh64 (castPtr ptr) len (fromIntegral seed)
where
len = fromIntegral $ BS.length bs
instance XXHash BL.ByteString where
xxh32 bs seed = fromIntegral . unsafePerformIO $
bracket c_xxh32_createState
c_xxh32_freeState $ \state -> do
c_xxh32_reset state (fromIntegral seed)
mapM_ (update state) (BL.toChunks bs)
c_xxh32_digest state
where
update state bs' =
let len = fromIntegral (BS.length bs') in
unsafeUseAsCString bs' $ \ ptr ->
c_xxh32_update state ptr len
xxh64 bs seed = fromIntegral . unsafePerformIO $
bracket c_xxh64_createState
c_xxh64_freeState $ \state -> do
c_xxh64_reset state (fromIntegral seed)
mapM_ (update state) (BL.toChunks bs)
c_xxh64_digest state
where
update state bs' =
let len = fromIntegral (BS.length bs') in
unsafeUseAsCString bs' $ \ ptr ->
c_xxh64_update state ptr len