module NHC.BinArray ( BinArray(..) , newBinArray , intoBinArray , fromBinArray , putBinArray , getBinArray ) where import qualified NHC.Binary import NHC.Binary import UnboxedArray (UnboxedArray, allocUBA, wUBA, rUBA, getUBAFree, getUBAEnd) ------------------------------------------------- data BinArray a = BA { baSize :: Int , baHandle :: BinHandle , baDefault :: Bin a , baArray :: UnboxedArray } data BinArrayFileHeader a = BAFH { bafhSize :: Int , bafhDefault :: Bin a , bafhArray :: Bin UnboxedArray } deriving Binary ------------------------------------------------- newBinArray :: Binary a => Int -> a -> IO (BinArray a) intoBinArray :: Binary a => BinArray a -> a -> IO Int fromBinArray :: Binary a => BinArray a -> Int -> IO a putBinArray :: Binary a => FilePath -> BinArray a -> IO () getBinArray :: Binary a => FilePath -> IO (BinArray a) ------------------------------------------------- newBinArray s d = let dummyHeader = BAFH { bafhSize=s, bafhDefault=0, bafhArray=0 } in openBin Memory >>= \bh-> put bh dummyHeader >> put bh d >>= \def-> tellBin bh >>= \end-> allocUBA s end >>= \arr-> return (BA {baSize=s, baHandle=bh, baDefault=def, baArray=arr}) intoBinArray ba x = let handle = baHandle ba array = baArray ba in getUBAFree array >>= \free-> if free > 0 then getUBAEnd array >>= \p-> putAt handle p x >> tellBin handle >>= \end-> wUBA array p end else fail "Attempt to write beyond end of BinArray" fromBinArray ba i = getUBAFree (baArray ba) >>= \free-> if i>=(baSize ba - free) then getAt (baHandle ba) (baDefault ba) else rUBA (baArray ba) i >>= \p-> getAt (baHandle ba) p putBinArray fp ba = copyBin (baHandle ba) (File fp WO) >>= \f-> put f (baArray ba) >>= \p-> let header = BAFH { bafhSize=baSize ba , bafhDefault=baDefault ba , bafhArray=p } in putAt f 0 header >> closeBin f getBinArray fp = openBin (File fp RO) >>= \f-> getAt f 0 >>= \header-> getAt f (bafhArray header) >>= \uba-> copyBin f Memory >>= \m-> closeBin f >> return (BA { baSize = bafhSize header , baHandle = m , baDefault = bafhDefault header , baArray = uba })