From 20223345a4376c6490736ca952427b919c178985 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 19 Apr 2024 00:33:31 +0100 Subject: [PATCH] Return partial reads --- core/encoding/csv/reader.odin | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/encoding/csv/reader.odin b/core/encoding/csv/reader.odin index 5d3626b9f..f8c72c423 100644 --- a/core/encoding/csv/reader.odin +++ b/core/encoding/csv/reader.odin @@ -124,6 +124,7 @@ reader_destroy :: proc(r: ^Reader) { // read reads a single record (a slice of fields) from r // // All \r\n sequences are normalized to \n, including multi-line field +@(require_results) read :: proc(r: ^Reader, allocator := context.allocator) -> (record: []string, err: Error) { if r.reuse_record { record, err = _read_record(r, &r.last_record, allocator) @@ -136,6 +137,7 @@ read :: proc(r: ^Reader, allocator := context.allocator) -> (record: []string, e } // is_io_error checks where an Error is a specific io.Error kind +@(require_results) is_io_error :: proc(err: Error, io_err: io.Error) -> bool { if v, ok := err.(io.Error); ok { return v == io_err @@ -143,10 +145,10 @@ is_io_error :: proc(err: Error, io_err: io.Error) -> bool { return false } - // read_all reads all the remaining records from r. // Each record is a slice of fields. // read_all is defined to read until an EOF, and does not treat, and does not treat EOF as an error +@(require_results) read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) { context.allocator = allocator records: [dynamic][]string @@ -156,13 +158,18 @@ read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Err return records[:], nil } if rerr != nil { - return nil, rerr + // allow for a partial read + if record != nil { + append(&records, record) + } + return records[:], rerr } append(&records, record) } } // read reads a single record (a slice of fields) from the provided input. +@(require_results) read_from_string :: proc(input: string, record_allocator := context.allocator, buffer_allocator := context.allocator) -> (record: []string, n: int, err: Error) { ir: strings.Reader strings.reader_init(&ir, input) @@ -178,6 +185,7 @@ read_from_string :: proc(input: string, record_allocator := context.allocator, b // read_all reads all the remaining records from the provided input. +@(require_results) read_all_from_string :: proc(input: string, records_allocator := context.allocator, buffer_allocator := context.allocator) -> ([][]string, Error) { ir: strings.Reader strings.reader_init(&ir, input) @@ -189,7 +197,7 @@ read_all_from_string :: proc(input: string, records_allocator := context.allocat return read_all(&r, records_allocator) } -@private +@(private, require_results) is_valid_delim :: proc(r: rune) -> bool { switch r { case 0, '"', '\r', '\n', utf8.RUNE_ERROR: @@ -198,8 +206,9 @@ is_valid_delim :: proc(r: rune) -> bool { return utf8.valid_rune(r) } -@private +@(private, require_results) _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.allocator) -> ([]string, Error) { + @(require_results) read_line :: proc(r: ^Reader) -> ([]byte, io.Error) { if !r.multiline_fields { line, err := bufio.reader_read_slice(&r.r, '\n') @@ -269,6 +278,7 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all unreachable() } + @(require_results) length_newline :: proc(b: []byte) -> int { if len(b) > 0 && b[len(b)-1] == '\n' { return 1 @@ -276,6 +286,7 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all return 0 } + @(require_results) next_rune :: proc(b: []byte) -> rune { r, _ := utf8.decode_rune(b) return r