added standard input reader for onyx and wasi
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 1 Dec 2021 17:50:25 +0000 (11:50 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 1 Dec 2021 17:50:25 +0000 (11:50 -0600)
core/io/reader.onyx
core/runtime/js.onyx
core/runtime/wasi.onyx
core/stdio.onyx
tests/aoc-2021/day01
tests/aoc-2021/day01.onyx

index 3f14df9dc608f0bd77d23730660dbbf8525d4c15..800313d5ba6c5a2b5a9c08073e4ddf251face549 100644 (file)
@@ -218,10 +218,12 @@ read_u64 :: (use reader: ^Reader) -> u64 {
     return n;
 }
 
-read_line :: (use reader: ^Reader, consume_newline := true, allocator := context.allocator) -> str {
+read_line :: (use reader: ^Reader, consume_newline := true, allocator := context.allocator, inplace := false) -> str {
     reader_read_next_chunk(reader);
 
     count := start;
+    defer start = count;
+
     while count < end && buffer[count] != #char "\n" {
         count += 1;
     }
@@ -230,21 +232,23 @@ read_line :: (use reader: ^Reader, consume_newline := true, allocator := context
         count += 1;
     }
 
+    if inplace do return buffer[start .. count];
+
     out := str.{
         data  = raw_alloc(allocator, count * sizeof(u8)),
         count = count - start,
     };
 
     memory.copy(out.data, buffer.data + start, count - start);
-    start = count;
     return out;
 }
 
-read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := context.allocator) -> str {
+read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := context.allocator, inplace := false) -> str {
     skip_whitespace(reader);
     reader_read_next_chunk(reader);
 
     count := start;
+    defer start = count;
     while count < end {
         curr := buffer[count];
         if     (curr >= #char "a" && curr <= #char "z")
@@ -258,20 +262,22 @@ read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := contex
         }
     }
 
+    if inplace do return buffer[start .. count];
+
     out := str.{
         data  = raw_alloc(allocator, count * sizeof(u8)),
         count = count - start,
     };
 
     memory.copy(out.data, buffer.data + start, count - start);
-    start = count;
     return out;
 }
 
-read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false) -> str {
+read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false, inplace := false) -> str {
     reader_read_next_chunk(reader);
 
     count := start;
+    defer start = count;
     while count < end {
         curr := buffer[count];
         if curr != until {
@@ -284,13 +290,14 @@ read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := conte
 
     if consume_end && count < end do count += 1;
 
+    if inplace do return buffer[start .. count];
+
     out := str.{
         data  = raw_alloc(allocator, count * sizeof(u8)),
         count = count - start,
     };
 
     memory.copy(out.data, buffer.data + start, count - start);
-    start = count;
     return out;
 }
 
index be24ba77f52cdb138713fc43e08e2f7f3e09e4de..3be872791aaf76924f677870d60b5b3e4dd23628 100644 (file)
@@ -4,8 +4,9 @@ package runtime
 
 use package core
 
-__output_string :: (s: str)      -> u32  #foreign "host" "print_str" ---
-__exit          :: (status: i32) -> void #foreign "host" "exit" ---
+__output_string   :: (s: str)      -> u32  #foreign "host" "print_str" ---
+__exit            :: (status: i32) -> void #foreign "host" "exit" ---
+__read_from_input :: (buf: [] u8)  -> u32 do return 0;
 
 // The builtin _start proc.
 // Sets up everything needed for execution.
index 16deca74f00eb3a61e0b019afcfcb52cbfaf079f..417035dec87dc6a1584c8e6a73cb5204399bfe96 100644 (file)
@@ -18,6 +18,18 @@ __output_string :: (s: str) -> u32 {
 
 __exit :: (status: i32) do proc_exit(status);
 
+__read_from_input :: (buffer: [] u8) -> i32 {
+    STDIN_FILENO :: 0
+
+    vec := IOVec.{ buf = cast(i32) buffer.data, len = buffer.count };
+    read: Size;
+    error := fd_read(STDIN_FILENO, .{ cast(i32) ^vec, 1 }, ^read);
+    if error != .Success do return -1;
+
+    return read;
+}
+
+
 // The builtin _start proc.
 // Sets up everything needed for execution.
 #export "_start" () {
index 1b611fbd7636ec37c6863207bce6a30ddfbe97ac..edc821408752b704d35801d64cb4672a863204d5 100644 (file)
@@ -108,6 +108,10 @@ byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) {
 __stdio_init :: () {
     stdio.print_stream = io.dynamic_string_stream_make(2048, context.allocator);
     stdio.print_writer = io.writer_make(^stdio.print_stream);
+    
+    // This shouldn't need to be here, but because ^stdin_vtable is not a compile-time
+    // known value (even through it should be).
+    stdin.vtable = ^stdin_vtable;
 }
 
 
@@ -121,3 +125,21 @@ __flush_stdio :: () {
     ^stdio.print_stream |> io.stream_flush();
 }
 
+#local stdin_vtable := io.Stream_Vtable.{
+    read = (_: ^io.Stream, buffer: [] u8) -> (io.Error, u32) {
+        bytes_read := runtime.__read_from_input(buffer);
+        if bytes_read <= 0 do return .EOF, 0;
+
+        return .None, bytes_read;
+    },
+
+    read_byte = (_: ^io.Stream) -> (io.Error, u8) {
+        buf: [1] u8;
+        bytes_read := runtime.__read_from_input(buf);
+        if bytes_read <= 0 do return .EOF, 0;
+
+        return .None, buf[0];
+    }
+}
+
+stdin: io.Stream;
\ No newline at end of file
index 6ba240298eb687d84788e0e1fcdfac5d4c75a72b..5021ac25faeee36299010fee78c48e9c8da07c3c 100644 (file)
@@ -1 +1,2 @@
+Part 1: 1564
 Part 2: 1611
index 9fe6f54561daed9c544f7878f0fde0e827f68a91..d1de70f92a6a371f3ff621f77e8e61680871d384 100644 (file)
@@ -1,5 +1,3 @@
-PART :: 2
-
 #load "core/std"
 
 use package core
@@ -33,12 +31,12 @@ main :: (args) => {
         io.skip_whitespace(^reader);
     }
 
-    #if PART == 1 {
+    { // Part 1
         increased_count := count_increasing(nums);
         printf("Part 1: {}\n", increased_count);
     }
 
-    #if PART == 2 {
+    { // Part 2
         windows := array.make(i32);
         for i: range.{ 0, nums.count - 2 } {
             sum := 0;
@@ -49,4 +47,4 @@ main :: (args) => {
         increased_count := count_increasing(windows);
         printf("Part 2: {}\n", increased_count);
     }
-}
\ No newline at end of file
+}