Carp/core/IO.carp

130 lines
7.6 KiB
Plaintext
Raw Normal View History

2018-01-24 18:08:18 +03:00
(system-include "carp_io.h")
2018-01-24 17:53:18 +03:00
(register-type FILE)
2017-06-26 12:15:03 +03:00
(defmodule IO
2021-06-08 22:05:51 +03:00
(doc stdin "the standard input file (thin wrapper for the C standard library).")
2019-07-29 22:50:08 +03:00
(register stdin (Ptr FILE) "stdin")
2021-06-08 22:05:51 +03:00
(doc stdout "the standard output file (thin wrapper for the C standard library).")
2019-07-29 22:50:08 +03:00
(register stdout (Ptr FILE) "stdout")
2021-06-08 22:05:51 +03:00
(doc stderr "the standard error file (thin wrapper for the C standard library).")
2019-07-29 22:50:08 +03:00
(register stderr (Ptr FILE) "stderr")
2021-06-08 22:05:51 +03:00
(doc println "prints a string ref to stdout, appends a newline.")
2017-06-26 12:15:03 +03:00
(register println (Fn [(Ref String)] ()))
2021-06-08 22:05:51 +03:00
(doc print "prints a string ref to stdout, does not append a newline.")
2017-06-26 12:15:03 +03:00
(register print (Fn [(Ref String)] ()))
2021-06-08 22:05:51 +03:00
(doc errorln "prints a string ref to stderr, appends a newline.")
2018-10-23 00:47:40 +03:00
(register errorln (Fn [(Ref String)] ()))
2021-06-08 22:05:51 +03:00
(doc error "prints a string ref to stderr, does not append a newline.")
2019-10-28 16:28:37 +03:00
(register error (Fn [(Ref String)] ()))
2021-06-08 22:05:51 +03:00
(doc get-line "gets a line from stdin.")
2017-06-26 12:15:03 +03:00
(register get-line (Fn [] String))
2021-06-08 22:05:51 +03:00
(doc get-char "gets a character from stdin (thin wrapper for getchar() from C standard library).")
2018-03-11 16:53:50 +03:00
(register get-char (Fn [] Char) "getchar")
2021-06-08 22:05:51 +03:00
(doc exit "exit the current program with a return code (thin wrapper for the C standard library).")
(register exit (Fn [Int] ()) "exit")
2021-06-08 22:05:51 +03:00
(doc EOF "the End-Of-File character as a literal (thin wrapper for the C standard library)")
2018-03-23 18:24:32 +03:00
(register EOF Char)
2021-06-08 22:05:51 +03:00
(doc fopen "opens a file for input/output/appending (thin wrapper for fopen(pathname, mode) from C standard library). Consider using the function [`open-file`](#open-file) instead.")
2018-03-18 19:51:23 +03:00
(register fopen (Fn [&String &String] (Ptr FILE)))
2021-06-08 22:05:51 +03:00
(doc open-file "opens a file by name using a mode (e.g. [r]ead, [w]rite, [a]ppend), [rb] read binary...). See fopen() in the C standard library for a detailed description of valid parameters.")
(defn open-file [filename mode]
(let [ptr (IO.fopen filename mode)]
(if (null? ptr)
(do
(Result.Error System.errno))
(Result.Success ptr))))
2021-06-08 22:05:51 +03:00
(doc fclose "closes a file pointer (thin wrapper for the C standard library).")
2018-03-23 18:24:32 +03:00
(register fclose (Fn [(Ptr FILE)] ()))
2021-06-08 22:05:51 +03:00
(doc fgetc "gets a character from a file pointer (thin wrapper for the C standard library).")
2018-03-23 18:24:32 +03:00
(register fgetc (Fn [(Ptr FILE)] Char))
2021-06-08 22:05:51 +03:00
(doc fwrite "writes a C-string to a file and returns the number of written items (thin wrapper for fwrite(cstr, item-size, items-count, file) from C standard library). Consider using [`write-file`](#write-file) instead.")
(register fwrite (Fn [(Ptr CChar) Int Int (Ptr FILE)] Int) "fwrite") ; any reason to use 'a' instead of '(Ptr CChar)' here?
(doc fread "reads from a file into C-String (thin wrapper for fread(cstr, item-size, items-count, file) from C standard library). Consider using [`read-file`](#read-file) or [`unsafe-read-file`](#unsafe-read-file) instead.")
(register fread (Fn [a Int Int (Ptr FILE)] Int) "fread")
2021-06-08 22:05:51 +03:00
(doc fflush "flushes a file pointer, i.e. commits every write (thin wrapper for the C standard library).")
(register fflush (Fn [(Ptr FILE)] ()) "fflush")
2021-06-08 22:05:51 +03:00
(doc rewind "rewinds a file pointer, i.e. puts input and output stream to beginning (thin wrapper for the C standard library).")
(register rewind (Fn [(Ptr FILE)] ()) "rewind")
2021-06-08 22:05:51 +03:00
(doc unlink "unlinks a file, i.e. deletes it (thin wrapper for POSIX api in <unistd.h>).")
2018-10-18 18:22:35 +03:00
(register unlink (Fn [String] ()) "unlink")
2021-06-08 22:05:51 +03:00
(doc fseek "sets the position indicator of a file (thin wrapper for fseek(file, offset, whence) from C standard library).")
2018-10-18 18:22:35 +03:00
(register fseek (Fn [(Ptr FILE) Int Int] ()) "fseek")
2021-06-08 22:05:51 +03:00
(doc ftell "gets the position indicator of a file (thin wrapper for the C standard library).")
2018-10-18 18:22:35 +03:00
(register ftell (Fn [(Ptr FILE)] Int) "ftell")
2021-06-08 22:05:51 +03:00
(doc SEEK-SET "to be used with fseek (thin wrapper for the C standard library).")
2018-10-18 18:22:35 +03:00
(register SEEK-SET Int "SEEK_SET")
2021-06-08 22:05:51 +03:00
(doc SEEK-CUR "to be used with fseek (thin wrapper for the C standard library).")
2018-10-18 18:22:35 +03:00
(register SEEK-CUR Int "SEEK_CUR")
2021-06-08 22:05:51 +03:00
(doc SEEK-END "to be used with fseek (thin wrapper for the C standard library).")
2018-10-18 18:22:35 +03:00
(register SEEK-END Int "SEEK_END")
2018-03-23 18:24:32 +03:00
2021-06-08 22:05:51 +03:00
(doc read->EOF "reads a file given by name until the End-Of-File character is reached.")
2018-03-23 18:24:32 +03:00
(defn read->EOF [filename]
(let [maybe (IO.open-file filename "rb")]
(match maybe
(Result.Error x) (Result.Error x)
(Result.Success f) (let [c (zero)
r []]
(do
(while (do (set! c (IO.fgetc f))
(/= c IO.EOF))
(set! r (Array.push-back r c)))
(IO.fclose f)
(Result.Success (String.from-chars &r)))))))
2020-01-25 16:23:14 +03:00
2021-06-08 22:05:51 +03:00
(doc unsafe-read-file "returns the contents of a file passed as argument as a string. Note: there is no way to distinguish the output for an empty file and a missing file!")
(register unsafe-read-file (Fn [&String] String))
(doc read-file "Reads the content of a file into a (Result String String).\nIt is intended for text files, since the way to determine the length of a String is to use strlen() which probably will be inaccurate for binaries.")
(defn read-file [filename]
(let [ finp? (open-file filename "rb") ]
(if (Result.error? &finp?)
(Result.Error (fmt "Failed to open file='%s', error-number=%d" filename (Result.unsafe-from-error finp?) ))
(let [ finput (Result.unsafe-from-success finp?)
length (do
(fseek finput 0 SEEK-END)
(let-do [ flength (ftell finput) ]
(rewind finput) ; aka (fseek ofile 0 SEEK-SET)
flength ))
buffer (String.allocate length \0 ) ]
(if (not (String.allocated? &buffer))
(do
(fclose finput)
(Result.Error (fmt "Failed to open buffer with size=%d from file='%s'" length filename)) )
(let [ bytes-read (fread (String.cstr &buffer) 1 length finput)
nop1 (fclose finput) ]
(if (not (Int.= bytes-read length))
(Result.Error (fmt "Error: file='%s' has length=%d but bytes-read=%d" filename length bytes-read))
(Result.Success buffer) )))))))
(doc write-file "Writes a string into a (text) file, overwriting it if it already exists.")
(defn write-file [content file-name]
(let [ fOut? (open-file file-name "wb") ; open as binary so line breaks don't multiply on Windows
bytes2write (String.length content) ]
(if (Result.error? &fOut?)
(Result.Error (fmt "error=%d opening file='%s'" (Result.unsafe-from-error fOut?) file-name))
(let-do [ fOut (Result.unsafe-from-success fOut?)
bytes-written (fwrite (String.cstr content) 1 bytes2write fOut) ]
(fclose fOut)
(if (Int.= bytes-written bytes2write)
(Result.Success true)
(Result.Error (fmt "only %d of %d bytes were written" bytes-written bytes2write)) )))))
2020-01-25 16:23:14 +03:00
(private getenv-)
(hidden getenv-)
2021-06-08 22:05:51 +03:00
(doc getenv- "gets the value of an environment variable (thin wrapper for the C standard library)")
2020-05-11 17:10:35 +03:00
(register getenv- (Fn [String] (Ptr CChar)) "getenv")
2021-06-08 22:05:51 +03:00
(doc getenv "gets the value of an environment variable (Carp-style wrapper for the C standard library)")
2020-01-25 16:23:14 +03:00
(defn getenv [s]
(let [e (getenv- s)]
(if (null? e)
(Maybe.Nothing)
(Maybe.Just (from-cstr e)))))
2017-10-20 18:00:47 +03:00
)
(defmacro println* [:rest forms]
`(IO.println %(build-str* forms)))
(defmacro print* [:rest forms]
`(IO.print %(build-str* forms)))