module Game.LambdaHack.Common.HSFile
( encodeEOF, strictDecodeEOF
, tryCreateDir, doesFileExist, tryWriteFile, readFile, renameFile
#ifdef EXPOSE_INTERNAL
, encodeData
#endif
) where
import Prelude ()
import Game.LambdaHack.Core.Prelude
import qualified Codec.Compression.Zlib as Z
import qualified Control.Exception as Ex
import Data.Binary
import qualified Data.ByteString.Lazy as LBS
import Data.Version
import System.Directory
import System.FilePath
import System.IO (IOMode (..), hClose, openBinaryFile, readFile,
withBinaryFile, writeFile)
encodeData :: Binary a => FilePath -> a -> IO ()
encodeData path a = do
let tmpPath = path <.> "tmp"
Ex.bracketOnError
(openBinaryFile tmpPath WriteMode)
(\h -> hClose h >> removeFile tmpPath)
(\h -> do
LBS.hPut h . encode $ a
hClose h
renameFile tmpPath path
)
encodeEOF :: Binary b => FilePath -> Version -> b -> IO ()
encodeEOF path v b =
encodeData path (v, (Z.compress $ encode b, "OK" :: String))
strictDecodeEOF :: Binary b => FilePath -> IO (Version, b)
strictDecodeEOF path =
withBinaryFile path ReadMode $ \h -> do
c1 <- LBS.hGetContents h
let (v1, (c2, s)) = decode c1
return $! if s == ("OK" :: String)
then (v1, decode $ Z.decompress c2)
else error $ "Fatal error: corrupted file " ++ path
tryCreateDir :: FilePath -> IO ()
tryCreateDir dir = do
dirExists <- doesDirectoryExist dir
unless dirExists $
Ex.handle (\(_ :: Ex.IOException) -> return ())
(createDirectory dir)
tryWriteFile :: FilePath -> String -> IO ()
tryWriteFile path content = do
fileExists <- doesFileExist path
unless fileExists $
Ex.handle (\(_ :: Ex.IOException) -> return ())
(writeFile path content)