mbeckerle commented on a change in pull request #488:
URL: https://github.com/apache/incubator-daffodil/pull/488#discussion_r573787898
##########
File path: daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
##########
@@ -62,6 +63,9 @@ static const struct argp parse_argp = {
parse_handler, // function to get these CLI options
parse_args_doc, // short usage documentation
parse_doc, // long help documentation
+ 0, // children
Review comment:
What are children, help filter, and domain? Expand comments to explain
what these are actually for.
##########
File path: daffodil-runtime2/src/main/resources/examples/ex_nums.c
##########
@@ -80,182 +71,133 @@ static const ptrdiff_t array_offsets[6] = {
};
static const ERD *array_childrenERDs[6] = {
- &be_int16_array_ex_nums__ERD,
- &be_int16_array_ex_nums__ERD,
- &be_int16_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD
+ &be_int16_array_ex_nums_ERD,
Review comment:
For these arrays of 3 int16 or 3 float, why are you storing the ERD
redundantly?
An array should have a single ERD pointer for all the elements. This of
course requires special case treatment of arrays vs. the way scalars are
handled.
##########
File path: daffodil-runtime2/src/main/resources/examples/ex_nums.c
##########
@@ -568,6 +467,7 @@ array_unparseSelf(const array *instance, UState *ustate)
static void
bigEndian_initSelf(bigEndian *instance)
Review comment:
Why does the byte order matter here?
##########
File path: daffodil-runtime2/src/main/resources/examples/NestedUnion.c
##########
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h" // for parse_be_double, parse_be_float,
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_double,
parse_le_float, 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_double, unparse_be_float,
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_double, unparse_le_float, 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 <math.h> // for NAN
+#include <stdbool.h> // for bool, false, true
+#include <stddef.h> // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState
*ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "tag", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "_choice", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ CHOICE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "a", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "b", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "c", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+ (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+ &a_FooType_ERD,
+ &b_FooType_ERD,
+ &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "foo", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ foo_offsets, // offsets
+ foo_childrenERDs, // childrenERDs
+ (ERDInitSelf)&foo_initSelf, // initSelf
+ (ERDParseSelf)&foo_parseSelf, // parseSelf
+ (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "x", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "y", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "z", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+ (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+ &x_BarType_ERD,
+ &y_BarType_ERD,
+ &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "bar", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ bar_offsets, // offsets
+ bar_childrenERDs, // childrenERDs
+ (ERDInitSelf)&bar_initSelf, // initSelf
+ (ERDParseSelf)&bar_parseSelf, // parseSelf
+ (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+ (const char *)&data_compute_offsets._choice - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.foo - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.bar - (const char
*)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+ &_choice_data_NestedUnionType_ERD,
+ &foo_data_NestedUnionType_ERD,
+ &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "data", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ data_offsets, // offsets
+ data_childrenERDs, // childrenERDs
+ (ERDInitSelf)&data_initSelf, // initSelf
+ (ERDParseSelf)&data_parseSelf, // parseSelf
+ (ERDUnparseSelf)&data_unparseSelf, // unparseSelf
+ (ERDInitChoice)&data_initChoice // initChoice
+};
+
+static const NestedUnion NestedUnion_compute_offsets;
+
+static const size_t NestedUnion_offsets[2] = {
+ (const char *)&NestedUnion_compute_offsets.tag - (const char
*)&NestedUnion_compute_offsets,
+ (const char *)&NestedUnion_compute_offsets.data - (const char
*)&NestedUnion_compute_offsets
+};
+
+static const ERD *NestedUnion_childrenERDs[2] = {
+ &tag_NestedUnionType_ERD,
+ &data_NestedUnionType_ERD
+};
+
+static const ERD NestedUnion_ERD = {
+ {
+ "idl", // namedQName.prefix
+ "NestedUnion", // namedQName.local
+ "urn:idl:1.0", // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ NestedUnion_offsets, // offsets
+ NestedUnion_childrenERDs, // childrenERDs
+ (ERDInitSelf)&NestedUnion_initSelf, // initSelf
+ (ERDParseSelf)&NestedUnion_parseSelf, // parseSelf
+ (ERDUnparseSelf)&NestedUnion_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement(void)
+{
+ static bool initialized;
+ static NestedUnion root;
+ if (!initialized)
+ {
+ NestedUnion_initSelf(&root);
+ initialized = true;
+ }
+ return &root._base;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+foo_initSelf(foo *instance)
+{
+ instance->_base.erd = &foo_data_NestedUnionType_ERD;
+ instance->a = 0xCCCCCCCC;
+ instance->b = 0xCCCCCCCC;
+ instance->c = 0xCCCCCCCC;
+}
+
+static void
+foo_parseSelf(foo *instance, PState *pstate)
+{
+ parse_be_int32(&instance->a, pstate);
+ parse_be_int32(&instance->b, pstate);
+ parse_be_int32(&instance->c, pstate);
+}
+
+static void
+foo_unparseSelf(const foo *instance, UState *ustate)
+{
+ unparse_be_int32(instance->a, ustate);
+ unparse_be_int32(instance->b, ustate);
+ unparse_be_int32(instance->c, ustate);
+}
+
+static void
+bar_initSelf(bar *instance)
+{
+ instance->_base.erd = &bar_data_NestedUnionType_ERD;
+ instance->x = NAN;
+ instance->y = NAN;
+ instance->z = NAN;
+}
+
+static void
+bar_parseSelf(bar *instance, PState *pstate)
+{
+ parse_be_double(&instance->x, pstate);
+ parse_be_double(&instance->y, pstate);
+ parse_be_double(&instance->z, pstate);
+}
+
+static void
+bar_unparseSelf(const bar *instance, UState *ustate)
+{
+ unparse_be_double(instance->x, ustate);
+ unparse_be_double(instance->y, ustate);
+ unparse_be_double(instance->z, ustate);
+}
+
+static void
+data_initSelf(data *instance)
+{
+ instance->_base.erd = &data_NestedUnionType_ERD;
+ instance->_choice = NO_CHOICE;
+ foo_initSelf(&instance->foo);
+ bar_initSelf(&instance->bar);
+}
+
+static bool
+data_initChoice(data *instance, const NestedUnion *rootElement)
+{
+ int64_t key = rootElement->tag;
+ switch (key)
+ {
+ case 1:
+ case 2:
+ instance->_choice = 0;
+ break;
+ case 3:
+ case 4:
+ instance->_choice = 1;
+ break;
+ default:
+ instance->_choice = NO_CHOICE;
+ break;
+ }
+
+ if (instance->_choice != NO_CHOICE)
+ {
+ const size_t choice = instance->_choice + 1; // skip the _choice field
+ const size_t offset = instance->_base.erd->offsets[choice];
+ const ERD * childERD = instance->_base.erd->childrenERDs[choice];
+ InfosetBase *childNode = (InfosetBase *)((const char *)instance +
offset);
+ childNode->erd = childERD;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static void
+data_parseSelf(data *instance, PState *pstate)
+{
+ instance->_base.erd->initChoice(&instance->_base, rootElement());
+ switch (instance->_choice)
+ {
+ case 0:
+ foo_parseSelf(&instance->foo, pstate);
+ break;
+ case 1:
+ bar_parseSelf(&instance->bar, pstate);
+ break;
+ default:
+ pstate->error_msg = "node's _choice field was not initialized during
parsing";
Review comment:
We should distinguish this kind of error. This isn't an error a DFDL
schema author should be able to cause. If this error occurs it's a bug in the
C-code-generator causing it, as an internal invariant - that _choice gets set
when parsing, has been violated.
##########
File path: daffodil-runtime2/src/main/resources/examples/ex_nums.c
##########
@@ -660,10 +559,10 @@ littleEndian_unparseSelf(const littleEndian *instance,
UState *ustate)
static void
ex_nums_initSelf(ex_nums *instance)
{
+ instance->_base.erd = &ex_nums_ERD;
array_initSelf(&instance->array);
bigEndian_initSelf(&instance->bigEndian);
littleEndian_initSelf(&instance->littleEndian);
- instance->_base.erd = &ex_nums__ERD;
}
Review comment:
They are hand-crafted examples of what the generated C code should be.
They are almost documentation, except we want them compiled so we know if our
generation goals lead to something similar.
I think src/test/c/handCrafted or something makes sense, because we do want
examples of this that can be tested against the generated code to be sure they
are work-alike.
##########
File path: daffodil-runtime2/src/main/resources/examples/ex_nums.c
##########
@@ -80,182 +71,133 @@ static const ptrdiff_t array_offsets[6] = {
};
static const ERD *array_childrenERDs[6] = {
- &be_int16_array_ex_nums__ERD,
- &be_int16_array_ex_nums__ERD,
- &be_int16_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD,
- &be_float_array_ex_nums__ERD
+ &be_int16_array_ex_nums_ERD,
+ &be_int16_array_ex_nums_ERD,
+ &be_int16_array_ex_nums_ERD,
+ &be_float_array_ex_nums_ERD,
+ &be_float_array_ex_nums_ERD,
+ &be_float_array_ex_nums_ERD
};
-static const ERD array_ex_nums__ERD = {
+static const ERD array_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"array", // namedQName.local
NULL, // namedQName.ns
},
- COMPLEX, // typeCode
- 6, // numChildren
- array_offsets, // offsets
- array_childrenERDs, // childrenERDs
- (ERDInitSelf)&array_initSelf, // initSelf
- (ERDParseSelf)&array_parseSelf, // parseSelf
+ COMPLEX, // typeCode
+ 6, // numChildren
Review comment:
ERD of an array element is metadata, and so needs a minOccurs and
maxOccurs, where minOccurs is unsigned and maxOccurs is signed with -1 meaning
"unbounded". The actual number of children in an array instance has to be
stored in the array instance object. An array node has to be a different kind
of infoset node with a place for this number of actual children to be stored.
Probably all ERDs should just get minOccurs and maxOccurs and a scalar is just
one with 1, 1 as those values, an optional element is 0,1, and an array is all
other legal combinations. N, -1 and N, M with N<=M. A restriction that
minOccurs is 0, 1, or equal to maxOccurs (which is not -1) is acceptable. A
restriction that maxOccurs is 1, -1, or equal to minOccurs is also fine (means
variable-length arrays always have unbounded number of elements.)
##########
File path: daffodil-runtime2/src/main/resources/examples/NestedUnion.c
##########
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h" // for parse_be_double, parse_be_float,
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_double,
parse_le_float, 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_double, unparse_be_float,
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_double, unparse_le_float, 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 <math.h> // for NAN
+#include <stdbool.h> // for bool, false, true
+#include <stddef.h> // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState
*ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "tag", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "_choice", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ CHOICE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "a", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "b", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "c", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+ (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+ &a_FooType_ERD,
+ &b_FooType_ERD,
+ &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "foo", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ foo_offsets, // offsets
+ foo_childrenERDs, // childrenERDs
+ (ERDInitSelf)&foo_initSelf, // initSelf
+ (ERDParseSelf)&foo_parseSelf, // parseSelf
+ (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "x", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "y", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "z", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+ (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+ &x_BarType_ERD,
+ &y_BarType_ERD,
+ &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "bar", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ bar_offsets, // offsets
+ bar_childrenERDs, // childrenERDs
+ (ERDInitSelf)&bar_initSelf, // initSelf
+ (ERDParseSelf)&bar_parseSelf, // parseSelf
+ (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+ (const char *)&data_compute_offsets._choice - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.foo - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.bar - (const char
*)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+ &_choice_data_NestedUnionType_ERD,
+ &foo_data_NestedUnionType_ERD,
+ &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "data", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ data_offsets, // offsets
+ data_childrenERDs, // childrenERDs
+ (ERDInitSelf)&data_initSelf, // initSelf
+ (ERDParseSelf)&data_parseSelf, // parseSelf
+ (ERDUnparseSelf)&data_unparseSelf, // unparseSelf
+ (ERDInitChoice)&data_initChoice // initChoice
+};
+
+static const NestedUnion NestedUnion_compute_offsets;
+
+static const size_t NestedUnion_offsets[2] = {
+ (const char *)&NestedUnion_compute_offsets.tag - (const char
*)&NestedUnion_compute_offsets,
+ (const char *)&NestedUnion_compute_offsets.data - (const char
*)&NestedUnion_compute_offsets
+};
+
+static const ERD *NestedUnion_childrenERDs[2] = {
+ &tag_NestedUnionType_ERD,
+ &data_NestedUnionType_ERD
+};
+
+static const ERD NestedUnion_ERD = {
+ {
+ "idl", // namedQName.prefix
+ "NestedUnion", // namedQName.local
+ "urn:idl:1.0", // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ NestedUnion_offsets, // offsets
+ NestedUnion_childrenERDs, // childrenERDs
+ (ERDInitSelf)&NestedUnion_initSelf, // initSelf
+ (ERDParseSelf)&NestedUnion_parseSelf, // parseSelf
+ (ERDUnparseSelf)&NestedUnion_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement(void)
+{
+ static bool initialized;
+ static NestedUnion root;
+ if (!initialized)
+ {
+ NestedUnion_initSelf(&root);
+ initialized = true;
+ }
+ return &root._base;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+foo_initSelf(foo *instance)
+{
+ instance->_base.erd = &foo_data_NestedUnionType_ERD;
+ instance->a = 0xCCCCCCCC;
+ instance->b = 0xCCCCCCCC;
+ instance->c = 0xCCCCCCCC;
+}
+
+static void
+foo_parseSelf(foo *instance, PState *pstate)
+{
+ parse_be_int32(&instance->a, pstate);
+ parse_be_int32(&instance->b, pstate);
+ parse_be_int32(&instance->c, pstate);
+}
+
+static void
+foo_unparseSelf(const foo *instance, UState *ustate)
+{
+ unparse_be_int32(instance->a, ustate);
+ unparse_be_int32(instance->b, ustate);
+ unparse_be_int32(instance->c, ustate);
+}
+
+static void
+bar_initSelf(bar *instance)
+{
+ instance->_base.erd = &bar_data_NestedUnionType_ERD;
+ instance->x = NAN;
+ instance->y = NAN;
+ instance->z = NAN;
+}
+
+static void
+bar_parseSelf(bar *instance, PState *pstate)
+{
+ parse_be_double(&instance->x, pstate);
+ parse_be_double(&instance->y, pstate);
+ parse_be_double(&instance->z, pstate);
+}
+
+static void
+bar_unparseSelf(const bar *instance, UState *ustate)
+{
+ unparse_be_double(instance->x, ustate);
+ unparse_be_double(instance->y, ustate);
+ unparse_be_double(instance->z, ustate);
+}
+
+static void
+data_initSelf(data *instance)
+{
+ instance->_base.erd = &data_NestedUnionType_ERD;
+ instance->_choice = NO_CHOICE;
+ foo_initSelf(&instance->foo);
+ bar_initSelf(&instance->bar);
+}
+
+static bool
+data_initChoice(data *instance, const NestedUnion *rootElement)
+{
+ int64_t key = rootElement->tag;
+ switch (key)
+ {
+ case 1:
+ case 2:
+ instance->_choice = 0;
+ break;
+ case 3:
+ case 4:
+ instance->_choice = 1;
+ break;
+ default:
+ instance->_choice = NO_CHOICE;
+ break;
+ }
+
+ if (instance->_choice != NO_CHOICE)
+ {
+ const size_t choice = instance->_choice + 1; // skip the _choice field
+ const size_t offset = instance->_base.erd->offsets[choice];
Review comment:
Where does this index value named choice come from that allows you to
index into the offsets & ERDs of children? I was assuming this would have to be
passed into this routine.
##########
File path: daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
##########
@@ -38,6 +33,8 @@ typedef struct VisitEventHandler VisitEventHandler;
typedef void (*ERDInitSelf)(InfosetBase *infoNode);
typedef void (*ERDParseSelf)(InfosetBase *infoNode, PState *pstate);
typedef void (*ERDUnparseSelf)(const InfosetBase *infoNode, UState *ustate);
+typedef bool (*ERDInitChoice)(const InfosetBase *infoNode,
Review comment:
I think you should rename this to InitChoiceRD. A choice needs a runtime
data structure, but it's not an "E"RD, it's a "C"RD.
##########
File path:
daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
##########
@@ -105,41 +129,178 @@ class CodeGeneratorState {
qnameInit
}
+ /**
+ * We want to convert a choiceDispatchKey expression into C struct dot
+ * notation (rootElement->[subElement.field]) which will access the C
+ * struct field containing the choiceDispatchKey's runtime value.
+ *
+ * We make some assumptions to make generating the dot notation easier:
+ * - the expression starts with '{xs:string( and ends with )}'
+ * - the expression returns the value of a previous element without
+ * changing the value in any way (except converting it to xs:string)
+ * - both the expression and the C code use only local names (for now...)
+ * - we can map the context node's path to a Unix-like slash path
+ * - all dpath operations look like Unix-like relative paths (../tag)
+ * - we can normalize the new path and convert it to C struct dot notation
+ * - we can store the accessed value in an int64_t local variable safely
+ */
+ private def choiceDispatchField(context: ElementBase): String = {
+ // We want to use SchemaComponent.scPath but it's private so duplicate it
here (for now...)
+ def scPath(sc: SchemaComponent): Seq[SchemaComponent] =
sc.optLexicalParent.map { scPath }.getOrElse(Nil) :+ sc
+ val localNames = scPath(context).map {
+ case er: AbstractElementRef => er.refQName.local
+ case e: ElementBase => e.namedQName.local
+ case ed: GlobalElementDecl => ed.namedQName.local
+ case _ => ""
+ }
+ val absoluteSlashPath = localNames.mkString("/")
+ val dispatchSlashPath = context.complexType.modelGroup match {
+ case choice: Choice if choice.isDirectDispatch =>
+ val expr = choice.choiceDispatchKeyEv.expr.toBriefXML()
+ val before = "'{xs:string("
+ val after = ")}'"
+ val relativePath = if (expr.startsWith(before) && expr.endsWith(after))
+ expr.substring(before.length, expr.length - after.length) else expr
+ val normalizedURI = new URI(absoluteSlashPath + "/" +
relativePath).normalize
+ normalizedURI.getPath.substring(1)
+ case _ => ""
+ }
+ // Strip namespace prefixes since C code uses only local names (for now...)
+ val localDispatchSlashPath = dispatchSlashPath.replaceAll("/[^:]+:", "/")
+ val res = localDispatchSlashPath.replace('/', '.')
+ res
+ }
Review comment:
Yes, the right way to do this eventually is have DPath generate C-code
from expressions.
##########
File path:
daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
##########
@@ -105,41 +129,178 @@ class CodeGeneratorState {
qnameInit
}
+ /**
+ * We want to convert a choiceDispatchKey expression into C struct dot
+ * notation (rootElement->[subElement.field]) which will access the C
+ * struct field containing the choiceDispatchKey's runtime value.
+ *
+ * We make some assumptions to make generating the dot notation easier:
+ * - the expression starts with '{xs:string( and ends with )}'
+ * - the expression returns the value of a previous element without
+ * changing the value in any way (except converting it to xs:string)
+ * - both the expression and the C code use only local names (for now...)
+ * - we can map the context node's path to a Unix-like slash path
+ * - all dpath operations look like Unix-like relative paths (../tag)
+ * - we can normalize the new path and convert it to C struct dot notation
+ * - we can store the accessed value in an int64_t local variable safely
+ */
+ private def choiceDispatchField(context: ElementBase): String = {
+ // We want to use SchemaComponent.scPath but it's private so duplicate it
here (for now...)
+ def scPath(sc: SchemaComponent): Seq[SchemaComponent] =
sc.optLexicalParent.map { scPath }.getOrElse(Nil) :+ sc
+ val localNames = scPath(context).map {
+ case er: AbstractElementRef => er.refQName.local
+ case e: ElementBase => e.namedQName.local
+ case ed: GlobalElementDecl => ed.namedQName.local
+ case _ => ""
+ }
+ val absoluteSlashPath = localNames.mkString("/")
+ val dispatchSlashPath = context.complexType.modelGroup match {
+ case choice: Choice if choice.isDirectDispatch =>
+ val expr = choice.choiceDispatchKeyEv.expr.toBriefXML()
+ val before = "'{xs:string("
+ val after = ")}'"
+ val relativePath = if (expr.startsWith(before) && expr.endsWith(after))
+ expr.substring(before.length, expr.length - after.length) else expr
+ val normalizedURI = new URI(absoluteSlashPath + "/" +
relativePath).normalize
+ normalizedURI.getPath.substring(1)
+ case _ => ""
+ }
+ // Strip namespace prefixes since C code uses only local names (for now...)
+ val localDispatchSlashPath = dispatchSlashPath.replaceAll("/[^:]+:", "/")
+ val res = localDispatchSlashPath.replace('/', '.')
+ res
+ }
+
+ def addBeforeSwitchStatements(context: ElementBase): Unit = {
+ val erd = erdName(context)
+ val initStatement = s" instance->_base.erd = &$erd;"
+
+ structs.top.initStatements += initStatement
+
+ val dispatchField = choiceDispatchField(context)
+ if (dispatchField.nonEmpty) {
+ val C = localName(context)
+ val declaration =
+ s""" size_t _choice; // choice of which union field to use
+ | union
+ | {""".stripMargin
+ val erdDef =
+ s"""static const ERD _choice_$erd = {
+ | {
+ | NULL, // namedQName.prefix
+ | "_choice", // namedQName.local
+ | NULL, // namedQName.ns
+ | },
+ | CHOICE, // typeCode
+ | 0, NULL, NULL, NULL, NULL, NULL, NULL
+ |};
+ |""".stripMargin
+ val offsetComputation = s" (const char
*)&${C}_compute_offsets._choice - (const char *)&${C}_compute_offsets"
+ val erdComputation = s" &_choice_$erd"
+ val initStatement = s" instance->_choice = NO_CHOICE;"
+ val initChoiceStatement =
+ s""" int64_t key = rootElement->$dispatchField;
+ | switch (key)
+ | {""".stripMargin
+ val parseStatement =
+ s""" instance->_base.erd->initChoice(&instance->_base,
rootElement());
+ | switch (instance->_choice)
+ | {""".stripMargin
+ val unparseStatement =
+ s""" instance->_base.erd->initChoice(&instance->_base,
rootElement());
+ | switch (instance->_choice)
+ | {""".stripMargin
+
+ erds += erdDef
+ structs.top.declarations += declaration
+ structs.top.offsetComputations += offsetComputation
+ structs.top.erdComputations += erdComputation
+ structs.top.initStatements += initStatement
+ structs.top.initChoiceStatements += initChoiceStatement
+ structs.top.parserStatements += parseStatement
+ structs.top.unparserStatements += unparseStatement
+ }
+ }
+
+ def addAfterSwitchStatements(): Unit = {
+ if (structs.top.initChoiceStatements.nonEmpty) {
+ val declaration = s" };"
+ val initChoiceStatement =
+ s""" default:
+ | instance->_choice = NO_CHOICE;
+ | break;
+ | }
+ |
+ | if (instance->_choice != NO_CHOICE)
+ | {
+ | const size_t choice = instance->_choice + 1; // skip the
_choice field
+ | const size_t offset = instance->_base.erd->offsets[choice];
+ | const ERD * childERD =
instance->_base.erd->childrenERDs[choice];
+ | InfosetBase *childNode = (InfosetBase *)((const char
*)instance + offset);
+ | childNode->erd = childERD;
+ | return true;
+ | }
+ | else
+ | {
+ | return false;
+ | }""".stripMargin
+ val parseStatement =
+ s""" default:
+ | pstate->error_msg = "node's _choice field was not
initialized during parsing";
Review comment:
I already made this comment in the example code. But this should be a
different kind of error. We need to distinghish errors that come from users
making mistakes writing schemas, and failures of the implementation to
correctly compile or run the schema.
The latter are fatal errors and the right thing is probably to fail and stop
processing. (Fail in simplest way possible.)
##########
File path: daffodil-runtime2/src/main/resources/examples/ex_nums.c
##########
@@ -269,186 +211,137 @@ static const ptrdiff_t bigEndian_offsets[10] = {
};
static const ERD *bigEndian_childrenERDs[10] = {
- &be_double_bigEndian_ex_nums__ERD,
- &be_float_bigEndian_ex_nums__ERD,
- &be_uint64_bigEndian_ex_nums__ERD,
- &be_uint32_bigEndian_ex_nums__ERD,
- &be_uint16_bigEndian_ex_nums__ERD,
- &be_uint8_bigEndian_ex_nums__ERD,
- &be_int64_bigEndian_ex_nums__ERD,
- &be_int32_bigEndian_ex_nums__ERD,
- &be_int16_bigEndian_ex_nums__ERD,
- &be_int8_bigEndian_ex_nums__ERD
-};
-
-static const ERD bigEndian_ex_nums__ERD = {
+ &be_double_bigEndian_ex_nums_ERD,
+ &be_float_bigEndian_ex_nums_ERD,
+ &be_uint64_bigEndian_ex_nums_ERD,
+ &be_uint32_bigEndian_ex_nums_ERD,
+ &be_uint16_bigEndian_ex_nums_ERD,
+ &be_uint8_bigEndian_ex_nums_ERD,
+ &be_int64_bigEndian_ex_nums_ERD,
+ &be_int32_bigEndian_ex_nums_ERD,
+ &be_int16_bigEndian_ex_nums_ERD,
+ &be_int8_bigEndian_ex_nums_ERD
+};
+
+static const ERD bigEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"bigEndian", // namedQName.local
NULL, // namedQName.ns
},
- COMPLEX, // typeCode
- 10, // numChildren
- bigEndian_offsets, // offsets
- bigEndian_childrenERDs, // childrenERDs
- (ERDInitSelf)&bigEndian_initSelf, // initSelf
- (ERDParseSelf)&bigEndian_parseSelf, // parseSelf
+ COMPLEX, // typeCode
+ 10, // numChildren
+ bigEndian_offsets, // offsets
+ bigEndian_childrenERDs, // childrenERDs
+ (ERDInitSelf)&bigEndian_initSelf, // initSelf
+ (ERDParseSelf)&bigEndian_parseSelf, // parseSelf
(ERDUnparseSelf)&bigEndian_unparseSelf, // unparseSelf
+ NULL // initChoice
};
-static const ERD le_uint64_littleEndian_ex_nums__ERD = {
+static const ERD le_uint64_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_uint64", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_UINT64, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_uint32_littleEndian_ex_nums__ERD = {
+static const ERD le_uint32_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_uint32", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_UINT32, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_uint16_littleEndian_ex_nums__ERD = {
+static const ERD le_uint16_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_uint16", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_UINT16, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_uint8_littleEndian_ex_nums__ERD = {
+static const ERD le_uint8_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_uint8", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_UINT8, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_int64_littleEndian_ex_nums__ERD = {
+static const ERD le_int64_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_int64", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_INT64, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_int32_littleEndian_ex_nums__ERD = {
+static const ERD le_int32_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_int32", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_INT32, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_int16_littleEndian_ex_nums__ERD = {
+static const ERD le_int16_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_int16", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_INT16, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_int8_littleEndian_ex_nums__ERD = {
+static const ERD le_int8_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_int8", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_INT8, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_float_littleEndian_ex_nums__ERD = {
+static const ERD le_float_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_float", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_FLOAT, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
-static const ERD le_double_littleEndian_ex_nums__ERD = {
+static const ERD le_double_littleEndian_ex_nums_ERD = {
{
NULL, // namedQName.prefix
"le_double", // namedQName.local
NULL, // namedQName.ns
},
PRIMITIVE_DOUBLE, // typeCode
- 0, // numChildren
- NULL, // offsets
- NULL, // childrenERDs
- NULL, // initSelf
- NULL, // parseSelf
- NULL, // unparseSelf
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
};
static const littleEndian littleEndian_compute_offsets;
-static const ptrdiff_t littleEndian_offsets[10] = {
+static const size_t littleEndian_offsets[10] = {
Review comment:
I don't understand this. littleEndian and bigEndian don't affect the
size of things, so why do we need different offset computations given the byte
order?
##########
File path: daffodil-runtime2/src/main/resources/examples/NestedUnion.c
##########
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h" // for parse_be_double, parse_be_float,
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_double,
parse_le_float, 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_double, unparse_be_float,
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_double, unparse_le_float, 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 <math.h> // for NAN
+#include <stdbool.h> // for bool, false, true
+#include <stddef.h> // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState
*ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "tag", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "_choice", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ CHOICE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "a", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "b", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "c", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+ (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+ &a_FooType_ERD,
+ &b_FooType_ERD,
+ &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "foo", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ foo_offsets, // offsets
+ foo_childrenERDs, // childrenERDs
+ (ERDInitSelf)&foo_initSelf, // initSelf
+ (ERDParseSelf)&foo_parseSelf, // parseSelf
+ (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "x", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "y", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "z", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+ (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+ &x_BarType_ERD,
+ &y_BarType_ERD,
+ &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "bar", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ bar_offsets, // offsets
+ bar_childrenERDs, // childrenERDs
+ (ERDInitSelf)&bar_initSelf, // initSelf
+ (ERDParseSelf)&bar_parseSelf, // parseSelf
+ (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+ (const char *)&data_compute_offsets._choice - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.foo - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.bar - (const char
*)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+ &_choice_data_NestedUnionType_ERD,
+ &foo_data_NestedUnionType_ERD,
+ &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "data", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ data_offsets, // offsets
+ data_childrenERDs, // childrenERDs
+ (ERDInitSelf)&data_initSelf, // initSelf
+ (ERDParseSelf)&data_parseSelf, // parseSelf
+ (ERDUnparseSelf)&data_unparseSelf, // unparseSelf
+ (ERDInitChoice)&data_initChoice // initChoice
Review comment:
I think this initChoice is null for a complex element that has choice
children. But in the ChoiceRDs of those choices this is populated. Do I have
that correct?
If so why isn't this initChoice just the initSelf of a ChoiceRD ? It would
need an offset passed to it, as it would be initializing a choice child within
the parent's structure.
##########
File path: daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
##########
@@ -81,34 +79,35 @@ typedef struct ElementRuntimeData
const NamedQName namedQName;
const enum TypeCode typeCode;
const size_t numChildren;
- const ptrdiff_t * offsets;
+ const size_t * offsets;
Review comment:
why change to size_t? I thought ptrdiff_t was a good selection of type
for this. An offset is the delta of two pointers.
##########
File path: daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
##########
@@ -81,34 +79,35 @@ typedef struct ElementRuntimeData
const NamedQName namedQName;
const enum TypeCode typeCode;
const size_t numChildren;
- const ptrdiff_t * offsets;
+ const size_t * offsets;
const ERD ** childrenERDs;
const ERDInitSelf initSelf;
const ERDParseSelf parseSelf;
const ERDUnparseSelf unparseSelf;
+ const ERDInitChoice initChoice;
} ERD;
-// InfosetBase - representation of an infoset element
+// InfosetBase - metadata of an infoset element
typedef struct InfosetBase
{
const ERD *erd;
} InfosetBase;
-// PState - parser state while parsing input
+// PState - mutable state while parsing data
typedef struct PState
{
- FILE * stream; // input to read from
+ FILE * stream; // input to read data from
const char *error_msg; // to stop if an error happens
} PState;
-// UState - unparser state while unparsing infoset
+// UState - mutable state while unparsing infoset
typedef struct UState
{
- FILE * stream; // output to write to
+ FILE * stream; // output to write infoset to
Review comment:
For unparser, we're not writing out the infoset, we're writing out the
native data representation.
##########
File path: daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
##########
@@ -159,6 +159,13 @@ walkInfosetNode(const VisitEventHandler *handler, const
InfosetBase *infoNode)
error_msg =
handler->visitNumberElem(handler, childERD, numLocation);
break;
+ case CHOICE:
+ if (!infoNode->erd->initChoice(infoNode, rootElement()))
Review comment:
What does initChoice do? I searched and did not find an example of one
in this change set.
This seems to assume the entire infonode is just a single choice. It seems
like it needs an offset passed to it, or a child number anyway in order for an
element to be able to have multiple choice groups inside it.
##########
File path:
daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
##########
@@ -105,41 +129,178 @@ class CodeGeneratorState {
qnameInit
}
+ /**
+ * We want to convert a choiceDispatchKey expression into C struct dot
+ * notation (rootElement->[subElement.field]) which will access the C
+ * struct field containing the choiceDispatchKey's runtime value.
+ *
Review comment:
This is ok temporarily. Eventually we want to modify the DPath
expression compiler to generate C code from expressions. That shouldn't be too
hard, but will require refactoring code a bit.
##########
File path: daffodil-runtime2/src/main/resources/examples/NestedUnion.c
##########
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h" // for parse_be_double, parse_be_float,
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_double,
parse_le_float, 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_double, unparse_be_float,
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_double, unparse_le_float, 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 <math.h> // for NAN
+#include <stdbool.h> // for bool, false, true
+#include <stddef.h> // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState
*ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "tag", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "_choice", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ CHOICE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "a", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "b", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "c", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_INT32, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+ (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+ (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+ &a_FooType_ERD,
+ &b_FooType_ERD,
+ &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "foo", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ foo_offsets, // offsets
+ foo_childrenERDs, // childrenERDs
+ (ERDInitSelf)&foo_initSelf, // initSelf
+ (ERDParseSelf)&foo_parseSelf, // parseSelf
+ (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "x", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "y", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "z", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ PRIMITIVE_DOUBLE, // typeCode
+ 0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+ (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+ (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+ &x_BarType_ERD,
+ &y_BarType_ERD,
+ &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "bar", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 3, // numChildren
+ bar_offsets, // offsets
+ bar_childrenERDs, // childrenERDs
+ (ERDInitSelf)&bar_initSelf, // initSelf
+ (ERDParseSelf)&bar_parseSelf, // parseSelf
+ (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+ NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+ (const char *)&data_compute_offsets._choice - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.foo - (const char
*)&data_compute_offsets,
+ (const char *)&data_compute_offsets.bar - (const char
*)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+ &_choice_data_NestedUnionType_ERD,
+ &foo_data_NestedUnionType_ERD,
+ &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+ {
+ NULL, // namedQName.prefix
+ "data", // namedQName.local
+ NULL, // namedQName.ns
+ },
+ COMPLEX, // typeCode
+ 2, // numChildren
+ data_offsets, // offsets
+ data_childrenERDs, // childrenERDs
Review comment:
Can one of these childrenERDs be for a choice?
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]