20.9.4 Accessing the Discriminator Value in a Union
A union type consists of a discriminator value and the member that it selects, if it selects one at all. The DynamicData member_id for this member is equal to the discriminator value. A member may be selected by one or more discriminator values. For example:
union Foo switch (short) {case 1:
long x;
case 2:
case 3:
string y;
};
In the above union, member x can be selected by setting the discriminator to 1, member y can be selected by a discriminator value of either 2 or 3. The discriminator can also be set to any other valid value for a short, therefore not selecting any member.
The DynamicData API does not consider the discriminator a member. This means that APIs like get_member_info() will not return information about the discriminator, and the member_count() API will return 1 if the discriminator selects a member (values of 1, 2, or 3 in our example) and 0 if the discriminator is set to a value that does not select a member.
Unions may have a default case label as well. In that case, when a value does not otherwise select a member, it will select the member that is selected by the default label. For example:
union FooWDefaultCase switch (short) {case 1:
long x;
case 2:
case 3:
string y;
default:
char z;
};
Any value other than 1, 2, and 3 selects member z. The member_count() API for a union with a default label will always return 1.
20.9.4.1 Getting the Discriminator Value
To get the value of the discriminator, use the operation get_discriminator() on the DynamicData.
Once you know the discriminator value, you can use the proper version of get_<type>() (such as get_long()) to access the member value.
For example:
int discriminatorValue = myDynamicData.get_discriminator();
int myMemberValue = myDynamicData.get_long(null, discriminatorValue);
20.9.4.2 Setting the Discriminator Value
The value of the discriminator can be set in two ways:
- Using the set_discriminator() API.
- As a side effect of any of the set_<type>() APIs.
20.9.4.2.1 set_discriminator()
When using the set_discriminator() API, if the discriminator value selects the same member in the union that is already set, the previously set value for the member is preserved and only the discriminator value is updated. In the union Foo at the beginning of this section, if member y is set to "hello" and the discriminator is 2, then the set_discriminator() API is used to set the discriminator to 3; the value of y will still be "hello".
If the discriminator is changed to select a different member in the union, the previously set member in the union will be finalized and the selected member will be initialized to its default value.
If the discriminator is changed to a value that doesn't select any member in the union, then the previously set member will be finalized and the discriminator will be set to the provided value.
Using the set_discriminator() API will overwrite any discriminator value that was previously set using a set_<type>() API.
20.9.4.2.2 set_<type>() APIs
Using any of the set_<type>() APIs on a union DynamicData object will also set the discriminator. If the member_id, instead of the member_name, is used to identify which member to set, then the supplied member_id will be used as the discriminator value. For example, in the union Foo at the beginning of this section, member y can be set using the set_string() API by supplying 2 or 3 as the member_id. Whichever member_id is used will be set as the discriminator.
When the member_name is supplied to the set<type>() API instead of the member_id, and the member_name identifies a member other than the currently set member, the first label for a member is used. So, using union Foo again, setting member y with set_string("y", "hello") will set the discriminator value to 2. If the member_name identifies the member that is currently set, then the discriminator value will be preserved and just the member value will be updated.
Using a version of the set_<type>() API that receives a member_id will overwrite any discriminator value that was previously set using the set_discriminator() API, and vice versa.