{-# 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
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
vGetBuffering a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return BufferMode
NoBuffering
vShow a
x = forall (m :: * -> *) a. Monad m => a -> m a
return (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 forall a. Maybe a
Nothing Maybe String
mfp
vGetFP a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
vThrow a
h IOErrorType
et = do
Maybe String
fp <- forall a. HVIO a => a -> IO (Maybe String)
vGetFP a
h
forall a. IOError -> IO a
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 <- forall a. HVIO a => a -> IO Bool
vIsEOF a
h
if Bool
e then forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
eofErrorType
else forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsOpen a
h = forall a. HVIO a => a -> IO Bool
vIsClosed a
h forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not
vIsClosed a
h = forall a. HVIO a => a -> IO Bool
vIsOpen a
h forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not
vTestOpen a
h = do Bool
e <- forall a. HVIO a => a -> IO Bool
vIsClosed a
h
if Bool
e then forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
else forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsReadable a
_ = 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 <- forall a. HVIO a => a -> IO Char
vGetChar a
h
case Char
c of
Char
'\n' -> forall (m :: * -> *) a. Monad m => a -> m a
return String
accum
Char
x -> String
accum seq :: forall a b. a -> b -> b
`seq` String -> IO String
loop (String
accum forall a. [a] -> [a] -> [a]
++ [Char
x])
handler :: IOError -> IO String
handler IOError
e = if IOError -> Bool
isEOFError IOError
e then forall (m :: * -> *) a. Monad m => a -> m a
return String
accum
else forall a. IOError -> IO a
ioError IOError
e
in 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 <- forall a. HVIO a => a -> IO Char
vGetChar a
h
case Char
firstchar of
Char
'\n' -> 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 <- forall a. HVIO a => a -> IO Char
vGetChar a
h
String
next <- IO String
loop
Char
c seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return (Char
c forall a. a -> [a] -> [a]
: String
next)
handler :: IOError -> IO [a]
handler IOError
e = if IOError -> Bool
isEOFError IOError
e then forall (m :: * -> *) a. Monad m => a -> m a
return []
else forall a. IOError -> IO a
ioError IOError
e
in forall e a. Exception e => IO a -> (e -> IO a) -> IO a
Control.Exception.catch IO String
func forall {a}. IOError -> IO [a]
handler
in
do IO String
loop
vReady a
h = do forall a. HVIO a => a -> IO ()
vTestEOF a
h
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
vIsWritable a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vPutStr a
_ [] = forall (m :: * -> *) a. Monad m => a -> m a
return ()
vPutStr a
h (Char
x:String
xs) = do forall a. HVIO a => a -> Char -> IO ()
vPutChar a
h Char
x
forall a. HVIO a => a -> String -> IO ()
vPutStr a
h String
xs
vPutStrLn a
h String
s = forall a. HVIO a => a -> String -> IO ()
vPutStr a
h (String
s forall a. [a] -> [a] -> [a]
++ String
"\n")
vPrint a
h b
s = forall a. HVIO a => a -> String -> IO ()
vPutStrLn a
h (forall a. Show a => a -> String
show b
s)
vFlush = forall a. HVIO a => a -> IO ()
vTestOpen
vIsSeekable a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vRewind a
h = forall a. HVIO a => a -> SeekMode -> Integer -> IO ()
vSeek a
h SeekMode
AbsoluteSeek Integer
0
vPutChar a
h Char
_ = forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vSeek a
h SeekMode
_ Integer
_ = forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vTell a
h = forall a b. HVIO a => a -> IOErrorType -> IO b
vThrow a
h IOErrorType
illegalOperationErrorType
vGetChar a
h = 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 (forall a b. Ptr a -> Ptr b
castPtr Ptr b
buf, Int
len)
forall a. HVIO a => a -> String -> IO ()
vPutStr a
h String
str
vGetBuf a
h Ptr b
b Int
l =
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 = forall (m :: * -> *) a. Monad m => a -> m a
return t
accum
worker Ptr b
buf t
len t
accum =
do Bool
iseof <- forall a. HVIO a => a -> IO Bool
vIsEOF a
h
if Bool
iseof
then forall (m :: * -> *) a. Monad m => a -> m a
return t
accum
else do Char
c <- forall a. HVIO a => a -> IO Char
vGetChar a
h
let cc :: CChar
cc = Char -> CChar
castCharToCChar Char
c
forall a. Storable a => Ptr a -> a -> IO ()
poke (forall a b. Ptr a -> Ptr b
castPtr Ptr b
buf) CChar
cc
let newptr :: Ptr b
newptr = forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr b
buf Int
1
Ptr b -> t -> t -> IO t
worker forall {b}. Ptr b
newptr (t
len forall a. Num a => a -> a -> a
- t
1) (t
accum 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 (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 :: forall b. Show b => Handle -> b -> IO ()
vPrint = 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 :: forall b. Handle -> Ptr b -> Int -> IO Int
vGetBuf = forall b. Handle -> Ptr b -> Int -> IO Int
hGetBuf
vPutBuf :: forall b. Handle -> Ptr b -> Int -> IO ()
vPutBuf = 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 :: forall a. VIOCloseSupport a -> IO Bool
vioc_isopen VIOCloseSupport a
x = forall a. IORef a -> IO a
readIORef VIOCloseSupport a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst
vioc_get :: VIOCloseSupport a -> IO a
vioc_get :: forall a. VIOCloseSupport a -> IO a
vioc_get VIOCloseSupport a
x = forall a. IORef a -> IO a
readIORef VIOCloseSupport a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd
vioc_close :: VIOCloseSupport a -> IO ()
vioc_close :: forall a. VIOCloseSupport a -> IO ()
vioc_close VIOCloseSupport a
x = 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 :: forall a. VIOCloseSupport a -> a -> IO ()
vioc_set VIOCloseSupport a
x a
newdat = 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 <- forall a. a -> IO (IORef a)
newIORef (Bool
True, String
s)
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 = forall a. VIOCloseSupport a -> IO ()
vioc_close forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamReader -> IORef (Bool, String)
srv
vIsEOF :: StreamReader -> IO Bool
vIsEOF StreamReader
h = do forall a. HVIO a => a -> IO ()
vTestOpen StreamReader
h
String
d <- forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case String
d of
[] -> Bool
True
String
_ -> Bool
False
vIsOpen :: StreamReader -> IO Bool
vIsOpen = forall a. VIOCloseSupport a -> IO Bool
vioc_isopen forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamReader -> IORef (Bool, String)
srv
vGetChar :: StreamReader -> IO Char
vGetChar StreamReader
h = do forall a. HVIO a => a -> IO ()
vTestEOF StreamReader
h
String
c <- forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
let retval :: Char
retval = forall a. [a] -> a
head String
c
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (StreamReader -> IORef (Bool, String)
srv StreamReader
h) (forall a. [a] -> [a]
tail String
c)
forall (m :: * -> *) a. Monad m => a -> m a
return Char
retval
vGetContents :: StreamReader -> IO String
vGetContents StreamReader
h = do forall a. HVIO a => a -> IO ()
vTestEOF StreamReader
h
String
c <- forall a. VIOCloseSupport a -> IO a
vioc_get (StreamReader -> IORef (Bool, String)
srv StreamReader
h)
forall a. HVIO a => a -> IO ()
vClose StreamReader
h
forall (m :: * -> *) a. Monad m => a -> m a
return String
c
vIsReadable :: StreamReader -> IO Bool
vIsReadable StreamReader
_ = 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 <- forall a. a -> IO (IORef a)
newIORef (Bool
True, (Int
0, String
initval))
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
_ = 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 <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
forall (m :: * -> *) a. Monad m => a -> m a
return (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 <- forall a. HVIO a => a -> IO Bool
vIsOpen MemoryBuffer
x
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 forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsEOF :: MemoryBuffer -> IO Bool
vIsEOF MemoryBuffer
h = do forall a. HVIO a => a -> IO ()
vTestOpen MemoryBuffer
h
(Int, String)
c <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
forall (m :: * -> *) a. Monad m => a -> m a
return ((forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall a b. (a, b) -> b
snd (Int, String)
c)) forall a. Eq a => a -> a -> Bool
== (forall a b. (a, b) -> a
fst (Int, String)
c))
vIsOpen :: MemoryBuffer -> IO Bool
vIsOpen = forall a. VIOCloseSupport a -> IO Bool
vioc_isopen forall b c a. (b -> c) -> (a -> b) -> a -> c
. MemoryBuffer -> IORef (Bool, (Int, String))
vrv
vGetChar :: MemoryBuffer -> IO Char
vGetChar MemoryBuffer
h = do forall a. HVIO a => a -> IO ()
vTestEOF MemoryBuffer
h
(Int, String)
c <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let retval :: Char
retval = (forall a b. (a, b) -> b
snd (Int, String)
c) forall a. [a] -> Int -> a
!! (forall a b. (a, b) -> a
fst (Int, String)
c)
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (forall a. Enum a => a -> a
succ (forall a b. (a, b) -> a
fst (Int, String)
c), forall a b. (a, b) -> b
snd (Int, String)
c)
forall (m :: * -> *) a. Monad m => a -> m a
return Char
retval
vGetContents :: MemoryBuffer -> IO String
vGetContents MemoryBuffer
h = do forall a. HVIO a => a -> IO ()
vTestEOF MemoryBuffer
h
(Int, String)
v <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let retval :: String
retval = forall a. Int -> [a] -> [a]
drop (forall a b. (a, b) -> a
fst (Int, String)
v) (forall a b. (a, b) -> b
snd (Int, String)
v)
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (-Int
1, String
"")
forall a. HVIO a => a -> IO ()
vClose MemoryBuffer
h
forall (m :: * -> *) a. Monad m => a -> m a
return String
retval
vIsReadable :: MemoryBuffer -> IO Bool
vIsReadable MemoryBuffer
_ = 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) <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let (String
pre, String
post) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
buf
let newbuf :: String
newbuf = String
pre forall a. [a] -> [a] -> [a]
++ String
s forall a. [a] -> [a] -> [a]
++ (forall a. Int -> [a] -> [a]
drop (forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s) String
post)
forall a. VIOCloseSupport a -> a -> IO ()
vioc_set (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h) (Int
pos forall a. Num a => a -> a -> a
+ (forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s), String
newbuf)
vPutChar :: MemoryBuffer -> Char -> IO ()
vPutChar MemoryBuffer
h Char
c = forall a. HVIO a => a -> String -> IO ()
vPutStr MemoryBuffer
h [Char
c]
vIsWritable :: MemoryBuffer -> IO Bool
vIsWritable MemoryBuffer
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
vTell :: MemoryBuffer -> IO Integer
vTell MemoryBuffer
h = do (Int, String)
v <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (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) <- forall a. VIOCloseSupport a -> IO a
vioc_get (MemoryBuffer -> IORef (Bool, (Int, String))
vrv MemoryBuffer
h)
let seekpos :: Int
seekpos = 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 forall a. Num a => a -> a -> a
+ Int
seekpos
SeekMode
SeekFromEnd -> (forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf) forall a. Num a => a -> a -> a
+ Int
seekpos
let buf2 :: String
buf2 = String
buf forall a. [a] -> [a] -> [a]
++ if Int
newpos forall a. Ord a => a -> a -> Bool
> (forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf)
then forall a. Int -> a -> [a]
replicate (Int
newpos forall a. Num a => a -> a -> a
- (forall (t :: * -> *) a. Foldable t => t a -> Int
length String
buf)) Char
'\0'
else []
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
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
newHVIOPipe :: IO (PipeReader, PipeWriter)
newHVIOPipe :: IO (PipeReader, PipeWriter)
newHVIOPipe = do MVar PipeBit
mv <- forall a. IO (MVar a)
newEmptyMVar
IORef (Bool, MVar PipeBit)
readerref <- 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 <- forall a. a -> IO (IORef a)
newIORef (Bool
True, PipeReader
reader)
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
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 -> ShowS
[PipeBit] -> ShowS
PipeBit -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PipeBit] -> ShowS
$cshowList :: [PipeBit] -> ShowS
show :: PipeBit -> String
$cshow :: PipeBit -> String
showsPrec :: Int -> PipeBit -> ShowS
$cshowsPrec :: Int -> PipeBit -> ShowS
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 <- forall a. VIOCloseSupport a -> IO a
vioc_get (PipeReader -> IORef (Bool, MVar PipeBit)
prv PipeReader
h)
forall a. MVar a -> IO a
takeMVar MVar PipeBit
mv
instance HVIO PipeReader where
vClose :: PipeReader -> IO ()
vClose = forall a. VIOCloseSupport a -> IO ()
vioc_close forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeReader -> IORef (Bool, MVar PipeBit)
prv
vIsOpen :: PipeReader -> IO Bool
vIsOpen = forall a. VIOCloseSupport a -> IO Bool
vioc_isopen forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeReader -> IORef (Bool, MVar PipeBit)
prv
vIsEOF :: PipeReader -> IO Bool
vIsEOF PipeReader
h = do forall a. HVIO a => a -> IO ()
vTestOpen PipeReader
h
MVar PipeBit
mv <- forall a. VIOCloseSupport a -> IO a
vioc_get (PipeReader -> IORef (Bool, MVar PipeBit)
prv PipeReader
h)
PipeBit
dat <- forall a. MVar a -> IO a
readMVar MVar PipeBit
mv
forall (m :: * -> *) a. Monad m => a -> m a
return (PipeBit
dat forall a. Eq a => a -> a -> Bool
== PipeBit
PipeEOF)
vGetChar :: PipeReader -> IO Char
vGetChar PipeReader
h = do 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 -> forall (m :: * -> *) a. Monad m => a -> m a
return Char
x
PipeBit
_ -> 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 -> forall (m :: * -> *) a. Monad m => a -> m a
return []
PipeBit Char
x -> do String
next <- IO String
loop
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
x forall a. a -> [a] -> [a]
: String
next)
in do forall a. HVIO a => a -> IO ()
vTestEOF PipeReader
h
IO String
loop
vIsReadable :: PipeReader -> IO Bool
vIsReadable PipeReader
_ = 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 <- forall a. VIOCloseSupport a -> IO a
vioc_get IORef (Bool, PipeReader)
x
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 <- 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
forall a. MVar a -> a -> IO ()
putMVar MVar PipeBit
mv PipeBit
PipeEOF
forall a. VIOCloseSupport a -> IO ()
vioc_close (PipeWriter -> IORef (Bool, PipeReader)
pwv PipeWriter
h)
else forall (m :: * -> *) a. Monad m => a -> m a
return ()
vIsOpen :: PipeWriter -> IO Bool
vIsOpen = forall a. VIOCloseSupport a -> IO Bool
vioc_isopen forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipeWriter -> IORef (Bool, PipeReader)
pwv
vIsEOF :: PipeWriter -> IO Bool
vIsEOF PipeWriter
h = do forall a. HVIO a => a -> IO ()
vTestOpen PipeWriter
h
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
vPutChar :: PipeWriter -> Char -> IO ()
vPutChar PipeWriter
h Char
c = do forall a. HVIO a => a -> IO ()
vTestOpen PipeWriter
h
PipeReader
child <- forall a. VIOCloseSupport a -> IO a
vioc_get (PipeWriter -> IORef (Bool, PipeReader)
pwv PipeWriter
h)
Bool
copen <- 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
forall a. MVar a -> a -> IO ()
putMVar MVar PipeBit
mv (Char -> PipeBit
PipeBit Char
c)
else 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
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True