diff --git a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/DecoderSelector.scala b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/DecoderSelector.scala index 791d6ef9..b8a4c30e 100644 --- a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/DecoderSelector.scala +++ b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/DecoderSelector.scala @@ -16,7 +16,6 @@ package za.co.absa.cobrix.cobol.parser.decoders -import java.nio.charset.{Charset, StandardCharsets} import za.co.absa.cobrix.cobol.parser.ast.datatype._ import za.co.absa.cobrix.cobol.parser.common.Constants import za.co.absa.cobrix.cobol.parser.common.Constants.{maxIntegerPrecision, maxLongPrecision} @@ -25,6 +24,7 @@ import za.co.absa.cobrix.cobol.parser.encoding._ import za.co.absa.cobrix.cobol.parser.encoding.codepage.{CodePage, CodePageCommon} import za.co.absa.cobrix.cobol.parser.position.Position +import java.nio.charset.{Charset, StandardCharsets} import scala.util.control.NonFatal object DecoderSelector { @@ -128,14 +128,14 @@ object DecoderSelector { case None => if (decimalType.explicitDecimal) { if (isEbcidic) - StringDecoders.decodeEbcdicBigDecimal(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + (bytes: Array[Byte]) => StringDecoders.decodeEbcdicBigDecimal(bytes, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) else - StringDecoders.decodeAsciiBigDecimal(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiBigDecimal(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) } else { if (isEbcidic) - StringDecoders.decodeEbcdicBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection, decimalType.scale, decimalType.scaleFactor) + (bytes: Array[Byte]) => StringDecoders.decodeEbcdicBigNumber(bytes, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection, decimalType.scale, decimalType.scaleFactor) else - StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection, decimalType.scale, decimalType.scaleFactor) + StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection, decimalType.scale, decimalType.scaleFactor) } // case Some(COMP()) => // // COMP aka BINARY encoded number @@ -207,24 +207,24 @@ object DecoderSelector { case None => if (strictIntegralPrecision) { if (isEbcidic) - StringDecoders.decodeEbcdicBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + (bytes: Array[Byte]) => StringDecoders.decodeEbcdicBigNumber(bytes, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) else - StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) } else if (integralType.precision <= Constants.maxIntegerPrecision) { if (isEbcidic) - StringDecoders.decodeEbcdicInt(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + (bytes: Array[Byte]) => StringDecoders.decodeEbcdicInt(bytes, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) else - StringDecoders.decodeAsciiInt(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiInt(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) } else if (integralType.precision <= Constants.maxLongPrecision) { if (isEbcidic) - StringDecoders.decodeEbcdicLong(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeEbcdicLong(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) else - StringDecoders.decodeAsciiLong(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiLong(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) } else { if (isEbcidic) - StringDecoders.decodeEbcdicBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + (bytes: Array[Byte]) => StringDecoders.decodeEbcdicBigNumber(bytes, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) else - StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiBigNumber(_, !isSigned, isSigned || !strictSignOverpunch, !strictSignOverpunch, improvedNullDetection) } // case Some(Constants.compBinary1) => // // COMP aka BINARY encoded number @@ -267,11 +267,11 @@ object DecoderSelector { if (isEbcdic) { bytes: Array[Byte] => { - StringDecoders.decodeEbcdicNumber(bytes, !isSigned, allowedSignOverpunch, improvedNullDetection) + StringDecoders.decodeEbcdicNumber(bytes, !isSigned, allowedSignOverpunch, !strictSignOverpunch, improvedNullDetection) } } else { bytes: Array[Byte] => { - StringDecoders.decodeAsciiNumber(bytes, !isSigned, allowedSignOverpunch, improvedNullDetection) + StringDecoders.decodeAsciiNumber(bytes, !isSigned, allowedSignOverpunch, !strictSignOverpunch, improvedNullDetection) } } } diff --git a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecoders.scala b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecoders.scala index f8c30231..c3bc51c5 100644 --- a/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecoders.scala +++ b/cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecoders.scala @@ -16,10 +16,10 @@ package za.co.absa.cobrix.cobol.parser.decoders -import java.nio.charset.StandardCharsets import za.co.absa.cobrix.cobol.parser.common.Constants import za.co.absa.cobrix.cobol.parser.encoding.codepage.CodePage +import java.nio.charset.StandardCharsets import scala.util.control.NonFatal object StringDecoders { @@ -160,12 +160,13 @@ object StringDecoders { * * * @param bytes A byte array that represents the binary data - * @param isUnsigned Is the number expected to be unsigned - * @param allowSignOverpunch if true, sign overpunching is allowed. - * @param improvedNullDetection if true, return null if all bytes are zero + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A string representation of the binary data */ - final def decodeEbcdicNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): String = { + final def decodeEbcdicNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): String = { if (improvedNullDetection && isNumberNull(bytes)) return null @@ -177,7 +178,7 @@ object StringDecoders { while (i < bytes.length) { val b = bytes(i) & 0xFF var ch = ' ' - if (sign != ' ') { + if (sign != ' ' && !relaxedOvepunch) { // Handle characters after a sign character is encountered if (b >= 0xF0 && b <= 0xF9) { ch = (b - 0xF0 + 0x30).toChar // unsigned @@ -193,11 +194,11 @@ object StringDecoders { } else if (b >= 0xF0 && b <= 0xF9) { ch = (b - 0xF0 + 0x30).toChar // unsigned } - else if (allowSignOverpunch && b >= 0xC0 && b <= 0xC9) { + else if ((allowSignOverpunch || relaxedOvepunch) && b >= 0xC0 && b <= 0xC9) { ch = (b - 0xC0 + 0x30).toChar // positive sign punched sign = '+' } - else if (allowSignOverpunch && b >= 0xD0 && b <= 0xD9) { + else if ((allowSignOverpunch || relaxedOvepunch) && b >= 0xD0 && b <= 0xD9) { ch = (b - 0xD0 + 0x30).toChar // negative sign punched sign = '-' } @@ -232,12 +233,13 @@ object StringDecoders { * A decoder for any ASCII uncompressed numbers supporting leading and trailing sign * * @param bytes A byte array that represents the binary data - * @param isUnsigned Is the number expected to be unsigned - * @param allowSignOverpunch if true, sign overpunching is allowed. - * @param improvedNullDetection if true, return null if all bytes are zero + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A string representation of the binary data */ - final def decodeAsciiNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): String = { + final def decodeAsciiNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): String = { val allowedDigitChars = " 0123456789" val punchedSignChars = "{ABCDEFGHI}JKLMNOPQR" @@ -269,10 +271,18 @@ object StringDecoders { } else if (char == '.' || char == ',') { buf.append('.') } else { - if (allowSignOverpunch && (i == 0 || i == bytes.length - 1) && punchedSignChars.contains(char)) { - decodeOverpunchedSign(char) + if (relaxedOvepunch) { + if (punchedSignChars.contains(char)) { + decodeOverpunchedSign(char) + } else { + return null + } } else { - return null + if (allowSignOverpunch && (i == 0 || i == bytes.length - 1) && punchedSignChars.contains(char)) { + decodeOverpunchedSign(char) + } else { + return null + } } } } @@ -290,13 +300,16 @@ object StringDecoders { /** * Decode integral number from an EBCDIC string converting it to an integer * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A boxed integer */ - final def decodeEbcdicInt(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): Integer = { + final def decodeEbcdicInt(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): Integer = { try { - decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection).toInt + decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection).toInt } catch { case NonFatal(_) => null } @@ -305,13 +318,16 @@ object StringDecoders { /** * Decode integral number from an ASCII string converting it to an integer * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A boxed integer */ - final def decodeAsciiInt(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): Integer = { + final def decodeAsciiInt(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): Integer = { try { - decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection).toInt + decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection).toInt } catch { case NonFatal(_) => null } @@ -320,13 +336,16 @@ object StringDecoders { /** * Decode integral number from an EBCDIC string converting it to an long * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A boxed long */ - final def decodeEbcdicLong(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): java.lang.Long = { + final def decodeEbcdicLong(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): java.lang.Long = { try { - decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection).toLong + decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection).toLong } catch { case NonFatal(_) => null } @@ -335,13 +354,16 @@ object StringDecoders { /** * Decode integral number from an ASCII string converting it to an long * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A boxed long */ - final def decodeAsciiLong(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): java.lang.Long = { + final def decodeAsciiLong(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): java.lang.Long = { try { - decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection).toLong + decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection).toLong } catch { case NonFatal(_) => null } @@ -350,15 +372,18 @@ object StringDecoders { /** * Decode a number from an EBCDIC string converting it to a big decimal * - * @param bytes A byte array that represents the binary data - * @param scale A decimal scale in case decimal number with implicit decimal point is expected - * @param scaleFactor Additional zeros to be added before of after the decimal point - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero + * @param scale A decimal scale in case decimal number with implicit decimal point is expected + * @param scaleFactor Additional zeros to be added before of after the decimal point * @return A big decimal containing a big integral number */ - final def decodeEbcdicBigNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean, scale: Int = 0, scaleFactor: Int = 0): BigDecimal = { + final def decodeEbcdicBigNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean, scale: Int = 0, scaleFactor: Int = 0): BigDecimal = { try { - BigDecimal(BinaryUtils.addDecimalPoint(decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection), scale, scaleFactor)) + BigDecimal(BinaryUtils.addDecimalPoint(decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection), scale, scaleFactor)) } catch { case NonFatal(_) => null } @@ -367,15 +392,18 @@ object StringDecoders { /** * Decode a number from an ASCII string converting it to a big decimal * - * @param bytes A byte array that represents the binary data - * @param scale A decimal scale in case decimal number with implicit decimal point is expected - * @param scaleFactor Additional zeros to be added before of after the decimal point - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero + * @param scale A decimal scale in case decimal number with implicit decimal point is expected + * @param scaleFactor Additional zeros to be added before of after the decimal point * @return A big decimal containing a big integral number */ - final def decodeAsciiBigNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean, scale: Int = 0, scaleFactor: Int = 0): BigDecimal = { + final def decodeAsciiBigNumber(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean, scale: Int = 0, scaleFactor: Int = 0): BigDecimal = { try { - BigDecimal(BinaryUtils.addDecimalPoint(decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection), scale, scaleFactor)) + BigDecimal(BinaryUtils.addDecimalPoint(decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection), scale, scaleFactor)) } catch { case NonFatal(_) => null } @@ -385,13 +413,16 @@ object StringDecoders { * Decode decimal number from an EBCDIC string converting it to a big decimal * This decoder is used to convert decimal numbers with explicit decimal point * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A big decimal containing a big integral number */ - final def decodeEbcdicBigDecimal(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): BigDecimal = { + final def decodeEbcdicBigDecimal(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): BigDecimal = { try { - BigDecimal(decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection)) + BigDecimal(decodeEbcdicNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection)) } catch { case NonFatal(_) => null } @@ -401,13 +432,16 @@ object StringDecoders { * Decode decimal number from an ASCII string converting it to a big decimal * This decoder is used to convert decimal numbers with explicit decimal point * - * @param bytes A byte array that represents the binary data - * @param allowSignOverpunch if true, sign overpunching is allowed. + * @param bytes A byte array that represents the binary data + * @param isUnsigned If true, negative numbers will be considered invalid and return null + * @param allowSignOverpunch If true, sign overpunching is allowed in first or last position + * @param relaxedOvepunch If true, multiple sign overpunching characters are allowed. The last one is going to be effective + * @param improvedNullDetection If true, return null if all bytes are zero * @return A big decimal containing a big integral number */ - final def decodeAsciiBigDecimal(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, improvedNullDetection: Boolean): BigDecimal = { + final def decodeAsciiBigDecimal(bytes: Array[Byte], isUnsigned: Boolean, allowSignOverpunch: Boolean, relaxedOvepunch: Boolean, improvedNullDetection: Boolean): BigDecimal = { try { - BigDecimal(decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, improvedNullDetection)) + BigDecimal(decodeAsciiNumber(bytes, isUnsigned, allowSignOverpunch, relaxedOvepunch, improvedNullDetection)) } catch { case NonFatal(_) => null } diff --git a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/BinaryDecoderSpec.scala b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/BinaryDecoderSpec.scala index 9a681eb3..3fe94d96 100644 --- a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/BinaryDecoderSpec.scala +++ b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/BinaryDecoderSpec.scala @@ -36,54 +36,73 @@ class BinaryDecoderSpec extends AnyFunSuite { test("Test uncompressed number decoding") { - assert(StringDecoders.decodeAsciiNumber("100200".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false).contains("100200")) - assert(StringDecoders.decodeAsciiBigNumber("1002551".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 3).toString.contains("1002.551")) - assert(StringDecoders.decodeAsciiBigNumber("1002.551".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0).toString.contains("1002.551")) + assert(StringDecoders.decodeAsciiNumber("100200".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false).contains("100200")) + assert(StringDecoders.decodeAsciiBigNumber("1002551".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 3).toString.contains("1002.551")) + assert(StringDecoders.decodeAsciiBigNumber("1002.551".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0).toString.contains("1002.551")) // "1002551" val ebcdicNum = Array[Byte](0xF1.toByte, 0xF0.toByte, 0xF0.toByte, 0xF2.toByte, 0xF5.toByte, 0xF5.toByte, 0xF1.toByte) - assert(StringDecoders.decodeEbcdicBigNumber(ebcdicNum, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 2).toString().contains("10025.51")) + assert(StringDecoders.decodeEbcdicBigNumber(ebcdicNum, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 2).toString().contains("10025.51")) + } + + test("Test uncompressed number decoding with relaxed sign overpunching") { + // "1002551" + val ebcdicNum1 = Array[Byte](0xF1.toByte, 0xF0.toByte, 0xF0.toByte, 0xF2.toByte, 0xF5.toByte, 0xD5.toByte, 0xC1.toByte) + assert(StringDecoders.decodeEbcdicBigNumber(ebcdicNum1, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false, 2).toString().contains("10025.51")) + val ebcdicNum2 = Array[Byte](0xF1.toByte, 0xF0.toByte, 0xF0.toByte, 0xF2.toByte, 0xF5.toByte, 0xC5.toByte, 0xD1.toByte) + assert(StringDecoders.decodeEbcdicBigNumber(ebcdicNum2, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false, 2).toString().contains("-10025.51")) + + // Unsigned negative still null + val ebcdicNum3 = Array[Byte](0xF1.toByte, 0xF0.toByte, 0xF0.toByte, 0xF2.toByte, 0xF5.toByte, 0xD5.toByte, 0xD1.toByte) + assert(StringDecoders.decodeEbcdicBigNumber(ebcdicNum3, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false, 2) == null) } test("Test positive sign overpunching") { - assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+0") - assert(StringDecoders.decodeAsciiNumber("10020{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100200") - assert(StringDecoders.decodeAsciiNumber("10020A".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100201") - assert(StringDecoders.decodeAsciiNumber("10020B".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100202") - assert(StringDecoders.decodeAsciiNumber("10020C".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100203") - assert(StringDecoders.decodeAsciiNumber("10020D".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100204") - assert(StringDecoders.decodeAsciiNumber("10020E".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100205") - assert(StringDecoders.decodeAsciiNumber("10020F".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100206") - assert(StringDecoders.decodeAsciiNumber("10020G".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100207") - assert(StringDecoders.decodeAsciiNumber("10020H".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100208") - assert(StringDecoders.decodeAsciiNumber("10020I".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100209") + assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+0") + assert(StringDecoders.decodeAsciiNumber("10020{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100200") + assert(StringDecoders.decodeAsciiNumber("10020A".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100201") + assert(StringDecoders.decodeAsciiNumber("10020B".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100202") + assert(StringDecoders.decodeAsciiNumber("10020C".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100203") + assert(StringDecoders.decodeAsciiNumber("10020D".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100204") + assert(StringDecoders.decodeAsciiNumber("10020E".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100205") + assert(StringDecoders.decodeAsciiNumber("10020F".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100206") + assert(StringDecoders.decodeAsciiNumber("10020G".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100207") + assert(StringDecoders.decodeAsciiNumber("10020H".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100208") + assert(StringDecoders.decodeAsciiNumber("10020I".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100209") } test("Test negative sign overpunching") { - assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-0") - assert(StringDecoders.decodeAsciiNumber("10020}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100200") - assert(StringDecoders.decodeAsciiNumber("10020J".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100201") - assert(StringDecoders.decodeAsciiNumber("10020K".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100202") - assert(StringDecoders.decodeAsciiNumber("10020L".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100203") - assert(StringDecoders.decodeAsciiNumber("10020M".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100204") - assert(StringDecoders.decodeAsciiNumber("10020N".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100205") - assert(StringDecoders.decodeAsciiNumber("10020O".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100206") - assert(StringDecoders.decodeAsciiNumber("10020P".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100207") - assert(StringDecoders.decodeAsciiNumber("10020Q".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100208") - assert(StringDecoders.decodeAsciiNumber("10020R".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100209") + assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-0") + assert(StringDecoders.decodeAsciiNumber("10020}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100200") + assert(StringDecoders.decodeAsciiNumber("10020J".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100201") + assert(StringDecoders.decodeAsciiNumber("10020K".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100202") + assert(StringDecoders.decodeAsciiNumber("10020L".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100203") + assert(StringDecoders.decodeAsciiNumber("10020M".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100204") + assert(StringDecoders.decodeAsciiNumber("10020N".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100205") + assert(StringDecoders.decodeAsciiNumber("10020O".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100206") + assert(StringDecoders.decodeAsciiNumber("10020P".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100207") + assert(StringDecoders.decodeAsciiNumber("10020Q".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100208") + assert(StringDecoders.decodeAsciiNumber("10020R".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100209") } test("Test incorrect sign overpunching") { - assert(StringDecoders.decodeAsciiNumber("1002}0".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(StringDecoders.decodeAsciiNumber("100K00".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(StringDecoders.decodeAsciiNumber("1A0200".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - - assert(StringDecoders.decodeAsciiNumber("10020}".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-0") - assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+0") - assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "+0") - assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) + assert(StringDecoders.decodeAsciiNumber("1002}0".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(StringDecoders.decodeAsciiNumber("100K00".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(StringDecoders.decodeAsciiNumber("1A0200".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + + assert(StringDecoders.decodeAsciiNumber("10020}".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-0") + assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+0") + assert(StringDecoders.decodeAsciiNumber("}".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+0") + assert(StringDecoders.decodeAsciiNumber("{".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + } + + test("Test uncompressed ASCII number decoding with relaxed sign overpunching") { + assert(StringDecoders.decodeAsciiNumber("1002MD".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false) == "+100244") + assert(StringDecoders.decodeAsciiNumber("1002DM".toCharArray.map(_.toByte), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false) == "-100244") + // Negative unsigned still null + assert(StringDecoders.decodeAsciiNumber("1002DM".toCharArray.map(_.toByte), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = true, improvedNullDetection = false) == null) } test("Test positive COMP-3 format decoding") { diff --git a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecodersSpec.scala b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecodersSpec.scala index 9f12d5cf..3d049b62 100644 --- a/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecodersSpec.scala +++ b/cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/StringDecodersSpec.scala @@ -16,11 +16,11 @@ package za.co.absa.cobrix.cobol.parser.decoders -import java.nio.charset.StandardCharsets import org.scalatest.wordspec.AnyWordSpec -import za.co.absa.cobrix.cobol.parser.encoding.codepage import za.co.absa.cobrix.cobol.parser.encoding.codepage._ +import java.nio.charset.StandardCharsets + class StringDecodersSpec extends AnyWordSpec { import StringDecoders._ @@ -630,289 +630,289 @@ class StringDecodersSpec extends AnyWordSpec { "decodeEbcdicNumber()" should { "decode ebcdic strings as parsable strings" in { - assert(decodeEbcdicNumber(toEbcdic("1"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "1") - assert(decodeEbcdicNumber(toEbcdic("1"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "1") - assert(decodeEbcdicNumber(toEbcdic(" 1 "), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "1") - assert(decodeEbcdicNumber(toEbcdic(" 1 "), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "1") - assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-1") + assert(decodeEbcdicNumber(toEbcdic("1"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeEbcdicNumber(toEbcdic("1"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeEbcdicNumber(toEbcdic(" 1 "), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeEbcdicNumber(toEbcdic(" 1 "), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-1") - assert(decodeEbcdicNumber(toEbcdic(" 18938717862,00 "), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "18938717862.00") - assert(decodeEbcdicNumber(toEbcdic(" 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "18938717862.00") - assert(decodeEbcdicNumber(toEbcdic(" + 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "+18938717862.00") - assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-18938717862.00") - assert(decodeEbcdicNumber(toEbcdic(" + 18938717862.00 "), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+18938717862.00") + assert(decodeEbcdicNumber(toEbcdic(" 18938717862,00 "), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "18938717862.00") + assert(decodeEbcdicNumber(toEbcdic(" 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "18938717862.00") + assert(decodeEbcdicNumber(toEbcdic(" + 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+18938717862.00") + assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-18938717862.00") + assert(decodeEbcdicNumber(toEbcdic(" + 18938717862.00 "), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+18938717862.00") } "return null if negative number encountered while parsing unsigned numbers" in { - assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("-1"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic(" - 18938717862.00 "), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "re-position leading and trailing sign" in { - assert(decodeEbcdicNumber(toEbcdic("+100,00"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100.00") - assert(decodeEbcdicNumber(toEbcdic("100.00+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100.00") - assert(decodeEbcdicNumber(toEbcdic("-100.00"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100.00") - assert(decodeEbcdicNumber(toEbcdic("100,00-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100.00") + assert(decodeEbcdicNumber(toEbcdic("+100,00"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100.00") + assert(decodeEbcdicNumber(toEbcdic("100.00+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100.00") + assert(decodeEbcdicNumber(toEbcdic("-100.00"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100.00") + assert(decodeEbcdicNumber(toEbcdic("100,00-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100.00") } "decode sign punched numbers" in { - assert(decodeEbcdicNumber(toEbcdic("A00,00"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100.00") - assert(decodeEbcdicNumber(toEbcdic("J00,00"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100.00") - assert(decodeEbcdicNumber(toEbcdic("B02"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+202") - assert(decodeEbcdicNumber(toEbcdic("K02"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-202") - assert(decodeEbcdicNumber(toEbcdic("30C"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+303") - assert(decodeEbcdicNumber(toEbcdic("30L"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-303") - assert(decodeEbcdicNumber(toEbcdic("40D"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+404") - assert(decodeEbcdicNumber(toEbcdic("40M"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-404") - assert(decodeEbcdicNumber(toEbcdic("E05"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+505") - assert(decodeEbcdicNumber(toEbcdic("N05"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-505") - assert(decodeEbcdicNumber(toEbcdic("F06"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+606") - assert(decodeEbcdicNumber(toEbcdic("O06"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-606") - assert(decodeEbcdicNumber(toEbcdic("G07"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+707") - assert(decodeEbcdicNumber(toEbcdic("P07"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-707") - assert(decodeEbcdicNumber(toEbcdic("H08"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+808") - assert(decodeEbcdicNumber(toEbcdic("Q08"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-808") - assert(decodeEbcdicNumber(toEbcdic("I09"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+909") - assert(decodeEbcdicNumber(toEbcdic("R09"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-909") - assert(decodeEbcdicNumber(toEbcdic("90{"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+900") - assert(decodeEbcdicNumber(toEbcdic("90}"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-900") + assert(decodeEbcdicNumber(toEbcdic("A00,00"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100.00") + assert(decodeEbcdicNumber(toEbcdic("J00,00"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100.00") + assert(decodeEbcdicNumber(toEbcdic("B02"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+202") + assert(decodeEbcdicNumber(toEbcdic("K02"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-202") + assert(decodeEbcdicNumber(toEbcdic("30C"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+303") + assert(decodeEbcdicNumber(toEbcdic("30L"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-303") + assert(decodeEbcdicNumber(toEbcdic("40D"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+404") + assert(decodeEbcdicNumber(toEbcdic("40M"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-404") + assert(decodeEbcdicNumber(toEbcdic("E05"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+505") + assert(decodeEbcdicNumber(toEbcdic("N05"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-505") + assert(decodeEbcdicNumber(toEbcdic("F06"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+606") + assert(decodeEbcdicNumber(toEbcdic("O06"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-606") + assert(decodeEbcdicNumber(toEbcdic("G07"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+707") + assert(decodeEbcdicNumber(toEbcdic("P07"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-707") + assert(decodeEbcdicNumber(toEbcdic("H08"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+808") + assert(decodeEbcdicNumber(toEbcdic("Q08"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-808") + assert(decodeEbcdicNumber(toEbcdic("I09"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+909") + assert(decodeEbcdicNumber(toEbcdic("R09"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-909") + assert(decodeEbcdicNumber(toEbcdic("90{"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+900") + assert(decodeEbcdicNumber(toEbcdic("90}"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-900") } "return null if a number is malformed" in { - assert(decodeEbcdicNumber(toEbcdic("AAABBBCCC"), isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+0") - assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-0") - assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "+0") - assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("AAABBBCCC"), isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+0") + assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-0") + assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+0") + assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("{"), isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicNumber(toEbcdic("}"), isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeAsciiNumber()" should { "decode strings as parsable strings" in { - assert(decodeAsciiNumber("1".getBytes, isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == "1") - assert(decodeAsciiNumber("1".getBytes, isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == "1") - assert(decodeAsciiNumber(" 1 ".getBytes, isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == "1") - assert(decodeAsciiNumber(" 1 ".getBytes, isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == "1") - assert(decodeAsciiNumber("-1".getBytes, isUnsigned = false, allowSignOverpunch = false, improvedNullDetection = false) == "-1") + assert(decodeAsciiNumber("1".getBytes, isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeAsciiNumber("1".getBytes, isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeAsciiNumber(" 1 ".getBytes, isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeAsciiNumber(" 1 ".getBytes, isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == "1") + assert(decodeAsciiNumber("-1".getBytes, isUnsigned = false, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == "-1") - assert(decodeAsciiNumber(" 18938717862,00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "18938717862.00") - assert(decodeAsciiNumber(" 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "18938717862.00") - assert(decodeAsciiNumber(" + 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == "+18938717862.00") - assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-18938717862.00") - assert(decodeAsciiNumber(" + 18938717862.00 ".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+18938717862.00") + assert(decodeAsciiNumber(" 18938717862,00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "18938717862.00") + assert(decodeAsciiNumber(" 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "18938717862.00") + assert(decodeAsciiNumber(" + 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+18938717862.00") + assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-18938717862.00") + assert(decodeAsciiNumber(" + 18938717862.00 ".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+18938717862.00") } "return null if negative number encountered while parsing unsigned numbers" in { - assert(decodeAsciiNumber("-1".getBytes, isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeAsciiNumber("-1".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = false, improvedNullDetection = false) == null) - assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiNumber("-1".getBytes, isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiNumber("-1".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = false, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiNumber(" - 18938717862.00 ".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "re-position leading and trailing sign" in { - assert(decodeAsciiNumber("+100,00".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100.00") - assert(decodeAsciiNumber("100.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "+100.00") - assert(decodeAsciiNumber("-100.00".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100.00") - assert(decodeAsciiNumber("100,00-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == "-100.00") + assert(decodeAsciiNumber("+100,00".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100.00") + assert(decodeAsciiNumber("100.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "+100.00") + assert(decodeAsciiNumber("-100.00".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100.00") + assert(decodeAsciiNumber("100,00-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == "-100.00") } "return null if non-digit characters are encountered" in { - assert(decodeAsciiNumber("AAABBBCCC".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiNumber("AAABBBCCC".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeEbcdicInt()" should { "decode parsable ints" in { - assert(decodeEbcdicInt(toEbcdic("+100"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeEbcdicInt(toEbcdic("100+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeEbcdicInt(toEbcdic("-100"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -100) - assert(decodeEbcdicInt(toEbcdic("100-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -100) + assert(decodeEbcdicInt(toEbcdic("+100"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeEbcdicInt(toEbcdic("100+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeEbcdicInt(toEbcdic("-100"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -100) + assert(decodeEbcdicInt(toEbcdic("100-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -100) } "decode unsigned numbers with sign" in { - assert(decodeEbcdicInt(toEbcdic("+100"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeEbcdicInt(toEbcdic("100+"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeEbcdicInt(toEbcdic("-100"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicInt(toEbcdic("100-"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("+100"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeEbcdicInt(toEbcdic("100+"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeEbcdicInt(toEbcdic("-100"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("100-"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on non-ints ints" in { - assert(decodeEbcdicInt(toEbcdic("+100,0"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicInt(toEbcdic("100.00+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicInt(toEbcdic("-100,000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicInt(toEbcdic("100.000-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("+100,0"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("100.00+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("-100,000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("100.000-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on unparsable ints" in { - assert(decodeEbcdicInt(toEbcdic("+1000000000000"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicInt(toEbcdic("AAA"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("+1000000000000"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicInt(toEbcdic("AAA"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeAsciiInt()" should { "decode parsable ints" in { - assert(decodeAsciiInt("+100".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeAsciiInt("100+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeAsciiInt("-100".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -100) - assert(decodeAsciiInt("100-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -100) + assert(decodeAsciiInt("+100".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeAsciiInt("100+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeAsciiInt("-100".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -100) + assert(decodeAsciiInt("100-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -100) } "decode unsigned numbers with sign" in { - assert(decodeAsciiInt("+100".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeAsciiInt("100+".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 100) - assert(decodeAsciiInt("-100".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiInt("100-".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiInt("+100".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeAsciiInt("100+".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 100) + assert(decodeAsciiInt("-100".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiInt("100-".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on non-ints ints" in { - assert(decodeAsciiInt("+100,0".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiInt("100.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiInt("-100,000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiInt("100.000-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiInt("+100,0".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiInt("100.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiInt("-100,000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiInt("100.000-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on unparsable ints" in { - assert(decodeAsciiInt("+1000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiInt("AAA".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiInt("+1000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiInt("AAA".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeEbcdicLong()" should { "decode parsable longs" in { - assert(decodeEbcdicLong(toEbcdic("+1000000000000000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeEbcdicLong(toEbcdic("1000000000000000+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeEbcdicLong(toEbcdic("-1000000000000000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -1000000000000000L) - assert(decodeEbcdicLong(toEbcdic("1000000000000000-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("+1000000000000000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("1000000000000000+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("-1000000000000000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("1000000000000000-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -1000000000000000L) } "decode unsigned numbers with sign" in { - assert(decodeEbcdicLong(toEbcdic("+1000000000000000"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeEbcdicLong(toEbcdic("1000000000000000+"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeEbcdicLong(toEbcdic("-1000000000000000"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicLong(toEbcdic("1000000000000000-"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("+1000000000000000"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("1000000000000000+"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeEbcdicLong(toEbcdic("-1000000000000000"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("1000000000000000-"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on non-ints longs" in { - assert(decodeEbcdicLong(toEbcdic("+1000000000000000,0"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicLong(toEbcdic("1000000000000000.00+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicLong(toEbcdic("-1000000000000000,000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeEbcdicLong(toEbcdic("1000000000000000.000-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("+1000000000000000,0"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("1000000000000000.00+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("-1000000000000000,000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("1000000000000000.000-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on unparsable longs" in { - assert(decodeEbcdicLong(toEbcdic("AAA"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicLong(toEbcdic("AAA"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeAsciiLong()" should { "decode parsable longs" in { - assert(decodeAsciiLong("+1000000000000000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeAsciiLong("1000000000000000+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeAsciiLong("-1000000000000000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -1000000000000000L) - assert(decodeAsciiLong("1000000000000000-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == -1000000000000000L) + assert(decodeAsciiLong("+1000000000000000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeAsciiLong("1000000000000000+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeAsciiLong("-1000000000000000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -1000000000000000L) + assert(decodeAsciiLong("1000000000000000-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == -1000000000000000L) } "decode unsigned numbers with sign" in { - assert(decodeAsciiLong("+1000000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeAsciiLong("1000000000000000+".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == 1000000000000000L) - assert(decodeAsciiLong("-1000000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiLong("1000000000000000-".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiLong("+1000000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeAsciiLong("1000000000000000+".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == 1000000000000000L) + assert(decodeAsciiLong("-1000000000000000".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiLong("1000000000000000-".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on non-ints longs" in { - assert(decodeAsciiLong("+1000000000000000,0".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiLong("1000000000000000.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiLong("-1000000000000000,000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) - assert(decodeAsciiLong("1000000000000000.000-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiLong("+1000000000000000,0".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiLong("1000000000000000.00+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiLong("-1000000000000000,000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) + assert(decodeAsciiLong("1000000000000000.000-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null on unparsable longs" in { - assert(decodeAsciiLong("AAA".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiLong("AAA".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeEbcdicBigNumber()" should { "decode parsable decimals" in { - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, 0) == BigDecimal("1000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 1, 0) == BigDecimal("100.0")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 3, 0) == BigDecimal("1.000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 4, 0) == BigDecimal("0.1000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 5, 0) == null) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, 0) == BigDecimal("1000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 1, 0) == BigDecimal("100.0")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 3, 0) == BigDecimal("1.000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 4, 0) == BigDecimal("0.1000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 5, 0) == null) } "decode numbers with scale factor" in { - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) - assert(decodeEbcdicBigNumber(toEbcdic("1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) + assert(decodeEbcdicBigNumber(toEbcdic("1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 1, 1) == BigDecimal("10000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 3, 2) == BigDecimal("100000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 4, 3) == BigDecimal("1000000")) - assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 5, 4) == BigDecimal("10000000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 1, 1) == BigDecimal("10000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 3, 2) == BigDecimal("100000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 4, 3) == BigDecimal("1000000")) + assert(decodeEbcdicBigNumber(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 5, 4) == BigDecimal("10000000")) } } "decodeAsciiBigNumber()" should { "decode parsable decimals" in { - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, 0) == BigDecimal("1000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 1, 0) == BigDecimal("100.0")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 3, 0) == BigDecimal("1.000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 4, 0) == BigDecimal("0.1000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 5, 0) == null) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, 0) == BigDecimal("1000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 1, 0) == BigDecimal("100.0")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 3, 0) == BigDecimal("1.000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 4, 0) == BigDecimal("0.1000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 5, 0) == null) } "decode numbers with scale factor" in { - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) - assert(decodeAsciiBigNumber("1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) + assert(decodeAsciiBigNumber("1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 0, -1) == BigDecimal("0.01000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 1, 1) == BigDecimal("10000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 3, 2) == BigDecimal("100000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 4, 3) == BigDecimal("1000000")) - assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false, 5, 4) == BigDecimal("10000000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 1, 1) == BigDecimal("10000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 3, 2) == BigDecimal("100000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 4, 3) == BigDecimal("1000000")) + assert(decodeAsciiBigNumber("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false, 5, 4) == BigDecimal("10000000")) } } "decodeEbcdicBigDecimal()" should { "decode parsable decimals" in { - assert(decodeEbcdicBigDecimal(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("1000")) - assert(decodeEbcdicBigDecimal(toEbcdic("1000,25+"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("1000.25")) - assert(decodeEbcdicBigDecimal(toEbcdic("-1000"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("-1000")) - assert(decodeEbcdicBigDecimal(toEbcdic("1000,25-"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("-1000.25")) - assert(decodeEbcdicBigDecimal(toEbcdic("12345678901234567890123456"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("12345678901234567890123456")) - assert(decodeEbcdicBigDecimal(toEbcdic("12345678901234567890123456.12345678901234567890123456"), isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("12345678901234567890123456.12345678901234567890123456")) + assert(decodeEbcdicBigDecimal(toEbcdic("+1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("1000")) + assert(decodeEbcdicBigDecimal(toEbcdic("1000,25+"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("1000.25")) + assert(decodeEbcdicBigDecimal(toEbcdic("-1000"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("-1000")) + assert(decodeEbcdicBigDecimal(toEbcdic("1000,25-"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("-1000.25")) + assert(decodeEbcdicBigDecimal(toEbcdic("12345678901234567890123456"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("12345678901234567890123456")) + assert(decodeEbcdicBigDecimal(toEbcdic("12345678901234567890123456.12345678901234567890123456"), isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("12345678901234567890123456.12345678901234567890123456")) } "return null for numbers in scientific format" in { - assert(decodeEbcdicBigDecimal(toEbcdic("200E+10"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicBigDecimal(toEbcdic("200E+10"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null for malformed numbers" in { - assert(decodeEbcdicBigDecimal(toEbcdic("ABC"), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeEbcdicBigDecimal(toEbcdic("ABC"), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } "decodeAsciiBigDecimal()" should { "decode parsable decimals" in { - assert(decodeAsciiBigDecimal("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("1000")) - assert(decodeAsciiBigDecimal("1000,25+".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("1000.25")) - assert(decodeAsciiBigDecimal("-1000".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("-1000")) - assert(decodeAsciiBigDecimal("1000,25-".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("-1000.25")) - assert(decodeAsciiBigDecimal("12345678901234567890123456".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("12345678901234567890123456")) - assert(decodeAsciiBigDecimal("12345678901234567890123456.12345678901234567890123456".getBytes, isUnsigned = true, allowSignOverpunch = true, improvedNullDetection = false) == BigDecimal("12345678901234567890123456.12345678901234567890123456")) + assert(decodeAsciiBigDecimal("+1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("1000")) + assert(decodeAsciiBigDecimal("1000,25+".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("1000.25")) + assert(decodeAsciiBigDecimal("-1000".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("-1000")) + assert(decodeAsciiBigDecimal("1000,25-".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("-1000.25")) + assert(decodeAsciiBigDecimal("12345678901234567890123456".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("12345678901234567890123456")) + assert(decodeAsciiBigDecimal("12345678901234567890123456.12345678901234567890123456".getBytes, isUnsigned = true, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == BigDecimal("12345678901234567890123456.12345678901234567890123456")) } "not decode numbers in scientific format" in { - assert(decodeAsciiBigDecimal("200E+10".getBytes, isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiBigDecimal("200E+10".getBytes, isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } "return null for malformed numbers" in { - assert(decodeAsciiBigDecimal("ABC".getBytes(), isUnsigned = false, allowSignOverpunch = true, improvedNullDetection = false) == null) + assert(decodeAsciiBigDecimal("ABC".getBytes(), isUnsigned = false, allowSignOverpunch = true, relaxedOvepunch = false, improvedNullDetection = false) == null) } } diff --git a/spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test19SignOverpunching.scala b/spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test19SignOverpunching.scala index 9791141f..417c2e30 100644 --- a/spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test19SignOverpunching.scala +++ b/spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test19SignOverpunching.scala @@ -167,5 +167,52 @@ class Test19SignOverpunching extends AnyWordSpec with SparkTestBase with BinaryF assertEqualsMultiline(actual, expected) } } + + "Test relaxed sign overpunching" when { + val copybook = + """ 01 R. + 05 A PIC S9(5)V9. + """ + "The number is EBCDIC" in { + val binFileContents: Array[Byte] = Array[Byte]( + 0xF1.toByte, 0xF2.toByte, 0xF3.toByte, 0xD0.toByte, 0xC4.toByte, 0x40 + ) + + withTempBinFile("sign_overpunch", ".dat", binFileContents) { tmpFileName => + val df = spark + .read + .format("cobol") + .option("copybook_contents", copybook) + .option("record_format", "F") + .option("strict_sign_overpunching", "false") + .option("pedantic", "true") + .load(tmpFileName) + + val actual = df.toJSON.collect().mkString("[", ",", "]") + val expected = """[{"A":1230.4}]""" + assertEqualsMultiline(actual, expected) + } + } + + "The number is ASCII" in { + val data = "123}D " + withTempTextFile("sign_overpunch", ".dat", StandardCharsets.US_ASCII, data) { tmpFileName => + val df = spark + .read + .format("cobol") + .option("copybook_contents", copybook) + .option("record_format", "D") + .option("strict_sign_overpunching", "false") + .option("pedantic", "true") + .load(tmpFileName) + + val expected = """[{"A":1230.4}]""" + + val actual = df.toJSON.collect().mkString("[", ",", "]") + + assertEqualsMultiline(actual, expected) + } + } + } } }