Skip to content

Commit 960d8c8

Browse files
committed
feat: ignore same comment character if comments are ignored
1 parent f0f04f3 commit 960d8c8

6 files changed

Lines changed: 77 additions & 30 deletions

File tree

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

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.junit.jupiter.api.Test;
2222
import org.junit.jupiter.params.ParameterizedTest;
23+
import org.junit.jupiter.params.provider.EnumSource;
2324
import org.junit.jupiter.params.provider.ValueSource;
2425

2526
import de.siegmar.fastcsv.reader.CloseableIterator;
@@ -72,21 +73,37 @@ void invalidCommentCharacter(final char c) {
7273
void dupeQuoteCharacter() {
7374
assertThatThrownBy(() -> crb.quoteCharacter(',').ofCsvRecord("foo"))
7475
.isInstanceOf(IllegalArgumentException.class)
75-
.hasMessage("Control characters must differ (fieldSeparator=,, quoteCharacter=,, commentCharacter=#)");
76+
.hasMessage("Control characters must differ (fieldSeparator=,, quoteCharacter=,)");
7677
}
7778

78-
@Test
79-
void dupeCommentCharacter() {
80-
assertThatThrownBy(() -> crb.commentCharacter(',').ofCsvRecord("foo"))
81-
.isInstanceOf(IllegalArgumentException.class)
82-
.hasMessage("Control characters must differ (fieldSeparator=,, quoteCharacter=\", commentCharacter=,)");
79+
@ParameterizedTest
80+
@EnumSource(CommentStrategy.class)
81+
void dupeCommentCharacter(final CommentStrategy commentStrategy) {
82+
crb.commentStrategy(commentStrategy).commentCharacter(',');
83+
84+
if (commentStrategy == CommentStrategy.NONE) {
85+
assertThatCode(() -> crb.ofCsvRecord("foo"))
86+
.doesNotThrowAnyException();
87+
} else {
88+
assertThatThrownBy(() -> crb.ofCsvRecord("foo"))
89+
.isInstanceOf(IllegalArgumentException.class)
90+
.hasMessage("Control characters must differ (fieldSeparator=,, quoteCharacter=\", commentCharacter=,)");
91+
}
8392
}
8493

85-
@Test
86-
void dupeCommentQuoteCharacter() {
87-
assertThatThrownBy(() -> crb.commentCharacter('"').ofCsvRecord("foo"))
88-
.isInstanceOf(IllegalArgumentException.class)
89-
.hasMessage("Control characters must differ (fieldSeparator=,, quoteCharacter=\", commentCharacter=\")");
94+
@ParameterizedTest
95+
@EnumSource(CommentStrategy.class)
96+
void dupeCommentQuoteCharacter(final CommentStrategy commentStrategy) {
97+
crb.commentStrategy(commentStrategy).commentCharacter('"');
98+
if (commentStrategy == CommentStrategy.NONE) {
99+
assertThatCode(() -> crb.ofCsvRecord("foo"))
100+
.doesNotThrowAnyException();
101+
} else {
102+
assertThatThrownBy(() -> crb.ofCsvRecord("foo"))
103+
.isInstanceOf(IllegalArgumentException.class)
104+
.hasMessage("Control characters must differ "
105+
+ "(fieldSeparator=,, quoteCharacter=\", commentCharacter=\")");
106+
}
90107
}
91108

92109
@Test

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void fieldSeparatorPartiallyOverlapping() {
106106
.stream().count()
107107
)
108108
.isInstanceOf(IllegalArgumentException.class)
109-
.hasMessage("Control characters must differ (fieldSeparator=~, quoteCharacter=~, commentCharacter=#)");
109+
.hasMessage("Control characters must differ (fieldSeparator=~, quoteCharacter=~)");
110110
}
111111

112112
@Test

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,16 @@ void controlCharacterDiffer() throws IOException {
271271
softly.assertThatThrownBy(() -> singlePageBuilder().fieldSeparator('"').ofCsvRecord(emptyFile))
272272
.as("fieldSeparator")
273273
.isInstanceOf(IllegalArgumentException.class)
274-
.hasMessage(expectedMessage, "\"", "\"", "#");
274+
.hasMessage("Control characters must differ (fieldSeparator=\", quoteCharacter=\")");
275275

276-
softly.assertThatThrownBy(() -> singlePageBuilder().quoteCharacter('#').ofCsvRecord(emptyFile))
276+
softly.assertThatThrownBy(() -> singlePageBuilder().commentStrategy(CommentStrategy.READ)
277+
.quoteCharacter('#').ofCsvRecord(emptyFile))
277278
.as("quoteCharacter")
278279
.isInstanceOf(IllegalArgumentException.class)
279280
.hasMessage(expectedMessage, ",", "#", "#");
280281

281-
softly.assertThatThrownBy(() -> singlePageBuilder().commentCharacter(',').ofCsvRecord(emptyFile))
282+
softly.assertThatThrownBy(() -> singlePageBuilder().commentStrategy(CommentStrategy.READ)
283+
.commentCharacter(',').ofCsvRecord(emptyFile))
282284
.as("commentCharacter")
283285
.isInstanceOf(IllegalArgumentException.class)
284286
.hasMessage(expectedMessage, ",", "\"", ",");

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ public final class IndexedCsvReader<T> implements Closeable {
7070
final StatusListener statusListener)
7171
throws IOException {
7272

73-
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter, commentCharacter), () ->
74-
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
75-
fieldSeparator, quoteCharacter, commentCharacter));
73+
assertFields(fieldSeparator, quoteCharacter, commentCharacter, commentStrategy);
7674

7775
this.file = file;
7876
this.fieldSeparator = fieldSeparator;
@@ -109,6 +107,19 @@ public final class IndexedCsvReader<T> implements Closeable {
109107
new InputStreamReader(new RandomAccessFileInputStream(raf), charset));
110108
}
111109

110+
private static void assertFields(final char fieldSeparator, final char quoteCharacter,
111+
final char commentCharacter, final CommentStrategy commentStrategy) {
112+
if (commentStrategy == CommentStrategy.NONE) {
113+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter), () ->
114+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s)".formatted(
115+
fieldSeparator, quoteCharacter));
116+
} else {
117+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter, commentCharacter), () ->
118+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
119+
fieldSeparator, quoteCharacter, commentCharacter));
120+
}
121+
}
122+
112123
private static Optional<BomHeader> detectBom(final Path file, final StatusListener statusListener)
113124
throws IOException {
114125
try {

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ final class RelaxedCsvParser implements CsvParser {
5151
final CsvCallbackHandler<?> callbackHandler,
5252
final int maxBufferSize,
5353
final Reader reader) {
54-
assertFields(fsep, qChar, cChar);
54+
assertFields(fsep, qChar, cChar, cStrat);
5555

5656
this.fsep = fsep.charAt(0);
5757
fsepRemainder = extractFsepRemainder(fsep);
@@ -72,7 +72,7 @@ final class RelaxedCsvParser implements CsvParser {
7272
final CsvCallbackHandler<?> callbackHandler,
7373
final int maxBufferSize,
7474
final String data) {
75-
assertFields(fsep, qChar, cChar);
75+
assertFields(fsep, qChar, cChar, cStrat);
7676

7777
this.fsep = fsep.charAt(0);
7878
fsepRemainder = extractFsepRemainder(fsep);
@@ -86,14 +86,22 @@ final class RelaxedCsvParser implements CsvParser {
8686
currentField = new char[Math.min(maxBufferSize, data.length())];
8787
}
8888

89-
private void assertFields(final String fieldSeparator, final char quoteCharacter, final char commentCharacter) {
89+
private static void assertFields(final String fieldSeparator, final char quoteCharacter,
90+
final char commentCharacter, final CommentStrategy commentStrategy) {
9091
Preconditions.checkArgument(!Util.containsNewline(fieldSeparator),
9192
"fieldSeparator must not contain newline chars");
9293
Preconditions.checkArgument(!Util.isNewline(quoteCharacter), "quoteCharacter must not be a newline char");
9394
Preconditions.checkArgument(!Util.isNewline(commentCharacter), "commentCharacter must not be a newline char");
94-
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator.charAt(0), quoteCharacter, commentCharacter),
95-
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
96-
fieldSeparator.charAt(0), quoteCharacter, commentCharacter));
95+
96+
if (commentStrategy == CommentStrategy.NONE) {
97+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator.charAt(0), quoteCharacter),
98+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s)".formatted(
99+
fieldSeparator.charAt(0), quoteCharacter));
100+
} else {
101+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator.charAt(0), quoteCharacter, commentCharacter),
102+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
103+
fieldSeparator.charAt(0), quoteCharacter, commentCharacter));
104+
}
97105
}
98106

99107
@Nullable

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ final class StrictCsvParser implements CsvParser {
5555
final int maxBufferSize,
5656
final Reader reader) {
5757

58-
assertFields(fieldSeparator, quoteCharacter, commentCharacter);
58+
assertFields(fieldSeparator, quoteCharacter, commentCharacter, commentStrategy);
5959

6060
fsep = fieldSeparator;
6161
qChar = quoteCharacter;
@@ -72,7 +72,7 @@ final class StrictCsvParser implements CsvParser {
7272
final CsvCallbackHandler<?> callbackHandler,
7373
final String data) {
7474

75-
assertFields(fieldSeparator, quoteCharacter, commentCharacter);
75+
assertFields(fieldSeparator, quoteCharacter, commentCharacter, commentStrategy);
7676

7777
fsep = fieldSeparator;
7878
qChar = quoteCharacter;
@@ -83,13 +83,22 @@ final class StrictCsvParser implements CsvParser {
8383
csvBuffer = new CsvBuffer(data);
8484
}
8585

86-
private void assertFields(final char fieldSeparator, final char quoteCharacter, final char commentCharacter) {
86+
private static void assertFields(final char fieldSeparator, final char quoteCharacter,
87+
final char commentCharacter, final CommentStrategy commentStrategy) {
8788
Preconditions.checkArgument(!Util.isNewline(fieldSeparator), "fieldSeparator must not contain newline chars");
8889
Preconditions.checkArgument(!Util.isNewline(quoteCharacter), "quoteCharacter must not be a newline char");
8990
Preconditions.checkArgument(!Util.isNewline(commentCharacter), "commentCharacter must not be a newline char");
90-
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter, commentCharacter),
91-
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
92-
fieldSeparator, quoteCharacter, commentCharacter));
91+
92+
if (commentStrategy == CommentStrategy.NONE) {
93+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter),
94+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s)".formatted(
95+
fieldSeparator, quoteCharacter));
96+
} else {
97+
Preconditions.checkArgument(!Util.containsDupe(fieldSeparator, quoteCharacter, commentCharacter),
98+
"Control characters must differ (fieldSeparator=%s, quoteCharacter=%s, commentCharacter=%s)".formatted(
99+
fieldSeparator, quoteCharacter, commentCharacter));
100+
101+
}
93102
}
94103

95104
@SuppressWarnings("checkstyle:ReturnCount")

0 commit comments

Comments
 (0)