module Data.Digest.CityHash
(
cityHash64
, cityHash64WithSeed
, cityHash64WithSeeds
, cityHash128
, cityHash128WithSeed
) where
import Foreign
import Foreign.C
import Control.Monad (liftM)
import System.IO.Unsafe as U (unsafePerformIO)
import Data.LargeWord
import qualified Data.ByteString as S
import qualified Data.ByteString.Unsafe as U
cityHash64 :: S.ByteString -> Word64
cityHash64 bs
= unsafeUseBS bs $ \(cstr, clen) -> do
return $ c_CityHash64 cstr clen
cityHash64WithSeed :: S.ByteString -> Word64 -> Word64
cityHash64WithSeed bs seed
= unsafeUseBS bs $ \(cstr, clen) -> do
return $ c_CityHash64WithSeed cstr clen seed
cityHash64WithSeeds :: S.ByteString -> Word64 -> Word64 -> Word64
cityHash64WithSeeds bs seed0 seed1
= unsafeUseBS bs $ \(cstr, clen) -> do
return $ c_CityHash64WithSeeds cstr clen seed0 seed1
cityHash128 :: S.ByteString -> Word128
cityHash128 bs
= unsafeUseBS bs $ \(cstr,clen) ->
allocaBytes w64s $ \lo ->
allocaBytes w64s $ \hi -> do
c_CityHash128 cstr clen lo hi
lo' <- (fromIntegral `liftM` peek lo) :: IO Word128
hi' <- (fromIntegral `liftM` peek hi) :: IO Word128
return $ (hi' `shiftL` 64) .|. lo'
where w64s = sizeOf (undefined :: Word64)
cityHash128WithSeed :: S.ByteString -> Word128 -> Word128
cityHash128WithSeed bs seed
= unsafeUseBS bs $ \(cstr,clen) ->
allocaBytes w64s $ \lo ->
allocaBytes w64s $ \hi -> do
c_CityHash128WithSeed cstr clen (loHalf seed) (hiHalf seed) lo hi
lo' <- (fromIntegral `liftM` peek lo) :: IO Word128
hi' <- (fromIntegral `liftM` peek hi) :: IO Word128
return $ (hi' `shiftL` 64) .|. lo'
where w64s = sizeOf (undefined :: Word64)
unsafeUseBS :: S.ByteString -> ((CString, Int) -> IO a) -> a
unsafeUseBS bs = U.unsafePerformIO . U.unsafeUseAsCStringLen bs
foreign import ccall unsafe "hs_city.h hs_CityHash64"
c_CityHash64 :: CString -> Int -> Word64
foreign import ccall unsafe "hs_city.h hs_CityHash64WithSeed"
c_CityHash64WithSeed :: CString -> Int -> Word64 -> Word64
foreign import ccall unsafe "hs_city.h hs_CityHash64WithSeeds"
c_CityHash64WithSeeds :: CString -> Int -> Word64 -> Word64 -> Word64
foreign import ccall unsafe "hs_city.h hs_CityHash128"
c_CityHash128 :: CString -> Int -> Ptr Word64 -> Ptr Word64 -> IO ()
foreign import ccall unsafe "hs_city.h hs_CityHash128WithSeed"
c_CityHash128WithSeed :: CString -> Int -> Word64 -> Word64
-> Ptr Word64 -> Ptr Word64 -> IO ()