Michael
2007-06-05 22:40:14 UTC
Hello,
while developing an Any serializer I found the following behaviour when handling labels in
unions. It seems liek (in case of enums as discriminators) CORBA::TypeCode::member_label
returns an ULong containing the value of DynEnumImpl::get_as_ulong instead the actual
enumeration value (so the any returned has a kind() of tk_ulong instead of tk_enum).
// example IDL
enum DataType {
DT_LONG_LONG,
DT_STRING
};
struct Tag {
string tagName;
union TagData switch (DataType) {
case DT_LONG_LONG:
long long longValue;
case DT_STRING:
string stringValue;
} data;
};
// example C++
Tag t;
t.tagName = "Test";
t.data.stringValue("test");
CORBA::Any any;
any <<= t;
CORBA::TypeCode_var tcStruct = any.type();
assert(tcStruct->kind() == CORBA::tk_struct); // kind of Tag is struct - ok
CORBA::TypeCode_var tcUnion = tcStruct->member_type(1);
assert(tcUnion->kind() == CORBA::tk_union); // type of Tag.data is union = ok
CORBA::TypeCode_var tcEnum = tcUnion->discriminator_type();
assert(tcEnum->kind() == CORBA::tk_enum);
// type of Tag.Tagdata's dicriminator is enum - ok
std::cout << "Fist union member name: " << tcUnion->member_name(0) << std::endl;
// outputs longValue - ok
CORBA::TypeCode_var memberTc = tcUnion->member_type(0);
assert(memberTc->kind() == CORBA::tk_longlong);
// Tag.TagData.longValue is a long long - ok
CORBA::Any_var label = tcUnion->member_label(0); // get label for first member (longValue)
CORBA::TypeCode_var labelTc = label->type();
CORBA::ULong ulongLabelValue;
if (labelTc->kind() == CORBA::tk_ulong)
{
label >>= ulongLabelValue;
std::cout << "!!!!Found type tk_ulong in labelTypeCode" << std::endl;
std::cout << "!!!!Label value is " << ulongLabelValue << std::endl;
}
assert(labelTc->kind() == CORBA::tk_enum || labelTc->kind() == CORBA::tk_octet); // oops
Output:
Fist union member name: longValue
!!!!Found type tk_ulong in labelTypeCode
!!!!Label value is 0
Assertion failed: (labelTc->kind() == CORBA::tk_enum || labelTc->kind() ==
CORBA::tk_octet), function main, file ...
-
I'm not certain if this is standard compliant (I would expect the get the same types from
discriminator_type and member_label(x).type()). Tt seems like omniORBs behaviour is
symmetric with constructing unions typecodes using ORB::create_union_tc. For me it was
easy to do a workaround in deserialization (pseudo code):
if (discriminatortype == tk_enum)
{
members[x].label <<= (CORBA::ULong) labelReadFromDisc.to_ulong();
}
else
{
..more serious construction
}
thanks & regards
michael
while developing an Any serializer I found the following behaviour when handling labels in
unions. It seems liek (in case of enums as discriminators) CORBA::TypeCode::member_label
returns an ULong containing the value of DynEnumImpl::get_as_ulong instead the actual
enumeration value (so the any returned has a kind() of tk_ulong instead of tk_enum).
// example IDL
enum DataType {
DT_LONG_LONG,
DT_STRING
};
struct Tag {
string tagName;
union TagData switch (DataType) {
case DT_LONG_LONG:
long long longValue;
case DT_STRING:
string stringValue;
} data;
};
// example C++
Tag t;
t.tagName = "Test";
t.data.stringValue("test");
CORBA::Any any;
any <<= t;
CORBA::TypeCode_var tcStruct = any.type();
assert(tcStruct->kind() == CORBA::tk_struct); // kind of Tag is struct - ok
CORBA::TypeCode_var tcUnion = tcStruct->member_type(1);
assert(tcUnion->kind() == CORBA::tk_union); // type of Tag.data is union = ok
CORBA::TypeCode_var tcEnum = tcUnion->discriminator_type();
assert(tcEnum->kind() == CORBA::tk_enum);
// type of Tag.Tagdata's dicriminator is enum - ok
std::cout << "Fist union member name: " << tcUnion->member_name(0) << std::endl;
// outputs longValue - ok
CORBA::TypeCode_var memberTc = tcUnion->member_type(0);
assert(memberTc->kind() == CORBA::tk_longlong);
// Tag.TagData.longValue is a long long - ok
CORBA::Any_var label = tcUnion->member_label(0); // get label for first member (longValue)
CORBA::TypeCode_var labelTc = label->type();
CORBA::ULong ulongLabelValue;
if (labelTc->kind() == CORBA::tk_ulong)
{
label >>= ulongLabelValue;
std::cout << "!!!!Found type tk_ulong in labelTypeCode" << std::endl;
std::cout << "!!!!Label value is " << ulongLabelValue << std::endl;
}
assert(labelTc->kind() == CORBA::tk_enum || labelTc->kind() == CORBA::tk_octet); // oops
Output:
Fist union member name: longValue
!!!!Found type tk_ulong in labelTypeCode
!!!!Label value is 0
Assertion failed: (labelTc->kind() == CORBA::tk_enum || labelTc->kind() ==
CORBA::tk_octet), function main, file ...
-
I'm not certain if this is standard compliant (I would expect the get the same types from
discriminator_type and member_label(x).type()). Tt seems like omniORBs behaviour is
symmetric with constructing unions typecodes using ORB::create_union_tc. For me it was
easy to do a workaround in deserialization (pseudo code):
if (discriminatortype == tk_enum)
{
members[x].label <<= (CORBA::ULong) labelReadFromDisc.to_ulong();
}
else
{
..more serious construction
}
thanks & regards
michael