summaryrefslogtreecommitdiff
path: root/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp')
-rw-r--r--TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp1413
1 files changed, 1413 insertions, 0 deletions
diff --git a/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp
new file mode 100644
index 00000000000..cd6a5735295
--- /dev/null
+++ b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp
@@ -0,0 +1,1413 @@
+// $Id$
+
+#include "tao/AnyTypeCode/TypeCode_CDR_Extraction.h"
+
+#include "tao/AnyTypeCode/TypeCode_Constants.h"
+#include "tao/AnyTypeCode/True_RefCount_Policy.h"
+
+#include "tao/AnyTypeCode/Alias_TypeCode.h"
+#include "tao/AnyTypeCode/Enum_TypeCode.h"
+#include "tao/AnyTypeCode/TypeCode_Case_Enum_T.h"
+#include "tao/AnyTypeCode/Fixed_TypeCode.h"
+#include "tao/AnyTypeCode/Objref_TypeCode.h"
+#include "tao/AnyTypeCode/Sequence_TypeCode.h"
+#include "tao/AnyTypeCode/String_TypeCode.h"
+#include "tao/AnyTypeCode/Struct_TypeCode.h"
+#include "tao/AnyTypeCode/Union_TypeCode.h"
+#include "tao/AnyTypeCode/Value_TypeCode.h"
+#include "tao/AnyTypeCode/Any.h"
+
+#include "tao/AnyTypeCode/Recursive_Type_TypeCode.h"
+
+#include "tao/AnyTypeCode/TypeCode_Case_T.h"
+#include "tao/AnyTypeCode/TypeCode_Struct_Field.h"
+#include "tao/AnyTypeCode/TypeCode_Value_Field.h"
+
+#include "tao/CDR.h"
+
+#include "ace/Array_Base.h"
+#include "ace/Value_Ptr.h"
+
+
+ACE_RCSID (AnyTypeCode,
+ TypeCode_CDR_Extraction,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ namespace TypeCodeFactory
+ {
+ // An array of TC_Info objects is used instead of a map of
+ // repository IDs to TypeCodes since it is presumed that the
+ // number of directly or indirectly embedded types in a TypeCode
+ // capable of holding another TypeCode will be small enough to
+ // make traversing a list faster than performing a map lookup.
+ // Use a simple array also reduces static and run-time footprint.
+
+ struct TC_Info
+ {
+ /// Constructor.
+ TC_Info (void) : id (0), type () {}
+
+ /// Repository ID.
+ char const * id;
+
+ /// TypeCode
+ CORBA::TypeCode_ptr type;
+ };
+
+ typedef ACE_Array_Base<TC_Info> TC_Info_List;
+ }
+}
+
+namespace
+{
+ bool start_cdr_encap_extraction (TAO_InputCDR & cdr)
+ {
+ CORBA::Boolean byte_order;
+
+ // Don't bother demarshaling the encapsulation length. Prefer
+ // speed over early error checking. Any CDR length related
+ // failures will be detected when demarshaling the remainder of
+ // the complex parameter list TypeCode.
+
+ if (!(cdr.skip_ulong () // Skip encapsulation length.
+ && cdr >> TAO_InputCDR::to_boolean (byte_order)))
+ return false;
+
+ cdr.reset_byte_order (byte_order);
+
+ return true;
+ }
+
+ // ---------------------------------------------------------
+
+ CORBA::ULong const TYPECODE_INDIRECTION = 0xffffffffU;
+
+ // ---------------------------------------------------------
+
+ // Use an ACE::Value_Ptr to provide exception safety and proper
+ // copying semantics.
+ typedef ACE::Value_Ptr<TAO::TypeCode::Case<CORBA::String_var, CORBA::TypeCode_var> > union_elem_type;
+ typedef ACE_Array_Base<union_elem_type> union_case_array_type;
+
+ // ------------------------------------------------------------
+
+ /// Demarshal a TypeCode.
+ bool tc_demarshal (TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TAO::TypeCodeFactory::TC_Info_List & infos);
+
+ /// Demarshal an indirected TypeCode.
+ bool tc_demarshal_indirection (TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TAO::TypeCodeFactory::TC_Info_List & infos);
+
+ bool find_recursive_tc (char const * id,
+ TAO::TypeCodeFactory::TC_Info_List & tcs,
+ TAO::TypeCodeFactory::TC_Info_List & infos)
+ {
+ // See comments above for rationale behind using an array instead
+ // of a map.
+
+ size_t const len = infos.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ TAO::TypeCodeFactory::TC_Info & info = infos[i];
+
+ if (ACE_OS::strcmp (info.id, id) == 0)
+ {
+ // We have a matching id, so store the TypeCode in the out
+ // array and then compare the others.
+ size_t const old_size = tcs.size ();
+ if (tcs.size (old_size + 1) == -1) // Incremental growth -- *sigh*
+ return false;
+
+ TAO::TypeCodeFactory::TC_Info & new_info = tcs[old_size];
+ new_info.type = info.type;
+ }
+ }
+
+ return (tcs.size () > 0) ;
+ }
+}
+
+bool
+TAO::TypeCodeFactory::tc_null_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_null);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_void_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_void);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_short_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_short);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_long_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_long);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_ushort_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ushort);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_ulong_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ulong);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_float_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_float);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_double_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_double);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_boolean_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_boolean);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_char_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_char);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_octet_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_octet);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_any_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_any);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_TypeCode_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_TypeCode);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_Principal_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_Principal);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_objref_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ // The remainder of a tk_objref TypeCode is encoded in a CDR
+ // encapsulation.
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID and name.
+ CORBA::String_var id;
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)))
+ return false;
+
+ static char const Object_id[] = "IDL:omg.org/CORBA/Object:1.0";
+ static char const CCMObject_id[] = "IDL:omg.org/CORBA/CCMObject:1.0";
+ static char const CCMHome_id[] = "IDL:omg.org/CORBA/CCMHome:1.0";
+
+ char const * tc_constant_id = "";
+
+ switch (kind)
+ {
+ case CORBA::tk_component:
+ tc_constant_id = CCMObject_id;
+ break;
+ case CORBA::tk_home:
+ tc_constant_id = CCMHome_id;
+ break;
+ case CORBA::tk_objref:
+ tc_constant_id = Object_id;
+ break;
+ default:
+ break;
+ }
+
+ if (ACE_OS::strcmp (id.in (), // len >= 0!!!
+ tc_constant_id) == 0)
+ {
+ if (!cdr.skip_string ()) // No need to demarshal the name.
+ return false;
+
+ CORBA::TypeCode_ptr tc_constant = CORBA::TypeCode::_nil ();
+ switch (kind)
+ {
+ case CORBA::tk_component:
+ tc_constant = CORBA::_tc_Component;
+ break;
+ case CORBA::tk_home:
+ tc_constant = CORBA::_tc_Home;
+ break;
+ case CORBA::tk_objref:
+ tc_constant = CORBA::_tc_Object;
+ break;
+ default:
+ break;
+ }
+
+ // No need to create a TypeCode. Just use the TypeCode
+ // constant.
+ tc =
+ CORBA::TypeCode::_duplicate (tc_constant);
+ }
+ else
+ {
+ CORBA::String_var name;
+
+ if (!(cdr >> TAO_InputCDR::to_string (name.out (), 0)))
+ return false;
+
+ typedef TAO::TypeCode::Objref<CORBA::String_var,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind,
+ id.in (),
+ name.in ()),
+ false);
+ }
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ ACE_ASSERT (kind == CORBA::tk_struct || kind == CORBA::tk_except);
+
+ // The remainder of a tk_struct/tk_except TypeCode is encoded in
+ // a CDR encapsulation.
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name and number of fields.
+ CORBA::String_var id, name;
+ CORBA::ULong nfields;
+
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)
+ && cdr >> TAO_InputCDR::to_string (name.out (), 0)
+ && cdr >> nfields))
+ return false;
+
+ typedef ACE_Array_Base<TAO::TypeCode::Struct_Field<CORBA::String_var,
+ CORBA::TypeCode_var> >
+ member_array_type;
+
+ member_array_type fields (nfields);
+
+ for (CORBA::ULong i = 0; i < nfields; ++i)
+ {
+ if (!(cdr >> TAO_InputCDR::to_string (fields[i].name.out (), 0)
+ && tc_demarshal (cdr, fields[i].type.out (), infos)))
+ return false;
+ }
+
+ typedef TAO::TypeCode::Struct<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ member_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ // Check if struct TypeCode is recursive.
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (kind == CORBA::tk_struct && find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ // Set remaining parameters.
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ member_array_type>
+ recursive_typecode_type;
+
+ size_t const len = recursive_tc.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i];
+
+ recursive_typecode_type * const rtc =
+ dynamic_cast<recursive_typecode_type *> (info.type);
+
+ if (!rtc)
+ return false; // Should never occur.
+
+ rtc->struct_parameters (name.in (), fields, nfields);
+ }
+
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind,
+ id.in (),
+ name.in (),
+ fields, // Will be copied.
+ nfields),
+ false);
+ }
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ // The remainder of a tk_enum TypeCode is encoded in a CDR
+ // encapsulation.
+
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name, discriminant type, default index
+ // and case count.
+ CORBA::String_var id, name;
+ CORBA::TypeCode_var discriminant_type;
+ CORBA::Long default_index = -1;
+ CORBA::ULong ncases = 0; // Just 'n case :-)
+
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)
+ && cdr >> TAO_InputCDR::to_string (name.out (), 0)
+ && cdr >> discriminant_type.out ())) // No need to use tc_demarshal()
+ return false;
+
+ CORBA::TCKind const discriminant_kind =
+ discriminant_type->kind ();
+
+ // Check for valid discriminant type.
+ if (!(discriminant_kind == CORBA::tk_enum
+ || discriminant_kind == CORBA::tk_ulong
+ || discriminant_kind == CORBA::tk_long
+ || discriminant_kind == CORBA::tk_ushort
+ || discriminant_kind == CORBA::tk_short
+ || discriminant_kind == CORBA::tk_char
+ || discriminant_kind == CORBA::tk_boolean
+ || discriminant_kind == CORBA::tk_longlong
+ || discriminant_kind == CORBA::tk_ulonglong))
+ return false;
+
+ if (!(cdr >> default_index
+ && default_index >= -1
+ && cdr >> ncases))
+ return false;
+
+ typedef union_elem_type elem_type;
+ typedef union_case_array_type case_array_type;
+
+ case_array_type cases (ncases);
+
+ for (CORBA::ULong i = 0; i < ncases; ++i)
+ {
+ elem_type & member = cases[i];
+
+ TAO::TypeCode::Case<CORBA::String_var, CORBA::TypeCode_var> * the_case = 0;
+
+ // Ugly. *sigh*
+ switch (discriminant_kind)
+ {
+ case CORBA::tk_enum:
+ {
+ CORBA::ULong label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_Enum_T<CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (discriminant_type.in(), label),
+ false);
+ }
+ break;
+ case CORBA::tk_ulong:
+ {
+ CORBA::ULong label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::ULong,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_long:
+ {
+ CORBA::Long label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::Long,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_ushort:
+ {
+ CORBA::UShort label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::UShort,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_short:
+ {
+ CORBA::Short label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::Short,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_char:
+ {
+ CORBA::Char label;
+ if (!(cdr >> CORBA::Any::to_char (label)))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::Char,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_boolean:
+ {
+ CORBA::Boolean label;
+ if (!(cdr >> CORBA::Any::to_boolean (label)))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::Boolean,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+ case CORBA::tk_longlong:
+ {
+ CORBA::LongLong label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::LongLong,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+#if !defined (ACE_LACKS_LONGLONG_T)
+ case CORBA::tk_ulonglong:
+ {
+ CORBA::ULongLong label;
+ if (!(cdr >> label))
+ return false;
+
+ typedef TypeCode::Case_T<CORBA::ULongLong,
+ CORBA::String_var,
+ CORBA::TypeCode_var> case_type;
+
+ ACE_NEW_RETURN (the_case,
+ case_type (label),
+ false);
+ }
+ break;
+#endif /* !ACE_LACKS_LONGLONG_T */
+ default:
+ return false;
+ }
+
+ elem_type case_value (the_case);
+ member.swap (case_value); // Exception-safe
+
+ CORBA::String_var the_name;
+ CORBA::TypeCode_var the_type;
+
+ if (!(cdr >> TAO_InputCDR::to_string (the_name.out (), 0)
+ && tc_demarshal (cdr, the_type.out (), infos)))
+ return false;
+
+ member->name (the_name.in ());
+ member->type (the_type.in ());
+ }
+
+ typedef TAO::TypeCode::Union<CORBA::String_var,
+ CORBA::TypeCode_var,
+ case_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ // Check if we have recursive members. There could be multiple.
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ // Set remaining parameters.
+
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ case_array_type>
+ recursive_typecode_type;
+
+ size_t const len = recursive_tc.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i];
+
+ recursive_typecode_type * const rtc =
+ dynamic_cast<recursive_typecode_type *> (info.type);
+
+ if (!rtc)
+ return false; // Should never occur.
+
+ rtc->union_parameters (name.in (),
+ discriminant_type,
+ cases, // Will be copied.
+ ncases,
+ default_index);
+ }
+
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ ACE_NEW_RETURN (tc,
+ typecode_type (id.in (),
+ name.in (),
+ discriminant_type,
+ cases, // Will be copied.
+ ncases,
+ default_index),
+ false);
+ }
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_enum_factory (CORBA::TCKind /* kind */,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ // The remainder of a tk_enum TypeCode is encoded in a CDR
+ // encapsulation.
+
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name and number of fields.
+ CORBA::String_var id, name;
+ CORBA::ULong nenumerators;
+
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)
+ && cdr >> TAO_InputCDR::to_string (name.out (), 0)
+ && cdr >> nenumerators))
+ return false;
+
+ ACE_Array_Base<CORBA::String_var> enumerators (nenumerators);
+
+ for (CORBA::ULong i = 0; i < nenumerators; ++i)
+ {
+ if (!(cdr >> TAO_InputCDR::to_string (enumerators[i].out (), 0)))
+ return false;
+ }
+
+ typedef TAO::TypeCode::Enum<
+ CORBA::String_var,
+ ACE_Array_Base<CORBA::String_var>,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (id.in (),
+ name.in (),
+ enumerators, // Will be copied.
+ nenumerators),
+ false);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_string_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ // A tk_string/tk_wstring TypeCode has a simple parameter list,
+ // i.e. it is not encoded in a CDR encapsulation.
+
+ CORBA::ULong bound;
+ if (!(cdr >> bound))
+ return false;
+
+ if (bound == 0)
+ {
+ // Just use the TypeCode constant.
+ if (kind == CORBA::tk_string)
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_string);
+ else if (kind == CORBA::tk_wstring)
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_wstring);
+ else
+ return false;
+
+ return true;
+ }
+
+ typedef TAO::TypeCode::String<TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind, bound),
+ false);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_sequence_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ ACE_ASSERT (kind == CORBA::tk_sequence || kind == CORBA::tk_array);
+
+ // The remainder of a tk_sequence TypeCode is encoded in a CDR
+ // encapsulation.
+
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name and content type.
+ CORBA::TypeCode_var content_type;
+ CORBA::ULong length;
+
+ if (!(tc_demarshal (cdr, content_type.out (), infos)
+ && cdr >> length))
+ return false;
+
+ typedef TAO::TypeCode::Sequence<
+ CORBA::TypeCode_var,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind, content_type, length),
+ false);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_array_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_sequence_factory (kind, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_alias_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ // The remainder of a tk_alias or tk_value_box TypeCode is encoded
+ // in a CDR encapsulation.
+
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name and content type.
+ CORBA::String_var id, name;
+ CORBA::TypeCode_var content_type;
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)
+ && cdr >> TAO_InputCDR::to_string (name.out (), 0)
+ && tc_demarshal (cdr, content_type.out (), infos)))
+ return false;
+
+ typedef TAO::TypeCode::Alias<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind,
+ id.in (),
+ name.in (),
+ content_type),
+ false);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_except_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_struct_factory (kind, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_longlong_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_longlong);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_ulonglong_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ulonglong);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_longdouble_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_longdouble);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_wchar_factory (CORBA::TCKind,
+ TAO_InputCDR &,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ tc = CORBA::TypeCode::_duplicate (CORBA::_tc_wchar);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_wstring_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_string_factory (kind, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_fixed_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List &)
+{
+ // A tk_fixed TypeCode has a simple parameter list, i.e. it is not
+ // encoded in a CDR encapsulation.
+
+ CORBA::UShort digits, scale;
+ if (!(cdr >> digits && cdr >> scale))
+ return false;
+
+ typedef TAO::TypeCode::Fixed<TAO::True_RefCount_Policy> typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ typecode_type (digits, scale),
+ false);
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_value_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ // The remainder of a tk_value/tk_event TypeCode is encoded in a
+ // CDR encapsulation
+
+ if (!start_cdr_encap_extraction (cdr))
+ return false;
+
+ // Extract the repository ID, name and number of fields.
+ CORBA::String_var id;
+ if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0)))
+ return false;
+
+// if (ACE_OS::strcmp (id.in (), "IDL:omg.org/CORBA/ValueBase:1.0") == 0)
+// {
+// // No need to create a TypeCode. Just use the TypeCode
+// // constant.
+// tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ValueBase);
+
+// return true;
+// }
+// else if (ACE_OS::strcmp (id.in (),
+// "IDL:omg.org/CORBA/EventBase:1.0") == 0)
+// {
+// // No need to create a TypeCode. Just use the TypeCode
+// // constant.
+// tc = CORBA::TypeCode::_duplicate (CORBA::_tc_EventBase);
+
+// return true;
+// }
+
+ CORBA::String_var name;
+ CORBA::ValueModifier type_modifier;
+ CORBA::TypeCode_var concrete_base;
+ CORBA::ULong nfields;
+
+ if (!(cdr >> TAO_InputCDR::to_string (name.out (), 0)
+ && cdr >> type_modifier
+ && cdr >> concrete_base.out ()
+ && cdr >> nfields))
+ return false;
+
+ typedef ACE_Array_Base<TAO::TypeCode::Value_Field<CORBA::String_var,
+ CORBA::TypeCode_var> >
+ member_array_type;
+
+ member_array_type fields (nfields);
+
+ for (CORBA::ULong i = 0; i < nfields; ++i)
+ {
+ TAO::TypeCode::Value_Field<CORBA::String_var,
+ CORBA::TypeCode_var> & field = fields[i];
+
+ if (!(cdr >> TAO_InputCDR::to_string (field.name.out (), 0)
+ && tc_demarshal (cdr, field.type.out (), infos)
+ && cdr >> field.visibility))
+ return false;
+ }
+
+ typedef TAO::TypeCode::Value<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ member_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ // Check if valuetype/eventtype TypeCode is recursive.
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ // Set remaining parameters.
+
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ member_array_type>
+ recursive_typecode_type;
+
+ size_t const len = recursive_tc.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i];
+
+ recursive_typecode_type * const rtc =
+ dynamic_cast<recursive_typecode_type *> (info.type);
+
+ if (!rtc)
+ return false; // Should never occur.
+
+ rtc->valuetype_parameters (name.in (),
+ type_modifier,
+ concrete_base,
+ fields, // Will be copied.
+ nfields);
+ }
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ ACE_NEW_RETURN (tc,
+ typecode_type (kind,
+ id.in (),
+ name.in (),
+ type_modifier,
+ concrete_base,
+ fields, // Will be copied.
+ nfields),
+ false);
+ }
+
+ return true;
+}
+
+bool
+TAO::TypeCodeFactory::tc_value_box_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_alias_factory (kind, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_native_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_objref_factory (CORBA::tk_native, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_abstract_interface_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_objref_factory (CORBA::tk_abstract_interface, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_local_interface_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_objref_factory (CORBA::tk_local_interface, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_component_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_objref_factory (CORBA::tk_component, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_home_factory (CORBA::TCKind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_objref_factory (CORBA::tk_home, cdr, tc, infos);
+}
+
+bool
+TAO::TypeCodeFactory::tc_event_factory (CORBA::TCKind kind,
+ TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TC_Info_List & infos)
+{
+ return tc_value_factory (kind, cdr, tc, infos);
+}
+
+// ---------------------------------------------------------------
+
+namespace
+{
+ bool
+ tc_demarshal (TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TAO::TypeCodeFactory::TC_Info_List & infos)
+ {
+ // ULong since we need to detect indirected TypeCodes, too.
+
+ CORBA::ULong kind;
+ if (!(cdr >> kind)
+ || (kind >= static_cast<CORBA::ULong> (CORBA::TAO_TC_KIND_COUNT)
+ && kind != TYPECODE_INDIRECTION))
+ return false;
+
+ if (kind == TYPECODE_INDIRECTION)
+ return tc_demarshal_indirection (cdr, tc, infos);
+
+ using namespace TAO::TypeCodeFactory;
+
+ static factory const factory_map[] =
+ {
+ tc_null_factory,
+ tc_void_factory,
+ tc_short_factory,
+ tc_long_factory,
+ tc_ushort_factory,
+ tc_ulong_factory,
+ tc_float_factory,
+ tc_double_factory,
+ tc_boolean_factory,
+ tc_char_factory,
+ tc_octet_factory,
+ tc_any_factory,
+ tc_TypeCode_factory,
+ tc_Principal_factory,
+ tc_objref_factory,
+ tc_struct_factory,
+ tc_union_factory,
+ tc_enum_factory,
+ tc_string_factory,
+ tc_sequence_factory,
+ tc_array_factory,
+ tc_alias_factory,
+ tc_except_factory,
+ tc_longlong_factory,
+ tc_ulonglong_factory,
+ tc_longdouble_factory,
+ tc_wchar_factory,
+ tc_wstring_factory,
+ tc_fixed_factory,
+ tc_value_factory,
+ tc_value_box_factory,
+ tc_native_factory,
+ tc_abstract_interface_factory,
+ tc_local_interface_factory,
+ tc_component_factory,
+ tc_home_factory,
+ tc_event_factory
+ };
+
+ return factory_map[kind] (static_cast<CORBA::TCKind> (kind),
+ cdr,
+ tc,
+ infos);
+ }
+
+ bool
+ tc_demarshal_indirection (TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc,
+ TAO::TypeCodeFactory::TC_Info_List & infos)
+ {
+ CORBA::Long offset;
+
+ if (!(cdr >> offset) || offset >= -4)
+ {
+ // Offsets must be negative since they point back to a
+ // TypeCode found earlier in the CDR stream. They must be
+ // less than -4 since an offset of -4 points back to the
+ // indirection TypeCode itself, meaning that it would be
+ // self-indirecting.
+ return false;
+ }
+
+// ACE_Message_Block * const mb =
+// const_cast<ACE_Message_Block *> (cdr.start ());
+
+// TAO_InputCDR indir_stream (mb->rd_ptr () + offset - 4,
+ TAO_InputCDR indir_stream (cdr.rd_ptr () + offset - sizeof (CORBA::Long),
+ (-offset) + sizeof (CORBA::Long),
+ cdr.byte_order ());
+
+ if (!indir_stream.good_bit ())
+ {
+ return false;
+ }
+
+ CORBA::TCKind kind;
+ if (!(indir_stream >> kind)
+
+ // Indirected TypeCode must point to top-level TypeCode.
+ || static_cast<CORBA::ULong> (kind) == TYPECODE_INDIRECTION
+
+ // Only struct, union and valuetype TypeCodes may be recursive.
+ || !(kind == CORBA::tk_struct
+ || kind == CORBA::tk_union
+ || kind == CORBA::tk_value
+ || kind == CORBA::tk_event)
+
+ // Currently all recursive TypeCodes have complex parameter
+ // lists, meaning they are encoded as CDR encapsulations.
+ || !start_cdr_encap_extraction (indir_stream))
+ {
+ return false;
+ }
+
+ /**
+ * @todo Recursive TypeCode demarshaling is currently suboptimal
+ * due to redundant demarshaling of TypeCode parameters,
+ * such as repository ID, and excessive
+ * allocations/copying.
+ */
+
+ CORBA::String_var id;
+ if (!(indir_stream >> TAO_InputCDR::to_string (id.out (), 0)))
+ return false;
+
+ // Don't bother demarshaling the rest of the parameters. They will
+ // be handled by the top-level TypeCode demarshaling call.
+ bool new_tc = false;
+
+ switch (kind)
+ {
+ case CORBA::tk_struct:
+ {
+ // Check if we already have a tc for this type, if yes, use that
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ new_tc = true;
+
+ typedef ACE_Array_Base<
+ TAO::TypeCode::Struct_Field<
+ CORBA::String_var,
+ CORBA::TypeCode_var> > member_array_type;
+
+ typedef TAO::TypeCode::Struct<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ member_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ member_array_type>
+ recursive_typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ recursive_typecode_type (kind,
+ id.in ()),
+ false);
+ }
+ }
+ break;
+ case CORBA::tk_union:
+ {
+ // Check if we already have a tc for this type, if yes, use that
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ new_tc = true;
+
+ typedef union_case_array_type member_array_type;
+
+ typedef TAO::TypeCode::Union<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ member_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ member_array_type>
+ recursive_typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ recursive_typecode_type (kind,
+ id.in ()),
+ false);
+ }
+ }
+ break;
+ case CORBA::tk_value:
+ case CORBA::tk_event:
+ {
+ // Check if we already have a tc for this type, if yes, use that
+ TAO::TypeCodeFactory::TC_Info_List recursive_tc;
+ if (find_recursive_tc (id.in (), recursive_tc, infos))
+ {
+ tc = recursive_tc[0].type;
+ }
+ else
+ {
+ new_tc = true;
+
+ typedef ACE_Array_Base<
+ TAO::TypeCode::Value_Field<
+ CORBA::String_var,
+ CORBA::TypeCode_var> > member_array_type;
+
+ typedef TAO::TypeCode::Value<
+ CORBA::String_var,
+ CORBA::TypeCode_var,
+ member_array_type,
+ TAO::True_RefCount_Policy> typecode_type;
+
+ typedef TAO::TypeCode::Recursive_Type<typecode_type,
+ CORBA::TypeCode_var,
+ member_array_type>
+ recursive_typecode_type;
+
+ ACE_NEW_RETURN (tc,
+ recursive_typecode_type (kind,
+ id.in ()),
+ false);
+ }
+ }
+ break;
+ default:
+ return false; // We should never get here.
+ };
+
+ // Only when we created a new tc add it to the list.
+ if (new_tc)
+ {
+ size_t const old_size = infos.size ();
+ if (infos.size (old_size + 1) == -1) // Incremental growth -- *sigh*
+ return false;
+
+ TAO::TypeCodeFactory::TC_Info & info = infos[old_size];
+
+ info.id = tc->id ();
+ // Should never throw!
+
+ info.type = tc;
+ }
+
+ return true;
+ }
+}
+
+// ----------------------------------------------------------------
+
+CORBA::Boolean
+operator>> (TAO_InputCDR & cdr,
+ CORBA::TypeCode_ptr & tc)
+{
+ TAO::TypeCodeFactory::TC_Info_List infos;
+
+ return tc_demarshal (cdr, tc, infos);
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL