diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ChoiceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ChoiceGroup.scala
index 927bb38987..8af289b2b9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ChoiceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ChoiceGroup.scala
@@ -24,7 +24,9 @@ import org.apache.daffodil.core.dsom.walker.ChoiceView
import org.apache.daffodil.core.grammar.ChoiceGrammarMixin
import org.apache.daffodil.lib.schema.annotation.props.Found
import org.apache.daffodil.lib.schema.annotation.props.gen.ChoiceAGMixin
+import org.apache.daffodil.lib.schema.annotation.props.gen.ChoiceLengthKind
import org.apache.daffodil.lib.schema.annotation.props.gen.Choice_AnnotationMixin
+import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits
import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo
/**
@@ -103,6 +105,7 @@ abstract class ChoiceTermBase(
requiredEvaluationsIfActivated(noBranchesFound)
requiredEvaluationsIfActivated(branchesAreNonOptional)
requiredEvaluationsIfActivated(branchesAreNotIVCElements)
+ requiredEvaluationsIfActivated(checkEndOfParentRestrictions())
final protected lazy val optionChoiceDispatchKeyRaw =
findPropertyOption("choiceDispatchKey", expressionAllowed = true)
@@ -159,7 +162,7 @@ abstract class ChoiceTermBase(
* Open issues:
* 1) Is alignment or leading/trailing skip to be considered syntax. Alignment might not be there.
* 2) What about an empty sequence that only carries statement annotations such as dfdl:assert or
- * dfdl:setVariable
+ * dfdl:setVariable
*
* This latter need to be allowed, because while they do not have known required syntax they do
* have to be executed for side-effect.
@@ -189,6 +192,33 @@ abstract class ChoiceTermBase(
}
assuming(branchesOk.forall { x => x })
}.value
+
+ lazy val optMyEffectiveLengthUnits: Option[LengthUnits] =
+ this match {
+ case self: ChoiceTermBase if self.choiceLengthKind == ChoiceLengthKind.Explicit =>
+ Some(LengthUnits.Bytes)
+ case _ => None
+ }
+
+ def checkEndOfParentRestrictions() = {
+ val parent = this
+ val eopChildren = this.childrenEndOfParent
+ if (eopChildren.isEmpty) {} else {
+ parent match {
+ case c: ChoiceTermBase if c.choiceLengthKind == ChoiceLengthKind.Implicit => {
+ schemaDefinitionWhen(
+ c.hasTerminator,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a choice with a dfdl:terminator."
+ )
+ schemaDefinitionWhen(
+ c.trailingSkip != 0,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a choice with a non-zero dfdl:trailingSkip."
+ )
+ }
+ case _ => // do nothing
+ }
+ }
+ }
}
object Choice {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/LocalElementMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/LocalElementMixin.scala
index 0e9aaf57e9..d00cbc2b3f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/LocalElementMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/LocalElementMixin.scala
@@ -61,10 +61,8 @@ trait LocalElementMixin extends ParticleMixin with LocalElementGrammarMixin {
else if (representation =:= Representation.Binary) true
else false
}
- case LengthKind.EndOfParent if isComplexType =>
- notYetImplemented("lengthKind='endOfParent' for complex type")
- case LengthKind.EndOfParent =>
- notYetImplemented("lengthKind='endOfParent' for simple type")
+ // we can rarely statically know if an endOfParent element must have non-zero length
+ case LengthKind.EndOfParent => false
}
res
}.value
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
index 18a2483fac..ca76780db9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
@@ -30,6 +30,7 @@ import org.apache.daffodil.lib.iapi.Diagnostic
import org.apache.daffodil.lib.iapi.UnitTestSchemaSource
import org.apache.daffodil.lib.oolag.OOLAG
import org.apache.daffodil.lib.schema.annotation.props.LookupLocation
+import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits
import org.apache.daffodil.lib.util.TransitiveClosure
import org.apache.daffodil.lib.xml.*
@@ -116,6 +117,7 @@ final class SchemaSet private (
requiredEvaluationsAlways(root)
requiredEvaluationsAlways(checkForDuplicateTopLevels())
+ requiredEvaluationsAlways(root.checkEndOfParentRestrictions(LengthUnits.Characters))
lazy val resolver = DFDLCatalogResolver.get
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
index a6a9bc0037..ef510f2a2f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
@@ -34,6 +34,7 @@ import org.apache.daffodil.lib.schema.annotation.props.gen.OccursCountKind
import org.apache.daffodil.lib.schema.annotation.props.gen.SeparatorPosition
import org.apache.daffodil.lib.schema.annotation.props.gen.SequenceKind
import org.apache.daffodil.lib.schema.annotation.props.gen.TestKind
+import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo
import org.apache.daffodil.lib.xml.RefQName
import org.apache.daffodil.lib.xml.XMLUtils
import org.apache.daffodil.runtime1.layers.LayerRuntimeData
@@ -105,6 +106,7 @@ abstract class SequenceGroupTermBase(xml: Node, lexicalParent: SchemaComponent,
requiredEvaluationsIfActivated(checkValidityOccursCountKind)
requiredEvaluationsIfActivated(checkIfNonEmptyAndDiscrimsOrAsserts)
requiredEvaluationsIfActivated(checkIfMultipleChildrenWithSameName)
+ requiredEvaluationsIfActivated(checkEndOfParentRestrictions())
protected def apparentXMLChildren: Seq[Node]
@@ -270,6 +272,38 @@ abstract class SequenceGroupTermBase(xml: Node, lexicalParent: SchemaComponent,
case SequenceKind.Unordered => false
}
+ def checkEndOfParentRestrictions() = {
+ val parent = this
+ val eopChildren = this.childrenEndOfParent
+ if (eopChildren.isEmpty) {} else {
+ parent match {
+ case s: SequenceTermBase => {
+ schemaDefinitionWhen(
+ s.separatorPosition == SeparatorPosition.Postfix,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a sequence with dfdl:separatorPosition defined as 'postfix'."
+ )
+ schemaDefinitionWhen(
+ s.sequenceKind != SequenceKind.Ordered,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a sequence with dfdl:sequenceKind defined as 'unordered'."
+ )
+ schemaDefinitionWhen(
+ s.hasTerminator,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a sequence with a dfdl:terminator."
+ )
+ schemaDefinitionWhen(
+ s.realElementChildren.exists(e => e.floating == YesNo.Yes),
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a sequence with elements defining dfdl:floating='yes'."
+ )
+ schemaDefinitionWhen(
+ s.trailingSkip != 0,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but is in a sequence with a non-zero dfdl:trailingSkip."
+ )
+ }
+ case null => // do nothing
+ }
+ }
+ }
+
}
/**
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
index 7558483d5b..d8db9d33a9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
@@ -27,9 +27,7 @@ import org.apache.daffodil.lib.iapi.WarnID
import org.apache.daffodil.lib.schema.annotation.props.Found
import org.apache.daffodil.lib.schema.annotation.props.NotFound
import org.apache.daffodil.lib.schema.annotation.props.SeparatorSuppressionPolicy
-import org.apache.daffodil.lib.schema.annotation.props.gen.LengthKind
-import org.apache.daffodil.lib.schema.annotation.props.gen.OccursCountKind
-import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo
+import org.apache.daffodil.lib.schema.annotation.props.gen.*
/**
* Mixin for objects that are shared, but have consistency checks to be run
@@ -96,6 +94,17 @@ trait Term
requiredEvaluationsIfActivated(defaultPropertySources)
requiredEvaluationsIfActivated(termChecks)
+ final lazy val childrenEndOfParent: Seq[ElementBase] = LV(Symbol("childrenEndOfParent")) {
+ val gms = termChildren
+ val chls = gms.flatMap {
+ case eb: ElementBase if eb.lengthKind == LengthKind.EndOfParent => Seq(eb)
+ case eb: ElementBase => Nil
+ case c: Choice => Nil
+ case mg: ModelGroup => mg.childrenEndOfParent
+ }
+ chls
+ }.value
+
private lazy val termChecks = {
statements.foreach { _.checkTerm(this) }
}
@@ -269,6 +278,26 @@ trait Term
.getOrElse(false)
}
+ final lazy val immediatelyEnclosingParentForEOPElem: Option[Term] = {
+ val p = optLexicalParent.flatMap {
+ case e: ElementBase => Some(e)
+ case ge: GlobalElementDecl => Some(ge.asRoot)
+ case s: SequenceTermBase => s.immediatelyEnclosingParentForEOPElem
+ case c: ChoiceTermBase => Some(c)
+ case ct: ComplexTypeBase => {
+ ct.optLexicalParent.flatMap {
+ case e: ElementBase => Some(e)
+ case ge: GlobalElementDecl => Some(ge.asRoot)
+ case _ => {
+ None
+ }
+ }
+ }
+ case _ => None
+ }
+ p
+ }
+
final lazy val immediatelyEnclosingGroupDef: Option[GroupDefLike] = {
optLexicalParent.flatMap { lexicalParent =>
val res: Option[GroupDefLike] = lexicalParent match {
@@ -562,4 +591,21 @@ trait Term
}
}
+ final protected lazy val realElementChildren: Seq[ElementBase] = {
+ termChildren.flatMap {
+ case eb: ElementBase => Seq(eb)
+ case c: Choice => Nil
+ case mg: ModelGroup => mg.realElementChildren
+ }
+ }
+
+ lazy val flattenedChildren: IndexedSeq[Term] = termChildren.flatMap { c =>
+ c match {
+ case eb: ElementBase => IndexedSeq(eb)
+ case mg: ModelGroup if mg.groupMembers.isEmpty => IndexedSeq(mg)
+ case s: SequenceTermBase => s.flattenedChildren
+ case c: ChoiceTermBase => c.flattenedChildren
+ case _ => Nil
+ }
+ }.toIndexedSeq
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/AlignedMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/AlignedMixin.scala
index 00ebdee130..9b0942e9b1 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/AlignedMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/AlignedMixin.scala
@@ -456,7 +456,11 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
}
case LengthKind.Delimited => encodingLengthApprox
case LengthKind.Pattern => encodingLengthApprox
- case LengthKind.EndOfParent => LengthMultipleOf(1) // NYI
+ case LengthKind.EndOfParent =>
+ // technically the alignment of an EndOfParent element would be the
+ // alignment of its parent minus our current alignment (i.e alignment of
+ // prior sibs) but since nothing can follow
+ LengthMultipleOf(1)
// If an element is lengthKind="prefixed", the element's length is the length
// of the value of the prefix element, which can't be known till runtime
case LengthKind.Prefixed => LengthMultipleOf(1) // NYI (see DAFFODIL-3066)
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 3a33fdfb07..16b09e2873 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
@@ -22,7 +22,9 @@ import java.lang.Long as JLong
import org.apache.daffodil.core.dsom.ElementBase
import org.apache.daffodil.core.dsom.ExpressionCompilers
import org.apache.daffodil.core.dsom.InitiatedTerminatedMixin
+import org.apache.daffodil.core.dsom.ModelGroup
import org.apache.daffodil.core.dsom.PrefixLengthQuasiElementDecl
+import org.apache.daffodil.core.dsom.Root
import org.apache.daffodil.core.grammar.primitives.*
import org.apache.daffodil.core.runtime1.ElementBaseRuntime1Mixin
import org.apache.daffodil.lib.exceptions.Assert
@@ -252,6 +254,127 @@ trait ElementBaseGrammarMixin
}
final lazy val prefixedLengthBody = prefixedLengthElementDecl.parsedValue
+ def myEffectiveLengthUnits(lastNonEOPLU: LengthUnits): LengthUnits = {
+ lengthKind match {
+ case LengthKind.EndOfParent => lastNonEOPLU
+ case LengthKind.Explicit | LengthKind.Prefixed => lengthUnits
+ case LengthKind.Pattern => LengthUnits.Characters
+ case _ =>
+ Assert.invariantFailed(
+ "Delimited and Implicit are illegal for the parent of EndOfParent element"
+ )
+ }
+ }
+
+ def checkChildrenForSiblingsAfterEOPElement(
+ parent: ElementBase,
+ specificChild: ElementBase
+ ) = {
+ lazy val foundPosition = flattenedChildren.indexOf(specificChild)
+ lazy val lastIndexOfChildren = flattenedChildren.length - 1
+ if (flattenedChildren.isEmpty || foundPosition < 0) {
+ // not found amongst children
+ Assert.impossible("EndOfParent element not found amongst term children of parent")
+ } else if (foundPosition != lastIndexOfChildren) {
+ // get the following children after the EOP element+ 1
+ val followingChildrenAfter =
+ flattenedChildren.slice(foundPosition + 1, lastIndexOfChildren + 1)
+ followingChildrenAfter.foreach {
+ case m: ModelGroup => {
+ specificChild.SDE(
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but a model group is defined between this element and the end of the enclosing component"
+ )
+ }
+ case r if r.isRepresented => {
+ specificChild.SDE(
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but a represented element is defined between this element and the end of the enclosing component"
+ )
+ }
+ case _ => // do nothing
+ }
+ }
+ }
+
+ def checkEndOfParentRestrictions(lastNonEOPLU: LengthUnits): Unit = {
+ val parent = this
+ val eopChildren = this.childrenEndOfParent
+ // checks
+ this match {
+ case rootElem: Root if lengthKind == LengthKind.EndOfParent => {
+ rootElem.checkEndOfParentRestrictionsOnCurrentElement(lastNonEOPLU)
+ }
+ case _ => // do nothing
+ }
+
+ if (eopChildren.isEmpty)
+ (
+ this.elementChildren.foreach(_.checkEndOfParentRestrictions(lastNonEOPLU))
+ )
+ else {
+ eopChildren.foreach { eopChild =>
+ lazy val parentELU = myEffectiveLengthUnits(lastNonEOPLU)
+ checkChildrenForSiblingsAfterEOPElement(parent, eopChild)
+ parent.lengthKind match {
+ case LengthKind.Implicit | LengthKind.Delimited =>
+ schemaDefinitionError(
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but its parent is an element with dfdl:lengthKind 'implicit' or 'delimited'."
+ )
+ case _ => // do nothing
+ }
+ eopChild.checkEndOfParentRestrictionsOnCurrentElement(parentELU)
+ if (parent.lengthKind != LengthKind.EndOfParent) {
+ eopChild.checkEndOfParentRestrictions(parentELU)
+ } else {
+ eopChild.checkEndOfParentRestrictions(lastNonEOPLU)
+ }
+ }
+ }
+ // end checks
+ }
+
+ def checkEndOfParentRestrictionsOnCurrentElement(parentELU: LengthUnits): Unit = {
+ val currentElement: ElementBase = this
+ if (currentElement.lengthKind != LengthKind.EndOfParent) {} else {
+ schemaDefinitionWhen(
+ currentElement.hasTerminator,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but specifies a dfdl:terminator."
+ )
+ schemaDefinitionWhen(
+ currentElement.trailingSkip != 0,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but specifies a non-zero dfdl:trailingSkip."
+ )
+ schemaDefinitionWhen(
+ currentElement.maxOccurs > 1,
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but specifies a maxOccurs greater than 1."
+ )
+ schemaDefinitionWhen(
+ currentElement.impliedRepresentation == Representation.Text
+ && (!currentElement.isKnownEncoding || !currentElement.knownEncodingIsFixedWidth || currentElement.knownEncodingWidthInBits != 8)
+ && (parentELU != LengthUnits.Characters),
+ "element is specified as dfdl:lengthKind=\"endOfParent\", but the element has text representation, and does not have a single-byte character set encoding, and the effective length units of the parent is not 'characters'."
+ )
+ if (currentElement.isSimpleType) {
+ schemaDefinitionUnless(
+ (currentElement.primType eq PrimType.String)
+ || (currentElement.representation == Representation.Text)
+ || (currentElement.primType eq PrimType.HexBinary)
+ || (currentElement.representation == Representation.Binary
+ && Seq(BinaryNumberRep.Packed, BinaryNumberRep.Bcd, BinaryNumberRep.Ibm4690Packed)
+ .contains(currentElement.binaryNumberRep))
+ || (currentElement.representation == Representation.Binary
+ && optionBinaryCalendarRep.isDefined
+ && Seq(
+ BinaryCalendarRep.Packed,
+ BinaryCalendarRep.Bcd,
+ BinaryCalendarRep.Ibm4690Packed
+ )
+ .contains(currentElement.binaryCalendarRep)),
+ "element is a simple type specified as dfdl:lengthKind=\"endOfParent\", but isn't a string type, doesn't have text representation, isn't a hexbinary type, or doesn't have binary representation with packed decimal representation."
+ )
+ }
+ }
+ }
+
/**
* Quite tricky when we add padding or fill
*
@@ -605,7 +728,19 @@ trait ElementBaseGrammarMixin
case LengthKind.Pattern =>
schemaDefinitionError("Binary data elements cannot have lengthKind='pattern'.")
case LengthKind.EndOfParent =>
- schemaDefinitionError("Binary data elements cannot have lengthKind='endOfParent'.")
+ // only for packed binary data, length must be computed at runtime.
+ if (
+ representation == Representation.Binary
+ && optionBinaryCalendarRep.isDefined
+ && Seq(BinaryCalendarRep.Packed, BinaryCalendarRep.Bcd, BinaryCalendarRep.Ibm4690Packed)
+ .contains(binaryCalendarRep)
+ || representation == Representation.Binary
+ && optionBinaryNumberRep.isDefined
+ && Seq(BinaryNumberRep.Packed, BinaryNumberRep.Bcd, BinaryNumberRep.Ibm4690Packed)
+ .contains(binaryNumberRep)
+ ) -1
+ else
+ SDE("lengthKind='endOfParent' only supported for packed binary formats.")
}
private def explicitBinaryLengthInBits() = {
@@ -648,10 +783,7 @@ trait ElementBaseGrammarMixin
Assert.invariant(pt == PrimType.String)
StringOfSpecifiedLength(this)
}
- case LengthKind.EndOfParent if isComplexType =>
- notYetImplemented("lengthKind='endOfParent' for complex type")
- case LengthKind.EndOfParent =>
- notYetImplemented("lengthKind='endOfParent' for simple type")
+ case LengthKind.EndOfParent => StringOfSpecifiedLength(this)
}
}
@@ -667,6 +799,10 @@ trait ElementBaseGrammarMixin
new HexBinaryLengthPrefixed(this)
}
+ private lazy val hexBinaryLengthEndOfParent = prod("hexBinaryLengthEndOfParent") {
+ new HexBinaryLengthEndOfParent(this)
+ }
+
private lazy val hexBinaryValue = prod("hexBinaryValue") {
schemaDefinitionWhen(
lengthUnits == LengthUnits.Characters,
@@ -678,10 +814,7 @@ trait ElementBaseGrammarMixin
case LengthKind.Delimited => hexBinaryDelimitedEndOfData
case LengthKind.Pattern => hexBinaryLengthPattern
case LengthKind.Prefixed => hexBinaryLengthPrefixed
- case LengthKind.EndOfParent if isComplexType =>
- notYetImplemented("lengthKind='endOfParent' for complex type")
- case LengthKind.EndOfParent =>
- notYetImplemented("lengthKind='endOfParent' for simple type")
+ case LengthKind.EndOfParent => hexBinaryLengthEndOfParent
}
}
@@ -793,6 +926,10 @@ trait ElementBaseGrammarMixin
prod("bcdPrefixedLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Bcd) {
ConvertZonedCombinator(this, new BCDIntegerPrefixedLength(this), textConverter)
}
+ private lazy val bcdEndOfParentLengthCalendar =
+ prod("bcdEndOfParentLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Bcd) {
+ ConvertZonedCombinator(this, new BCDIntegerEndOfParentLength(this), textConverter)
+ }
private lazy val ibm4690PackedKnownLengthCalendar = prod(
"ibm4690PackedKnownLengthCalendar",
@@ -834,6 +971,16 @@ trait ElementBaseGrammarMixin
textConverter
)
}
+ private lazy val ibm4690PackedEndOfParentLengthCalendar = prod(
+ "ibm4690PackedEndOfParentLengthCalendar",
+ binaryCalendarRep == BinaryCalendarRep.Ibm4690Packed
+ ) {
+ ConvertZonedCombinator(
+ this,
+ new IBM4690PackedIntegerEndOfParentLength(this),
+ textConverter
+ )
+ }
private lazy val packedKnownLengthCalendar =
prod("packedKnownLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Packed) {
@@ -871,6 +1018,14 @@ trait ElementBaseGrammarMixin
textConverter
)
}
+ private lazy val packedEndOfParentLengthCalendar =
+ prod("packedPrefixedLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Packed) {
+ ConvertZonedCombinator(
+ this,
+ new PackedIntegerEndOfParentLength(this, packedSignCodes),
+ textConverter
+ )
+ }
def primType: PrimType
@@ -922,6 +1077,8 @@ trait ElementBaseGrammarMixin
byteOrderRaw // must be defined or SDE
}
(binaryNumberRep, lengthKind, binaryNumberKnownLengthInBits) match {
+ case (BinaryNumberRep.Binary, LengthKind.EndOfParent, _) =>
+ SDE("lengthKind='endOfParent' is not allowed with binary number representation")
case (BinaryNumberRep.Binary, LengthKind.Prefixed, _) =>
new BinaryIntegerPrefixedLength(this)
case (BinaryNumberRep.Binary, _, -1) => new BinaryIntegerRuntimeLength(this)
@@ -939,6 +1096,8 @@ trait ElementBaseGrammarMixin
new PackedIntegerDelimitedEndOfData(this, packedSignCodes)
case (BinaryNumberRep.Packed, LengthKind.Prefixed, -1) =>
new PackedIntegerPrefixedLength(this, packedSignCodes)
+ case (BinaryNumberRep.Packed, LengthKind.EndOfParent, -1) =>
+ new PackedIntegerEndOfParentLength(this, packedSignCodes)
case (BinaryNumberRep.Packed, _, -1) =>
new PackedIntegerRuntimeLength(this, packedSignCodes)
case (BinaryNumberRep.Packed, _, _) =>
@@ -951,6 +1110,8 @@ trait ElementBaseGrammarMixin
new IBM4690PackedIntegerDelimitedEndOfData(this)
case (BinaryNumberRep.Ibm4690Packed, LengthKind.Prefixed, -1) =>
new IBM4690PackedIntegerPrefixedLength(this)
+ case (BinaryNumberRep.Ibm4690Packed, LengthKind.EndOfParent, -1) =>
+ new IBM4690PackedIntegerEndOfParentLength(this)
case (BinaryNumberRep.Ibm4690Packed, _, -1) =>
new IBM4690PackedIntegerRuntimeLength(this)
case (BinaryNumberRep.Ibm4690Packed, _, _) =>
@@ -963,6 +1124,7 @@ trait ElementBaseGrammarMixin
(lengthKind, binaryNumberKnownLengthInBits) match {
case (LengthKind.Delimited, -1) => new BCDIntegerDelimitedEndOfData(this)
case (LengthKind.Prefixed, -1) => new BCDIntegerPrefixedLength(this)
+ case (LengthKind.EndOfParent, -1) => new BCDIntegerEndOfParentLength(this)
case (_, -1) => new BCDIntegerRuntimeLength(this)
case (_, _) => new BCDIntegerKnownLength(this, binaryNumberKnownLengthInBits)
}
@@ -1030,6 +1192,8 @@ trait ElementBaseGrammarMixin
) byteOrderRaw // must have or SDE
(binaryNumberRep, lengthKind, binaryNumberKnownLengthInBits) match {
+ case (BinaryNumberRep.Binary, LengthKind.EndOfParent, _) =>
+ SDE("lengthKind='endOfParent' is not allowed with binary number representation")
case (BinaryNumberRep.Binary, LengthKind.Prefixed, _) =>
new BinaryDecimalPrefixedLength(this)
case (BinaryNumberRep.Binary, _, -1) => new BinaryDecimalRuntimeLength(this)
@@ -1047,6 +1211,8 @@ trait ElementBaseGrammarMixin
new PackedDecimalDelimitedEndOfData(this, packedSignCodes)
case (BinaryNumberRep.Packed, LengthKind.Prefixed, _) =>
new PackedDecimalPrefixedLength(this, packedSignCodes)
+ case (BinaryNumberRep.Packed, LengthKind.EndOfParent, _) =>
+ new PackedDecimalEndOfParentLength(this, packedSignCodes)
case (BinaryNumberRep.Packed, _, -1) =>
new PackedDecimalRuntimeLength(this, packedSignCodes)
case (BinaryNumberRep.Packed, _, _) =>
@@ -1055,6 +1221,8 @@ trait ElementBaseGrammarMixin
new BCDDecimalDelimitedEndOfData(this)
case (BinaryNumberRep.Bcd, LengthKind.Prefixed, _) =>
new BCDDecimalPrefixedLength(this)
+ case (BinaryNumberRep.Bcd, LengthKind.EndOfParent, _) =>
+ new BCDDecimalEndOfParentLength(this)
case (BinaryNumberRep.Bcd, _, -1) => new BCDDecimalRuntimeLength(this)
case (BinaryNumberRep.Bcd, _, _) =>
new BCDDecimalKnownLength(this, binaryNumberKnownLengthInBits)
@@ -1062,6 +1230,8 @@ trait ElementBaseGrammarMixin
new IBM4690PackedDecimalDelimitedEndOfData(this)
case (BinaryNumberRep.Ibm4690Packed, LengthKind.Prefixed, _) =>
new IBM4690PackedDecimalPrefixedLength(this)
+ case (BinaryNumberRep.Ibm4690Packed, LengthKind.EndOfParent, _) =>
+ new IBM4690PackedDecimalEndOfParentLength(this)
case (BinaryNumberRep.Ibm4690Packed, _, -1) =>
new IBM4690PackedDecimalRuntimeLength(this)
case (BinaryNumberRep.Ibm4690Packed, _, _) =>
@@ -1072,6 +1242,7 @@ trait ElementBaseGrammarMixin
case PrimType.Boolean => {
lengthKind match {
case LengthKind.Prefixed => new BinaryBooleanPrefixedLength(this)
+ case LengthKind.EndOfParent => new BinaryBooleanEndOfParentLength(this)
case _ => new BinaryBoolean(this)
}
}
@@ -1125,6 +1296,7 @@ trait ElementBaseGrammarMixin
(lengthKind, binaryNumberKnownLengthInBits) match {
case (LengthKind.Delimited, -1) => bcdDelimitedLengthCalendar
case (LengthKind.Prefixed, -1) => bcdPrefixedLengthCalendar
+ case (LengthKind.EndOfParent, -1) => bcdEndOfParentLengthCalendar
case (_, -1) => bcdRuntimeLengthCalendar
case (_, _) => bcdKnownLengthCalendar
}
@@ -1133,6 +1305,7 @@ trait ElementBaseGrammarMixin
(lengthKind, binaryNumberKnownLengthInBits) match {
case (LengthKind.Delimited, -1) => ibm4690PackedDelimitedLengthCalendar
case (LengthKind.Prefixed, -1) => ibm4690PackedPrefixedLengthCalendar
+ case (LengthKind.EndOfParent, -1) => ibm4690PackedEndOfParentLengthCalendar
case (_, -1) => ibm4690PackedRuntimeLengthCalendar
case (_, _) => ibm4690PackedKnownLengthCalendar
}
@@ -1141,6 +1314,7 @@ trait ElementBaseGrammarMixin
(lengthKind, binaryNumberKnownLengthInBits) match {
case (LengthKind.Delimited, -1) => packedDelimitedLengthCalendar
case (LengthKind.Prefixed, -1) => packedPrefixedLengthCalendar
+ case (LengthKind.EndOfParent, -1) => packedEndOfParentLengthCalendar
case (_, -1) => packedRuntimeLengthCalendar
case (_, _) => packedKnownLengthCalendar
}
@@ -1280,10 +1454,7 @@ trait ElementBaseGrammarMixin
case LengthKind.Implicit =>
LiteralValueNilOfSpecifiedLength(this)
case LengthKind.Prefixed => LiteralValueNilOfSpecifiedLength(this)
- case LengthKind.EndOfParent if isComplexType =>
- notYetImplemented("lengthKind='endOfParent' for complex type")
- case LengthKind.EndOfParent =>
- notYetImplemented("lengthKind='endOfParent' for simple type")
+ case LengthKind.EndOfParent => LiteralValueNilOfSpecifiedLength(this)
}
}
case NilKind.LiteralCharacter => {
@@ -1346,13 +1517,15 @@ trait ElementBaseGrammarMixin
// 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
- )
+ val bodyRequiresSpecifiedLengthBitLimit = lengthKind != LengthKind.Delimited
+ && !(isSimpleType && lengthKind == LengthKind.EndOfParent && !this.isInstanceOf[Root])
+ && (
+ isSimpleType && impliedRepresentation == Representation.Text ||
+ isSimpleType && isNillable ||
+ isComplexType && lengthKind != LengthKind.Implicit ||
+ lengthKind == LengthKind.Prefixed ||
+ isSimpleType && primType == PrimType.HexBinary && lengthKind == LengthKind.Pattern
+ )
if (!bodyRequiresSpecifiedLengthBitLimit) {
body
} else {
@@ -1396,11 +1569,9 @@ trait ElementBaseGrammarMixin
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")
- case LengthKind.Delimited | LengthKind.Implicit =>
+ case LengthKind.EndOfParent if (isComplexType || this.isInstanceOf[Root]) =>
+ new SpecifiedLengthEndOfParent(this, body)
+ case LengthKind.Delimited | LengthKind.Implicit | LengthKind.EndOfParent =>
Assert.impossibleCase(
"Delimited and ComplexType Implicit cases should not be reached"
)
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 e9e0996b00..5dda4397b1 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
@@ -52,7 +52,18 @@ class BCDIntegerKnownLength(val e: ElementBase, lengthInBits: Long) extends Term
class BCDIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) {
- override lazy val parser = new BCDIntegerBitLimitLengthParser(e.elementRuntimeData)
+ override lazy val parser =
+ new BCDIntegerBitLimitLengthParser(e.elementRuntimeData, isEndOfParent = false)
+
+ override lazy val unparser: Unparser = new BCDIntegerMinimumLengthUnparser(
+ e.elementRuntimeData
+ )
+}
+
+class BCDIntegerEndOfParentLength(val e: ElementBase) extends Terminal(e, true) {
+
+ override lazy val parser =
+ new BCDIntegerBitLimitLengthParser(e.elementRuntimeData, isEndOfParent = true)
override lazy val unparser: Unparser = new BCDIntegerMinimumLengthUnparser(
e.elementRuntimeData
@@ -94,9 +105,26 @@ class BCDDecimalPrefixedLength(val e: ElementBase) extends Terminal(e, true) {
override lazy val parser =
new BCDDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: Unparser =
+ new BCDDecimalMinimumLengthUnparser(
e.elementRuntimeData,
e.binaryDecimalVirtualPoint
)
+}
+
+class BCDDecimalEndOfParentLength(val e: ElementBase) extends Terminal(e, true) {
+
+ override lazy val parser =
+ new BCDDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ isEndOfParent = true
+ )
override lazy val unparser: Unparser =
new BCDDecimalMinimumLengthUnparser(
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 b934a24fb5..a5be07b9c1 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
@@ -47,11 +47,29 @@ class BinaryBoolean(val e: ElementBase) extends Terminal(e, true) {
class BinaryBooleanPrefixedLength(val e: ElementBase) extends Terminal(e, true) {
override lazy val parser = new BinaryBooleanBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryBooleanTrueRep,
+ e.binaryBooleanFalseRep,
+ e.lengthUnits,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: Unparser = new BinaryBooleanMinimumLengthUnparser(
e.elementRuntimeData,
e.binaryBooleanTrueRep,
e.binaryBooleanFalseRep,
e.lengthUnits
)
+}
+
+class BinaryBooleanEndOfParentLength(val e: ElementBase) extends Terminal(e, true) {
+ override lazy val parser = new BinaryBooleanBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryBooleanTrueRep,
+ e.binaryBooleanFalseRep,
+ e.lengthUnits,
+ isEndOfParent = true
+ )
override lazy val unparser: Unparser = new BinaryBooleanMinimumLengthUnparser(
e.elementRuntimeData,
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 91d0d25efe..6c04df2801 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
@@ -59,7 +59,16 @@ class IBM4690PackedIntegerKnownLength(val e: ElementBase, lengthInBits: Long)
class IBM4690PackedIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) {
override lazy val parser =
- new IBM4690PackedIntegerBitLimitLengthParser(e.elementRuntimeData)
+ new IBM4690PackedIntegerBitLimitLengthParser(e.elementRuntimeData, isEndOfParent = false)
+
+ override lazy val unparser: Unparser = new IBM4690PackedIntegerMinimumLengthUnparser(
+ e.elementRuntimeData
+ )
+}
+
+class IBM4690PackedIntegerEndOfParentLength(val e: ElementBase) extends Terminal(e, true) {
+ override lazy val parser =
+ new IBM4690PackedIntegerBitLimitLengthParser(e.elementRuntimeData, isEndOfParent = true)
override lazy val unparser: Unparser = new IBM4690PackedIntegerMinimumLengthUnparser(
e.elementRuntimeData
@@ -104,10 +113,26 @@ class IBM4690PackedDecimalKnownLength(val e: ElementBase, lengthInBits: Long)
class IBM4690PackedDecimalPrefixedLength(val e: ElementBase) extends Terminal(e, true) {
override lazy val parser = new IBM4690PackedDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ e.decimalSigned,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: Unparser = new IBM4690PackedDecimalMinimumLengthUnparser(
e.elementRuntimeData,
e.binaryDecimalVirtualPoint,
e.decimalSigned
)
+}
+
+class IBM4690PackedDecimalEndOfParentLength(val e: ElementBase) extends Terminal(e, true) {
+ override lazy val parser = new IBM4690PackedDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ e.decimalSigned,
+ isEndOfParent = true
+ )
override lazy val unparser: Unparser = new IBM4690PackedDecimalMinimumLengthUnparser(
e.elementRuntimeData,
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 e069353bd5..521e1370b7 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
@@ -174,7 +174,8 @@ case class HexBinaryDelimitedEndOfData(e: ElementBase) extends HexBinaryDelimite
case class HexBinaryEndOfBitLimit(e: ElementBase) extends Terminal(e, true) {
override lazy val parser: DaffodilParser = new HexBinaryEndOfBitLimitParser(
- e.elementRuntimeData
+ e.elementRuntimeData,
+ isEndOfParent = false
)
override lazy val unparser: DaffodilUnparser =
@@ -184,7 +185,19 @@ case class HexBinaryEndOfBitLimit(e: ElementBase) extends Terminal(e, true) {
case class HexBinaryLengthPrefixed(e: ElementBase) extends Terminal(e, true) {
override lazy val parser: DaffodilParser = new HexBinaryEndOfBitLimitParser(
- e.elementRuntimeData
+ e.elementRuntimeData,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: DaffodilUnparser =
+ new HexBinaryMinLengthInBytesUnparser(e.minLength.longValue, e.elementRuntimeData)
+}
+
+case class HexBinaryLengthEndOfParent(e: ElementBase) extends Terminal(e, true) {
+
+ override lazy val parser: DaffodilParser = new HexBinaryEndOfBitLimitParser(
+ e.elementRuntimeData,
+ isEndOfParent = true
)
override lazy val unparser: DaffodilUnparser =
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 f5c81be1f4..bb4b010cd2 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
@@ -78,7 +78,27 @@ class PackedIntegerPrefixedLength(
) extends Terminal(e, true) {
override lazy val parser =
- new PackedIntegerBitLimitLengthParser(e.elementRuntimeData, packedSignCodes)
+ new PackedIntegerBitLimitLengthParser(
+ e.elementRuntimeData,
+ packedSignCodes,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: Unparser =
+ new PackedIntegerMinimumLengthUnparser(e.elementRuntimeData, packedSignCodes)
+}
+
+class PackedIntegerEndOfParentLength(
+ val e: ElementBase,
+ packedSignCodes: PackedSignCodes
+) extends Terminal(e, true) {
+
+ override lazy val parser =
+ new PackedIntegerBitLimitLengthParser(
+ e.elementRuntimeData,
+ packedSignCodes,
+ isEndOfParent = true
+ )
override lazy val unparser: Unparser =
new PackedIntegerMinimumLengthUnparser(e.elementRuntimeData, packedSignCodes)
@@ -132,11 +152,31 @@ class PackedDecimalPrefixedLength(val e: ElementBase, packedSignCodes: PackedSig
extends Terminal(e, true) {
override lazy val parser = new PackedDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ packedSignCodes,
+ e.decimalSigned,
+ isEndOfParent = false
+ )
+
+ override lazy val unparser: Unparser = new PackedDecimalMinimumLengthUnparser(
e.elementRuntimeData,
e.binaryDecimalVirtualPoint,
packedSignCodes,
e.decimalSigned
)
+}
+
+class PackedDecimalEndOfParentLength(val e: ElementBase, packedSignCodes: PackedSignCodes)
+ extends Terminal(e, true) {
+
+ override lazy val parser = new PackedDecimalBitLimitLengthParser(
+ e.elementRuntimeData,
+ e.binaryDecimalVirtualPoint,
+ packedSignCodes,
+ e.decimalSigned,
+ isEndOfParent = true
+ )
override lazy val unparser: Unparser = new PackedDecimalMinimumLengthUnparser(
e.elementRuntimeData,
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SpecifiedLength.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SpecifiedLength.scala
index 0ae3e6a4d9..5c2bde7f84 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SpecifiedLength.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SpecifiedLength.scala
@@ -132,6 +132,24 @@ class SpecifiedLengthExplicit(e: ElementBase, eGram: => Gram, bitsMultiplier: In
}
+class SpecifiedLengthEndOfParent(e: ElementBase, eGram: => Gram)
+ extends SpecifiedLengthCombinatorBase(e, eGram) {
+
+ lazy val kind = "EndOfParent_" + e.lengthUnits.toString
+
+ lazy val parser: Parser = {
+ if (eParser.isEmpty) eParser
+ else
+ new SpecifiedLengthEndOfParentParser(
+ eParser,
+ e.elementRuntimeData
+ )
+ }
+
+ lazy val unparser: Unparser = eUnparser
+
+}
+
class SpecifiedLengthImplicit(e: ElementBase, eGram: => Gram, nBits: Long)
extends SpecifiedLengthCombinatorBase(e, eGram)
with SpecifiedLengthExplicitImplicitUnparserMixin {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSource.scala b/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSource.scala
index c951fb2c7f..627c48ee2a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSource.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSource.scala
@@ -181,6 +181,12 @@ abstract class InputSource {
*/
def releasePosition(bytePos0b: Long): Unit
+ /**
+ * Get the number of bytes that are available to be read until the end of
+ * the data stream.
+ */
+ lazy val bytesTillEndOfDataStream: Long = -1L
+
/**
* Alerts the implementation to attempt to free data that is no longer used,
* if possible. If possible, this should free any unlocked bytes.
@@ -564,6 +570,22 @@ class BucketingInputSource(
headBucketBytePosition0b += bytesRemoved
oldestBucketIndex = 0
}
+
+ override lazy val bytesTillEndOfDataStream: Long = {
+ val initialBytePosition = position()
+ val endOfDataNotReached = fillBucketsToIndex(maxNumberOfNonNullBuckets, 8)
+ if (!endOfDataNotReached) {
+ val numBytesFilled = totalBytesBucketed - initialBytePosition
+ // reset the byte position to the initial byte position
+ position(initialBytePosition)
+ numBytesFilled
+ } else {
+ position(initialBytePosition)
+ throw new Exception(
+ s"Attempted to fill to end of data stream, but did not reach end of data stream before maxCacheSizeInBytes: ${maxCacheSizeInBytes}."
+ )
+ }
+ }
}
/**
@@ -645,4 +667,11 @@ class ByteBufferInputSource(byteBuffer: ByteBuffer) extends InputSource {
override def close(): Unit = {
// do nothing. No resources to release.
}
+
+ override lazy val bytesTillEndOfDataStream: Long = {
+ val initialPosition = position()
+ val br = byteBuffer.remaining
+ position(initialPosition)
+ br
+ }
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala b/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
index 8e39d7db43..5e1bc1ff5d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
@@ -136,6 +136,8 @@ final class InputSourceDataInputStream private (val inputSource: InputSource)
*/
def hasReachedEndOfData: Boolean = inputSource.hasReachedEndOfData
+ lazy val bytesTillEndOfDataStream: Long = inputSource.bytesTillEndOfDataStream
+
/**
* Return the number of currently available bytes.
*
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala
index 36fc5ddeda..f6c285d04a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/BCDParsers.scala
@@ -52,9 +52,10 @@ class BCDDecimalRuntimeLengthParser(
class BCDDecimalBitLimitLengthParser(
e: ElementRuntimeData,
- binaryDecimalVirtualPoint: Int
+ binaryDecimalVirtualPoint: Int,
+ isEndOfParent: Boolean
) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint, None)
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigDecimal =
DecimalUtils.bcdToBigDecimal(num, binaryDecimalVirtualPoint)
@@ -79,9 +80,9 @@ class BCDIntegerKnownLengthParser(e: ElementRuntimeData, val lengthInBits: Int)
}
-class BCDIntegerBitLimitLengthParser(e: ElementRuntimeData)
+class BCDIntegerBitLimitLengthParser(e: ElementRuntimeData, isEndOfParent: Boolean)
extends PackedBinaryIntegerBaseParser(e)
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigInteger = DecimalUtils.bcdToBigInteger(num)
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala
index 6ea612a57d..e9761a4349 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala
@@ -56,9 +56,10 @@ class IBM4690PackedDecimalRuntimeLengthParser(
class IBM4690PackedDecimalBitLimitLengthParser(
e: ElementRuntimeData,
binaryDecimalVirtualPoint: Int,
- decimalSigned: YesNo
+ decimalSigned: YesNo,
+ isEndOfParent: Boolean
) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint, Some(decimalSigned))
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigDecimal =
DecimalUtils.ibm4690ToBigDecimal(num, binaryDecimalVirtualPoint)
@@ -88,9 +89,9 @@ class IBM4690PackedIntegerKnownLengthParser(
}
-class IBM4690PackedIntegerBitLimitLengthParser(e: ElementRuntimeData)
+class IBM4690PackedIntegerBitLimitLengthParser(e: ElementRuntimeData, isEndOfParent: Boolean)
extends PackedBinaryIntegerBaseParser(e)
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigInteger =
DecimalUtils.ibm4690ToBigInteger(num)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala
index 46fc6c091d..59779e1a84 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala
@@ -58,9 +58,10 @@ class PackedDecimalBitLimitLengthParser(
e: ElementRuntimeData,
binaryDecimalVirtualPoint: Int,
packedSignCodes: PackedSignCodes,
- decimalSigned: YesNo
+ decimalSigned: YesNo,
+ isEndOfParent: Boolean
) extends PackedBinaryDecimalBaseParser(e, binaryDecimalVirtualPoint, Some(decimalSigned))
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigDecimal =
DecimalUtils.packedToBigDecimal(num, binaryDecimalVirtualPoint, packedSignCodes)
@@ -93,9 +94,10 @@ class PackedIntegerKnownLengthParser(
class PackedIntegerBitLimitLengthParser(
e: ElementRuntimeData,
- packedSignCodes: PackedSignCodes
+ packedSignCodes: PackedSignCodes,
+ isEndOfParent: Boolean
) extends PackedBinaryIntegerBaseParser(e)
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def toNumber(num: Array[Byte]): JBigInteger =
DecimalUtils.packedToBigInteger(num, packedSignCodes)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala
index a4a30de0bd..72584d234a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryBooleanParsers.scala
@@ -109,9 +109,10 @@ class BinaryBooleanBitLimitLengthParser(
override val context: ElementRuntimeData,
binaryBooleanTrueRep: MaybeULong,
binaryBooleanFalseRep: ULong,
- lengthUnits: LengthUnits
+ lengthUnits: LengthUnits,
+ isEndOfParent: Boolean
) extends BinaryBooleanParserBase(binaryBooleanTrueRep, binaryBooleanFalseRep, lengthUnits)
- with BitLengthFromBitLimitMixin {
+ with BitLengthFromBitLimitMixin(isEndOfParent) {
override def runtimeDependencies = Vector()
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala
index 7c9f50efca..2e496d59df 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/HexBinaryLengthParsers.scala
@@ -83,12 +83,9 @@ final class HexBinarySpecifiedLengthParser(erd: ElementRuntimeData, lengthEv: Le
}
-final class HexBinaryEndOfBitLimitParser(erd: ElementRuntimeData)
- extends HexBinaryLengthParser(erd) {
+final class HexBinaryEndOfBitLimitParser(erd: ElementRuntimeData, isEndOfParent: Boolean)
+ extends HexBinaryLengthParser(erd),
+ BitLengthFromBitLimitMixin(isEndOfParent) {
override def runtimeDependencies = Vector()
-
- override def getLengthInBits(pstate: PState): Long = {
- pstate.bitLimit0b.get - pstate.bitPos0b
- }
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParserTraits.scala
similarity index 94%
rename from daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala
rename to daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParserTraits.scala
index 814a9ee31b..93feb7d6de 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberTraits.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParserTraits.scala
@@ -172,7 +172,7 @@ trait PrefixedLengthParserMixin {
* 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 {
+trait BitLengthFromBitLimitMixin(val isEndOfParent: Boolean = false) {
def getBitLength(s: ParseOrUnparseState): Int = {
val pState = s.asInstanceOf[PState]
@@ -181,7 +181,14 @@ trait BitLengthFromBitLimitMixin {
}
def getLengthInBits(pstate: PState): Long = {
- val len = pstate.bitLimit0b.get - pstate.bitPos0b
- len
+ if (pstate.bitLimit0b.isDefined) {
+ val len = pstate.bitLimit0b.get - pstate.bitPos0b
+ len
+ } else if (isEndOfParent) {
+ val byteLimit = pstate.dataInputStream.bytesTillEndOfDataStream
+ byteLimit * 8
+ } else {
+ Assert.invariantFailed("BitLimit not set for parser.")
+ }
}
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala
index 2f3ee1f5dd..a2fec40539 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SpecifiedLengthParsers.scala
@@ -132,6 +132,17 @@ class SpecifiedLengthPatternParser(
}
}
+class SpecifiedLengthEndOfParentParser(
+ eParser: Parser,
+ erd: ElementRuntimeData
+) extends SpecifiedLengthParserBase(eParser, erd),
+ BitLengthFromBitLimitMixin(true) {
+
+ override protected def getBitLength(s: PState): MaybeULong = {
+ MaybeULong(super[BitLengthFromBitLimitMixin].getBitLength(s))
+ }
+}
+
class SpecifiedLengthExplicitParser(
eParser: Parser,
erd: ElementRuntimeData,
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
index c2be97ef3f..e97a545c6b 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
@@ -639,6 +639,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -664,6 +686,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4357,6 +4403,21 @@
+
+ IaaBbb
+
+
+
+
+
+ aa
+ bb
+
+
+
+
+
+
IAaabbee
@@ -4373,6 +4434,22 @@
+
+ IAaabbee
+
+
+
+
+
+ aa
+ bb
+
+ ee
+
+
+
+
+
aaTBbb
@@ -4613,4 +4690,6 @@
+
+
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml
index fdbcc2e32d..6b2348fee5 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml
@@ -20,9 +20,10 @@
description="Section 12 - lengthKind=endOfParent" xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
- xmlns:ex="http://example.com" defaultRoundTrip="true">
+ xmlns:ex="http://example.com" defaultRoundTrip="onePass"
+ xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schema Definition Error
+ endOfParent
+ but its parent
+ lengthKind
+ delimited
+
+
+
+
+
+
+ Schema Definition Error
+ endOfParent
+ but its parent
+ lengthKind
+ delimited
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Schema Definition Error
+ endOfParent
+ but its parent
+ lengthKind
+ implicit
+
+
+
+
+
+
+ Schema Definition Error
+ endOfParent
+ but its parent
+ lengthKind
+ implicit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+
+ A
+
+
+
+
+
+
+
+
+ endOfParent
+ does not have
+ single-byte character set encoding
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+
+
+
+
+
+
+
-
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
- Schema Definition Error
- not
- implemented
endOfParent
- complex
- type
+ represented element
+ between this element and
+ end of the enclosing component
-
-
+
+
+
+ endOfParent
+ represented element
+ between this element and
+ end of the enclosing component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ model group
+ between this element and
+ end of the enclosing component
+
+
+
+
+
- Schema Definition Error
- not
- implemented
endOfParent
- simple
- type
+ model group
+ between this element and
+ end of the enclosing component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ specifies
+ terminator
+
+
+
+
+
+
+ endOfParent
+ specifies
+ terminator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ specifies
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+ endOfParent
+ specifies
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ specifies
+ maxOccurs
+ greater than 1
+
+
+
+
+
+
+ endOfParent
+ specifies
+ maxOccurs
+ greater than 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ does not have
+ single-byte character set encoding
+
+
+
+
+
+
+ endOfParent
+ does not have
+ single-byte character set encoding
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ separatorPosition
+ postfix
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ separatorPosition
+ postfix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ sequenceKind
+ unordered
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ sequenceKind
+ unordered
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ elements
+ floating='yes
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ elements
+ floating='yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+ endOfParent
+ in a sequence with
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a choice with
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+ endOfParent
+ in a choice with
+ non-zero
+ trailingSkip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ in a choice with
+ terminator
+
+
+
+
+
+
+ endOfParent
+ in a choice with
+ terminator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ endOfParent
+ supported for
+ packed binary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+ 3132
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+ 12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 2
+ 2
+
+
+ 3
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+ YZ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ abcde
+
+
+
+ abcde
+
+
+
+
+
+
+ ábcde
+
+
+ endOfParent
+ represented element
+ between this element and
+ end of the enclosing component
+
+
+
+
+
+ abcde
+
+
+
+
+ abcde
+
+
+
+
+
+
+
+ abcde
+
+
+
+
+
+ abcde
+
+
+
+
+
+
+
+
+ abcde
+
+
+
+ abcde
+
+
+
+
+
+
+ abcde
+
+
+
+ abcde
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+
+
+
+ 12
+
+
+
+
+
+
+ 123
+
+
+ endOfParent
+ represented element
+ between this element and
+ end of the enclosing component
+
+
+
+
+
+ 12
+
+
+
+ 12
+
+
+
+
+
+
+ 12
+
+
+
+ 12
+
+
+
+
+
+
+ 123.45
+
+
+
+ 123.45
+
+
+
+
+
+
+ 123.45
+
+
+
+ 123.45
+
+
+
+
+
+
+ 123.45
+
+
+
+ 123.45
+
+
+
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+ 2017-08-28T18:29:00
+
+
+
+
+
+
+ TRUE
+
+
+
+ true
+
+
+
+
+
+
+ TRUE
+
+
+
+ true
+
+
+
+
+
+
+
+ TRUE
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01234C
+
+
+
+ 1234
+
+
+
+
+
+
+
+ 1234
+
+
+
+ 1234
+
+
+
+
+
+
+ 1234
+
+
+
+ 1234
+
+
+
+
+
+
+ 30 39
+
+
+ endOfParent
+ only supported
+ packed binary formats
+
+
+
+
+
+ 01234C
+
+
+
+ 12.34
+
+
+
+
+
+
+ 1234
+
+
+
+ 12.34
+
+
+
+
+
+
+ 1234
+
+
+
+ 12.34
+
+
+
+
+
+
+
+ DE AD BE EF
+
+
+
+ DEADBEEF
+
+
+
+
+
+
+
+ 01
+
+
+ endOfParent
+ doesn't have
+ packed decimal representation
+
+
+
+
+
+
+ 01 22 51 64 51 93 65 0C
+
+
+
+ 1645-12-25T19:36:50
+
+
+
+
+
+
+ 06 14 20 04 18 56 03
+
+
+
+ 2004-06-14T18:56:03
+
+
+
+
+
+
+ 11 30 20 07 04 15 08
+
+
+
+ 2007-11-30T04:15:08
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hello
+
+
+
+ hello
+
+
+
+
+
+
+ hello
+
+
+
+ hello
+
+
+
+
+
+
+ hello}
+
+
+ endOfParent
+ sequence with
+ terminator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ helff
+
+
+
+ hel
+
+
+
+
+
+
+ helff
+
+
+
+ hel
+
+
+
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section13/packed/packed.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section13/packed/packed.tdml
index 6714a288c5..ce71d4d347 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section13/packed/packed.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section13/packed/packed.tdml
@@ -259,6 +259,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1050,4 +1112,187 @@
+
+
+
+ 003C 123D
+
+
+
+
+ 3
+ -123
+
+
+
+
+
+
+
+
+ 003C 123D
+
+
+
+
+ 0.03
+ -1.23
+
+
+
+
+
+
+
+
+
+ 3
+ -123
+
+
+
+
+
+ 003C 123D
+
+
+
+
+
+
+
+
+ 0.03
+ -1.23
+
+
+
+
+
+ 003C 123D
+
+
+
+
+
+
+ 0003 0123
+
+
+
+
+ 3
+ 123
+
+
+
+
+
+
+
+
+ 0003 0123
+
+
+
+
+ 0.03
+ 1.23
+
+
+
+
+
+
+
+
+
+ 3
+ 123
+
+
+
+
+
+ 0003 0123
+
+
+
+
+
+
+
+ 0.03
+ 1.23
+
+
+
+
+
+ 0003 0123
+
+
+
+
+
+
+
+ FFF3 D123
+
+
+
+
+ 3
+ -123
+
+
+
+
+
+
+
+
+ FFF3 D123
+
+
+
+
+ 0.03
+ -1.23
+
+
+
+
+
+
+
+
+
+
+ 3
+ -123
+
+
+
+
+
+ FFF3 D123
+
+
+
+
+
+
+
+ 0.03
+ -1.23
+
+
+
+
+
+ FFF3 D123
+
+
+
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceLengthExplicit.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceLengthExplicit.tdml
index 099c6c5a1b..ff00047748 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceLengthExplicit.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceLengthExplicit.tdml
@@ -84,6 +84,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+ BC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+ BC
+
+
+
+
+
+
+
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section12/aligned_data/TestAlignedData.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section12/aligned_data/TestAlignedData.scala
index 3c4de0add4..ad587d2a09 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section12/aligned_data/TestAlignedData.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section12/aligned_data/TestAlignedData.scala
@@ -209,6 +209,10 @@ class TestAlignedData extends TdmlTests {
@Test def prior_siblings_3 = test
@Test def prior_siblings_4 = test
@Test def prior_siblings_5 = test
+
+ // DAFFODIL-238
+ @Test def test_init_alignment_1_eop = test
+ @Test def test_init_alignment_2_eop = test
}
class TestBinaryInput extends TdmlTests {
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent.scala
new file mode 100644
index 0000000000..606daefff3
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent.scala
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section12.lengthKind
+
+import org.apache.daffodil.junit.tdml.TdmlSuite
+import org.apache.daffodil.junit.tdml.TdmlTests
+
+import org.junit.Test
+
+object TestLengthKindEndOfParent extends TdmlSuite {
+ val tdmlResource = "/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml"
+}
+
+class TestLengthKindEndOfParent extends TdmlTests {
+ val tdmlSuite = TestLengthKindEndOfParent
+
+ @Test def TestEndOfParentComplexTypesDelimited = test
+ @Test def TestEndOfParentSimpleTypesDelimited = test
+ @Test def TestEndOfParentComplexTypesImplicit = test
+ @Test def TestEndOfParentSimpleTypesImplicit = test
+ @Test def TestEndOfParentComplexTypesExplicit = test
+ @Test def TestEndOfParentSimpleTypesExplicit = test
+ @Test def TestEndOfParentCSVExplicit = test
+ @Test def TestEndOfParentComplexTypesPrefixed = test
+ @Test def TestEndOfParentSimpleTypesPrefixed = test
+ @Test def TestEndOfParentComplexTypesPattern = test
+ @Test def TestEndOfParentSimpleTypesPattern = test
+ @Test def TestEndOfParentComplexTypesEOP = test
+ @Test def TestEndOfParentSimpleTypesEOP = test
+ @Test def TestEndOfParentComplexTypes1 = test
+ @Test def TestEndOfParentSimpleTypes1 = test
+ @Test def TestEndOfParentComplexTypes2 = test
+ @Test def TestEndOfParentSimpleTypes2 = test
+ @Test def TestEndOfParentComplexTypes3 = test
+ @Test def TestEndOfParentSimpleTypes3 = test
+ @Test def TestEndOfParentComplexTypes4 = test
+ @Test def TestEndOfParentSimpleTypes4 = test
+ @Test def TestEndOfParentComplexTypes5 = test
+ @Test def TestEndOfParentSimpleTypes5 = test
+ @Test def TestEndOfParentComplexTypes6 = test
+ @Test def TestEndOfParentSimpleTypes6 = test
+ @Test def TestEndOfParentComplexTypes7 = test
+ @Test def TestEndOfParentSimpleTypes7 = test
+ @Test def TestEndOfParentComplexTypes8 = test
+ @Test def TestEndOfParentSimpleTypes8 = test
+ @Test def TestEndOfParentComplexTypes9 = test
+ @Test def TestEndOfParentSimpleTypes9 = test
+ @Test def TestEndOfParentComplexTypes10 = test
+ @Test def TestEndOfParentSimpleTypes10 = test
+ @Test def TestEndOfParentComplexTypes11 = test
+ @Test def TestEndOfParentSimpleTypes11 = test
+// @Test def TestEndOfParentComplexTypesRootChoice = test
+// @Test def TestEndOfParentSimpleTypesRootChoice = test
+ @Test def TestEndOfParentComplexTypes12 = test
+ @Test def TestEndOfParentSimpleTypes12 = test
+ @Test def TestEndOfParentComplexTypes13 = test
+ @Test def TestEndOfParentSimpleTypes13 = test
+ @Test def TestEndOfParentSimpleTypes14 = test
+ @Test def TestEndOfParentSimpleTypes16 = test
+ @Test def TestEndOfParentSimpleTypes17 = test
+ @Test def TestEndOfParentComplexTypesRootEOP = test
+ @Test def TestEndOfParentSimpleTypesRootEOP = test
+
+ @Test def text_string_txt_bytes = test
+ @Test def text_string_txt_bits = test
+ @Test def text_string_txt_chars = test
+ @Test def text_string_txt_ref1 = test
+ @Test def text_string_txt_ref2 = test
+ @Test def text_string_txt_ref3 = test
+ @Test def text_string_txt_bytes_nil = test
+ @Test def text_string_txt_bits_nil = test
+ @Test def text_string_txt_chars_nil = test
+ @Test def text_int_txt_bytes = test
+ @Test def text_int_txt_bytes_group_ref = test
+ @Test def text_int_txt_bits = test
+ @Test def text_int_txt_chars = test
+ @Test def text_dec_txt_bytes = test
+ @Test def text_dec_txt_bits = test
+ @Test def text_dec_txt_chars = test
+ @Test def text_date_txt_bytes = test
+ @Test def text_date_txt_bits = test
+ @Test def text_date_txt_chars = test
+ @Test def text_bool_txt_bytes = test
+ @Test def text_bool_txt_bits = test
+ @Test def text_bool_txt_chars = test
+ @Test def bin_int_bin_bytes_packed = test
+ @Test def bin_int_bin_bytes_bcd = test
+ @Test def bin_int_bin_bytes_ibm4690 = test
+ @Test def bin_dec_bin_bytes = test
+ @Test def bin_dec_bin_bytes_packed = test
+ @Test def bin_dec_bin_bytes_bcd = test
+ @Test def bin_dec_bin_bytes_ibm4690 = test
+ @Test def bin_hex_bytes = test
+ @Test def bin_bool_bin_bytes = test
+ @Test def bin_date_bin_bytes_packed = test
+ @Test def bin_date_bin_bytes_bcd = test
+ @Test def bin_date_bin_bytes_ibm4690 = test
+
+ @Test def nested_01 = test
+ @Test def nested_02 = test
+ @Test def nested_03 = test
+ @Test def checks_01 = test
+ @Test def checks_02 = test
+}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent2.scala
deleted file mode 100644
index 5928ed5f71..0000000000
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindEndOfParent2.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.daffodil.section12.lengthKind
-
-import org.apache.daffodil.junit.tdml.TdmlSuite
-import org.apache.daffodil.junit.tdml.TdmlTests
-
-import org.junit.Test
-
-object TestLengthKindEndOfParent2 extends TdmlSuite {
- val tdmlResource = "/org/apache/daffodil/section12/lengthKind/EndOfParentTests.tdml"
-}
-
-class TestLengthKindEndOfParent2 extends TdmlTests {
- val tdmlSuite = TestLengthKindEndOfParent2
-
- @Test def TestEndOfParentNYIComplexTypes = test
- @Test def TestEndOfParentNYISimpleTypes = test
-}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section13/packed/TestPacked.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section13/packed/TestPacked.scala
index 48fbcf95cf..4c7b516881 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section13/packed/TestPacked.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section13/packed/TestPacked.scala
@@ -95,4 +95,18 @@ class TestPacked extends TdmlTests {
// Daffodil-2961
@Test def bcdBigIntToLongExpr = test
+
+ // Daffodil-238
+ @Test def EOPPackedIntSeq = test
+ @Test def EOPPackedDecSeq = test
+ @Test def EOPPackedIntSeqUnparser = test
+ @Test def EOPPackedDecSeqUnparser = test
+ @Test def EOPBCDIntSeq = test
+ @Test def EOPBCDDecSeq = test
+ @Test def EOPBCDIntSeqUnparser = test
+ @Test def EOPBCDDecSeqUnparser = test
+ @Test def EOPIBM4690IntSeq = test
+ @Test def EOPIBM4690DecSeq = test
+ @Test def EOPIBM4690IntSeqUnparser = test
+ @Test def EOPIBM4690DecSeqUnparser = test
}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice.scala
index cfbb16a117..075f3a5183 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice.scala
@@ -133,6 +133,8 @@ class TestChoiceLengthExplicit extends TdmlTests {
@Test def explicit_07 = test
@Test def explicit_08 = test
@Test def explicit_09 = test
+ @Test def explicit_10 = test
+ @Test def explicit_11 = test
@Test def explicit_multiple_choices = test