Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

At this point we have unparsed element 'd', so we know it's length now, it is 28 bits long.NEXT UP:  'a' outputValueCalc can be evaluated, and the whole thing can collapse to the right (illustrate this).the details of that are elsewhere, but basically, when we receive the event for element 'd', we construct an infoset element node. Since element 'd' is used in expressions, we know we must capture four things: contentStartPosition, valueStartPosition, valueEndPosition, and contentEndPosition (tbd; names aren't right), and as we unparse the value of 'd' into the output stream (third one, right-most above), we record these positions.

The expression for computing element 'a' value depends on knowing the content-length of element 'd', so once we have the contentEndPosition, we can subtract the contentStartPosition and we know the content length. This allows the suspended computation of the value for element 'a', and the unparsing thereof, to be resumed.

So, that expression is evaluated, creates the value 28, and that value is stored in the infoset element for the instance of 'a'. Then the unparsing of that infoset element is done, and stored with the suspended computation/unparser is the data output stream to use, which is the left-most one above. Now 28 expressed as binary is 11100 (5 bits), so we write these bits to the data output stream.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameCopy of Copy of Copy of Copy of Copy of buffered50
simpleViewerfalse
width
diagramWidth893
revision3

The last thing the suspended computation and unparser for 'a' does, is "setFinal" on the data output stream. This tells the data output stream that no further data will be appended. What follows its contents is then logically the next data output stream (middle one above). The "setFinal" operation initiates a process called "collapsing" the data output stream buffers.

The data output streams are connected into a double-linked chain:

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameCopy of Copy of Copy of Copy of Copy of Copy of buffered50
simpleViewerfalse
width
diagramWidth893
revision2

We've also emphasized that this first data output stream on the left is  special. it is the "direct" output stream in that it is actually connected to a java.io.OutputStream, not just to a buffer. Bytes written to the "whole bytes" of the direct output stream actually are being written out by Daffodil.

So when a buffered data output stream is setFinal, it is simply marked as such, and this will be checked on later. But when the direct data output stream is marked final, then it is combined with the next data output stream. If that stream is final, then it will be combined with the next after that, and so on until either all the streams have been collapsed and all data written out, or a data stream that is not final is encountered.

So looking at the collapsing of the direct and first buffered data output stream, first the data of the buffered stream is written to the direct data output stream. Since the direct data output stream has a frag byte, that byte must be completed first. In this example, the buffered data output stream (middle above) doesn't have any whole bytes, but it does have a frag byte, and so bits from this frag byte are moved into the direct data output stream's frag byte.

In this example, the direct data output stream's frag byte has 5 bits, and the buffered data output stream contributes 3 more, making a whole byte:

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph10
simpleViewerfalse
width
diagramWidth893
revision3

Notice now that the middle stream has no contents any more. It's bit length is now 0. Since the frag byte of the direct stream is full, this is output, and the direct stream's frag byte is cleared.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph20
simpleViewerfalse
width
diagramWidth893
revision3

Next the direct output stream and the buffered data output stream (left and middle) are "Morphed". The middle buffered data output stream will morph into being a direct output stream by taking up the actual java.io.OutputStream of the left-most stream. The formerly direct data output stream on the left is now "dead", and can be discarded (garbage collected, or returned to a pool).

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph30
simpleViewerfalse
width
diagramWidth886
revision2

Now, the middle data output stream (now the direct one), was FINAL before, and remains FINAL. That means we continue to look to the right and combine the direct data output stream into the next buffered data output stream. In this case, the right-most stream has 3 whole bytes, the direct stream has no frag byte, so those whole bytes are just output to the direct stream's whole bytes.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph40
simpleViewerfalse
width
diagramWidth886
revision2

Next the frag byte contents from the right-most data stream are output to the direct stream. As the frag byte of the direct stream is empty, these bits just move over to the direct stream's frag byte.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph50
simpleViewerfalse
width
diagramWidth886
revision2

Note that in the above, we're now collapsing the data output stream created by unparsing element 'c', and that element had bit order LSBF. When we copied the whole bytes, since there was no frag byte the bit-order change is legal. Had there been a frag byte on the direct stream, then changing bit orders would have had to create a runtime Schema Definition Error, as it is not meaningful to change bit order in the middle of a byte.

Now the last step is that the direct stream and buffered stream will again morph:

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamemorph60
simpleViewerfalse
width
diagramWidth886
revision2