From 0606d26ba7d090792a126f938a6f84f7e72608e9 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 10 May 2020 20:19:26 +0800 Subject: [PATCH] csv: fix field multiple lines error --- vlib/encoding/csv/reader.v | 51 ++++++++++++++++++--------------- vlib/encoding/csv/reader_test.v | 25 ++++++++++++++++ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/vlib/encoding/csv/reader.v b/vlib/encoding/csv/reader.v index 1e994004c1..a434fb8277 100644 --- a/vlib/encoding/csv/reader.v +++ b/vlib/encoding/csv/reader.v @@ -98,27 +98,32 @@ fn (r mut Reader) read_record() ?[]string { if !valid_delim(r.delimiter) { return err_invalid_delim } + mut need_read := true + mut keep_raw := false mut line := '' - for { - l := r.read_line() or { - return error(err) - } - if l.len <= 0 { - continue - } - line = l - // skip commented lines - if line[0] == r.comment { - continue - } - break - } mut fields := []string{} mut i := -1 + for { - // not quoted - if line[0] != `"` { - // QTODO i = ... + if need_read { + l := r.read_line() or { + return error(err) + } + if l.len <= 0 { + if keep_raw { line += '\n'} + continue + } else if l[0] == r.comment { + if keep_raw { line += '\n' + l } + continue + } else { + if keep_raw { line += '\n'} + line += l + } + need_read = false + keep_raw = false + } + + if line[0] != `"` { // not quoted j := line.index(r.delimiter.str()) or { // last fields << line[..line.len] @@ -128,13 +133,13 @@ fn (r mut Reader) read_record() ?[]string { fields << line[..i] line = line[i+1..] continue - } - // quoted - else { - line = line[1..] - j := line.index('"') or { - break + } else { // quoted + j := line[1..].index('"') or { + need_read = true + keep_raw = true + continue } + line = line[1..] if j+1 == line.len { // last record fields << line[..j] diff --git a/vlib/encoding/csv/reader_test.v b/vlib/encoding/csv/reader_test.v index 28ff0c6219..f53d0b1ba9 100644 --- a/vlib/encoding/csv/reader_test.v +++ b/vlib/encoding/csv/reader_test.v @@ -174,3 +174,28 @@ fn test_empty_line() { } } } + +fn test_field_multiple_line() { + data := '"name","multiple + + line","value"\n"one","first","1"' + mut csv_reader := csv.new_reader(data) + + mut row_count := 0 + for { + row := csv_reader.read() or { + break + } + row_count++ + if row_count == 1 { + assert row[0] == 'name' + assert row[1] == 'multiple\n\n line' + assert row[2] == 'value' + } + if row_count == 2 { + assert row[0] == 'one' + assert row[1] == 'first' + assert row[2] == '1' + } + } +}