From 5c46b0c2a09f89168f606cba7df763a77d7cd192 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 26 Mar 2025 18:19:19 +0100 Subject: [PATCH] Add @each_row for the csv module. --- lib/std/encoding/csv.c3 | 18 ++++++++++++------ test/unit/stdlib/encoding/csv.c3 | 31 ++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/lib/std/encoding/csv.c3 b/lib/std/encoding/csv.c3 index 7a7273968..3104208b2 100644 --- a/lib/std/encoding/csv.c3 +++ b/lib/std/encoding/csv.c3 @@ -69,13 +69,11 @@ fn void? CsvReader.skip_row(self) @maydiscard => @pool() (void)io::treadline(self.stream); } -macro void? CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) @maydiscard +macro void? @each_row(InStream stream, String separator = ",", int max_rows = int.max; @body(String[] row)) @maydiscard { - InStream stream = self.stream; - String sep = self.separator; - while (rows--) + while (max_rows--) { - @stack_mem(512; Allocator mem) + @stack_mem(512; mem) { String? s = io::readline(mem, stream); if (catch err = s) @@ -83,7 +81,15 @@ macro void? CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) @ if (err == io::EOF) return; return err?; } - @body(s.split(mem, sep)); + @body(s.split(mem, separator)); }; } +} + +macro void? CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) @maydiscard +{ + return @each_row(self.stream, self.separator, rows; row) + { + @body(row); + }; } \ No newline at end of file diff --git a/test/unit/stdlib/encoding/csv.c3 b/test/unit/stdlib/encoding/csv.c3 index 504804101..e3d9f500f 100644 --- a/test/unit/stdlib/encoding/csv.c3 +++ b/test/unit/stdlib/encoding/csv.c3 @@ -2,7 +2,8 @@ module csv_test @test; import std::encoding::csv; import std::io; -struct TestCase { +struct TestCase +{ String input; String[] want; String sep; @@ -32,17 +33,33 @@ fn void csv_each_row() "," }, }; - foreach (t : tests) { + foreach (t : tests) + { String[] want = t.want; CsvReader r; r.init((ByteReader){}.init(t.input), t.sep); r.@each_row(; String[] row) { - foreach (i, s : row) { - assert(want.len > 0, - "more records than we want"); - assert(s == want[0], "columns do not match; " - "got: '%s', want: '%s'", s, want[0]); + foreach (i, s : row) + { + assert(want.len > 0, "more records than we want"); + assert(s == want[0], "columns do not match; got: '%s', want: '%s'", s, want[0]); + want = want[1..]; + } + }; + assert(want.len == 0, "not enough records found"); + } + foreach (t : tests) + { + String[] want = t.want; + CsvReader r; + + csv::@each_row((ByteReader){}.init(t.input), t.sep; String[] row) + { + foreach (i, s : row) + { + assert(want.len > 0, "more records than we want"); + assert(s == want[0], "columns do not match; got: '%s', want: '%s'", s, want[0]); want = want[1..]; } };