commit bd39ecf5de04e2a1a501dc8af7b01c586abc0b8e
parent 4b68264ddce335f0d43f29c77219a5dad718eb3e
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 24 Feb 2021 12:03:27 -0500
bufio: flesh out bufio::fixed
Diffstat:
4 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/bufio/fixed.ha b/bufio/fixed.ha
@@ -1,21 +1,30 @@
+use bytes;
use io;
-use rt;
+use strings;
-// XXX: All of this is temporary
-export type fixed_stream = struct {
+type fixed_stream = struct {
stream: io::stream,
buf: []u8,
};
-export fn fixed(in: []u8) *io::stream = {
+// Creates an [io::stream] for a fixed, caller-supplied buffer. Supports either
+// read or write, but not both.
+export fn fixed(in: []u8, mode: io::mode) *io::stream = {
let s = alloc(fixed_stream {
stream = io::stream {
name = "<bufio::fixed>",
- reader = &fixed_read,
...
},
buf = in,
});
+ if (mode & io::mode::READ == io::mode::READ) {
+ assert(mode & io::mode::WRITE != io::mode::WRITE);
+ s.stream.reader = &fixed_read;
+ };
+ if (mode & io::mode::WRITE == io::mode::WRITE) {
+ assert(mode & io::mode::READ != io::mode::READ);
+ s.stream.writer = &fixed_write;
+ };
return &s.stream;
};
@@ -29,3 +38,24 @@ fn fixed_read(s: *io::stream, buf: []u8) (size | io::error | io::EOF) = {
stream.buf = stream.buf[n..];
return n;
};
+
+fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = {
+ let stream = s: *fixed_stream;
+ if (len(stream.buf) == 0) {
+ return 0z;
+ };
+ const n = if (len(buf) > len(stream.buf)) len(stream.buf) else len(buf);
+ stream.buf[..n] = buf[..n];
+ stream.buf = stream.buf[n..];
+ return n;
+};
+
+@test fn fixed() void = {
+ // TODO: add a read test too
+ static let buf: [1024]u8 = [0...];
+ let stream = fixed(buf, io::mode::WRITE);
+ let n = 0z;
+ n += io::write(stream, strings::to_utf8("hello ")) as size;
+ n += io::write(stream, strings::to_utf8("world")) as size;
+ assert(bytes::equal(buf[..n], strings::to_utf8("hello world")));
+};
diff --git a/fs/fs.ha b/fs/fs.ha
@@ -16,7 +16,7 @@ export fn open(fs: *fs, path: path, mode: io::mode) (*io::stream | error) = {
};
};
-// Creates a new file.
+// Creates a new file. The default file permissions are implementation defined.
export fn create(fs: *fs, path: path, mode: io::mode) (*io::stream | error) = {
return match (fs.create) {
null => io::unsupported,
diff --git a/hare/lex/+test.ha b/hare/lex/+test.ha
@@ -1,10 +1,12 @@
use bufio;
use fmt;
use io;
+use io::{mode};
use strings;
@test fn unget() void = {
- let lexer = lexer_init(bufio::fixed(strings::to_utf8("z")), "<test>");
+ let buf = bufio::fixed(strings::to_utf8("z"), mode::READ);
+ let lexer = lexer_init(buf, "<test>");
unget(&lexer, 'x');
unget(&lexer, 'y');
assert(next(&lexer) as rune == 'y');
@@ -55,7 +57,8 @@ fn liteq(expected: literal, actual: literal) bool = {
};
fn lextest(in: str, expected: [](uint, uint, token)) void = {
- let lexer = lexer_init(bufio::fixed(strings::to_utf8(in)), "<test>");
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
+ let lexer = lexer_init(buf, "<test>");
for (let i = 0z; i < len(expected); i += 1) {
let eline = expected[i].0, ecol = expected[i].1,
etok = expected[i].2;
@@ -189,7 +192,8 @@ fn lextest(in: str, expected: [](uint, uint, token)) void = {
let keywords = bmap[..btoken::LAST_KEYWORD+1];
for (let i = 0z; i < len(keywords); i += 1) {
let lexer = lexer_init(bufio::fixed(
- strings::to_utf8(keywords[i])), "<test>");
+ strings::to_utf8(keywords[i]), mode::READ),
+ "<test>");
let tl = match (lex(&lexer)) {
tl: (token, location) => tl,
* => abort(),
diff --git a/hare/parse/+test.ha b/hare/parse/+test.ha
@@ -1,13 +1,14 @@
use bufio;
+use fmt;
use hare::ast;
use hare::lex;
+use io::{mode};
use strings;
-use fmt;
@test fn ident() void = {
{
const in = "foo";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let ident = ident(&lexer) as ast::ident;
defer ast::ident_free(ident);
@@ -18,7 +19,7 @@ use fmt;
{
const in = "foo::bar";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let ident = ident(&lexer) as ast::ident;
defer ast::ident_free(ident);
@@ -29,7 +30,7 @@ use fmt;
{
const in = "foo::bar::baz";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let ident = ident(&lexer) as ast::ident;
defer ast::ident_free(ident);
@@ -41,7 +42,7 @@ use fmt;
{
const in = "foo::bar;";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let ident = ident(&lexer) as ast::ident;
defer ast::ident_free(ident);
@@ -55,7 +56,7 @@ use fmt;
@test fn imports() void = {
{
const in = "use foo;";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let mods = imports(&lexer) as []ast::import;
defer for (let i = 0z; i < len(mods); i += 1) {
@@ -76,7 +77,7 @@ use fmt;
"use bar;\n"
"use baz::bat;\n\n"
"export fn main() void = void;";
- let buf = bufio::fixed(strings::to_utf8(in));
+ let buf = bufio::fixed(strings::to_utf8(in), mode::READ);
let lexer = lex::lexer_init(buf, "<test>");
let mods = imports(&lexer) as []ast::import;
defer for (let i = 0z; i < len(mods); i += 1) {