Data Streams

Compile using blc my-file-name.bl and run ./out.

#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;
}