From 57ecadd23e5469e1b6c6e89ad1e18ab679e48065 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 10 Oct 2024 14:14:24 +0200 Subject: [PATCH] Updated CSV API --- lib/std/encoding/csv.c3 | 76 +++++++++++++++++++++++++++++------------ releasenotes.md | 1 + 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/lib/std/encoding/csv.c3 b/lib/std/encoding/csv.c3 index cae32db50..07f12e031 100644 --- a/lib/std/encoding/csv.c3 +++ b/lib/std/encoding/csv.c3 @@ -1,34 +1,73 @@ module std::encoding::csv; import std::io; + struct CsvReader { InStream stream; String separator; } +struct CsvRow (Printable) +{ + String[] list; + String row; + Allocator allocator; +} + +fn usz! CsvRow.to_format(&self, Formatter* f) @dynamic +{ + return f.printf("%s", self.list); +} + +fn usz CsvRow.len(&self) @operator(len) +{ + return self.list.len; +} + +/** + * @require col < self.list.len + **/ +fn String CsvRow.get_col(&self, usz col) @operator([]) +{ + return self.list[col]; +} + fn void CsvReader.init(&self, InStream stream, String separator = ",") { self.stream = stream; self.separator = separator; } -fn String[]! CsvReader.read_new_row(self, Allocator allocator = allocator::heap()) +fn CsvRow! CsvReader.read_new_row(self) { - return self.read_new_row_with_allocator(allocator::temp()) @inline; + return self.read_row(allocator::heap()) @inline; } -fn String[]! CsvReader.read_new_row_with_allocator(self, Allocator allocator = allocator::heap()) +/** + * @param [&inout] allocator + **/ +fn CsvRow! CsvReader.read_row(self, Allocator allocator) { - @pool(allocator) - { - return io::treadline(self.stream).split(self.separator, allocator: allocator); - }; + String row = io::readline(self.stream, allocator: allocator)!; + defer catch allocator::free(allocator, row); + String[] list = row.split(self.separator, allocator: allocator); + return { list, row, allocator }; } -fn String[]! CsvReader.read_temp_row(self) +fn CsvRow! CsvReader.read_temp_row(self) { - return self.read_new_row_with_allocator(allocator::temp()) @inline; + return self.read_row(allocator::temp()) @inline; +} + +/** + * @require self.allocator `Row already freed` + **/ +fn void CsvRow.free(&self) +{ + allocator::free(self.allocator, self.list); + allocator::free(self.allocator, self.row); + self.allocator = null; } fn void! CsvReader.skip_row(self) @maydiscard @@ -41,24 +80,19 @@ fn void! CsvReader.skip_row(self) @maydiscard macro CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) { - InputStream* stream = self.stream; + InStream stream = self.stream; String sep = self.separator; while (rows--) { @stack_mem(512; Allocator mem) { - String[] parts; - @pool() + String! s = io::readline(stream, mem); + if (catch err = s) { - String! s = stream.treadline(); - if (catch err = s) - { - if (err == IoError.EOF) return; - return err?; - } - parts = s.split(sep, allocator: mem); - }; - @body(parts); + if (err == IoError.EOF) return; + return err?; + } + @body(s.split(sep, allocator: mem)); }; } } \ No newline at end of file diff --git a/releasenotes.md b/releasenotes.md index 8836c3e9f..351943b7a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -22,6 +22,7 @@ - Bug when a continue is copied in a defer. - Compiler error when any/interface initialized using {} #1533. - Bug when defers and $if were combined in a macro, which would cause miscompilation. +- Fixes to the CSV reader. ### Stdlib changes - Remove unintended print of `char[]` as String