This is an automated email from the ASF dual-hosted git repository.
olabusayo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new 62d9bb016 Add logic for separator/initiator/prefixed/terminator
alignment
62d9bb016 is described below
commit 62d9bb016b8893d3906763a701c0f71c0c4c239f
Author: olabusayoT <[email protected]>
AuthorDate: Mon Nov 24 17:17:59 2025 -0500
Add logic for separator/initiator/prefixed/terminator alignment
- Implement logic to calculate prefix, infix, and postfix separator
alignments and lengths in sequence terms.
- Added new alignment logic/test cases covering initiator alignment,
prefixed length elements, terminator alignment and value MTA (for optimization)
behavior.
- Add new variables to more accurately represent alignment, such as
contentEndAlignment, which is useful for delimiter text alignment before the
terminator and trailing skip is considered.
- Updated schemas and TDML files to include test data for new alignment
scenarios.
DAFFODIL-2295, DAFFODIL-3056, DAFFODIL-3057
---
.../daffodil/core/grammar/AlignedMixin.scala | 270 ++++++--
.../section12/aligned_data/Aligned_Data.tdml | 703 +++++++++++++++++++++
.../org/apache/daffodil/usertests/SepTests.tdml | 185 +++++-
.../section12/aligned_data/TestAlignedData.scala | 23 +
.../apache/daffodil/usertests/TestSepTests.scala | 7 +
5 files changed, 1113 insertions(+), 75 deletions(-)
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 a6d52b8a5..00ebdee13 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
@@ -21,17 +21,26 @@ import org.apache.daffodil.core.dsom.ElementBase
import org.apache.daffodil.core.dsom.ModelGroup
import org.apache.daffodil.core.dsom.QuasiElementDeclBase
import org.apache.daffodil.core.dsom.Root
+import org.apache.daffodil.core.dsom.SequenceTermBase
import org.apache.daffodil.core.dsom.Term
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.schema.annotation.props.gen.AlignmentKind
import org.apache.daffodil.lib.schema.annotation.props.gen.AlignmentUnits
import org.apache.daffodil.lib.schema.annotation.props.gen.LengthKind
+import org.apache.daffodil.lib.schema.annotation.props.gen.LengthKind.Prefixed
import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits
+import org.apache.daffodil.lib.schema.annotation.props.gen.Representation
+import org.apache.daffodil.lib.schema.annotation.props.gen.SeparatorPosition
import org.apache.daffodil.lib.util.Math
case class AlignmentMultipleOf(nBits: Long) {
+ // To combine alignments that could all happen at the same point in data,
use *,
+ // To add new alignment to an existing approximate alignment, use +
def *(that: AlignmentMultipleOf) = AlignmentMultipleOf(Math.gcd(nBits,
that.nBits))
def %(that: AlignmentMultipleOf) = nBits % that.nBits
+ def +(that: AlignmentMultipleOf) =
+ if (this.nBits % that.nBits == 0) this else that
+ // To combine AlignmentMultipleOfs and lengths, use +
def +(that: LengthApprox) = AlignmentMultipleOf(Math.gcd(nBits, nBits +
that.nBits))
}
@@ -63,13 +72,14 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
* Hence we are guaranteed to be properly aligned.
*/
final lazy val isKnownToBeAligned: Boolean =
LV(Symbol("isKnownToBeAligned")) {
- if (!isRepresented || (alignmentKindDefaulted == AlignmentKind.Manual))
true
- else {
- val pa = priorAlignmentWithLeadingSkipApprox
- val aa = alignmentApprox
- val res = (pa % aa) == 0
- res
- }
+ val res =
+ if (!isRepresented || (alignmentKindDefaulted == AlignmentKind.Manual))
true
+ else {
+ val pa = priorAlignmentWithLeadingSkipApprox
+ val aa = alignmentApprox
+ (pa % aa) == 0
+ }
+ res
}.value
/**
@@ -81,33 +91,37 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
* considers the surrounding context meeting the alignment needs.
*/
final lazy val isKnownToBeTextAligned: Boolean =
LV(Symbol("isKnownToBeTextAligned")) {
- if (alignmentKindDefaulted == AlignmentKind.Manual) true // manual
alignment
- else if (isKnownEncoding) {
- if (knownEncodingAlignmentInBits == 1)
- true
- else if (priorAlignmentWithLeadingSkipApprox.nBits %
knownEncodingAlignmentInBits == 0)
+ val res =
+ if (alignmentKindDefaulted == AlignmentKind.Manual) true // manual
alignment
+ else if (isKnownEncoding) {
+ if (knownEncodingAlignmentInBits == 1)
+ true
+ else if (priorAlignmentWithLeadingSkipApprox.nBits %
knownEncodingAlignmentInBits == 0)
+ true
+ else
+ false
+ } else if (schemaSet.root.isScannable)
true
else
false
- } else if (schemaSet.root.isScannable)
- true
- else
- false
+ res
}.value
final lazy val isDelimiterKnownToBeTextAligned: Boolean = {
- if (alignmentKindDefaulted == AlignmentKind.Manual) true // manual
alignment
- else if (isKnownEncoding) {
- if (knownEncodingAlignmentInBits == 1)
- true
- else if (endingAlignmentApprox.nBits % knownEncodingAlignmentInBits == 0)
+ val res =
+ if (alignmentKindDefaulted == AlignmentKind.Manual) true // manual
alignment
+ else if (isKnownEncoding) {
+ if (knownEncodingAlignmentInBits == 1)
+ true
+ else if (contentEndAlignment.nBits % knownEncodingAlignmentInBits == 0)
+ true
+ else
+ false
+ } else if (schemaSet.root.isScannable)
true
else
false
- } else if (schemaSet.root.isScannable)
- true
- else
- false
+ res
}
final lazy val hasNoSkipRegions = LV(Symbol("hasNoSkipRegions")) {
@@ -134,17 +148,17 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
LengthExact(trailingSkipInBits)
}
- // FIXME: DAFFODIL-2295
- // Does not take into account that in a sequence, what may be prior may be a
separator.
- // The separator is text in some encoding, might not be the same as this
term's encoding, and
- // the alignment will be left where that text leaves it.
- //
+ /**
+ * The priorAlignmentApprox doesn't need to take into account the separator
+ * alignment/length as that comes after the priorAlignmentApprox, but before
+ * the leadingSkip.
+ */
private lazy val priorAlignmentApprox: AlignmentMultipleOf =
LV(Symbol("priorAlignmentApprox")) {
if (this.isInstanceOf[Root] || this.isInstanceOf[QuasiElementDeclBase]) {
AlignmentMultipleOf(
0
- ) // root and quasi elements are aligned with anything // TODO:
really? Why quasi-elements - they should have implicit alignment ?
+ ) // root and quasi elements are aligned with anything (quasi elements
are always 1 aligned)
} else {
val priorSibs = potentialPriorTerms
val arraySelfAlignment =
@@ -201,7 +215,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
// Return 0 here, unordered alignment will be handled by
unorderedSequenceSelfAlignment
AlignmentMultipleOf(0)
} else {
- ps.endingAlignmentApprox
+ ps.endingAlignmentWithRightFramingApprox
}
eaa
}
@@ -222,75 +236,197 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
val priorAlignmentsApprox =
priorSibsAlignmentsApprox ++ parentAlignmentApprox ++
arraySelfAlignment ++ unorderedSequenceSelfAlignment
if (priorAlignmentsApprox.isEmpty)
- alignmentApprox // it will be the containing context's
responsibility to insure this IS where we start.
+ alignmentApprox // it will be the containing context's
responsibility to ensure this IS where we start.
else
priorAlignmentsApprox.reduce(_ * _)
}
}.value
- private lazy val priorAlignmentWithLeadingSkipApprox: AlignmentMultipleOf = {
- priorAlignmentApprox + leadingSkipApprox
+ private lazy val separatorPrefixInfixMTAApprox =
+ this.optLexicalParent match {
+ case Some(s: SequenceTermBase) if s.hasSeparator =>
+ import SeparatorPosition.*
+ s.separatorPosition match {
+ case Prefix | Infix =>
AlignmentMultipleOf(s.knownEncodingAlignmentInBits)
+ case Postfix => AlignmentMultipleOf(1)
+ }
+ case _ => AlignmentMultipleOf(1)
+ }
+
+ private lazy val separatorPostfixMTAApprox =
+ this.optLexicalParent match {
+ case Some(s: SequenceTermBase) if s.hasSeparator =>
+ import SeparatorPosition.*
+ s.separatorPosition match {
+ case Prefix | Infix => AlignmentMultipleOf(1)
+ case Postfix => AlignmentMultipleOf(s.knownEncodingAlignmentInBits)
+ }
+ case _ => AlignmentMultipleOf(1)
+ }
+
+ private lazy val separatorLengthApprox = this.optLexicalParent match {
+ case Some(s: SequenceTermBase) if s.hasSeparator =>
+ s.encodingLengthApprox
+ case _ => LengthExact(0)
}
- protected lazy val contentStartAlignment: AlignmentMultipleOf = {
- if (priorAlignmentWithLeadingSkipApprox % alignmentApprox == 0) {
- // alignment won't be needed, continue using prior alignment as start
alignment
- priorAlignmentWithLeadingSkipApprox
+ private lazy val initiatorMTAApprox =
+ if (this.hasInitiator) {
+ AlignmentMultipleOf(this.knownEncodingAlignmentInBits)
+ } else {
+ AlignmentMultipleOf(1)
+ }
+
+ private lazy val initiatorLengthApprox = if (this.hasInitiator) {
+ this.encodingLengthApprox
+ } else {
+ LengthExact(0)
+ }
+
+ private lazy val terminatorMTAApprox =
+ if (this.hasTerminator) {
+ AlignmentMultipleOf(this.knownEncodingAlignmentInBits)
} else {
- // alignment will be needed, it will be forced to be aligned to
alignmentApprox
- alignmentApprox
+ AlignmentMultipleOf(1)
+ }
+
+ private lazy val terminatorLengthApprox = if (this.hasTerminator) {
+ this.encodingLengthApprox
+ } else {
+ LengthExact(0)
+ }
+
+ /**
+ * prior alignment with leading skip includes the prefix/infix separator MTA
and length,
+ * any leading skips
+ */
+ private lazy val priorAlignmentWithLeadingSkipApprox: AlignmentMultipleOf = {
+ val priorAlignmentWithSeparatorApprox = priorAlignmentApprox
+ + separatorPrefixInfixMTAApprox
+ + separatorLengthApprox
+ val leadingAlignmentApprox = (priorAlignmentWithSeparatorApprox
+ + leadingSkipApprox)
+ leadingAlignmentApprox
+ }
+
+ /**
+ * The length of the prefix length quasi element.
+ *
+ * This is only relevant for quasi elements, or prefixed terms.
+ */
+ protected lazy val prefixLengthElementLength: LengthApprox = {
+ this match {
+ case eb: ElementBase => {
+ if (eb.lengthKind == Prefixed) {
+ val prefixTypeElem = eb.prefixedLengthElementDecl
+ prefixTypeElem.elementSpecifiedLengthApprox
+ } else {
+ LengthExact(0)
+ }
+ }
+ case _ => LengthExact(0)
+ }
+ }
+
+ /**
+ * The alignment of the term's value.
+ *
+ * This is only relevant for simple elements with textual representation.
+ */
+ private lazy val valueMTAApprox = {
+ this match {
+ case eb: ElementBase if eb.isSimpleType && eb.representation ==
Representation.Text => {
+ AlignmentMultipleOf(eb.knownEncodingAlignmentInBits)
+ }
+ case _ => AlignmentMultipleOf(1)
}
}
- protected lazy val endingAlignmentApprox: AlignmentMultipleOf = {
+ /**
+ * This alignment is made up of the alignment of the term itself,
+ * the initiator MTA and length, the prefix length quasi
+ * element length, and the value MTA (we add it for optimization
+ * but is extremely difficult to test, as other things such
+ * as unparsers will provide MTA, even elementSpecifiedLengthApprox
+ * considers the encoding also).
+ */
+ protected lazy val contentStartAlignment: AlignmentMultipleOf = {
+ val leftFramingApprox = priorAlignmentWithLeadingSkipApprox
+ + alignmentApprox
+ + initiatorMTAApprox
+ + initiatorLengthApprox
+ val csa = (leftFramingApprox + prefixLengthElementLength) + valueMTAApprox
+ csa
+ }
+
+ /**
+ * Accounts for the start of the content start alignment and element length.
+ * This is used to determine the alignment before the terminator and
trailing skip
+ */
+ protected lazy val contentEndAlignment: AlignmentMultipleOf = {
this match {
case eb: ElementBase => {
- if (eb.isComplexType && eb.lengthKind == LengthKind.Implicit) {
- eb.complexType.group.endingAlignmentApprox + trailingSkipApprox
+ val res = if (eb.isComplexType && eb.lengthKind ==
LengthKind.Implicit) {
+ eb.complexType.group.contentEndAlignment
} else {
// simple type or complex type with specified length
- contentStartAlignment + (elementSpecifiedLengthApprox +
trailingSkipApprox)
+ contentStartAlignment + elementSpecifiedLengthApprox
}
+ res
}
case mg: ModelGroup => {
//
// We're interested in how the model group ends. Whatever could be
- // the last term, each individual such possibility has an
endingAlignmentApprox,
- // and we need to aggregate those to get the summary
endingAlignmentApprox.
+ // the last term, each individual such possibility has an
endingAlignmentWithRightFramingApprox,
+ // and we need to aggregate those to get the summary
endingAlignmentWithRightFramingApprox.
//
val (lastChildren, couldBeLast) = mg.potentialLastChildren
val lastApproxesConsideringChildren: Seq[AlignmentMultipleOf] =
lastChildren.map { lc =>
- //
- // for each possible last child, add its ending alignment
- // to our trailing skip to get where it would leave off were
- // it the actual last child.
- //
- val lceaa = lc.endingAlignmentApprox
- val res = lceaa + trailingSkipApprox
- res
+ // for each possible last child, gather its
endingAlignmentWithRightFramingApprox
+ // as we want to account for the separators that are a part of the
SequenceContent (see DFDL spec)
+ val lceaa = lc.endingAlignmentWithRightFramingApprox
+ lceaa
}
val optApproxIfNoChildren =
//
// gather possibilities for this item itself
//
- if (couldBeLast)
+ if (couldBeLast) {
//
// if this model group could be last, then consider
// if none of its content was present.
- // We'd just have the contentStart, nothing, and the trailing Skip.
+ // We'd just have the contentStart
//
- Some(contentStartAlignment + trailingSkipApprox)
- else
+ Some(contentStartAlignment)
+ } else
// can't be last, no possibilities to gather.
None
val lastApproxes = lastApproxesConsideringChildren ++
optApproxIfNoChildren
+ // take all the gathered possibilities to get where it would leave off
were
+ // each the actual last child.
Assert.invariant(lastApproxes.nonEmpty)
- val res = lastApproxes.reduce { _ * _ }
- res
+ lastApproxes.reduce(_ * _)
}
}
}
+ /**
+ * Add the ending alignment of the term
+ * to terminator MTA/length and our trailing skip
+ *
+ * The postfix separator MTA/length needs to be added after the trailing skip
+ */
+ protected lazy val endingAlignmentWithRightFramingApprox:
AlignmentMultipleOf = {
+ val endingAlignmentApprox = this.contentEndAlignment
+ + terminatorMTAApprox
+ + terminatorLengthApprox
+ + trailingSkipApprox
+ val res = endingAlignmentApprox
+ + separatorPostfixMTAApprox
+ + separatorLengthApprox
+ res
+ }
+
protected lazy val elementSpecifiedLengthApprox: LengthApprox = {
this match {
case eb: ElementBase => {
@@ -315,22 +451,24 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
eb.lengthUnits match {
case LengthUnits.Bits => LengthMultipleOf(1)
case LengthUnits.Bytes => LengthMultipleOf(8)
- case LengthUnits.Characters => encodingLengthApprox
+ case LengthUnits.Characters => eb.encodingLengthApprox
}
}
case LengthKind.Delimited => encodingLengthApprox
case LengthKind.Pattern => encodingLengthApprox
case LengthKind.EndOfParent => LengthMultipleOf(1) // NYI
- case LengthKind.Prefixed => LengthMultipleOf(1) // NYI
+ // 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)
}
}
case _: ModelGroup => Assert.usageError("Only for elements")
}
}
- private lazy val encodingLengthApprox: LengthApprox = {
- if (isKnownEncoding) {
- val dfdlCharset = charsetEv.optConstant.get
+ protected lazy val encodingLengthApprox: LengthApprox = {
+ if (this.isKnownEncoding) {
+ val dfdlCharset = this.charsetEv.optConstant.get
val fixedWidth =
if (dfdlCharset.maybeFixedWidth.isDefined)
dfdlCharset.maybeFixedWidth.get else 8
LengthMultipleOf(fixedWidth)
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 119c79985..c2be97ef3 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
@@ -603,6 +603,438 @@
</xs:element>
</tdml:defineSchema>
+ <tdml:defineSchema name="s2" elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormatPortable.dfdl.xsd"/>
+ <dfdl:format
+ ref="ex:GeneralFormat"
+ representation="text"
+ lengthKind="delimited"
+ separatorPosition="infix"
+ lengthUnits="bits"
+ alignmentUnits="bits"
+ encoding="US-ASCII"
+ />
+
+ <xs:element name="postfix_init">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:initiator="I"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix_init_2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="1" dfdl:initiator="I">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2" type="xs:string"
+ dfdl:length="16" dfdl:fillByte="2"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix_term">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A" dfdl:terminator="T"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix_term_2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="1" dfdl:terminator="T">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2" type="xs:string"
+ dfdl:length="16" dfdl:fillByte="2"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:simpleType name="prefixType" dfdl:lengthKind="explicit"
dfdl:length="8">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:element name="prefixed_element">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="c" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="16"
+ dfdl:fillByte="C"/>
+ <xs:element name="a" type="xs:string"
+ dfdl:prefixLengthType="ex:prefixType"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:lengthKind="prefixed"
+ dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ </tdml:defineSchema>
+
+ <tdml:defineSchema name="s3" elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormatPortable.dfdl.xsd"/>
+ <dfdl:format
+ ref="ex:GeneralFormat"
+ representation="text"
+ lengthKind="delimited"
+ separatorPosition="infix"
+ lengthUnits="bytes"
+ alignmentUnits="bytes"
+ encoding="US-ASCII"
+ />
+ <xs:simpleType name="prefixType" dfdl:lengthKind="explicit"
dfdl:length="1">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:element name="prefixed_element">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="c" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="C"/>
+ <xs:element name="a" type="xs:string"
+ dfdl:prefixLengthType="ex:prefixType"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:lengthKind="prefixed"
+ dfdl:alignment="2"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+
+ <xs:simpleType name="prefixType_bits" dfdl:lengthKind="explicit"
dfdl:lengthUnits="bits" dfdl:length="16">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="deep_prefixed_inner" dfdl:lengthKind="explicit"
dfdl:lengthUnits="bits" dfdl:length="16">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="deep_prefixed_outer"
+ dfdl:lengthKind="prefixed"
+ dfdl:prefixLengthType="ex:prefixType_bits"
+ dfdl:prefixIncludesPrefixLength="no">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:element name="prefixed_element_bits">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="c" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="C"/>
+ <xs:element name="a" type="xs:string"
+ dfdl:lengthUnits="bits"
+ dfdl:prefixLengthType="ex:prefixType_bits"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:lengthKind="prefixed"
+ dfdl:alignment="2"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="prefixed_element_nested">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="c" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="C"/>
+ <xs:element name="a" type="xs:string"
+ dfdl:lengthUnits="bits"
+ dfdl:prefixLengthType="ex:deep_prefixed_outer"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:lengthKind="prefixed"
+ dfdl:alignment="2"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="2"
+ dfdl:lengthKind="explicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:defineSchema name="s4" elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormatPortable.dfdl.xsd"/>
+ <dfdl:format
+ ref="ex:GeneralFormat"
+ representation="text"
+ lengthKind="delimited"
+ separatorPosition="infix"
+ lengthUnits="bytes"
+ alignmentUnits="bytes"
+ encoding="US-ASCII"
+ />
+
+ <xs:element name="elem">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:encoding="X-DFDL-BITS-MSBF"
+ dfdl:lengthUnits="bits"
+ dfdl:fillByte="%#r00;"
+ dfdl:length="4"
+ dfdl:lengthKind="explicit"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="0"
+ dfdl:lengthKind="explicit"
+ dfdl:trailingSkip="4"
+ dfdl:fillByte="%#rFF;"/>
+ <xs:element name="c" type="xs:string"
+ dfdl:encoding="X-DFDL-BITS-MSBF"
+ dfdl:lengthUnits="bits"
+ dfdl:fillByte="%#r00;"
+ dfdl:length="4"
+ dfdl:lengthKind="explicit"
+ />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:defineSchema name="s5" elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormatPortable.dfdl.xsd"/>
+ <dfdl:format
+ ref="ex:GeneralFormat"
+ representation="text"
+ lengthKind="explicit"
+ lengthUnits="bytes"
+ alignmentUnits="bytes"
+ encoding="US-ASCII"
+ />
+
+ <xs:element name="elem1" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:string" dfdl:length="1"/>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:string"
+ dfdl:fillByte="A"
+ dfdl:length="1"
+ dfdl:alignment="2"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="1"
+ dfdl:alignment="2"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="elem2" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+<!-- <xs:element name="e0" type="xs:string" dfdl:length="1"/>-->
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="a" type="xs:int"
+ dfdl:representation="binary"
+ dfdl:fillByte="%#rFF;"
+ dfdl:encoding="X-DFDL-BITS-MSBF"
+ dfdl:lengthUnits="bits"
+ dfdl:alignmentUnits="bits"
+ dfdl:length="4"/>
+ <xs:element name="b" type="xs:int"
+ minOccurs="0"
+ dfdl:representation="binary"
+ dfdl:initiator="-"
+ dfdl:fillByte="%#r00;"
+ dfdl:length="1"
+ dfdl:alignment="1"/>
+ <xs:element name="c" type="xs:int"
+ dfdl:representation="binary"
+ dfdl:length="1"
+ dfdl:alignment="1"
+ dfdl:fillByte="%#rFF;"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="elem3" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:string" dfdl:length="1"/>
+ <xs:element name="e1" dfdl:lengthKind="implicit"
+ dfdl:alignment="2"
+ dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="opt" type="xs:string"
+ minOccurs="0"
+ dfdl:initiator="-"
+ dfdl:fillByte="O"
+ dfdl:length="1"
+ dfdl:alignment="2"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="1"
+ dfdl:alignment="2"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:simpleType name="innerPrefixType" dfdl:lengthKind="explicit"
dfdl:representation="binary" dfdl:length="1">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="outerPrefixType" dfdl:lengthKind="prefixed"
+ dfdl:prefixLengthType="ex:innerPrefixType"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:representation="binary">
+ <xs:restriction base="xs:int"/>
+ </xs:simpleType>
+
+
+
+ <xs:element name="elem4" type="xs:int"
+ dfdl:representation="binary" dfdl:lengthKind="prefixed"
+ dfdl:prefixLengthType="ex:outerPrefixType"
+ dfdl:prefixIncludesPrefixLength="no"
+ dfdl:initiator="FOO:" dfdl:encoding="US-ASCII" />
+ </tdml:defineSchema>
+
<!--
Test Name: impAlignmentHexBinary
Schema: implicitAlignmentSchema
@@ -3909,5 +4341,276 @@
<tdml:documentPart type="bits">01</tdml:documentPart> <!-- base-4 "1"
string (no mta fill bits)-->
</tdml:document>
</tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_init_alignment_1" root="postfix_init"
model="s2" roundTrip="onePass">
+ <tdml:document>IaaBbb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix_init xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:postfix_init>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_init_alignment_2" root="postfix_init_2"
model="s2" roundTrip="onePass">
+ <tdml:document>IAaabbee</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix_init_2 xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ <e2>ee</e2>
+ </ex:postfix_init_2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_term_alignment_1" root="postfix_term"
model="s2" roundTrip="onePass">
+ <tdml:document>aaTBbb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix_term xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:postfix_term>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_term_alignment_2" root="postfix_term_2"
model="s2" roundTrip="onePass">
+ <tdml:document>aabbT2ee</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix_term_2 xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ <e2>ee</e2>
+ </ex:postfix_term_2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_prefix_alignment_0"
root="prefixed_element" model="s2" roundTrip="onePass">
+ <!-- can't be 1 bit aligned, and no way to set to 8 bits without it
complaining -->
+ <!-- <tdml:document>cc16aaBbb</tdml:document>-->
+
+ <tdml:errors>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>1 bits</tdml:error>
+ <tdml:error>must be a multiple</tdml:error>
+ <tdml:error>8 bits</tdml:error>
+ <tdml:error>US-ASCII</tdml:error>
+ </tdml:errors>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:prefixed_element xmlns:ex="http://example.com">
+ <e1>
+ <c>cc</c>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:prefixed_element>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_prefix_alignment_1"
root="prefixed_element" model="s3" roundTrip="onePass">
+ <tdml:document>cc2aaBbb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:prefixed_element xmlns:ex="http://example.com">
+ <e1>
+ <c>cc</c>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:prefixed_element>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_prefix_alignment_2"
root="prefixed_element_bits" model="s3" roundTrip="onePass">
+ <tdml:document>cc16aabb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:prefixed_element_bits xmlns:ex="http://example.com">
+ <e1>
+ <c>cc</c>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:prefixed_element_bits>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_prefix_alignment_3"
root="prefixed_element_nested" model="s3" roundTrip="onePass">
+ <tdml:document>cc16aabb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:prefixed_element_nested xmlns:ex="http://example.com">
+ <e1>
+ <c>cc</c>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:prefixed_element_nested>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ <tdml:errors>
+ <tdml:error>Nested</tdml:error>
+ <tdml:error>prefixed</tdml:error>
+ <tdml:error>not supported</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_prefix_alignment_4" root="elem4"
model="s5" roundTrip="onePass">
+ <tdml:document>
+ <tdml:documentPart type="text">FOO:</tdml:documentPart>
+ <tdml:documentPart type="byte">040000FFFF</tdml:documentPart>
+ </tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem4 xmlns:ex="http://example.com">65535</ex:elem4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ <tdml:errors>
+ <tdml:error>Nested</tdml:error>
+ <tdml:error>prefixed</tdml:error>
+ <tdml:error>not supported</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_valueMTA_alignment_1" root="elem"
model="s4" roundTrip="onePass">
+ <tdml:document>
+ <tdml:documentPart type="bits">1110</tdml:documentPart>
+ <tdml:documentPart type="bits">1111</tdml:documentPart> <!-- pre b
alignment -->
+ <tdml:documentPart type="byte">FFFFFFFF</tdml:documentPart> <!-- post b
trailing skip -->
+ <tdml:documentPart type="bits">0111</tdml:documentPart><!-- c -->
+ <tdml:documentPart type="bits">0000</tdml:documentPart><!-- c -->
+ </tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem xmlns:ex="http://example.com">
+ <e1>
+ <a>1110</a>
+ <b></b>
+ <c>0111</c>
+ </e1>
+ </ex:elem>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="prior_siblings_1" root="elem1" model="s5"
roundTrip="onePass">
+ <tdml:document>eEaBb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem1 xmlns:ex="http://example.com">
+ <e0>e</e0>
+ <e1>
+ <a>a</a>
+ <b>b</b>
+ </e1>
+ </ex:elem1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="prior_siblings_2" root="elem2" model="s5"
roundTrip="onePass">
+ <tdml:document>
+ <tdml:documentPart type="bits">0011</tdml:documentPart>
+ <tdml:documentPart type="bits">1111</tdml:documentPart> <!-- pre c
alignment -->
+ <tdml:documentPart type="bits">0000</tdml:documentPart> <!-- c -->
+ <tdml:documentPart type="bits">0100</tdml:documentPart> <!-- c -->
+ </tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem2 xmlns:ex="http://example.com">
+ <e1>
+ <a>3</a>
+ <c>4</c>
+ </e1>
+ </ex:elem2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="prior_siblings_3" root="elem2" model="s5"
roundTrip="onePass">
+ <tdml:document>
+ <tdml:documentPart type="bits">0011</tdml:documentPart>
+ <tdml:documentPart type="bits">0000</tdml:documentPart> <!-- pre b
alignment -->
+ <tdml:documentPart type="text">-</tdml:documentPart> <!-- b initiator-->
+ <tdml:documentPart type="bits">00000101</tdml:documentPart> <!-- b -->
+ <tdml:documentPart type="bits">00000100</tdml:documentPart> <!-- c -->
+ </tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem2 xmlns:ex="http://example.com">
+ <e1>
+ <a>3</a>
+ <b>5</b>
+ <c>4</c>
+ </e1>
+ </ex:elem2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="prior_siblings_4" root="elem3" model="s5"
roundTrip="onePass">
+ <tdml:document>eE-ob</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem3 xmlns:ex="http://example.com">
+ <e0>e</e0>
+ <e1>
+ <opt>o</opt>
+ <b>b</b>
+ </e1>
+ </ex:elem3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="prior_siblings_5" root="elem3" model="s5"
roundTrip="onePass">
+ <tdml:document>eEb</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:elem3 xmlns:ex="http://example.com">
+ <e0>e</e0>
+ <e1>
+ <b>b</b>
+ </e1>
+ </ex:elem3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
index 0ab4ea916..61d08de6b 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
@@ -143,14 +143,6 @@
separatorPosition="infix"
emptyElementParsePolicy="treatAsEmpty"/>
- <!-- DAFFODIL-2217
- These additional tests give another case where trailingEmptyStrict
should be causing a
- parse error, but it does not in a case where maxOccurs="3" but works
correctly when maxOccurs="4".
- -->
-
- <!-- maxOccurs='3' fails to detect the trailing "/" i.e., this should fail
with a parse error
- due to trailingEmptyStrict -->
-
<xs:element name="file1">
<xs:complexType>
<xs:sequence dfdl:separator="/" dfdl:separatorPosition="infix"
@@ -160,7 +152,6 @@
</xs:complexType>
</xs:element>
- <!-- same, but maxOccurs is 4. This works, as in detects the error. -->
<xs:element name="file2">
<xs:complexType>
<xs:sequence dfdl:separator="/" dfdl:separatorPosition="infix"
@@ -680,4 +671,180 @@
</tdml:dfdlInfoset>
</tdml:infoset>
</tdml:parserTestCase>
+
+ <tdml:defineSchema name="s8" elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormatPortable.dfdl.xsd"/>
+ <dfdl:format
+ ref="ex:GeneralFormat"
+ representation="text"
+ lengthKind="delimited"
+ separatorPosition="infix"
+ lengthUnits="bits"
+ alignmentUnits="bits"
+ />
+
+ <xs:element name="infix">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence
+ dfdl:separator="/"
+ dfdl:separatorPosition="infix" dfdl:fillByte="S">
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="prefix">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence
+ dfdl:separator="/"
+ dfdl:separatorPosition="prefix" dfdl:fillByte="S">
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence
+ dfdl:separator="/"
+ dfdl:separatorPosition="postfix" dfdl:fillByte="S">
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix_2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:fillByte="E">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="-" dfdl:separatorPosition="postfix"
dfdl:fillByte="0">
+ <xs:element name="c" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="C"/>
+ <xs:sequence
+ dfdl:separator="/"
+ dfdl:separatorPosition="postfix" dfdl:fillByte="1">
+ <xs:element name="a" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="A"/>
+ <xs:element name="b" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="B"/>
+ </xs:sequence>
+ <xs:element name="d" type="xs:string"
+ dfdl:length="16"
+ dfdl:lengthKind="explicit" dfdl:alignment="16"
+ dfdl:fillByte="D"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:unparserTestCase name="test_sep_alignment_1" root="infix" model="s8"
roundTrip="onePass">
+ <tdml:document>aa/Bbb</tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:infix xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:infix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_sep_alignment_2" root="prefix" model="s8"
roundTrip="onePass">
+ <tdml:document>/Aaa/Bbb</tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:prefix xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:prefix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_sep_alignment_3" root="postfix"
model="s8" roundTrip="onePass">
+ <tdml:document>aa/Bbb/</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix xmlns:ex="http://example.com">
+ <e1>
+ <a>aa</a>
+ <b>bb</b>
+ </e1>
+ </ex:postfix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="test_sep_alignment_4" root="postfix_2"
model="s8" roundTrip="onePass">
+ <tdml:document>cc-Aaa/Bbb/-dd-</tdml:document>
+
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:postfix_2 xmlns:ex="http://example.com">
+ <e1>
+ <c>cc</c>
+ <a>aa</a>
+ <b>bb</b>
+ <d>dd</d>
+ </e1>
+ </ex:postfix_2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
</tdml:testSuite>
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 23967c96a..3c4de0add 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
@@ -186,6 +186,29 @@ class TestAlignedData extends TdmlTests {
@Test def alignmentFillByteDefined = test
@Test def separatorMTA_01 = test
+
+ // DAFFODIL-3056
+ @Test def test_init_alignment_1 = test
+ @Test def test_init_alignment_2 = test
+ @Test def test_prefix_alignment_1 = test
+ @Test def test_prefix_alignment_2 = test
+ @Test def test_prefix_alignment_3 = test
+ @Test def test_prefix_alignment_4 = test
+ @Test def test_valueMTA_alignment_1 = test
+
+ // DAFFODIL-3057
+ @Test def test_term_alignment_1 = test
+ @Test def test_term_alignment_2 = test
+
+ // DAFFODIL-3059
+ @Test def test_prefix_alignment_0 = test
+
+ // DAFFODIL-3060
+ @Test def prior_siblings_1 = test
+ @Test def prior_siblings_2 = test
+ @Test def prior_siblings_3 = test
+ @Test def prior_siblings_4 = test
+ @Test def prior_siblings_5 = test
}
class TestBinaryInput extends TdmlTests {
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
index 3ffd03612..9c27ba726 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
@@ -55,4 +55,11 @@ class TestSepTests extends TdmlTests {
// DAFFODIL-2791
@Test def test_treatAsAbsent_occursIndex = test
+
+ // DAFFODIL-2295
+ @Test def test_sep_alignment_1 = test
+ @Test def test_sep_alignment_2 = test
+ @Test def test_sep_alignment_3 = test
+
+ @Test def test_sep_alignment_4 = test
}