You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ji...@apache.org on 2023/04/07 23:14:04 UTC
[daffodil] branch main updated: Add left over data check to generated C parsers
This is an automated email from the ASF dual-hosted git repository.
jinterrante 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 7d52935d8 Add left over data check to generated C parsers
7d52935d8 is described below
commit 7d52935d8983d6038a8f071c44e547cf3e6b85ad
Author: John Interrante <in...@research.ge.com>
AuthorDate: Sat Apr 1 11:38:25 2023 -0700
Add left over data check to generated C parsers
Fix generated C parsers not checking for left over data after parse
calls and not clearing infoset between parse calls. Rename some
infoset C functions more consistently (C snake style).
Also enhance C code generator to support DFDL schemas containing
simple type root elements, allowing generated C parsers to parse data
and infosets containing only a single element. Add examples and new
tests for simple root elements as well.
Also replace any non-alphabetical / non-numerical characters with
underscores when converting XML identifiers to C identifiers, allowing
XML element names like "simple-boolean" to become "simple_boolean" in
generated C code.
DAFFODIL-2807
Main.scala: Avoid second exception if TDMLRunner throws a
NullPointerException and Main tries to print its message (NPEs don't
have a message).
testNonCompatibleImplementation.tdml: Both ibm and daffodilC can use
same schema with single element now. Merge s1 into s2 and remove s2.
TestCLItdml.scala: Remove unnecessary "-iii" options from CLI test.
daffodil_main.c: Call `get_infoset(CLEAR_INFOSET)` instead of
`rootElement()`, call `parse_data(infoset, &pstate)` instead of
`root->erd->parseSelf(root, &pstate)`, call `walk_infoset` instead of
`walkInfoset`, and call `unparse_infoset(infoset, &ustate)` instead of
`root->erd->unparseSelf(root, &ustate)`, showing how you can clear the
infoset between `parse_data` calls if you call the C parser in a loop.
xml_reader.h: Remove unused `root` field from XMLReader struct.
errors.c: Add error message for new error `ERR_LEFTOVER_DATA`.
errors.h: Define new error `ERR_LEFTOVER_DATA` and remove `UNUSED`
macro (define it in infoset.h instead).
infoset.c: Rename some infoset C functions more consistently (C snake
style). Define new functions `parse_data` and `unparse_infoset` and
make them call `no_leftover_data` and `flush_fragment_byte` so user
will only need to call `get_infoset(CLEAR_INFOSET)` and `parse_data`
to get correct C parser behavior. Also rename ERD field `offsets` to
`childrenOffsets`. Remove `flushUstate` function (define it as
`flush_fragment_byte` in unparsers.c instead).
infoset.h: Rename ERD field `offsets` to `childrenOffsets` and PState,
UState fields `unreadLen`, `unwritLen` to `numUnreadBits`,
`numUnwritBits`. Rename function `rootElement(void)` to
`get_infoset(clear_infoset)`. Declare new functions `parse_data` and
`unparse_infoset`. Rename `walkInfoset` to `walk_infoset` (snake
style). Define `UNUSED` macro here to let extras.c use it.
parsers.[ch]: Say fragment byte, not fractional byte. Define function
`no_leftover_data` to check for leftover data (called by
`parse_data`). Use renamed `pstate->numUnreadBits`.
unparsers.[ch]: Say fragment byte, not fractional byte. Use renamed
`ustate->numUnwritBits`. Define function `flush_fragment_byte`, give
it a fill_byte parameter, fill fragment byte from fill byte, write
fragment byte, and increment ustate->bitPos0b correctly (was adding
BYTE_WIDTH - ustate->numUnwritBits instead of ustate->numUnwritBits).
bits.c: Use renamed `numUnreadBits` and `numUnwritBits`. Call
`flush_fragment_byte` instead of `flushUstate` and pass it a zero
fill_byte. Fix incorrect ustate.bitPos0b expected values after
`flush_fragment_byte` calls.
extras.c: Implement `get_infoset` instead of `rootElement`.
DaffodilCExamplesGenerator.scala: Replace multiple schema, root name,
and example dir variables with Array of tuples to be more terse.
Generate simple root element C example too.
BinaryBooleanCodeGenerator.scala: Convert XML names to C names.
BinaryValueCodeGenerator.scala: Convert XML names to C names.
CodeGeneratorState.scala: Detect the case when a root element is a
simple type and translate it as a hybrid complex and simple type (that
is, push state for a complex element on the stack and when popping
that state, generate the hybrid offset computations and ERD
declarations needed to parse the simple type root element
successfully). Generate C function `get_infoset(clear_infoset)`
instead of `rootElement(void)` to clear infoset between parses with a
comment to warn callers that get_infoset(CLEAR_INFOSET) won't free
malloc'ed storage for hexBinary prefixed length elements at this time.
Define new `cName` method and `makeLegalForC` helper method to convert
XML names to C names. Use renamed ERD field `childrenOffsets` and
remove comments suffixing identifiers with redundant names.
HexBinaryCodeGenerator.scala: Convert XML names to C names.
examples/**/generated_code.c: Regenerate C examples to show effect of
pull request changes and add a simple root element's C example.
data/simple*.dat: Add new data files to test simple root elements.
infosets/simple*.dat.xml: Add simple root element infosets.
simple.dfdl.xsd: Add new DFDL schema with choice of simple root
elements to test (one root element for each primitive type).
simple.tdml: Add test cases for all simple root elements listed in
simple.dfdl.xsd.
simple-errors.tdml: Add error test cases for simple root elements
listed in simple.dfdl.xsd, although don't need to test every integer
type.
TestSimple.scala: Add unit tests for all test cases listed in
simple.tdml.
TestSimpleErrors.scala: Add unit tests for all test cases listed in
simple-errors.tdml.
---
.../main/scala/org/apache/daffodil/cli/Main.scala | 2 +-
.../cli/testNonCompatibleImplementation.tdml | 33 +--
.../apache/daffodil/cli/cliTest/TestCLItdml.scala | 2 +-
.../codegen/c/files/libcli/daffodil_main.c | 29 +-
.../daffodil/codegen/c/files/libcli/xml_reader.h | 5 +-
.../daffodil/codegen/c/files/libcli/xml_writer.h | 2 +-
.../daffodil/codegen/c/files/libruntime/errors.c | 1 +
.../daffodil/codegen/c/files/libruntime/errors.h | 5 +-
.../daffodil/codegen/c/files/libruntime/infoset.c | 148 ++++-----
.../daffodil/codegen/c/files/libruntime/infoset.h | 53 ++--
.../daffodil/codegen/c/files/libruntime/parsers.c | 75 +++--
.../daffodil/codegen/c/files/libruntime/parsers.h | 7 +-
.../codegen/c/files/libruntime/unparsers.c | 68 +++--
.../codegen/c/files/libruntime/unparsers.h | 7 +-
.../apache/daffodil/codegen/c/files/tests/bits.c | 90 +++---
.../apache/daffodil/codegen/c/files/tests/extras.c | 8 +-
.../codegen/c/DaffodilCExamplesGenerator.scala | 35 +--
.../c/generators/BinaryBooleanCodeGenerator.scala | 2 +-
.../c/generators/BinaryValueCodeGenerator.scala | 4 +-
.../codegen/c/generators/CodeGeneratorState.scala | 161 +++++++---
.../c/generators/HexBinaryCodeGenerator.scala | 6 +-
.../src/test/examples/NestedUnion/generated_code.c | 70 ++---
.../src/test/examples/ex_nums/generated_code.c | 142 ++++-----
.../src/test/examples/padtest/generated_code.c | 46 +--
.../src/test/examples/simple/generated_code.c | 79 +++++
.../src/test/examples/simple/generated_code.h | 19 ++
.../src/test/examples/variablelen/generated_code.c | 58 ++--
.../daffodil/codegen/c/data/simple-boolean.dat | Bin 0 -> 4 bytes
.../apache/daffodil/codegen/c/data/simple-byte.dat | Bin 0 -> 1 bytes
.../daffodil/codegen/c/data/simple-double.dat | Bin 0 -> 8 bytes
.../daffodil/codegen/c/data/simple-float.dat | Bin 0 -> 4 bytes
.../daffodil/codegen/c/data/simple-hexBinary.dat | Bin 0 -> 4 bytes
.../codegen/c/data/simple-hexBinaryPrefixed.dat | Bin 0 -> 6 bytes
.../apache/daffodil/codegen/c/data/simple-int.dat | Bin 0 -> 4 bytes
.../daffodil/codegen/c/data/simple-integer.dat | Bin 0 -> 4 bytes
.../apache/daffodil/codegen/c/data/simple-long.dat | Bin 0 -> 8 bytes
.../codegen/c/data/simple-nonNegativeInteger.dat | Bin 0 -> 4 bytes
.../daffodil/codegen/c/data/simple-short.dat | Bin 0 -> 2 bytes
.../codegen/c/data/simple-unsignedByte.dat | Bin 0 -> 1 bytes
.../daffodil/codegen/c/data/simple-unsignedInt.dat | Bin 0 -> 4 bytes
.../codegen/c/data/simple-unsignedLong.dat | Bin 0 -> 8 bytes
.../codegen/c/data/simple-unsignedShort.dat | Bin 0 -> 2 bytes
.../codegen/c/infosets/simple-boolean.dat.xml | 19 ++
.../codegen/c/infosets/simple-byte.dat.xml | 19 ++
.../codegen/c/infosets/simple-double.dat.xml | 19 ++
.../codegen/c/infosets/simple-float.dat.xml | 19 ++
.../codegen/c/infosets/simple-hexBinary.dat.xml | 19 ++
.../c/infosets/simple-hexBinaryPrefixed.dat.xml | 19 ++
.../daffodil/codegen/c/infosets/simple-int.dat.xml | 19 ++
.../codegen/c/infosets/simple-integer.dat.xml | 19 ++
.../codegen/c/infosets/simple-long.dat.xml | 19 ++
.../c/infosets/simple-nonNegativeInteger.dat.xml | 19 ++
.../codegen/c/infosets/simple-short.dat.xml | 19 ++
.../codegen/c/infosets/simple-unsignedByte.dat.xml | 19 ++
.../codegen/c/infosets/simple-unsignedInt.dat.xml | 19 ++
.../codegen/c/infosets/simple-unsignedLong.dat.xml | 19 ++
.../c/infosets/simple-unsignedShort.dat.xml | 19 ++
.../org/apache/daffodil/codegen/c/simple.dfdl.xsd | 65 ++++
.../org/apache/daffodil/codegen/c/simple.tdml | 330 +++++++++++++++++++++
.../apache/daffodil/codegen/c/simple_errors.tdml | 158 ++++++++++
.../org/apache/daffodil/codegen/c/TestSimple.scala | 53 ++++
.../daffodil/codegen/c/TestSimpleErrors.scala | 46 +++
62 files changed, 1639 insertions(+), 455 deletions(-)
diff --git a/daffodil-cli/src/main/scala/org/apache/daffodil/cli/Main.scala b/daffodil-cli/src/main/scala/org/apache/daffodil/cli/Main.scala
index 26141b797..68dbf5542 100644
--- a/daffodil-cli/src/main/scala/org/apache/daffodil/cli/Main.scala
+++ b/daffodil-cli/src/main/scala/org/apache/daffodil/cli/Main.scala
@@ -1618,7 +1618,7 @@ class Main(
fail += 1
if (testOpts.info() > 0) {
STDOUT.println(" Failure Information:")
- STDOUT.println(indent(e.getMessage(), 4))
+ STDOUT.println(indent(e.toString, 4))
}
if (testOpts.info() > 1) {
STDOUT.println(" Backtrace:")
diff --git a/daffodil-cli/src/test/resources/org/apache/daffodil/cli/testNonCompatibleImplementation.tdml b/daffodil-cli/src/test/resources/org/apache/daffodil/cli/testNonCompatibleImplementation.tdml
index adb663afd..26b3c1a08 100644
--- a/daffodil-cli/src/test/resources/org/apache/daffodil/cli/testNonCompatibleImplementation.tdml
+++ b/daffodil-cli/src/test/resources/org/apache/daffodil/cli/testNonCompatibleImplementation.tdml
@@ -26,27 +26,16 @@
<tdml:defineSchema name="s1">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
- <dfdl:format ref="ex:GeneralFormat" />
- <xs:element name="e1" dfdl:lengthKind="explicit"
- dfdl:length="2" type="xs:int" />
+ <dfdl:format ref="ex:GeneralFormat" representation="binary"/>
+ <xs:element name="e1" type="xs:int"/>
</tdml:defineSchema>
- <tdml:defineSchema name="s2">
- <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
- <dfdl:format ref="ex:GeneralFormat" representation="binary" />
- <xs:element name="e1">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="e2" type="xs:int"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </tdml:defineSchema>
-
- <tdml:parserTestCase name="testNotCompatibleImplementation1" root="e1"
- model="s1" description="this test specifies ibm as implementation."
+ <tdml:parserTestCase name="testNotCompatibleImplementation1" model="s1"
+ root="e1" description="this test specifies ibm as implementation."
implementations="ibm">
- <tdml:document>42</tdml:document>
+ <tdml:document>
+ <tdml:documentPart type="byte">0000002a</tdml:documentPart>
+ </tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
<e1>42</e1>
@@ -54,17 +43,15 @@
</tdml:infoset>
</tdml:parserTestCase>
- <tdml:parserTestCase name="testDaffodilCImplementation1" root="e1"
- model="s2" description="this test specifies daffodilC as implementation."
+ <tdml:parserTestCase name="testDaffodilCImplementation1" model="s1"
+ root="e1" description="this test specifies daffodilC as implementation."
implementations="daffodilC">
<tdml:document>
<tdml:documentPart type="byte">0000002a</tdml:documentPart>
</tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
- <e1>
- <e2>42</e2>
- </e1>
+ <e1>42</e1>
</tdml:dfdlInfoset>
</tdml:infoset>
</tdml:parserTestCase>
diff --git a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLItdml.scala b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLItdml.scala
index 667589799..cb087f669 100644
--- a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLItdml.scala
+++ b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLItdml.scala
@@ -115,7 +115,7 @@ class TestCLItdml {
"daffodil-cli/src/test/resources/org/apache/daffodil/cli/testNonCompatibleImplementation.tdml",
)
- runCLI(args"test -iii $tdml testNotCompatibleImplementation1") { cli =>
+ runCLI(args"test $tdml testNotCompatibleImplementation1") { cli =>
cli.expect(
"[Skipped] testNotCompatibleImplementation1 (not compatible with implementation: daffodil)",
)
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/daffodil_main.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/daffodil_main.c
index bb0e8e010..bd9c66aa5 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/daffodil_main.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/daffodil_main.c
@@ -16,12 +16,13 @@
*/
// clang-format off
+#include <stdbool.h> // for bool, true
#include <stdio.h> // for NULL, FILE, perror, fclose, fopen, stdin, stdout
#include <string.h> // for strcmp
#include "cli_errors.h" // for CLI_DIAGNOSTICS, CLI_FILE_CLOSE, CLI_FILE_OPEN
-#include "daffodil_getopt.h" // for daffodil_cli, parse_daffodil_cli, daffodil_parse, daffodil_parse_cli, daffodil_unparse, daffodil_unparse_cli, DAFFODIL_PARSE, DAFFODIL_UNPARSE
+#include "daffodil_getopt.h" // for daffodil_cli, daffodil_parse, daffodil_parse_cli, parse_daffodil_cli, daffodil_unparse, daffodil_unparse_cli, DAFFODIL_PARSE, DAFFODIL_UNPARSE
#include "errors.h" // for continue_or_exit, print_diagnostics, Error, Diagnostics, Error::(anonymous)
-#include "infoset.h" // for walkInfoset, InfosetBase, PState, UState, flushUState, rootElement, ERD, VisitEventHandler
+#include "infoset.h" // for get_infoset, walk_infoset, PState, UState, parse_data, unparse_infoset, InfosetBase, VisitEventHandler
#include "xml_reader.h" // for xmlReaderMethods, XMLReader
#include "xml_writer.h" // for xmlWriterMethods, XMLWriter
// clang-format on
@@ -66,10 +67,9 @@ main(int argc, char *argv[])
const Error *error = parse_daffodil_cli(argc, argv);
continue_or_exit(error);
- // Get our infoset ready
- FILE * input = stdin;
- FILE * output = stdout;
- InfosetBase *root = rootElement();
+ // We will read from stdin and write to stdout unless overridden
+ FILE *input = stdin;
+ FILE *output = stdout;
// Perform our command
if (daffodil_cli.subcommand == DAFFODIL_PARSE)
@@ -79,14 +79,16 @@ main(int argc, char *argv[])
output = fopen_or_exit(output, daffodil_parse.outfile, "w");
// Parse the input file into our infoset
- PState pstate = {input, 0, NULL, NULL, 0, 0};
- root->erd->parseSelf(root, &pstate);
+ const bool CLEAR_INFOSET = true;
+ InfosetBase *infoset = get_infoset(CLEAR_INFOSET);
+ PState pstate = {input, 0, NULL, NULL, 0, 0};
+ parse_data(infoset, &pstate);
print_diagnostics(pstate.diagnostics);
continue_or_exit(pstate.error);
// Visit the infoset and print XML from it
XMLWriter xmlWriter = {xmlWriterMethods, output, {NULL, NULL, 0}};
- error = walkInfoset((VisitEventHandler *)&xmlWriter, root);
+ error = walk_infoset((VisitEventHandler *)&xmlWriter, infoset);
continue_or_exit(error);
// Any diagnostics will fail the parse if validate mode is on
@@ -105,14 +107,15 @@ main(int argc, char *argv[])
output = fopen_or_exit(output, daffodil_unparse.outfile, "w");
// Initialize our infoset's values from the XML data
- XMLReader xmlReader = {xmlReaderMethods, input, root, NULL, NULL};
- error = walkInfoset((VisitEventHandler *)&xmlReader, root);
+ const bool CLEAR_INFOSET = true;
+ InfosetBase *infoset = get_infoset(CLEAR_INFOSET);
+ XMLReader xmlReader = {xmlReaderMethods, input, NULL, NULL};
+ error = walk_infoset((VisitEventHandler *)&xmlReader, infoset);
continue_or_exit(error);
// Unparse our infoset to the output file
UState ustate = {output, 0, NULL, NULL, 0, 0};
- root->erd->unparseSelf(root, &ustate);
- flushUState(&ustate);
+ unparse_infoset(infoset, &ustate);
print_diagnostics(ustate.diagnostics);
continue_or_exit(ustate.error);
}
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_reader.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_reader.h
index cc15e01e7..c90f93d93 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_reader.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_reader.h
@@ -21,7 +21,7 @@
// clang-format off
#include <mxml.h> // for mxml_node_t
#include <stdio.h> // for FILE
-#include "infoset.h" // for VisitEventHandler, InfosetBase
+#include "infoset.h" // for VisitEventHandler
// clang-format on
// XMLReader - infoset visitor with methods to read XML
@@ -30,12 +30,11 @@ typedef struct XMLReader
{
const VisitEventHandler handler;
FILE * stream;
- InfosetBase * root;
mxml_node_t * xml;
mxml_node_t * node;
} XMLReader;
-// XMLReader methods to pass to walkInfoset method
+// XMLReader methods to pass to walk_infoset method
extern const VisitEventHandler xmlReaderMethods;
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_writer.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_writer.h
index ea9db3e7a..3fa5d5737 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_writer.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libcli/xml_writer.h
@@ -33,7 +33,7 @@ typedef struct XMLWriter
c_stack_t stack;
} XMLWriter;
-// XMLWriter methods to pass to walkInfoset method
+// XMLWriter methods to pass to walk_infoset method
extern const VisitEventHandler xmlWriterMethods;
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.c
index 55d8325a1..608b1b577 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.c
@@ -82,6 +82,7 @@ error_lookup(uint8_t code)
{ERR_CHOICE_KEY, "no match between choice dispatch key %" PRId64 " and any branch key\n", FIELD_D64},
{ERR_FIXED_VALUE, "value of element '%s' does not match value of its 'fixed' attribute\n", FIELD_S},
{ERR_HEXBINARY_ALLOC, "error allocating hexBinary memory -- %" PRId64 " bytes\n", FIELD_D64},
+ {ERR_LEFTOVER_DATA, "Left over data, at least %i bit(s) remaining after end of parse\n", FIELD_C},
{ERR_PARSE_BOOL, "error parsing binary value %" PRId64 " as either true or false\n", FIELD_D64},
{ERR_STREAM_EOF, "EOF in stream, stopping program\n", FIELD_ZZZ},
{ERR_STREAM_ERROR, "error in stream, stopping program\n", FIELD_ZZZ},
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.h
index 52315c888..6a22a2af9 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/errors.h
@@ -33,6 +33,7 @@ enum ErrorCode
ERR_CHOICE_KEY,
ERR_FIXED_VALUE,
ERR_HEXBINARY_ALLOC,
+ ERR_LEFTOVER_DATA,
ERR_PARSE_BOOL,
ERR_STREAM_EOF,
ERR_STREAM_ERROR,
@@ -117,8 +118,4 @@ extern cli_error_lookup_t *cli_error_lookup;
extern const char *daffodil_program_version;
-// UNUSED - suppress compiler warning about unused variable
-
-#define UNUSED(x) (void)(x)
-
#endif // ERRORS_H
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.c
index 88e3f28ac..0aa123592 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.c
@@ -17,18 +17,19 @@
// clang-format off
#include "infoset.h"
-#include <stdio.h> // for fwrite
-#include <string.h> // for memccpy
-#include "errors.h" // for Error, eof_or_error, LIMIT_NAME_LENGTH
+#include <string.h> // for memccpy
+#include "errors.h" // for Error, LIMIT_NAME_LENGTH
+#include "parsers.h" // for no_leftover_data
+#include "unparsers.h" // for flush_fragment_byte
// clang-format on
// Declare prototypes for easier compilation
-static const Error *walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode);
-static const Error *walkInfosetNodeChild(const VisitEventHandler *handler, const InfosetBase *infoNode,
- const ERD *childERD, const void *child);
-static const Error *walkArray(const VisitEventHandler *handler, const InfosetBase *infoNode,
- const ERD *arrayERD, const void *child);
+static const Error *walk_infoset_node(const VisitEventHandler *handler, const InfosetBase *infoNode,
+ const ERD *childERD, const void *child);
+static const Error *walk_array(const VisitEventHandler *handler, const InfosetBase *infoNode,
+ const ERD *arrayERD, const void *child);
+static const Error *walk_infoset_node_children(const VisitEventHandler *handler, const InfosetBase *infoNode);
// get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
// attribute/value from ERD to use on XML element
@@ -123,64 +124,56 @@ get_erd_ns(const ERD *erd)
return erd->namedQName.ns;
}
-// walkInfoset - walk each node of an infoset and call
-// VisitEventHandler methods
+// parse_data - parse an input stream into an infoset, check for
+// leftover data, and return any errors in pstate
-const Error *
-walkInfoset(const VisitEventHandler *handler, const InfosetBase *infoNode)
+void
+parse_data(InfosetBase *infoset, PState *pstate)
{
- const Error *error = handler->visitStartDocument(handler);
+ infoset->erd->parseSelf(infoset, pstate);
+ no_leftover_data(pstate);
+}
- if (!error)
- {
- error = walkInfosetNode(handler, infoNode);
- }
- if (!error)
- {
- error = handler->visitEndDocument(handler);
- }
+// unparse_infoset - unparse an infoset to an output stream, flush the
+// fragment byte if not done yet, and return any errors in ustate
- return error;
+void
+unparse_infoset(InfosetBase *infoset, UState *ustate)
+{
+ infoset->erd->unparseSelf(infoset, ustate);
+ const uint8_t fill_byte = '\0';
+ flush_fragment_byte(fill_byte, ustate);
}
-// walkInfosetNode - walk each child of an infoset node and call
-// VisitEventHandler methods
+// walk_infoset - walk an infoset and call VisitEventHandler methods
-static const Error *
-walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
+const Error *
+walk_infoset(const VisitEventHandler *handler, const InfosetBase *infoNode)
{
- const size_t numChildren = infoNode->erd->numChildren;
- const ERD *const *const childrenERDs = infoNode->erd->childrenERDs;
- const size_t * offsets = infoNode->erd->offsets;
-
- // Start visiting the node
- const Error *error = handler->visitStartComplex(handler, infoNode);
+ const Error *error = handler->visitStartDocument(handler);
- // Walk each child of the node
- for (size_t i = 0; i < numChildren && !error; i++)
+ if (!error)
{
- const ERD * childERD = childrenERDs[i];
- const size_t offset = offsets[i];
- const void * child = (const void *)((const char *)infoNode + offset);
+ const ERD * childERD = infoNode->erd;
+ const size_t childOffset = childERD->numChildren ? 0 : childERD->childrenOffsets[0];
+ const void * child = (const void *)((const char *)infoNode + childOffset);
- error = walkInfosetNodeChild(handler, infoNode, childERD, child);
+ error = walk_infoset_node(handler, infoNode, childERD, child);
}
-
- // End visiting the node
if (!error)
{
- error = handler->visitEndComplex(handler, infoNode);
+ error = handler->visitEndDocument(handler);
}
return error;
}
-// walkInfosetNodeChild - walk a child of an infoset node and call
-// VisitEventHandler methods
+// walk_infoset_node - walk an infoset node and call VisitEventHandler
+// methods
static const Error *
-walkInfosetNodeChild(const VisitEventHandler *handler, const InfosetBase *infoNode, const ERD *childERD,
- const void *child)
+walk_infoset_node(const VisitEventHandler *handler, const InfosetBase *infoNode, const ERD *childERD,
+ const void *child)
{
// Get the type of child to walk
const Error * error = NULL;
@@ -192,15 +185,15 @@ walkInfosetNodeChild(const VisitEventHandler *handler, const InfosetBase *infoNo
{
case ARRAY:
// Walk an array recursively
- error = walkArray(handler, infoNode, childERD, child);
+ error = walk_array(handler, infoNode, childERD, child);
break;
case CHOICE:
// Point next ERD to choice of alternative elements' ERDs
error = infoNode->erd->initChoice(infoNode);
break;
case COMPLEX:
- // Walk a child node recursively
- error = walkInfosetNode(handler, childNode);
+ // Walk a node's children recursively
+ error = walk_infoset_node_children(handler, childNode);
break;
case PRIMITIVE_BOOLEAN:
case PRIMITIVE_DOUBLE:
@@ -222,53 +215,60 @@ walkInfosetNodeChild(const VisitEventHandler *handler, const InfosetBase *infoNo
return error;
}
-// walkArray - walk each element of an array and call
+// walk_array - walk each element of an array and call
// VisitEventHandler methods
static const Error *
-walkArray(const VisitEventHandler *handler, const InfosetBase *infoNode, const ERD *arrayERD,
- const void *child)
+walk_array(const VisitEventHandler *handler, const InfosetBase *infoNode, const ERD *arrayERD,
+ const void *child)
{
// Get the array's size, type of its elements, and offset between its elements
const Error *error = NULL;
const size_t arraySize = arrayERD->getArraySize(infoNode);
const ERD * childERD = arrayERD->childrenERDs[0];
- const size_t offset = arrayERD->offsets[0];
+ const size_t childOffset = arrayERD->childrenOffsets[0];
// Walk each element of the array
for (size_t i = 0; i < arraySize && !error; i++)
{
// Walk an element of the array recursively
- error = walkInfosetNodeChild(handler, infoNode, childERD, child);
+ error = walk_infoset_node(handler, infoNode, childERD, child);
- // Increment child by offset in order to walk the next element
- child = (const char *)child + offset;
+ // Increment child by childOffset in order to walk the next element
+ child = (const char *)child + childOffset;
}
return error;
}
-// flushUState - flush any buffered bits not written yet
-
-#define BYTE_WIDTH 8
+// walk_infoset_node_children - walk each child of an infoset node and
+// call VisitEventHandler methods
-void
-flushUState(UState *ustate)
+static const Error *
+walk_infoset_node_children(const VisitEventHandler *handler, const InfosetBase *infoNode)
{
- // Do we have any bits within the fractional byte?
- if (ustate->unwritLen)
+ const size_t numChildren = infoNode->erd->numChildren;
+ const ERD *const *const childrenERDs = infoNode->erd->childrenERDs;
+ const size_t * childrenOffsets = infoNode->erd->childrenOffsets;
+
+ // Start visiting the node
+ const Error *error = handler->visitStartComplex(handler, infoNode);
+
+ // Walk each child of the node
+ for (size_t i = 0; i < numChildren && !error; i++)
{
- // Fill the fractional byte
- size_t num_bits_fill = BYTE_WIDTH - ustate->unwritLen;
- ustate->unwritBits <<= num_bits_fill;
- ustate->bitPos0b += num_bits_fill;
- ustate->unwritLen = 0; // Even though we don't flush until next line
-
- // Flush the fractional byte
- size_t count = fwrite(&ustate->unwritBits, 1, 1, ustate->stream);
- if (count < 1)
- {
- ustate->error = eof_or_error(ustate->stream);
- }
+ const ERD * childERD = childrenERDs[i];
+ const size_t childOffset = childrenOffsets[i];
+ const void * child = (const void *)((const char *)infoNode + childOffset);
+
+ error = walk_infoset_node(handler, infoNode, childERD, child);
+ }
+
+ // End visiting the node
+ if (!error)
+ {
+ error = handler->visitEndComplex(handler, infoNode);
}
+
+ return error;
}
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.h
index e8cb6d895..73374c339 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/infoset.h
@@ -85,7 +85,7 @@ typedef struct ERD
const NamedQName namedQName;
const enum TypeCode typeCode;
const size_t numChildren;
- const size_t * offsets;
+ const size_t * childrenOffsets;
const struct ERD *const *childrenERDs;
const ERDParseSelf parseSelf;
@@ -119,24 +119,24 @@ typedef struct InfosetBase
typedef struct PState
{
- FILE * stream; // stream to read data from (input)
- size_t bitPos0b; // 0-based position of last successful parse (1-bit granularity)
- Diagnostics *diagnostics; // any validation diagnostics
- const Error *error; // any error which stops parse
- uint8_t unreadBits; // any buffered bits not read yet
- uint8_t unreadLen; // number of buffered bits not read yet
+ FILE * stream; // stream to read data from (input)
+ size_t bitPos0b; // 0-based position of last successful parse (1-bit granularity)
+ Diagnostics *diagnostics; // any validation diagnostics
+ const Error *error; // any error which stops parse
+ uint8_t unreadBits; // any buffered bits not read yet
+ uint8_t numUnreadBits; // number of buffered bits not read yet
} PState;
// UState - mutable state while unparsing infoset
typedef struct UState
{
- FILE * stream; // stream to write data to (output)
- size_t bitPos0b; // 0-based position of last successful write (1-bit granularity)
- Diagnostics *diagnostics; // any validation diagnostics
- const Error *error; // any error which stops unparse
- uint8_t unwritBits; // any buffered bits not written yet
- uint8_t unwritLen; // number of buffered bits not written yet
+ FILE * stream; // stream to write data to (output)
+ size_t bitPos0b; // 0-based position of last successful write (1-bit granularity)
+ Diagnostics *diagnostics; // any validation diagnostics
+ const Error *error; // any error which stops unparse
+ uint8_t unwritBits; // any buffered bits not written yet
+ uint8_t numUnwritBits; // number of buffered bits not written yet
} UState;
// VisitEventHandler - methods to be called when walking an infoset
@@ -157,18 +157,29 @@ extern const char *get_erd_name(const ERD *erd);
extern const char *get_erd_xmlns(const ERD *erd);
extern const char *get_erd_ns(const ERD *erd);
-// rootElement - return an infoset's root element for parsing,
-// walking, or unparsing (implementation actually is generated in
-// generated_code.c, not defined in infoset.c)
+// get_infoset - get an infoset (optionally clearing it first) for
+// parsing/walking (note get_infoset actually is defined in
+// generated_code.c, not infoset.c)
-extern InfosetBase *rootElement(void);
+extern InfosetBase *get_infoset(bool clear_infoset);
-// walkInfoset - walk each node of an infoset and call VisitEventHandler methods
+// parse_data - parse an input stream into an infoset, check for
+// leftover data, and return any errors in pstate
-extern const Error *walkInfoset(const VisitEventHandler *handler, const InfosetBase *infoset);
+extern void parse_data(InfosetBase *infoset, PState *pstate);
-// flushUState - flush any buffered bits not written yet
+// unparse_infoset - unparse an infoset to an output stream, flush the
+// fragment byte if not done yet, and return any errors in ustate
-extern void flushUState(UState *ustate);
+extern void unparse_infoset(InfosetBase *infoset, UState *ustate);
+
+// walk_infoset - walk each node of an infoset and call
+// VisitEventHandler methods
+
+extern const Error *walk_infoset(const VisitEventHandler *handler, const InfosetBase *infoset);
+
+// UNUSED - suppress compiler warning about unused variable
+
+#define UNUSED(x) (void)(x)
#endif // INFOSET_H
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.c
index da231e4f1..f39739582 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.c
@@ -19,9 +19,9 @@
#include "parsers.h"
#include <assert.h> // for assert
#include <stdbool.h> // for bool, false, true
-#include <stdio.h> // for fread
+#include <stdio.h> // for fread, fgetc, EOF
#include <stdlib.h> // for free, malloc
-#include "errors.h" // for eof_or_error, Error, add_diagnostic, get_diagnostics, ERR_ARRAY_BOUNDS, ERR_FIXED_VALUE, ERR_HEXBINARY_ALLOC, ERR_PARSE_BOOL, Error::(anonymous), Diagnostics
+#include "errors.h" // for Error, eof_or_error, Error::(anonymous), ERR_LEFTOVER_DATA, add_diagnostic, get_diagnostics, ERR_ARRAY_BOUNDS, ERR_FIXED_VALUE, ERR_HEXBINARY_ALLOC, ERR_PARSE_BOOL, Diagnostics
#include "p_endian.h" // for be64toh, le64toh, be32toh, le32toh
// clang-format on
@@ -35,7 +35,7 @@
#define HIGH_BITS(byte, n) ((byte & HIGH_MASK(n)) >> (BYTE_WIDTH - n))
// Helper method to read bits using whole bytes while storing
-// remaining bits not yet read within a fractional byte; returns last
+// remaining bits not yet read within a fragment byte; returns last
// bits of last byte already shifted to left end
// Note callers must check pstate->error after calling read_bits and
@@ -46,7 +46,7 @@ read_bits(uint8_t *bytes, size_t num_bits, PState *pstate)
{
// Copy as many bytes directly from stream as possible
size_t ix_bytes = 0;
- if (!pstate->unreadLen)
+ if (!pstate->numUnreadBits)
{
size_t num_bytes = num_bits / BYTE_WIDTH;
if (num_bytes)
@@ -62,8 +62,8 @@ read_bits(uint8_t *bytes, size_t num_bits, PState *pstate)
}
}
- // Copy and fill the fractional byte as many times as needed
- while (num_bits > pstate->unreadLen)
+ // Copy and fill the fragment byte as many times as needed
+ while (num_bits > pstate->numUnreadBits)
{
// Copy one whole byte from stream to temporary storage
size_t whole_byte = 0;
@@ -74,42 +74,42 @@ read_bits(uint8_t *bytes, size_t num_bits, PState *pstate)
return;
}
- // Copy bits from whole byte to fill fractional byte
- size_t num_bits_fill = BYTE_WIDTH - pstate->unreadLen;
+ // Copy bits from whole byte to fill fragment byte
+ size_t num_bits_fill = BYTE_WIDTH - pstate->numUnreadBits;
pstate->unreadBits <<= num_bits_fill;
pstate->unreadBits |= HIGH_BITS(whole_byte, num_bits_fill);
- pstate->unreadLen += num_bits_fill;
+ pstate->numUnreadBits += num_bits_fill;
whole_byte <<= num_bits_fill;
- // Copy bits from fractional byte to `bytes`
+ // Copy bits from fragment byte to `bytes`
size_t num_bits_read = BYTE_WIDTH;
if (num_bits_read > num_bits) num_bits_read = num_bits;
num_bits -= num_bits_read;
bytes[ix_bytes++] = pstate->unreadBits & HIGH_MASK(num_bits_read);
- pstate->unreadLen -= num_bits_read;
+ pstate->numUnreadBits -= num_bits_read;
- // Copy rest of bits from whole byte to fractional byte
+ // Copy rest of bits from whole byte to fragment byte
size_t num_bits_unread = BYTE_WIDTH - num_bits_fill;
- assert(num_bits_unread + pstate->unreadLen < BYTE_WIDTH);
+ assert(num_bits_unread + pstate->numUnreadBits < BYTE_WIDTH);
if (num_bits_unread)
{
pstate->unreadBits <<= num_bits_unread;
pstate->unreadBits |= HIGH_BITS(whole_byte, num_bits_unread);
- pstate->unreadLen += num_bits_unread;
+ pstate->numUnreadBits += num_bits_unread;
}
}
- // Copy bits from fractional byte to `bytes` one last time,
- // keeping unread bits in right end (NOT shifted left)
- assert(num_bits <= pstate->unreadLen);
+ // Copy bits from fragment byte to `bytes` one last time, keeping
+ // unread bits in right end (NOT shifted left)
+ assert(num_bits <= pstate->numUnreadBits);
if (num_bits)
{
// Shift the unread bits to the left end so we can copy some
// of them starting from the first unread bit
- size_t shift = BYTE_WIDTH - pstate->unreadLen;
+ size_t shift = BYTE_WIDTH - pstate->numUnreadBits;
pstate->unreadBits <<= shift;
bytes[ix_bytes] = pstate->unreadBits & HIGH_MASK(num_bits);
- pstate->unreadLen -= num_bits;
+ pstate->numUnreadBits -= num_bits;
// Shift any remaining unread bits back to the right end since
// we append new unread bits from the right
@@ -195,7 +195,7 @@ parse_endian_float(bool big_endian_data, float *number, size_t num_bits, PState
pstate->bitPos0b += num_bits;
}
-// Helper method to read signed integers using fractional byte shifts
+// Helper method to read signed integers using fragment byte shifts
// depending on data endianness (note not tested on big-endian
// architecture; might work only on low-endian architecture)
@@ -256,8 +256,8 @@ parse_endian_int64(bool big_endian_data, int64_t *number, size_t num_bits, PStat
pstate->bitPos0b += num_bits;
}
-// Helper method to read unsigned integers using fractional byte
-// shifts depending on data endianness (note not tested on big-endian
+// Helper method to read unsigned integers using fragment byte shifts
+// depending on data endianness (note not tested on big-endian
// architecture; might work only on low-endian architecture)
static void
@@ -594,3 +594,34 @@ parse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t maxO
pstate->error = &error;
}
}
+
+// Check for any data left over after end of parse
+
+void
+no_leftover_data(PState *pstate)
+{
+ // Skip the check if we already have an error
+ if (!pstate->error)
+ {
+ // Check for any unread bits left in pstate's fragment byte
+ if (pstate->numUnreadBits)
+ {
+ // We have some unread bits remaining, so report leftover data
+ static Error error = {ERR_LEFTOVER_DATA, {0}};
+ error.arg.c = pstate->numUnreadBits;
+ pstate->error = &error;
+ }
+ else
+ {
+ // Check for any unread bytes left in input stream
+ int c = fgetc(pstate->stream);
+ if (c != EOF)
+ {
+ // We have some unread bytes remaining, so report leftover data
+ static Error error = {ERR_LEFTOVER_DATA, {0}};
+ error.arg.c = BYTE_WIDTH;
+ pstate->error = &error;
+ }
+ }
+ }
+}
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.h
index 38812c366..4428c07c9 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/parsers.h
@@ -76,6 +76,11 @@ extern void parse_validate_fixed(bool same, const char *element, PState *pstate)
// Check array count is within bounds
-extern void parse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t maxOccurs, PState *pstate);
+extern void parse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t maxOccurs,
+ PState *pstate);
+
+// Check for any data left over after end of parse
+
+extern void no_leftover_data(PState *pstate);
#endif // PARSERS_H
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.c
index 37e5ba4fa..9614b39fc 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.c
@@ -20,7 +20,7 @@
#include <assert.h> // for assert
#include <stdbool.h> // for bool
#include <stdio.h> // for fwrite
-#include "errors.h" // for eof_or_error, add_diagnostic, get_diagnostics, ERR_ARRAY_BOUNDS, ERR_FIXED_VALUE, Diagnostics, Error
+#include "errors.h" // for eof_or_error, Error, add_diagnostic, get_diagnostics, ERR_ARRAY_BOUNDS, ERR_FIXED_VALUE, Diagnostics, Error::(anonymous)
#include "p_endian.h" // for htobe64, htole64, htobe32, htole32
// clang-format on
@@ -34,8 +34,8 @@
#define HIGH_BITS(byte, n) ((byte & HIGH_MASK(n)) >> (BYTE_WIDTH - n))
// Helper method to write bits using whole bytes while storing
-// remaining bits not yet written within a fractional byte; expects
-// last bits of last byte to be already shifted to left end
+// remaining bits not yet written within a fragment byte; expects last
+// bits of last byte to be already shifted to left end
// Note callers must check ustate->error after calling write_bits and
// update ustate->bitPos0b themselves after successful unparses
@@ -45,7 +45,7 @@ write_bits(const uint8_t *bytes, size_t num_bits, UState *ustate)
{
// Copy as many bytes directly to stream as possible
size_t ix_bytes = 0;
- if (!ustate->unwritLen)
+ if (!ustate->numUnwritBits)
{
size_t num_bytes = num_bits / BYTE_WIDTH;
if (num_bytes)
@@ -61,19 +61,19 @@ write_bits(const uint8_t *bytes, size_t num_bits, UState *ustate)
}
}
- // Fill and copy the fractional byte as many times as needed
- while (num_bits + ustate->unwritLen >= BYTE_WIDTH)
+ // Fill and copy the fragment byte as many times as needed
+ while (num_bits + ustate->numUnwritBits >= BYTE_WIDTH)
{
- // Fill the fractional byte
+ // Fill the fragment byte
uint8_t whole_byte = bytes[ix_bytes++];
- size_t num_bits_fill = BYTE_WIDTH - ustate->unwritLen;
+ size_t num_bits_fill = BYTE_WIDTH - ustate->numUnwritBits;
ustate->unwritBits <<= num_bits_fill;
ustate->unwritBits |= HIGH_BITS(whole_byte, num_bits_fill);
- ustate->unwritLen += num_bits_fill;
+ ustate->numUnwritBits += num_bits_fill;
num_bits -= num_bits_fill;
whole_byte <<= num_bits_fill;
- // Copy the fractional byte to stream
+ // Copy the fragment byte to stream
size_t num_bits_write = BYTE_WIDTH;
size_t count = fwrite(&ustate->unwritBits, 1, 1, ustate->stream);
if (count < 1)
@@ -81,29 +81,29 @@ write_bits(const uint8_t *bytes, size_t num_bits, UState *ustate)
ustate->error = eof_or_error(ustate->stream);
return;
}
- ustate->unwritLen -= num_bits_write;
+ ustate->numUnwritBits -= num_bits_write;
// Copy any remaining unused bits from the whole byte to the
- // fractional byte
+ // fragment byte
size_t num_bits_unused = BYTE_WIDTH - num_bits_fill;
if (num_bits_unused > num_bits) num_bits_unused = num_bits;
if (num_bits_unused)
{
ustate->unwritBits <<= num_bits_unused;
ustate->unwritBits |= HIGH_BITS(whole_byte, num_bits_unused);
- ustate->unwritLen += num_bits_unused;
+ ustate->numUnwritBits += num_bits_unused;
num_bits -= num_bits_unused;
}
}
- // Fill the fractional byte one last time
+ // Fill the fragment byte one last time
if (num_bits)
{
- assert(num_bits + ustate->unwritLen < BYTE_WIDTH);
+ assert(num_bits + ustate->numUnwritBits < BYTE_WIDTH);
ustate->unwritBits <<= num_bits;
ustate->unwritBits |= HIGH_BITS(bytes[ix_bytes], num_bits);
- ustate->unwritLen += num_bits;
+ ustate->numUnwritBits += num_bits;
}
}
@@ -177,7 +177,7 @@ unparse_endian_float(bool big_endian_data, float number, size_t num_bits, UState
ustate->bitPos0b += num_bits;
}
-// Helper method to write signed integers using fractional byte shifts
+// Helper method to write signed integers using fragment byte shifts
// depending on data endianness (note not tested on big-endian
// architecture; might work only on low-endian architecture)
@@ -219,8 +219,8 @@ unparse_endian_int64(bool big_endian_data, int64_t number, size_t num_bits, USta
ustate->bitPos0b += num_bits;
}
-// Helper method to write unsigned integers using fractional byte
-// shifts depending on data endianness (note not tested on big-endian
+// Helper method to write unsigned integers using fragment byte shifts
+// depending on data endianness (note not tested on big-endian
// architecture; might work only on low-endian architecture)
// Also note that we probably could use this helper function to write
@@ -465,3 +465,33 @@ unparse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t ma
ustate->error = &error;
}
}
+
+// Flush the fragment byte if not done yet
+
+void
+flush_fragment_byte(const uint8_t fill_byte, UState *ustate)
+{
+ // Skip the flush if we already have an error
+ if (!ustate->error)
+ {
+ // Do we have any unwritten bits left in the fragment byte?
+ if (ustate->numUnwritBits)
+ {
+ // Fill the fragment byte
+ size_t num_bits_fill = BYTE_WIDTH - ustate->numUnwritBits;
+ ustate->unwritBits <<= num_bits_fill;
+ ustate->unwritBits |= HIGH_BITS(fill_byte, num_bits_fill);
+
+ // Flush the fragment byte
+ size_t num_bits_write = ustate->numUnwritBits;
+ size_t count = fwrite(&ustate->unwritBits, 1, 1, ustate->stream);
+ if (count < 1)
+ {
+ ustate->error = eof_or_error(ustate->stream);
+ num_bits_write = 0;
+ }
+ ustate->numUnwritBits -= num_bits_write;
+ ustate->bitPos0b += num_bits_write;
+ }
+ }
+}
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.h b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.h
index 6eee51f23..af5b9c8ea 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.h
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/libruntime/unparsers.h
@@ -72,6 +72,11 @@ extern void unparse_validate_fixed(bool same, const char *element, UState *ustat
// Check array count is within bounds
-extern void unparse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t maxOccurs, UState *ustate);
+extern void unparse_check_bounds(const char *name, size_t count, size_t minOccurs, size_t maxOccurs,
+ UState *ustate);
+
+// Flush the fragment byte if not done yet
+
+extern void flush_fragment_byte(const uint8_t fill_byte, UState *ustate);
#endif // UNPARSERS_H
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/bits.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/bits.c
index 6fb1bb47e..6bdde9928 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/bits.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/bits.c
@@ -23,9 +23,9 @@
#include <stdint.h> // for uint32_t, int16_t, int32_t, int64_t, int8_t, uint16_t, uint64_t, uint8_t
#include <stdio.h> // for fclose, NULL, fflush, fmemopen, open_memstream, FILE, size_t
#include <stdlib.h> // for free
-#include "infoset.h" // for UState, PState, flushUState
+#include "infoset.h" // for UState, PState
#include "parsers.h" // for parse_be_bool, parse_le_bool, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
-#include "unparsers.h" // for unparse_be_bool, unparse_le_bool, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
+#include "unparsers.h" // for unparse_be_bool, unparse_le_bool, flush_fragment_byte, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
// clang-format on
Test(bits, be_bool_24)
@@ -44,7 +44,7 @@ Test(bits, be_bool_24)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 24), "ustate should advance 24 bits");
cr_expect(eq(u8, ustate.unwritBits, 0), "ustate should hold nothing");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 3), "stream should hold 3 bytes");
cr_expect(eq(u8, buffer[0], 0372), "stream should hold 0b_11_111_010");
cr_expect(eq(u8, buffer[1], 0306), "stream should hold 0b_11_000_110");
@@ -62,7 +62,7 @@ Test(bits, be_bool_24)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 24), "pstate should advance 24 bits");
cr_expect(eq(u8, pstate.unreadBits, 0), "pstate should hold nothing");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -85,14 +85,14 @@ Test(bits, be_bool_4)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 4), "ustate should advance 4 bits");
cr_expect(eq(u8, ustate.unwritBits, 012), "ustate should hold 0b_1_010");
- cr_expect(eq(u8, ustate.unwritLen, 4), "ustate should buffer 4 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 4), "ustate should buffer 4 bits");
cr_expect(eq(sz, size, 0), "stream should be empty");
unparse_be_bool(false, 4, true4_rep, false_rep, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 8), "ustate should advance 4 bits");
cr_expect(eq(u8, ustate.unwritBits, 0255), "ustate should hold 0b_10_101_101");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 1), "stream should have 1 byte");
cr_expect(eq(u8, buffer[0], 0255), "stream should hold 0b_10_101_101");
@@ -108,14 +108,14 @@ Test(bits, be_bool_4)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 4), "pstate should advance 4 bits");
cr_expect(eq(u8, pstate.unreadBits, 0255), "pstate should hold 0b_10_101_101");
- cr_expect(eq(u8, pstate.unreadLen, 4), "pstate should buffer 4 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 4), "pstate should buffer 4 bits");
number = false;
parse_be_bool(&number, 4, true4_rep, false_rep, &pstate);
cr_expect(eq(int, number, false), "boolean number should be false");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 8), "pstate should advance 4 bits");
cr_expect(eq(u8, pstate.unreadBits, 015), "pstate should hold 0b_1_101");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -138,24 +138,25 @@ Test(bits, be_bool_7_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 7), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0146), "ustate should hold 0b_01_100_110");
- cr_expect(eq(u8, ustate.unwritLen, 7), "ustate should buffer 7 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 7), "ustate should buffer 7 bits");
cr_expect(eq(sz, size, 0), "stream should be empty");
unparse_be_bool(false, 7, true7_rep, false_rep, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 14), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0157), "ustate should hold 0b_01_101_111");
- cr_expect(eq(u8, ustate.unwritLen, 6), "ustate should buffer 6 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 6), "ustate should buffer 6 bits");
cr_expect(eq(sz, size, 1), "stream should have 1 byte");
cr_expect(eq(u8, buffer[0], 0315), "stream should hold 0b_11_001_101");
// Verify that flushing ustate writes 10111100
- flushUState(&ustate);
+ const uint8_t fill_byte = '\0';
+ flush_fragment_byte(fill_byte, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
- cr_expect(eq(sz, ustate.bitPos0b, 16), "ustate should advance 2 bits");
+ cr_expect(eq(sz, ustate.bitPos0b, 20), "ustate should advance 6 bits");
cr_expect(eq(u8, ustate.unwritBits, 0274), "ustate should hold 0b_10_111_100");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 2), "stream should have 2 bytes");
cr_expect(eq(u8, buffer[1], 0274), "stream should hold 0b_10_111_100");
@@ -171,14 +172,14 @@ Test(bits, be_bool_7_7)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 7), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0315), "pstate should hold 0b_11_001_101");
- cr_expect(eq(u8, pstate.unreadLen, 1), "pstate should buffer 1 bit");
+ cr_expect(eq(u8, pstate.numUnreadBits, 1), "pstate should buffer 1 bit");
number = false;
parse_be_bool(&number, 7, true7_rep, false_rep, &pstate);
cr_expect(eq(int, number, false), "boolean number should be false");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 14), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0274), "pstate should hold 0b_10_111_100");
- cr_expect(eq(u8, pstate.unreadLen, 2), "pstate should buffer 2 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 2), "pstate should buffer 2 bits");
// Close stream and free dynamic buffer
fclose(stream);
@@ -202,7 +203,7 @@ Test(bits, be_bool_9_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 9), "ustate should advance 9 bits");
cr_expect(eq(u8, ustate.unwritBits, 01), "ustate should hold 0b_00_000_001");
- cr_expect(eq(u8, ustate.unwritLen, 1), "ustate should buffer 1 bit");
+ cr_expect(eq(u8, ustate.numUnwritBits, 1), "ustate should buffer 1 bit");
cr_expect(eq(sz, size, 1), "stream should hold 1 byte");
cr_expect(eq(u8, buffer[0], 0363), "stream should hold 0b_11_110_011");
unparse_be_bool(true, 7, true7_rep, false_rep, &ustate);
@@ -210,7 +211,7 @@ Test(bits, be_bool_9_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 16), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0367), "ustate should hold 0b_11_110_111");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 2), "stream should hold 2 bytes");
cr_expect(eq(u8, buffer[1], 0367), "stream should hold 0b_11_110_111");
@@ -226,14 +227,14 @@ Test(bits, be_bool_9_7)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 9), "pstate should advance 9 bits");
cr_expect(eq(u8, pstate.unreadBits, 0367), "pstate should hold 0b_11_110_111");
- cr_expect(eq(u8, pstate.unreadLen, 7), "pstate should buffer 7 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 7), "pstate should buffer 7 bits");
number = false;
parse_be_bool(&number, 7, true7_rep, false_rep, &pstate);
cr_expect(eq(int, number, true), "boolean number should be true");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 16), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0167), "pstate should hold 0b_01_110_111");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -271,7 +272,7 @@ Test(bits, be_signed_integers)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 176), "ustate should advance 176 bits");
cr_expect(eq(sz, size, 22), "stream should have 22 bytes");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
// Reopen stream for reading from same dynamic buffer
fclose(stream);
@@ -297,7 +298,7 @@ Test(bits, be_signed_integers)
parse_be_int64(&tin63, 63, &pstate);
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 176), "pstate should advance 176 bits");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Verify that these 8 integers are the same integers originally written
cr_expect(eq(i8, int1, tin1), "numbers should be the same");
@@ -345,7 +346,7 @@ Test(bits, be_unsigned_integers)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 176), "ustate should advance 176 bits");
cr_expect(eq(sz, size, 22), "stream should have 22 bytes");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
// Reopen stream for reading from same dynamic buffer
fclose(stream);
@@ -371,7 +372,7 @@ Test(bits, be_unsigned_integers)
parse_be_uint64(&tniu63, 63, &pstate);
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 176), "pstate should advance 176 bits");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Verify that these 8 integers are the same integers originally written
cr_expect(eq(u8, uint1, tniu1), "numbers should be the same");
@@ -404,7 +405,7 @@ Test(bits, le_bool_24)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 24), "ustate should advance 24 bits");
cr_expect(eq(u8, ustate.unwritBits, 0), "ustate should hold nothing");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 3), "stream should hold 3 bytes");
cr_expect(eq(u8, buffer[0], 0210), "stream should hold 0b_10_001_000");
cr_expect(eq(u8, buffer[1], 0306), "stream should hold 0b_11_000_110");
@@ -422,7 +423,7 @@ Test(bits, le_bool_24)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 24), "pstate should advance 24 bits");
cr_expect(eq(u8, pstate.unreadBits, 0), "pstate should hold nothing");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -445,14 +446,14 @@ Test(bits, le_bool_4_4)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 4), "ustate should advance 4 bits");
cr_expect(eq(u8, ustate.unwritBits, 012), "ustate should hold 0b_1_010");
- cr_expect(eq(u8, ustate.unwritLen, 4), "ustate should buffer 4 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 4), "ustate should buffer 4 bits");
cr_expect(eq(sz, size, 0), "stream should be empty");
unparse_le_bool(false, 4, true4_rep, false_rep, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 8), "ustate should advance 4 bits");
cr_expect(eq(u8, ustate.unwritBits, 0255), "ustate should hold 0b_10_101_101");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 1), "stream should have 1 byte");
cr_expect(eq(u8, buffer[0], 0255), "stream should hold 0b_10_101_101");
@@ -468,14 +469,14 @@ Test(bits, le_bool_4_4)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 4), "pstate should advance 4 bits");
cr_expect(eq(u8, pstate.unreadBits, 0255), "pstate should hold 0b_10_101_101");
- cr_expect(eq(u8, pstate.unreadLen, 4), "pstate should buffer 4 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 4), "pstate should buffer 4 bits");
number = false;
parse_le_bool(&number, 4, true4_rep, false_rep, &pstate);
cr_expect(eq(int, number, false), "boolean number should be false");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 8), "pstate should advance 4 bits");
cr_expect(eq(u8, pstate.unreadBits, 015), "pstate should hold 0b_1_101");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -498,24 +499,25 @@ Test(bits, le_bool_7_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 7), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0146), "ustate should hold 0b_01_100_110");
- cr_expect(eq(u8, ustate.unwritLen, 7), "ustate should buffer 7 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 7), "ustate should buffer 7 bits");
cr_expect(eq(sz, size, 0), "stream should be empty");
unparse_le_bool(false, 7, true7_rep, false_rep, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 14), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0157), "ustate should hold 0b_01_101_111");
- cr_expect(eq(u8, ustate.unwritLen, 6), "ustate should buffer 6 bits");
+ cr_expect(eq(u8, ustate.numUnwritBits, 6), "ustate should buffer 6 bits");
cr_expect(eq(sz, size, 1), "stream should have 1 byte");
cr_expect(eq(u8, buffer[0], 0315), "stream should hold 0b_11_001_101");
// Verify that flushing ustate writes 10111100
- flushUState(&ustate);
+ const uint8_t fill_byte = '\0';
+ flush_fragment_byte(fill_byte, &ustate);
fflush(stream);
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
- cr_expect(eq(sz, ustate.bitPos0b, 16), "ustate should advance 2 bits");
+ cr_expect(eq(sz, ustate.bitPos0b, 20), "ustate should advance 6 bits");
cr_expect(eq(u8, ustate.unwritBits, 0274), "ustate should hold 0b_10_111_100");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 2), "stream should have 2 bytes");
cr_expect(eq(u8, buffer[1], 0274), "stream should hold 0b_10_111_100");
@@ -531,14 +533,14 @@ Test(bits, le_bool_7_7)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 7), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0315), "pstate should hold 0b_11_001_101");
- cr_expect(eq(u8, pstate.unreadLen, 1), "pstate should buffer 1 bit");
+ cr_expect(eq(u8, pstate.numUnreadBits, 1), "pstate should buffer 1 bit");
number = false;
parse_le_bool(&number, 7, true7_rep, false_rep, &pstate);
cr_expect(eq(int, number, false), "boolean number should be false");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 14), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0274), "pstate should hold 0b_10_111_100");
- cr_expect(eq(u8, pstate.unreadLen, 2), "pstate should buffer 2 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 2), "pstate should buffer 2 bits");
// Close stream and free dynamic buffer
fclose(stream);
@@ -562,7 +564,7 @@ Test(bits, le_bool_9_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 9), "ustate should advance 9 bits");
cr_expect(eq(u8, ustate.unwritBits, 01), "ustate should hold 0b_00_000_001");
- cr_expect(eq(u8, ustate.unwritLen, 1), "ustate should buffer 1 bit");
+ cr_expect(eq(u8, ustate.numUnwritBits, 1), "ustate should buffer 1 bit");
cr_expect(eq(sz, size, 1), "stream should hold 1 byte");
cr_expect(eq(u8, buffer[0], 0347), "stream should hold 0b_11_100_111");
unparse_le_bool(true, 7, true7_rep, false_rep, &ustate);
@@ -570,7 +572,7 @@ Test(bits, le_bool_9_7)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 16), "ustate should advance 7 bits");
cr_expect(eq(u8, ustate.unwritBits, 0367), "ustate should hold 0b_11_110_111");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
cr_expect(eq(sz, size, 2), "stream should hold 2 bytes");
cr_expect(eq(u8, buffer[1], 0367), "stream should hold 0b_11_110_111");
@@ -586,14 +588,14 @@ Test(bits, le_bool_9_7)
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 9), "pstate should advance 9 bits");
cr_expect(eq(u8, pstate.unreadBits, 0367), "pstate should hold 0b_11_110_111");
- cr_expect(eq(u8, pstate.unreadLen, 7), "pstate should buffer 7 bits");
+ cr_expect(eq(u8, pstate.numUnreadBits, 7), "pstate should buffer 7 bits");
number = false;
parse_le_bool(&number, 7, true7_rep, false_rep, &pstate);
cr_expect(eq(int, number, true), "boolean number should be true");
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 16), "pstate should advance 7 bits");
cr_expect(eq(u8, pstate.unreadBits, 0167), "pstate should hold 0b_01_110_111");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Close stream and free dynamic buffer
fclose(stream);
@@ -631,7 +633,7 @@ Test(bits, le_signed_integers)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 176), "ustate should advance 176 bits");
cr_expect(eq(sz, size, 22), "stream should have 22 bytes");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
// Reopen stream for reading from same dynamic buffer
fclose(stream);
@@ -657,7 +659,7 @@ Test(bits, le_signed_integers)
parse_le_int64(&tin63, 63, &pstate);
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 176), "pstate should advance 176 bits");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Verify that these 8 integers are the same integers originally written
cr_expect(eq(i8, int1, tin1), "numbers should be the same");
@@ -705,7 +707,7 @@ Test(bits, le_unsigned_integers)
cr_expect(eq(ptr, (void *)ustate.error, 0), "ustate should have no error");
cr_expect(eq(sz, ustate.bitPos0b, 176), "ustate should advance 176 bits");
cr_expect(eq(sz, size, 22), "stream should have 22 bytes");
- cr_expect(eq(u8, ustate.unwritLen, 0), "ustate should be empty");
+ cr_expect(eq(u8, ustate.numUnwritBits, 0), "ustate should be empty");
// Reopen stream for reading from same dynamic buffer
fclose(stream);
@@ -731,7 +733,7 @@ Test(bits, le_unsigned_integers)
parse_le_uint64(&tniu63, 63, &pstate);
cr_expect(eq(ptr, (void *)pstate.error, 0), "pstate should have no error");
cr_expect(eq(sz, pstate.bitPos0b, 176), "pstate should advance 176 bits");
- cr_expect(eq(u8, pstate.unreadLen, 0), "pstate should be empty");
+ cr_expect(eq(u8, pstate.numUnreadBits, 0), "pstate should be empty");
// Verify that these 8 integers are the same integers originally written
cr_expect(eq(u8, uint1, tniu1), "numbers should be the same");
diff --git a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/extras.c b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/extras.c
index 1fe997607..d7b69e689 100644
--- a/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/extras.c
+++ b/daffodil-codegen-c/src/main/resources/org/apache/daffodil/codegen/c/files/tests/extras.c
@@ -16,14 +16,16 @@
*/
// clang-format off
+#include <stdbool.h> // for bool
#include <stddef.h> // for NULL
-#include "infoset.h" // for InfosetBase, rootElement
+#include "infoset.h" // for InfosetBase, get_infoset
// clang-format on
-// Define `rootElement' to avoid an undefined reference when linking.
+// Define `get_infoset' to avoid an undefined reference when linking.
InfosetBase *
-rootElement(void)
+get_infoset(bool clear_infoset)
{
+ UNUSED(clear_infoset);
return NULL;
}
diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCExamplesGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCExamplesGenerator.scala
index 6b6d93550..9ba25ef72 100644
--- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCExamplesGenerator.scala
+++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCExamplesGenerator.scala
@@ -29,11 +29,11 @@ object DaffodilCExamplesGenerator {
// Update one example of generated C code from a sample schema
private def updateCExample(
schemaFile: os.Path,
- rootName: Option[String],
+ optRootName: Option[String],
exampleDir: os.Path,
): Unit = {
// Generate example code from the sample schema
- val pf = Compiler().compileFile(schemaFile.toIO, rootName)
+ val pf = Compiler().compileFile(schemaFile.toIO, optRootName)
assert(!pf.isError, pf.getDiagnostics.map(_.getMessage()).mkString("\n"))
val cg = pf.forLanguage("c")
val tempDir = os.temp.dir(dir = null, prefix = TDMLImplementation.DaffodilC.toString)
@@ -75,25 +75,22 @@ object DaffodilCExamplesGenerator {
val schemaDir =
rootDir / "daffodil-codegen-c" / "src" / "test" / "resources" / "org" / "apache" / "daffodil" / "codegen" / "c"
- val exNumsSchema = schemaDir / "ex_nums.dfdl.xsd"
- val exNumsRootName = None
- val nestedSchema = schemaDir / "nested.dfdl.xsd"
- val nestedRootName = Some("NestedUnion")
- val padTestSchema = schemaDir / "padtest.dfdl.xsd"
- val padTestRootName = None
- val variableLenSchema = schemaDir / "variablelen.dfdl.xsd"
- val variableLenRootName = Some("expressionElement")
-
val examplesDir = os.Path(args(0))
- val exNumsExampleDir = examplesDir / "ex_nums"
- val nestedExampleDir = examplesDir / "NestedUnion"
- val padTestExampleDir = examplesDir / "padtest"
- val variableLenExampleDir = examplesDir / "variablelen"
+ val examples = Array(
+ (schemaDir / "ex_nums.dfdl.xsd", None, examplesDir / "ex_nums"),
+ (schemaDir / "nested.dfdl.xsd", Some("NestedUnion"), examplesDir / "NestedUnion"),
+ (schemaDir / "padtest.dfdl.xsd", None, examplesDir / "padtest"),
+ (schemaDir / "simple.dfdl.xsd", Some("simple-byte"), examplesDir / "simple"),
+ (
+ schemaDir / "variablelen.dfdl.xsd",
+ Some("expressionElement"),
+ examplesDir / "variablelen",
+ ),
+ )
// Update each example of generated C code
- updateCExample(exNumsSchema, exNumsRootName, exNumsExampleDir)
- updateCExample(nestedSchema, nestedRootName, nestedExampleDir)
- updateCExample(padTestSchema, padTestRootName, padTestExampleDir)
- updateCExample(variableLenSchema, variableLenRootName, variableLenExampleDir)
+ examples.foreach { case (schemaFile, optRootName, exampleDir) =>
+ updateCExample(schemaFile, optRootName, exampleDir)
+ }
}
}
diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryBooleanCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryBooleanCodeGenerator.scala
index 177dde884..81222215d 100644
--- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryBooleanCodeGenerator.scala
+++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryBooleanCodeGenerator.scala
@@ -51,7 +51,7 @@ trait BinaryBooleanCodeGenerator extends BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val conv = if (e.byteOrderEv.constValue eq ByteOrder.BigEndian) "be" else "le"
val function = s"${conv}_$primType"
diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryValueCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryValueCodeGenerator.scala
index 7c23afad1..374e08e5d 100644
--- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryValueCodeGenerator.scala
+++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryValueCodeGenerator.scala
@@ -68,7 +68,7 @@ trait BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val conv = if (e.byteOrderEv.constValue eq ByteOrder.BigEndian) "be" else "le"
val function = s"${conv}_$primType"
@@ -92,7 +92,7 @@ trait BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val fixed = e.fixedValueAsString
diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/CodeGeneratorState.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/CodeGeneratorState.scala
index abdedc09f..107305a58 100644
--- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/CodeGeneratorState.scala
+++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/CodeGeneratorState.scala
@@ -17,6 +17,7 @@
package org.apache.daffodil.codegen.c.generators
+import scala.collection.immutable
import scala.collection.mutable
import org.apache.daffodil.core.dsom.Choice
@@ -40,8 +41,8 @@ class CodeGeneratorState(private val root: ElementBase) {
private val finalStructs = mutable.ArrayBuffer[String]()
private val finalImplementation = mutable.ArrayBuffer[String]()
- // Create the topmost "main_struct" struct immediately
- structs.push(new ComplexCGState("main_struct"))
+ // Push a dummy topmost state to simplify code
+ structs.push(new ComplexCGState(cStructName(root), root))
// Returns true if the generator is currently processing an array
def hasArray: Boolean = structs.nonEmpty && structs.top.inArray
@@ -62,8 +63,8 @@ class CodeGeneratorState(private val root: ElementBase) {
structs.top.unparserStatements += s" case $position:"
}
- if (context.isComplexType) {
- // Initialize complex element
+ if (context.isComplexType || context == root) {
+ // Initialize complex element or distinguished root element which we treat like a complex element
val C = cStructName(context)
structs.push(new ComplexCGState(C, context))
val erd = erdName(context)
@@ -72,7 +73,9 @@ class CodeGeneratorState(private val root: ElementBase) {
| instance->_base.parent = parent;""".stripMargin
// Calculate padding if complex element has an explicit length
- if (context.maybeFixedLengthInBits.isDefined && context.maybeFixedLengthInBits.get > 0) {
+ if (
+ context.isComplexType && context.maybeFixedLengthInBits.isDefined && context.maybeFixedLengthInBits.get > 0
+ ) {
val lengthInBits = context.maybeFixedLengthInBits.get
structs.top.parserStatements += s" const size_t end_bitPos0b = pstate->bitPos0b + $lengthInBits;"
structs.top.unparserStatements += s" const size_t end_bitPos0b = ustate->bitPos0b + $lengthInBits;"
@@ -107,7 +110,7 @@ class CodeGeneratorState(private val root: ElementBase) {
val indent1 = if (hasChoice) INDENT else NO_INDENT
val indent2 = if (hasArray) INDENT else NO_INDENT
val C = cStructName(context)
- val e = context.namedQName.local
+ val e = cName(context)
val deref = if (hasArray) "[i]" else ""
if (hasChoice)
structs.top.initChoiceStatements += s"$indent2 ${C}_initERD(&instance->$e$deref, (InfosetBase *)instance);"
@@ -119,6 +122,14 @@ class CodeGeneratorState(private val root: ElementBase) {
structs.top.unparserStatements +=
s"""$indent1$indent2 ${C}_unparseSelf(&instance->$e$deref, ustate);
|$indent1$indent2 if (ustate->error) return;""".stripMargin
+ } else if (context == root) {
+ // Treat a simple type root element as a hybrid of simple and complex types
+ addFieldDeclaration(context) // struct member for element
+ addComputations(context) // offset, ERD computations
+ addSimpleTypeERD(context) // ERD static initializer
+ addStruct(context) // struct definition
+ addImplementation(context)
+ structs.pop()
} else {
// Prevent redundant definitions on reused types
if (elementNotSeenYet(context, cStructName(context))) {
@@ -338,7 +349,7 @@ class CodeGeneratorState(private val root: ElementBase) {
|#include "generated_code.h"
|#include <stdbool.h> // for false, bool, true
|#include <stddef.h> // for NULL, size_t
- |#include <string.h> // for memcmp
+ |#include <string.h> // for memcmp, memset
|#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
|#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, par [...]
|#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unp [...]
@@ -354,19 +365,23 @@ class CodeGeneratorState(private val root: ElementBase) {
|// Initialize, parse, and unparse nodes of the infoset
|
|$finalImplementation
- |// Return a root element for parsing or unparsing the infoset
+ |// Get an infoset (optionally clearing it first) for parsing/walking
|
|InfosetBase *
- |rootElement(void)
+ |get_infoset(bool clear_infoset)
|{
- | static bool initialized;
- | static $rootName root;
- | if (!initialized)
+ | static $rootName infoset;
+ |
+ | if (clear_infoset)
| {
- | ${rootName}_initERD(&root, (InfosetBase *)&root);
- | initialized = true;
+ | // If your infoset contains hexBinary prefixed length elements,
+ | // you may want to walk infoset first to free their malloc'ed
+ | // storage - we are not handling that case for now...
+ | memset(&infoset, 0, sizeof(infoset));
+ | ${rootName}_initERD(&infoset, (InfosetBase *)&infoset);
| }
- | return &root._base;
+ |
+ | return &infoset._base;
|}
|""".stripMargin
code.replace("\r\n", "\n").replace("\n", System.lineSeparator)
@@ -375,13 +390,23 @@ class CodeGeneratorState(private val root: ElementBase) {
// Returns a name for the given element's C struct identifier
private def cStructName(context: ElementBase): String = {
val sb = buildName(context, new StringBuilder)
+ makeLegalForC(sb)
val name = sb.toString
name
}
- // Returns a name for the given element's element runtime data.
+ // Returns a name for the given element's element runtime data
private def erdName(context: ElementBase): String = {
val sb = buildName(context, new StringBuilder) ++= "ERD"
+ makeLegalForC(sb)
+ val name = sb.toString
+ name
+ }
+
+ // Returns a name for the given element's local name
+ def cName(context: ElementBase): String = {
+ val sb = new StringBuilder(context.namedQName.local)
+ makeLegalForC(sb)
val name = sb.toString
name
}
@@ -400,7 +425,7 @@ class CodeGeneratorState(private val root: ElementBase) {
if (numChildren > 0)
s"""static const $C ${C}_compute_offsets;
|
- |static const size_t ${C}_offsets[$count] = {
+ |static const size_t ${C}_childrenOffsets[$count] = {
|$offsetComputations
|};
|
@@ -412,11 +437,11 @@ class CodeGeneratorState(private val root: ElementBase) {
|$qNameInit
| COMPLEX, // typeCode
| $numChildren, // numChildren
- | ${C}_offsets, // offsets
- | ${C}_childrenERDs, // childrenERDs
- | (ERDParseSelf)&${C}_parseSelf, // parseSelf
- | (ERDUnparseSelf)&${C}_unparseSelf, // unparseSelf
- | {$initChoice} // initChoice
+ | ${C}_childrenOffsets,
+ | ${C}_childrenERDs,
+ | (ERDParseSelf)&${C}_parseSelf,
+ | (ERDUnparseSelf)&${C}_unparseSelf,
+ | {.initChoice = $initChoice}
|};
|""".stripMargin
else
@@ -424,11 +449,11 @@ class CodeGeneratorState(private val root: ElementBase) {
|$qNameInit
| COMPLEX, // typeCode
| $numChildren, // numChildren
- | NULL, // offsets
+ | NULL, // childrenOffsets
| NULL, // childrenERDs
- | (ERDParseSelf)&${C}_parseSelf, // parseSelf
- | (ERDUnparseSelf)&${C}_unparseSelf, // unparseSelf
- | {$initChoice} // initChoice
+ | (ERDParseSelf)&${C}_parseSelf,
+ | (ERDUnparseSelf)&${C}_unparseSelf,
+ | {.initChoice = $initChoice}
|};
|""".stripMargin
@@ -521,9 +546,12 @@ class CodeGeneratorState(private val root: ElementBase) {
!alreadySeen
}
- // Adds an ERD definition for a simple element
+ // Adds an ERD definition for a simple element or simple root element
private def addSimpleTypeERD(context: ElementBase): Unit = {
+ val C = cStructName(context)
val erd = erdName(context)
+ val count = structs.top.offsetComputations.length
+ val offsetComputations = structs.top.offsetComputations.mkString(",\n")
val qNameInit = defineQNameInit(context)
val typeCode = getPrimType(context) match {
case PrimType.Boolean => "PRIMITIVE_BOOLEAN"
@@ -540,13 +568,34 @@ class CodeGeneratorState(private val root: ElementBase) {
case PrimType.UnsignedByte => "PRIMITIVE_UINT8"
case p => context.SDE("PrimType %s is not supported.", p.toString)
}
+ // Treat a simple type root element as a hybrid of simple and complex types
val erdDef =
- s"""static const ERD $erd = {
- |$qNameInit
- | $typeCode, // typeCode
- | 0, NULL, NULL, NULL, NULL, {NULL}
- |};
- |""".stripMargin
+ if (context == root)
+ s"""|static const $C ${C}_compute_offsets;
+ |
+ |static const size_t ${C}_childrenOffsets[$count] = {
+ |$offsetComputations
+ |};
+ |
+ |static const ERD $erd = {
+ |$qNameInit
+ | $typeCode, // typeCode
+ | 0, // numChildren
+ | ${C}_childrenOffsets,
+ | NULL, // childrenERDs
+ | (ERDParseSelf)&${C}_parseSelf,
+ | (ERDUnparseSelf)&${C}_unparseSelf,
+ | {.initChoice = NULL}
+ |};
+ |""".stripMargin
+ else
+ s"""|static const ERD $erd = {
+ |$qNameInit
+ | $typeCode, // typeCode
+ | 0, NULL, NULL, NULL, NULL, {NULL}
+ |};
+ |""".stripMargin
+
erds += erdDef
}
@@ -571,7 +620,7 @@ class CodeGeneratorState(private val root: ElementBase) {
} else {
cStructName(child)
}
- val e = child.namedQName.local
+ val e = cName(child)
val arraySize = arrayMaxOccurs(child)
val arrayDef = if (arraySize > 0) s"[$arraySize]" else ""
val indent = if (hasChoice) INDENT else NO_INDENT
@@ -593,7 +642,7 @@ class CodeGeneratorState(private val root: ElementBase) {
// Adds an element's ERD & offset to its parent element's children ERD & offset computations.
private def addComputations(child: ElementBase): Unit = {
val C = structs.top.C
- val e = child.namedQName.local
+ val e = cName(child)
val hasArray = arrayMaxOccurs(child) > 0
val arrayName = s"array_${cStructName(child)}$C"
val erd = if (hasArray) s"${arrayName}ERD" else erdName(child)
@@ -605,21 +654,21 @@ class CodeGeneratorState(private val root: ElementBase) {
structs.top.erdComputations += erdComputation
}
- // Generates an array's ERD, offsets, childrenERDs, initERD, parseSelf, unparseSelf, getArraySize
+ // Generates an array's ERD, childrenOffsets, childrenERDs, initERD, parseSelf, unparseSelf, getArraySize
private def addArrayImplementation(elem: ElementBase): Unit = {
val C = structs.top.C
- val e = elem.namedQName.local
+ val e = cName(elem)
val arrayName = s"array_${cStructName(elem)}$C"
val erd = erdName(elem)
val maxOccurs = elem.maxOccurs
val minOccurs = elem.minOccurs
val qNameInit = defineQNameInit(elem)
- // Add the array's ERD, offsets, childrenERDs
+ // Add the array's ERD, childrenOffsets, childrenERDs
val arrayERD =
s"""static const $C ${arrayName}_compute_offsets;
|
- |static const size_t ${arrayName}_offsets[1] = {
+ |static const size_t ${arrayName}_childrenOffsets[1] = {
| (const char *)&${arrayName}_compute_offsets.$e[1] - (const char *)&${arrayName}_compute_offsets.$e[0]
|};
|
@@ -631,11 +680,11 @@ class CodeGeneratorState(private val root: ElementBase) {
|$qNameInit
| ARRAY, // typeCode
| $maxOccurs, // maxOccurs
- | ${arrayName}_offsets, // offsets
- | ${arrayName}_childrenERDs, // childrenERDs
- | (ERDParseSelf)&${arrayName}_parseSelf, // parseSelf
- | (ERDUnparseSelf)&${arrayName}_unparseSelf, // unparseSelf
- | {.getArraySize = (GetArraySize)&${arrayName}_getArraySize} // getArraySize
+ | ${arrayName}_childrenOffsets,
+ | ${arrayName}_childrenERDs,
+ | (ERDParseSelf)&${arrayName}_parseSelf,
+ | (ERDUnparseSelf)&${arrayName}_unparseSelf,
+ | {.getArraySize = (GetArraySize)&${arrayName}_getArraySize}
|};
|""".stripMargin
erds += arrayERD
@@ -727,22 +776,36 @@ class CodeGeneratorState(private val root: ElementBase) {
// Recursively builds a hopefully unique name using the given StringBuilder
private def buildName(sc: SchemaComponent, sb: StringBuilder): StringBuilder = {
+ // Append schema component's name
sc match {
case eb: ElementBase => sb ++= eb.namedQName.local += '_'
case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
case ct: GlobalComplexTypeDef => sb ++= ct.namedQName.local += '_'
case _ => // don't include other schema components in qualified name
}
+ // Recursively append parent schema components' names
sc.optLexicalParent.foreach {
buildName(_, sb)
}
sb
}
+ // Makes any XML identifier a legal C identifier
+ private def makeLegalForC(sb: StringBuilder): Unit = {
+ lazy val legalCharsForC: immutable.Set[Char] =
+ Set('_') ++ ('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')
+ // Ensure sb contains only legal characters for C identifiers
+ for (i <- sb.indices) {
+ if (!legalCharsForC.contains(sb.charAt(i))) {
+ sb.setCharAt(i, '_')
+ }
+ }
+ }
+
// Generates the name part of an ERD definition
private def defineQNameInit(context: ElementBase): String = {
val prefix = context.namedQName.prefix.map(p => s""""$p"""").getOrElse("NULL")
- val local = context.namedQName.local
+ val local = context.namedQName.local // we want XML name not C name
val nsUri = context.namedQName.namespace.toStringOrNullIfNoNS
// Optimize away ns declaration if possible, although this approach may not be entirely correct
val parentNsUri = context.enclosingElements.headOption
@@ -870,19 +933,19 @@ class CodeGeneratorState(private val root: ElementBase) {
// assumptions to make generating the field access easier:
// - the expression contains only a relative or absolute path, nothing else (e.g.,
// the expression doesn't call any functions or perform any computation)
- // - we can convert an absolute path to a rootElement()-> indirection
+ // - we can convert an absolute path to a get_infoset()-> indirection
// - we can convert a relative path beginning with up dirs to a parents-> indirection
// - we can convert a relative path without any up dirs to an instance-> indirection
// - we can convert slashes in the path to dots in a C struct field access notation
private def cStructFieldAccess(expr: String): String = {
// Strip any namespace prefixes from expr and the root element's local name since
// C code uses only struct fields' names.
- val rootName = root.namedQName.local
+ val rootName = cName(root)
val exprPath = expr.replaceAll("/[^/:]+:", "/").stripPrefix(s"/$rootName")
val fieldAccess = if (exprPath.startsWith("/")) {
- // Convert exprPath to a rootElement()-> indirection
+ // Convert exprPath to a get_infoset()-> indirection
val C = cStructName(root)
- s"""(($C *)rootElement())->${exprPath.stripPrefix("/")}"""
+ s"""(($C *)get_infoset(false))->${exprPath.stripPrefix("/")}"""
} else if (exprPath.startsWith("../")) {
// Split exprPath into the up dirs and after the up dirs
val afterUpDirs = exprPath.split("\\.\\./").mkString
diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/HexBinaryCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/HexBinaryCodeGenerator.scala
index b66624376..96d90897a 100644
--- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/HexBinaryCodeGenerator.scala
+++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/HexBinaryCodeGenerator.scala
@@ -49,7 +49,7 @@ trait HexBinaryCodeGenerator extends BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val intType = e.prefixedLengthElementDecl.optPrimType.get match {
case PrimType.Byte | PrimType.Short | PrimType.Int | PrimType.Long | PrimType.Integer =>
@@ -93,7 +93,7 @@ trait HexBinaryCodeGenerator extends BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val fieldArray = s"instance->_a_$localName$deref"
val specifiedLength = e.elementLengthInBitsEv.constValue.get
@@ -124,7 +124,7 @@ trait HexBinaryCodeGenerator extends BinaryValueCodeGenerator {
): Unit = {
val indent1 = if (cgState.hasChoice) INDENT else NO_INDENT
val indent2 = if (deref.nonEmpty) INDENT else NO_INDENT
- val localName = e.namedQName.local
+ val localName = cgState.cName(e)
val field = s"instance->$localName$deref"
val fixed = s"${localName}_fixed"
val array = e.fixedValueAsString.grouped(2).mkString("0x", ", 0x", "")
diff --git a/daffodil-codegen-c/src/test/examples/NestedUnion/generated_code.c b/daffodil-codegen-c/src/test/examples/NestedUnion/generated_code.c
index 094551efb..a8ecfe8d8 100644
--- a/daffodil-codegen-c/src/test/examples/NestedUnion/generated_code.c
+++ b/daffodil-codegen-c/src/test/examples/NestedUnion/generated_code.c
@@ -2,7 +2,7 @@
#include "generated_code.h"
#include <stdbool.h> // for false, bool, true
#include <stddef.h> // for NULL, size_t
-#include <string.h> // for memcmp
+#include <string.h> // for memcmp, memset
#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, parse_le_uint [...]
#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_in [...]
@@ -74,7 +74,7 @@ static const ERD c_FooType_ERD = {
static const foo_data_NestedUnionType_ foo_data_NestedUnionType__compute_offsets;
-static const size_t foo_data_NestedUnionType__offsets[3] = {
+static const size_t foo_data_NestedUnionType__childrenOffsets[3] = {
(const char *)&foo_data_NestedUnionType__compute_offsets.a - (const char *)&foo_data_NestedUnionType__compute_offsets,
(const char *)&foo_data_NestedUnionType__compute_offsets.b - (const char *)&foo_data_NestedUnionType__compute_offsets,
(const char *)&foo_data_NestedUnionType__compute_offsets.c - (const char *)&foo_data_NestedUnionType__compute_offsets
@@ -94,11 +94,11 @@ static const ERD foo_data_NestedUnionType_ERD = {
},
COMPLEX, // typeCode
3, // numChildren
- foo_data_NestedUnionType__offsets, // offsets
- foo_data_NestedUnionType__childrenERDs, // childrenERDs
- (ERDParseSelf)&foo_data_NestedUnionType__parseSelf, // parseSelf
- (ERDUnparseSelf)&foo_data_NestedUnionType__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ foo_data_NestedUnionType__childrenOffsets,
+ foo_data_NestedUnionType__childrenERDs,
+ (ERDParseSelf)&foo_data_NestedUnionType__parseSelf,
+ (ERDUnparseSelf)&foo_data_NestedUnionType__unparseSelf,
+ {.initChoice = NULL}
};
static const ERD x_BarType_ERD = {
@@ -133,7 +133,7 @@ static const ERD z_BarType_ERD = {
static const bar_data_NestedUnionType_ bar_data_NestedUnionType__compute_offsets;
-static const size_t bar_data_NestedUnionType__offsets[3] = {
+static const size_t bar_data_NestedUnionType__childrenOffsets[3] = {
(const char *)&bar_data_NestedUnionType__compute_offsets.x - (const char *)&bar_data_NestedUnionType__compute_offsets,
(const char *)&bar_data_NestedUnionType__compute_offsets.y - (const char *)&bar_data_NestedUnionType__compute_offsets,
(const char *)&bar_data_NestedUnionType__compute_offsets.z - (const char *)&bar_data_NestedUnionType__compute_offsets
@@ -153,16 +153,16 @@ static const ERD bar_data_NestedUnionType_ERD = {
},
COMPLEX, // typeCode
3, // numChildren
- bar_data_NestedUnionType__offsets, // offsets
- bar_data_NestedUnionType__childrenERDs, // childrenERDs
- (ERDParseSelf)&bar_data_NestedUnionType__parseSelf, // parseSelf
- (ERDUnparseSelf)&bar_data_NestedUnionType__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ bar_data_NestedUnionType__childrenOffsets,
+ bar_data_NestedUnionType__childrenERDs,
+ (ERDParseSelf)&bar_data_NestedUnionType__parseSelf,
+ (ERDUnparseSelf)&bar_data_NestedUnionType__unparseSelf,
+ {.initChoice = NULL}
};
static const data_NestedUnionType_ data_NestedUnionType__compute_offsets;
-static const size_t data_NestedUnionType__offsets[3] = {
+static const size_t data_NestedUnionType__childrenOffsets[3] = {
(const char *)&data_NestedUnionType__compute_offsets._choice - (const char *)&data_NestedUnionType__compute_offsets,
(const char *)&data_NestedUnionType__compute_offsets.foo - (const char *)&data_NestedUnionType__compute_offsets,
(const char *)&data_NestedUnionType__compute_offsets.bar - (const char *)&data_NestedUnionType__compute_offsets
@@ -182,16 +182,16 @@ static const ERD data_NestedUnionType_ERD = {
},
COMPLEX, // typeCode
2, // numChildren
- data_NestedUnionType__offsets, // offsets
- data_NestedUnionType__childrenERDs, // childrenERDs
- (ERDParseSelf)&data_NestedUnionType__parseSelf, // parseSelf
- (ERDUnparseSelf)&data_NestedUnionType__unparseSelf, // unparseSelf
- {(InitChoiceRD)&data_NestedUnionType__initChoice} // initChoice
+ data_NestedUnionType__childrenOffsets,
+ data_NestedUnionType__childrenERDs,
+ (ERDParseSelf)&data_NestedUnionType__parseSelf,
+ (ERDUnparseSelf)&data_NestedUnionType__unparseSelf,
+ {.initChoice = (InitChoiceRD)&data_NestedUnionType__initChoice}
};
static const NestedUnion_ NestedUnion__compute_offsets;
-static const size_t NestedUnion__offsets[2] = {
+static const size_t NestedUnion__childrenOffsets[2] = {
(const char *)&NestedUnion__compute_offsets.tag - (const char *)&NestedUnion__compute_offsets,
(const char *)&NestedUnion__compute_offsets.data - (const char *)&NestedUnion__compute_offsets
};
@@ -209,11 +209,11 @@ static const ERD NestedUnion_ERD = {
},
COMPLEX, // typeCode
2, // numChildren
- NestedUnion__offsets, // offsets
- NestedUnion__childrenERDs, // childrenERDs
- (ERDParseSelf)&NestedUnion__parseSelf, // parseSelf
- (ERDUnparseSelf)&NestedUnion__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ NestedUnion__childrenOffsets,
+ NestedUnion__childrenERDs,
+ (ERDParseSelf)&NestedUnion__parseSelf,
+ (ERDUnparseSelf)&NestedUnion__unparseSelf,
+ {.initChoice = NULL}
};
// Initialize, parse, and unparse nodes of the infoset
@@ -387,17 +387,21 @@ NestedUnion__unparseSelf(const NestedUnion_ *instance, UState *ustate)
if (ustate->error) return;
}
-// Return a root element for parsing or unparsing the infoset
+// Get an infoset (optionally clearing it first) for parsing/walking
InfosetBase *
-rootElement(void)
+get_infoset(bool clear_infoset)
{
- static bool initialized;
- static NestedUnion_ root;
- if (!initialized)
+ static NestedUnion_ infoset;
+
+ if (clear_infoset)
{
- NestedUnion__initERD(&root, (InfosetBase *)&root);
- initialized = true;
+ // If your infoset contains hexBinary prefixed length elements,
+ // you may want to walk infoset first to free their malloc'ed
+ // storage - we are not handling that case for now...
+ memset(&infoset, 0, sizeof(infoset));
+ NestedUnion__initERD(&infoset, (InfosetBase *)&infoset);
}
- return &root._base;
+
+ return &infoset._base;
}
diff --git a/daffodil-codegen-c/src/test/examples/ex_nums/generated_code.c b/daffodil-codegen-c/src/test/examples/ex_nums/generated_code.c
index 8e84102cd..29228f267 100644
--- a/daffodil-codegen-c/src/test/examples/ex_nums/generated_code.c
+++ b/daffodil-codegen-c/src/test/examples/ex_nums/generated_code.c
@@ -2,7 +2,7 @@
#include "generated_code.h"
#include <stdbool.h> // for false, bool, true
#include <stddef.h> // for NULL, size_t
-#include <string.h> // for memcmp
+#include <string.h> // for memcmp, memset
#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, parse_le_uint [...]
#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_in [...]
@@ -50,7 +50,7 @@ static const ERD be_boolean_array_ex_nums_ERD = {
static const array_ex_nums_ array_be_boolean_array_ex_nums_array_ex_nums__compute_offsets;
-static const size_t array_be_boolean_array_ex_nums_array_ex_nums__offsets[1] = {
+static const size_t array_be_boolean_array_ex_nums_array_ex_nums__childrenOffsets[1] = {
(const char *)&array_be_boolean_array_ex_nums_array_ex_nums__compute_offsets.be_boolean[1] - (const char *)&array_be_boolean_array_ex_nums_array_ex_nums__compute_offsets.be_boolean[0]
};
@@ -66,11 +66,11 @@ static const ERD array_be_boolean_array_ex_nums_array_ex_nums_ERD = {
},
ARRAY, // typeCode
2, // maxOccurs
- array_be_boolean_array_ex_nums_array_ex_nums__offsets, // offsets
- array_be_boolean_array_ex_nums_array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_be_boolean_array_ex_nums_array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_be_boolean_array_ex_nums_array_ex_nums__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_be_boolean_array_ex_nums_array_ex_nums__getArraySize} // getArraySize
+ array_be_boolean_array_ex_nums_array_ex_nums__childrenOffsets,
+ array_be_boolean_array_ex_nums_array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_be_boolean_array_ex_nums_array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_be_boolean_array_ex_nums_array_ex_nums__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_be_boolean_array_ex_nums_array_ex_nums__getArraySize}
};
static const ERD be_float_array_ex_nums_ERD = {
@@ -85,7 +85,7 @@ static const ERD be_float_array_ex_nums_ERD = {
static const array_ex_nums_ array_be_float_array_ex_nums_array_ex_nums__compute_offsets;
-static const size_t array_be_float_array_ex_nums_array_ex_nums__offsets[1] = {
+static const size_t array_be_float_array_ex_nums_array_ex_nums__childrenOffsets[1] = {
(const char *)&array_be_float_array_ex_nums_array_ex_nums__compute_offsets.be_float[1] - (const char *)&array_be_float_array_ex_nums_array_ex_nums__compute_offsets.be_float[0]
};
@@ -101,11 +101,11 @@ static const ERD array_be_float_array_ex_nums_array_ex_nums_ERD = {
},
ARRAY, // typeCode
3, // maxOccurs
- array_be_float_array_ex_nums_array_ex_nums__offsets, // offsets
- array_be_float_array_ex_nums_array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_be_float_array_ex_nums_array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_be_float_array_ex_nums_array_ex_nums__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_be_float_array_ex_nums_array_ex_nums__getArraySize} // getArraySize
+ array_be_float_array_ex_nums_array_ex_nums__childrenOffsets,
+ array_be_float_array_ex_nums_array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_be_float_array_ex_nums_array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_be_float_array_ex_nums_array_ex_nums__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_be_float_array_ex_nums_array_ex_nums__getArraySize}
};
static const ERD be_int16_array_ex_nums_ERD = {
@@ -120,7 +120,7 @@ static const ERD be_int16_array_ex_nums_ERD = {
static const array_ex_nums_ array_be_int16_array_ex_nums_array_ex_nums__compute_offsets;
-static const size_t array_be_int16_array_ex_nums_array_ex_nums__offsets[1] = {
+static const size_t array_be_int16_array_ex_nums_array_ex_nums__childrenOffsets[1] = {
(const char *)&array_be_int16_array_ex_nums_array_ex_nums__compute_offsets.be_int16[1] - (const char *)&array_be_int16_array_ex_nums_array_ex_nums__compute_offsets.be_int16[0]
};
@@ -136,11 +136,11 @@ static const ERD array_be_int16_array_ex_nums_array_ex_nums_ERD = {
},
ARRAY, // typeCode
3, // maxOccurs
- array_be_int16_array_ex_nums_array_ex_nums__offsets, // offsets
- array_be_int16_array_ex_nums_array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_be_int16_array_ex_nums_array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_be_int16_array_ex_nums_array_ex_nums__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_be_int16_array_ex_nums_array_ex_nums__getArraySize} // getArraySize
+ array_be_int16_array_ex_nums_array_ex_nums__childrenOffsets,
+ array_be_int16_array_ex_nums_array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_be_int16_array_ex_nums_array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_be_int16_array_ex_nums_array_ex_nums__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_be_int16_array_ex_nums_array_ex_nums__getArraySize}
};
static const ERD hexBinary2_array_ex_nums_ERD = {
@@ -155,7 +155,7 @@ static const ERD hexBinary2_array_ex_nums_ERD = {
static const array_ex_nums_ array_hexBinary2_array_ex_nums_array_ex_nums__compute_offsets;
-static const size_t array_hexBinary2_array_ex_nums_array_ex_nums__offsets[1] = {
+static const size_t array_hexBinary2_array_ex_nums_array_ex_nums__childrenOffsets[1] = {
(const char *)&array_hexBinary2_array_ex_nums_array_ex_nums__compute_offsets.hexBinary2[1] - (const char *)&array_hexBinary2_array_ex_nums_array_ex_nums__compute_offsets.hexBinary2[0]
};
@@ -171,11 +171,11 @@ static const ERD array_hexBinary2_array_ex_nums_array_ex_nums_ERD = {
},
ARRAY, // typeCode
3, // maxOccurs
- array_hexBinary2_array_ex_nums_array_ex_nums__offsets, // offsets
- array_hexBinary2_array_ex_nums_array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_hexBinary2_array_ex_nums_array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_hexBinary2_array_ex_nums_array_ex_nums__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_hexBinary2_array_ex_nums_array_ex_nums__getArraySize} // getArraySize
+ array_hexBinary2_array_ex_nums_array_ex_nums__childrenOffsets,
+ array_hexBinary2_array_ex_nums_array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_hexBinary2_array_ex_nums_array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_hexBinary2_array_ex_nums_array_ex_nums__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_hexBinary2_array_ex_nums_array_ex_nums__getArraySize}
};
static const ERD hexBinaryPrefixed_array_ex_nums_ERD = {
@@ -190,7 +190,7 @@ static const ERD hexBinaryPrefixed_array_ex_nums_ERD = {
static const array_ex_nums_ array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__compute_offsets;
-static const size_t array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__offsets[1] = {
+static const size_t array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__childrenOffsets[1] = {
(const char *)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__compute_offsets.hexBinaryPrefixed[1] - (const char *)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__compute_offsets.hexBinaryPrefixed[0]
};
@@ -206,16 +206,16 @@ static const ERD array_hexBinaryPrefixed_array_ex_nums_array_ex_nums_ERD = {
},
ARRAY, // typeCode
3, // maxOccurs
- array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__offsets, // offsets
- array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__getArraySize} // getArraySize
+ array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__childrenOffsets,
+ array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_hexBinaryPrefixed_array_ex_nums_array_ex_nums__getArraySize}
};
static const array_ex_nums_ array_ex_nums__compute_offsets;
-static const size_t array_ex_nums__offsets[5] = {
+static const size_t array_ex_nums__childrenOffsets[5] = {
(const char *)&array_ex_nums__compute_offsets.be_boolean[0] - (const char *)&array_ex_nums__compute_offsets,
(const char *)&array_ex_nums__compute_offsets.be_float[0] - (const char *)&array_ex_nums__compute_offsets,
(const char *)&array_ex_nums__compute_offsets.be_int16[0] - (const char *)&array_ex_nums__compute_offsets,
@@ -239,11 +239,11 @@ static const ERD array_ex_nums_ERD = {
},
COMPLEX, // typeCode
5, // numChildren
- array_ex_nums__offsets, // offsets
- array_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_ex_nums__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ array_ex_nums__childrenOffsets,
+ array_ex_nums__childrenERDs,
+ (ERDParseSelf)&array_ex_nums__parseSelf,
+ (ERDUnparseSelf)&array_ex_nums__unparseSelf,
+ {.initChoice = NULL}
};
static const ERD be_bool16_bigEndian_ex_nums_ERD = {
@@ -408,7 +408,7 @@ static const ERD hexBinaryPrefixed_bigEndian_ex_nums_ERD = {
static const bigEndian_ex_nums_ bigEndian_ex_nums__compute_offsets;
-static const size_t bigEndian_ex_nums__offsets[16] = {
+static const size_t bigEndian_ex_nums__childrenOffsets[16] = {
(const char *)&bigEndian_ex_nums__compute_offsets.be_bool16 - (const char *)&bigEndian_ex_nums__compute_offsets,
(const char *)&bigEndian_ex_nums__compute_offsets.be_boolean - (const char *)&bigEndian_ex_nums__compute_offsets,
(const char *)&bigEndian_ex_nums__compute_offsets.be_double - (const char *)&bigEndian_ex_nums__compute_offsets,
@@ -454,11 +454,11 @@ static const ERD bigEndian_ex_nums_ERD = {
},
COMPLEX, // typeCode
16, // numChildren
- bigEndian_ex_nums__offsets, // offsets
- bigEndian_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&bigEndian_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&bigEndian_ex_nums__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ bigEndian_ex_nums__childrenOffsets,
+ bigEndian_ex_nums__childrenERDs,
+ (ERDParseSelf)&bigEndian_ex_nums__parseSelf,
+ (ERDUnparseSelf)&bigEndian_ex_nums__unparseSelf,
+ {.initChoice = NULL}
};
static const ERD le_bool16_littleEndian_ex_nums_ERD = {
@@ -623,7 +623,7 @@ static const ERD hexBinaryPrefixed_littleEndian_ex_nums_ERD = {
static const littleEndian_ex_nums_ littleEndian_ex_nums__compute_offsets;
-static const size_t littleEndian_ex_nums__offsets[16] = {
+static const size_t littleEndian_ex_nums__childrenOffsets[16] = {
(const char *)&littleEndian_ex_nums__compute_offsets.le_bool16 - (const char *)&littleEndian_ex_nums__compute_offsets,
(const char *)&littleEndian_ex_nums__compute_offsets.le_boolean - (const char *)&littleEndian_ex_nums__compute_offsets,
(const char *)&littleEndian_ex_nums__compute_offsets.le_double - (const char *)&littleEndian_ex_nums__compute_offsets,
@@ -669,11 +669,11 @@ static const ERD littleEndian_ex_nums_ERD = {
},
COMPLEX, // typeCode
16, // numChildren
- littleEndian_ex_nums__offsets, // offsets
- littleEndian_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&littleEndian_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&littleEndian_ex_nums__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ littleEndian_ex_nums__childrenOffsets,
+ littleEndian_ex_nums__childrenERDs,
+ (ERDParseSelf)&littleEndian_ex_nums__parseSelf,
+ (ERDUnparseSelf)&littleEndian_ex_nums__unparseSelf,
+ {.initChoice = NULL}
};
static const ERD boolean_false_fixed_ex_nums_ERD = {
@@ -758,7 +758,7 @@ static const ERD hexBinaryPrefixed_ab_fixed_ex_nums_ERD = {
static const fixed_ex_nums_ fixed_ex_nums__compute_offsets;
-static const size_t fixed_ex_nums__offsets[8] = {
+static const size_t fixed_ex_nums__childrenOffsets[8] = {
(const char *)&fixed_ex_nums__compute_offsets.boolean_false - (const char *)&fixed_ex_nums__compute_offsets,
(const char *)&fixed_ex_nums__compute_offsets.boolean_true - (const char *)&fixed_ex_nums__compute_offsets,
(const char *)&fixed_ex_nums__compute_offsets.double_3 - (const char *)&fixed_ex_nums__compute_offsets,
@@ -788,16 +788,16 @@ static const ERD fixed_ex_nums_ERD = {
},
COMPLEX, // typeCode
8, // numChildren
- fixed_ex_nums__offsets, // offsets
- fixed_ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&fixed_ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&fixed_ex_nums__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ fixed_ex_nums__childrenOffsets,
+ fixed_ex_nums__childrenERDs,
+ (ERDParseSelf)&fixed_ex_nums__parseSelf,
+ (ERDUnparseSelf)&fixed_ex_nums__unparseSelf,
+ {.initChoice = NULL}
};
static const ex_nums_ ex_nums__compute_offsets;
-static const size_t ex_nums__offsets[4] = {
+static const size_t ex_nums__childrenOffsets[4] = {
(const char *)&ex_nums__compute_offsets.array - (const char *)&ex_nums__compute_offsets,
(const char *)&ex_nums__compute_offsets.bigEndian - (const char *)&ex_nums__compute_offsets,
(const char *)&ex_nums__compute_offsets.littleEndian - (const char *)&ex_nums__compute_offsets,
@@ -819,11 +819,11 @@ static const ERD ex_nums_ERD = {
},
COMPLEX, // typeCode
4, // numChildren
- ex_nums__offsets, // offsets
- ex_nums__childrenERDs, // childrenERDs
- (ERDParseSelf)&ex_nums__parseSelf, // parseSelf
- (ERDUnparseSelf)&ex_nums__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ ex_nums__childrenOffsets,
+ ex_nums__childrenERDs,
+ (ERDParseSelf)&ex_nums__parseSelf,
+ (ERDUnparseSelf)&ex_nums__unparseSelf,
+ {.initChoice = NULL}
};
// Initialize, parse, and unparse nodes of the infoset
@@ -1411,17 +1411,21 @@ ex_nums__unparseSelf(const ex_nums_ *instance, UState *ustate)
if (ustate->error) return;
}
-// Return a root element for parsing or unparsing the infoset
+// Get an infoset (optionally clearing it first) for parsing/walking
InfosetBase *
-rootElement(void)
+get_infoset(bool clear_infoset)
{
- static bool initialized;
- static ex_nums_ root;
- if (!initialized)
+ static ex_nums_ infoset;
+
+ if (clear_infoset)
{
- ex_nums__initERD(&root, (InfosetBase *)&root);
- initialized = true;
+ // If your infoset contains hexBinary prefixed length elements,
+ // you may want to walk infoset first to free their malloc'ed
+ // storage - we are not handling that case for now...
+ memset(&infoset, 0, sizeof(infoset));
+ ex_nums__initERD(&infoset, (InfosetBase *)&infoset);
}
- return &root._base;
+
+ return &infoset._base;
}
diff --git a/daffodil-codegen-c/src/test/examples/padtest/generated_code.c b/daffodil-codegen-c/src/test/examples/padtest/generated_code.c
index 62d41b30e..7f859e89f 100644
--- a/daffodil-codegen-c/src/test/examples/padtest/generated_code.c
+++ b/daffodil-codegen-c/src/test/examples/padtest/generated_code.c
@@ -2,7 +2,7 @@
#include "generated_code.h"
#include <stdbool.h> // for false, bool, true
#include <stddef.h> // for NULL, size_t
-#include <string.h> // for memcmp
+#include <string.h> // for memcmp, memset
#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, parse_le_uint [...]
#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_in [...]
@@ -29,7 +29,7 @@ static const ERD opaque_padhexbinary_ERD = {
static const padhexbinary_padtest_ padhexbinary_padtest__compute_offsets;
-static const size_t padhexbinary_padtest__offsets[1] = {
+static const size_t padhexbinary_padtest__childrenOffsets[1] = {
(const char *)&padhexbinary_padtest__compute_offsets.opaque - (const char *)&padhexbinary_padtest__compute_offsets
};
@@ -45,11 +45,11 @@ static const ERD padhexbinary_padtest_ERD = {
},
COMPLEX, // typeCode
1, // numChildren
- padhexbinary_padtest__offsets, // offsets
- padhexbinary_padtest__childrenERDs, // childrenERDs
- (ERDParseSelf)&padhexbinary_padtest__parseSelf, // parseSelf
- (ERDUnparseSelf)&padhexbinary_padtest__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ padhexbinary_padtest__childrenOffsets,
+ padhexbinary_padtest__childrenERDs,
+ (ERDParseSelf)&padhexbinary_padtest__parseSelf,
+ (ERDUnparseSelf)&padhexbinary_padtest__unparseSelf,
+ {.initChoice = NULL}
};
static const ERD after_padtest_ERD = {
@@ -64,7 +64,7 @@ static const ERD after_padtest_ERD = {
static const padtest_ padtest__compute_offsets;
-static const size_t padtest__offsets[2] = {
+static const size_t padtest__childrenOffsets[2] = {
(const char *)&padtest__compute_offsets.padhexbinary - (const char *)&padtest__compute_offsets,
(const char *)&padtest__compute_offsets.after - (const char *)&padtest__compute_offsets
};
@@ -82,11 +82,11 @@ static const ERD padtest_ERD = {
},
COMPLEX, // typeCode
2, // numChildren
- padtest__offsets, // offsets
- padtest__childrenERDs, // childrenERDs
- (ERDParseSelf)&padtest__parseSelf, // parseSelf
- (ERDUnparseSelf)&padtest__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ padtest__childrenOffsets,
+ padtest__childrenERDs,
+ (ERDParseSelf)&padtest__parseSelf,
+ (ERDUnparseSelf)&padtest__unparseSelf,
+ {.initChoice = NULL}
};
// Initialize, parse, and unparse nodes of the infoset
@@ -152,17 +152,21 @@ padtest__unparseSelf(const padtest_ *instance, UState *ustate)
if (ustate->error) return;
}
-// Return a root element for parsing or unparsing the infoset
+// Get an infoset (optionally clearing it first) for parsing/walking
InfosetBase *
-rootElement(void)
+get_infoset(bool clear_infoset)
{
- static bool initialized;
- static padtest_ root;
- if (!initialized)
+ static padtest_ infoset;
+
+ if (clear_infoset)
{
- padtest__initERD(&root, (InfosetBase *)&root);
- initialized = true;
+ // If your infoset contains hexBinary prefixed length elements,
+ // you may want to walk infoset first to free their malloc'ed
+ // storage - we are not handling that case for now...
+ memset(&infoset, 0, sizeof(infoset));
+ padtest__initERD(&infoset, (InfosetBase *)&infoset);
}
- return &root._base;
+
+ return &infoset._base;
}
diff --git a/daffodil-codegen-c/src/test/examples/simple/generated_code.c b/daffodil-codegen-c/src/test/examples/simple/generated_code.c
new file mode 100644
index 000000000..5bde5a4cb
--- /dev/null
+++ b/daffodil-codegen-c/src/test/examples/simple/generated_code.c
@@ -0,0 +1,79 @@
+// clang-format off
+#include "generated_code.h"
+#include <stdbool.h> // for false, bool, true
+#include <stddef.h> // for NULL, size_t
+#include <string.h> // for memcmp, memset
+#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
+#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, parse_le_uint [...]
+#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_in [...]
+// clang-format on
+
+// Declare prototypes for easier compilation
+
+static void simple_byte__parseSelf(simple_byte_ *instance, PState *pstate);
+static void simple_byte__unparseSelf(const simple_byte_ *instance, UState *ustate);
+
+// Define metadata for the infoset
+
+static const simple_byte_ simple_byte__compute_offsets;
+
+static const size_t simple_byte__childrenOffsets[1] = {
+ (const char *)&simple_byte__compute_offsets.simple_byte - (const char *)&simple_byte__compute_offsets
+};
+
+static const ERD simple_byte_ERD = {
+ {
+ "si", // namedQName.prefix
+ "simple-byte", // namedQName.local
+ "urn:simple", // namedQName.ns
+ },
+ PRIMITIVE_INT8, // typeCode
+ 0, // numChildren
+ simple_byte__childrenOffsets,
+ NULL, // childrenERDs
+ (ERDParseSelf)&simple_byte__parseSelf,
+ (ERDUnparseSelf)&simple_byte__unparseSelf,
+ {.initChoice = NULL}
+};
+
+// Initialize, parse, and unparse nodes of the infoset
+
+static void
+simple_byte__initERD(simple_byte_ *instance, InfosetBase *parent)
+{
+ instance->_base.erd = &simple_byte_ERD;
+ instance->_base.parent = parent;
+}
+
+static void
+simple_byte__parseSelf(simple_byte_ *instance, PState *pstate)
+{
+ parse_be_int8(&instance->simple_byte, 8, pstate);
+ if (pstate->error) return;
+}
+
+static void
+simple_byte__unparseSelf(const simple_byte_ *instance, UState *ustate)
+{
+ unparse_be_int8(instance->simple_byte, 8, ustate);
+ if (ustate->error) return;
+}
+
+// Get an infoset (optionally clearing it first) for parsing/walking
+
+InfosetBase *
+get_infoset(bool clear_infoset)
+{
+ static simple_byte_ infoset;
+
+ if (clear_infoset)
+ {
+ // If your infoset contains hexBinary prefixed length elements,
+ // you may want to walk infoset first to free their malloc'ed
+ // storage - we are not handling that case for now...
+ memset(&infoset, 0, sizeof(infoset));
+ simple_byte__initERD(&infoset, (InfosetBase *)&infoset);
+ }
+
+ return &infoset._base;
+}
diff --git a/daffodil-codegen-c/src/test/examples/simple/generated_code.h b/daffodil-codegen-c/src/test/examples/simple/generated_code.h
new file mode 100644
index 000000000..5f0ebb5c5
--- /dev/null
+++ b/daffodil-codegen-c/src/test/examples/simple/generated_code.h
@@ -0,0 +1,19 @@
+#ifndef GENERATED_CODE_H
+#define GENERATED_CODE_H
+
+// clang-format off
+#include <stdbool.h> // for bool
+#include <stddef.h> // for size_t
+#include <stdint.h> // for uint8_t, int16_t, int32_t, int64_t, uint32_t, int8_t, uint16_t, uint64_t
+#include "infoset.h" // for InfosetBase, HexBinary
+// clang-format on
+
+// Define infoset structures
+
+typedef struct simple_byte_
+{
+ InfosetBase _base;
+ int8_t simple_byte;
+} simple_byte_;
+
+#endif // GENERATED_CODE_H
diff --git a/daffodil-codegen-c/src/test/examples/variablelen/generated_code.c b/daffodil-codegen-c/src/test/examples/variablelen/generated_code.c
index 94a5273fb..2e87beb13 100644
--- a/daffodil-codegen-c/src/test/examples/variablelen/generated_code.c
+++ b/daffodil-codegen-c/src/test/examples/variablelen/generated_code.c
@@ -2,7 +2,7 @@
#include "generated_code.h"
#include <stdbool.h> // for false, bool, true
#include <stddef.h> // for NULL, size_t
-#include <string.h> // for memcmp
+#include <string.h> // for memcmp, memset
#include "errors.h" // for Error, PState, UState, ERR_CHOICE_KEY, Error::(anonymous), UNUSED
#include "parsers.h" // for alloc_hexBinary, parse_hexBinary, parse_be_float, parse_be_int16, parse_validate_fixed, parse_be_bool32, parse_be_bool16, parse_be_int32, parse_be_uint16, parse_be_uint32, parse_le_bool32, parse_le_int64, parse_le_uint16, parse_le_uint8, parse_be_bool8, parse_be_double, parse_be_int64, parse_be_int8, parse_be_uint64, parse_be_uint8, parse_le_bool16, parse_le_bool8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int8, parse_le_uint [...]
#include "unparsers.h" // for unparse_hexBinary, unparse_be_float, unparse_be_int16, unparse_validate_fixed, unparse_be_bool32, unparse_be_bool16, unparse_be_int32, unparse_be_uint16, unparse_be_uint32, unparse_le_bool32, unparse_le_int64, unparse_le_uint16, unparse_le_uint8, unparse_be_bool8, unparse_be_double, unparse_be_int64, unparse_be_int8, unparse_be_uint64, unparse_be_uint8, unparse_le_bool16, unparse_le_bool8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_in [...]
@@ -53,7 +53,7 @@ static const ERD variablelen_expressionType_ERD = {
static const expressionElement_ array_variablelen_expressionType_expressionElement__compute_offsets;
-static const size_t array_variablelen_expressionType_expressionElement__offsets[1] = {
+static const size_t array_variablelen_expressionType_expressionElement__childrenOffsets[1] = {
(const char *)&array_variablelen_expressionType_expressionElement__compute_offsets.variablelen[1] - (const char *)&array_variablelen_expressionType_expressionElement__compute_offsets.variablelen[0]
};
@@ -69,11 +69,11 @@ static const ERD array_variablelen_expressionType_expressionElement_ERD = {
},
ARRAY, // typeCode
16, // maxOccurs
- array_variablelen_expressionType_expressionElement__offsets, // offsets
- array_variablelen_expressionType_expressionElement__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_variablelen_expressionType_expressionElement__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_variablelen_expressionType_expressionElement__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_variablelen_expressionType_expressionElement__getArraySize} // getArraySize
+ array_variablelen_expressionType_expressionElement__childrenOffsets,
+ array_variablelen_expressionType_expressionElement__childrenERDs,
+ (ERDParseSelf)&array_variablelen_expressionType_expressionElement__parseSelf,
+ (ERDUnparseSelf)&array_variablelen_expressionType_expressionElement__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_variablelen_expressionType_expressionElement__getArraySize}
};
static const ERD after_expressionType_ERD = {
@@ -88,7 +88,7 @@ static const ERD after_expressionType_ERD = {
static const expressionElement_ array_after_expressionType_expressionElement__compute_offsets;
-static const size_t array_after_expressionType_expressionElement__offsets[1] = {
+static const size_t array_after_expressionType_expressionElement__childrenOffsets[1] = {
(const char *)&array_after_expressionType_expressionElement__compute_offsets.after[1] - (const char *)&array_after_expressionType_expressionElement__compute_offsets.after[0]
};
@@ -104,16 +104,16 @@ static const ERD array_after_expressionType_expressionElement_ERD = {
},
ARRAY, // typeCode
2, // maxOccurs
- array_after_expressionType_expressionElement__offsets, // offsets
- array_after_expressionType_expressionElement__childrenERDs, // childrenERDs
- (ERDParseSelf)&array_after_expressionType_expressionElement__parseSelf, // parseSelf
- (ERDUnparseSelf)&array_after_expressionType_expressionElement__unparseSelf, // unparseSelf
- {.getArraySize = (GetArraySize)&array_after_expressionType_expressionElement__getArraySize} // getArraySize
+ array_after_expressionType_expressionElement__childrenOffsets,
+ array_after_expressionType_expressionElement__childrenERDs,
+ (ERDParseSelf)&array_after_expressionType_expressionElement__parseSelf,
+ (ERDUnparseSelf)&array_after_expressionType_expressionElement__unparseSelf,
+ {.getArraySize = (GetArraySize)&array_after_expressionType_expressionElement__getArraySize}
};
static const expressionElement_ expressionElement__compute_offsets;
-static const size_t expressionElement__offsets[4] = {
+static const size_t expressionElement__childrenOffsets[4] = {
(const char *)&expressionElement__compute_offsets.before - (const char *)&expressionElement__compute_offsets,
(const char *)&expressionElement__compute_offsets.variablelen_size - (const char *)&expressionElement__compute_offsets,
(const char *)&expressionElement__compute_offsets.variablelen[0] - (const char *)&expressionElement__compute_offsets,
@@ -135,11 +135,11 @@ static const ERD expressionElement_ERD = {
},
COMPLEX, // typeCode
4, // numChildren
- expressionElement__offsets, // offsets
- expressionElement__childrenERDs, // childrenERDs
- (ERDParseSelf)&expressionElement__parseSelf, // parseSelf
- (ERDUnparseSelf)&expressionElement__unparseSelf, // unparseSelf
- {NULL} // initChoice
+ expressionElement__childrenOffsets,
+ expressionElement__childrenERDs,
+ (ERDParseSelf)&expressionElement__parseSelf,
+ (ERDUnparseSelf)&expressionElement__unparseSelf,
+ {.initChoice = NULL}
};
// Initialize, parse, and unparse nodes of the infoset
@@ -262,17 +262,21 @@ expressionElement__unparseSelf(const expressionElement_ *instance, UState *ustat
if (ustate->error) return;
}
-// Return a root element for parsing or unparsing the infoset
+// Get an infoset (optionally clearing it first) for parsing/walking
InfosetBase *
-rootElement(void)
+get_infoset(bool clear_infoset)
{
- static bool initialized;
- static expressionElement_ root;
- if (!initialized)
+ static expressionElement_ infoset;
+
+ if (clear_infoset)
{
- expressionElement__initERD(&root, (InfosetBase *)&root);
- initialized = true;
+ // If your infoset contains hexBinary prefixed length elements,
+ // you may want to walk infoset first to free their malloc'ed
+ // storage - we are not handling that case for now...
+ memset(&infoset, 0, sizeof(infoset));
+ expressionElement__initERD(&infoset, (InfosetBase *)&infoset);
}
- return &root._base;
+
+ return &infoset._base;
}
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-boolean.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-boolean.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-boolean.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-byte.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-byte.dat
new file mode 100644
index 000000000..f76dd238a
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-byte.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-double.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-double.dat
new file mode 100644
index 000000000..1b1cb4d44
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-double.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-float.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-float.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-float.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinary.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinary.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinary.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinaryPrefixed.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinaryPrefixed.dat
new file mode 100644
index 000000000..68782e0ef
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-hexBinaryPrefixed.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-int.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-int.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-int.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-integer.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-integer.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-integer.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-long.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-long.dat
new file mode 100644
index 000000000..1b1cb4d44
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-long.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-nonNegativeInteger.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-nonNegativeInteger.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-nonNegativeInteger.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-short.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-short.dat
new file mode 100644
index 000000000..09f370e38
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-short.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedByte.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedByte.dat
new file mode 100644
index 000000000..f76dd238a
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedByte.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedInt.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedInt.dat
new file mode 100644
index 000000000..593f4708d
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedInt.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedLong.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedLong.dat
new file mode 100644
index 000000000..1b1cb4d44
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedLong.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedShort.dat b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedShort.dat
new file mode 100644
index 000000000..09f370e38
Binary files /dev/null and b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/data/simple-unsignedShort.dat differ
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-boolean.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-boolean.dat.xml
new file mode 100644
index 000000000..38dab6790
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-boolean.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-boolean xmlns:si="urn:simple">false</si:simple-boolean>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-byte.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-byte.dat.xml
new file mode 100644
index 000000000..93d82871f
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-byte.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-byte xmlns:si="urn:simple">0</si:simple-byte>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-double.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-double.dat.xml
new file mode 100644
index 000000000..7955ed0a8
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-double.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-double xmlns:si="urn:simple">0.0</si:simple-double>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-float.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-float.dat.xml
new file mode 100644
index 000000000..c33e2b057
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-float.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-float xmlns:si="urn:simple">0.0</si:simple-float>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinary.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinary.dat.xml
new file mode 100644
index 000000000..1aade3608
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinary.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-hexBinary xmlns:si="urn:simple">00000000</si:simple-hexBinary>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinaryPrefixed.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinaryPrefixed.dat.xml
new file mode 100644
index 000000000..e38aff897
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-hexBinaryPrefixed.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-hexBinaryPrefixed xmlns:si="urn:simple">00000000</si:simple-hexBinaryPrefixed>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-int.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-int.dat.xml
new file mode 100644
index 000000000..4fd827083
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-int.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-int xmlns:si="urn:simple">0</si:simple-int>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-integer.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-integer.dat.xml
new file mode 100644
index 000000000..55dfc6be8
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-integer.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-integer xmlns:si="urn:simple">0</si:simple-integer>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-long.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-long.dat.xml
new file mode 100644
index 000000000..955de4ed5
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-long.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-long xmlns:si="urn:simple">0</si:simple-long>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-nonNegativeInteger.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-nonNegativeInteger.dat.xml
new file mode 100644
index 000000000..571189f65
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-nonNegativeInteger.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-nonNegativeInteger xmlns:si="urn:simple">0</si:simple-nonNegativeInteger>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-short.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-short.dat.xml
new file mode 100644
index 000000000..ebc3c4e01
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-short.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-short xmlns:si="urn:simple">0</si:simple-short>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedByte.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedByte.dat.xml
new file mode 100644
index 000000000..0188c9491
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedByte.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-unsignedByte xmlns:si="urn:simple">0</si:simple-unsignedByte>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedInt.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedInt.dat.xml
new file mode 100644
index 000000000..137308bfd
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedInt.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-unsignedInt xmlns:si="urn:simple">0</si:simple-unsignedInt>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedLong.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedLong.dat.xml
new file mode 100644
index 000000000..0430c75f1
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedLong.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-unsignedLong xmlns:si="urn:simple">0</si:simple-unsignedLong>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedShort.dat.xml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedShort.dat.xml
new file mode 100644
index 000000000..6bdc4688c
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/infosets/simple-unsignedShort.dat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<si:simple-unsignedShort xmlns:si="urn:simple">0</si:simple-unsignedShort>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.dfdl.xsd b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.dfdl.xsd
new file mode 100644
index 000000000..6c74fe040
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.dfdl.xsd
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<schema
+ targetNamespace="urn:simple"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:si="urn:simple"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.w3.org/2001/XMLSchema">
+
+ <!-- Binary representation properties -->
+
+ <include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <annotation>
+ <appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format
+ binaryBooleanFalseRep="0"
+ binaryBooleanTrueRep="1"
+ fillByte="%NUL;"
+ prefixIncludesPrefixLength="no"
+ ref="si:GeneralFormat"
+ representation="binary"/>
+ </appinfo>
+ </annotation>
+
+ <!-- Root elements (pick only one) -->
+
+ <element name="simple-boolean" type="xs:boolean"/>
+ <element name="simple-byte" type="xs:byte"/>
+ <element name="simple-double" type="xs:double"/>
+ <element name="simple-float" type="xs:float"/>
+ <element name="simple-hexBinary" type="xs:hexBinary" dfdl:length="4" dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes"/>
+ <element name="simple-hexBinaryPrefixed" type="xs:hexBinary" dfdl:lengthKind="prefixed" dfdl:lengthUnits="bytes" dfdl:prefixLengthType="si:prefixedCount"/>
+ <element name="simple-int" type="xs:int"/>
+ <element name="simple-integer" type="xs:integer" dfdl:length="4" dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes"/>
+ <element name="simple-long" type="xs:long"/>
+ <element name="simple-nonNegativeInteger" type="xs:nonNegativeInteger" dfdl:length="4" dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes"/>
+ <element name="simple-short" type="xs:short"/>
+ <element name="simple-unsignedByte" type="xs:unsignedByte"/>
+ <element name="simple-unsignedInt" type="xs:unsignedInt"/>
+ <element name="simple-unsignedLong" type="xs:unsignedLong"/>
+ <element name="simple-unsignedShort" type="xs:unsignedShort"/>
+
+ <!-- Simple data types -->
+
+ <simpleType name="prefixedCount">
+ <restriction base="xs:unsignedShort"/>
+ </simpleType>
+
+</schema>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.tdml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.tdml
new file mode 100644
index 000000000..3732a2621
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple.tdml
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<!--
+ Run all tests with each backend
+ daffodil test -i -I daffodil simple.tdml
+ daffodil test -i -I daffodilC simple.tdml
+
+ Or you can debug specific backends in isolation, see below
+-->
+<tdml:testSuite
+ defaultRoundTrip="onePass"
+ xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+ <!--
+ daffodil parse -r simple-boolean -s simple.dfdl.xsd -o c/simple-boolean.dat.xml data/simple-boolean.dat
+ daffodil unparse -r simple-boolean -s simple.dfdl.xsd -o c/simple-boolean.dat infosets/simple-boolean.dat.xml
+
+ daffodil generate c -r simple-boolean -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-boolean.dat.xml data/simple-boolean.dat
+ c/daffodil unparse -o c/simple-boolean.dat infosets/simple-boolean.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-boolean"
+ root="simple-boolean">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-boolean.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-boolean.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-byte -s simple.dfdl.xsd -o c/simple-byte.dat.xml data/simple-byte.dat
+ daffodil unparse -r simple-byte -s simple.dfdl.xsd -o c/simple-byte.dat infosets/simple-byte.dat.xml
+
+ daffodil generate c -r simple-byte -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-byte.dat.xml data/simple-byte.dat
+ c/daffodil unparse -o c/simple-byte.dat infosets/simple-byte.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-byte"
+ root="simple-byte">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-byte.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-byte.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-double -s simple.dfdl.xsd -o c/simple-double.dat.xml data/simple-double.dat
+ daffodil unparse -r simple-double -s simple.dfdl.xsd -o c/simple-double.dat infosets/simple-double.dat.xml
+
+ daffodil generate c -r simple-double -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-double.dat.xml data/simple-double.dat
+ c/daffodil unparse -o c/simple-double.dat infosets/simple-double.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-double"
+ root="simple-double">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-double.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-double.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-float -s simple.dfdl.xsd -o c/simple-float.dat.xml data/simple-float.dat
+ daffodil unparse -r simple-float -s simple.dfdl.xsd -o c/simple-float.dat infosets/simple-float.dat.xml
+
+ daffodil generate c -r simple-float -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-float.dat.xml data/simple-float.dat
+ c/daffodil unparse -o c/simple-float.dat infosets/simple-float.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-float"
+ root="simple-float">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-float.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-float.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-hexBinary -s simple.dfdl.xsd -o c/simple-hexBinary.dat.xml data/simple-hexBinary.dat
+ daffodil unparse -r simple-hexBinary -s simple.dfdl.xsd -o c/simple-hexBinary.dat infosets/simple-hexBinary.dat.xml
+
+ daffodil generate c -r simple-hexBinary -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-hexBinary.dat.xml data/simple-hexBinary.dat
+ c/daffodil unparse -o c/simple-hexBinary.dat infosets/simple-hexBinary.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-hexBinary"
+ root="simple-hexBinary">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-hexBinary.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-hexBinary.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-hexBinaryPrefixed -s simple.dfdl.xsd -o c/simple-hexBinaryPrefixed.dat.xml data/simple-hexBinaryPrefixed.dat
+ daffodil unparse -r simple-hexBinaryPrefixed -s simple.dfdl.xsd -o c/simple-hexBinaryPrefixed.dat infosets/simple-hexBinaryPrefixed.dat.xml
+
+ daffodil generate c -r simple-hexBinaryPrefixed -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-hexBinaryPrefixed.dat.xml data/simple-hexBinaryPrefixed.dat
+ c/daffodil unparse -o c/simple-hexBinaryPrefixed.dat infosets/simple-hexBinaryPrefixed.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-hexBinaryPrefixed"
+ root="simple-hexBinaryPrefixed">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-hexBinaryPrefixed.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-hexBinaryPrefixed.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-int -s simple.dfdl.xsd -o c/simple-int.dat.xml data/simple-int.dat
+ daffodil unparse -r simple-int -s simple.dfdl.xsd -o c/simple-int.dat infosets/simple-int.dat.xml
+
+ daffodil generate c -r simple-int -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-int.dat.xml data/simple-int.dat
+ c/daffodil unparse -o c/simple-int.dat infosets/simple-int.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-int"
+ root="simple-int">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-int.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-int.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-integer -s simple.dfdl.xsd -o c/simple-integer.dat.xml data/simple-integer.dat
+ daffodil unparse -r simple-integer -s simple.dfdl.xsd -o c/simple-integer.dat infosets/simple-integer.dat.xml
+
+ daffodil generate c -r simple-integer -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-integer.dat.xml data/simple-integer.dat
+ c/daffodil unparse -o c/simple-integer.dat infosets/simple-integer.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-integer"
+ root="simple-integer">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-integer.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-integer.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-long -s simple.dfdl.xsd -o c/simple-long.dat.xml data/simple-long.dat
+ daffodil unparse -r simple-long -s simple.dfdl.xsd -o c/simple-long.dat infosets/simple-long.dat.xml
+
+ daffodil generate c -r simple-long -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-long.dat.xml data/simple-long.dat
+ c/daffodil unparse -o c/simple-long.dat infosets/simple-long.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-long"
+ root="simple-long">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-long.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-long.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-nonNegativeInteger -s simple.dfdl.xsd -o c/simple-nonNegativeInteger.dat.xml data/simple-nonNegativeInteger.dat
+ daffodil unparse -r simple-nonNegativeInteger -s simple.dfdl.xsd -o c/simple-nonNegativeInteger.dat infosets/simple-nonNegativeInteger.dat.xml
+
+ daffodil generate c -r simple-nonNegativeInteger -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-nonNegativeInteger.dat.xml data/simple-nonNegativeInteger.dat
+ c/daffodil unparse -o c/simple-nonNegativeInteger.dat infosets/simple-nonNegativeInteger.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-nonNegativeInteger"
+ root="simple-nonNegativeInteger">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-nonNegativeInteger.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-nonNegativeInteger.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-short -s simple.dfdl.xsd -o c/simple-short.dat.xml data/simple-short.dat
+ daffodil unparse -r simple-short -s simple.dfdl.xsd -o c/simple-short.dat infosets/simple-short.dat.xml
+
+ daffodil generate c -r simple-short -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-short.dat.xml data/simple-short.dat
+ c/daffodil unparse -o c/simple-short.dat infosets/simple-short.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-short"
+ root="simple-short">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-short.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-short.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-unsignedByte -s simple.dfdl.xsd -o c/simple-unsignedByte.dat.xml data/simple-unsignedByte.dat
+ daffodil unparse -r simple-unsignedByte -s simple.dfdl.xsd -o c/simple-unsignedByte.dat infosets/simple-unsignedByte.dat.xml
+
+ daffodil generate c -r simple-unsignedByte -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-unsignedByte.dat.xml data/simple-unsignedByte.dat
+ c/daffodil unparse -o c/simple-unsignedByte.dat infosets/simple-unsignedByte.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-unsignedByte"
+ root="simple-unsignedByte">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-unsignedByte.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-unsignedByte.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-unsignedInt -s simple.dfdl.xsd -o c/simple-unsignedInt.dat.xml data/simple-unsignedInt.dat
+ daffodil unparse -r simple-unsignedInt -s simple.dfdl.xsd -o c/simple-unsignedInt.dat infosets/simple-unsignedInt.dat.xml
+
+ daffodil generate c -r simple-unsignedInt -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-unsignedInt.dat.xml data/simple-unsignedInt.dat
+ c/daffodil unparse -o c/simple-unsignedInt.dat infosets/simple-unsignedInt.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-unsignedInt"
+ root="simple-unsignedInt">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-unsignedInt.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-unsignedInt.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-unsignedLong -s simple.dfdl.xsd -o c/simple-unsignedLong.dat.xml data/simple-unsignedLong.dat
+ daffodil unparse -r simple-unsignedLong -s simple.dfdl.xsd -o c/simple-unsignedLong.dat infosets/simple-unsignedLong.dat.xml
+
+ daffodil generate c -r simple-unsignedLong -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-unsignedLong.dat.xml data/simple-unsignedLong.dat
+ c/daffodil unparse -o c/simple-unsignedLong.dat infosets/simple-unsignedLong.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-unsignedLong"
+ root="simple-unsignedLong">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-unsignedLong.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-unsignedLong.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ daffodil parse -r simple-unsignedShort -s simple.dfdl.xsd -o c/simple-unsignedShort.dat.xml data/simple-unsignedShort.dat
+ daffodil unparse -r simple-unsignedShort -s simple.dfdl.xsd -o c/simple-unsignedShort.dat infosets/simple-unsignedShort.dat.xml
+
+ daffodil generate c -r simple-unsignedShort -s simple.dfdl.xsd && make -C c
+ c/daffodil parse -o c/simple-unsignedShort.dat.xml data/simple-unsignedShort.dat
+ c/daffodil unparse -o c/simple-unsignedShort.dat infosets/simple-unsignedShort.dat.xml
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-unsignedShort"
+ root="simple-unsignedShort">
+ <tdml:document>
+ <tdml:documentPart type="file">data/simple-unsignedShort.dat</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset type="file">infosets/simple-unsignedShort.dat.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple_errors.tdml b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple_errors.tdml
new file mode 100644
index 000000000..10b45721a
--- /dev/null
+++ b/daffodil-codegen-c/src/test/resources/org/apache/daffodil/codegen/c/simple_errors.tdml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<!--
+ Run all tests with each backend
+ daffodil test -i -I daffodil simple.err.tdml
+ daffodil test -i -I daffodilC simple.err.tdml
+-->
+<tdml:testSuite
+ defaultRoundTrip="none"
+ xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+ <!--
+ Checks boolean must be 0 or 1, not 42
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-boolean-42"
+ root="simple-boolean">
+ <tdml:document>
+ <tdml:documentPart type="byte">0000002a</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>parse</tdml:error>
+ <tdml:error>boolean</tdml:error>
+ <tdml:error>42</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks byte with any left over bits causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-byte-2b"
+ root="simple-byte">
+ <tdml:document>
+ <tdml:documentPart type="byte">0102</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>8 bit</tdml:error>
+ <tdml:error>remaining</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks double with only 4 bytes causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-double-4b"
+ root="simple-double">
+ <tdml:document>
+ <tdml:documentPart type="byte">01020304</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>64 bit</tdml:error>
+ <tdml:error>32 available</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks float with NaN pattern is parsed as NaN
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-float-NaN"
+ root="simple-float">
+ <tdml:document>
+ <tdml:documentPart type="byte">7fc00000</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <si:simple-float xmlns:si="urn:simple">NaN</si:simple-float>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks hexBinary with too many bytes causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-hexBinary-5b"
+ root="simple-hexBinary">
+ <tdml:document>
+ <tdml:documentPart type="byte">0102030405</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>8 bit</tdml:error>
+ <tdml:error>remaining</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks hexBinary with too few bytes causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-hexBinaryPrefixed-4b"
+ root="simple-hexBinaryPrefixed">
+ <tdml:document>
+ <tdml:documentPart type="byte">01020304</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>2064 bit</tdml:error>
+ <tdml:error>16 available</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks int with 1 byte causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-int-1b"
+ root="simple-int">
+ <tdml:document>
+ <tdml:documentPart type="byte">01</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>32 bit</tdml:error>
+ <tdml:error>8 available</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ Checks unsignedShort with 4 bytes causes parse error
+ -->
+ <tdml:parserTestCase
+ model="simple.dfdl.xsd"
+ name="simple-unsignedShort-4b"
+ root="simple-unsignedShort">
+ <tdml:document>
+ <tdml:documentPart type="byte">01020304</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>16 bit</tdml:error>
+ <tdml:error>remaining</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimple.scala b/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimple.scala
new file mode 100644
index 000000000..5b09f61b6
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimple.scala
@@ -0,0 +1,53 @@
+/*
+ * 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.codegen.c
+
+import org.apache.daffodil.lib.api.TDMLImplementation
+import org.apache.daffodil.tdml.Runner
+
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestSimple {
+ val testDir = "/org/apache/daffodil/codegen/c/"
+ val runner = Runner(testDir, "simple.tdml", TDMLImplementation.DaffodilC)
+
+ @AfterClass def shutDown(): Unit = { runner.reset() }
+}
+
+class TestSimple {
+ import TestSimple._
+
+ @Test def simple_boolean(): Unit = { runner.runOneTest("simple-boolean") }
+ @Test def simple_byte(): Unit = { runner.runOneTest("simple-byte") }
+ @Test def simple_double(): Unit = { runner.runOneTest("simple-double") }
+ @Test def simple_float(): Unit = { runner.runOneTest("simple-float") }
+ @Test def simple_hexBinary(): Unit = { runner.runOneTest("simple-hexBinary") }
+ @Test def simple_hexBinaryPrefixed(): Unit = { runner.runOneTest("simple-hexBinaryPrefixed") }
+ @Test def simple_int(): Unit = { runner.runOneTest("simple-int") }
+ @Test def simple_integer(): Unit = { runner.runOneTest("simple-integer") }
+ @Test def simple_long(): Unit = { runner.runOneTest("simple-long") }
+ @Test def simple_nonNegativeInteger(): Unit = {
+ runner.runOneTest("simple-nonNegativeInteger")
+ }
+ @Test def simple_short(): Unit = { runner.runOneTest("simple-short") }
+ @Test def simple_unsignedByte(): Unit = { runner.runOneTest("simple-unsignedByte") }
+ @Test def simple_unsignedInt(): Unit = { runner.runOneTest("simple-unsignedInt") }
+ @Test def simple_unsignedLong(): Unit = { runner.runOneTest("simple-unsignedLong") }
+ @Test def simple_unsignedShort(): Unit = { runner.runOneTest("simple-unsignedShort") }
+}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimpleErrors.scala b/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimpleErrors.scala
new file mode 100644
index 000000000..942e3dc18
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/codegen/c/TestSimpleErrors.scala
@@ -0,0 +1,46 @@
+/*
+ * 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.codegen.c
+
+import org.apache.daffodil.lib.api.TDMLImplementation
+import org.apache.daffodil.tdml.Runner
+
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestSimpleErrors {
+ val testDir = "/org/apache/daffodil/codegen/c/"
+ val runner = Runner(testDir, "simple_errors.tdml", TDMLImplementation.DaffodilC)
+
+ @AfterClass def shutDown(): Unit = { runner.reset() }
+}
+
+class TestSimpleErrors {
+ import TestSimpleErrors._
+
+ @Test def simple_boolean_42(): Unit = { runner.runOneTest("simple-boolean-42") }
+ @Test def simple_byte_2b(): Unit = { runner.runOneTest("simple-byte-2b") }
+ @Test def simple_double_4b(): Unit = { runner.runOneTest("simple-double-4b") }
+ @Test def simple_float_NaN(): Unit = { runner.runOneTest("simple-float-NaN") }
+ @Test def simple_hexBinary_5b(): Unit = { runner.runOneTest("simple-hexBinary-5b") }
+ @Test def simple_hexBinaryPrefixed_4b(): Unit = {
+ runner.runOneTest("simple-hexBinaryPrefixed-4b")
+ }
+ @Test def simple_int_1b(): Unit = { runner.runOneTest("simple-int-1b") }
+ @Test def simple_unsignedShort_4b(): Unit = { runner.runOneTest("simple-unsignedShort-4b") }
+}