Whole-file byte and UTF-8 text operations built on the platform C stdio library.


File model


Platform errno

For loadFile and saveFile, add the target platform's standard-library directory to the compiler include path and preload its errno module at global level. On Linux, use -I path/to/mpl-sl -I path/to/mpl-sl/linux with "errno" use (or "linux/errno" use). Use the corresponding macos or windows directory/module for those targets. An include path alone does not satisfy the global-preload requirement. Without the preload the compiler reports File «errno.mpl» was not initially loaded at the global level at the first loadFile or saveFile call.


Imported C functions

Stream/buffer/string addresses and fread/fwrite sizes, counts, and results are Natx. Other declared results, offsets, origins, and error numbers are Int32. Stream and buffer pointers are borrowed caller-owned storage; returned stream pointers remain valid until the corresponding close operation.

fclose

(stream -- result) Closes a stream and returns the C Int32 result.
  • Returns zero on success and a nonzero result on failure. The stream is no longer usable after the call; callers must not retry with the same stream.

ferror

(stream -- result) Returns the C Int32 error indicator for a stream.
  • Returns zero when no error indicator is set and nonzero otherwise. This is not an errno value.

fflush

(stream -- result) Flushes a stream and returns the C Int32 result.
  • Returns zero on success and a nonzero result on failure.

fopen

(mode filename -- stream) Opens the zero-terminated mode and filename strings and returns a stream pointer.
  • The filename and mode are zero-terminated strings. Returns address zero on failure; otherwise the caller must eventually close the returned stream.

fread

(stream count size buffer -- items) Reads count items of size bytes into buffer and returns the item count.
  • Returns complete items transferred, not bytes. A smaller count can indicate EOF or an error for reading; inspect the error indicator. The buffer must cover the requested byte range.

fseek

(origin offset stream -- result) Moves the stream position by the Int32 offset from the Int32 origin.
  • Returns zero on success; a nonzero result reports failure, subject to the current binding's width limitation.

Known issue: the current bindings declare fseek's offset and ftell's result as Int32. On 64-bit Linux, negative offsets are not passed correctly to the native long parameter, and large positions are truncated; restrict these bindings to verified nonnegative offsets and positions in the Int32 range; they are not a portable large-file interface.

ftell

(stream -- position) Returns the current stream position as Int32.
  • Returns a position or -1 on error, subject to the current binding's width limitation.

See the fseek known-issue note for the shared width limitation.

fwrite

(stream count size buffer -- items) Writes count items of size bytes from buffer and returns the item count.
  • Returns complete items written, not bytes. With a nonzero item size, writing fewer than requested indicates a write failure; inspect ferror. A zero-size transfer writes nothing. The source buffer must cover the requested byte range.

strerror

(errnum -- message) Returns a borrowed, non-writable pointer to the platform text for an Int32 error number; its validity follows the platform error-text storage.

SEEK_SET

(-- origin) Pushes the Int32 origin constant 0.

SEEK_CUR

(-- origin) Pushes the Int32 origin constant 1.

SEEK_END

(-- origin) Pushes the Int32 origin constant 2.

Whole-file helpers

getErrnoText

(errnum -- textView) Returns an immutable, non-owning StringView for the supplied platform error number.
  • The view is valid while the platform error-text storage remains valid; it does not own the text.

loadFile

(name -- record) Loads one whole file into a byte-array record.
  • record.result is an error String, empty on success; record.data is the Nat8 Array of bytes read, owned by the record.
  • Open failures from loadFile and saveFile use fopen failed, plus the platform errno text.
  • On failure, discard record.data. Its size can reflect the planned allocation rather than the bytes read; contents beyond the successful read are not valid file data.

saveFile

(data name -- result) Saves a contiguous byte source to one file and returns an error String.
  • saveFile expects a contiguous source whose size is a byte count and whose data exposes a reference to at least that many bytes. A numeric address alone is not the data reference expected here. A Nat8 Array, a String, or a StringView fits this contract; an Array of wider elements needs an explicit byte view/count.
  • File-name inputs are converted to zero-terminated strings. An embedded zero terminates the path; the suffix is not part of the file name. These binary-mode helpers write the source bytes without UTF-8 validation or newline conversion; a Text literal is not a valid data source, so convert it with toString or makeStringView first.
  • An empty result means the open and fwrite checks passed; it does not guarantee a complete write. See the Limits of the whole-file helpers.

loadString

(name -- record) Loads one whole file into a record containing success and a String.
  • record.success is FALSE if open, seek, read, or close fails. record.data is the loaded, owned String. On failure, discard record.data; its reported size can include bytes not read from the file.
  • Bytes are stored without UTF-8 validation. See the Limits of the whole-file helpers.

saveString

(name text -- success) Replaces a file with the bytes of text and returns a Cond.
  • The result is TRUE only when opening, writing or empty-write handling, flushing, and closing succeed.

appendString

(name text -- success) Appends the bytes of text to a file and returns a Cond.
  • The result is TRUE only when opening, writing or empty-write handling, flushing, and closing succeed.

Limits of the whole-file helpers

Known issue: A failed loadFile or saveFile transfer after opening leaves the stream open; use the raw bindings with explicit cleanup.


Examples

Compile-time example: signature-level result schemas

"control" use
"file"    use

{} () {} [
  "sample.txt" "alpha" saveString printStack _:;
  "sample.txt" loadString.success printStack _:;
  "sample.txt" loadString.data.size printStack _:;
  "sample.txt" "beta" appendString printStack _:;
] "main" exportFunction

Expected Output During Compilation

Cond
Cond Cref
Int32
Cond

Runtime example: String helpers

"String"  use
"control" use
"file"    use

{} Int32 {} [
  ["sample.txt" "alpha" saveString] "save failed" ensure
  ["sample.txt" "beta" appendString] "append failed" ensure
  loaded: "sample.txt" loadString;
  [loaded.success] "load failed" ensure
  loaded.data print
  0
] "main" exportFunction

Expected Output

alphabeta

Runtime example: loadFile and saveFile

"Array"       use
"String"      use
"control"     use
"file"        use
"linux/errno" use

{} Int32 {} [
  bytes: Nat8 Array;
  104n8 @bytes.append 105n8 @bytes.append
  saved: bytes "probe.bin" saveFile;
  loaded: "probe.bin" loadFile;
  missing: "no-such-file.bin" loadFile;
  ("save result=[" saved "]" LF) printList
  ("load result=[" loaded.result "] size=" loaded.data.size LF) printList
  ("missing result=[" missing.result "] size=" missing.data.size LF) printList
  0
] "main" exportFunction

Expected Output

save result=[]
load result=[] size=2
missing result=[fopen failed, No such file or directory] size=0

See also