2019-06-15 13:54:22 +03:00
|
|
|
module System.File
|
|
|
|
|
|
|
|
import Data.List
|
|
|
|
import Data.Strings
|
|
|
|
|
|
|
|
public export
|
|
|
|
data Mode = Read | WriteTruncate | Append | ReadWrite | ReadWriteTruncate | ReadAppend
|
|
|
|
|
|
|
|
public export
|
|
|
|
data FilePtr : Type where
|
|
|
|
|
|
|
|
%extern prim__open : String -> String -> Int ->
|
|
|
|
(1 x : %World) -> IORes (Either Int FilePtr)
|
|
|
|
%extern prim__close : FilePtr -> (1 x : %World) -> IORes ()
|
|
|
|
%extern prim__readLine : FilePtr -> (1 x : %World) -> IORes (Either Int String)
|
|
|
|
%extern prim__writeLine : FilePtr -> String -> (1 x : %World) -> IORes (Either Int ())
|
|
|
|
%extern prim__eof : FilePtr -> (1 x : %World) -> IORes Int
|
|
|
|
|
2020-03-30 15:06:59 +03:00
|
|
|
%extern prim__fileModifiedTime : FilePtr -> (1 x : %World) ->
|
|
|
|
IORes (Either Int Integer)
|
|
|
|
|
2019-06-30 17:50:58 +03:00
|
|
|
%extern prim__stdin : FilePtr
|
|
|
|
%extern prim__stdout : FilePtr
|
|
|
|
%extern prim__stderr : FilePtr
|
|
|
|
|
2019-06-15 13:54:22 +03:00
|
|
|
modeStr : Mode -> String
|
|
|
|
modeStr Read = "r"
|
|
|
|
modeStr WriteTruncate = "w"
|
|
|
|
modeStr Append = "a"
|
|
|
|
modeStr ReadWrite = "r+"
|
|
|
|
modeStr ReadWriteTruncate = "w+"
|
|
|
|
modeStr ReadAppend = "a+"
|
|
|
|
|
|
|
|
public export
|
|
|
|
data FileError = GenericFileError Int -- errno
|
|
|
|
| FileReadError
|
|
|
|
| FileWriteError
|
|
|
|
| FileNotFound
|
|
|
|
| PermissionDenied
|
2019-09-28 20:10:14 +03:00
|
|
|
| FileExists
|
2019-06-15 13:54:22 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
Show FileError where
|
2019-09-28 20:10:14 +03:00
|
|
|
show (GenericFileError errno) = "File error: " ++ show errno
|
2019-06-15 13:54:22 +03:00
|
|
|
show FileReadError = "File Read Error"
|
|
|
|
show FileWriteError = "File Write Error"
|
|
|
|
show FileNotFound = "File Not Found"
|
|
|
|
show PermissionDenied = "Permission Denied"
|
2019-09-28 20:10:14 +03:00
|
|
|
show FileExists = "File Exists"
|
2019-06-15 13:54:22 +03:00
|
|
|
|
|
|
|
toFileError : Int -> FileError
|
|
|
|
toFileError 1 = FileReadError
|
|
|
|
toFileError 2 = FileWriteError
|
|
|
|
toFileError 3 = FileNotFound
|
|
|
|
toFileError 4 = PermissionDenied
|
2020-04-23 03:28:54 +03:00
|
|
|
toFileError 5 = FileExists
|
2019-09-28 20:10:14 +03:00
|
|
|
toFileError x = GenericFileError (x - 256)
|
2019-06-15 13:54:22 +03:00
|
|
|
|
|
|
|
fpure : Either Int a -> IO (Either FileError a)
|
|
|
|
fpure (Left err) = pure (Left (toFileError err))
|
|
|
|
fpure (Right x) = pure (Right x)
|
|
|
|
|
|
|
|
public export
|
|
|
|
data FileT : Bool -> Type where
|
|
|
|
FHandle : FilePtr -> FileT bin
|
|
|
|
|
|
|
|
public export
|
|
|
|
File : Type
|
|
|
|
File = FileT False
|
|
|
|
|
|
|
|
public export
|
|
|
|
BinaryFile : Type
|
|
|
|
BinaryFile = FileT True
|
|
|
|
|
2019-06-30 17:50:58 +03:00
|
|
|
export
|
|
|
|
stdin : File
|
|
|
|
stdin = FHandle prim__stdin
|
|
|
|
|
|
|
|
export
|
|
|
|
stdout : File
|
|
|
|
stdout = FHandle prim__stdout
|
|
|
|
|
|
|
|
export
|
|
|
|
stderr : File
|
|
|
|
stderr = FHandle prim__stderr
|
|
|
|
|
2019-06-15 13:54:22 +03:00
|
|
|
export
|
|
|
|
openFile : String -> Mode -> IO (Either FileError File)
|
2019-10-26 00:24:25 +03:00
|
|
|
openFile f m
|
2019-06-15 13:54:22 +03:00
|
|
|
= do res <- primIO (prim__open f (modeStr m) 0)
|
|
|
|
fpure (map FHandle res)
|
|
|
|
|
|
|
|
export
|
|
|
|
openBinaryFile : String -> Mode -> IO (Either FileError BinaryFile)
|
2019-10-26 00:24:25 +03:00
|
|
|
openBinaryFile f m
|
2019-06-15 13:54:22 +03:00
|
|
|
= do res <- primIO (prim__open f (modeStr m) 1)
|
|
|
|
fpure (map FHandle res)
|
|
|
|
|
|
|
|
export
|
|
|
|
closeFile : FileT t -> IO ()
|
|
|
|
closeFile (FHandle f) = primIO (prim__close f)
|
|
|
|
|
|
|
|
export
|
|
|
|
fGetLine : (h : File) -> IO (Either FileError String)
|
2019-10-26 00:24:25 +03:00
|
|
|
fGetLine (FHandle f)
|
2019-06-15 13:54:22 +03:00
|
|
|
= do res <- primIO (prim__readLine f)
|
|
|
|
fpure res
|
|
|
|
|
|
|
|
export
|
|
|
|
fPutStr : (h : File) -> String -> IO (Either FileError ())
|
|
|
|
fPutStr (FHandle f) str
|
|
|
|
= do res <- primIO (prim__writeLine f str)
|
|
|
|
fpure res
|
|
|
|
|
|
|
|
export
|
|
|
|
fPutStrLn : (h : File) -> String -> IO (Either FileError ())
|
2019-10-26 00:24:25 +03:00
|
|
|
fPutStrLn f str = fPutStr f (str ++ "\n")
|
2019-06-15 13:54:22 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
fEOF : (h : File) -> IO Bool
|
|
|
|
fEOF (FHandle f)
|
|
|
|
= do res <- primIO (prim__eof f)
|
|
|
|
pure (res /= 0)
|
2019-10-26 00:24:25 +03:00
|
|
|
|
2020-03-30 15:06:59 +03:00
|
|
|
export
|
|
|
|
fileModifiedTime : (h : File) -> IO (Either FileError Integer)
|
|
|
|
fileModifiedTime (FHandle f)
|
|
|
|
= do res <- primIO (prim__fileModifiedTime f)
|
|
|
|
fpure res
|
|
|
|
|
2019-06-15 13:54:22 +03:00
|
|
|
export
|
|
|
|
readFile : String -> IO (Either FileError String)
|
|
|
|
readFile file
|
|
|
|
= do Right h <- openFile file Read
|
|
|
|
| Left err => pure (Left err)
|
|
|
|
Right content <- read [] h
|
|
|
|
| Left err => do closeFile h
|
|
|
|
pure (Left err)
|
|
|
|
closeFile h
|
|
|
|
pure (Right (fastAppend content))
|
|
|
|
where
|
|
|
|
read : List String -> File -> IO (Either FileError (List String))
|
|
|
|
read acc h
|
|
|
|
= do eof <- fEOF h
|
|
|
|
if eof
|
|
|
|
then pure (Right (reverse acc))
|
|
|
|
else
|
|
|
|
do Right str <- fGetLine h
|
|
|
|
| Left err => pure (Left err)
|
2020-05-04 23:05:51 +03:00
|
|
|
read ((str ++ "\n") :: acc) h
|
2020-03-30 15:06:59 +03:00
|
|
|
|
|
|
|
||| Write a string to a file
|
|
|
|
export
|
|
|
|
writeFile : (filepath : String) -> (contents : String) ->
|
|
|
|
IO (Either FileError ())
|
|
|
|
writeFile fn contents = do
|
|
|
|
Right h <- openFile fn WriteTruncate
|
|
|
|
| Left err => pure (Left err)
|
|
|
|
Right () <- fPutStr h contents
|
|
|
|
| Left err => do closeFile h
|
|
|
|
pure (Left err)
|
|
|
|
closeFile h
|
|
|
|
pure (Right ())
|