-- | Little functions connected with IO
module Util.IOExtras(
   catchEOF, -- :: IO a -> IO (Maybe a)
   -- If successful return result.
   -- if unsuccessful because of EOF return Nothing
   -- otherwise pass on error

   catchAlreadyExists, -- :: IO a -> IO (Maybe a)
   -- If successful return results,
   -- If unsuccessful because of an isAlreadyExists error return Nothing
   -- otherwise pass on error.

   catchDoesNotExist,
      -- :: IO a -> IO (Maybe a)

   catchErrorCalls, -- :: IO a -> IO (Either String a)
   -- Catch all calls to the error function.

   hGetLineR, -- :: Read a => Handle -> IO a
   -- hGetLine and then read.

   simpleModifyIORef,
      -- :: IORef a -> (a -> (a,b)) -> IO b
      -- carry out a pure modification of an IORef.
   ) where

import System.IO.Error
import System.IO

import Data.IORef
import Control.Exception

catchEOF :: IO a -> IO (Maybe a)
catchEOF :: IO a -> IO (Maybe a)
catchEOF IO a
action = (IOError -> Bool) -> IO a -> IO (Maybe a)
forall a. (IOError -> Bool) -> IO a -> IO (Maybe a)
catchGeneral IOError -> Bool
isEOFError IO a
action

catchAlreadyExists :: IO a -> IO (Maybe a)
catchAlreadyExists :: IO a -> IO (Maybe a)
catchAlreadyExists IO a
action = (IOError -> Bool) -> IO a -> IO (Maybe a)
forall a. (IOError -> Bool) -> IO a -> IO (Maybe a)
catchGeneral IOError -> Bool
isAlreadyExistsError IO a
action

catchDoesNotExist :: IO a -> IO (Maybe a)
catchDoesNotExist :: IO a -> IO (Maybe a)
catchDoesNotExist IO a
action = (IOError -> Bool) -> IO a -> IO (Maybe a)
forall a. (IOError -> Bool) -> IO a -> IO (Maybe a)
catchGeneral IOError -> Bool
isDoesNotExistError IO a
action

catchGeneral :: (IOError -> Bool) -> IO a -> IO (Maybe a)
catchGeneral :: (IOError -> Bool) -> IO a -> IO (Maybe a)
catchGeneral IOError -> Bool
discriminator IO a
action =
   do
      Either () a
result <- (IOError -> Maybe ()) -> IO a -> IO (Either () a)
forall e b a.
Exception e =>
(e -> Maybe b) -> IO a -> IO (Either b a)
tryJust
         (\ IOError
ioErr ->
                  if IOError -> Bool
discriminator IOError
ioErr
                     then
                        () -> Maybe ()
forall a. a -> Maybe a
Just ()
                     else
                        Maybe ()
forall a. Maybe a
Nothing
            )
         IO a
action
      case Either () a
result of
         Left () -> Maybe a -> IO (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
         Right a
success -> Maybe a -> IO (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
success)

catchErrorCalls :: IO a -> IO (Either ErrorCall a)
catchErrorCalls :: IO a -> IO (Either ErrorCall a)
catchErrorCalls = IO a -> IO (Either ErrorCall a)
forall e a. Exception e => IO a -> IO (Either e a)
Control.Exception.try

hGetLineR :: Read a => Handle -> IO a
hGetLineR :: Handle -> IO a
hGetLineR Handle
handle =
   do
      String
line <- Handle -> IO String
hGetLine Handle
handle
      a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> a
forall a. Read a => String -> a
read String
line)

simpleModifyIORef :: IORef a -> (a -> (a,b)) -> IO b
simpleModifyIORef :: IORef a -> (a -> (a, b)) -> IO b
simpleModifyIORef = IORef a -> (a -> (a, b)) -> IO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef