module Database.Haskey.Utils.IO where import Data.ByteString (ByteString, packCStringLen) import Data.ByteString.Unsafe (unsafeUseAsCString) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import Foreign (allocaBytes, castPtr, plusPtr) import qualified FileIO as IO import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString) readByteString :: IO.FHandle -> Int -> IO ByteString readByteString fd n = allocaBytes n $ \buf -> do go 0 buf packCStringLen (castPtr buf, fromIntegral n) where go c buf | c == n = return () | otherwise = do rc <- IO.read fd buf (fromIntegral (n - c)) case rc of 0 -> ioError (ioeSetErrorString (mkIOError eofErrorType "getByteString" Nothing Nothing) "EOF") n' -> go (c + fromIntegral n') (buf `plusPtr` fromIntegral n') writeByteString :: IO.FHandle -> ByteString -> IO () writeByteString fd bs = unsafeUseAsCString bs $ \buf -> go 0 buf where n = BS.length bs go c buf | c == n = return () | otherwise = do n' <- IO.write fd (castPtr buf) (fromIntegral (n - c)) go (c + fromIntegral n') (buf `plusPtr` fromIntegral n') writeLazyByteString :: IO.FHandle -> BL.ByteString -> IO () writeLazyByteString fh bs = mapM_ (writeByteString fh) (BL.toChunks bs)