Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
garydgregory committed Sep 21, 2024
2 parents 342547b + 113147f commit f4e3269
Show file tree
Hide file tree
Showing 21 changed files with 313 additions and 276 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -68,7 +68,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8

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

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
31 changes: 31 additions & 0 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: 'Dependency Review'
on: [pull_request]

permissions:
contents: read

jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
2 changes: 1 addition & 1 deletion .github/workflows/scorecards-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ jobs:
retention-days: 5

- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # 3.26.6
uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # 3.26.8
with:
sarif_file: results.sarif
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
<configLocation>${checkstyle.config.file}</configLocation>
<enableRulesSummary>false</enableRulesSummary>
<suppressionsLocation>${checkstyle.suppress.file}</suppressionsLocation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
</plugin>
<plugin>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/apache/commons/csv/CSVParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
* For those who like fluent APIs, parsers can be created using {@link CSVFormat#parse(java.io.Reader)} as a shortcut:
* </p>
* <pre>
* for(CSVRecord record : CSVFormat.EXCEL.parse(in)) {
* for (CSVRecord record : CSVFormat.EXCEL.parse(in)) {
* ...
* }
* </pre>
Expand Down
56 changes: 28 additions & 28 deletions src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,6 @@ final class ExtendedBufferedReader extends UnsynchronizedBufferedReader {
super(reader);
}

@Override
public void mark(final int readAheadLimit) throws IOException {
lineNumberMark = lineNumber;
lastCharMark = lastChar;
positionMark = position;
super.mark(readAheadLimit);
}

@Override
public void reset() throws IOException {
lineNumber = lineNumberMark;
lastChar = lastCharMark;
position = positionMark;
super.reset();
}

/**
* Closes the stream.
*
Expand All @@ -85,6 +69,18 @@ public void close() throws IOException {
super.close();
}

/**
* Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by
* any of the read methods. This will not include a character read using the {@link #peek()} method. If no
* character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached
* on the last read then this will return {@link IOUtils#EOF}.
*
* @return the last character that was read
*/
int getLastChar() {
return lastChar;
}

/**
* Returns the current line number
*
Expand All @@ -98,18 +94,6 @@ long getLineNumber() {
return lineNumber + 1; // Allow for counter being incremented only at EOL
}

/**
* Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by
* any of the read methods. This will not include a character read using the {@link #peek()} method. If no
* character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached
* on the last read then this will return {@link IOUtils#EOF}.
*
* @return the last character that was read
*/
int getLastChar() {
return lastChar;
}

/**
* Gets the character position in the reader.
*
Expand All @@ -119,6 +103,14 @@ long getPosition() {
return this.position;
}

@Override
public void mark(final int readAheadLimit) throws IOException {
lineNumberMark = lineNumber;
lastCharMark = lastChar;
positionMark = position;
super.mark(readAheadLimit);
}

@Override
public int read() throws IOException {
final int current = super.read();
Expand Down Expand Up @@ -190,4 +182,12 @@ public String readLine() throws IOException {
return buffer.toString();
}

@Override
public void reset() throws IOException {
lineNumber = lineNumberMark;
lastChar = lastCharMark;
position = positionMark;
super.reset();
}

}
48 changes: 24 additions & 24 deletions src/main/java/org/apache/commons/csv/Lexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ final class Lexer implements Closeable {
this.escapeDelimiterBuf = new char[2 * delimiter.length - 1];
}

/**
* Appends the next escaped character to the token's content.
*
* @param token the current token
* @throws IOException on stream access error
* @throws CSVException Thrown on invalid input.
*/
private void appendNextEscapedCharacterToToken(final Token token) throws IOException {
if (isEscapeDelimiter()) {
token.content.append(delimiter);
} else {
final int unescaped = readEscape();
if (unescaped == EOF) { // unexpected char after escape
token.content.append((char) escape).append((char) reader.getLastChar());
} else {
token.content.append((char) unescaped);
}
}
}

/**
* Closes resources.
*
Expand Down Expand Up @@ -190,10 +210,6 @@ boolean isStartOfLine(final int ch) {
return ch == Constants.LF || ch == Constants.CR || ch == Constants.UNDEFINED;
}

private int nullToDisabled(final Character c) {
return c == null ? Constants.UNDEFINED : c.charValue(); // Explicit unboxing
}

/**
* Returns the next token.
* <p>
Expand Down Expand Up @@ -279,6 +295,10 @@ Token nextToken(final Token token) throws IOException {
return token;
}

private int nullToDisabled(final Character c) {
return c == null ? Constants.UNDEFINED : c.charValue(); // Explicit unboxing
}

/**
* Parses an encapsulated token.
* <p>
Expand Down Expand Up @@ -408,26 +428,6 @@ private Token parseSimpleToken(final Token token, int ch) throws IOException {
return token;
}

/**
* Appends the next escaped character to the token's content.
*
* @param token the current token
* @throws IOException on stream access error
* @throws CSVException Thrown on invalid input.
*/
private void appendNextEscapedCharacterToToken(final Token token) throws IOException {
if (isEscapeDelimiter()) {
token.content.append(delimiter);
} else {
final int unescaped = readEscape();
if (unescaped == EOF) { // unexpected char after escape
token.content.append((char) escape).append((char) reader.getLastChar());
} else {
token.content.append((char) unescaped);
}
}
}

/**
* Greedily accepts \n, \r and \r\n This checker consumes silently the second control-character...
*
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/org/apache/commons/csv/CSVBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;

import com.generationjava.io.CsvReader;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReaderBuilder;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.openjdk.jmh.annotations.Benchmark;
Expand All @@ -49,6 +45,10 @@
import org.supercsv.io.CsvListReader;
import org.supercsv.prefs.CsvPreference;

import com.generationjava.io.CsvReader;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReaderBuilder;

@BenchmarkMode(Mode.AverageTime)
@Fork(value = 1, jvmArgs = {"-server", "-Xms1024M", "-Xmx1024M"})
@Threads(1)
Expand Down
27 changes: 13 additions & 14 deletions src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -307,25 +307,24 @@ public void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode,
final boolean allowMissingColumnNames,
final boolean ignoreHeaderCase,
final String[] headers,
final boolean valid) throws IOException {
final CSVFormat format =
CSVFormat.DEFAULT.builder()
.setDuplicateHeaderMode(duplicateHeaderMode)
.setAllowMissingColumnNames(allowMissingColumnNames)
.setIgnoreHeaderCase(ignoreHeaderCase)
.setNullString("NULL")
.setHeader()
.build();
final boolean valid) throws IOException {
// @formatter:off
final CSVFormat format = CSVFormat.DEFAULT.builder()
.setDuplicateHeaderMode(duplicateHeaderMode)
.setAllowMissingColumnNames(allowMissingColumnNames)
.setIgnoreHeaderCase(ignoreHeaderCase)
.setNullString("NULL")
.setHeader()
.build();
// @formatter:on
final String input = Arrays.stream(headers)
.map(s -> s == null ? format.getNullString() : s)
.collect(Collectors.joining(format.getDelimiterString()));
// @formatter:off
if (valid) {
try(CSVParser parser = CSVParser.parse(input, format)) {
try (CSVParser parser = CSVParser.parse(input, format)) {
// Parser ignores null headers
final List<String> expected =
Arrays.stream(headers)
.filter(s -> s != null)
.collect(Collectors.toList());
final List<String> expected = Arrays.stream(headers).filter(s -> s != null).collect(Collectors.toList());
Assertions.assertEquals(expected, parser.getHeaderNames(), "HeaderNames");
}
} else {
Expand Down
26 changes: 19 additions & 7 deletions src/test/java/org/apache/commons/csv/CSVFormatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,21 @@ public void testFormatThrowsNullPointerException() {

@Test
public void testFormatToString() {
final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuoteMode(QuoteMode.MINIMAL).withRecordSeparator(CRLF).withQuote('"')
.withNullString("").withIgnoreHeaderCase(true).withHeaderComments("This is HeaderComments").withHeader("col1", "col2", "col3");
// @formatter:off
final CSVFormat format = CSVFormat.RFC4180
.withEscape('?')
.withDelimiter(',')
.withQuoteMode(QuoteMode.MINIMAL)
.withRecordSeparator(CRLF)
.withQuote('"')
.withNullString("")
.withIgnoreHeaderCase(true)
.withHeaderComments("This is HeaderComments")
.withHeader("col1", "col2", "col3");
// @formatter:on
assertEquals(
"Delimiter=<,> Escape=<?> QuoteChar=<\"> QuoteMode=<MINIMAL> NullString=<> RecordSeparator=<" + CRLF
+ "> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
"Delimiter=<,> Escape=<?> QuoteChar=<\"> QuoteMode=<MINIMAL> NullString=<> RecordSeparator=<" + CRLF +
"> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
format.toString());
}

Expand Down Expand Up @@ -960,12 +970,14 @@ public void testQuoteCharSameAsDelimiterThrowsException_Deprecated() {

@Test
public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() {
final Exception exception = assertThrows(IllegalArgumentException.class, () -> {
final Exception exception = assertThrows(IllegalArgumentException.class, () ->
// @formatter:off
CSVFormat.DEFAULT.builder()
.setHeader("Col1", "Col2", "Col3", "Col4")
.setQuoteMode(QuoteMode.NONE)
.build();
});
.build()
// @formatter:on
);
final String actualMessage = exception.getMessage();
final String expectedMessage = "Quote mode set to NONE but no escape character is set";
assertEquals(expectedMessage, actualMessage);
Expand Down
Loading

0 comments on commit f4e3269

Please sign in to comment.