diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala index 92348ee819..a42fab04f7 100644 --- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala +++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala @@ -59,6 +59,7 @@ import org.apache.daffodil.core.grammar.primitives.RightFill import org.apache.daffodil.core.grammar.primitives.ScalarOrderedSequenceChild import org.apache.daffodil.core.grammar.primitives.SpecifiedLengthExplicit import org.apache.daffodil.core.grammar.primitives.SpecifiedLengthImplicit +import org.apache.daffodil.core.grammar.primitives.SpecifiedLengthPrefixed import org.apache.daffodil.lib.api.Diagnostic import org.apache.daffodil.lib.api.WarnID import org.apache.daffodil.lib.schema.annotation.props.gen.FailureType @@ -301,6 +302,7 @@ object DaffodilCCodeGenerator case g: SeqComp => seqCompGenerateCode(g, cgState) case g: SpecifiedLengthExplicit => specifiedLengthExplicit(g, cgState) case g: SpecifiedLengthImplicit => specifiedLengthImplicit(g, cgState) + case g: SpecifiedLengthPrefixed => specifiedLengthPrefixed(g, cgState) case _ => gram.SDE("Code generation not supported for: %s", Misc.getNameFromClass(gram)) } } @@ -409,4 +411,11 @@ object DaffodilCCodeGenerator ): Unit = { DaffodilCCodeGenerator.generateCode(g.eGram, cgState) } + + private def specifiedLengthPrefixed( + g: SpecifiedLengthPrefixed, + cgState: CodeGeneratorState + ): Unit = { + DaffodilCCodeGenerator.generateCode(g.eGram, cgState) + } } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala index 12b53c352a..6f33784500 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala @@ -72,7 +72,9 @@ trait ElementBaseGrammarMixin } } - protected lazy val isDelimitedPrefixedPattern = { + lazy val isPrefixed: Boolean = lengthKind == LengthKind.Prefixed + + protected lazy val isDelimitedPrefixedPattern: Boolean = { import LengthKind._ lengthKind match { case Delimited => @@ -474,12 +476,16 @@ trait ElementBaseGrammarMixin lazy val leftPadding = leftPaddingArg lazy val rightPadFill = rightPadFillArg lazy val body = bodyArg - CaptureContentLengthStart(this) ~ - leftPadding ~ - CaptureValueLengthStart(this) ~ - body ~ - CaptureValueLengthEnd(this) ~ - rightPadFill ~ + specifiedLength( + CaptureContentLengthStart(this) ~ + leftPadding ~ + CaptureValueLengthStart(this) ~ + body ~ + CaptureValueLengthEnd(this) ~ + rightPadFill + ) ~ + // CaptureContentLengthEnd must be outside the specified length so it can + // do any skipping of bits it needs to before capturing the end of content length CaptureContentLengthEnd(this) } @@ -623,14 +629,14 @@ trait ElementBaseGrammarMixin private lazy val stringPrim = { lengthKind match { - case LengthKind.Explicit => specifiedLength(StringOfSpecifiedLength(this)) - case LengthKind.Prefixed => specifiedLength(StringOfSpecifiedLength(this)) + case LengthKind.Explicit => StringOfSpecifiedLength(this) + case LengthKind.Prefixed => StringOfSpecifiedLength(this) case LengthKind.Delimited => stringDelimitedEndOfData - case LengthKind.Pattern => specifiedLength(StringOfSpecifiedLength(this)) + case LengthKind.Pattern => StringOfSpecifiedLength(this) case LengthKind.Implicit => { val pt = this.simpleType.primType Assert.invariant(pt == PrimType.String) - specifiedLength(StringOfSpecifiedLength(this)) + StringOfSpecifiedLength(this) } case LengthKind.EndOfParent if isComplexType => notYetImplemented("lengthKind='endOfParent' for complex type") @@ -645,7 +651,7 @@ trait ElementBaseGrammarMixin } private lazy val hexBinaryLengthPattern = prod("hexBinaryLengthPattern") { - new SpecifiedLengthPattern(this, new HexBinaryEndOfBitLimit(this)) + new HexBinaryEndOfBitLimit(this) } private lazy val hexBinaryLengthPrefixed = prod("hexBinaryLengthPrefixed") { @@ -1219,7 +1225,7 @@ trait ElementBaseGrammarMixin } private lazy val nilLitSimple = prod("nilLitSimple", isSimpleType) { - captureLengthRegions(leftPadding, specifiedLength(nilLitContent), rightPadding ~ rightFill) + captureLengthRegions(leftPadding, nilLitContent, rightPadding ~ rightFill) } private lazy val nilLitComplex = prod("nilLitComplex", isComplexType) { @@ -1322,59 +1328,70 @@ trait ElementBaseGrammarMixin * as well, by not enclosing the body in a specified length enforcer. */ private def specifiedLength(bodyArg: => Gram) = { - lazy val body = bodyArg - lazy val bitsMultiplier = lengthUnits match { - case LengthUnits.Bits => 1 - case LengthUnits.Bytes => 8 - case LengthUnits.Characters if knownEncodingIsFixedWidth => this.knownEncodingWidthInBits - case _ => 0 // zero means can't multiply to get width in bits. - } - val lk = lengthKind - lk match { - case LengthKind.Delimited => body - case LengthKind.Pattern => new SpecifiedLengthPattern(this, body) - case LengthKind.Explicit if bitsMultiplier != 0 => - new SpecifiedLengthExplicit(this, body, bitsMultiplier) - case LengthKind.Explicit => { - Assert.invariant(!knownEncodingIsFixedWidth) - Assert.invariant(lengthUnits eq LengthUnits.Characters) - new SpecifiedLengthExplicitCharacters(this, body) - } - case LengthKind.Prefixed if (bitsMultiplier != 0) => - new SpecifiedLengthPrefixed(this, body, bitsMultiplier) - case LengthKind.Prefixed => { - Assert.invariant(!knownEncodingIsFixedWidth) - Assert.invariant(lengthUnits eq LengthUnits.Characters) - new SpecifiedLengthPrefixedCharacters(this, body) - } - case LengthKind.Implicit - if isSimpleType && primType == PrimType.String && - encodingInfo.knownEncodingIsFixedWidth => { - // - // Important case to optimize - // If we can convert to a number of bits, then we should do so - // - val nBits = encodingInfo.knownFixedWidthEncodingInCharsToBits(this.maxLength.longValue) - new SpecifiedLengthImplicit(this, body, nBits) + // we need this to evaluate before we wrap in specified length parser, + // so it can do any internal checks for example blobValue's check for + // non-explicit lengthKind + val body = bodyArg + + // there are essentially two categories of processors that read/write data input/output + // stream: those that calculate lengths themselves and those that expect another + // processor to calculate the length and set the bit limit which this processor will use as + // the length. The following determines if this element requires another processor to + // calculate and set the bit limit, and if so adds the appropriate grammar to do that + val bodyRequiresSpecifiedLengthBitLimit = lengthKind != LengthKind.Delimited && ( + isSimpleType && impliedRepresentation == Representation.Text || + isSimpleType && isNillable || + isComplexType && lengthKind != LengthKind.Implicit || + lengthKind == LengthKind.Prefixed || + isSimpleType && primType == PrimType.HexBinary && lengthKind == LengthKind.Pattern + ) + if (!bodyRequiresSpecifiedLengthBitLimit) { + body + } else { + lazy val bitsMultiplier = lengthUnits match { + case LengthUnits.Bits => 1 + case LengthUnits.Bytes => 8 + case LengthUnits.Characters if knownEncodingIsFixedWidth => + this.knownEncodingWidthInBits + case _ => 0 // zero means can't multiply to get width in bits. } - case LengthKind.Implicit if isSimpleType && primType == PrimType.String => - new SpecifiedLengthImplicitCharacters(this, body, this.maxLength.longValue) - - case LengthKind.Implicit if isSimpleType && primType == PrimType.HexBinary => - new SpecifiedLengthImplicit(this, body, this.maxLength.longValue * bitsMultiplier) - case LengthKind.Implicit - if isSimpleType && impliedRepresentation == Representation.Binary => - new SpecifiedLengthImplicit(this, body, implicitBinaryLengthInBits) - case LengthKind.Implicit if isComplexType => - body // for complex types, implicit means "roll up from the bottom" - case LengthKind.EndOfParent if isComplexType => - notYetImplemented("lengthKind='endOfParent' for complex type") - case LengthKind.EndOfParent => - notYetImplemented("lengthKind='endOfParent' for simple type") - case _ => { - // TODO: implement other specified length like end of parent - // for now, no restriction - body + val lk = lengthKind + lk match { + case LengthKind.Pattern => new SpecifiedLengthPattern(this, body) + case LengthKind.Explicit if bitsMultiplier != 0 => + new SpecifiedLengthExplicit(this, body, bitsMultiplier) + case LengthKind.Explicit => { + Assert.invariant(!knownEncodingIsFixedWidth) + Assert.invariant(lengthUnits eq LengthUnits.Characters) + new SpecifiedLengthExplicitCharacters(this, body) + } + case LengthKind.Prefixed if (bitsMultiplier != 0) => + new SpecifiedLengthPrefixed(this, body, bitsMultiplier) + case LengthKind.Prefixed => { + Assert.invariant(!knownEncodingIsFixedWidth) + Assert.invariant(lengthUnits eq LengthUnits.Characters) + new SpecifiedLengthPrefixedCharacters(this, body) + } + case LengthKind.Implicit + if isSimpleType && primType == PrimType.String && + encodingInfo.knownEncodingIsFixedWidth => { + // + // Important case to optimize + // If we can convert to a number of bits, then we should do so + // + val nBits = + encodingInfo.knownFixedWidthEncodingInCharsToBits(this.maxLength.longValue) + new SpecifiedLengthImplicit(this, body, nBits) + } + case LengthKind.Implicit if isSimpleType && primType == PrimType.String => + new SpecifiedLengthImplicitCharacters(this, body, this.maxLength.longValue) + case LengthKind.Implicit + if isSimpleType && impliedRepresentation == Representation.Binary => + new SpecifiedLengthImplicit(this, body, implicitBinaryLengthInBits) + case LengthKind.EndOfParent if isComplexType => + notYetImplemented("lengthKind='endOfParent' for complex type") + case LengthKind.EndOfParent => + notYetImplemented("lengthKind='endOfParent' for simple type") } } } @@ -1396,7 +1413,7 @@ trait ElementBaseGrammarMixin private lazy val sharedComplexContentRegion: Gram = schemaSet.sharedComplexContentFactory.getShared( shareKey, - captureLengthRegions(EmptyGram, specifiedLength(complexContent), elementUnused) ~ + captureLengthRegions(EmptyGram, complexContent, elementUnused) ~ terminatorRegion ) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBCD.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBCD.scala index 550daffa76..154e221376 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBCD.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBCD.scala @@ -19,18 +19,18 @@ package org.apache.daffodil.core.grammar.primitives import org.apache.daffodil.core.dsom.ElementBase import org.apache.daffodil.core.grammar.Terminal +import org.apache.daffodil.runtime1.processors.parsers.BCDDecimalBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.BCDDecimalKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.BCDDecimalPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.BCDDecimalRuntimeLengthParser +import org.apache.daffodil.runtime1.processors.parsers.BCDIntegerBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.BCDIntegerKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.BCDIntegerPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.BCDIntegerRuntimeLengthParser import org.apache.daffodil.runtime1.processors.unparsers.Unparser import org.apache.daffodil.unparsers.runtime1.BCDDecimalKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.BCDDecimalPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.BCDDecimalMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.BCDDecimalRuntimeLengthUnparser import org.apache.daffodil.unparsers.runtime1.BCDIntegerKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.BCDIntegerPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.BCDIntegerMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.BCDIntegerRuntimeLengthUnparser class BCDIntegerRuntimeLength(val e: ElementBase) extends Terminal(e, true) { @@ -52,20 +52,10 @@ class BCDIntegerKnownLength(val e: ElementBase, lengthInBits: Long) extends Term class BCDIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) { - override lazy val parser = new BCDIntegerPrefixedLengthParser( - e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val parser = new BCDIntegerBitLimitLengthParser(e.elementRuntimeData) - override lazy val unparser: Unparser = new BCDIntegerPrefixedLengthUnparser( - e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + override lazy val unparser: Unparser = new BCDIntegerMinimumLengthUnparser( + e.elementRuntimeData ) } @@ -102,21 +92,9 @@ class BCDDecimalKnownLength(val e: ElementBase, lengthInBits: Long) extends Term class BCDDecimalPrefixedLength(val e: ElementBase) extends Terminal(e, true) { - override lazy val parser = new BCDDecimalPrefixedLengthParser( - e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val parser = + new BCDDecimalBitLimitLengthParser(e.elementRuntimeData, e.binaryDecimalVirtualPoint) - override lazy val unparser: Unparser = new BCDDecimalPrefixedLengthUnparser( - e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val unparser: Unparser = + new BCDDecimalMinimumLengthUnparser(e.elementRuntimeData, e.binaryDecimalVirtualPoint) } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryBoolean.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryBoolean.scala index 05a6dfd9b8..b934a24fb5 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryBoolean.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryBoolean.scala @@ -19,10 +19,10 @@ package org.apache.daffodil.core.grammar.primitives import org.apache.daffodil.core.dsom.ElementBase import org.apache.daffodil.core.grammar.Terminal +import org.apache.daffodil.runtime1.processors.parsers.BinaryBooleanBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryBooleanParser -import org.apache.daffodil.runtime1.processors.parsers.BinaryBooleanPrefixedLengthParser import org.apache.daffodil.runtime1.processors.unparsers.Unparser -import org.apache.daffodil.unparsers.runtime1.BinaryBooleanPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.BinaryBooleanMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryBooleanUnparser class BinaryBoolean(val e: ElementBase) extends Terminal(e, true) { @@ -46,23 +46,17 @@ class BinaryBoolean(val e: ElementBase) extends Terminal(e, true) { } class BinaryBooleanPrefixedLength(val e: ElementBase) extends Terminal(e, true) { - override lazy val parser = new BinaryBooleanPrefixedLengthParser( + override lazy val parser = new BinaryBooleanBitLimitLengthParser( e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, e.binaryBooleanTrueRep, e.binaryBooleanFalseRep, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.lengthUnits ) - override lazy val unparser: Unparser = new BinaryBooleanPrefixedLengthUnparser( + override lazy val unparser: Unparser = new BinaryBooleanMinimumLengthUnparser( e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, e.binaryBooleanTrueRep, e.binaryBooleanFalseRep, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.lengthUnits ) } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala index 8c2b4b5940..655f580bfe 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala @@ -22,22 +22,22 @@ import org.apache.daffodil.core.grammar.Terminal import org.apache.daffodil.lib.exceptions.Assert import org.apache.daffodil.lib.util.MaybeInt import org.apache.daffodil.runtime1.dpath.NodeInfo +import org.apache.daffodil.runtime1.processors.parsers.BinaryDecimalBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryDecimalKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.BinaryDecimalPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryDecimalRuntimeLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryDoubleParser import org.apache.daffodil.runtime1.processors.parsers.BinaryFloatParser +import org.apache.daffodil.runtime1.processors.parsers.BinaryIntegerBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryIntegerKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.BinaryIntegerPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.BinaryIntegerRuntimeLengthParser import org.apache.daffodil.runtime1.processors.unparsers.Unparser import org.apache.daffodil.unparsers.runtime1.BinaryDecimalKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.BinaryDecimalPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.BinaryDecimalMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryDecimalRuntimeLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryDoubleUnparser import org.apache.daffodil.unparsers.runtime1.BinaryFloatUnparser import org.apache.daffodil.unparsers.runtime1.BinaryIntegerKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.BinaryIntegerPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.BinaryIntegerMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryIntegerRuntimeLengthUnparser class BinaryIntegerRuntimeLength(val e: ElementBase) extends Terminal(e, true) { @@ -69,17 +69,9 @@ class BinaryIntegerKnownLength(val e: ElementBase, val lengthInBits: Long) class BinaryIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) { private lazy val erd = e.elementRuntimeData - private lazy val plerd = e.prefixedLengthElementDecl.elementRuntimeData - private lazy val pladj = e.prefixedLengthAdjustmentInUnits override lazy val parser = - new BinaryIntegerPrefixedLengthParser( - erd, - e.prefixedLengthBody.parser, - plerd, - e.lengthUnits, - pladj - ) + new BinaryIntegerBitLimitLengthParser(erd) override lazy val unparser: Unparser = { val maybeNBits = e.primType match { @@ -91,14 +83,7 @@ class BinaryIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) case _ => Assert.invariantFailed("Only integer base types should be used for this primitive") } - new BinaryIntegerPrefixedLengthUnparser( - erd, - e.prefixedLengthBody.unparser, - plerd, - maybeNBits, - e.lengthUnits, - pladj - ) + new BinaryIntegerMinimumLengthUnparser(erd, maybeNBits) } } @@ -143,25 +128,17 @@ class BinaryDecimalKnownLength(val e: ElementBase, lengthInBits: Long) class BinaryDecimalPrefixedLength(val e: ElementBase) extends Terminal(e, true) { override lazy val parser = - new BinaryDecimalPrefixedLengthParser( + new BinaryDecimalBitLimitLengthParser( e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, e.decimalSigned, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.binaryDecimalVirtualPoint ) override lazy val unparser: Unparser = - new BinaryDecimalPrefixedLengthUnparser( + new BinaryDecimalMinimumLengthUnparser( e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, e.decimalSigned, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.binaryDecimalVirtualPoint ) } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala index a5380474f5..1316426de5 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala @@ -19,18 +19,18 @@ package org.apache.daffodil.core.grammar.primitives import org.apache.daffodil.core.dsom.ElementBase import org.apache.daffodil.core.grammar.Terminal +import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedDecimalBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedDecimalKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedDecimalPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedDecimalRuntimeLengthParser +import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedIntegerBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedIntegerKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedIntegerPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedIntegerRuntimeLengthParser import org.apache.daffodil.runtime1.processors.unparsers.Unparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedDecimalKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.IBM4690PackedDecimalPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.IBM4690PackedDecimalMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedDecimalRuntimeLengthUnparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerRuntimeLengthUnparser class IBM4690PackedIntegerRuntimeLength(val e: ElementBase) extends Terminal(e, true) { @@ -58,20 +58,11 @@ class IBM4690PackedIntegerKnownLength(val e: ElementBase, lengthInBits: Long) } class IBM4690PackedIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) { - override lazy val parser = new IBM4690PackedIntegerPrefixedLengthParser( - e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val parser = + new IBM4690PackedIntegerBitLimitLengthParser(e.elementRuntimeData) - override lazy val unparser: Unparser = new IBM4690PackedIntegerPrefixedLengthUnparser( - e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + override lazy val unparser: Unparser = new IBM4690PackedIntegerMinimumLengthUnparser( + e.elementRuntimeData ) } @@ -108,21 +99,13 @@ class IBM4690PackedDecimalKnownLength(val e: ElementBase, lengthInBits: Long) } class IBM4690PackedDecimalPrefixedLength(val e: ElementBase) extends Terminal(e, true) { - override lazy val parser = new IBM4690PackedDecimalPrefixedLengthParser( + override lazy val parser = new IBM4690PackedDecimalBitLimitLengthParser( e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.binaryDecimalVirtualPoint ) - override lazy val unparser: Unparser = new IBM4690PackedDecimalPrefixedLengthUnparser( + override lazy val unparser: Unparser = new IBM4690PackedDecimalMinimumLengthUnparser( e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.binaryDecimalVirtualPoint, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + e.binaryDecimalVirtualPoint ) } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala index 21baad5654..09ce2c1df1 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala @@ -34,7 +34,6 @@ import org.apache.daffodil.runtime1.processors.parsers.BCDIntegerDelimitedParser import org.apache.daffodil.runtime1.processors.parsers.BlobSpecifiedLengthParser import org.apache.daffodil.runtime1.processors.parsers.HexBinaryDelimitedParser import org.apache.daffodil.runtime1.processors.parsers.HexBinaryEndOfBitLimitParser -import org.apache.daffodil.runtime1.processors.parsers.HexBinaryLengthPrefixedParser import org.apache.daffodil.runtime1.processors.parsers.HexBinarySpecifiedLengthParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedDecimalDelimitedParser import org.apache.daffodil.runtime1.processors.parsers.IBM4690PackedIntegerDelimitedParser @@ -48,7 +47,6 @@ import org.apache.daffodil.runtime1.processors.unparsers.{ Unparser => DaffodilU import org.apache.daffodil.unparsers.runtime1.BCDDecimalDelimitedUnparser import org.apache.daffodil.unparsers.runtime1.BCDIntegerDelimitedUnparser import org.apache.daffodil.unparsers.runtime1.BlobSpecifiedLengthUnparser -import org.apache.daffodil.unparsers.runtime1.HexBinaryLengthPrefixedUnparser import org.apache.daffodil.unparsers.runtime1.HexBinaryMinLengthInBytesUnparser import org.apache.daffodil.unparsers.runtime1.HexBinarySpecifiedLengthUnparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedDecimalDelimitedUnparser @@ -185,22 +183,12 @@ case class HexBinaryEndOfBitLimit(e: ElementBase) extends Terminal(e, true) { case class HexBinaryLengthPrefixed(e: ElementBase) extends Terminal(e, true) { - override lazy val parser: DaffodilParser = new HexBinaryLengthPrefixedParser( - e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + override lazy val parser: DaffodilParser = new HexBinaryEndOfBitLimitParser( + e.elementRuntimeData ) - override lazy val unparser: DaffodilUnparser = new HexBinaryLengthPrefixedUnparser( - e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - e.minLength.longValue, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val unparser: DaffodilUnparser = + new HexBinaryMinLengthInBytesUnparser(e.minLength.longValue, e.elementRuntimeData) } abstract class PackedIntegerDelimited( diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala index c0f7a73ecd..109abfef9c 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala @@ -20,18 +20,18 @@ package org.apache.daffodil.core.grammar.primitives import org.apache.daffodil.core.dsom.ElementBase import org.apache.daffodil.core.grammar.Terminal import org.apache.daffodil.lib.util.PackedSignCodes +import org.apache.daffodil.runtime1.processors.parsers.PackedDecimalBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.PackedDecimalKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.PackedDecimalPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.PackedDecimalRuntimeLengthParser +import org.apache.daffodil.runtime1.processors.parsers.PackedIntegerBitLimitLengthParser import org.apache.daffodil.runtime1.processors.parsers.PackedIntegerKnownLengthParser -import org.apache.daffodil.runtime1.processors.parsers.PackedIntegerPrefixedLengthParser import org.apache.daffodil.runtime1.processors.parsers.PackedIntegerRuntimeLengthParser import org.apache.daffodil.runtime1.processors.unparsers.Unparser import org.apache.daffodil.unparsers.runtime1.PackedDecimalKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.PackedDecimalPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.PackedDecimalMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.PackedDecimalRuntimeLengthUnparser import org.apache.daffodil.unparsers.runtime1.PackedIntegerKnownLengthUnparser -import org.apache.daffodil.unparsers.runtime1.PackedIntegerPrefixedLengthUnparser +import org.apache.daffodil.unparsers.runtime1.PackedIntegerMinimumLengthUnparser import org.apache.daffodil.unparsers.runtime1.PackedIntegerRuntimeLengthUnparser class PackedIntegerRuntimeLength( @@ -77,23 +77,11 @@ class PackedIntegerPrefixedLength( packedSignCodes: PackedSignCodes ) extends Terminal(e, true) { - override lazy val parser = new PackedIntegerPrefixedLengthParser( - e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, - packedSignCodes, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val parser = + new PackedIntegerBitLimitLengthParser(e.elementRuntimeData, packedSignCodes) - override lazy val unparser: Unparser = new PackedIntegerPrefixedLengthUnparser( - e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, - packedSignCodes, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits - ) + override lazy val unparser: Unparser = + new PackedIntegerMinimumLengthUnparser(e.elementRuntimeData, packedSignCodes) } class PackedDecimalRuntimeLength(val e: ElementBase, packedSignCodes: PackedSignCodes) @@ -139,23 +127,15 @@ class PackedDecimalKnownLength( class PackedDecimalPrefixedLength(val e: ElementBase, packedSignCodes: PackedSignCodes) extends Terminal(e, true) { - override lazy val parser = new PackedDecimalPrefixedLengthParser( + override lazy val parser = new PackedDecimalBitLimitLengthParser( e.elementRuntimeData, - e.prefixedLengthBody.parser, - e.prefixedLengthElementDecl.elementRuntimeData, e.binaryDecimalVirtualPoint, - packedSignCodes, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + packedSignCodes ) - override lazy val unparser: Unparser = new PackedDecimalPrefixedLengthUnparser( + override lazy val unparser: Unparser = new PackedDecimalMinimumLengthUnparser( e.elementRuntimeData, - e.prefixedLengthBody.unparser, - e.prefixedLengthElementDecl.elementRuntimeData, e.binaryDecimalVirtualPoint, - packedSignCodes, - e.lengthUnits, - e.prefixedLengthAdjustmentInUnits + packedSignCodes ) } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala index aa2e6a1dd8..2a4ef31fa3 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala @@ -24,7 +24,7 @@ import org.apache.daffodil.core.dsom.PrimitiveType import org.apache.daffodil.core.dsom.Root import org.apache.daffodil.core.dsom.SimpleTypeDefBase import org.apache.daffodil.lib.schema.annotation.props.gen.LengthKind -import org.apache.daffodil.lib.schema.annotation.props.gen.Representation +import org.apache.daffodil.lib.schema.annotation.props.gen.Representation.Text import org.apache.daffodil.lib.util.Delay import org.apache.daffodil.lib.util.Maybe import org.apache.daffodil.runtime1.dsom.DPathElementCompileInfo @@ -65,7 +65,12 @@ trait ElementBaseRuntime1Mixin { self: ElementBase => // no reason (unless it is referenced in a contentLength expression). val mightHaveSuspensions = (maybeFixedLengthInBits.isDefined && couldHaveSuspensions) - isReferenced || mightHaveSuspensions + // we want to capture contentlength when LK = prefixed because + // some prefixed length unparsers are unable to calculate the prefixed length + // of the field. Instead, they unparse the field to a buffer and the captured + // content length of the buffer is used. For this reason, prefixed length + // elements must capture content length for unparse. + lengthKind == LengthKind.Prefixed || isReferenced || mightHaveSuspensions } /** @@ -89,17 +94,18 @@ trait ElementBaseRuntime1Mixin { self: ElementBase => // // For complex elements with specified length, value length is captured in // the specified length parsers, since they handle skipping unused - // element regions. For complex elements, this means lengthKind is not + // element regions, and the length capturing has to be done before that. + // For complex elements, this means lengthKind is not // implicit or delimited. // // So for these cases we do not want to capture value length with the // Capture{Start,End}OfValueLengthParsers, since those lengths are captured // by the value parsers - val capturedByParsers = - (isSimpleType && (impliedRepresentation == Representation.Text || lengthKind == LengthKind.Delimited)) || + val capturedByValueParsers = + (isSimpleType && (impliedRepresentation == Text || lengthKind == LengthKind.Delimited)) || (isComplexType && (lengthKind != LengthKind.Implicit && lengthKind != LengthKind.Delimited)) - !capturedByParsers && isReferenced + !capturedByValueParsers && isReferenced } /** diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BCDUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BCDUnparsers.scala index 84dde6a128..86c80ba430 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BCDUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BCDUnparsers.scala @@ -25,7 +25,6 @@ import org.apache.daffodil.lib.util.DecimalUtils import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.parsers.HasKnownLengthInBits import org.apache.daffodil.runtime1.processors.parsers.HasRuntimeExplicitLength import org.apache.daffodil.runtime1.processors.unparsers._ @@ -57,16 +56,9 @@ final class BCDIntegerDelimitedUnparser(e: ElementRuntimeData) override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class BCDIntegerPrefixedLengthUnparser( - e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BCDIntegerBaseUnparser(e) - with KnownPrefixedLengthUnparserMixin { +final class BCDIntegerMinimumLengthUnparser(e: ElementRuntimeData) + extends BCDIntegerBaseUnparser(e) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -75,11 +67,6 @@ final class BCDIntegerPrefixedLengthUnparser( val (byteLength, _) = DecimalUtils.bcdFromBigIntegerLength(absBigIntStr, 0) byteLength * 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } abstract class BCDDecimalBaseUnparser(e: ElementRuntimeData, binaryDecimalVirtualPoint: Int) @@ -113,17 +100,11 @@ final class BCDDecimalDelimitedUnparser(e: ElementRuntimeData, binaryDecimalVirt override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class BCDDecimalPrefixedLengthUnparser( +final class BCDDecimalMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BCDDecimalBaseUnparser(e, binaryDecimalVirtualPoint) - with KnownPrefixedLengthUnparserMixin { + binaryDecimalVirtualPoint: Int +) extends BCDDecimalBaseUnparser(e, binaryDecimalVirtualPoint) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -132,9 +113,4 @@ final class BCDDecimalPrefixedLengthUnparser( val (byteLength, _) = DecimalUtils.bcdFromBigIntegerLength(absBigIntStr, 0) byteLength * 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryBooleanUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryBooleanUnparsers.scala index 8f57d2b59a..59bb85d04c 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryBooleanUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryBooleanUnparsers.scala @@ -30,7 +30,6 @@ import org.apache.daffodil.lib.util.Numbers import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.unparsers._ import passera.unsigned.ULong @@ -129,26 +128,20 @@ class BinaryBooleanUnparser( } } -class BinaryBooleanPrefixedLengthUnparser( +class BinaryBooleanMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, binaryBooleanTrueRep: MaybeULong, binaryBooleanFalseRep: ULong, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryBooleanUnparserBase(e, binaryBooleanTrueRep, binaryBooleanFalseRep, lengthUnits) - with KnownPrefixedLengthUnparserMixin { - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) + lengthUnits: LengthUnits +) extends BinaryBooleanUnparserBase( + e, + binaryBooleanTrueRep, + binaryBooleanFalseRep, + lengthUnits + ) { override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = 32 - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } - } diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala index b4f99d9ab2..437587def9 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala @@ -32,7 +32,6 @@ import org.apache.daffodil.runtime1.dpath.NodeInfo import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.parsers.BinaryNumberCheckWidth import org.apache.daffodil.runtime1.processors.parsers.HasKnownLengthInBits import org.apache.daffodil.runtime1.processors.parsers.HasRuntimeExplicitLength @@ -126,19 +125,13 @@ class BinaryIntegerRuntimeLengthUnparser( override val runtimeDependencies = Vector(lengthEv) } -class BinaryIntegerPrefixedLengthUnparser( +class BinaryIntegerMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - maybeNBits: MaybeInt, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryIntegerBaseUnparser(e: ElementRuntimeData) - with KnownPrefixedLengthUnparserMixin { + maybeNBits: MaybeInt +) extends BinaryIntegerBaseUnparser(e: ElementRuntimeData) { private val primNumeric = e.optPrimType.get.asInstanceOf[NodeInfo.PrimType.PrimNumeric] - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -154,11 +147,6 @@ class BinaryIntegerPrefixedLengthUnparser( (signedLen + 7) & ~0x7 // round up to nearest multilpe of 8 } } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } class BinaryFloatUnparser(e: ElementRuntimeData) extends BinaryNumberBaseUnparser(e) { @@ -218,18 +206,12 @@ class BinaryDecimalRuntimeLengthUnparser( override val runtimeDependencies = Vector(lengthEv) } -class BinaryDecimalPrefixedLengthUnparser( +class BinaryDecimalMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, signed: YesNo, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryDecimalUnparserBase(e, signed, binaryDecimalVirtualPoint) - with KnownPrefixedLengthUnparserMixin { + binaryDecimalVirtualPoint: Int +) extends BinaryDecimalUnparserBase(e, signed, binaryDecimalVirtualPoint) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -240,11 +222,6 @@ class BinaryDecimalPrefixedLengthUnparser( val signedLen = if (signed == YesNo.Yes) len + 1 else len (signedLen + 7) & ~0x7 // round up to nearest multilpe of 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } abstract class BinaryDecimalUnparserBase( diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HexBinaryLengthUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HexBinaryLengthUnparser.scala index 6fa3d845e7..2bd7d316ff 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HexBinaryLengthUnparser.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HexBinaryLengthUnparser.scala @@ -18,12 +18,9 @@ package org.apache.daffodil.unparsers.runtime1 import org.apache.daffodil.lib.exceptions.Assert -import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.util.Maybe._ import org.apache.daffodil.runtime1.infoset.RetryableException import org.apache.daffodil.runtime1.processors.ElementRuntimeData -import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.UnparseTargetLengthInBitsEv import org.apache.daffodil.runtime1.processors.unparsers._ @@ -129,26 +126,3 @@ final class HexBinarySpecifiedLengthUnparser( l } } - -final class HexBinaryLengthPrefixedUnparser( - erd: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - minLengthInBytes: Long, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends HexBinaryMinLengthInBytesUnparser(minLengthInBytes, erd) - with KnownPrefixedLengthUnparserMixin { - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - val bits = getLengthInBits(state.asInstanceOf[UState]) - bits.toInt - } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } -} diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/IBM4690PackedDecimalUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/IBM4690PackedDecimalUnparsers.scala index c401643e7e..1fb458cf9a 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/IBM4690PackedDecimalUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/IBM4690PackedDecimalUnparsers.scala @@ -25,7 +25,6 @@ import org.apache.daffodil.lib.util.DecimalUtils import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.parsers.HasKnownLengthInBits import org.apache.daffodil.runtime1.processors.parsers.HasRuntimeExplicitLength import org.apache.daffodil.runtime1.processors.unparsers._ @@ -59,16 +58,9 @@ final class IBM4690PackedIntegerDelimitedUnparser(e: ElementRuntimeData) override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class IBM4690PackedIntegerPrefixedLengthUnparser( - e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends IBM4690PackedIntegerBaseUnparser(e) - with KnownPrefixedLengthUnparserMixin { +final class IBM4690PackedIntegerMinimumLengthUnparser(e: ElementRuntimeData) + extends IBM4690PackedIntegerBaseUnparser(e) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -79,11 +71,6 @@ final class IBM4690PackedIntegerPrefixedLengthUnparser( val (byteLength, _) = DecimalUtils.ibm4690FromBigIntegerLength(absBigIntStr, 0, negative) byteLength * 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } abstract class IBM4690PackedDecimalBaseUnparser( @@ -121,17 +108,11 @@ final class IBM4690PackedDecimalDelimitedUnparser( override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class IBM4690PackedDecimalPrefixedLengthUnparser( +final class IBM4690PackedDecimalMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends IBM4690PackedDecimalBaseUnparser(e, binaryDecimalVirtualPoint) - with KnownPrefixedLengthUnparserMixin { + binaryDecimalVirtualPoint: Int +) extends IBM4690PackedDecimalBaseUnparser(e, binaryDecimalVirtualPoint) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -142,9 +123,4 @@ final class IBM4690PackedDecimalPrefixedLengthUnparser( val (byteLength, _) = DecimalUtils.ibm4690FromBigIntegerLength(absBigIntStr, 0, negative) byteLength * 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedDecimalUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedDecimalUnparsers.scala index ccad3a7a46..c378f80b3f 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedDecimalUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedDecimalUnparsers.scala @@ -25,7 +25,6 @@ import org.apache.daffodil.lib.util.{ DecimalUtils, PackedSignCodes } import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.parsers.HasKnownLengthInBits import org.apache.daffodil.runtime1.processors.parsers.HasRuntimeExplicitLength import org.apache.daffodil.runtime1.processors.unparsers._ @@ -65,17 +64,11 @@ final class PackedIntegerDelimitedUnparser( override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class PackedIntegerPrefixedLengthUnparser( +final class PackedIntegerMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, - packedSignCodes: PackedSignCodes, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends PackedIntegerBaseUnparser(e, packedSignCodes) - with KnownPrefixedLengthUnparserMixin { + packedSignCodes: PackedSignCodes +) extends PackedIntegerBaseUnparser(e, packedSignCodes) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -84,11 +77,6 @@ final class PackedIntegerPrefixedLengthUnparser( val (byteLength, _) = DecimalUtils.packedFromBigIntegerLength(absBigIntStr, 0) byteLength * 8 } - - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } } abstract class PackedDecimalBaseUnparser( @@ -130,18 +118,12 @@ final class PackedDecimalDelimitedUnparser( override def getBitLength(state: ParseOrUnparseState): Int = { 0 } } -final class PackedDecimalPrefixedLengthUnparser( +final class PackedDecimalMinimumLengthUnparser( e: ElementRuntimeData, - override val prefixedLengthUnparser: Unparser, - override val prefixedLengthERD: ElementRuntimeData, binaryDecimalVirtualPoint: Int, - packedSignCodes: PackedSignCodes, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends PackedDecimalBaseUnparser(e, binaryDecimalVirtualPoint, packedSignCodes) - with KnownPrefixedLengthUnparserMixin { + packedSignCodes: PackedSignCodes +) extends PackedDecimalBaseUnparser(e, binaryDecimalVirtualPoint, packedSignCodes) { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() override def getBitLength(s: ParseOrUnparseState): Int = { @@ -151,9 +133,4 @@ final class PackedDecimalPrefixedLengthUnparser( byteLength * 8 } - override def unparse(state: UState): Unit = { - unparsePrefixedLength(state) - super.unparse(state) - } - } diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLength2.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLength2.scala index 3dcebfa9d6..957110f4e4 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLength2.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLength2.scala @@ -931,11 +931,11 @@ class PrefixLengthSuspendableOperation( override protected def maybeKnownLengthInBits(ustate: UState): MaybeULong = MaybeULong(0L) override def test(ustate: UState): Boolean = { - elem.valueLength.maybeLengthInBits.isDefined + elem.contentLength.maybeLengthInBits.isDefined } override def continuation(state: UState): Unit = { - val len = elem.valueLength.maybeLengthInBits.isDefined + val len = elem.contentLength.maybeLengthInBits.isDefined assignPrefixLength(state, elem, plElem) } } diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLengthUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLengthUnparsers.scala index f2ec32e9b3..d8e9bc3c48 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLengthUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLengthUnparsers.scala @@ -26,7 +26,6 @@ import org.apache.daffodil.runtime1.infoset.DISimple import org.apache.daffodil.runtime1.infoset.Infoset import org.apache.daffodil.runtime1.processors.CharsetEv import org.apache.daffodil.runtime1.processors.ElementRuntimeData -import org.apache.daffodil.runtime1.processors.ParseOrUnparseState import org.apache.daffodil.runtime1.processors.UnparseTargetLengthInBitsEv import org.apache.daffodil.runtime1.processors.unparsers._ @@ -73,85 +72,10 @@ final class SpecifiedLengthExplicitImplicitUnparser( } } -// TODO: implement the capture length unparsers as just using this trait? -trait CaptureUnparsingValueLength { - - def captureValueLengthStart(state: UState, elem: DIElement): Unit = { - val dos = state.dataOutputStream - if (dos.maybeAbsBitPos0b.isDefined) { - elem.valueLength.setAbsStartPos0bInBits(dos.maybeAbsBitPos0b.getULong) - } else { - elem.valueLength.setRelStartPos0bInBits(dos.relBitPos0b, dos) - } - } - - def captureValueLengthEnd(state: UState, elem: DIElement): Unit = { - val dos = state.dataOutputStream - if (dos.maybeAbsBitPos0b.isDefined) { - elem.valueLength.setAbsEndPos0bInBits(dos.maybeAbsBitPos0b.getULong) - } else { - elem.valueLength.setRelEndPos0bInBits(dos.relBitPos0b, dos) - } - } -} - -/** - * This trait is to be used with prefixed length unparsers where the length is - * known without needing to unparse the data. This means there is either a - * fixed length (like in the case of some binary numbers), or the length can be - * determined completly be inspecting the infoset data (like in the case of - * packed decimals). The length calculation performed in the getBitLength - * function, which returns the length of the data in bits. - */ -trait KnownPrefixedLengthUnparserMixin { - def prefixedLengthERD: ElementRuntimeData - def prefixedLengthUnparser: Unparser - def lengthUnits: LengthUnits - def getBitLength(s: ParseOrUnparseState): Int - def prefixedLengthAdjustmentInUnits: Long - - def unparsePrefixedLength(state: UState): Unit = { - val bits = getBitLength(state) - val lenInUnits = - if (lengthUnits == LengthUnits.Bytes) { - bits >> 3 - } else { - bits - } - val adjustedLenInUnits = lenInUnits + prefixedLengthAdjustmentInUnits - // Create a "detached" DIDocument with a single child element that the - // prefix length will be unparsed from. This creates a completely new - // infoset and unparses from that, so care is taken to ensure this infoset - // is only used for the prefix length unparsing and is removed afterwards - val plElement = Infoset.newDetachedElement(state, prefixedLengthERD).asInstanceOf[DISimple] - - plElement.setDataValue(java.lang.Integer.valueOf(adjustedLenInUnits.toInt)) - - // do checks on facets expressed on prefixLengthType - val optSTRD = plElement.erd.optSimpleTypeRuntimeData - if (optSTRD.isDefined) { - val strd = optSTRD.get - val check = strd.executeCheck(plElement) - if (check.isError) { - UnparseError( - One(state.schemaFileLocation), - One(state.currentLocation), - s"The calculated value of ${prefixedLengthERD.namedQName} ($adjustedLenInUnits) failed check due to ${check.errMsg}" - ) - } - } - - // unparse the prefixed length element - state.currentInfosetNodeStack.push(One(plElement)) - prefixedLengthUnparser.unparse1(state) - state.currentInfosetNodeStack.pop - } -} - /** * This trait is to be used with prefixed length unparsers where the length - * must be calculated based on the value length of the data. This means the - * data must be unparsed, the value length calculated, and that value will be + * must be calculated based on the content length of the data. This means the + * data must be unparsed, the content length calculated, and that value will be * assigned to the prefix length element. */ trait CalculatedPrefixedLengthUnparserMixin { @@ -168,16 +92,16 @@ trait CalculatedPrefixedLengthUnparserMixin { */ def assignPrefixLength(state: UState, elem: DIElement, plElem: DISimple): Unit = { val lenInUnits = lengthUnits match { - case LengthUnits.Bits => elem.valueLength.lengthInBits - case LengthUnits.Bytes => elem.valueLength.lengthInBytes + case LengthUnits.Bits => elem.contentLength.lengthInBits + case LengthUnits.Bytes => elem.contentLength.lengthInBytes case LengthUnits.Characters => { val maybeFixedWidth = elem.erd.encInfo.getEncoderInfo(state).coder.bitsCharset.maybeFixedWidth val lengthInChars = if (maybeFixedWidth.isDefined) { val fixedWidth = maybeFixedWidth.get - Assert.invariant((elem.valueLength.lengthInBits % fixedWidth) == 0) // divisible - elem.valueLength.lengthInBits / fixedWidth + Assert.invariant((elem.contentLength.lengthInBits % fixedWidth) == 0) // divisible + elem.contentLength.lengthInBits / fixedWidth } else { // This is checked for statically, so should not get here. // $COVERAGE-OFF$ @@ -200,7 +124,7 @@ trait CalculatedPrefixedLengthUnparserMixin { UnparseError( One(state.schemaFileLocation), One(state.currentLocation), - s"The calculated value of ${elem.namedQName} ($adjustedLenInUnits) failed check due to ${check.errMsg}" + s"The prefix length value of ${elem.namedQName} ($adjustedLenInUnits) failed check due to ${check.errMsg}" ) } } @@ -215,7 +139,6 @@ class SpecifiedLengthPrefixedUnparser( override val lengthUnits: LengthUnits, override val prefixedLengthAdjustmentInUnits: Long ) extends CombinatorUnparser(erd) - with CaptureUnparsingValueLength with CalculatedPrefixedLengthUnparserMixin { override lazy val runtimeDependencies = Vector() @@ -238,13 +161,10 @@ class SpecifiedLengthPrefixedUnparser( prefixedLengthUnparser.unparse1(state) state.currentInfosetNodeStack.pop - // We now need to capture the length of the actual element val elem = state.currentInfosetNode.asInstanceOf[DIElement] - captureValueLengthStart(state, elem) eUnparser.unparse1(state) - captureValueLengthEnd(state, elem) - if (elem.valueLength.maybeLengthInBits.isDefined) { + if (elem.contentLength.maybeLengthInBits.isDefined) { // If we were able to immediately calculate the length of the element, // then just set it as the value of the detached element created above so // that when the prefixedLengthUnparser suspension resumes it can unparse @@ -253,7 +173,7 @@ class SpecifiedLengthPrefixedUnparser( } else { // The length was not able to be calculated, likely because there was a // suspension when unparsing the eUnparser. So let's create a new - // suspension with the only goal to retry until the valueLength of this + // suspension with the only goal to retry until the contentLength of this // element is determined. Once determined, it will set the value of the // prefix length element, ultimately allowing the prefix length element // suspension to resume and unparse the value diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala index 1aed39f826..03c4c15e1b 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala @@ -733,6 +733,10 @@ sealed abstract class LengthState(ie: DIElement) { } def setAbsStartPos0bInBits(absPosInBits0b: ULong): Unit = { + Assert.invariant( + maybeStartPos0bInBits.isEmpty, + s"maybeStartPos0bInBits already has a value: $maybeStartPos0bInBits" + ) maybeStartPos0bInBits = MaybeULong(absPosInBits0b.longValue) maybeStartDataOutputStream = Nope } @@ -743,6 +747,10 @@ sealed abstract class LengthState(ie: DIElement) { } def setAbsEndPos0bInBits(absPosInBits0b: ULong): Unit = { + Assert.invariant( + maybeEndPos0bInBits.isEmpty, + s"maybeEndPos0bInBits already has a value: $maybeEndPos0bInBits" + ) maybeEndPos0bInBits = MaybeULong(absPosInBits0b.longValue) maybeEndDataOutputStream = Nope } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala index e18eecd502..60dae90905 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala @@ -24,8 +24,6 @@ import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.util.DecimalUtils import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable -import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor class BCDDecimalKnownLengthParser( e: ElementRuntimeData, @@ -52,25 +50,14 @@ class BCDDecimalRuntimeLengthParser( } -class BCDDecimalPrefixedLengthParser( +class BCDDecimalBitLimitLengthParser( e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + binaryDecimalVirtualPoint: Int ) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint) - with PrefixedLengthParserMixin { + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigDecimal = DecimalUtils.bcdToBigDecimal(num, binaryDecimalVirtualPoint) - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } - } class BCDIntegerRuntimeLengthParser( @@ -92,20 +79,9 @@ class BCDIntegerKnownLengthParser(e: ElementRuntimeData, val lengthInBits: Int) } -class BCDIntegerPrefixedLengthParser( - e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends PackedBinaryIntegerBaseParser(e) - with PrefixedLengthParserMixin { +class BCDIntegerBitLimitLengthParser(e: ElementRuntimeData) + extends PackedBinaryIntegerBaseParser(e) + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigInteger = DecimalUtils.bcdToBigInteger(num) - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala index e0a3598188..077c766713 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala @@ -24,8 +24,6 @@ import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.util.DecimalUtils import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable -import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor class IBM4690PackedDecimalKnownLengthParser( e: ElementRuntimeData, @@ -52,25 +50,15 @@ class IBM4690PackedDecimalRuntimeLengthParser( } -class IBM4690PackedDecimalPrefixedLengthParser( +class IBM4690PackedDecimalBitLimitLengthParser( e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + binaryDecimalVirtualPoint: Int ) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint) - with PrefixedLengthParserMixin { + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigDecimal = DecimalUtils.ibm4690ToBigDecimal(num, binaryDecimalVirtualPoint) - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } - } class IBM4690PackedIntegerRuntimeLengthParser( @@ -96,21 +84,11 @@ class IBM4690PackedIntegerKnownLengthParser( } -class IBM4690PackedIntegerPrefixedLengthParser( - e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends PackedBinaryIntegerBaseParser(e) - with PrefixedLengthParserMixin { +class IBM4690PackedIntegerBitLimitLengthParser(e: ElementRuntimeData) + extends PackedBinaryIntegerBaseParser(e) + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigInteger = DecimalUtils.ibm4690ToBigInteger(num) - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala index 7e19f2d1ff..1ac74993d8 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala @@ -24,8 +24,6 @@ import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.util.{ DecimalUtils, PackedSignCodes } import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable -import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor class PackedDecimalKnownLengthParser( e: ElementRuntimeData, @@ -53,26 +51,15 @@ class PackedDecimalRuntimeLengthParser( DecimalUtils.packedToBigDecimal(num, binaryDecimalVirtualPoint, packedSignCodes) } -class PackedDecimalPrefixedLengthParser( +class PackedDecimalBitLimitLengthParser( e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, binaryDecimalVirtualPoint: Int, - packedSignCodes: PackedSignCodes, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + packedSignCodes: PackedSignCodes ) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint) - with PrefixedLengthParserMixin { + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigDecimal = DecimalUtils.packedToBigDecimal(num, binaryDecimalVirtualPoint, packedSignCodes) - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } - } class PackedIntegerRuntimeLengthParser( @@ -100,22 +87,13 @@ class PackedIntegerKnownLengthParser( } -class PackedIntegerPrefixedLengthParser( +class PackedIntegerBitLimitLengthParser( e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - packedSignCodes: PackedSignCodes, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + packedSignCodes: PackedSignCodes ) extends PackedBinaryIntegerBaseParser(e) - with PrefixedLengthParserMixin { + with BitLengthFromBitLimitMixin { override def toNumber(num: Array[Byte]): JBigInteger = DecimalUtils.packedToBigInteger(num, packedSignCodes) - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala index ee7e85ba3b..3ce64df07a 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala @@ -26,7 +26,6 @@ import org.apache.daffodil.lib.util.MaybeULong import org.apache.daffodil.lib.util.Numbers import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable -import org.apache.daffodil.runtime1.processors.Processor import passera.unsigned.ULong @@ -106,21 +105,17 @@ class BinaryBooleanParser( } } -class BinaryBooleanPrefixedLengthParser( +class BinaryBooleanBitLimitLengthParser( override val context: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, binaryBooleanTrueRep: MaybeULong, binaryBooleanFalseRep: ULong, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + lengthUnits: LengthUnits ) extends BinaryBooleanParserBase(binaryBooleanTrueRep, binaryBooleanFalseRep, lengthUnits) - with PrefixedLengthParserMixin { + with BitLengthFromBitLimitMixin { - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) override val runtimeDependencies = Vector() override def getBitLength(state: PState): Int = { - getPrefixedLengthInBits(state).toInt + getLengthInBits(state).toInt } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala index fac7a9078f..1b65a6e08c 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala @@ -28,7 +28,6 @@ import org.apache.daffodil.runtime1.dpath.NodeInfo import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState -import org.apache.daffodil.runtime1.processors.Processor import org.apache.daffodil.runtime1.processors.unparsers.UState class BinaryFloatParser(override val context: ElementRuntimeData) extends PrimParser { @@ -80,23 +79,12 @@ class BinaryDecimalRuntimeLengthParser( ) extends BinaryDecimalParserBase(e, signed, binaryDecimalVirtualPoint) with HasRuntimeExplicitLength {} -class BinaryDecimalPrefixedLengthParser( +class BinaryDecimalBitLimitLengthParser( e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, signed: YesNo, - binaryDecimalVirtualPoint: Int, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long + binaryDecimalVirtualPoint: Int ) extends BinaryDecimalParserBase(e, signed, binaryDecimalVirtualPoint) - with PrefixedLengthParserMixin { - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } -} + with BitLengthFromBitLimitMixin abstract class BinaryDecimalParserBase( override val context: ElementRuntimeData, @@ -142,21 +130,9 @@ class BinaryIntegerKnownLengthParser( ) extends BinaryIntegerBaseParser(e) with HasKnownLengthInBits {} -class BinaryIntegerPrefixedLengthParser( - e: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryIntegerBaseParser(e) - with PrefixedLengthParserMixin { - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - - override def getBitLength(state: ParseOrUnparseState): Int = { - getPrefixedLengthInBits(state.asInstanceOf[PState]).toInt - } -} +class BinaryIntegerBitLimitLengthParser(e: ElementRuntimeData) + extends BinaryIntegerBaseParser(e) + with BitLengthFromBitLimitMixin abstract class BinaryIntegerBaseParser( override val context: ElementRuntimeData diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala index 29317a2952..9641aef5f1 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala @@ -110,7 +110,7 @@ trait PrefixedLengthParserMixin { val check = strd.executeCheck(plElement) if (check.isError) { val pe = state.toProcessingError( - s"The value of ${prefixedLengthERD.namedQName} ($parsedLen) failed check due to ${check.errMsg}" + s"The prefix length value of ${savedInfoset.namedQName} ($parsedLen) failed check due to ${check.errMsg}" ) state.setFailed(pe) } @@ -165,3 +165,23 @@ trait PrefixedLengthParserMixin { } } } + +/** + * Some parsers do not calculate their own length, but instead expect another parser + * to set the bit limit, and then they use that bit limit as the length. + * An example of this is prefix length parsers. This trait can be used by those + * parsers to do determine the length based on the bitLimit and position. + */ +trait BitLengthFromBitLimitMixin { + + def getBitLength(s: ParseOrUnparseState): Int = { + val pState = s.asInstanceOf[PState] + val len = getLengthInBits(pState) + len.toInt + } + + def getLengthInBits(pstate: PState): Long = { + val len = pstate.bitLimit0b.get - pstate.bitPos0b + len + } +} diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala index 5f00208a4b..b211ce2ee0 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala @@ -19,10 +19,8 @@ package org.apache.daffodil.runtime1.processors.parsers import java.nio.ByteBuffer -import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.LengthInBitsEv -import org.apache.daffodil.runtime1.processors.Processor sealed abstract class HexBinaryLengthParser(override val context: ElementRuntimeData) extends PrimParser @@ -94,20 +92,3 @@ final class HexBinaryEndOfBitLimitParser(erd: ElementRuntimeData) pstate.bitLimit0b.get - pstate.bitPos0b } } - -final class HexBinaryLengthPrefixedParser( - erd: ElementRuntimeData, - override val prefixedLengthParser: Parser, - override val prefixedLengthERD: ElementRuntimeData, - override val lengthUnits: LengthUnits, - override val prefixedLengthAdjustmentInUnits: Long -) extends HexBinaryLengthParser(erd) - with PrefixedLengthParserMixin { - - override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) - override val runtimeDependencies = Vector() - - override def getLengthInBits(pstate: PState): Long = { - getPrefixedLengthInBits(pstate) - } -} diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala index a969ba8b6b..42e42f10e5 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala @@ -85,7 +85,11 @@ sealed abstract class SpecifiedLengthParserBase(eParser: Parser, erd: RuntimeDat if (pState.processorStatus ne Success) return val finalEndPos0b = startingBitPos0b + nBits - captureValueLength(pState, ULong(startingBitPos0b), ULong(dis.bitPos0b)) + // we want to capture the length before we do any skipping + // value length of simple types is captured by the eParser if needed + // the SpecifiedLengthParserBase is extended by SpecifiedLengthChoiceParser which should not have its valueLength captured here + if (pState.infoset.isComplex && !erd.isInstanceOf[ChoiceRuntimeData]) + captureValueLength(pState, ULong(startingBitPos0b), ULong(dis.bitPos0b)) Assert.invariant(dis eq pState.dataInputStream) val bitsToSkip = finalEndPos0b - dis.bitPos0b diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/PrefixedTests.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/PrefixedTests.tdml index 6882e2057b..4a331602b1 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/PrefixedTests.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/PrefixedTests.tdml @@ -19,7 +19,7 @@ - + + + + + + + + + + + + + + + @@ -2326,6 +2347,28 @@ + + + + + + + + + + + + + + + + + + + ABC + + + + + ABC + 3 + + + + + + + + 00 00 00 0B + ABC + + + + + ABC + 3 + + + + + @@ -2580,7 +2654,7 @@ + ignoreUnexpectedWarnings="false"> 08 ff @@ -2913,7 +2987,7 @@ failed check - field2 (prefixLength) (5) + field2 (5) facet maxInclusive (4) @@ -2926,7 +3000,7 @@ failed check - field1 (prefixLength) (6) + field1 (6) facet maxInclusive (4) @@ -2956,7 +3030,7 @@ failed check - field3 (prefixLength) (1) + field3 (1) facet minInclusive (2) diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindPrefixed.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindPrefixed.scala index 99a563fd90..3ec2eec760 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindPrefixed.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindPrefixed.scala @@ -172,7 +172,11 @@ class TestLengthKindPrefixed extends TdmlTests { @Test def pl_simpleContentLengthBytes_1 = test // DAFFODIL-2658 - @Ignore @Test def pl_simpleValueLengthBytes_1 = test + @Test def pl_simpleValueLengthBytes_1() = test + @Test def pl_simpleValueLengthBytes_2() = test + + // DAFFODIL-2948 + @Test def pl_simpleValueLengthBytes_3() = test @Test def pl_simpleContentLengthCharacters_1 = test @Test def pl_complexContentLengthCharacters_1 = test