digest-0.0.0.9: Data/Digest/CRC32.hsc
{-# LANGUAGE ForeignFunctionInterface, FlexibleInstances #-}
------------------------------------------------------------
-- |
-- Copyright : (c) 2008 Eugene Kirpichov
-- License : BSD-style
--
-- Maintainer : ekirpichov@gmail.com
-- Stability : experimental
-- Portability : portable (H98 + FFI)
--
-- CRC32 wrapper
--
------------------------------------------------------------
module Data.Digest.CRC32 (
CRC32, crc32, crc32Update
) where
import Foreign
import Foreign.C.Types
import Foreign.ForeignPtr ()
import GHC.Ptr ()
import qualified Data.ByteString as S
import qualified Data.ByteString.Internal as BI
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Internal as LI
#include "zlib.h"
-- | The class of values for which CRC32 may be computed
class CRC32 a where
-- | Compute CRC32 checksum
crc32 :: a -> Word32
crc32 = crc32Update 0
-- | Given the CRC32 checksum of a string, compute CRC32 of its
-- concatenation with another string (t.i., incrementally update
-- the CRC32 hash value)
crc32Update :: Word32 -> a -> Word32
instance CRC32 S.ByteString where
crc32Update = crc32_s_update
instance CRC32 L.ByteString where
crc32Update = crc32_l_update
instance CRC32 [Word8] where
crc32Update n = (crc32Update n) . L.pack
crc32_s_update :: Word32 -> S.ByteString -> Word32
crc32_s_update n s = crc32_l_update n (LI.Chunk s LI.Empty)
crc32_l_update :: Word32 -> L.ByteString -> Word32
crc32_l_update n = LI.foldlChunks updateCRC n
where updateCRC crc bs = fromIntegral $ crc32_c (fromIntegral crc) buf (fromIntegral len)
where (ptr, offset, len) = BI.toForeignPtr bs
buf = (unsafeForeignPtrToPtr ptr) `plusPtr` offset
foreign import ccall unsafe "zlib.h crc32"
crc32_c :: CInt -> Ptr Word8 -> CInt -> CInt -- crc, buf, len -> crc'