diff --git a/judges/recodex_token_judge/judge.hpp b/judges/recodex_token_judge/judge.hpp index ad1403fc..fad096a5 100644 --- a/judges/recodex_token_judge/judge.hpp +++ b/judges/recodex_token_judge/judge.hpp @@ -274,7 +274,7 @@ template class Judge */ void logImpairedCorrectLine(const line_t &line) const { - bpp::log().error() << "-" << line.lineNumber() << ": " << line.getRawLineAsString(); + bpp::log().error() << "-" << line.lineNumber() << ": " << line.getRawLineAsString() << "\n"; } @@ -283,7 +283,7 @@ template class Judge */ void logImpairedResultLine(const line_t &line) const { - bpp::log().error() << "+" << line.lineNumber() << ": " << line.getRawLineAsString(); + bpp::log().error() << "+" << line.lineNumber() << ": " << line.getRawLineAsString() << "\n"; } diff --git a/judges/recodex_token_judge/reader.hpp b/judges/recodex_token_judge/reader.hpp index cda3dcea..af61bc8f 100644 --- a/judges/recodex_token_judge/reader.hpp +++ b/judges/recodex_token_judge/reader.hpp @@ -174,6 +174,7 @@ template class Reader bool mIgnoreEmptyLines; ///< Empty lines are skipped completely. bool mAllowComments; ///< Allow comments (lines starting with '#'), which are completely skipped. bool mIgnoreLineEnds; ///< Treat end lines as regular whitespace. + bool mIgnoreTrailingWhitespace; ///< All whitespace (empty lines) at the end of the file is ignored char_t *mData; ///< Mmaped data of the file. offset_t mOffset; ///< Offset from the beginning of the file (currently processed). @@ -248,9 +249,9 @@ template class Reader } public: - Reader(bool ignoreEmptyLines, bool allowComments, bool ignoreLineEnds) + Reader(bool ignoreEmptyLines, bool allowComments, bool ignoreLineEnds, bool ignoreTrailingWhitespace) : mIgnoreEmptyLines(ignoreEmptyLines), mAllowComments(allowComments), mIgnoreLineEnds(ignoreLineEnds), - mData(nullptr), mOffset(0), mLength(0) + mIgnoreTrailingWhitespace(ignoreTrailingWhitespace), mData(nullptr), mOffset(0), mLength(0) { } @@ -275,6 +276,13 @@ template class Reader mLength = mFile.length() / sizeof(char_t); mLineNumber = 1; mLineOffset = 0; + + if (mIgnoreTrailingWhitespace) { + // Reduce the file length to ignore all whitespace at the end ... + while (mLength > 0 && std::isspace(mData[mLength - 1])) { + --mLength; + } + } } @@ -313,7 +321,9 @@ template class Reader */ std::unique_ptr readLine() { - if (eof()) { return std::unique_ptr(); } + if (eof()) { + return std::unique_ptr(); + } offset_t startOffset = mOffset; auto line = bpp::make_unique(*this, mLineNumber, mData + mOffset); @@ -348,7 +358,8 @@ template class Reader return std::unique_ptr(); } - line->mRawLength = mOffset - startOffset; + line->mRawLength = + line->mTokens.size() > 0 ? line->mTokens.back().charNumber() + line->mTokens.back().length() : 0; return line; } }; diff --git a/judges/recodex_token_judge/recodex-token-judge.cpp b/judges/recodex_token_judge/recodex-token-judge.cpp index a5401e95..6ca136ce 100644 --- a/judges/recodex_token_judge/recodex-token-judge.cpp +++ b/judges/recodex_token_judge/recodex-token-judge.cpp @@ -28,7 +28,10 @@ int main(int argc, char *argv[]) "allow-comments", "Lines starting with '#' are ignored completely.")); args.registerArg(bpp::make_unique( "ignore-line-ends", "New lines characters are treated as regular whitespace.")); - args.getArg("ignore-empty-lines").conflictsWith("ignore-line-ends"); + args.registerArg(bpp::make_unique("ignore-trailing-whitespace", + "Any whitespace (i.e., empty lines or comments if allowed) at the end of files is ignored.")); + args.getArg("ignore-empty-lines").conflictsWith("ignore-line-ends").conflictsWith("ignore-trailing-whitespace"); + args.getArg("ignore-line-ends").conflictsWith("ignore-trailing-whitespace"); // Token comparator args args.registerArg(bpp::make_unique( @@ -73,10 +76,12 @@ int main(int argc, char *argv[]) // Open data readers ... Reader<> correctReader(args.getArgBool("ignore-empty-lines").getValue(), args.getArgBool("allow-comments").getValue(), - args.getArgBool("ignore-line-ends").getValue()); + args.getArgBool("ignore-line-ends").getValue(), + args.getArgBool("ignore-trailing-whitespace").getValue()); Reader<> resultReader(args.getArgBool("ignore-empty-lines").getValue(), args.getArgBool("allow-comments").getValue(), - args.getArgBool("ignore-line-ends").getValue()); + args.getArgBool("ignore-line-ends").getValue(), + args.getArgBool("ignore-trailing-whitespace").getValue()); correctReader.open(args[0]); resultReader.open(args[1]); diff --git a/judges/recodex_token_judge/tests/10.error.out b/judges/recodex_token_judge/tests/10.error.out index 259ac0ea..3f465f1a 100644 --- a/judges/recodex_token_judge/tests/10.error.out +++ b/judges/recodex_token_judge/tests/10.error.out @@ -1,7 +1,12 @@ -0 --1: first row 42 -+2: first -3: unexpected 'row' -+4: 42 pzr --4: kzr pzr # this is the end -+5: kzr +0 +-1: first row 42 + ++2: first + +3: unexpected 'row' ++4: 42 pzr + +-4: kzr pzr + ++5: kzr + diff --git a/judges/recodex_token_judge/tests/12-trailing-whitespace.bats b/judges/recodex_token_judge/tests/12-trailing-whitespace.bats new file mode 100644 index 00000000..4327d4e0 --- /dev/null +++ b/judges/recodex_token_judge/tests/12-trailing-whitespace.bats @@ -0,0 +1,15 @@ +#!/usr/bin/env bats + +load bats-shared + +@test "ignore trailing whitespace" { + run $EXE_FILE --ignore-trailing-whitespace $CORRECT_FILE $RESULT_FILE + [ "$status" -eq 0 ] + [ "${lines[0]}" -eq 1 ] +} + +@test "ignore trailing whitespace (negative test)" { + run $EXE_FILE $CORRECT_FILE $RESULT_FILE + [ "$status" -eq 1 ] + echo "$output" | diff -abB - $ERROR_FILE +} diff --git a/judges/recodex_token_judge/tests/12.correct.in b/judges/recodex_token_judge/tests/12.correct.in new file mode 100644 index 00000000..4be3fff9 --- /dev/null +++ b/judges/recodex_token_judge/tests/12.correct.in @@ -0,0 +1 @@ +9 5 4 1 2 3 6 7 8 10 \ No newline at end of file diff --git a/judges/recodex_token_judge/tests/12.error.out b/judges/recodex_token_judge/tests/12.error.out new file mode 100644 index 00000000..d007473d --- /dev/null +++ b/judges/recodex_token_judge/tests/12.error.out @@ -0,0 +1,4 @@ +0 ++2: ++3: ++4: diff --git a/judges/recodex_token_judge/tests/12.result.in b/judges/recodex_token_judge/tests/12.result.in new file mode 100644 index 00000000..805c938a --- /dev/null +++ b/judges/recodex_token_judge/tests/12.result.in @@ -0,0 +1,4 @@ +9 5 4 1 2 3 6 7 8 10 + + + \ No newline at end of file