file-io 0.1.0.1 → 0.1.0.2
raw patch · 9 files changed
+298/−258 lines, 9 filesdep +os-stringdep ~filepathPVP ok
version bump matches the API change (PVP)
Dependencies added: os-string
Dependency ranges changed: filepath
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- System/File/Common.hs +0/−82
- System/File/OsPath.hs +81/−11
- System/File/PlatformPath.hs +53/−16
- System/File/Posix.hs +0/−32
- System/File/Windows.hs +0/−111
- file-io.cabal +17/−6
- posix/System/File/Platform.hs +32/−0
- windows/System/File/Platform.hs +111/−0
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for file-io +## 0.1.0.2 -- 2023-12-11++* support `os-string` package and newer `filepath`+ ## 0.1.0.1 -- YYYY-mm-dd * Don't use creat flag when only reading files
− System/File/Common.hs
@@ -1,82 +0,0 @@---- | Like 'openFile', but open the file in binary mode.--- On Windows, reading a file in text mode (which is the default)--- will translate CRLF to LF, and writing will translate LF to CRLF.--- This is usually what you want with text files. With binary files--- this is undesirable; also, as usual under Microsoft operating systems,--- text mode treats control-Z as EOF. Binary mode turns off all special--- treatment of end-of-line and end-of-file characters.--- (See also 'System.IO.hSetBinaryMode'.)---- On POSIX systems, 'openBinaryFile' is an /interruptible operation/ as--- described in "Control.Exception".-openBinaryFile :: FILE_PATH -> IOMode -> IO Handle-openBinaryFile fp iomode = do- h <- openFile fp iomode- hSetBinaryMode h True- pure h---- | Run an action on a file.------ The 'Handle' is automatically closed afther the action.-withFile :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r-withFile fp iomode action = bracket- (openFile fp iomode)- hClose- action--withBinaryFile :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r-withBinaryFile fp iomode action = bracket- (openBinaryFile fp iomode)- hClose- action---- | Run an action on a file.------ The 'Handle' is not automatically closed to allow lazy IO. Use this--- with caution.-withFile'- :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r-withFile' fp iomode action = do- h <- openFile fp iomode- action h--withBinaryFile'- :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r-withBinaryFile' fp iomode action = do- h <- openBinaryFile fp iomode- action h---- | The 'readFile' function reads a file and returns the contents of the file--- as a 'ByteString'. The file is read lazily, on demand.-readFile :: FILE_PATH -> IO BSL.ByteString-readFile fp = withFile' fp ReadMode BSL.hGetContents---- | The 'readFile'' function reads a file and returns the contents of the file--- as a 'ByteString'. The file is fully read before being returned.-readFile'- :: FILE_PATH -> IO BS.ByteString-readFile' fp = withFile fp ReadMode BS.hGetContents---- | The computation 'writeFile' @file str@ function writes the lazy 'ByteString' @str@,--- to the file @file@.-writeFile :: FILE_PATH -> BSL.ByteString -> IO ()-writeFile fp contents = withFile fp WriteMode (`BSL.hPut` contents)---- | The computation 'writeFile' @file str@ function writes the strict 'ByteString' @str@,--- to the file @file@.-writeFile'- :: FILE_PATH -> BS.ByteString -> IO ()-writeFile' fp contents = withFile fp WriteMode (`BS.hPut` contents)---- | The computation 'appendFile' @file str@ function appends the lazy 'ByteString' @str@,--- to the file @file@.-appendFile :: FILE_PATH -> BSL.ByteString -> IO ()-appendFile fp contents = withFile fp AppendMode (`BSL.hPut` contents)---- | The computation 'appendFile' @file str@ function appends the strict 'ByteString' @str@,--- to the file @file@.-appendFile'- :: FILE_PATH -> BS.ByteString -> IO ()-appendFile' fp contents = withFile fp AppendMode (`BS.hPut` contents)-
System/File/OsPath.hs view
@@ -1,14 +1,6 @@-{-# LANGUAGE CPP #-}- module System.File.OsPath where -#if defined(mingw32_HOST_OS) || defined(__MINGW32__)-#define CTOR WS-import qualified System.File.Windows as P-#else-#define CTOR PS-import qualified System.File.Posix as P-#endif+import qualified System.File.Platform as P import Control.Exception (bracket) import System.IO (IOMode(..), Handle, hSetBinaryMode, hClose)@@ -18,8 +10,86 @@ import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL -#define FILE_PATH OsPath-#include "Common.hs"+-- | Like 'openFile', but open the file in binary mode.+-- On Windows, reading a file in text mode (which is the default)+-- will translate CRLF to LF, and writing will translate LF to CRLF.+-- This is usually what you want with text files. With binary files+-- this is undesirable; also, as usual under Microsoft operating systems,+-- text mode treats control-Z as EOF. Binary mode turns off all special+-- treatment of end-of-line and end-of-file characters.+-- (See also 'System.IO.hSetBinaryMode'.)++-- On POSIX systems, 'openBinaryFile' is an /interruptible operation/ as+-- described in "Control.Exception".+openBinaryFile :: OsPath -> IOMode -> IO Handle+openBinaryFile fp iomode = do+ h <- openFile fp iomode+ hSetBinaryMode h True+ pure h++-- | Run an action on a file.+--+-- The 'Handle' is automatically closed afther the action.+withFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r+withFile fp iomode action = bracket+ (openFile fp iomode)+ hClose+ action++withBinaryFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile fp iomode action = bracket+ (openBinaryFile fp iomode)+ hClose+ action++-- | Run an action on a file.+--+-- The 'Handle' is not automatically closed to allow lazy IO. Use this+-- with caution.+withFile'+ :: OsPath -> IOMode -> (Handle -> IO r) -> IO r+withFile' fp iomode action = do+ h <- openFile fp iomode+ action h++withBinaryFile'+ :: OsPath -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile' fp iomode action = do+ h <- openBinaryFile fp iomode+ action h++-- | The 'readFile' function reads a file and returns the contents of the file+-- as a 'ByteString'. The file is read lazily, on demand.+readFile :: OsPath -> IO BSL.ByteString+readFile fp = withFile' fp ReadMode BSL.hGetContents++-- | The 'readFile'' function reads a file and returns the contents of the file+-- as a 'ByteString'. The file is fully read before being returned.+readFile'+ :: OsPath -> IO BS.ByteString+readFile' fp = withFile fp ReadMode BS.hGetContents++-- | The computation 'writeFile' @file str@ function writes the lazy 'ByteString' @str@,+-- to the file @file@.+writeFile :: OsPath -> BSL.ByteString -> IO ()+writeFile fp contents = withFile fp WriteMode (`BSL.hPut` contents)++-- | The computation 'writeFile' @file str@ function writes the strict 'ByteString' @str@,+-- to the file @file@.+writeFile'+ :: OsPath -> BS.ByteString -> IO ()+writeFile' fp contents = withFile fp WriteMode (`BS.hPut` contents)++-- | The computation 'appendFile' @file str@ function appends the lazy 'ByteString' @str@,+-- to the file @file@.+appendFile :: OsPath -> BSL.ByteString -> IO ()+appendFile fp contents = withFile fp AppendMode (`BSL.hPut` contents)++-- | The computation 'appendFile' @file str@ function appends the strict 'ByteString' @str@,+-- to the file @file@.+appendFile'+ :: OsPath -> BS.ByteString -> IO ()+appendFile' fp contents = withFile fp AppendMode (`BS.hPut` contents) -- | Open a file and return the 'Handle'. openFile :: OsPath -> IOMode -> IO Handle
System/File/PlatformPath.hs view
@@ -1,28 +1,65 @@-{-# LANGUAGE CPP #-}- module System.File.PlatformPath where -#if defined(mingw32_HOST_OS) || defined(__MINGW32__)-import qualified System.File.Windows as P-#else-import qualified System.File.Posix as P-#endif -import Control.Exception (bracket)-import System.IO (IOMode(..), Handle, hSetBinaryMode, hClose)+import System.IO (IOMode(..), Handle) import System.OsPath.Types import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL -#define FILE_PATH PlatformPath-#include "Common.hs"+import qualified System.File.OsPath as OsPath+import System.OsString.Internal.Types --- | Open a file and return the 'Handle'.+import Data.Coerce (coerce)++-- | Like `OsPath.openBinaryFile`, but takes a `PlatformPath` instead of an `OsPath`.+openBinaryFile :: PlatformPath -> IOMode -> IO Handle+openBinaryFile = OsPath.openBinaryFile . coerce++-- | Like `OsPath.withFile`, but takes a `PlatformPath` instead of an `OsPath`.+withFile :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r+withFile = OsPath.withFile . coerce++-- | Like `OsPath.withBinaryFile`, but takes a `PlatformPath` instead of an `OsPath`.+withBinaryFile :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile = OsPath.withBinaryFile . coerce++-- | Like `OsPath.withFile'`, but takes a `PlatformPath` instead of an `OsPath`.+withFile' :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r+withFile' = OsPath.withFile' . coerce++-- | Like `OsPath.withBinaryFile'`, but takes a `PlatformPath` instead of an `OsPath`.+withBinaryFile' :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile' = OsPath.withBinaryFile' . coerce++-- | Like `OsPath.readFile`, but takes a `PlatformPath` instead of an `OsPath`.+readFile :: PlatformPath -> IO BSL.ByteString+readFile = OsPath.readFile . coerce++-- | Like `OsPath.readFile'`, but takes a `PlatformPath` instead of an `OsPath`.+readFile' :: PlatformPath -> IO BS.ByteString+readFile' = OsPath.readFile' . coerce++-- | Like `OsPath.writeFile`, but takes a `PlatformPath` instead of an `OsPath`.+writeFile :: PlatformPath -> BSL.ByteString -> IO ()+writeFile = OsPath.writeFile . coerce++-- | Like `OsPath.writeFile'`, but takes a `PlatformPath` instead of an `OsPath`.+writeFile' :: PlatformPath -> BS.ByteString -> IO ()+writeFile' = OsPath.writeFile' . coerce++-- | Like `OsPath.appendFile`, but takes a `PlatformPath` instead of an `OsPath`.+appendFile :: PlatformPath -> BSL.ByteString -> IO ()+appendFile = OsPath.appendFile . coerce++-- | Like `OsPath.appendFile'`, but takes a `PlatformPath` instead of an `OsPath`.+appendFile' :: PlatformPath -> BS.ByteString -> IO ()+appendFile' = OsPath.appendFile' . coerce++-- | Like `OsPath.openFile`, but takes a `PlatformPath` instead of an `OsPath`. openFile :: PlatformPath -> IOMode -> IO Handle-openFile fp = P.openFile fp+openFile = OsPath.openFile . coerce --- | Open an existing file and return the 'Handle'.+-- | Like `OsPath.openExistingFile`, but takes a `PlatformPath` instead of an `OsPath`. openExistingFile :: PlatformPath -> IOMode -> IO Handle-openExistingFile fp = P.openExistingFile fp-+openExistingFile = OsPath.openExistingFile . coerce
− System/File/Posix.hs
@@ -1,32 +0,0 @@-module System.File.Posix where--import System.IO (IOMode(..), Handle)-import System.Posix.IO.PosixString- ( defaultFileFlags,- fdToHandle,- openFd,- OpenFileFlags(noctty, nonBlock, creat, append, trunc),- OpenMode(ReadWrite, ReadOnly, WriteOnly) )-import System.OsPath.Posix ( PosixPath )---- | Open a file and return the 'Handle'.-openFile :: PosixPath -> IOMode -> IO Handle-openFile fp iomode = fdToHandle =<< case iomode of- ReadMode -> open ReadOnly df- WriteMode -> open WriteOnly df { trunc = True, creat = Just 0o666 }- AppendMode -> open WriteOnly df { append = True, creat = Just 0o666 }- ReadWriteMode -> open ReadWrite df { creat = Just 0o666 }- where- open = openFd fp- df = defaultFileFlags { noctty = True, nonBlock = True }---- | Open an existing file and return the 'Handle'.-openExistingFile :: PosixPath -> IOMode -> IO Handle-openExistingFile fp iomode = fdToHandle =<< case iomode of- ReadMode -> open ReadOnly df- WriteMode -> open WriteOnly df { trunc = True }- AppendMode -> open WriteOnly df { append = True }- ReadWriteMode -> open ReadWrite df- where- open = openFd fp- df = defaultFileFlags { noctty = True, nonBlock = True, creat = Nothing }
− System/File/Windows.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE CPP #-}--module System.File.Windows where--import Control.Exception (bracketOnError)-import Data.Bits-import System.IO (IOMode(..), Handle)-import System.OsPath.Windows ( WindowsPath )--import qualified System.Win32 as Win32-import qualified System.Win32.WindowsString.File as WS-import Control.Monad (when, void)-#if defined(__IO_MANAGER_WINIO__)-import GHC.IO.SubSystem-#endif---- | Open a file and return the 'Handle'.-openFile :: WindowsPath -> IOMode -> IO Handle-openFile fp iomode = bracketOnError- (WS.createFile- fp- accessMode- shareMode- Nothing- createMode-#if defined(__IO_MANAGER_WINIO__)- (case ioSubSystem of- IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL- IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED- )-#else- Win32.fILE_ATTRIBUTE_NORMAL-#endif- Nothing)- Win32.closeHandle- toHandle- where- toHandle h = do- when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END- Win32.hANDLEToHandle h- accessMode = case iomode of- ReadMode -> Win32.gENERIC_READ- WriteMode -> Win32.gENERIC_WRITE- AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA- ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE-- createMode = case iomode of- ReadMode -> Win32.oPEN_ALWAYS- WriteMode -> Win32.cREATE_ALWAYS- AppendMode -> Win32.oPEN_ALWAYS- ReadWriteMode -> Win32.oPEN_ALWAYS-- shareMode = case iomode of- ReadMode -> maxShareMode- WriteMode -> writeShareMode- AppendMode -> writeShareMode- ReadWriteMode -> maxShareMode--maxShareMode :: Win32.ShareMode-maxShareMode =- Win32.fILE_SHARE_DELETE .|.- Win32.fILE_SHARE_READ .|.- Win32.fILE_SHARE_WRITE--writeShareMode :: Win32.ShareMode-writeShareMode =- Win32.fILE_SHARE_DELETE .|.- Win32.fILE_SHARE_READ-- -- | Open an existing file and return the 'Handle'.-openExistingFile :: WindowsPath -> IOMode -> IO Handle-openExistingFile fp iomode = bracketOnError- (WS.createFile- fp- accessMode- shareMode- Nothing- createMode-#if defined(__IO_MANAGER_WINIO__)- (case ioSubSystem of- IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL- IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED- )-#else- Win32.fILE_ATTRIBUTE_NORMAL-#endif- Nothing)- Win32.closeHandle- toHandle- where- toHandle h = do- when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END- Win32.hANDLEToHandle h- accessMode = case iomode of- ReadMode -> Win32.gENERIC_READ- WriteMode -> Win32.gENERIC_WRITE- AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA- ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE-- createMode = case iomode of- ReadMode -> Win32.oPEN_EXISTING- WriteMode -> Win32.tRUNCATE_EXISTING- AppendMode -> Win32.oPEN_EXISTING- ReadWriteMode -> Win32.oPEN_EXISTING-- shareMode = case iomode of- ReadMode -> maxShareMode- WriteMode -> writeShareMode- AppendMode -> writeShareMode- ReadWriteMode -> maxShareMode-
file-io.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: file-io-version: 0.1.0.1+version: 0.1.0.2 synopsis: Basic file IO operations via 'OsPath' description: Basic file IO operations like Prelude, but for 'OsPath'. homepage: https://github.com/hasufell/file-io@@ -12,30 +12,41 @@ category: System extra-source-files: CHANGELOG.md- System/File/Common.hs source-repository head type: git location: https://github.com/hasufell/file-io.git +flag os-string+ description: Use the new os-string package+ default: False+ manual: False+ library default-language: Haskell2010 if os(windows)- other-modules: System.File.Windows+ hs-source-dirs: windows build-depends: Win32 >=2.13.3.0 else- other-modules: System.File.Posix+ hs-source-dirs: posix build-depends: unix >=2.8.0.0 + hs-source-dirs: . build-depends:- , base >=4.10 && <4.17+ , base >=4.10 && <5 , bytestring >=0.11.3.0- , filepath >=1.4.100.0 + if flag(os-string)+ build-depends: filepath >= 1.5.0.0, os-string >= 2.0.0+ else+ build-depends: filepath >= 1.4.100.0 && < 1.5.0.0+ exposed-modules: System.File.OsPath System.File.PlatformPath++ other-modules: System.File.Platform ghc-options: -Wall
+ posix/System/File/Platform.hs view
@@ -0,0 +1,32 @@+module System.File.Platform where++import System.IO (IOMode(..), Handle)+import System.Posix.IO.PosixString+ ( defaultFileFlags,+ fdToHandle,+ openFd,+ OpenFileFlags(noctty, nonBlock, creat, append, trunc),+ OpenMode(ReadWrite, ReadOnly, WriteOnly) )+import System.OsPath.Posix ( PosixPath )++-- | Open a file and return the 'Handle'.+openFile :: PosixPath -> IOMode -> IO Handle+openFile fp iomode = fdToHandle =<< case iomode of+ ReadMode -> open ReadOnly df+ WriteMode -> open WriteOnly df { trunc = True, creat = Just 0o666 }+ AppendMode -> open WriteOnly df { append = True, creat = Just 0o666 }+ ReadWriteMode -> open ReadWrite df { creat = Just 0o666 }+ where+ open = openFd fp+ df = defaultFileFlags { noctty = True, nonBlock = True }++-- | Open an existing file and return the 'Handle'.+openExistingFile :: PosixPath -> IOMode -> IO Handle+openExistingFile fp iomode = fdToHandle =<< case iomode of+ ReadMode -> open ReadOnly df+ WriteMode -> open WriteOnly df { trunc = True }+ AppendMode -> open WriteOnly df { append = True }+ ReadWriteMode -> open ReadWrite df+ where+ open = openFd fp+ df = defaultFileFlags { noctty = True, nonBlock = True, creat = Nothing }
+ windows/System/File/Platform.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE CPP #-}++module System.File.Platform where++import Control.Exception (bracketOnError)+import Data.Bits+import System.IO (IOMode(..), Handle)+import System.OsPath.Windows ( WindowsPath )++import qualified System.Win32 as Win32+import qualified System.Win32.WindowsString.File as WS+import Control.Monad (when, void)+#if defined(__IO_MANAGER_WINIO__)+import GHC.IO.SubSystem+#endif++-- | Open a file and return the 'Handle'.+openFile :: WindowsPath -> IOMode -> IO Handle+openFile fp iomode = bracketOnError+ (WS.createFile+ fp+ accessMode+ shareMode+ Nothing+ createMode+#if defined(__IO_MANAGER_WINIO__)+ (case ioSubSystem of+ IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL+ IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED+ )+#else+ Win32.fILE_ATTRIBUTE_NORMAL+#endif+ Nothing)+ Win32.closeHandle+ toHandle+ where+ toHandle h = do+ when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END+ Win32.hANDLEToHandle h+ accessMode = case iomode of+ ReadMode -> Win32.gENERIC_READ+ WriteMode -> Win32.gENERIC_WRITE+ AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA+ ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE++ createMode = case iomode of+ ReadMode -> Win32.oPEN_ALWAYS+ WriteMode -> Win32.cREATE_ALWAYS+ AppendMode -> Win32.oPEN_ALWAYS+ ReadWriteMode -> Win32.oPEN_ALWAYS++ shareMode = case iomode of+ ReadMode -> maxShareMode+ WriteMode -> writeShareMode+ AppendMode -> writeShareMode+ ReadWriteMode -> maxShareMode++maxShareMode :: Win32.ShareMode+maxShareMode =+ Win32.fILE_SHARE_DELETE .|.+ Win32.fILE_SHARE_READ .|.+ Win32.fILE_SHARE_WRITE++writeShareMode :: Win32.ShareMode+writeShareMode =+ Win32.fILE_SHARE_DELETE .|.+ Win32.fILE_SHARE_READ++ -- | Open an existing file and return the 'Handle'.+openExistingFile :: WindowsPath -> IOMode -> IO Handle+openExistingFile fp iomode = bracketOnError+ (WS.createFile+ fp+ accessMode+ shareMode+ Nothing+ createMode+#if defined(__IO_MANAGER_WINIO__)+ (case ioSubSystem of+ IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL+ IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED+ )+#else+ Win32.fILE_ATTRIBUTE_NORMAL+#endif+ Nothing)+ Win32.closeHandle+ toHandle+ where+ toHandle h = do+ when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END+ Win32.hANDLEToHandle h+ accessMode = case iomode of+ ReadMode -> Win32.gENERIC_READ+ WriteMode -> Win32.gENERIC_WRITE+ AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA+ ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE++ createMode = case iomode of+ ReadMode -> Win32.oPEN_EXISTING+ WriteMode -> Win32.tRUNCATE_EXISTING+ AppendMode -> Win32.oPEN_EXISTING+ ReadWriteMode -> Win32.oPEN_EXISTING++ shareMode = case iomode of+ ReadMode -> maxShareMode+ WriteMode -> writeShareMode+ AppendMode -> writeShareMode+ ReadWriteMode -> maxShareMode+