{-# LANGUAGE Safe #-}
module System.IO.HVIO(
HVIO(..),
StreamReader, newStreamReader,
MemoryBuffer, newMemoryBuffer,
mbDefaultCloseFunc, getMemoryBuffer,
PipeReader, PipeWriter, newHVIOPipe
)
where
import safe Control.Concurrent.MVar
( newEmptyMVar, putMVar, readMVar, takeMVar, MVar )
import qualified Control.Exception (catch)
import safe Data.IORef ( IORef, modifyIORef, newIORef, readIORef )
import safe Foreign.C ( castCharToCChar, peekCStringLen )
import safe Foreign.Ptr ( Ptr, castPtr, plusPtr )
import safe Foreign.Storable ( Storable(poke) )
import safe System.IO
( Handle,
hClose,
hFlush,
hGetBuffering,
hIsClosed,
hIsEOF,
hIsOpen,
hIsReadable,
hIsSeekable,
hIsWritable,
hSeek,
hSetBuffering,
hShow,
hTell,
hGetBuf,
hGetChar,
hGetContents,
hGetLine,
hPutBuf,
hPutChar,
hPutStr,
hPutStrLn,
hPrint,
hReady,
SeekMode(..),
BufferMode(NoBuffering) )
import safe System.IO.Error
( IOErrorType,
eofErrorType,
illegalOperationErrorType,
isEOFError,
mkIOError )
class (Show a) => HVIO a where
vClose :: a -> IO ()
vIsOpen :: a -> IO Bool
vIsClosed :: a -> IO Bool
vTestOpen :: a -> IO ()
vIsEOF :: a -> IO Bool
vShow :: a -> IO String
vMkIOError :: a -> IOErrorType -> String -> Maybe FilePath -> IOError
vThrow :: a -> IOErrorType -> IO b
vGetFP :: a -> IO (Maybe FilePath)
vTestEOF :: a -> IO ()
vGetChar :: a -> IO Char
vGetLine :: a -> IO String
vGetContents :: a -> IO String
vReady :: a -> IO Bool
vIsReadable :: a -> IO Bool
vPutChar :: a -> Char -> IO ()
vPutStr :: a -> String -> IO ()
vPutStrLn :: a -> String -> IO ()
vPrint :: Show b => a -> b -> IO ()
vFlush :: a -> IO ()
vIsWritable :: a -> IO Bool
vSeek :: a -> SeekMode -> Integer -> IO ()
vTell :: a -> IO Integer
vRewind :: a -> IO ()
vIsSeekable :: a -> IO Bool
vSetBuffering :: a -> BufferMode -> IO ()
vGetBuffering :: a -> IO BufferMode
vPutBuf :: a -> Ptr b -> Int -> IO ()
vGetBuf :: a -> Ptr b -> Int -> IO Int
vSetBuffering a
_ BufferMode
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vGetBuffering a
_ = BufferMode -> IO BufferMode
forall (m :: * -> *) a. Monad m => a -> m a
return BufferMode
NoBuffering
vShow a
x = String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> String
forall a. Show a => a -> String
show a
x)
vMkIOError a
_ IOErrorType
et String
desc Maybe String
mfp =
IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
mkIOError IOErrorType
et String
desc Maybe Handle
forall a. Maybe a
Nothing Maybe String
mfp
vGetFP a
_ = Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing
vThrow a
h IOErrorType
et = do
Maybe String
fp <- a -> IO (Maybe String)
forall a. HVIO a => a -> IO (Maybe String)
vGetFP a
h
IOError -> IO b
forall a. IOError -> IO a
ioError (a -> IOErrorType -> String -> Maybe String -> IOError
forall a.
HVIO a =>
a -> IOErrorType -> String -> Maybe String -> IOError
vMkIOError a
h IOErrorType
et String
"" Maybe String
fp)
vTestEOF a
h = do Bool
e <- a -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsEOF a
h
if Bool
e then a -> IOErrorType -> IO ()
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
eofErrorType
else () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsOpen a
h = a -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsClosed a
h IO Bool -> (Bool -> IO Bool) -> IO Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> (Bool -> Bool) -> Bool -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not
vIsClosed a
h = a -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsOpen a
h IO Bool -> (Bool -> IO Bool) -> IO Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> (Bool -> Bool) -> Bool -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not
vTestOpen a
h = do Bool
e <- a -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsClosed a
h
if Bool
e then a -> IOErrorType -> IO ()
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
else () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsReadable a
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vGetLine a
h =
let loop :: String -> IO String
loop String
accum =
let func :: IO String
func = do Char
c <- a -> IO Char
forall a. HVIO a => a -> IO Char
vGetChar a
h
case Char
c of
Char
'\n' -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
accum
Char
x -> String
accum String -> IO String -> IO String
`seq` String -> IO String
loop (String
accum String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
x])
handler :: IOError -> IO String
handler IOError
e = if IOError -> Bool
isEOFError IOError
e then String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
accum
else IOError -> IO String
forall a. IOError -> IO a
ioError IOError
e
in IO String -> (IOError -> IO String) -> IO String
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
Control.Exception.catch IO String
func IOError -> IO String
handler
in
do Char
firstchar <- a -> IO Char
forall a. HVIO a => a -> IO Char
vGetChar a
h
case Char
firstchar of
Char
'\n' -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return []
Char
x -> String -> IO String
loop [Char
x]
vGetContents a
h =
let loop :: IO String
loop =
let func :: IO String
func = do Char
c <- a -> IO Char
forall a. HVIO a => a -> IO Char
vGetChar a
h
String
next <- IO String
loop
Char
c Char -> IO String -> IO String
`seq` String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
next)
handler :: IOError -> IO [a]
handler IOError
e = if IOError -> Bool
isEOFError IOError
e then [a] -> IO [a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
else IOError -> IO [a]
forall a. IOError -> IO a
ioError IOError
e
in IO String -> (IOError -> IO String) -> IO String
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
Control.Exception.catch IO String
func IOError -> IO String
forall a. IOError -> IO [a]
handler
in
do IO String
loop
vReady a
h = do a -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF a
h
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
vIsWritable a
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vPutStr a
_ [] = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vPutStr a
h (Char
x:String
xs) = do a -> Char -> IO ()
forall a. HVIO a => a -> Char -> IO ()
vPutChar a
h Char
x
a -> String -> IO ()
forall a. HVIO a => a -> String -> IO ()
vPutStr a
h String
xs
vPutStrLn a
h String
s = a -> String -> IO ()
forall a. HVIO a => a -> String -> IO ()
vPutStr a
h (String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n")
vPrint a
h b
s = a -> String -> IO ()
forall a. HVIO a => a -> String -> IO ()
vPutStrLn a
h (b -> String
forall a. Show a => a -> String
show b
s)
vFlush = a -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen
vIsSeekable a
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vRewind a
h = a -> SeekMode -> Integer -> IO ()
forall a. HVIO a => a -> SeekMode -> Integer -> IO ()
vSeek a
h SeekMode
AbsoluteSeek Integer
0
vPutChar a
h Char
_ = a -> IOErrorType -> IO ()
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vSeek a
h SeekMode
_ Integer
_ = a -> IOErrorType -> IO ()
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vTell a
h = a -> IOErrorType -> IO Integer
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vGetChar a
h = a -> IOErrorType -> IO Char
forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vPutBuf a
h Ptr b
buf Int
len =
do String
str <- CStringLen -> IO String
peekCStringLen (Ptr b -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr b
buf, Int
len)
a -> String -> IO ()
forall a. HVIO a => a -> String -> IO ()
vPutStr a
h String
str
vGetBuf a
h Ptr b
b Int
l =
Ptr b -> Int -> Int -> IO Int
forall t t b. (Eq t, Num t, Num t) => Ptr b -> t -> t -> IO t
worker Ptr b
b Int
l Int
0
where worker :: Ptr b -> t -> t -> IO t
worker Ptr b
_ t
0 t
accum = t -> IO t
forall (m :: * -> *) a. Monad m => a -> m a
return t
accum
worker Ptr b
buf t
len t
accum =
do Bool
iseof <- a -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsEOF a
h
if Bool
iseof
then t -> IO t
forall (m :: * -> *) a. Monad m => a -> m a
return t
accum
else do Char
c <- a -> IO Char
forall a. HVIO a => a -> IO Char
vGetChar a
h
let cc :: CChar
cc = Char -> CChar
castCharToCChar Char
c
Ptr CChar -> CChar -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr b -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr b
buf) CChar
cc
let newptr :: Ptr b
newptr = Ptr b -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr b
buf Int
1
Ptr b -> t -> t -> IO t
worker Ptr b
forall b. Ptr b
newptr (t
len t -> t -> t
forall a. Num a => a -> a -> a
- t
1) (t
accum t -> t -> t
forall a. Num a => a -> a -> a
+ t
1)
instance HVIO Handle where
vClose :: Handle -> IO ()
vClose = Handle -> IO ()
hClose
vIsEOF :: Handle -> IO Bool
vIsEOF = Handle -> IO Bool
hIsEOF
vShow :: Handle -> IO String
vShow = Handle -> IO String
hShow
vMkIOError :: Handle -> IOErrorType -> String -> Maybe String -> IOError
vMkIOError Handle
h IOErrorType
et String
desc Maybe String
mfp =
IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
mkIOError IOErrorType
et String
desc (Handle -> Maybe Handle
forall a. a -> Maybe a
Just Handle
h) Maybe String
mfp
vGetChar :: Handle -> IO Char
vGetChar = Handle -> IO Char
hGetChar
vGetLine :: Handle -> IO String
vGetLine = Handle -> IO String
hGetLine
vGetContents :: Handle -> IO String
vGetContents = Handle -> IO String
hGetContents
vReady :: Handle -> IO Bool
vReady = Handle -> IO Bool
hReady
vIsReadable :: Handle -> IO Bool
vIsReadable = Handle -> IO Bool
hIsReadable
vPutChar :: Handle -> Char -> IO ()
vPutChar = Handle -> Char -> IO ()
hPutChar
vPutStr :: Handle -> String -> IO ()
vPutStr = Handle -> String -> IO ()
hPutStr
vPutStrLn :: Handle -> String -> IO ()
vPutStrLn = Handle -> String -> IO ()
hPutStrLn
vPrint :: Handle -> b -> IO ()
vPrint = Handle -> b -> IO ()
forall b. Show b => Handle -> b -> IO ()
hPrint
vFlush :: Handle -> IO ()
vFlush = Handle -> IO ()
hFlush
vIsWritable :: Handle -> IO Bool
vIsWritable = Handle -> IO Bool
hIsWritable
vSeek :: Handle -> SeekMode -> Integer -> IO ()
vSeek = Handle -> SeekMode -> Integer -> IO ()
hSeek
vTell :: Handle -> IO Integer
vTell = Handle -> IO Integer
hTell
vIsSeekable :: Handle -> IO Bool
vIsSeekable = Handle -> IO Bool
hIsSeekable
vSetBuffering :: Handle -> BufferMode -> IO ()
vSetBuffering = Handle -> BufferMode -> IO ()
hSetBuffering
vGetBuffering :: Handle -> IO BufferMode
vGetBuffering = Handle -> IO BufferMode
hGetBuffering
vGetBuf :: Handle -> Ptr b -> Int -> IO Int
vGetBuf = Handle -> Ptr b -> Int -> IO Int
forall b. Handle -> Ptr b -> Int -> IO Int
hGetBuf
vPutBuf :: Handle -> Ptr b -> Int -> IO ()
vPutBuf = Handle -> Ptr b -> Int -> IO ()
forall b. Handle -> Ptr b -> Int -> IO ()
hPutBuf
vIsOpen :: Handle -> IO Bool
vIsOpen = Handle -> IO Bool
hIsOpen
vIsClosed :: Handle -> IO Bool
vIsClosed = Handle -> IO Bool
hIsClosed
type VIOCloseSupport a = IORef (Bool, a)
vioc_isopen :: VIOCloseSupport a -> IO Bool
vioc_isopen :: VIOCloseSupport a -> IO Bool
vioc_isopen VIOCloseSupport a
x = VIOCloseSupport a -> IO (Bool, a)
forall a. IORef a -> IO a
readIORef VIOCloseSupport a
x IO (Bool, a) -> ((Bool, a) -> IO Bool) -> IO Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> ((Bool, a) -> Bool) -> (Bool, a) -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool, a) -> Bool
forall a b. (a, b) -> a
fst
vioc_get :: VIOCloseSupport a -> IO a
vioc_get :: VIOCloseSupport a -> IO a
vioc_get VIOCloseSupport a
x = VIOCloseSupport a -> IO (Bool, a)
forall a. IORef a -> IO a
readIORef VIOCloseSupport a
x IO (Bool, a) -> ((Bool, a) -> IO a) -> IO a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> IO a) -> ((Bool, a) -> a) -> (Bool, a) -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool, a) -> a
forall a b. (a, b) -> b
snd
vioc_close :: VIOCloseSupport a -> IO ()
vioc_close :: VIOCloseSupport a -> IO ()
vioc_close VIOCloseSupport a
x = VIOCloseSupport a -> ((Bool, a) -> (Bool, a)) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef VIOCloseSupport a
x (\ (Bool
_, a
dat) -> (Bool
False, a
dat))
vioc_set :: VIOCloseSupport a -> a -> IO ()
vioc_set :: VIOCloseSupport a -> a -> IO ()
vioc_set VIOCloseSupport a
x a
newdat = VIOCloseSupport a -> ((Bool, a) -> (Bool, a)) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef VIOCloseSupport a
x (\ (Bool
stat, a
_) -> (Bool
stat, a
newdat))
newtype StreamReader = StreamReader (VIOCloseSupport String)
newStreamReader :: String
-> IO StreamReader
newStreamReader :: String -> IO StreamReader
newStreamReader String
s = do IORef (Bool, String)
ref <- (Bool, String) -> IO (IORef (Bool, String))
forall a. a -> IO (IORef a)
newIORef (Bool
True, String
s)
StreamReader -> IO StreamReader
forall (m :: * -> *) a. Monad m => a -> m a
return (IORef (Bool, String) -> StreamReader
StreamReader IORef (Bool, String)
ref)
srv :: StreamReader -> VIOCloseSupport String
srv :: StreamReader -> IORef (Bool, String)
srv (StreamReader IORef (Bool, String)
x) = IORef (Bool, String)
x
instance Show StreamReader where
show :: StreamReader -> String
show StreamReader
_ = String
"<StreamReader>"
instance HVIO StreamReader where
vClose :: StreamReader -> IO ()
vClose = IORef (Bool, String) -> IO ()
forall a. VIOCloseSupport a -> IO ()
vioc_close (IORef (Bool, String) -> IO ())
-> (StreamReader -> IORef (Bool, String)) -> StreamReader -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamReader -> IORef (Bool, String)
srv
vIsEOF :: StreamReader -> IO Bool
vIsEOF StreamReader
h = do StreamReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen StreamReader
h
String
d <- IORef (Bool, String) -> IO String
forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ case String
d of
[] -> Bool
True
String
_ -> Bool
False
vIsOpen :: StreamReader -> IO Bool
vIsOpen = IORef (Bool, String) -> IO Bool
forall a. VIOCloseSupport a -> IO Bool
vioc_isopen (IORef (Bool, String) -> IO Bool)
-> (StreamReader -> IORef (Bool, String))
-> StreamReader
-> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamReader -> IORef (Bool, String)
srv
vGetChar :: StreamReader -> IO Char
vGetChar StreamReader
h = do StreamReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF StreamReader
h
String
c <- IORef (Bool, String) -> IO String
forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
let retval :: Char
retval = String -> Char
forall a. [a] -> a
head String
c
IORef (Bool, String) -> String -> IO ()
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (StreamReader -> IORef (Bool, String)
srv StreamReader
h) (String -> String
forall a. [a] -> [a]
tail String
c)
Char -> IO Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
retval
vGetContents :: StreamReader -> IO String
vGetContents StreamReader
h = do StreamReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF StreamReader
h
String
c <- IORef (Bool, String) -> IO String
forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
StreamReader -> IO ()
forall a. HVIO a => a -> IO ()
vClose StreamReader
h
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
c
vIsReadable :: StreamReader -> IO Bool
vIsReadable StreamReader
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
data MemoryBuffer = MemoryBuffer (String -> IO ()) (VIOCloseSupport (Int, String))
newMemoryBuffer :: String
-> (String -> IO ())
-> IO MemoryBuffer
newMemoryBuffer :: String -> (String -> IO ()) -> IO MemoryBuffer
newMemoryBuffer String
initval String -> IO ()
closefunc = do IORef (Bool, (Int, String))
ref <- (Bool, (Int, String)) -> IO (IORef (Bool, (Int, String)))
forall a. a -> IO (IORef a)
newIORef (Bool
True, (Int
0, String
initval))
MemoryBuffer -> IO MemoryBuffer
forall (m :: * -> *) a. Monad m => a -> m a
return ((String -> IO ()) -> IORef (Bool, (Int, String)) -> MemoryBuffer
MemoryBuffer String -> IO ()
closefunc IORef (Bool, (Int, String))
ref)
mbDefaultCloseFunc :: String -> IO ()
mbDefaultCloseFunc :: String -> IO ()
mbDefaultCloseFunc String
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vrv :: MemoryBuffer -> VIOCloseSupport (Int, String)
vrv :: MemoryBuffer -> IORef (Bool, (Int, String))
vrv (MemoryBuffer String -> IO ()
_ IORef (Bool, (Int, String))
x) = IORef (Bool, (Int, String))
x
getMemoryBuffer :: MemoryBuffer -> IO String
getMemoryBuffer :: MemoryBuffer -> IO String
getMemoryBuffer MemoryBuffer
h = do (Int, String)
c <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return ((Int, String) -> String
forall a b. (a, b) -> b
snd (Int, String)
c)
instance Show MemoryBuffer where
show :: MemoryBuffer -> String
show MemoryBuffer
_ = String
"<MemoryBuffer>"
instance HVIO MemoryBuffer where
vClose :: MemoryBuffer -> IO ()
vClose MemoryBuffer
x = do Bool
wasopen <- MemoryBuffer -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsOpen MemoryBuffer
x
IORef (Bool, (Int, String)) -> IO ()
forall a. VIOCloseSupport a -> IO ()
vioc_close (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
x)
if Bool
wasopen
then do String
c <- MemoryBuffer -> IO String
getMemoryBuffer MemoryBuffer
x
case MemoryBuffer
x of
MemoryBuffer String -> IO ()
cf IORef (Bool, (Int, String))
_ -> String -> IO ()
cf String
c
else () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsEOF :: MemoryBuffer -> IO Bool
vIsEOF MemoryBuffer
h = do MemoryBuffer -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen MemoryBuffer
h
(Int, String)
c <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return ((String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((Int, String) -> String
forall a b. (a, b) -> b
snd (Int, String)
c)) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ((Int, String) -> Int
forall a b. (a, b) -> a
fst (Int, String)
c))
vIsOpen :: MemoryBuffer -> IO Bool
vIsOpen = IORef (Bool, (Int, String)) -> IO Bool
forall a. VIOCloseSupport a -> IO Bool
vioc_isopen (IORef (Bool, (Int, String)) -> IO Bool)
-> (MemoryBuffer -> IORef (Bool, (Int, String)))
-> MemoryBuffer
-> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MemoryBuffer -> IORef (Bool, (Int, String))
vrv
vGetChar :: MemoryBuffer -> IO Char
vGetChar MemoryBuffer
h = do MemoryBuffer -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF MemoryBuffer
h
(Int, String)
c <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let retval :: Char
retval = ((Int, String) -> String
forall a b. (a, b) -> b
snd (Int, String)
c) String -> Int -> Char
forall a. [a] -> Int -> a
!! ((Int, String) -> Int
forall a b. (a, b) -> a
fst (Int, String)
c)
IORef (Bool, (Int, String)) -> (Int, String) -> IO ()
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (Int -> Int
forall a. Enum a => a -> a
succ ((Int, String) -> Int
forall a b. (a, b) -> a
fst (Int, String)
c), (Int, String) -> String
forall a b. (a, b) -> b
snd (Int, String)
c)
Char -> IO Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
retval
vGetContents :: MemoryBuffer -> IO String
vGetContents MemoryBuffer
h = do MemoryBuffer -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF MemoryBuffer
h
(Int, String)
v <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let retval :: String
retval = Int -> String -> String
forall a. Int -> [a] -> [a]
drop ((Int, String) -> Int
forall a b. (a, b) -> a
fst (Int, String)
v) ((Int, String) -> String
forall a b. (a, b) -> b
snd (Int, String)
v)
IORef (Bool, (Int, String)) -> (Int, String) -> IO ()
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (-Int
1, String
"")
MemoryBuffer -> IO ()
forall a. HVIO a => a -> IO ()
vClose MemoryBuffer
h
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
retval
vIsReadable :: MemoryBuffer -> IO Bool
vIsReadable MemoryBuffer
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
vPutStr :: MemoryBuffer -> String -> IO ()
vPutStr MemoryBuffer
h String
s = do (Int
pos, String
buf) <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let (String
pre, String
post) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
buf
let newbuf :: String
newbuf = String
pre String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Int -> String -> String
forall a. Int -> [a] -> [a]
drop (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s) String
post)
IORef (Bool, (Int, String)) -> (Int, String) -> IO ()
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s), String
newbuf)
vPutChar :: MemoryBuffer -> Char -> IO ()
vPutChar MemoryBuffer
h Char
c = MemoryBuffer -> String -> IO ()
forall a. HVIO a => a -> String -> IO ()
vPutStr MemoryBuffer
h [Char
c]
vIsWritable :: MemoryBuffer -> IO Bool
vIsWritable MemoryBuffer
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
vTell :: MemoryBuffer -> IO Integer
vTell MemoryBuffer
h = do (Int, String)
v <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
Integer -> IO Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> IO Integer) -> (Int -> Integer) -> Int -> IO Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> IO Integer) -> Int -> IO Integer
forall a b. (a -> b) -> a -> b
$ ((Int, String) -> Int
forall a b. (a, b) -> a
fst (Int, String)
v)
vSeek :: MemoryBuffer -> SeekMode -> Integer -> IO ()
vSeek MemoryBuffer
h SeekMode
seekmode Integer
seekposp =
do (Int
pos, String
buf) <- IORef (Bool, (Int, String)) -> IO (Int, String)
forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let seekpos :: Int
seekpos = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
seekposp
let newpos :: Int
newpos = case SeekMode
seekmode of
SeekMode
AbsoluteSeek -> Int
seekpos
SeekMode
RelativeSeek -> Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
seekpos
SeekMode
SeekFromEnd -> (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
seekpos
let buf2 :: String
buf2 = String
buf String -> String -> String
forall a. [a] -> [a] -> [a]
++ if Int
newpos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf)
then Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
newpos Int -> Int -> Int
forall a. Num a => a -> a -> a
- (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf)) Char
'\0'
else []
IORef (Bool, (Int, String)) -> (Int, String) -> IO ()
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (Int
newpos, String
buf2)
vIsSeekable :: MemoryBuffer -> IO Bool
vIsSeekable MemoryBuffer
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
newHVIOPipe :: IO (PipeReader, PipeWriter)
newHVIOPipe :: IO (PipeReader, PipeWriter)
newHVIOPipe = do MVar PipeBit
mv <- IO (MVar PipeBit)
forall a. IO (MVar a)
newEmptyMVar
IORef (Bool, MVar PipeBit)
readerref <- (Bool, MVar PipeBit) -> IO (IORef (Bool, MVar PipeBit))
forall a. a -> IO (IORef a)
newIORef (Bool
True, MVar PipeBit
mv)
let reader :: PipeReader
reader = IORef (Bool, MVar PipeBit) -> PipeReader
PipeReader IORef (Bool, MVar PipeBit)
readerref
IORef (Bool, PipeReader)
writerref <- (Bool, PipeReader) -> IO (IORef (Bool, PipeReader))
forall a. a -> IO (IORef a)
newIORef (Bool
True, PipeReader
reader)
(PipeReader, PipeWriter) -> IO (PipeReader, PipeWriter)
forall (m :: * -> *) a. Monad m => a -> m a
return (PipeReader
reader, IORef (Bool, PipeReader) -> PipeWriter
PipeWriter IORef (Bool, PipeReader)
writerref)
data PipeBit = PipeBit Char
| PipeEOF
deriving (PipeBit -> PipeBit -> Bool
(PipeBit -> PipeBit -> Bool)
-> (PipeBit -> PipeBit -> Bool) -> Eq PipeBit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PipeBit -> PipeBit -> Bool
$c/= :: PipeBit -> PipeBit -> Bool
== :: PipeBit -> PipeBit -> Bool
$c== :: PipeBit -> PipeBit -> Bool
Eq, Int -> PipeBit -> String -> String
[PipeBit] -> String -> String
PipeBit -> String
(Int -> PipeBit -> String -> String)
-> (PipeBit -> String)
-> ([PipeBit] -> String -> String)
-> Show PipeBit
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PipeBit] -> String -> String
$cshowList :: [PipeBit] -> String -> String
show :: PipeBit -> String
$cshow :: PipeBit -> String
showsPrec :: Int -> PipeBit -> String -> String
$cshowsPrec :: Int -> PipeBit -> String -> String
Show)
newtype PipeReader = PipeReader (VIOCloseSupport (MVar PipeBit))
newtype PipeWriter = PipeWriter (VIOCloseSupport PipeReader)
prv :: PipeReader -> VIOCloseSupport (MVar PipeBit)
prv :: PipeReader -> IORef (Bool, MVar PipeBit)
prv (PipeReader IORef (Bool, MVar PipeBit)
x) = IORef (Bool, MVar PipeBit)
x
instance Show PipeReader where
show :: PipeReader -> String
show PipeReader
_ = String
"<PipeReader>"
pr_getc :: PipeReader -> IO PipeBit
pr_getc :: PipeReader -> IO PipeBit
pr_getc PipeReader
h = do MVar PipeBit
mv <- IORef (Bool, MVar PipeBit) -> IO (MVar PipeBit)
forall a. VIOCloseSupport a -> IO a
vioc_get (PipeReader -> IORef (Bool, MVar PipeBit)
prv PipeReader
h)
MVar PipeBit -> IO PipeBit
forall a. MVar a -> IO a
takeMVar MVar PipeBit
mv
instance HVIO PipeReader where
vClose :: PipeReader -> IO ()
vClose = IORef (Bool, MVar PipeBit) -> IO ()
forall a. VIOCloseSupport a -> IO ()
vioc_close (IORef (Bool, MVar PipeBit) -> IO ())
-> (PipeReader -> IORef (Bool, MVar PipeBit))
-> PipeReader
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeReader -> IORef (Bool, MVar PipeBit)
prv
vIsOpen :: PipeReader -> IO Bool
vIsOpen = IORef (Bool, MVar PipeBit) -> IO Bool
forall a. VIOCloseSupport a -> IO Bool
vioc_isopen (IORef (Bool, MVar PipeBit) -> IO Bool)
-> (PipeReader -> IORef (Bool, MVar PipeBit))
-> PipeReader
-> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeReader -> IORef (Bool, MVar PipeBit)
prv
vIsEOF :: PipeReader -> IO Bool
vIsEOF PipeReader
h = do PipeReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen PipeReader
h
MVar PipeBit
mv <- IORef (Bool, MVar PipeBit) -> IO (MVar PipeBit)
forall a. VIOCloseSupport a -> IO a
vioc_get (PipeReader -> IORef (Bool, MVar PipeBit)
prv PipeReader
h)
PipeBit
dat <- MVar PipeBit -> IO PipeBit
forall a. MVar a -> IO a
readMVar MVar PipeBit
mv
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (PipeBit
dat PipeBit -> PipeBit -> Bool
forall a. Eq a => a -> a -> Bool
== PipeBit
PipeEOF)
vGetChar :: PipeReader -> IO Char
vGetChar PipeReader
h = do PipeReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF PipeReader
h
PipeBit
c <- PipeReader -> IO PipeBit
pr_getc PipeReader
h
case PipeBit
c of
PipeBit Char
x -> Char -> IO Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
x
PipeBit
_ -> String -> IO Char
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Internal error in HVIOReader vGetChar"
vGetContents :: PipeReader -> IO String
vGetContents PipeReader
h =
let loop :: IO String
loop = do PipeBit
c <- PipeReader -> IO PipeBit
pr_getc PipeReader
h
case PipeBit
c of
PipeBit
PipeEOF -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return []
PipeBit Char
x -> do String
next <- IO String
loop
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
next)
in do PipeReader -> IO ()
forall a. HVIO a => a -> IO ()
vTestEOF PipeReader
h
IO String
loop
vIsReadable :: PipeReader -> IO Bool
vIsReadable PipeReader
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
pwv :: PipeWriter -> VIOCloseSupport PipeReader
pwv :: PipeWriter -> IORef (Bool, PipeReader)
pwv (PipeWriter IORef (Bool, PipeReader)
x) = IORef (Bool, PipeReader)
x
pwmv :: PipeWriter -> IO (MVar PipeBit)
pwmv :: PipeWriter -> IO (MVar PipeBit)
pwmv (PipeWriter IORef (Bool, PipeReader)
x) = do PipeReader
mv1 <- IORef (Bool, PipeReader) -> IO PipeReader
forall a. VIOCloseSupport a -> IO a
vioc_get IORef (Bool, PipeReader)
x
IORef (Bool, MVar PipeBit) -> IO (MVar PipeBit)
forall a. VIOCloseSupport a -> IO a
vioc_get (PipeReader -> IORef (Bool, MVar PipeBit)
prv PipeReader
mv1)
instance Show PipeWriter where
show :: PipeWriter -> String
show PipeWriter
_ = String
"<PipeWriter>"
instance HVIO PipeWriter where
vClose :: PipeWriter -> IO ()
vClose PipeWriter
h = do Bool
o <- PipeWriter -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsOpen PipeWriter
h
if Bool
o then do
MVar PipeBit
mv <- PipeWriter -> IO (MVar PipeBit)
pwmv PipeWriter
h
MVar PipeBit -> PipeBit -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar PipeBit
mv PipeBit
PipeEOF
IORef (Bool, PipeReader) -> IO ()
forall a. VIOCloseSupport a -> IO ()
vioc_close (PipeWriter -> IORef (Bool, PipeReader)
pwv PipeWriter
h)
else () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsOpen :: PipeWriter -> IO Bool
vIsOpen = IORef (Bool, PipeReader) -> IO Bool
forall a. VIOCloseSupport a -> IO Bool
vioc_isopen (IORef (Bool, PipeReader) -> IO Bool)
-> (PipeWriter -> IORef (Bool, PipeReader))
-> PipeWriter
-> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeWriter -> IORef (Bool, PipeReader)
pwv
vIsEOF :: PipeWriter -> IO Bool
vIsEOF PipeWriter
h = do PipeWriter -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen PipeWriter
h
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vPutChar :: PipeWriter -> Char -> IO ()
vPutChar PipeWriter
h Char
c = do PipeWriter -> IO ()
forall a. HVIO a => a -> IO ()
vTestOpen PipeWriter
h
PipeReader
child <- IORef (Bool, PipeReader) -> IO PipeReader
forall a. VIOCloseSupport a -> IO a
vioc_get (PipeWriter -> IORef (Bool, PipeReader)
pwv PipeWriter
h)
Bool
copen <- PipeReader -> IO Bool
forall a. HVIO a => a -> IO Bool
vIsOpen PipeReader
child
if Bool
copen
then do MVar PipeBit
mv <- PipeWriter -> IO (MVar PipeBit)
pwmv PipeWriter
h
MVar PipeBit -> PipeBit -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar PipeBit
mv (Char -> PipeBit
PipeBit Char
c)
else String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"PipeWriter: Couldn't write to pipe because child end is closed"
vIsWritable :: PipeWriter -> IO Bool
vIsWritable PipeWriter
_ = Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True