module BinArray
( BinArray
, newBinArray
, sizeBinArray
, zeroBinArray
, readWord8
, writeWord8
, readWord32
, writeWord32
, copy
, getBinArrayRawBuffer
) where
import GHC.Base
import GHC.IOBase
import GHC.Word
#ifdef PROFILING
#define IOSCC(label) (\ fn -> IO $ \ s -> {-# SCC label #-} case fn of { IO m -> m s })
#else
#define IOSCC(label) id
#endif
data BinArray = BinArray Int#
(MutableByteArray# RealWorld)
getBinArrayRawBuffer :: BinArray -> MutableByteArray# RealWorld
getBinArrayRawBuffer (BinArray _ arr) = arr
newBinArray :: Int -> IO BinArray
newBinArray (I# sz) = IO $ \ s_in ->
case newByteArray# size s_in of { (# s, arr #) ->
(# s, BinArray sz arr #) }
where (I# size) = ((I# sz + 3) `div` 4) * 4
sizeBinArray :: BinArray -> Int
sizeBinArray (BinArray sz _) = I# sz
zeroBinArray :: BinArray -> IO ()
zeroBinArray arr@(BinArray sz _) =
sequence_ [ writeWord8 arr i 0x0 | i <- take (I# sz) [0..] ]
copy :: BinArray -> BinArray -> IO ()
copy ba1@(BinArray i1 _) ba2@(BinArray i2 _)
| i1 <=# i2
&& ((I# i1) `mod` 4) == 0
&& ((I# i2) `mod` 4) == 0 = IOSCC("copy") $
do let loop i t | t == 0 = return ()
| otherwise =
do v <- unsafeReadWord32 ba1 (I# i)
unsafeWriteWord32 ba2 (I# i) v
loop (i +# 1#) (t 1)
loop 0# ((I# i1) `div` (4 :: Int))
| otherwise = error "BinArray.copy: BinArray's need to be the same size (or bigger) for copy, and power of 4"
readWord8 :: BinArray -> Int -> IO Word8
readWord8 ba@(BinArray i1 _) (I# i)
| i <# i1 = unsafeReadWord8 ba (I# i)
| otherwise = fail "Bad index value in readWord8"
unsafeReadWord8 :: BinArray -> Int -> IO Word8
unsafeReadWord8 (BinArray _ arr) (I# i) =
IO $ \ s_in -> case readWord8Array# arr i s_in of { (# s, v #) ->
(# s, W8# v #) }
writeWord8 :: BinArray -> Int -> Word8 -> IO ()
writeWord8 ba@(BinArray i1 _) (I# i) v
| i <# i1 = unsafeWriteWord8 ba (I# i) v
| otherwise = fail "Bad index value in writeWord8"
unsafeWriteWord8 :: BinArray -> Int -> Word8 -> IO ()
unsafeWriteWord8 (BinArray _ arr) (I# i) (W8# v) =
IO $ \ s_in -> case writeWord8Array# arr i v s_in of { s ->
(# s, () #) }
readWord32 :: BinArray -> Int -> IO Word32
readWord32 ba@(BinArray i1 _) (I# i)
| (i *# 4#) <# i1 = unsafeReadWord32 ba (I# i)
| otherwise = fail "Bad index value in readWord32"
unsafeReadWord32 :: BinArray -> Int -> IO Word32
unsafeReadWord32 (BinArray _ arr) (I# i) =
IO $ \ s_in -> case readWord32Array# arr i s_in of { (# s, v #) ->
(# s, W32# v #) }
writeWord32 :: BinArray -> Int -> Word32 -> IO ()
writeWord32 ba@(BinArray i1 _) (I# i) v
| (i *# 4#) <# i1 = unsafeWriteWord32 ba (I# i) v
| otherwise = fail "Bad index value in writeWord32"
unsafeWriteWord32 :: BinArray -> Int -> Word32 -> IO ()
unsafeWriteWord32 (BinArray _ arr) (I# i) (W32# v) =
IO $ \ s_in -> case writeWord32Array# arr i v s_in of { s ->
(# s, () #) }