lhc-0.6.20090126: lib/base/src/System/IO.hs
{-# OPTIONS_LHC -fffi #-}
module System.IO(
BufferMode(..),
Handle,
IOMode(..),
SeekMode(..),
hClose,
hFileSize,
hSeek,
hTell,
hFlush,
hGetBuf,
hGetPosn,
hSetPosn,
hGetContents,
hIsOpen,
hPrint,
hPutBuf,
hPutChar,
hPutStr,
hPutStrLn,
openFile,
withFile,
fixIO,
stdin,stdout,stderr,
try
) where
import Lhc.IO
import Lhc.Handle
import Prelude.IOError
import Foreign.Ptr
import Foreign.Storable
import Foreign.C.Types
import Data.Char(ord)
import Data.Int
data BufferMode = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
deriving(Eq, Ord, Read, Show)
data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
deriving(Eq,Ord,Bounded,Enum,Read,Show)
type HandlePosn = Integer
try :: IO a -> IO (Either IOError a)
try f = catch (do r <- f
return (Right r))
(return . Left)
withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
withFile fp iom action = do
h <- openFile fp iom
r <- action h
hClose h
return r
hFlush :: Handle -> IO ()
hFlush h = withHandle h c_fflush
isEOF :: IO Bool
isEOF = hIsEOF stdin
hIsEOF :: Handle -> IO Bool
hIsEOF h = withHandle h $ \ptr -> do
r <- c_feof ptr
return (r /= 0)
hPutChar h ch = withHandle h $ \ptr -> do
c_fputwc (fromInt (ord ch)) ptr
return ()
hPutStr :: Handle -> String -> IO ()
hPutStr h s = withHandle h $ \ptr -> do
sequence_ [ c_fputwc (fromInt (ord ch)) ptr | ch <- s ]
hPutStrLn :: Handle -> String -> IO ()
hPutStrLn h s = do
hPutStr h s
hPutChar h '\n'
hPrint :: Show a => Handle -> a -> IO ()
hPrint h x = hPutStrLn h (show x)
hGetContents :: Handle -> IO String
hGetContents h = withHandle h $ \ptr -> do
let getContents' = do
ch <- c_fgetwc ptr
case ch of
-1 -> return []
_ -> do
xs <- unsafeInterleaveIO getContents'
return (unsafeChr ch:xs)
unsafeInterleaveIO getContents'
hTell :: Handle -> IO Integer
hTell h = withHandle h $ \ptr -> fmap fromIntegral (c_ftell ptr)
hSeek :: Handle -> SeekMode -> Integer -> IO ()
hSeek h v w = withHandle h $ \ptr -> do
let sm x = case x of
AbsoluteSeek -> c_SEEK_SET
RelativeSeek -> c_SEEK_CUR
SeekFromEnd -> c_SEEK_END
c_fseek ptr (fromIntegral w) (sm v)
return ()
hGetPosn :: Handle -> IO HandlePosn
hGetPosn h = hTell h
hSetPosn :: Handle -> HandlePosn -> IO ()
hSetPosn h hp = hSeek h AbsoluteSeek hp
hPutBuf :: Handle -> Ptr a -> Int -> IO ()
hPutBuf h p c = do
let count = fromIntegral c
rc <- withHandle h $ fwrite p 1 count
if rc /= count then fail "hPutBuf: short write" else return ()
hGetBuf :: Handle -> Ptr a -> Int -> IO Int
hGetBuf h p c = do
let count = fromIntegral c
rc <- withHandle h $ fread p 1 count
return $ fromIntegral rc
hFileSize :: Handle -> IO Integer
hFileSize h = do
cp <- hTell h
hSeek h SeekFromEnd 0
fl <- hTell h
hSeek h AbsoluteSeek cp
return fl
foreign import ccall "stdio.h fwrite_unlocked" fwrite :: Ptr a -> CSize -> CSize -> Ptr Handle -> IO CSize
foreign import ccall "stdio.h fread_unlocked" fread :: Ptr a -> CSize -> CSize -> Ptr Handle -> IO CSize
foreign import primitive "I2I" cwintToChar :: CWint -> Char
foreign import ccall "stdio.h fflush" c_fflush :: Ptr Handle -> IO ()
foreign import ccall "wchar.h lhc_utf8_getc" c_fgetwc :: Ptr Handle -> IO Int
foreign import ccall "wchar.h lhc_utf8_putc" c_fputwc :: Int -> Ptr Handle -> IO Int
foreign import ccall "stdio.h feof" c_feof :: Ptr Handle -> IO CInt
foreign import ccall "stdio.h ftell" c_ftell :: Ptr Handle -> IO Int -- XXX
--foreign import ccall "stdio.h ftell" c_ftell :: Ptr Handle -> IO IntMax -- XXX
foreign import ccall "stdio.h fseek" c_fseek :: Ptr Handle -> Int -> CInt -> IO CInt -- XXX
--foreign import ccall "stdio.h fseek" c_fseek :: Ptr Handle -> IntMax -> CInt -> IO CInt -- XXX
foreign import primitive "const.SEEK_SET" c_SEEK_SET :: CInt
foreign import primitive "const.SEEK_CUR" c_SEEK_CUR :: CInt
foreign import primitive "const.SEEK_END" c_SEEK_END :: CInt