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