hgrib-0.1.0.0: src/Data/Grib/Raw/CFile.chs
{- |
Module : Data.Grib.Raw.CFile
Copyright : (c) Mattias Jakobsson 2015
License : GPL-3
Maintainer : mjakob422@gmail.com
Stability : unstable
Portability : portable
Open and close C streams in Haskell.
-}
module Data.Grib.Raw.CFile
( CFilePtr
, withBinaryCFile
, openBinaryCFile
, closeCFile
, IOMode(..)
) where
import Control.Exception (bracket)
import Control.Monad (when)
import Foreign.C
import System.IO (IOMode(..))
#include <stdio.h>
-- |A pointer to a C stream (FILE).
{#pointer *FILE as CFilePtr -> CFile #}
-- This comment is inserted to help Haddock keep all docs.
-- |A constant indicating end of file.
eof :: CInt
eof = {#const EOF #}
-- FILE *fopen(const char *path, const char *mode);
--
-- This function is not macro expanded since we want to use the given
-- filename in the return value marshaller 'throwErrnoPathIfNull'.
--
-- |Like 'System.IO.openBinaryFile', but return a 'CFilePtr' instead of a
-- file 'System.IO.Handle'.
openBinaryCFile :: FilePath -> IOMode -> IO CFilePtr
openBinaryCFile name mode =
withCString name $ \c_name ->
withCString mode_str $ \c_mode ->
throwErrnoPathIfNull "openBinaryCFile" name ({#call fopen #} c_name c_mode)
where mode_str = case mode of
ReadMode -> "rb"
WriteMode -> "wb"
AppendMode -> "ab"
ReadWriteMode -> "r+b"
-- |Close an open 'Foreign.C.CFile'.
{#fun fclose as closeCFile { `CFilePtr' } -> `()' checkStatus*- #}
where checkStatus r = when (r == eof) $ throwErrno "closeCFile"
-- |Like 'System.IO.withBinaryFile', but use a 'CFilePtr' instead of a file
-- 'System.IO.Handle'.
withBinaryCFile :: FilePath -> IOMode -> (CFilePtr -> IO a) -> IO a
withBinaryCFile name mode = bracket (openBinaryCFile name mode) closeCFile