Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

Commit f4e3269

Browse files
committed
2 parents 342547b + 113147f commit f4e3269

21 files changed

Lines changed: 313 additions & 276 deletions

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
5858
# Initializes the CodeQL tools for scanning.
5959
- name: Initialize CodeQL
60-
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
60+
uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
6161
with:
6262
languages: ${{ matrix.language }}
6363
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -68,7 +68,7 @@ jobs:
6868
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
6969
# If this step fails, then you should remove it and run the build manually (see below)
7070
- name: Autobuild
71-
uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
71+
uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
7272

7373
# ℹ️ Command-line programs to run using the OS shell.
7474
# 📚 https://git.io/JvXDl
@@ -82,4 +82,4 @@ jobs:
8282
# make release
8383

8484
- name: Perform CodeQL Analysis
85-
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
85+
uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
name: 'Dependency Review'
19+
on: [pull_request]
20+
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
dependency-review:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: 'Checkout Repository'
29+
uses: actions/checkout@v4
30+
- name: 'Dependency Review'
31+
uses: actions/dependency-review-action@v4

.github/workflows/scorecards-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@ jobs:
6464
retention-days: 5
6565

6666
- name: "Upload to code-scanning"
67-
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
67+
uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
6868
with:
6969
sarif_file: results.sarif

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
<configLocation>${checkstyle.config.file}</configLocation>
207207
<enableRulesSummary>false</enableRulesSummary>
208208
<suppressionsLocation>${checkstyle.suppress.file}</suppressionsLocation>
209+
<includeTestSourceDirectory>true</includeTestSourceDirectory>
209210
</configuration>
210211
</plugin>
211212
<plugin>

src/main/java/org/apache/commons/csv/CSVParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
* For those who like fluent APIs, parsers can be created using {@link CSVFormat#parse(java.io.Reader)} as a shortcut:
7373
* </p>
7474
* <pre>
75-
* for(CSVRecord record : CSVFormat.EXCEL.parse(in)) {
75+
* for (CSVRecord record : CSVFormat.EXCEL.parse(in)) {
7676
* ...
7777
* }
7878
* </pre>

src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,6 @@ final class ExtendedBufferedReader extends UnsynchronizedBufferedReader {
5656
super(reader);
5757
}
5858

59-
@Override
60-
public void mark(final int readAheadLimit) throws IOException {
61-
lineNumberMark = lineNumber;
62-
lastCharMark = lastChar;
63-
positionMark = position;
64-
super.mark(readAheadLimit);
65-
}
66-
67-
@Override
68-
public void reset() throws IOException {
69-
lineNumber = lineNumberMark;
70-
lastChar = lastCharMark;
71-
position = positionMark;
72-
super.reset();
73-
}
74-
7559
/**
7660
* Closes the stream.
7761
*
@@ -85,6 +69,18 @@ public void close() throws IOException {
8569
super.close();
8670
}
8771

72+
/**
73+
* Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by
74+
* any of the read methods. This will not include a character read using the {@link #peek()} method. If no
75+
* character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached
76+
* on the last read then this will return {@link IOUtils#EOF}.
77+
*
78+
* @return the last character that was read
79+
*/
80+
int getLastChar() {
81+
return lastChar;
82+
}
83+
8884
/**
8985
* Returns the current line number
9086
*
@@ -98,18 +94,6 @@ long getLineNumber() {
9894
return lineNumber + 1; // Allow for counter being incremented only at EOL
9995
}
10096

101-
/**
102-
* Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by
103-
* any of the read methods. This will not include a character read using the {@link #peek()} method. If no
104-
* character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached
105-
* on the last read then this will return {@link IOUtils#EOF}.
106-
*
107-
* @return the last character that was read
108-
*/
109-
int getLastChar() {
110-
return lastChar;
111-
}
112-
11397
/**
11498
* Gets the character position in the reader.
11599
*
@@ -119,6 +103,14 @@ long getPosition() {
119103
return this.position;
120104
}
121105

106+
@Override
107+
public void mark(final int readAheadLimit) throws IOException {
108+
lineNumberMark = lineNumber;
109+
lastCharMark = lastChar;
110+
positionMark = position;
111+
super.mark(readAheadLimit);
112+
}
113+
122114
@Override
123115
public int read() throws IOException {
124116
final int current = super.read();
@@ -190,4 +182,12 @@ public String readLine() throws IOException {
190182
return buffer.toString();
191183
}
192184

185+
@Override
186+
public void reset() throws IOException {
187+
lineNumber = lineNumberMark;
188+
lastChar = lastCharMark;
189+
position = positionMark;
190+
super.reset();
191+
}
192+
193193
}

src/main/java/org/apache/commons/csv/Lexer.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ final class Lexer implements Closeable {
6363
this.escapeDelimiterBuf = new char[2 * delimiter.length - 1];
6464
}
6565

66+
/**
67+
* Appends the next escaped character to the token's content.
68+
*
69+
* @param token the current token
70+
* @throws IOException on stream access error
71+
* @throws CSVException Thrown on invalid input.
72+
*/
73+
private void appendNextEscapedCharacterToToken(final Token token) throws IOException {
74+
if (isEscapeDelimiter()) {
75+
token.content.append(delimiter);
76+
} else {
77+
final int unescaped = readEscape();
78+
if (unescaped == EOF) { // unexpected char after escape
79+
token.content.append((char) escape).append((char) reader.getLastChar());
80+
} else {
81+
token.content.append((char) unescaped);
82+
}
83+
}
84+
}
85+
6686
/**
6787
* Closes resources.
6888
*
@@ -190,10 +210,6 @@ boolean isStartOfLine(final int ch) {
190210
return ch == Constants.LF || ch == Constants.CR || ch == Constants.UNDEFINED;
191211
}
192212

193-
private int nullToDisabled(final Character c) {
194-
return c == null ? Constants.UNDEFINED : c.charValue(); // Explicit unboxing
195-
}
196-
197213
/**
198214
* Returns the next token.
199215
* <p>
@@ -279,6 +295,10 @@ Token nextToken(final Token token) throws IOException {
279295
return token;
280296
}
281297

298+
private int nullToDisabled(final Character c) {
299+
return c == null ? Constants.UNDEFINED : c.charValue(); // Explicit unboxing
300+
}
301+
282302
/**
283303
* Parses an encapsulated token.
284304
* <p>
@@ -408,26 +428,6 @@ private Token parseSimpleToken(final Token token, int ch) throws IOException {
408428
return token;
409429
}
410430

411-
/**
412-
* Appends the next escaped character to the token's content.
413-
*
414-
* @param token the current token
415-
* @throws IOException on stream access error
416-
* @throws CSVException Thrown on invalid input.
417-
*/
418-
private void appendNextEscapedCharacterToToken(final Token token) throws IOException {
419-
if (isEscapeDelimiter()) {
420-
token.content.append(delimiter);
421-
} else {
422-
final int unescaped = readEscape();
423-
if (unescaped == EOF) { // unexpected char after escape
424-
token.content.append((char) escape).append((char) reader.getLastChar());
425-
} else {
426-
token.content.append((char) unescaped);
427-
}
428-
}
429-
}
430-
431431
/**
432432
* Greedily accepts \n, \r and \r\n This checker consumes silently the second control-character...
433433
*

src/test/java/org/apache/commons/csv/CSVBenchmark.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
import java.util.concurrent.TimeUnit;
2929
import java.util.zip.GZIPInputStream;
3030

31-
import com.generationjava.io.CsvReader;
32-
import com.opencsv.CSVParserBuilder;
33-
import com.opencsv.CSVReaderBuilder;
34-
3531
import org.apache.commons.io.IOUtils;
3632
import org.apache.commons.lang3.StringUtils;
3733
import org.openjdk.jmh.annotations.Benchmark;
@@ -49,6 +45,10 @@
4945
import org.supercsv.io.CsvListReader;
5046
import org.supercsv.prefs.CsvPreference;
5147

48+
import com.generationjava.io.CsvReader;
49+
import com.opencsv.CSVParserBuilder;
50+
import com.opencsv.CSVReaderBuilder;
51+
5252
@BenchmarkMode(Mode.AverageTime)
5353
@Fork(value = 1, jvmArgs = {"-server", "-Xms1024M", "-Xmx1024M"})
5454
@Threads(1)

src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -307,25 +307,24 @@ public void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode,
307307
final boolean allowMissingColumnNames,
308308
final boolean ignoreHeaderCase,
309309
final String[] headers,
310-
final boolean valid) throws IOException {
311-
final CSVFormat format =
312-
CSVFormat.DEFAULT.builder()
313-
.setDuplicateHeaderMode(duplicateHeaderMode)
314-
.setAllowMissingColumnNames(allowMissingColumnNames)
315-
.setIgnoreHeaderCase(ignoreHeaderCase)
316-
.setNullString("NULL")
317-
.setHeader()
318-
.build();
310+
final boolean valid) throws IOException {
311+
// @formatter:off
312+
final CSVFormat format = CSVFormat.DEFAULT.builder()
313+
.setDuplicateHeaderMode(duplicateHeaderMode)
314+
.setAllowMissingColumnNames(allowMissingColumnNames)
315+
.setIgnoreHeaderCase(ignoreHeaderCase)
316+
.setNullString("NULL")
317+
.setHeader()
318+
.build();
319+
// @formatter:on
319320
final String input = Arrays.stream(headers)
320321
.map(s -> s == null ? format.getNullString() : s)
321322
.collect(Collectors.joining(format.getDelimiterString()));
323+
// @formatter:off
322324
if (valid) {
323-
try(CSVParser parser = CSVParser.parse(input, format)) {
325+
try (CSVParser parser = CSVParser.parse(input, format)) {
324326
// Parser ignores null headers
325-
final List<String> expected =
326-
Arrays.stream(headers)
327-
.filter(s -> s != null)
328-
.collect(Collectors.toList());
327+
final List<String> expected = Arrays.stream(headers).filter(s -> s != null).collect(Collectors.toList());
329328
Assertions.assertEquals(expected, parser.getHeaderNames(), "HeaderNames");
330329
}
331330
} else {

src/test/java/org/apache/commons/csv/CSVFormatTest.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -715,11 +715,21 @@ public void testFormatThrowsNullPointerException() {
715715

716716
@Test
717717
public void testFormatToString() {
718-
final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuoteMode(QuoteMode.MINIMAL).withRecordSeparator(CRLF).withQuote('"')
719-
.withNullString("").withIgnoreHeaderCase(true).withHeaderComments("This is HeaderComments").withHeader("col1", "col2", "col3");
718+
// @formatter:off
719+
final CSVFormat format = CSVFormat.RFC4180
720+
.withEscape('?')
721+
.withDelimiter(',')
722+
.withQuoteMode(QuoteMode.MINIMAL)
723+
.withRecordSeparator(CRLF)
724+
.withQuote('"')
725+
.withNullString("")
726+
.withIgnoreHeaderCase(true)
727+
.withHeaderComments("This is HeaderComments")
728+
.withHeader("col1", "col2", "col3");
729+
// @formatter:on
720730
assertEquals(
721-
"Delimiter=<,> Escape=<?> QuoteChar=<\"> QuoteMode=<MINIMAL> NullString=<> RecordSeparator=<" + CRLF
722-
+ "> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
731+
"Delimiter=<,> Escape=<?> QuoteChar=<\"> QuoteMode=<MINIMAL> NullString=<> RecordSeparator=<" + CRLF +
732+
"> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
723733
format.toString());
724734
}
725735

@@ -960,12 +970,14 @@ public void testQuoteCharSameAsDelimiterThrowsException_Deprecated() {
960970

961971
@Test
962972
public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() {
963-
final Exception exception = assertThrows(IllegalArgumentException.class, () -> {
973+
final Exception exception = assertThrows(IllegalArgumentException.class, () ->
974+
// @formatter:off
964975
CSVFormat.DEFAULT.builder()
965976
.setHeader("Col1", "Col2", "Col3", "Col4")
966977
.setQuoteMode(QuoteMode.NONE)
967-
.build();
968-
});
978+
.build()
979+
// @formatter:on
980+
);
969981
final String actualMessage = exception.getMessage();
970982
final String expectedMessage = "Quote mode set to NONE but no escape character is set";
971983
assertEquals(expectedMessage, actualMessage);

0 commit comments

Comments
 (0)