From ebe07c782ba66e19038335807c52d7784e967629 Mon Sep 17 00:00:00 2001 From: Ruslan Iushchenko Date: Tue, 26 Oct 2021 12:14:53 +0200 Subject: [PATCH] #430 Add support for 'twisted' RDW headers. --- .../headerparsers/RecordHeaderParserRDW.scala | 11 +++++++++-- .../recordheader/RecordHeaderDecoderRdw.scala | 13 +++++++++---- .../RecordHeaderDecoderRdwSuite.scala | 19 ++++++------------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/headerparsers/RecordHeaderParserRDW.scala b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/headerparsers/RecordHeaderParserRDW.scala index 31ba7691..41de1223 100644 --- a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/headerparsers/RecordHeaderParserRDW.scala +++ b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/headerparsers/RecordHeaderParserRDW.scala @@ -65,10 +65,17 @@ class RecordHeaderParserRDW(isBigEndian: Boolean, RecordMetadata(-1, isValid = false) } else { + val useSecondHalf = header(0) == 0 && header(1) == 0 && (header(2) != 0 || header(3) != 0) val recordLength = if (isBigEndian) { - (header(1) & 0xFF) + 256 * (header(0) & 0xFF) + rdwAdjustment + if (useSecondHalf) + (header(3) & 0xFF) + 256 * (header(2) & 0xFF) + rdwAdjustment + else + (header(1) & 0xFF) + 256 * (header(0) & 0xFF) + rdwAdjustment } else { - (header(2) & 0xFF) + 256 * (header(3) & 0xFF) + rdwAdjustment + if (useSecondHalf) + (header(2) & 0xFF) + 256 * (header(3) & 0xFF) + rdwAdjustment + else + (header(0) & 0xFF) + 256 * (header(1) & 0xFF) + rdwAdjustment } if (recordLength > 0) { diff --git a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdw.scala b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdw.scala index faf7dc35..42273722 100644 --- a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdw.scala +++ b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdw.scala @@ -30,12 +30,17 @@ class RecordHeaderDecoderRdw(rdwParameters: RecordHeaderParameters) extends Reco override def getRecordLength(header: Array[Byte], offset: Long): Int = { validateHeader(header, offset) + val useSecondHalf = header(0) == 0 && header(0) == 0 && (header(2) != 0 || header(3) != 0) val recordLength = if (rdwParameters.isBigEndian) { - if (header(2) != 0 || header(3) != 0) reportInvalidHeaderZeros(header, offset) - (header(1) & 0xFF) + 256 * (header(0) & 0xFF) + rdwParameters.adjustment + if (useSecondHalf) + (header(3) & 0xFF) + 256 * (header(2) & 0xFF) + rdwParameters.adjustment + else + (header(1) & 0xFF) + 256 * (header(0) & 0xFF) + rdwParameters.adjustment } else { - if (header(0) != 0 || header(1) != 0) reportInvalidHeaderZeros(header, offset) - (header(2) & 0xFF) + 256 * (header(3) & 0xFF) + rdwParameters.adjustment + if (useSecondHalf) + (header(2) & 0xFF) + 256 * (header(3) & 0xFF) + rdwParameters.adjustment + else + (header(0) & 0xFF) + 256 * (header(1) & 0xFF) + rdwParameters.adjustment } validateRecordLength(header, offset, recordLength) diff --git a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdwSuite.scala b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdwSuite.scala index 71138fca..9ab1c13d 100644 --- a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdwSuite.scala +++ b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/reader/recordheader/RecordHeaderDecoderRdwSuite.scala @@ -84,32 +84,25 @@ class RecordHeaderDecoderRdwSuite extends WordSpec { assert(ex.getMessage.contains("The length of RDW headers is unexpected. Expected: 4, got 5. Header: 0,0,2,0,0, offset: 123.")) } - "fail when big-endian header is used for little-endian headers" in { + "read big-endian headers even when a little-endian mode is used" in { val rhd = new RecordHeaderDecoderRdw(RecordHeaderParametersFactory.getDummyRecordHeaderParameters(false, 0)) + val len = rhd.getRecordLength(Array[Byte](0, 1, 0, 0), 0) - val ex = intercept[IllegalStateException] { - rhd.getRecordLength(Array[Byte](0, 1, 0, 0), 234) - } - - assert(ex.getMessage.contains("RDW headers contain non-zero values where zeros are expected (check 'rdw_big_endian' flag")) + assert(len == 256) } - "fail when little-endian header is used for big-endian headers" in { + "read little-endian headers even when a big-endian mode is used" in { val rhd = new RecordHeaderDecoderRdw(RecordHeaderParametersFactory.getDummyRecordHeaderParameters(true, 0)) + val len = rhd.getRecordLength(Array[Byte](0, 0, 0, 1), 0) - val ex = intercept[IllegalStateException] { - rhd.getRecordLength(Array[Byte](0, 0, 0, 1), 234) - } - - assert(ex.getMessage.contains("RDW headers contain non-zero values where zeros are expected (check 'rdw_big_endian' flag")) + assert(len == 1) } "fail when record size is incorrect" in { val rhd = new RecordHeaderDecoderRdw(RecordHeaderParametersFactory.getDummyRecordHeaderParameters(true, -10)) - val ex = intercept[IllegalStateException] { rhd.getRecordLength(Array[Byte](0, 1, 0, 0), 234) }