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);

Reply via email to