Input/Ouput

#import "std/io"

Input and output is handled by generic stream interface containing callbacks for read, write and seek operations. The stream itself can contain any data needed (i.e. memory buffer, handle to file, etc.), generic functionality is handled via virtual table containing pointers to the implementation of all needed (supported) stream API functions.

Example

#import "std/io"

// Custom stream implementation based on std.Stream.
MyStream :: struct #base std.Stream {
    // Preallocated static buffer.
    buffer: [64]u8;
    // Current position in the buffer array.
    position: s64;
}

// Virtual table of the stream setting up stream API functions. Our implementation
// does not support seeking, so the seek function is null.
MY_STRAM_VTABLE :: std.StreamVTable.{
    read  = auto &my_read,
    write = auto &my_write
};

// Actual read function implementation.
my_read :: fn (stream: *MyStream, dest: *u8, bytes_to_read: s64) (s64, Error) {
    using std;
    size := min(stream.position, bytes_to_read);
    stream.position -= size;
    if stream.position < 0 {
        size -= stream.position;
        stream.position = 0;
    }
    if size > 0 {
        memcpy(dest, &stream.buffer[stream.position], auto size);
    }
    return size, OK;
}

// Actual write function implementation.
my_write :: fn (stream: *MyStream, src: *u8, bytes_to_write: s64) (s64, Error) {
    size :: std.min(stream.buffer.len - stream.position, bytes_to_write);
    if size > 0 {
        // size may be zero even in case the buffer is full.
        memcpy(&stream.buffer[stream.position], src, auto size);
        stream.position += size;
    }
    return size, OK;
}

init_stream :: fn (stream: *MyStream) {
    stream.vtable = &MY_STRAM_VTABLE;
    stream.position = 0;
}

main :: fn () s32 {
    using std;

    stream: MyStream #noinit;
    init_stream(&stream);

    // Use of the IO API.
    write_string(&stream, "Hello");
    write_string(&stream, "World");

    str := str_new();
    defer str_delete(&str);

    read_string(&stream, &str);

    print("%\n", str);
    return 0;
}

std.Stream

Stream :: struct {
    vtable: *StreamVTable;
}

File: io.bl

std.StreamVTable

StreamVTable :: struct {
    read: *fn (stream: *Stream, dest: *u8, bytes_to_write: s64) (bytes_read: s64, err: Error
);
    write: *fn (stream: *Stream, src: *u8, bytes_to_read: s64) (bytes: s64, err: Error
);
    seek: *fn (stream: *Stream, locator: StreamLocator, offset: s64) (position: s64, err: Error
);
    flush: *fn (stream: *Stream) Error;
}

File: io.bl

std.StreamLocator

StreamLocator :: enum {
    CURRENT;
    BEGIN;
    END;
}

Stream seek offset locator.

File: io.bl

std.write

write :: fn (stream: *Stream, src: *u8, bytes_to_write: s64) (_0: s64, _1: Error
) #inline

Write bytes_to_write count of bytes from the str into the stream. Returns count of actually written bytes or an error.

File: io.bl

std.write_data

write_data :: fn (stream: *Stream, data: []u8, bytes_to_write :: ) (_0: s64, _1: Error
) #inline

Write the data slice into the stream, the bytes_to_write can be specified to limit count of written bytes. Returns count of actually written bytes or an error.

File: io.bl

std.write_string

write_string :: fn (stream: *Stream, str: string_view, bytes_to_write :: ) (_0: s64, _1: Error
) #inline

Write the data string into the stream, the bytes_to_write can be specified to limit count of written bytes. Returns count of actually written bytes or an error.

File: io.bl

std.read

read :: fn (stream: *Stream, dest: *u8, bytes_to_read: s64) (_0: s64, _1: Error
) #inline

Read bytes_to_read count of bytes from the stream into dest memory. Returns count of actually read bytes or an error.

File: io.bl

std.read_data

read_data :: fn (stream: *Stream, dest: *[..]u8, bytes_to_read : s64: ) (_0: s64, _1: Error
)

Read bytes_to_read count of bytes from the stream into dest dynamic array. Returns count of actually read bytes or an error.

File: io.bl

std.read_string

read_string :: fn (stream: *Stream, dest: *string, bytes_to_read : s64: ) (_0: s64, _1: Error
)

Read bytes_to_read count of bytes from the stream into dest stream. Returns count of actually read bytes or an error.

File: io.bl

std.seek

seek :: fn (stream: *Stream, locator :: , offset : s64: 0) (position: s64, err: Error
)

Set the stream pointer position to the offset value relative to the stream locator. Returns the pointer position or an error.

File: io.bl

std.flush

flush :: fn (stream: *Stream) Error

Flush all buffered stream data.

File: io.bl