Return partial reads

This commit is contained in:
gingerBill
2024-04-19 00:33:31 +01:00
parent 3812d5e002
commit 20223345a4

View File

@@ -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