14.3. Complex Types

If the application’s data model is complex, it is possible to combine the basic types to create complex types, including nested composed types (structures within structures within unions). Types can also be extended using inheritance, improving the flexibility of the definition of the data types to fit the model.

The following subsections describe these complex types and their use.

14.3.1. Nested structures

Structures can contain other structures as members. The access to these compound members is restricted and managed by the DynamicData instance. Users must request access calling loan_value before using them, and release them with return_loaned_value once they finished. The loan operation will fail if the member is already loaned and has not been released yet.

// Create a struct type
DynamicTypeBuilder_ptr builder = DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
builder->add_member(0, "first", DynamicTypeBuilderFactory::get_instance()->create_int32_type());
builder->add_member(1, "other", DynamicTypeBuilderFactory::get_instance()->create_uint64_type());
DynamicType_ptr struct_type = builder->build();

// Create a struct type with the previous struct as member
DynamicTypeBuilder_ptr parent_builder = DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
parent_builder->add_member(0, "child_struct", struct_type);
parent_builder->add_member(1, "second", DynamicTypeBuilderFactory::get_instance()->create_int32_type());
DynamicData_ptr data(DynamicDataFactory::get_instance()->create_data(parent_builder.get()));

// Access the child struct with the loan operations
DynamicData* child_data = data->loan_value(0);
child_data->set_int32_value(5, 0);
child_data->set_uint64_value(13, 1);
data->return_loaned_value(child_data);

14.3.2. Structure inheritance

To inherit a structure from another one, use the create_child_struct_type function from DynamicTypeBuilderFactory. The resultant type contains all members from the base class and the new ones added to the child.

Structures support several levels of inheritance, so the base class can be another derived type itself.

// Create a base struct type
DynamicTypeBuilder_ptr builder = DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
builder->add_member(0, "first", DynamicTypeBuilderFactory::get_instance()->create_int32_type());
builder->add_member(1, "other", DynamicTypeBuilderFactory::get_instance()->create_uint64_type());

// Create a struct type derived from the previous struct
DynamicTypeBuilder_ptr child_builder =
        DynamicTypeBuilderFactory::get_instance()->create_child_struct_builder(builder.get());

// Add new members to the derived type
builder->add_member(2, "third", DynamicTypeBuilderFactory::get_instance()->create_uint64_type());

// Create the data instance
DynamicType_ptr struct_type = child_builder->build();
DynamicData_ptr data(DynamicDataFactory::get_instance()->create_data(struct_type));

// The derived type includes the members defined on the base type
data->set_int32_value(5, 0);
data->set_uint64_value(13, 1);
data->set_uint64_value(47, 2);

14.3.3. Alias of an alias

Alias types support recursion, simply use an alias name as base type for create_alias_type().

// Using Builders
DynamicTypeBuilder_ptr created_builder = DynamicTypeBuilderFactory::get_instance()->create_string_builder(100);
DynamicType_ptr created_type = DynamicTypeBuilderFactory::get_instance()->create_type(created_builder.get());
DynamicTypeBuilder_ptr builder = DynamicTypeBuilderFactory::get_instance()->create_alias_builder(
    created_builder.get(), "alias");
DynamicTypeBuilder_ptr builder2 = DynamicTypeBuilderFactory::get_instance()->create_alias_builder(
    builder.get(), "alias2");
DynamicData* data(DynamicDataFactory::get_instance()->create_data(builder2->build()));
data->set_string_value("Dynamic Alias 2 String");

// Creating directly the Dynamic Type
DynamicType_ptr pType = DynamicTypeBuilderFactory::get_instance()->create_string_type(100);
DynamicType_ptr pAliasType = DynamicTypeBuilderFactory::get_instance()->create_alias_type(pType, "alias");
DynamicType_ptr pAliasType2 =
        DynamicTypeBuilderFactory::get_instance()->create_alias_type(pAliasType, "alias2");
DynamicData* data2(DynamicDataFactory::get_instance()->create_data(pAliasType));
data2->set_string_value("Dynamic Alias 2 String");

14.3.4. Unions with complex types

Unions support complex type fields. The access to these complex type fields is restricted and managed by the DynamicData instance. Users must request access calling loan_value before using them, and release them with return_loaned_value once they finished. The loan operation will fail if the fields is already loaned and has not been released yet.

// Create a union DynamicTypeBuilder
DynamicType_ptr discriminator = DynamicTypeBuilderFactory::get_instance()->create_int32_type();
DynamicTypeBuilder_ptr builder = DynamicTypeBuilderFactory::get_instance()->create_union_builder(discriminator);

// Add a int32 to the union
builder->add_member(0, "first", DynamicTypeBuilderFactory::get_instance()->create_int32_type(), "", { 0 },
        true);

// Create a struct type and add it to the union
DynamicTypeBuilder_ptr struct_builder = DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
struct_builder->add_member(0, "first", DynamicTypeBuilderFactory::get_instance()->create_int32_type());
struct_builder->add_member(1, "other", DynamicTypeBuilderFactory::get_instance()->create_uint64_type());
builder->add_member(1, "first", struct_builder.get(), "", { 1 }, false);

// Create the union data instance
DynamicType_ptr union_type = builder->build();
DynamicData_ptr data(DynamicDataFactory::get_instance()->create_data(union_type));

// Access the struct member using the loan operations
DynamicData* child_data = data->loan_value(1);
child_data->set_int32_value(9, 0);
child_data->set_int64_value(13, 1);
data->return_loaned_value(child_data);