{-# OPTIONS -fglasgow-exts -fbang-patterns #-} module Codec.Image.PNG.Internal.CRC (update_crc, crc) where import Data.Word import Data.Array.Unboxed import Data.Bits import qualified Data.ByteString.Lazy as LB crc_table :: UArray Word32 Word32 crc_table = listArray (0,255) . map iterate_c $ [0..] where iterate_c = (!! 8) . iterate compute_c compute_c c | c .&. 1 == 1 = 0xedb88320 `xor` (c `shiftR` 1) | otherwise = c `shiftR` 1 update_crc :: Word32 -> LB.ByteString -> Word32 update_crc !c bs | LB.null bs = c | otherwise = let w = LB.head bs newcrc = (crc_table ! ((c `xor` fromIntegral w) .&. 0xff)) `xor` (c `shiftR` 8) in update_crc newcrc (LB.tail bs) crc :: LB.ByteString -> Word32 crc = (`xor` 0xffffffff) . update_crc 0xffffffff --test = crc $ LB.replicate 10000000 128