packages feed

safer-file-handles 0.2.0.1 → 0.3

raw patch · 7 files changed

+708/−249 lines, 7 filesdep +bytestringdep ~explicit-iomodesdep ~regionsPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring

Dependency ranges changed: explicit-iomodes, regions

API changes (from Hackage documentation)

- System.IO.SaferFileHandles: data RegionalFileHandle ioMode r :: (* -> *)
- System.IO.SaferFileHandles: instance Dup (RegionalFileHandle ioMode)
- System.IO.SaferFileHandles: instance Resource File
+ Data.ByteString.Char8.SaferFileHandles: hGet :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Char8.SaferFileHandles: hGetContents :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.Char8.SaferFileHandles: hGetLine :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.Char8.SaferFileHandles: hGetNonBlocking :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Char8.SaferFileHandles: hPut :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.Char8.SaferFileHandles: hPutStr :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.Char8.SaferFileHandles: hPutStrLn :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.Lazy.Char8.SaferFileHandles: hGet :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Lazy.Char8.SaferFileHandles: hGetContents :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.Lazy.Char8.SaferFileHandles: hGetNonBlocking :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Lazy.Char8.SaferFileHandles: hPut :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.Lazy.SaferFileHandles: hGet :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Lazy.SaferFileHandles: hGetContents :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.Lazy.SaferFileHandles: hGetNonBlocking :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.Lazy.SaferFileHandles: hPut :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.Lazy.SaferFileHandles: hPutStr :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.SaferFileHandles: hGet :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.SaferFileHandles: hGetContents :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.SaferFileHandles: hGetLine :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> cr ByteString
+ Data.ByteString.SaferFileHandles: hGetNonBlocking :: (ParentOf pr cr, MonadIO cr, ReadModes ioMode) => RegionalFileHandle ioMode pr -> Int -> cr ByteString
+ Data.ByteString.SaferFileHandles: hPut :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.SaferFileHandles: hPutStr :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ Data.ByteString.SaferFileHandles: hPutStrLn :: (ParentOf pr cr, MonadIO cr, WriteModes ioMode) => RegionalFileHandle ioMode pr -> ByteString -> cr ()
+ System.IO.SaferFileHandles: Err :: Standard W
+ System.IO.SaferFileHandles: File :: Binary -> FilePath -> IOMode ioMode -> File ioMode
+ System.IO.SaferFileHandles: In :: Standard R
+ System.IO.SaferFileHandles: Out :: Standard W
+ System.IO.SaferFileHandles: Std :: Standard ioMode -> File ioMode
+ System.IO.SaferFileHandles: TempFile :: Binary -> FilePath -> Template -> DefaultPermissions -> File RW
+ System.IO.SaferFileHandles: data Standard ioMode
+ System.IO.SaferFileHandles: type Binary = Bool
+ System.IO.SaferFileHandles: type RegionalFileHandle ioMode r = RegionalHandle (File ioMode) r
- System.IO.SaferFileHandles: data File
+ System.IO.SaferFileHandles: data File ioMode

Files

+ Data/ByteString/Char8/SaferFileHandles.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Data.ByteString.SaferFileHandles+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-- This module lifts the bytestring IO operations into the region monad.+--+-------------------------------------------------------------------------------++module Data.ByteString.Char8.SaferFileHandles+    ( hGetLine+    , hGetContents+    , hGet+    , hGetNonBlocking++    , hPut+    , hPutStr+    , hPutStrLn+    ) where++-------------------------------------------------------------------------------+-- Imports+-------------------------------------------------------------------------------++-- from base:+import Data.Int ( Int )++-- from transformers:+import Control.Monad.Trans ( MonadIO )++-- from bytestring:+import qualified Data.ByteString.Char8 as B++-- from regions:+import Control.Monad.Trans.Region ( ParentOf )++-- from explicit-iomodes:+import qualified Data.ByteString.Char8.ExplicitIOModes as E ( hGetLine+                                                            , hGetContents+                                                            , hGet+                                                            , hGetNonBlocking++                                                            , hPut+                                                            , hPutStr+                                                            , hPutStrLn+                                                            )++-- from ourselves:+import System.IO.SaferFileHandles          ( RegionalFileHandle+                                           , ReadModes, WriteModes+                                           )+import System.IO.SaferFileHandles.Internal ( wrap, wrap2 )+++-------------------------------------------------------------------------------+-- ByteString I/O with regional file handles+-------------------------------------------------------------------------------++-- | Wraps @Data.ByteString.@'B.hGetLine'.+hGetLine ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+         ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetLine = wrap E.hGetLine++-- | Wraps @Data.ByteString.@'B.hGetContents'.+hGetContents ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+             ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetContents = wrap E.hGetContents++-- | Wraps @Data.ByteString.@'B.hGet'.+hGet ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGet = wrap2 E.hGet++-- | Wraps @Data.ByteString.@'B.hGetNonBlocking'.+hGetNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+                ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGetNonBlocking = wrap2 E.hGetNonBlocking+++-- | Wraps @Data.ByteString.@'B.hPut'.+hPut ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPut = wrap2 E.hPut++-- | Wraps @Data.ByteString.@'B.hPutStr'.+hPutStr ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+        ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPutStr = wrap2 E.hPutStr++-- | Wraps @Data.ByteString.@'B.hPutStrLn'.+hPutStrLn ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+          ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPutStrLn = wrap2 E.hPutStrLn+++-- The End ---------------------------------------------------------------------
+ Data/ByteString/Lazy/Char8/SaferFileHandles.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Data.ByteString.SaferFileHandles+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-- This module lifts the bytestring IO operations into the region monad.+--+-------------------------------------------------------------------------------++module Data.ByteString.Lazy.Char8.SaferFileHandles+    ( hGetContents+    , hGet+    , hGetNonBlocking++    , hPut+    ) where++-------------------------------------------------------------------------------+-- Imports+-------------------------------------------------------------------------------++-- from base:+import Data.Int ( Int )++-- from transformers:+import Control.Monad.Trans ( MonadIO )++-- from bytestring:+import qualified Data.ByteString.Lazy.Char8 as B++-- from regions:+import Control.Monad.Trans.Region ( ParentOf )++-- from explicit-iomodes:+import qualified Data.ByteString.Lazy.Char8.ExplicitIOModes as E+    ( hGetContents, hGet, hGetNonBlocking+    , hPut+    )++-- from ourselves:+import System.IO.SaferFileHandles ( RegionalFileHandle , ReadModes, WriteModes )+import System.IO.SaferFileHandles.Internal ( wrap, wrap2 )+++-------------------------------------------------------------------------------+-- ByteString I/O with regional file handles+-------------------------------------------------------------------------------++-- | Wraps @Data.ByteString.@'B.hGetContents'.+hGetContents ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+             ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetContents = wrap E.hGetContents++-- | Wraps @Data.ByteString.@'B.hGet'.+hGet ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGet = wrap2 E.hGet++-- | Wraps @Data.ByteString.@'B.hGetNonBlocking'.+hGetNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+                ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGetNonBlocking = wrap2 E.hGetNonBlocking+++-- | Wraps @Data.ByteString.@'B.hPut'.+hPut ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPut = wrap2 E.hPut+++-- The End ---------------------------------------------------------------------
+ Data/ByteString/Lazy/SaferFileHandles.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Data.ByteString.SaferFileHandles+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-- This module lifts the bytestring IO operations into the region monad.+--+-------------------------------------------------------------------------------++module Data.ByteString.Lazy.SaferFileHandles+    ( hGetContents+    , hGet+    , hGetNonBlocking++    , hPut+    , hPutStr+    ) where++-------------------------------------------------------------------------------+-- Imports+-------------------------------------------------------------------------------++-- from base:+import Data.Int ( Int )++-- from transformers:+import Control.Monad.Trans ( MonadIO )++-- from bytestring:+import qualified Data.ByteString.Lazy as B++-- from regions:+import Control.Monad.Trans.Region ( ParentOf )++-- from explicit-iomodes:+import qualified Data.ByteString.Lazy.ExplicitIOModes as E ( hGetContents+                                                           , hGet+                                                           , hGetNonBlocking++                                                           , hPut+                                                           , hPutStr+                                                           )++-- from ourselves:+import System.IO.SaferFileHandles          ( RegionalFileHandle+                                           , ReadModes, WriteModes+                                           )+import System.IO.SaferFileHandles.Internal ( wrap, wrap2 )+++-------------------------------------------------------------------------------+-- ByteString I/O with regional file handles+-------------------------------------------------------------------------------++-- | Wraps @Data.ByteString.@'B.hGetContents'.+hGetContents ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+             ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetContents = wrap E.hGetContents++-- | Wraps @Data.ByteString.@'B.hGet'.+hGet ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGet = wrap2 E.hGet++-- | Wraps @Data.ByteString.@'B.hGetNonBlocking'.+hGetNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+                ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGetNonBlocking = wrap2 E.hGetNonBlocking+++-- | Wraps @Data.ByteString.@'B.hPut'.+hPut ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPut = wrap2 E.hPut++-- | Wraps @Data.ByteString.@'B.hPutStr'.+hPutStr ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+        ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPutStr = wrap2 E.hPutStr+++-- The End ---------------------------------------------------------------------
+ Data/ByteString/SaferFileHandles.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Data.ByteString.SaferFileHandles+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-- This module lifts the bytestring IO operations into the region monad.+--+-------------------------------------------------------------------------------++module Data.ByteString.SaferFileHandles+    ( hGetLine+    , hGetContents+    , hGet+    , hGetNonBlocking++    , hPut+    , hPutStr+    , hPutStrLn+    ) where++-------------------------------------------------------------------------------+-- Imports+-------------------------------------------------------------------------------++-- from base:+import Data.Int ( Int )++-- from transformers:+import Control.Monad.Trans ( MonadIO )++-- from bytestring:+import qualified Data.ByteString as B++-- from regions:+import Control.Monad.Trans.Region ( ParentOf )++-- from explicit-iomodes:+import qualified Data.ByteString.ExplicitIOModes as E ( hGetLine+                                                      , hGetContents+                                                      , hGet+                                                      , hGetNonBlocking++                                                      , hPut+                                                      , hPutStr+                                                      , hPutStrLn+                                                      )++-- from ourselves:+import System.IO.SaferFileHandles          ( RegionalFileHandle+                                           , ReadModes, WriteModes+                                           )+import System.IO.SaferFileHandles.Internal ( wrap, wrap2 )+++-------------------------------------------------------------------------------+-- ByteString I/O with regional file handles+-------------------------------------------------------------------------------++-- | Wraps @Data.ByteString.@'B.hGetLine'.+hGetLine ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+         ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetLine = wrap E.hGetLine++-- | Wraps @Data.ByteString.@'B.hGetContents'.+hGetContents ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+             ⇒ RegionalFileHandle ioMode pr → cr B.ByteString+hGetContents = wrap E.hGetContents++-- | Wraps @Data.ByteString.@'B.hGet'.+hGet ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGet = wrap2 E.hGet++-- | Wraps @Data.ByteString.@'B.hGetNonBlocking'.+hGetNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)+                ⇒ RegionalFileHandle ioMode pr → Int → cr B.ByteString+hGetNonBlocking = wrap2 E.hGetNonBlocking++-- | Wraps @Data.ByteString.@'B.hPut'.+hPut ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+     ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPut = wrap2 E.hPut++-- | Wraps @Data.ByteString.@'B.hPutStr'.+hPutStr ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+        ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPutStr = wrap2 E.hPutStr++-- | Wraps @Data.ByteString.@'B.hPutStrLn'.+hPutStrLn ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)+          ⇒ RegionalFileHandle ioMode pr → B.ByteString → cr ()+hPutStrLn = wrap2 E.hPutStrLn+++-- The End ---------------------------------------------------------------------
System/IO/SaferFileHandles.hs view
@@ -1,11 +1,12 @@-{-# LANGUAGE UnicodeSyntax #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UnicodeSyntax+           , NoImplicitPrelude+           , CPP+           , GADTs+           , TypeFamilies+           , RankNTypes+           , ViewPatterns+           , MultiParamTypeClasses+  #-}  ------------------------------------------------------------------------------- -- |@@ -14,16 +15,15 @@ -- License     :  BSD3 (see the file LICENSE) -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com> ----- This module provides the abstract type 'File' which represents an actual--- file. A file is a scarce resource, that is, in certain IOModes it can only be--- used by one user at a time. Because of the scarcity, a file needs to be--- /opened/ to grant temporary sole access to the file. When the file is no--- longer needed it should be /closed/ a.s.a.p to grant others access to the--- file.+-- This module provides the type 'File' which represents an actual file. A file+-- is a scarce resource, that is, in certain IOModes it can only be used by one+-- user at a time. Because of the scarcity, a file needs to be /opened/ to grant+-- temporary sole access to the file. When the file is no longer needed it+-- should be /closed/ a.s.a.p to grant others access to the file. ----- The contribution of this module are as follows:+-- The contributions of this module are as follows: ----- * First of all this module provides an instance for 'Resource' for a 'File'+-- * First of all this module provides an instance for 'Resource' for 'File' -- which allows it to be used with the @regions@ package. The @regions@ package -- provides the region monad transformer 'RegionT'. Scarce resources, like files -- for example, can be opened in a region. When the region terminates, all@@ -49,10 +49,26 @@ -- -- darcs get <http://code.haskell.org/~basvandijk/code/safer-file-handles-examples> ----- /WARNING:/ Currenly the handling of the standard files ('stdin', 'stdout' and+-- Note that this package is early work and still very experimental. Take note+-- of the following warnings:+--+-- * /WARNING:/ You are able to lift an arbitrary @IO@ action into a region. This+-- action may throw an @IOError@ which may contain a low-level handle to a+-- file. This handle can be retrieved from the @IOError@ using @ioeGetHandle@+-- from @System.IO.Error@.  So when an @IOError@ is thrown you will be able to+-- manually close the respected file! This will defeat the safety-guarantees+-- that this package promises to provide. /TODO: Think about how to solve this.../+-- The solution that Oleg provides in his paper is to filter out the low-level+-- handle in an @IOError@ when it's thrown. I can't easily do this because I have+-- to modify the @catch@ method of the 'MonadCatchIO' instance for 'RegionT' in+-- the @regions@ package. It feels like an ugly hack to solve this+-- @safer-file-handles@ specific problem in the independent general @regions@+-- package.+--+-- * /WARNING:/ Currenly the handling of the standard files ('stdin', 'stdout' and -- 'stderr') is not to my liking. See the documentation for details. ----- /NOTE:/ This module also provides functions from @System.IO@ which don't+-- * /NOTE:/ This module also provides functions from @System.IO@ which don't -- directly work with file handles like 'putStrLn' or 'getLine' for -- example. These functions implicitly use the standard handles. I actually -- provide more general versions of these that work in any 'MonadIO'. It could@@ -65,7 +81,9 @@  module System.IO.SaferFileHandles     ( -- * Files with explicit IO modes as scarce resources-      File+      File(..)+    , Binary+    , Standard(..)      , FilePath @@ -80,11 +98,13 @@       {-| Note that this module re-exports the @Control.Monad.Trans.Region@       module from the @regions@ package which allows you to: -      * Run regions using 'runRegionT'.+      * 'open' a 'File' in a 'RegionT'. -      * Concurrently run regions inside another region using 'forkTopRegion'.+      * Run a region using 'runRegionT'. -       * Duplicate regional file handles to a parent region using 'dup'.+      * Concurrently run a region inside another region using 'forkTopRegion'.++       * Duplicate a regional file handle to a parent region using 'dup'.       -}     , module Control.Monad.Trans.Region @@ -236,39 +256,17 @@  -- from base: import Prelude       ( Integer )-import Control.Monad ( fmap-                     , return, (>>=), fail-                     , liftM+import Control.Monad ( return, (>>=), fail                      ) import Data.Function ( ($) )-import Data.Tuple    ( uncurry ) import Data.Bool     ( Bool(False, True) ) import Data.Char     ( Char, String ) import Data.Int      ( Int )-import Data.Maybe    ( Maybe(Nothing, Just) )+import Data.Maybe    ( Maybe(Just) ) import Text.Show     ( Show ) import Text.Read     ( Read ) import Foreign.Ptr   ( Ptr ) -import System.IO ( IO-                 , FilePath-                 , BufferMode(..)-                 , HandlePosn-                 , SeekMode(..)-#if MIN_VERSION_base(4,2,0) && !defined(__NHC__) && !defined(__HUGS__)-                 , TextEncoding-                 , latin1-                 , utf8, utf8_bom-                 , utf16, utf16le, utf16be-                 , utf32, utf32le, utf32be-                 , localeEncoding--                 , Newline(..)-                 , nativeNewline-                 , NewlineMode(..)-                 , noNewlineTranslation, universalNewlineMode, nativeNewlineMode-#endif-                 ) import qualified System.IO as SIO  -- from base-unicode-symbols:@@ -282,132 +280,59 @@  -- from regions: import Control.Monad.Trans.Region -- (re-exported entirely)-import Control.Monad.Trans.Region.Unsafe ( Resource-                                         , openResource-                                         , closeResource-                                         , internalHandle-                                         , ParentOf-                                         , Dup-                                         )-import qualified Control.Monad.Trans.Region.Unsafe as R ( Handle )+import Control.Monad.Trans.Region.Unsafe ( internalHandle )  -- from explicit-iomodes import System.IO.ExplicitIOModes ( IOMode(..)-                                 , regularIOMode                                  , R, W, A, RW                                  , ReadModes                                  , WriteModes                                  -- TODO:, CheckMode-                                 ) ------------------------------------------------------------------------------------ * Files with explicit IO modes as scarce resources----------------------------------------------------------------------------------{-| A file scarce resource.--This module provides an instance for 'Resource' for 'File'. This allows you to-open files in a region which are automatically closed when the region terminates-but it disallows you to return handles to these closed files from the region so-preventing I/O with closed files.--You can open a file with one of the following functions:--* 'openFile'--* 'openBinaryFile'--* 'openTempFile'--* 'openBinaryTempFile'-#if MIN_VERSION_base(4,2,0)-* 'openTempFileWithDefaultPermissions'--* 'openBinaryTempFileWithDefaultPermissions'-#endif--* 'stdin', 'stdout', 'stderr'--}-data File = File Binary-                 FilePath-                 SIO.IOMode-          | TempFile Binary-                     FilePath-                     Template-#if MIN_VERSION_base(4,2,0)-                     DefaultPermissions-#endif-          -- TODO: I need to review the handling of standard files:-          | Std Standard---- | Should the file be opened in binary mode?-type Binary = Bool---- | The template of a temporary file path.-type Template = String+                                 , FilePath+                                 , BufferMode(..)+                                 , HandlePosn+                                 , SeekMode(..)+#if MIN_VERSION_base(4,2,0) && !defined(__NHC__) && !defined(__HUGS__)+                                 , TextEncoding+                                 , latin1+                                 , utf8, utf8_bom+                                 , utf16, utf16le, utf16be+                                 , utf32, utf32le, utf32be+                                 , localeEncoding -#if MIN_VERSION_base(4,2,0)--- | Should default permissions be used when opening a temporary file?-type DefaultPermissions = Bool+                                 , Newline(..)+                                 , nativeNewline+                                 , NewlineMode(..)+                                 , noNewlineTranslation+                                 , universalNewlineMode+                                 , nativeNewlineMode #endif---- | The standard files.-data Standard = In | Out | Err---- | Internally used function to convert a standard file to the corresponding--- handle.-stdHndl ∷ Standard → SIO.Handle-stdHndl In  = SIO.stdin-stdHndl Out = SIO.stdout-stdHndl Err = SIO.stderr--instance Resource File where-    data R.Handle File = FileHandle (Maybe FilePath)-                                    -- The optional file path is needed-                                    -- because opening a temporary file-                                    -- also yields the generated file-                                    -- path.-                                    SIO.Handle+                                 ) -    openResource (File isBinary filePath ioMode) =-        fmap (FileHandle Nothing) $-             (if isBinary then SIO.openBinaryFile else SIO.openFile)-             filePath ioMode+import qualified System.IO.ExplicitIOModes as E -#if MIN_VERSION_base(4,2,0)-    openResource (TempFile isBinary filePath template defaultPerms) = do-        fmap (uncurry (FileHandle ∘ Just)) $-             (case (isBinary, defaultPerms) of-               (False, False) → SIO.openTempFile-               (True,  False) → SIO.openBinaryTempFile-               (False, True)  → SIO.openTempFileWithDefaultPermissions-               (True,  True)  → SIO.openBinaryTempFileWithDefaultPermissions-             ) filePath template-#else-    openResource (TempFile isBinary filePath template) = do-        fmap (uncurry (FileHandle ∘ Just)) $-             (if isBinary then SIO.openBinaryTempFile else SIO.openTempFile)-             filePath template-#endif-    -- TODO: I need to review the handling of standard files:-    openResource (Std std) = return $ FileHandle Nothing $ stdHndl std+-- from ourselves:+import System.IO.SaferFileHandles.Internal -    closeResource (FileHandle _ h) = SIO.hClose h+-- TODO: explicit import:+-- import System.IO.SaferFileHandles.Internal ( RegionalFileHandle+--                                            , File(..)+--                                            , Binary+--                                            , Template+--                                            , Standard(..)+--                                            , wrap, wrap2, wrap3+--                                            )  --- ** Opening files in a region---- | A handle to a file parameterised by the IOMode with which the file was--- opened and the region @r@ in which it was created.-newtype RegionalFileHandle ioMode (r ∷ * → *) = RegionalFileHandle-    { unRegionalFileHandle ∷ RegionalHandle File r }+-------------------------------------------------------------------------------+-- * Files with explicit IO modes as scarce resources+------------------------------------------------------------------------------- -instance Dup (RegionalFileHandle ioMode) where-    dup = liftM RegionalFileHandle ∘ dup ∘ unRegionalFileHandle+{-| Convenience function for opening a file which yields a regional handle to+it. This provides a safer replacement for @System.IO.@'SIO.openFile'. -{-| Open a file yielding a regional handle to it. This provides a safer-replacement for @System.IO.@'SIO.openFile'.+Note that: @openFile filePath ioMode =@ 'open' @$@ 'File' @False filePath ioMode@  Note that the returned regional file handle is parameterized by the region in which it was created. This ensures that handles can never escape their@@ -422,29 +347,30 @@          → IOMode ioMode          → RegionT s pr                    (RegionalFileHandle ioMode (RegionT s pr))-openFile filePath ioMode = liftM RegionalFileHandle-                         $ open $ File False filePath $ regularIOMode ioMode+openFile filePath ioMode = open $ File False filePath ioMode -{-| Opens a file, applies the given continuation function to the resulting-regional file handle and runs the resulting region. This provides a safer safer-replacement for @System.IO.@'SIO.withFile'.+{-| Convenience function which opens a file, applies the given continuation+function to the resulting regional file handle and runs the resulting+region. This provides a safer safer replacement for @System.IO.@'SIO.withFile'.++Note that: @withFile filePath ioMode =@ 'with' @$@ 'File' @False filePath ioMode@+ -} withFile ∷ MonadCatchIO pr          ⇒ FilePath          → IOMode ioMode-         →  (∀ s. RegionalFileHandle ioMode (RegionT s pr)-            → RegionT s pr α-            )+         → (∀ s. RegionalFileHandle ioMode (RegionT s pr)+           → RegionT s pr α+           )          → pr α-withFile filePath ioMode f = with (File False filePath (regularIOMode ioMode))-                                  (f ∘ RegionalFileHandle)+withFile filePath ioMode = with $ File False filePath ioMode   -- ** Standard handles  {- $stdHndls -/BIG WARNING:/ I'm not satisfied with my current implementation of the standard+/WARNING:/ I'm not satisfied with my current implementation of the standard handles ('stdin', 'stdout' and 'stderr')! Currently the standard handles are regional computations that return the regional file handles to the respected standard handles. There are 4 problems with this approach:@@ -488,23 +414,29 @@  -- TODO: I need to review these: --- | Return a regional handle to standard input. This provides a safer--- replacement for @System.IO.@'SIO.stdin'.+-- | Convenience function for returning a regional handle to standard+-- input. This provides a safer replacement for @System.IO.@'SIO.stdin'.+--+-- Note that: @stdin =@ 'open' @$@ 'Std' 'In' stdin ∷ MonadCatchIO pr       ⇒ RegionT s pr (RegionalFileHandle R (RegionT s pr))-stdin = liftM RegionalFileHandle $ open $ Std In+stdin = open $ Std In --- | Return a regional handle to standard output. This provides a safer--- replacement for @System.IO.@'SIO.stdout'.+-- | Convenience function for returning a regional handle to standard+-- output. This provides a safer replacement for @System.IO.@'SIO.stdout'.+--+-- Note that: @stdin =@ 'open' @$@ 'Std' 'Out' stdout ∷ MonadCatchIO pr        ⇒ RegionT s pr (RegionalFileHandle W (RegionT s pr))-stdout = liftM RegionalFileHandle $ open $ Std Out+stdout = open $ Std Out --- | Return a regional handle to standard error. This provides a safer--- replacement for @System.IO.@'SIO.stderr'.+-- | Convenience function for returning a regional handle to standard+-- error. This provides a safer replacement for @System.IO.@'SIO.stderr'.+--+-- Note that: @stdin =@ 'open' @$@ 'Std' 'Err' stderr ∷ MonadCatchIO pr        ⇒ RegionT s pr (RegionalFileHandle W (RegionT s pr))-stderr = liftM RegionalFileHandle $ open $ Std Err+stderr = open $ Std Err  {- $TODO_cast @@ -527,29 +459,7 @@ However I'm not sure yet how to implement it... -} ------------------------------------------------------------------------------------ Utility wrapping functions--------------------------------------------------------------------------------- -regularHandle ∷ RegionalFileHandle ioMode r → SIO.Handle-regularHandle (unRegionalFileHandle → (internalHandle → FileHandle _ h)) = h--wrap ∷ MonadIO m-     ⇒ (SIO.Handle → IO α)-     → (RegionalFileHandle ioMode r → m α)-wrap f = \h → liftIO $ f (regularHandle h)--wrap2 ∷ MonadIO m-      ⇒ (SIO.Handle → β → IO α)-      → (RegionalFileHandle ioMode r → β → m α)-wrap2 f = \h y → liftIO $ f (regularHandle h) y--wrap3 ∷ MonadIO m-      ⇒ (SIO.Handle → γ → β → IO α)-      → (RegionalFileHandle ioMode r → γ → β → m α)-wrap3 f = \h z y → liftIO $ f (regularHandle h) z y-- ------------------------------------------------------------------------------- -- * Operations on regional file handles -------------------------------------------------------------------------------@@ -559,13 +469,13 @@ -- | Wraps @System.IO.@'SIO.hFileSize'. hFileSize ∷ (pr `ParentOf` cr, MonadIO cr)           ⇒ RegionalFileHandle ioMode pr → cr Integer-hFileSize = wrap SIO.hFileSize+hFileSize = wrap E.hFileSize  #ifdef __GLASGOW_HASKELL__ -- | Wraps @System.IO.@'SIO.hSetFileSize'. hSetFileSize ∷ (pr `ParentOf` cr, MonadIO cr)              ⇒ RegionalFileHandle ioMode pr → Integer → cr ()-hSetFileSize = wrap2 SIO.hSetFileSize+hSetFileSize = wrap2 E.hSetFileSize #endif  @@ -574,11 +484,11 @@ -- | Wraps @System.IO.@'SIO.hIsEOF'. hIsEOF ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)        ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsEOF = wrap SIO.hIsEOF+hIsEOF = wrap E.hIsEOF  -- | Wraps @System.IO.@'SIO.isEOF'. isEOF ∷ MonadIO m ⇒ m Bool-isEOF = liftIO $ SIO.isEOF+isEOF = liftIO $ E.isEOF   -- ** Buffering operations@@ -586,17 +496,17 @@ -- | Wraps @System.IO.@'SIO.hSetBuffering'. hSetBuffering ∷ (pr `ParentOf` cr, MonadIO cr)               ⇒ RegionalFileHandle ioMode pr → BufferMode → cr ()-hSetBuffering = wrap2 SIO.hSetBuffering+hSetBuffering = wrap2 E.hSetBuffering  -- | Wraps @System.IO.@'SIO.hGetBuffering'. hGetBuffering ∷ (pr `ParentOf` cr, MonadIO cr)               ⇒ RegionalFileHandle ioMode pr → cr BufferMode-hGetBuffering = wrap SIO.hGetBuffering+hGetBuffering = wrap E.hGetBuffering  -- | Wraps @System.IO.@'SIO.hFlush'. hFlush ∷ (pr `ParentOf` cr, MonadIO cr)        ⇒ RegionalFileHandle ioMode pr → cr ()-hFlush = wrap SIO.hFlush+hFlush = wrap E.hFlush   -- ** Repositioning handles@@ -604,22 +514,22 @@ -- | Wraps @System.IO.@'SIO.hGetPosn'. hGetPosn ∷ (pr `ParentOf` cr, MonadIO cr)          ⇒ RegionalFileHandle ioMode pr → cr HandlePosn-hGetPosn = wrap SIO.hGetPosn+hGetPosn = wrap E.hGetPosn  -- | Wraps @System.IO.@'SIO.hSetPosn'. hSetPosn ∷ MonadIO m ⇒ HandlePosn → m ()-hSetPosn = liftIO ∘ SIO.hSetPosn+hSetPosn = liftIO ∘ E.hSetPosn  -- | Wraps @System.IO.@'SIO.hSeek'. hSeek ∷ (pr `ParentOf` cr, MonadIO cr)       ⇒ RegionalFileHandle ioMode pr → SeekMode → Integer → cr ()-hSeek = wrap3 SIO.hSeek+hSeek = wrap3 E.hSeek  #if !defined(__NHC__) -- | Wraps @System.IO.@'SIO.hTell'. hTell ∷ (pr `ParentOf` cr, MonadIO cr)       ⇒ RegionalFileHandle ioMode pr → cr Integer-hTell = wrap SIO.hTell+hTell = wrap E.hTell #endif  @@ -628,27 +538,27 @@ -- | Wraps @System.IO.@'SIO.hIsOpen'. hIsOpen ∷ (pr `ParentOf` cr, MonadIO cr)          ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsOpen = wrap SIO.hIsOpen+hIsOpen = wrap E.hIsOpen  -- | Wraps @System.IO.@'SIO.hIsClosed'. hIsClosed ∷ (pr `ParentOf` cr, MonadIO cr)            ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsClosed = wrap SIO.hIsClosed+hIsClosed = wrap E.hIsClosed  -- | Wraps @System.IO.@'SIO.hIsReadable'. hIsReadable ∷ (pr `ParentOf` cr, MonadIO cr)             ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsReadable = wrap SIO.hIsReadable+hIsReadable = wrap E.hIsReadable  -- | Wraps @System.IO.@'SIO.hIsWritable'. hIsWritable ∷ (pr `ParentOf` cr, MonadIO cr)             ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsWritable = wrap SIO.hIsWritable+hIsWritable = wrap E.hIsWritable  -- | Wraps @System.IO.@'SIO.hIsSeekable'. hIsSeekable ∷ (pr `ParentOf` cr, MonadIO cr)             ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsSeekable = wrap SIO.hIsSeekable+hIsSeekable = wrap E.hIsSeekable   -- ** Terminal operations (not portable: GHC/Hugs only)@@ -657,17 +567,17 @@ -- | Wraps @System.IO.@'SIO.hIsTerminalDevice'. hIsTerminalDevice ∷ (pr `ParentOf` cr, MonadIO cr)                   ⇒ RegionalFileHandle ioMode pr → cr Bool-hIsTerminalDevice = wrap SIO.hIsTerminalDevice+hIsTerminalDevice = wrap E.hIsTerminalDevice  -- | Wraps @System.IO.@'SIO.hSetEcho'. hSetEcho ∷ (pr `ParentOf` cr, MonadIO cr)          ⇒ RegionalFileHandle ioMode pr → Bool → cr ()-hSetEcho = wrap2 SIO.hSetEcho+hSetEcho = wrap2 E.hSetEcho  -- | Wraps @System.IO.@'SIO.hGetEcho'. hGetEcho ∷ (pr `ParentOf` cr, MonadIO cr)          ⇒ RegionalFileHandle ioMode pr → cr Bool-hGetEcho = wrap SIO.hGetEcho+hGetEcho = wrap E.hGetEcho #endif  @@ -677,7 +587,7 @@ -- | Wraps @System.IO.@'SIO.hShow'. hShow ∷ (pr `ParentOf` cr, MonadIO cr)       ⇒ RegionalFileHandle ioMode pr → cr String-hShow = wrap SIO.hShow+hShow = wrap E.hShow #endif  @@ -690,32 +600,32 @@ -- | Wraps @System.IO.@'SIO.hWaitForInput'. hWaitForInput ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)               ⇒ RegionalFileHandle ioMode pr → Int → cr Bool-hWaitForInput = wrap2 SIO.hWaitForInput+hWaitForInput = wrap2 E.hWaitForInput  -- | Wraps @System.IO.@'SIO.hReady'. hReady ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)        ⇒ RegionalFileHandle ioMode pr → cr Bool-hReady = wrap SIO.hReady+hReady = wrap E.hReady  -- | Wraps @System.IO.@'SIO.hGetChar'. hGetChar ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)          ⇒ RegionalFileHandle ioMode pr → cr Char-hGetChar = wrap SIO.hGetChar+hGetChar = wrap E.hGetChar  -- | Wraps @System.IO.@'SIO.hGetLine'. hGetLine ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)          ⇒ RegionalFileHandle ioMode pr → cr String-hGetLine = wrap SIO.hGetLine+hGetLine = wrap E.hGetLine  -- | Wraps @System.IO.@'SIO.hLookAhead'. hLookAhead ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)            ⇒ RegionalFileHandle ioMode pr → cr Char-hLookAhead = wrap SIO.hLookAhead+hLookAhead = wrap E.hLookAhead  -- | Wraps @System.IO.@'SIO.hGetContents'. hGetContents ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)              ⇒ RegionalFileHandle ioMode pr → cr String-hGetContents = wrap SIO.hGetContents+hGetContents = wrap E.hGetContents   -- ** Text ouput@@ -723,22 +633,22 @@ -- | Wraps @System.IO.@'SIO.hPutChar'. hPutChar ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)          ⇒ RegionalFileHandle ioMode pr → Char → cr ()-hPutChar = wrap2 SIO.hPutChar+hPutChar = wrap2 E.hPutChar  -- | Wraps @System.IO.@'SIO.hPutStr'. hPutStr ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)         ⇒ RegionalFileHandle ioMode pr → String → cr ()-hPutStr = wrap2 SIO.hPutStr+hPutStr = wrap2 E.hPutStr  -- | Wraps @System.IO.@'SIO.hPutStrLn'. hPutStrLn ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)           ⇒ RegionalFileHandle ioMode pr → String → cr ()-hPutStrLn = wrap2 SIO.hPutStrLn+hPutStrLn = wrap2 E.hPutStrLn  -- | Wraps @System.IO.@'SIO.hPrint'. hPrint ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode, Show α)        ⇒ RegionalFileHandle ioMode pr → α → cr ()-hPrint = wrap2 SIO.hPrint+hPrint = wrap2 E.hPrint   -- ** Special cases for standard input and output@@ -792,6 +702,8 @@ continuation function to the resulting regional file handle and runs the resulting region. This provides a safer replacement for @System.IO.@'SIO.withBinaryFile'.++Note that: @withBinaryFile filePath ioMode =@ 'with' @$@ 'File' @True filePath ioMode@ -} withBinaryFile ∷ MonadCatchIO pr                ⇒ FilePath@@ -800,44 +712,45 @@                   → RegionT s pr α                   )                → pr α-withBinaryFile filePath ioMode f = with (File True filePath (regularIOMode ioMode))-                                        (f ∘ RegionalFileHandle)+withBinaryFile filePath ioMode = with $ File True filePath ioMode --- | Open a file in binary yielding a regional handle to it. This provides a--- safer replacement for @System.IO.@'SIO.openBinaryFile'.+-- | Convenience function whichs opens a file in binary mode yielding a regional+-- handle to it. This provides a safer replacement for+-- @System.IO.@'SIO.openBinaryFile'.+--+-- Note that: @openBinaryFile filePath ioMode =@ 'open' @$@ 'File' @True filePath ioMode@ openBinaryFile ∷ MonadCatchIO pr                ⇒ FilePath                → IOMode ioMode                → RegionT s pr                          (RegionalFileHandle ioMode (RegionT s pr))-openBinaryFile filePath ioMode = liftM RegionalFileHandle-                               $ open $ File True filePath (regularIOMode ioMode)+openBinaryFile filePath ioMode = open $ File True filePath ioMode  -- | Wraps @System.IO.@'SIO.hSetBinaryMode'. hSetBinaryMode ∷ (pr `ParentOf` cr, MonadIO cr)                ⇒ RegionalFileHandle ioMode pr → Bool → cr ()-hSetBinaryMode = wrap2 SIO.hSetBinaryMode+hSetBinaryMode = wrap2 E.hSetBinaryMode  -- | Wraps @System.IO.@'SIO.hPutBuf'. hPutBuf ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)         ⇒ RegionalFileHandle ioMode pr → Ptr α → Int → cr ()-hPutBuf = wrap3 SIO.hPutBuf+hPutBuf = wrap3 E.hPutBuf  -- | Wraps @System.IO.@'SIO.hGetBuf'. hGetBuf ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)         ⇒ RegionalFileHandle ioMode pr → Ptr α → Int → cr Int-hGetBuf = wrap3 SIO.hGetBuf+hGetBuf = wrap3 E.hGetBuf  #if !defined(__NHC__) && !defined(__HUGS__) -- | Wraps @System.IO.@'SIO.hPutBufNonBlocking'. hPutBufNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, WriteModes ioMode)                    ⇒ RegionalFileHandle ioMode pr → Ptr α → Int → cr Int-hPutBufNonBlocking = wrap3 SIO.hPutBufNonBlocking+hPutBufNonBlocking = wrap3 E.hPutBufNonBlocking  -- | Wraps @System.IO.@'SIO.hGetBufNonBlocking'. hGetBufNonBlocking ∷ (pr `ParentOf` cr, MonadIO cr, ReadModes ioMode)                    ⇒ RegionalFileHandle ioMode pr → Ptr α → Int → cr Int-hGetBufNonBlocking = wrap3 SIO.hGetBufNonBlocking+hGetBufNonBlocking = wrap3 E.hGetBufNonBlocking #endif  @@ -857,7 +770,7 @@ #if MIN_VERSION_base(4,2,0)                                                                  False #endif-  return (fp, RegionalFileHandle rh)+  return (fp, rh)  -- | Open a temporary file yielding a regional handle to it paired with the -- generated file path. This provides a safer replacement for@@ -890,7 +803,7 @@                                                                  filePath                                                                  template                                                                  True-  return (fp, RegionalFileHandle rh)+  return (fp, rh)  -- | Open a temporary file with default permissions yielding a regional handle -- to it paired with the generated file path. This provides a safer replacement@@ -923,16 +836,16 @@ -- | Wraps @System.IO.@'SIO.hSetEncoding'. hSetEncoding ∷ (pr `ParentOf` cr, MonadIO cr)              ⇒ RegionalFileHandle ioMode pr → TextEncoding → cr ()-hSetEncoding = wrap2 SIO.hSetEncoding+hSetEncoding = wrap2 E.hSetEncoding  -- | Wraps @System.IO.@'SIO.hGetEncoding'. hGetEncoding ∷ (pr `ParentOf` cr, MonadIO cr)              ⇒ RegionalFileHandle ioMode pr → cr (Maybe TextEncoding)-hGetEncoding = wrap SIO.hGetEncoding+hGetEncoding = wrap E.hGetEncoding  -- | Generalizes @System.IO.@'SIO.mkTextEncoding' to any 'MonadIO'. mkTextEncoding ∷ MonadIO m ⇒ String → m TextEncoding-mkTextEncoding = liftIO ∘ SIO.mkTextEncoding+mkTextEncoding = liftIO ∘ E.mkTextEncoding   --------------------------------------------------------------------------------@@ -942,7 +855,7 @@ -- | Wraps @System.IO.@'SIO.hSetNewlineMode'. hSetNewlineMode ∷ (pr `ParentOf` cr, MonadIO cr)                 ⇒ RegionalFileHandle ioMode pr → NewlineMode → cr ()-hSetNewlineMode = wrap2 SIO.hSetNewlineMode+hSetNewlineMode = wrap2 E.hSetNewlineMode #endif  
+ System/IO/SaferFileHandles/Internal.hs view
@@ -0,0 +1,178 @@+{-# LANGUAGE UnicodeSyntax+           , NoImplicitPrelude+           , CPP+           , GADTs+           , TypeFamilies+           , RankNTypes+           , ViewPatterns+           , MultiParamTypeClasses+  #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  System.IO.Internal+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-------------------------------------------------------------------------------++module System.IO.SaferFileHandles.Internal where++-- from base:+import Control.Monad ( fmap , return )+import Data.Function ( ($) )+import Data.Tuple    ( uncurry )+import Data.Bool     ( Bool(False, True) )+import Data.Char     ( String )+import Data.Maybe    ( Maybe(Nothing, Just) )++-- from base-unicode-symbols:+import Data.Function.Unicode ( (∘) )++-- from transformers:+import Control.Monad.Trans ( MonadIO, liftIO )++-- from regions:+import Control.Monad.Trans.Region        ( RegionalHandle )+import Control.Monad.Trans.Region.Unsafe ( Resource+                                         , openResource+                                         , closeResource+                                         , internalHandle+                                         )+import qualified Control.Monad.Trans.Region.Unsafe as R ( Handle )++-- from explicit-iomodes+import System.IO.ExplicitIOModes ( IOMode(..)+                                 , R, W, RW+                                 , IO+                                 , FilePath+                                 )++import qualified System.IO.ExplicitIOModes as E+                                 ( Handle+                                 , stdin, stdout, stderr+                                 , openFile+                                 , openBinaryFile+                                 , openTempFile+                                 , openBinaryTempFile+                                 , openTempFileWithDefaultPermissions+                                 , openBinaryTempFileWithDefaultPermissions+                                 , hClose+                                 )+++-------------------------------------------------------------------------------+-- * Files with explicit IO modes as scarce resources+-------------------------------------------------------------------------------++{-| A file scarce resource parameterized by the IOMode in which you want to open+the file.++Note that this module provides an instance for 'Resource' for 'File' @ioMode@. This allows+you to 'open' files in a region which are automatically closed when the region+terminates but it disallows you to return handles to these closed files from the+region so preventing I/O with closed files.+-}+data File ioMode where+    File ∷ Binary → FilePath → IOMode ioMode → File ioMode+    TempFile ∷ Binary+             → FilePath+             → Template+#if MIN_VERSION_base(4,2,0)+             → DefaultPermissions+#endif+             → File RW++          -- TODO: I need to review the handling of standard files:+    Std ∷ Standard ioMode → File ioMode++-- | Should the file be opened in binary mode?+type Binary = Bool++-- | The template of a temporary file path.+type Template = String++#if MIN_VERSION_base(4,2,0)+-- | Should default permissions be used when opening a temporary file?+type DefaultPermissions = Bool+#endif++-- | The standard files parameterized by concrete IOModes which work for the+-- majority of cases.+data Standard ioMode where+    In  ∷ Standard R+    Out ∷ Standard W+    Err ∷ Standard W++-- | Internally used function to convert a standard file to the corresponding+-- handle.+stdHndl ∷ Standard ioMode → E.Handle ioMode+stdHndl In  = E.stdin+stdHndl Out = E.stdout+stdHndl Err = E.stderr++instance Resource (File ioMode) where+    data R.Handle (File ioMode) = FileHandle (Maybe FilePath)+                                    -- The optional file path is needed+                                    -- because opening a temporary file+                                    -- also yields the generated file+                                    -- path.+                                    (E.Handle ioMode)++    openResource (File isBinary filePath ioMode) =+        fmap (FileHandle Nothing) $+             (if isBinary then E.openBinaryFile else E.openFile)+             filePath ioMode++#if MIN_VERSION_base(4,2,0)+    openResource (TempFile isBinary filePath template defaultPerms) = do+        fmap (uncurry (FileHandle ∘ Just)) $+             (case (isBinary, defaultPerms) of+               (False, False) → E.openTempFile+               (True,  False) → E.openBinaryTempFile+               (False, True)  → E.openTempFileWithDefaultPermissions+               (True,  True)  → E.openBinaryTempFileWithDefaultPermissions+             ) filePath template+#else+    openResource (TempFile isBinary filePath template) = do+        fmap (uncurry (FileHandle ∘ Just)) $+             (if isBinary then E.openBinaryTempFile else E.openTempFile)+             filePath template+#endif+    -- TODO: I need to review the handling of standard files:+    openResource (Std std) = return $ FileHandle Nothing $ stdHndl std++    closeResource (FileHandle _ h) = E.hClose h++-- | A handy type synonym for a regional handle to an opened file parameterized+-- by the IOMode in which you opened the file and the region in which it was+-- created.+type RegionalFileHandle ioMode r = RegionalHandle (File ioMode) r+++--------------------------------------------------------------------------------+-- Utility wrapping functions+--------------------------------------------------------------------------------++regularHandle ∷ RegionalFileHandle ioMode r → E.Handle ioMode+regularHandle (internalHandle → FileHandle _ h) = h++wrap ∷ MonadIO m+     ⇒ (E.Handle ioMode → IO α)+     → (RegionalFileHandle ioMode r → m α)+wrap f = \h → liftIO $ f (regularHandle h)++wrap2 ∷ MonadIO m+      ⇒ (E.Handle ioMode → β → IO α)+      → (RegionalFileHandle ioMode r → β → m α)+wrap2 f = \h y → liftIO $ f (regularHandle h) y++wrap3 ∷ MonadIO m+      ⇒ (E.Handle ioMode → γ → β → IO α)+      → (RegionalFileHandle ioMode r → γ → β → m α)+wrap3 f = \h z y → liftIO $ f (regularHandle h) z y+++-- The End ---------------------------------------------------------------------+
safer-file-handles.cabal view
@@ -1,5 +1,5 @@ name:          safer-file-handles-version:       0.2.0.1+version:       0.3 cabal-version: >=1.6 build-type:    Simple license:       BSD3@@ -58,11 +58,19 @@   Location: http://code.haskell.org/~basvandijk/code/safer-file-handles  Library-  GHC-Options: -O2 -Wall-  build-depends: base                      >= 4 && < 4.3+  GHC-Options: -Wall+  build-depends: base                      >= 4     && < 4.3                , base-unicode-symbols      >= 0.1.1 && < 0.2-               , regions                   == 0.2.*+               , bytestring                == 0.9.*+               , regions                   >= 0.2   && < 0.4                , transformers              >= 0.1.4 && < 0.2                , MonadCatchIO-transformers == 0.0.2.*-               , explicit-iomodes          >= 0.1.5 && < 0.2+               , explicit-iomodes          == 0.2.*   exposed-modules: System.IO.SaferFileHandles++                   Data.ByteString.SaferFileHandles+                   Data.ByteString.Char8.SaferFileHandles+                   Data.ByteString.Lazy.SaferFileHandles+                   Data.ByteString.Lazy.Char8.SaferFileHandles++  other-modules:   System.IO.SaferFileHandles.Internal