This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-csv.git
The following commit(s) were added to refs/heads/master by this push:
new fe6fe22a Quote value ending with multi-character delimiter prefix
(#620).
fe6fe22a is described below
commit fe6fe22afb6f4e1b4b6ceb2dd293bae104889669
Author: Gary Gregory <[email protected]>
AuthorDate: Sun Jul 5 06:39:18 2026 -0400
Quote value ending with multi-character delimiter prefix (#620).
Sort members
---
.../java/org/apache/commons/csv/CSVFormat.java | 54 +++++++++++-----------
.../org/apache/commons/csv/CSVPrinterTest.java | 18 ++++----
2 files changed, 36 insertions(+), 36 deletions(-)
diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java
b/src/main/java/org/apache/commons/csv/CSVFormat.java
index 4909de1f..a2a29136 100644
--- a/src/main/java/org/apache/commons/csv/CSVFormat.java
+++ b/src/main/java/org/apache/commons/csv/CSVFormat.java
@@ -1688,6 +1688,33 @@ public final class CSVFormat implements Serializable {
return builder().get();
}
+ /**
+ * Tests whether appending the delimiter after {@code charSeq} would let
the parser match the delimiter starting inside the value. This happens with a
+ * multi-character delimiter when the value ends with a straddling prefix
of it (for delimiter {@code ||}, a value ending in {@code |} followed by the
+ * delimiter yields {@code |||}, which the greedy lexer splits one
character early). Such a value must be encapsulated so the field boundary is
unambiguous.
+ */
+ private boolean endsWithDelimiterPrefix(final CharSequence charSeq, final
char[] delimiter, final int delimiterLength) {
+ if (delimiterLength < 2) {
+ return false;
+ }
+ final int len = charSeq.length();
+ for (int start = Math.max(0, len - delimiterLength + 1); start < len;
start++) {
+ boolean match = true;
+ for (int j = 0; j < delimiterLength; j++) {
+ final int idx = start + j;
+ final char c = idx < len ? charSeq.charAt(idx) : delimiter[idx
- len];
+ if (c != delimiter[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public boolean equals(final Object obj) {
if (this == obj) {
@@ -2097,33 +2124,6 @@ public final class CSVFormat implements Serializable {
return true;
}
- /**
- * Tests whether appending the delimiter after {@code charSeq} would let
the parser match the delimiter starting inside the value. This happens with a
- * multi-character delimiter when the value ends with a straddling prefix
of it (for delimiter {@code ||}, a value ending in {@code |} followed by the
- * delimiter yields {@code |||}, which the greedy lexer splits one
character early). Such a value must be encapsulated so the field boundary is
unambiguous.
- */
- private boolean endsWithDelimiterPrefix(final CharSequence charSeq, final
char[] delimiter, final int delimiterLength) {
- if (delimiterLength < 2) {
- return false;
- }
- final int len = charSeq.length();
- for (int start = Math.max(0, len - delimiterLength + 1); start < len;
start++) {
- boolean match = true;
- for (int j = 0; j < delimiterLength; j++) {
- final int idx = start + j;
- final char c = idx < len ? charSeq.charAt(idx) : delimiter[idx
- len];
- if (c != delimiter[j]) {
- match = false;
- break;
- }
- }
- if (match) {
- return true;
- }
- }
- return false;
- }
-
/**
* Tests whether escapes are being processed.
*
diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
index 257a951c..70af43c1 100644
--- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
@@ -1908,6 +1908,15 @@ class CSVPrinterTest {
}
}
+ @Test
+ void testQuoteNonNumeric() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw,
CSVFormat.DEFAULT.withQuoteMode(QuoteMode.NON_NUMERIC))) {
+ printer.printRecord("a", "b\nc", Integer.valueOf(1));
+ assertEquals("\"a\",\"b\nc\",1" + RECORD_SEPARATOR, sw.toString());
+ }
+ }
+
@Test
void testQuoteValueEndingWithMultiCharacterDelimiterPrefix() throws
IOException {
final CSVFormat format =
CSVFormat.DEFAULT.builder().setDelimiter("||").get();
@@ -1954,15 +1963,6 @@ class CSVPrinterTest {
}
}
- @Test
- void testQuoteNonNumeric() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw,
CSVFormat.DEFAULT.withQuoteMode(QuoteMode.NON_NUMERIC))) {
- printer.printRecord("a", "b\nc", Integer.valueOf(1));
- assertEquals("\"a\",\"b\nc\",1" + RECORD_SEPARATOR, sw.toString());
- }
- }
-
@Test
void testRandomDefault() throws Exception {
doRandom(CSVFormat.DEFAULT, ITERATIONS_FOR_RANDOM_TEST);