From c961ae6f4f05d493b3a827d679419b93210dec84 Mon Sep 17 00:00:00 2001 From: kolpackov Date: Fri, 18 Jan 2002 19:06:50 +0000 Subject: *** empty log message *** --- TAO/TAO_IDL/be/be_valuetype.cpp | 128 +++++++++ TAO/TAO_IDL/be/be_visitor_valuetype.cpp | 3 +- TAO/TAO_IDL/be/be_visitor_valuetype/any_op_ch.cpp | 23 +- TAO/TAO_IDL/be/be_visitor_valuetype/any_op_cs.cpp | 86 +++++- .../be/be_visitor_valuetype/valuetype_ch.cpp | 23 ++ .../be/be_visitor_valuetype/valuetype_cs.cpp | 30 ++ TAO/tao/Typecode.cpp | 305 ++++++++++++++++++++- TAO/tao/Typecode.h | 20 ++ TAO/tao/ValueBase.cpp | 15 +- TAO/tao/append.cpp | 95 +++++++ TAO/tao/skip.cpp | 86 ++++++ 11 files changed, 804 insertions(+), 10 deletions(-) diff --git a/TAO/TAO_IDL/be/be_valuetype.cpp b/TAO/TAO_IDL/be/be_valuetype.cpp index 7b4a241ca63..8391baa5784 100644 --- a/TAO/TAO_IDL/be/be_valuetype.cpp +++ b/TAO/TAO_IDL/be/be_valuetype.cpp @@ -748,6 +748,134 @@ be_valuetype::accept (be_visitor *visitor) return visitor->visit_valuetype (this); } +ACE_CDR::ULong +be_valuetype::data_members_count (AST_Field::Visibility vis) +{ + ACE_CDR::ULong count = 0; + + // proceed if the number of members in our scope is greater than 0 + if (this->nmembers () > 0) + { + // initialize an iterator to iterate thru our scope + UTL_ScopeActiveIterator *si; + ACE_NEW_RETURN (si, + UTL_ScopeActiveIterator (this, + UTL_Scope::IK_decls), + 0); + + // continue until each element is visited + for (;!si->is_done ();si->next()) + { + AST_Decl *d = si->item (); + + if (!d) + { + delete si; + ACE_ERROR_RETURN (( + LM_ERROR, + "(%N:%l) be_valuetype::data_members_count - " + "bad node in this scope\n"), 0); + } + + AST_Field *field = AST_Field::narrow_from_decl (d); + + if (!field) + { + continue; + } + + if (vis != AST_Field::vis_NA) + { + if (vis == field->visibility ()) ++count; + } + else + { + ++count; + } + + } // end of for loop + + delete si; + } + return count; +} + +idl_bool +be_valuetype::in_recursion (AST_Type *node) +{ + if (node == 0) + { + node = this; + } + + // proceed if the number of members in our scope is greater than 0 + if (this->nmembers () > 0) + { + // initialize an iterator to iterate thru our scope + UTL_ScopeActiveIterator *si; + ACE_NEW_RETURN (si, + UTL_ScopeActiveIterator (this, + UTL_Scope::IK_decls), + 0); + + // continue until each element is visited + for (;!si->is_done ();si->next()) + { + AST_Decl *d = si->item (); + + if (!d) + { + delete si; + ACE_ERROR_RETURN (( + LM_ERROR, + "(%N:%l) be_valuetype::in_recursion - " + "bad node in this scope\n"), 0); + } + + AST_Field *field = AST_Field::narrow_from_decl (d); + + if (!field) + { + continue; + } + + // IDL doesn't have such a feature as name reuse so + // just compare fully qualified names + + AST_Type *type = AST_Type::narrow_from_decl (field->field_type ()); + + if (!type) + { + delete si; + ACE_ERROR_RETURN (( + LM_ERROR, + "(%N:%l) be_valuetype::in_recursion - " + "bad base type\n"), 0); + } + + if (!ACE_OS::strcmp (node->full_name (), + type->full_name ())) + { + delete si; + return 1; + } + + // Now hand over to our field type + if (type->in_recursion (node)) + { + delete si; + return 1; + } + + } // end of for loop + + delete si; + } + + return 0; +} + + // Narrowing. IMPL_NARROW_METHODS1 (be_valuetype, be_interface) IMPL_NARROW_FROM_DECL (be_valuetype) diff --git a/TAO/TAO_IDL/be/be_visitor_valuetype.cpp b/TAO/TAO_IDL/be/be_visitor_valuetype.cpp index 53c530e207b..21eb2c2c90b 100644 --- a/TAO/TAO_IDL/be/be_visitor_valuetype.cpp +++ b/TAO/TAO_IDL/be/be_visitor_valuetype.cpp @@ -53,5 +53,6 @@ #include "be_visitor_valuetype/valuetype_init_ci.cpp" #include "be_visitor_valuetype/valuetype_init_cs.cpp" #include "be_visitor_valuetype/valuetype_init_arglist_ch.cpp" - +#include "be_visitor_valuetype/any_op_ch.cpp" +#include "be_visitor_valuetype/any_op_cs.cpp" diff --git a/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_ch.cpp b/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_ch.cpp index 0b760f96ee1..b461d181ca6 100644 --- a/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_ch.cpp +++ b/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_ch.cpp @@ -16,6 +16,7 @@ // // = AUTHOR // Jeff Parsons +// Boris Kolpackov // // ============================================================================ @@ -46,12 +47,30 @@ be_visitor_valuetype_any_op_ch::~be_visitor_valuetype_any_op_ch (void) int be_visitor_valuetype_any_op_ch::visit_valuetype (be_valuetype *node) { - if (node->cli_hdr_any_op_gen () || node->imported () || node->is_local ()) + if (node->cli_hdr_any_op_gen () + || node->imported () + || node->is_local ()) { return 0; } - // TODO + TAO_OutStream *os = this->ctx_->stream (); + + // Generate the Any <<= and >>= operator declarations. + os->indent (); + *os << "// Any operators for valuetype " << node->name () << be_nl; + + *os << be_global->stub_export_macro () << "void" + << " operator<<= (CORBA::Any &, " << node->name () + << " *); // copying" << be_nl; + + *os << be_global->stub_export_macro () << "void" + << " operator<<= (CORBA::Any &, " << node->name () + << " **); // non-copying" << be_nl; + + *os << be_global->stub_export_macro () << "CORBA::Boolean" + << " operator>>= (const CORBA::Any &, " + << node->name () << " *&);\n"; node->cli_hdr_any_op_gen (1); diff --git a/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_cs.cpp b/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_cs.cpp index 0af1db9391d..404d08ec99c 100644 --- a/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_cs.cpp +++ b/TAO/TAO_IDL/be/be_visitor_valuetype/any_op_cs.cpp @@ -14,6 +14,7 @@ // // = AUTHOR // Jeff Parsons +// Boris Kolpackov // // ============================================================================ @@ -53,9 +54,88 @@ be_visitor_valuetype_any_op_cs::visit_valuetype (be_valuetype *node) os->indent (); - // TODO - - *os << be_nl; + // Generate the Any <<= and >>= operator declarations + + *os << be_global->stub_export_macro () << "void" << be_nl + << "operator<<= (CORBA::Any &any, " << node->name () + << " *value) // copying" << be_nl + << "{" << be_idt_nl + << "TAO_OutputCDR stream;" << be_nl + << "if (stream << value)" << be_nl + << "{" << be_idt_nl + << "any._tao_replace (" << be_idt << be_idt_nl + << node->tc_name () << ", " << be_nl + << "TAO_ENCAP_BYTE_ORDER," << be_nl + << "stream.begin ());" << be_uidt << be_uidt << be_uidt_nl + << "}" << be_uidt_nl + << "}" << be_nl << be_nl; + + *os << be_global->stub_export_macro () << "void" << be_nl + << "operator<<= (CORBA::Any &any, " << node->name () + << " **value) // non-copying" << be_nl + << "{" << be_idt_nl + << "TAO_OutputCDR stream;" << be_nl + << "if (stream << *value)" << be_nl + << "{" << be_idt_nl + << "any._tao_replace (" << be_idt << be_idt_nl + << node->tc_name () << ", " << be_nl + << "TAO_ENCAP_BYTE_ORDER," << be_nl + << "stream.begin ()," << be_nl + << "1," << be_nl + << "*value," << be_nl + << node->name () << "::_tao_any_destructor);" + << be_uidt << be_uidt << be_uidt_nl + << "}" << be_uidt_nl + << "}" << be_nl << be_nl; + + + *os << be_global->stub_export_macro () << "CORBA::Boolean" << be_nl + << "operator>>= (const CORBA::Any &any, " + << node->name () << " *&value)" << be_nl + << "{" << be_idt_nl + << "ACE_TRY_NEW_ENV" << be_nl + << "{" << be_idt_nl + << "value = 0;" << be_nl + << "CORBA::TypeCode_var type = any.type ();" << be_nl << be_nl + << "CORBA::Boolean result = type->equivalent (" << node->tc_name () + << " TAO_ENV_ARG_PARAMETER);" << be_nl + << "ACE_TRY_CHECK;" << be_nl << be_nl + << "if (!result)" << be_nl + << "{" << be_idt_nl + << "return 0; // not equivalent" << be_uidt_nl + << "}" << be_nl + << "if (any.any_owns_data ())" << be_nl + << "{" << be_idt_nl + << "value = ACE_static_cast(" << be_idt << be_idt_nl + << node->name () << "*," << be_nl + << "any.value ());" << be_uidt << be_uidt_nl + << "return 1;" << be_uidt_nl + << "}" << be_nl + << "else" << be_nl // else any does not own the data + << "{" << be_idt_nl + << node->name () << " *tmp;" << be_nl + << "TAO_InputCDR stream (" << be_idt << be_idt_nl + << "any._tao_get_cdr ()," << be_nl + << "any._tao_byte_order ());" << be_uidt << be_uidt_nl + << "if (stream >> tmp)" << be_nl + << "{" << be_idt_nl + << "((CORBA::Any *)&any)->_tao_replace (" << be_idt << be_idt_nl + << node->tc_name () << "," << be_nl + << "1," << be_nl + << "ACE_static_cast (void *, tmp)," << be_nl + << node->name () << "::_tao_any_destructor);" << be_uidt << be_uidt_nl + << "value = tmp;" << be_nl + << "return 1;" << be_uidt_nl + << "}" << be_nl + << be_uidt_nl + << "}" << be_uidt_nl + << "}" << be_nl + << "ACE_CATCHANY" << be_nl + << "{" << be_nl + << "}" << be_nl + << "ACE_ENDTRY;" << be_nl + << "return 0;" << be_uidt_nl + << "}" << be_nl << be_nl; *os << "#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) || \\" << be_idt_nl diff --git a/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_ch.cpp b/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_ch.cpp index a530996d54a..92fa9608d7b 100644 --- a/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_ch.cpp +++ b/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_ch.cpp @@ -216,6 +216,11 @@ be_visitor_valuetype_ch::visit_valuetype (be_valuetype *node) << "static const char* " << "_tao_obv_static_repository_id ();" << be_nl << be_nl; + // Ugly TAO any support routine + *os << "static void _tao_any_destructor (void *);" + << be_nl << be_nl; + + // Generate code for the valuetype definition. if (this->visit_valuetype_scope (node) == -1) { @@ -315,6 +320,24 @@ be_visitor_valuetype_ch::visit_valuetype (be_valuetype *node) delete visitor; + // Step last: generate typecode declaration + { + be_visitor *visitor; + be_visitor_context ctx (*this->ctx_); + ctx.state (TAO_CodeGen::TAO_TYPECODE_DECL); + visitor = tao_cg->make_visitor (&ctx); + + if (!visitor || (node->accept (visitor) == -1)) + { + ACE_ERROR_RETURN ((LM_ERROR, + "(%N:%l) be_visitor_valuetype_ch::" + "visit_structure - " + "TypeCode declaration failed\n" + ), + -1); + } + } + node->cli_hdr_gen (I_TRUE); return 0; diff --git a/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_cs.cpp b/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_cs.cpp index 417e2c58ea4..fa658ecdffb 100644 --- a/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_cs.cpp +++ b/TAO/TAO_IDL/be/be_visitor_valuetype/valuetype_cs.cpp @@ -51,6 +51,25 @@ be_visitor_valuetype_cs::visit_valuetype (be_valuetype *node) return 0; } + // by using a visitor to declare and define the TypeCode, we have the + // added advantage to conditionally not generate any code. This will be + // based on the command line options. This is still TO-DO + { + be_visitor *visitor; + be_visitor_context ctx (*this->ctx_); + ctx.state (TAO_CodeGen::TAO_TYPECODE_DEFN); + ctx.sub_state (TAO_CodeGen::TAO_TC_DEFN_TYPECODE); + visitor = tao_cg->make_visitor (&ctx); + if (!visitor || (node->accept (visitor) == -1)) + { + ACE_ERROR_RETURN ((LM_ERROR, + "(%N:%l) be_visitor_valuetype_cs::" + "visit_valuetype - " + "TypeCode definition failed\n" + ), -1); + } + } + os = this->ctx_->stream (); os->indent (); // start with whatever indentation level we are at @@ -132,6 +151,17 @@ be_visitor_valuetype_cs::visit_valuetype (be_valuetype *node) *os << "return rval;" << be_uidt_nl << "}\n\n"; + // Ugly TAO any support routine + *os << "void" << be_nl + << node->name () + << "::_tao_any_destructor (void *_tao_void_pointer)" << be_nl + << "{" << be_idt_nl + << node->local_name () << " *tmp = ACE_static_cast (" + << node->local_name () << "*, _tao_void_pointer);" << be_nl + << "delete tmp;" << be_uidt_nl + << "}" << be_nl << be_nl; + + // Nothing to marshal if abstract valuetype. if (!node->is_abstract_valuetype ()) { diff --git a/TAO/tao/Typecode.cpp b/TAO/tao/Typecode.cpp index 471b73b195d..254bfb5eb31 100644 --- a/TAO/tao/Typecode.cpp +++ b/TAO/tao/Typecode.cpp @@ -427,6 +427,25 @@ CORBA_TypeCode::content_type (TAO_ENV_SINGLE_ARG_DECL) const } +CORBA::TypeCode_ptr +CORBA_TypeCode::concrete_base_type (TAO_ENV_SINGLE_ARG_DECL) const +{ + if (this->private_state_->tc_concrete_base_type_known_) + { + return CORBA_TypeCode::_duplicate ( + this->private_state_->tc_concrete_base_type_ + ); + } + else + { + CORBA::TypeCode_ptr tmp = + this->private_concrete_base_type (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + + return CORBA_TypeCode::_duplicate (tmp); + } +} + // skip a typecode encoding in a given CDR stream // This is just a helper function CORBA::Boolean @@ -462,6 +481,7 @@ CORBA_TypeCode::skip_typecode (TAO_InputCDR &stream) case CORBA::tk_array: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: return (stream.read_ulong (temp) != 0 && stream.skip_bytes (temp) != 0); } @@ -485,6 +505,8 @@ TC_Private_State::TC_Private_State (CORBA::TCKind kind) tc_default_index_used_known_ (0), tc_length_known_ (0), tc_content_type_known_ (0), + tc_discrim_pad_size_known_ (0), + tc_concrete_base_type_known_ (0), tc_id_ (0), tc_name_ (0), tc_member_count_ (0), @@ -494,7 +516,8 @@ TC_Private_State::TC_Private_State (CORBA::TCKind kind) tc_discriminator_type_ (0), tc_default_index_used_ (0), tc_length_ (0), - tc_content_type_ (0) + tc_content_type_ (0), + tc_concrete_base_type_ (0) { } @@ -631,6 +654,49 @@ TC_Private_State::~TC_Private_State (void) } break; + case CORBA::tk_value: + { + // free up the member name list + if (this->tc_member_name_list_known_) + { + for (CORBA::ULong i = 0; + i < this->tc_member_count_; + i++) + { + CORBA::string_free (this->tc_member_name_list_ [i]); + this->tc_member_name_list_ [i] = 0; + } + + delete [] this->tc_member_name_list_; + this->tc_member_name_list_ = 0; + } + + // free up member type list + if (this->tc_member_type_list_known_) + { + for (CORBA::ULong i = 0; + i < this->tc_member_count_; + i++) + { + CORBA::release (this->tc_member_type_list_[i]); + } + + // Now free up the array. + delete [] this->tc_member_type_list_; + this->tc_member_type_list_ = 0; + } + this->tc_member_count_ = 0; + + // free up concrete base value typecode + if (this->tc_concrete_base_type_known_) + { + CORBA::release (this->tc_concrete_base_type_); + this->tc_concrete_base_type_ = 0; + this->tc_concrete_base_type_known_ = 0; + } + break; + } + default: // nothing to do break; @@ -792,6 +858,11 @@ CORBA_TypeCode::private_equal (CORBA::TypeCode_ptr tc, return this->private_equal_except (tc, equiv_only TAO_ENV_ARG_PARAMETER); + case CORBA::tk_value: + return this->private_equal_valuetype (tc, + equiv_only + TAO_ENV_ARG_PARAMETER); + case ~0u: // indirection { // indirection offset must be same @@ -1415,6 +1486,56 @@ CORBA_TypeCode::private_equal_except (CORBA::TypeCode_ptr tc, return 1; // success } + +//@@ boris: This version is incomplete... +CORBA::Boolean +CORBA_TypeCode::private_equal_valuetype ( + CORBA::TypeCode_ptr tc, + CORBA::Boolean equiv_only + TAO_ENV_ARG_DECL + ) const +{ + // compare the repoID and name, of which the name is optional as per GIOP + // spec. However, the repoID is mandatory. + const char *my_id = this->id (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + const char *tc_id = tc->id (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + if (!ACE_OS::strcmp (my_id, tc_id)) + { + // Equality of repoIDs is sufficient for equivalence. + if (equiv_only) + { + return 1; + } + // Name check is skipped by equivalent(). + else + { + // same repository IDs. Now check their names + const char *myname = this->name (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + const char *tcname = tc->name (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + if ((ACE_OS::strlen (myname) > 1) && + (ACE_OS::strlen (tcname) > 1)) + { + // both of them specify names, compare them + if (!ACE_OS::strcmp (myname, tcname)) + return 1; // success + else + return 0; // failed + } + return 1; // success + } + } + return 0; // failed +} + + // Return the type ID (RepositoryId) for the TypeCode; it may be empty. // // NOTE the string returned here is owned by the typecode!! @@ -1437,6 +1558,7 @@ CORBA_TypeCode::private_id (TAO_ENV_SINGLE_ARG_DECL) const case CORBA::tk_enum: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { // Double checked locking... ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, @@ -1476,6 +1598,7 @@ CORBA_TypeCode::private_name (TAO_ENV_SINGLE_ARG_DECL) const case CORBA::tk_enum: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { // Double checked locking... ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, @@ -1569,6 +1692,55 @@ CORBA_TypeCode::private_member_count (TAO_ENV_SINGLE_ARG_DECL) const || !stream.read_ulong (members)) // real member count ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + this->private_state_->tc_member_count_known_ = 1; + this->private_state_->tc_member_count_ = members; + return this->private_state_->tc_member_count_; + } + case CORBA::tk_value: + { + // Double checked locking... + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, + this->private_state_->mutex_, 0); + if (this->private_state_->tc_member_count_known_) + return this->private_state_->tc_member_count_; + + CORBA::ULong members; + // setup an encapsulation + TAO_InputCDR stream (this->buffer_+4, this->length_-4, + this->byte_order_); + + // skip rest of header (type ID, name, etc) and collect the + // number of value members + CORBA::ULong tc_kind_holder; + CORBA::TCKind tc_kind; + if (!stream.skip_string () // ID + || !stream.skip_string () // Name + || !stream.skip_ulong () // ValueModifier + || !stream.read_ulong(tc_kind_holder)) // Base's TCKind + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + tc_kind = ACE_static_cast(CORBA::TCKind, tc_kind_holder); + + + // The tc_kind can be either tk_null or tk_value. + // In the latter case we should skip encapsulation or + // indirection - whatever comes in. + CORBA::ULong encap_length; + if (tc_kind != CORBA::tk_null) + { + if (!stream.read_ulong(encap_length)) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + + if (encap_length != 0xffffffff) // check for indirection + { + if (!stream.skip_bytes (encap_length)) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + } + } + + // Now read member count. + if (!stream.read_ulong (members)) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + this->private_state_->tc_member_count_known_ = 1; this->private_state_->tc_member_count_ = members; return this->private_state_->tc_member_count_; @@ -1723,6 +1895,97 @@ CORBA_TypeCode::private_member_type (CORBA::ULong slot } ACE_NOTREACHED (break); + case CORBA::tk_value: + mcount = this->member_count (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN ((CORBA::TypeCode_ptr)0); + + { + // Double checked locking... + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, + this->private_state_->mutex_, 0); + if (this->private_state_->tc_member_type_list_known_) + if (slot < mcount) + return this->private_state_->tc_member_type_list_[slot]; + else + ACE_THROW_RETURN (CORBA::TypeCode::Bounds (), + CORBA::TypeCode::_nil ()); + + // the first time in. Precompute and store types of all members + + // Allocate a list to hold the member typecodes + ACE_NEW_THROW_EX (this->private_state_->tc_member_type_list_, + CORBA::TypeCode_ptr [mcount], + CORBA::NO_MEMORY ()); + + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + + // skip rest of header (type ID, name, etc) and collect the + // number of value members + CORBA::ULong tc_kind_holder; + CORBA::TCKind tc_kind; + if (!stream.skip_string () // ID + || !stream.skip_string () // Name + || !stream.skip_ulong () // ValueModifier + || !stream.read_ulong(tc_kind_holder)) // Base's TCKind + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + tc_kind = ACE_static_cast (CORBA::TCKind, tc_kind_holder); + + // The tc_kind can be either tk_null or tk_value. + // In the latter case we should skip encapsulation or + // indirection - whatever comes in. + CORBA::ULong encap_length; + if (tc_kind != CORBA::tk_null) + { + if (!stream.read_ulong(encap_length)) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + + if (encap_length != 0xffffffff) // check for indirection + { + if (!stream.skip_bytes (encap_length)) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + } + } + + // Now skip member count. + if (!stream.skip_ulong ()) + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + + // compute the typecodes for all the members and + // return the required one. + for (CORBA::ULong i = 0; i < mcount; i++) + // the ith entry will have the typecode of the ith guy + { + if (!stream.skip_string ()) // skip the name + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + + CORBA::TypeCode_ptr& member_type = + this->private_state_->tc_member_type_list_[i]; + CORBA_TypeCode::_tao_decode (this, + stream, + member_type + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::_nil ()); + + if (!stream.skip_ulong ()) // skip member visibility + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), + CORBA::TypeCode::_nil ()); + } + + this->private_state_->tc_member_type_list_known_ = 1; + + if (slot < mcount) + return this->private_state_->tc_member_type_list_[slot]; + else + ACE_THROW_RETURN (CORBA::TypeCode::Bounds (), + CORBA::TypeCode::_nil ()); + } + ACE_NOTREACHED (break;) + default: // bad kind ACE_THROW_RETURN (CORBA::TypeCode::BadKind (), @@ -2238,6 +2501,40 @@ CORBA_TypeCode::private_content_type (TAO_ENV_SINGLE_ARG_DECL) const ACE_NOTREACHED (return 0); } +CORBA::TypeCode_ptr +CORBA_TypeCode::private_concrete_base_type (TAO_ENV_SINGLE_ARG_DECL) const +{ + if (kind_ != CORBA::tk_value) + ACE_THROW_RETURN (CORBA::TypeCode::BadKind (), 0); + + // Double checked locking... + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, + this->private_state_->mutex_, 0); + if (this->private_state_->tc_concrete_base_type_known_) + return this->private_state_->tc_concrete_base_type_; + + // setup an encapsulation + TAO_InputCDR stream (this->buffer_+4, this->length_-4, + this->byte_order_); + + // skip rest of header (type ID, name, etc) and collect the + // number of value members + if (!stream.skip_string () // ID + || !stream.skip_string () // Name + || !stream.skip_ulong ()) // ValueModifier + ACE_THROW_RETURN (CORBA::BAD_TYPECODE (), 0); + + // retrieve the concrete base typecode + CORBA_TypeCode::_tao_decode (this, + stream, + this->private_state_->tc_concrete_base_type_ + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + this->private_state_->tc_concrete_base_type_known_ = 1; + return this->private_state_->tc_concrete_base_type_; +} + // **************************************************************** void @@ -2285,7 +2582,9 @@ CORBA_TypeCode::_tao_decode (const CORBA_TypeCode *parent, CORBA::_tc_ulonglong, CORBA::_tc_longdouble, CORBA::_tc_wchar, - 0 // CORBA::_tc_wstring ... unbounded + 0, // CORBA::_tc_wstring ... unbounded + 0, // CORBA_tk_fixed @@ boris: This is unsupported but I need next value + 0, // CORBA_tk_value }; if (kind < CORBA::TC_KIND_COUNT && tc_consts [kind] != 0) @@ -2451,6 +2750,7 @@ CORBA_TypeCode::_tao_decode (const CORBA_TypeCode *parent, case CORBA::tk_array: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { CORBA::ULong length; @@ -2638,6 +2938,7 @@ operator<< (TAO_OutputCDR& cdr, const CORBA::TypeCode *x) case CORBA::tk_array: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { if (!cdr.write_ulong (x->length_) || !cdr.write_octet_array ((CORBA::Octet*)x->buffer_, diff --git a/TAO/tao/Typecode.h b/TAO/tao/Typecode.h index 99610b73f20..747bc19547a 100644 --- a/TAO/tao/Typecode.h +++ b/TAO/tao/Typecode.h @@ -154,6 +154,13 @@ public: /// for tk_sequence, tk_array, and tk_alias. CORBA::TypeCode_ptr content_type (TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) const; + + /// Returns the concrete base type. Raises (BadKind); Useful + /// for tk_value only. + CORBA::TypeCode_ptr concrete_base_type ( + TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) const; + // = Creation/refcounting // These aren't really public APIs, but an IDL compiler will need to @@ -348,6 +355,10 @@ private: TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS ) const; + CORBA::TypeCode_ptr private_concrete_base_type ( + TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) const; + // = All the private helpers testing for equality of typecodes /// test equality for typecodes of objrefs @@ -400,6 +411,13 @@ private: CORBA::Boolean equiv_only TAO_ENV_ARG_DECL_WITH_DEFAULTS) const; + /// test equality for typecodes of exceptions + CORBA::Boolean private_equal_valuetype (CORBA::TypeCode_ptr tc, + CORBA::Boolean equiv_only + TAO_ENV_ARG_DECL_WITH_DEFAULTS) + const; + + /// if refcount reaches 0, free this typecode CORBA::ULong refcount_; @@ -475,6 +493,7 @@ public: CORBA::Boolean tc_length_known_; CORBA::Boolean tc_content_type_known_; CORBA::Boolean tc_discrim_pad_size_known_; + CORBA::Boolean tc_concrete_base_type_known_; // = These data members store the precomputed values char * tc_id_; @@ -487,6 +506,7 @@ public: CORBA::Long tc_default_index_used_; CORBA::ULong tc_length_; CORBA::TypeCode_ptr tc_content_type_; + CORBA::TypeCode_ptr tc_concrete_base_type_; }; /** diff --git a/TAO/tao/ValueBase.cpp b/TAO/tao/ValueBase.cpp index 1505f62ce21..dfbc4170e70 100644 --- a/TAO/tao/ValueBase.cpp +++ b/TAO/tao/ValueBase.cpp @@ -196,8 +196,19 @@ CORBA_ValueBase::_tao_unmarshal_pre (TAO_InputCDR &strm, return 0; } - factory = strm.orb_core ()->orb () - ->lookup_value_factory (repo_id_stream.in()); + TAO_ORB_Core *orb_core = strm.orb_core (); + if (orb_core == 0) + { + orb_core = TAO_ORB_Core_instance (); + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_WARNING, + "TAO (%P|%t) WARNING: extracting valuetype using " + "default ORB_Core\n")); + } + } + + factory = orb_core->orb ()->lookup_value_factory (repo_id_stream.in()); if (factory == 0) // %! except.! { ACE_DEBUG ((LM_ERROR, ACE_TEXT ("(%N:%l) OBV factory is null !!!\n"))); diff --git a/TAO/tao/append.cpp b/TAO/tao/append.cpp index 2df57c58492..e6ea5de14ac 100644 --- a/TAO/tao/append.cpp +++ b/TAO/tao/append.cpp @@ -23,6 +23,7 @@ #include "tao/CDR.h" #include "tao/Environment.h" #include "tao/Any.h" +#include "tao/ValueBase.h" #include "tao/debug.h" ACE_RCSID(tao, append, "$Id$") @@ -206,6 +207,7 @@ TAO_Marshal_TypeCode::append (CORBA::TypeCode_ptr, case CORBA::tk_array: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { // write the encapsulation i.e., octet sequence retval = @@ -1156,3 +1158,96 @@ TAO_Marshal_WString::append (CORBA::TypeCode_ptr, CORBA::COMPLETED_MAYBE), CORBA::TypeCode::TRAVERSE_STOP); } + +CORBA::TypeCode::traverse_status +TAO_Marshal_Value::append (CORBA::TypeCode_ptr tc, + TAO_InputCDR *src, + TAO_OutputCDR *dest + TAO_ENV_ARG_DECL) +{ + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + CORBA::TypeCode_var param; + + // Use the same method to append our base valuetype. + // To achive this we'll need to distinguish between + // first-time/nested appends so that we won't attempt to + // append rep_id several times. + // + if (nested_processing_ == 0) + { + nested_processing_ = 1; + + CORBA::ULong value_tag; + + if (!src->read_ulong (value_tag) || + !dest->write_ulong (value_tag)) + { + return CORBA::TypeCode::TRAVERSE_STOP; + } + + if (value_tag == 0) // Null value type pointer. + { + //We are done. + return retval; + } + else if (value_tag & TAO_OBV_GIOP_Flags::Type_info_single) + { + // Append repository id which is of type string. + dest->append_string (*src); + } + else + { + //@@ boris: VT CDR + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + + // Handle our base valuetype if any. + param = tc->concrete_base_type (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + if (param->kind () != CORBA::tk_null) + { + retval = this->append (param.in (), + src, + dest + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + if (retval != CORBA::TypeCode::TRAVERSE_CONTINUE) + { + return retval; + } + } + + // Number of fields in the struct. + int member_count = tc->member_count (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + for (int i = 0; + i < member_count && retval == CORBA::TypeCode::TRAVERSE_CONTINUE; + i++) + { + // get member type + param = tc->member_type (i TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + retval = + TAO_Marshal_Object::perform_append (param.in (), + src, + dest + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + } + + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO_Marshal_Value::append detected error\n"))); + + ACE_THROW_RETURN (CORBA::MARSHAL (TAO_DEFAULT_MINOR_CODE, + CORBA::COMPLETED_MAYBE), + CORBA::TypeCode::TRAVERSE_STOP); +} diff --git a/TAO/tao/skip.cpp b/TAO/tao/skip.cpp index 7790558531e..65ffe868d3f 100644 --- a/TAO/tao/skip.cpp +++ b/TAO/tao/skip.cpp @@ -23,6 +23,7 @@ #include "tao/CDR.h" #include "tao/Any.h" #include "tao/Environment.h" +#include "tao/ValueBase.h" #include "tao/debug.h" ACE_RCSID(tao, skip, "$Id$") @@ -163,6 +164,7 @@ TAO_Marshal_TypeCode::skip (CORBA::TypeCode_ptr, case CORBA::tk_array: case CORBA::tk_alias: case CORBA::tk_except: + case CORBA::tk_value: { CORBA::ULong length; @@ -896,3 +898,87 @@ TAO_Marshal_WString::skip (CORBA::TypeCode_ptr, CORBA::COMPLETED_MAYBE), CORBA::TypeCode::TRAVERSE_STOP); } + +CORBA::TypeCode::traverse_status +TAO_Marshal_Value::skip (CORBA::TypeCode_ptr tc, + TAO_InputCDR *stream + TAO_ENV_ARG_DECL) +{ + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + CORBA::TypeCode_var param; + + // Use the same method to skip over our base valuetype. + // To achive this we'll need to distinguish between + // first-time/nested skips so that we won't attempt to + // skip rep_id several times. + // + if (nested_processing_ == 0) + { + nested_processing_ = 1; + + CORBA::ULong value_tag; + + if (!stream->read_ulong (value_tag)) + { + return CORBA::TypeCode::TRAVERSE_STOP; + } + + if (value_tag == 0) // Null value type pointer. + { + //We are done. + return retval; + } + else if (value_tag & TAO_OBV_GIOP_Flags::Type_info_single) + { + // Skip a single repository id which is of type string. + stream->skip_string (); + } + else + { + //@@ boris: VT CDR + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + + // Handle our base valuetype if any. + param = tc->concrete_base_type (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + if (param->kind () != CORBA::tk_null) + { + retval = this->skip (param.in (), stream TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + if (retval != CORBA::TypeCode::TRAVERSE_CONTINUE) + { + return retval; + } + } + + // Number of fields in the valuetype. + int member_count = tc->member_count (TAO_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + for (int i = 0; i < member_count + && retval == CORBA::TypeCode::TRAVERSE_CONTINUE; + i++) + { + param = tc->member_type (i TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + + retval = TAO_Marshal_Object::perform_skip (param.in (), + stream + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::TypeCode::TRAVERSE_STOP); + } + + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO_Marshal_Value::skip detected error\n"))); + ACE_THROW_RETURN (CORBA::MARSHAL (TAO_DEFAULT_MINOR_CODE, + CORBA::COMPLETED_MAYBE), + CORBA::TypeCode::TRAVERSE_STOP); +} -- cgit v1.2.1