Skip to content

Commit 9c0d607

Browse files
committed
fix: reset() in StrictCsvParser left parser-state fields stale
reset() restored only startingLineNumber and the buffer, but not lines, status, or finished. IndexedCsvReader.readPage() calls reset() before each page; the leaked state then corrupted the next page's results: - A previous page that ended on a multi-line quoted record left lines >= 2. The next page's parse() did startingLineNumber += lines, reporting subsequent records on the wrong line number (regression-tested). - A previous page that exhausted its data set finished = true. A later readPage() on the same reader then returned an empty list because parse() short-circuited on the leaked finished (regression-tested). Also reset status to STATUS_RESET so reset() truly restores the initial parser state rather than partially.
1 parent 0819c4f commit 9c0d607

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

lib/src/intTest/java/blackbox/reader/IndexedCsvReaderTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,40 @@ void unicode() throws IOException {
110110
}
111111
}
112112

113+
@Test
114+
void resetClearsLineCounterBetweenPages() throws IOException {
115+
// Page 0 contains a 2-line quoted field, so the parser bumps `lines` to 2.
116+
// Page 1 must report its record's startingLineNumber from a fresh state,
117+
// not inherit the leaked `lines` from the previous page.
118+
try (var csv = buildSinglePage("\"a\nb\"\nc")) {
119+
assertThat(csv.readPage(0))
120+
.singleElement(CsvRecordAssert.CSV_RECORD)
121+
.isStartingLineNumber(1).fields().containsExactly("a\nb");
122+
assertThat(csv.readPage(1))
123+
.singleElement(CsvRecordAssert.CSV_RECORD)
124+
.isStartingLineNumber(3).fields().containsExactly("c");
125+
}
126+
}
127+
128+
@Test
129+
void resetClearsFinishedFlag() throws IOException {
130+
// Reading the partial last page calls parse() pageSize times;
131+
// the trailing call hits EOF and sets parser.finished = true.
132+
// A subsequent re-read of any page must still succeed; the leaked
133+
// `finished` flag would otherwise cause parse() to short-circuit
134+
// and return an empty list.
135+
final var icrb = IndexedCsvReader.builder().pageSize(2);
136+
try (var csv = icrb.ofCsvRecord(prepareTestFile("a\nb\nc"))) {
137+
assertThat(csv.readPage(1))
138+
.singleElement(CsvRecordAssert.CSV_RECORD)
139+
.fields().containsExactly("c");
140+
assertThat(csv.readPage(0))
141+
.satisfiesExactly(
142+
rec1 -> CsvRecordAssert.assertThat(rec1).fields().containsExactly("a"),
143+
rec2 -> CsvRecordAssert.assertThat(rec2).fields().containsExactly("b"));
144+
}
145+
}
146+
113147
@Test
114148
void explicitCharset() throws IOException {
115149
try (var csv = singlePageBuilder().ofCsvRecord(prepareTestFile("abc\nüöä\nabc"), StandardCharsets.UTF_8)) {

lib/src/main/java/de/siegmar/fastcsv/reader/StrictCsvParser.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ public long getStartingLineNumber() {
345345
public void reset(final long startingLineNumber) {
346346
this.startingLineNumber = startingLineNumber;
347347
csvBuffer.reset();
348+
lines = 1;
349+
status = STATUS_RESET;
350+
finished = false;
348351
}
349352

350353
@Override

0 commit comments

Comments
 (0)