summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorparsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-05-25 17:14:07 +0000
committerparsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-05-25 17:14:07 +0000
commitf33b90c56969c8e1d333c4547ad113c49102b681 (patch)
treee7d020da158e27f6ad20258381cbd02f14cf225d
parente48708fd68c8d04225d5f55255c2d06f61a332b9 (diff)
downloadATCD-f33b90c56969c8e1d333c4547ad113c49102b681.tar.gz
Added create_union_tc().
-rw-r--r--TAO/orbsvcs/IFR_Service/TypeCodeFactory_i.cpp299
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;
+ }
+}