Eigenstate : libbio

Myrddin's BIO library is used for buffered input and output. It is a fairly simple library that handles reading and writing from file descriptors. Support for reading and writing from any abstract source as a byte stream is planned, but not yet implemented.

API reference.

    pkg bio =
            type mode

            const Rd
            const Wr
            const Rw

            type file

            /* creation */
            const mkfile    : (fd : std.fd, mode : mode     -> file#)
            const open      : (path : byte[:], mode : mode  -> std.option(file#))
            const create    : (path : byte[:], mode : mode, perm : int      -> std.option(file#))
            const close     : (f : file# -> bool)

            /* basic i/o. Returns sub-buffer when applicable. */
            const write     : (f : file#, src : byte[:]     -> std.size)
            const read      : (f : file#, dst : byte[:]     -> std.option(byte[:]))
            const flush     : (f : file# -> bool)

            /* seeking */

            /* single unit operations */
            const putb      : (f : file#, b : byte  -> std.size)
            const putc      : (f : file#, c : char  -> std.size)
            const getb      : (f : file# -> std.option(byte))
            const getc      : (f : file# -> std.option(char))

            /* typed binary reads */
            generic putbe   : (f : file#, v : @a::(numeric,integral) -> std.size)
            generic putle   : (f : file#, v : @a::(numeric,integral) -> std.size)
            generic getbe   : (f : file# -> std.option(@a::(numeric,integral)))
            generic getle   : (f : file# -> std.option(@a::(numeric,integral)))

            /* peeking */
            const peekb     : (f : file# -> std.option(byte))
            const peekc     : (f : file# -> std.option(char))

            /* delimited read; returns freshly allocated buffer. */
            const readln    : (f : file#    -> std.option(byte[:]))
            const readto    : (f : file#, delim : byte[:]   -> std.option(byte[:]))
            const skipto    : (f : file#, delim : byte[:]   -> bool)

            /* formatted i/o */
            const put       : (f : file#, fmt : byte[:], args : ... -> std.size)
    ;;

For all of these functions, the output buffer is not automatically flushed, and might not touch the output stream until the file is either explicitly closed or flushed. The output buffers are not automatically flushed on program exit.

The mode type describes the input/output mode of the file. Rd means that the file is in read only mode. Wr means that it is in write only mode. Rw means that the file can be both read and write, and is equivalent to Rd|Wr.

mkfile creates a file from any FD, with the given mode requested. It does not check the mode, but assumes that it was correct.

open opens the file, returning an error if it does not yet exist. create is identical to open, however, it will create the file if it does not exist. It does not create the directory path.

close flushes the file, closes the file descriptor, and frees any resources associated with the FD.

write writes from the buffer src to a file descriptor, returning the number of bytes written. It will try to write all the bytes to the FD in one go, if it can.

read will read from the file f into the provided buffer dst, returning the slice of the buffer that was actually written to.

flush clears any output that has accumulated in the output buffer but has not yet been written. It is a no-op on read-only streams.

putb and getb will read and write a single byte to a buffered file returning the number of bytes written, or \std.Some byte` , respectively.

putc and getc are similar to putc and getc, however they will encode or decode the byte on I/O.

putbe and putle will write a single integer like value to the output file in big or little endian format. getbe and getle will do the converse operation.

peekb will return the next byte that will be read from the input buffer, reading from the file to get it if needed. It will not consume the byte. peekc will do the same thing for a single utf8 character.

readto will read to the next instance of the provided delimiter, allocating a buffer to return the line in with std.slalloc. The buffer must be freed after use with std.slfree. The delimiter is not included in the returned value, but it is consumed. skipto is similar, however, the input is discarded instead of being returned. readln is identical to readto, however, the delimiter is hard coded to \n.

put outputs formatted text similar to std.put, and sharing the same format specifiers.

Examples

The example below is the simplest program that creates and opens a file, and writes to it. It creates it with 0o644 permissions (ie, rw-r--r--), and then immediately closes it. The result of this program should be a file called create-example containing the words.

The next example shows reading from a file called "lines", line by line. It should echo the lines, numbering them as it prints them: