diff options
author | parsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-05-25 17:14:07 +0000 |
---|---|---|
committer | parsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-05-25 17:14:07 +0000 |
commit | f33b90c56969c8e1d333c4547ad113c49102b681 (patch) | |
tree | e7d020da158e27f6ad20258381cbd02f14cf225d | |
parent | e48708fd68c8d04225d5f55255c2d06f61a332b9 (diff) | |
download | ATCD-f33b90c56969c8e1d333c4547ad113c49102b681.tar.gz |
Added create_union_tc().
-rw-r--r-- | TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp | 299 |
1 files changed, 297 insertions, 2 deletions
diff --git a/TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp b/TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp index f830ef7566b..9c7c3013c88 100644 --- a/TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp +++ b/TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp @@ -2,6 +2,7 @@ // $Id$ #include "TypeCodeFactory_i.h" +#include "tao/Marshal.h" ACE_RCSID(IFR_Service, TypeCodeFactory_i, "$Id$") @@ -65,8 +66,108 @@ TAO_TypeCodeFactory_i::create_union_tc ( ) ACE_THROW_SPEC ((CORBA::SystemException)) { - // TODO - return 0; + TAO_OutputCDR cdr; + + cdr << TAO_ENCAP_BYTE_ORDER; + + cdr << id; + + cdr << name; + + cdr << discriminator_type; + + CORBA::ULong len = members.length (); + CORBA::ULong dups = 0; + CORBA::Long default_index = -1; + CORBA::Long raw_default_index = -1; + CORBA::Octet value = ACE_OCTET_MAX; + + for (CORBA::ULong i = 0; i < len; i++) + { + if (i > 0) + { + // Is this a duplicate case label? If so, we have to adjust + // the 'length' we encode - a member gets encoded only once. + if (ACE_OS::strcmp (members[i].name, + members[i - 1].name) + == 0) + { + ++dups; + } + } + // Reset the default index, if we have a default case label. + if ((members[i].label >>= CORBA::Any::to_octet (value)) == 1) + { + if (value == 0) + { + raw_default_index = ACE_static_cast (CORBA::Long, i); + // Only the multiple labels that come before the + // default label affect its adjusted value. + default_index = ACE_static_cast (CORBA::Long, i - dups); + } + } + } + + cdr << default_index; + + cdr << len - dups; + + for (CORBA::ULong index = 0; index < len; index++) + { + if (index > 0) + { + // Is this a duplicate case label? If so, skip it - a member + // goes into the typecode only once. + if (ACE_OS::strcmp (members[index].name, + members[index - 1].name) + == 0) + continue; + } + + if (raw_default_index >= 0 + && index == ACE_static_cast (CORBA::ULong, raw_default_index)) + { + // This is the default label - we have to find a legal value. + CORBA::TCKind kind = discriminator_type->kind (ACE_TRY_ENV); + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + + this->compute_default_label (kind, + index, + members, + cdr); + } + else + { + // Interpretive marshaling refuses to die ;-). + TAO_InputCDR in (members[index].label._tao_get_cdr (), + members[index].label._tao_byte_order ()); + + CORBA::TypeCode_var tc = members[index].label.type (); + + (void) TAO_Marshal_Object::perform_append (tc.in (), + &in, + &cdr, + ACE_TRY_ENV); + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + } + + cdr << members[index].name; + + cdr << members[index].type; + } + + CORBA::TypeCode_ptr union_typecode = + CORBA::TypeCode::_nil (); + ACE_NEW_THROW_EX (union_typecode, + CORBA_TypeCode (CORBA::tk_union, + cdr.total_length (), + cdr.buffer (), + 0, + 0), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + + return union_typecode; } CORBA::TypeCode_ptr @@ -479,3 +580,197 @@ TAO_TypeCodeFactory_i::create_home_tc ( return 0; } +void +TAO_TypeCodeFactory_i::compute_default_label (CORBA::TCKind kind, + CORBA::ULong skip_slot, + const IR::UnionMemberSeq &members, + TAO_OutputCDR &cdr) +{ + // One to hold the current default value, one to + // hold the curent label's extracted value. + union disc_types + { + CORBA::Char char_val; + CORBA::WChar wchar_val; + CORBA::Boolean bool_val; + CORBA::Short short_val; + CORBA::UShort ushort_val; + CORBA::Long long_val; + CORBA::ULong ulong_val; + CORBA::ULongLong ulonglong_val; + CORBA::ULong enum_val; + // TODO - handle longlong types + } dv, u; + + // Set these to the minimum value they can have. + switch (kind) + { + case CORBA::tk_char: + dv.char_val = 0; + break; + case CORBA::tk_wchar: + dv.wchar_val = 0; + break; + case CORBA::tk_boolean: + dv.bool_val = 0; + break; + case CORBA::tk_short: + dv.short_val = ACE_INT16_MIN; + break; + case CORBA::tk_ushort: + dv.ushort_val = 0; + break; + case CORBA::tk_long: + dv.long_val = ACE_INT32_MIN; + break; + case CORBA::tk_ulong: + dv.ulong_val = 0; + break; + case CORBA::tk_ulonglong: + dv.ulonglong_val = 0; + break; + case CORBA::tk_enum: + dv.enum_val = 0; + break; + default: + break; + } + + CORBA::ULong len = members.length (); + int success = 0; + + // A collision forces us to start over, because the label + // values need not be in sorted order. + while (success == 0) + { + success = 1; + + for (CORBA::ULong i = 0; i < len; i++) + { + // This is the one we're trying to find a legal value for. + if (i == skip_slot) + continue; + + // If there's a collision, we increment the default value. + switch (kind) + { + case CORBA::tk_char: + members[i].label >>= CORBA::Any::to_char (u.char_val); + if (u.char_val == dv.char_val) + { + dv.char_val++; + success = 0; + } + break; + case CORBA::tk_wchar: + members[i].label >>= CORBA::Any::to_wchar (u.wchar_val); + if (u.wchar_val == dv.wchar_val) + { + dv.wchar_val++; + success = 0; + } + break; + case CORBA::tk_boolean: + members[i].label >>= CORBA::Any::to_boolean (u.bool_val); + if (u.bool_val == dv.bool_val) + { + dv.bool_val++; + success = 0; + } + break; + case CORBA::tk_short: + members[i].label >>= u.short_val; + if (u.short_val == dv.short_val) + { + dv.short_val++; + success = 0; + } + break; + case CORBA::tk_ushort: + members[i].label >>= u.ushort_val; + if (u.ushort_val == dv.ushort_val) + { + dv.ushort_val++; + success = 0; + } + break; + case CORBA::tk_long: + members[i].label >>= u.long_val; + if (u.long_val == dv.long_val) + { + dv.long_val++; + success = 0; + } + break; + case CORBA::tk_ulong: + members[i].label >>= u.ulong_val; + if (u.ulong_val == dv.ulong_val) + { + dv.ulong_val++; + success = 0; + } + break; + case CORBA::tk_ulonglong: + members[i].label >>= u.ulonglong_val; + if (u.ulonglong_val == dv.ulonglong_val) + { + dv.ulonglong_val++; + success = 0; + } + break; + case CORBA::tk_enum: + { + TAO_InputCDR cdr (members[i].label._tao_get_cdr (), + members[i].label._tao_byte_order ()); + cdr.read_ulong (u.enum_val); + if (u.enum_val == dv.enum_val) + { + dv.enum_val++; + success = 0; + } + break; + } + default: + break; + } + + // If there's been a collision, we should start over right away. + if (success == 0) + break; + } + } + + // Add the default value to the encapsulation. + switch (kind) + { + case CORBA::tk_char: + cdr << CORBA::Any::from_char (dv.char_val); + break; + case CORBA::tk_wchar: + cdr << CORBA::Any::from_wchar (dv.wchar_val); + break; + case CORBA::tk_boolean: + cdr << CORBA::Any::from_boolean (dv.bool_val); + break; + case CORBA::tk_short: + cdr << dv.short_val; + break; + case CORBA::tk_ushort: + cdr << dv.ushort_val; + break; + case CORBA::tk_long: + cdr << dv.long_val; + break; + case CORBA::tk_ulong: + cdr << dv.ulong_val; + break; + case CORBA::tk_ulonglong: + cdr << dv.ulonglong_val; + break; + case CORBA::tk_enum: + cdr << dv.enum_val; + break; + default: + break; + } +} |