module Bio.PDB.IO.OpenAnyFile(readFile, writeFile)
where
import Prelude hiding (readFile, writeFile)
import System.Directory (doesFileExist, getPermissions, Permissions(..))
import System.IO.Error (userError, IOError)
import System.IO (withFile, IOMode(..))
import Control.Monad (void)
import qualified Codec.Compression.GZip as GZip
import qualified Data.ByteString.Lazy as BSL
import qualified Control.Exception as Exc
#ifdef HAVE_MMAP
import System.IO.MMap (mmapFileByteString)
#endif
import qualified Data.ByteString.Char8 as BS
readFile fname = do r <- isReadable fname
if r
then
readFile' fname
else
throwNotFound fname
readFile' fname = do content <- simpleRead fname
let r = let codec = getCodec fname content
in BS.concat $ BSL.toChunks $ codec $ BSL.fromChunks [content]
return r
throwNotFound :: String -> IO a
throwNotFound fname = ioError $ userError $ concat ["Cannot read ", show fname, "!"]
getCodec fname c | (".gz" `BS.isSuffixOf` BS.pack fname) ||
(".Z" `BS.isSuffixOf` BS.pack fname) = GZip.decompressWith (gzipParams c)
getCodec fname c = id
gzipParams c = GZip.DecompressParams GZip.defaultWindowBits (fromIntegral (BS.length c * 5))
#if MIN_VERSION_zlib(0,5,4)
Nothing
#endif
#if MIN_VERSION_zlib(0,6,1)
True
#endif
isReadable fname = do exists <- doesFileExist fname
if exists
then do perms <- getPermissions fname
return $! readable perms
else return False
#ifndef HAVE_MMAP
simpleRead = BS.readFile
#else
simpleRead fname = mmapFileByteString fname Nothing `Exc.catch` \e -> do reportError (e :: IOError)
BS.readFile fname
where
reportError e = do putStrLn $ concat [show e, "while trying to mmap('", fname, "')"]
#endif
writeFile fname writer = void $ withFile fname WriteMode writer