diff options
Diffstat (limited to 'TAO/tao/typecode.cpp')
-rw-r--r-- | TAO/tao/typecode.cpp | 1547 |
1 files changed, 0 insertions, 1547 deletions
diff --git a/TAO/tao/typecode.cpp b/TAO/tao/typecode.cpp deleted file mode 100644 index 9016bdc4ec2..00000000000 --- a/TAO/tao/typecode.cpp +++ /dev/null @@ -1,1547 +0,0 @@ -// @ (#)typecode.cpp 1.4 95/09/19 -// Copyright 1994-1995 by Sun Microsystems Inc. -// All Rights Reserved -// -// TYPECODE: basic implementation of TypeCodes -// -// Typecodes essentially consist of just the CDR octets that get -// marshaled and unmarshaled, and this code knows how to parse those -// octets and answer questions CORBA's TypeCode APIs require. -// -// NOTE: This isn't well tuned performance-wise. Given how much is -// variable (byte order, alignment) it's clear tuning has its limits -// with respect to CDR bytecode interpretation. -// -// THREADING NOTE: Typecodes are readonly data structures, and the -// only mutual exclusion relates to reference counting and -// construction. - -#include "tao/corba.h" - -// @@ This is a botch... -// @@ Can you please explain why? -size_t -calc_key_union_attributes (CDR *stream, - size_t &alignment, - size_t &size_with_pad, - CORBA::Environment &env); - -// Constructor for all other typecodes, including constants with -// non-empty parameter lists. See "corba.hh" for details. - -CORBA_TypeCode::CORBA_TypeCode (CORBA::TCKind kind, - CORBA::ULong length, - CORBA::Octet *buffer, - CORBA::Boolean orb_owns_tc, - CORBA::TypeCode_ptr parent) - : length_ (length), - // buffer_ (buffer), - kind_ (kind), - parent_ (parent), - refcount_ (1), - _delete_flag (CORBA::B_FALSE), - _orb_owns (orb_owns_tc), - private_state_ (new TC_Private_State (kind)) -{ - // The CDR code used to interpret TypeCodes requires in-memory - // alignments to match the "on-the-wire" alignments, simplifying - // algorithms used to marshal/unmarshal. - // - // However, it's often hard to get compilers (in particular) to - // generate data that's so aligned, since C++ doesn't provide - // primitives giving control at that low a level. Although there - // are ways to get that alignment which work in almost all cases, we - // need to ensure adequate alignment in _all_ cases. - // - // This code exists to ensure such alignment; since the constructor - // is intended only for use by an IDL compiler or ORB code, it's not - // currently a priority to ensure the allocated code is freed. - -#if 0 - if ((((ptr_arith_t) buffer) & 0x03) != 0) - { - ptr_arith_t temp; - - temp = (ptr_arith_t) ACE_OS::malloc (length + 4); - temp += 3; - temp &= ~0x03; - buffer_ = (CORBA::Octet *) temp; - - (void) ACE_OS::memcpy (buffer_, buffer, (size_t) length); - _orb_owns = CORBA::B_FALSE; // XXX may leak - } -#endif /* 0 */ - - // TAO comments: - - // For free standing typecodes, we choose to always make a copy of - // the buffer passed in. That way, our destructor doesn't have to - // deal with the case where the buffer was either allocated in which - // case it must be freed or the case where our buffer just points to - // the buffer passed in. - - if (!parent_) - { - // No parent. We are free standing. - ptr_arith_t temp; - - // Allocate a buffer to hold the encapsulated stream. We - // allocate extra space since we need a buffer that is aligned - // on a 4 byte word boundary. As a result, it is quite possible - // that we may start accessing the buffer from a position - // shifted to the right in the allocated buffer. As a result, - // during destruction, we do not want part of the allocated heap - // to remain dangling. Hence we save a handle to the original - // allocated buffer. - - non_aligned_buffer_ = new CORBA::Octet [length + 4]; - - temp = (ptr_arith_t) non_aligned_buffer_; - temp += 3; - temp &= ~0x03; - buffer_ = (CORBA::Octet *) temp; - - (void) ACE_OS::memcpy (buffer_, buffer, (size_t) length); - - // The ORB does not own this typecode. - _orb_owns = CORBA::B_FALSE; - } - else - { - // We are a child. We do not allocate a new buffer, but share it - // with our parent. We know that our parent's buffer was - // properly aligned. - buffer_ = buffer; - } -} - -// Destructor. For "indirected" typecodes and children, the typecode -// reuses the buffer owned by its parent. - -void -CORBA_TypeCode::operator delete (void* p) -{ - if (!((CORBA_TypeCode *) p)->_orb_owns) - ::delete p; -} - -CORBA_TypeCode::~CORBA_TypeCode (void) -{ - if (_orb_owns) - // we are constants, don't do anything - return; - else if (parent_) // check if we have a parent - { - // We have a parent which means that we were not directly - // created by IDL compiler generated code, but by the - // precomputation logic. We should delete ourselves and the - // subtree below us only if our parent was in the process of - // deleteing itself - if (parent_->_delete_flag) - // Parent is deleteing, so we have to go. - { - // Set our delete flag to TRUE so that our children (if any) - // will know that we have initiated our destruction - _delete_flag = CORBA::B_TRUE; - - // Delete any private state we have and thus free up the - // children. - delete private_state_; - - // We share the buffer octets of our parent. Hence we don't - // deallocate it. - buffer_ = 0; - } - // Else, somebody maliciously tried to delete us, but we won't - // get deleted. - } - else - { - // We are free standing (IDL compiler generated code) and are to - // be deleted. We indicate to our children that we are getting - // deleted. - _delete_flag = CORBA::B_TRUE; - - // Free up our children. - delete private_state_; - - // Delete the original, possibly nonaligned, buffer. - delete [] non_aligned_buffer_; - buffer_ = 0; - } -} - -// decreases the refcount and deletes when refcount reaches 0 - -void CORBA::release (CORBA::TypeCode_ptr tc) -{ - if (tc) - tc->Release (); -} - -// returns true if the typecode is NULL -CORBA::Boolean CORBA::is_nil (CORBA::TypeCode_ptr tc) -{ - return (CORBA::Boolean) tc == 0; -} - -// COM's IUnknown support - -// {A201E4C1-F258-11ce-9598-0000C07CA898} -DEFINE_GUID (IID_CORBA_TypeCode, -0xa201e4c1, 0xf258, 0x11ce, 0x95, 0x98, 0x0, 0x0, 0xc0, 0x7c, 0xa8, 0x98); - -// COM stuff -u_long __stdcall -CORBA_TypeCode::AddRef (void) -{ - ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, lock_, 0)); - - assert (this != 0); - - if (_orb_owns) - return refcount_; // this better be 1 - else if (parent_) - // we are owned by the parent - // return parent_->Addref (); - return refcount_; // 1 - else - return refcount_++; -} - -// COM stuff -u_long __stdcall -CORBA_TypeCode::Release (void) -{ - // This code is subtle since we need to make sure that we don't try - // to release the lock after we've deleted this... - ACE_MT (this->lock_.acquire ()); - - ACE_ASSERT (this != 0); - - u_long result; - - if (_orb_owns) - result = refcount_; // 1 - else if (parent_) - // return parent_->Release (); - result = refcount_; // 1 - else - { - result = --refcount_; - ACE_MT (this->lock_.release ()); - - if (result == 0) - delete this; - - return result; - } - - ACE_MT (this->lock_.release ()); - return result; -} - -// constructor for the private state -TC_Private_State::TC_Private_State (CORBA::TCKind kind) - : tc_kind_ (kind), - tc_id_known_ (CORBA::B_FALSE), - tc_name_known_ (CORBA::B_FALSE), - tc_member_count_known_ (CORBA::B_FALSE), - tc_member_type_list_known_ (CORBA::B_FALSE), - tc_member_label_list_known_ (CORBA::B_FALSE), - tc_discriminator_type_known_ (CORBA::B_FALSE), - tc_default_index_used_known_ (CORBA::B_FALSE), - tc_length_known_ (CORBA::B_FALSE), - tc_content_type_known_ (CORBA::B_FALSE), - tc_size_known_ (CORBA::B_FALSE), - tc_alignment_known_ (CORBA::B_FALSE), - tc_discrim_pad_size_known_ (CORBA::B_FALSE), - tc_id_ (0), - tc_name_ (0), - tc_member_count_ (0), - tc_member_type_list_ (0), - tc_member_label_list_ (0), - tc_discriminator_type_ (0), - tc_default_index_used_ (0), - tc_length_ (0), - tc_content_type_ (0), - tc_size_ (0), - tc_alignment_ (0), - tc_discrim_pad_size_ (0) -{ -} - -// destructor for the private state. In effect, this cleans up all the children -// and the subtree we hold. -TC_Private_State::~TC_Private_State (void) -{ - // the following two just point into the buffer. So we just make it point to NULL - tc_id_ = 0; - tc_name_ = 0; - - // determine what kind of children we may have and free the space accordingly - switch (tc_kind_) - { - case CORBA::tk_struct: - case CORBA::tk_except: - { - // free up member type list - for (CORBA::ULong i = 0; - i < tc_member_count_; - i++) - { - // free up the memory allocated for the typecode - delete tc_member_type_list_[i]; - } - // now free up the array - delete [] tc_member_type_list_; - tc_member_count_ = 0; - } - break; - case CORBA::tk_sequence: - case CORBA::tk_array: - case CORBA::tk_alias: - // delete the content type - delete tc_content_type_; - break; - case CORBA::tk_union: - { - // Free up type list, label list, and finally the discriminator - if (tc_member_type_list_known_) - { - for (CORBA::ULong i = 0; - i < tc_member_count_; - i++) - { - // free up the memory allocated for the typecode - delete tc_member_type_list_[i]; - } - // now free up the array - delete [] tc_member_type_list_; - } - if (tc_member_label_list_known_) - { - for (CORBA::ULong i = 0; - i < tc_member_count_; - i++) - { - // free up the label (Any_ptr) - delete tc_member_label_list_[i]; - } - delete [] tc_member_label_list_; - } - tc_member_count_ = 0; - // Discriminator must come last b/c it will be inside the Any - // in each element of the label list. - delete tc_discriminator_type_; - } - break; - default: - // nothing to do - break; - } -} - -// COM stuff -HRESULT __stdcall -CORBA_TypeCode::QueryInterface (REFIID riid, - void **ppv) -{ - *ppv = 0; - - if (IID_CORBA_TypeCode == riid || IID_IUnknown == riid) - *ppv = this; - - if (*ppv == 0) - return ResultFromScode (E_NOINTERFACE); - - (void) AddRef (); - return NOERROR; -} - -// This method is not yet implemented completely - low priority task -CORBA::Boolean -CORBA_TypeCode::private_equal (CORBA::TypeCode_ptr, - CORBA::Environment &) const -{ - // We come in here only if the typecode kinds of both are same - // Handle each complex typecode separately. - switch (kind_) - { - case CORBA::tk_null: - case CORBA::tk_void: - case CORBA::tk_short: - case CORBA::tk_ushort: - case CORBA::tk_long: - case CORBA::tk_ulong: - case CORBA::tk_float: - case CORBA::tk_double: - case CORBA::tk_longlong: - case CORBA::tk_longdouble: - case CORBA::tk_boolean: - case CORBA::tk_octet: - case CORBA::tk_char: - case CORBA::tk_wchar: - case CORBA::tk_TypeCode: - case CORBA::tk_Principal: - // all these are simple typecodes and the comparison is based solely on - // the kind_ field - return CORBA::B_TRUE; - case CORBA::tk_objref: - // return private_equal_objref (tc, env); - case CORBA::tk_struct: - // return private_equal_struct (tc, env); - case CORBA::tk_union: - // return private_equal_union (tc, env); - case CORBA::tk_enum: - // return private_equal_enum (tc, env); - case CORBA::tk_string: - // return private_equal_string (tc, env); - case CORBA::tk_wstring: - // return private_equal_string (tc, env); - case CORBA::tk_sequence: - // return private_equal_sequence (tc, env); - case CORBA::tk_array: - // return private_equal_array (tc, env); - case CORBA::tk_alias: - // return private_equal_alias (tc, env); - case CORBA::tk_except: - // return private_equal_except (tc, env); - default: - // Not implemented yet - return CORBA::B_TRUE; - } -} - -// Return the type ID (RepositoryId) for the TypeCode; it may be empty. -// -// NOTE the string returned here is owned by the typecode!! -// -// Valid only for objref, struct, union, enum, alias, and except. Raises -// BadKind exception for the rest of the cases. -TAO_CONST CORBA::String -CORBA_TypeCode::private_id (CORBA::Environment &env) const -{ - env.clear (); - - switch (kind_) - { - // These are all complex typecodes, which have as their first - // parameter (number zero) a repository/type ID string encoded - // per CDR rules. That means we can just return a pointer to - // that string directly! - - case CORBA::tk_objref: - case CORBA::tk_struct: - case CORBA::tk_union: - case CORBA::tk_enum: - case CORBA::tk_alias: - case CORBA::tk_except: - { - private_state_->tc_id_known_ = CORBA::B_TRUE; - private_state_->tc_id_ = (CORBA::String) (buffer_ - + 4 // skip byte order flag - // and padding - + 4); // skip (strlen + 1) - return private_state_->tc_id_; // this is OK because the strings in the - // CDR stream are NULL terminated - } - // No other typecodes ever have type IDs - default: - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -// return the name. The string is owned by the typecode -TAO_CONST CORBA::String -CORBA_TypeCode::private_name (CORBA::Environment &env) const -{ - env.clear (); - - switch (kind_) - { - // These are all complex typecodes, which have as their second - // parameter (number one) a name string encoded - // per CDR rules. That means we can just return a pointer to - // that string directly! - - case CORBA::tk_objref: - case CORBA::tk_struct: - case CORBA::tk_union: - case CORBA::tk_enum: - case CORBA::tk_alias: - case CORBA::tk_except: - { - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip the typecode ID - if (stream.skip_string ()) // ID - { - private_state_->tc_name_known_ = CORBA::B_TRUE; - - // skip past the length field. - private_state_->tc_name_ = (CORBA::String) (stream.next + CDR::LONG_SIZE); - - return private_state_->tc_name_; - } - else - { - env.exception (new CORBA::INTERNAL (CORBA::COMPLETED_NO)); - return (CORBA::String)0; - } - } - // No other typecodes ever have type IDs - default: - env.exception (new CORBA::TypeCode::BadKind ()); - return (CORBA::String)0; - } -} - -// Return the number of members defined by this typecode -// -// Applicable to struct, union, enum, alias, and except -// For the rest of the cases, raises the BadKind exception. - -CORBA::ULong -CORBA_TypeCode::private_member_count (CORBA::Environment &env) const -{ - env.clear (); - - switch (kind_) - { - case CORBA::tk_alias: - // tc_member_count_known_ = CORBA::B_TRUE; - //tc_member_count_ = 1; - return 1; - - case CORBA::tk_enum: - case CORBA::tk_except: - case CORBA::tk_struct: - { - CORBA::ULong members; - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip rest of header (type ID and name) and collect the - // number of struct members - if (!stream.skip_string () // ID - || !stream.skip_string () // struct name - || !stream.get_ulong (members)) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - private_state_->tc_member_count_known_ = CORBA::B_TRUE; - private_state_->tc_member_count_ = members; - return private_state_->tc_member_count_; - } - case CORBA::tk_union: - { - CORBA::ULong members; - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip rest of header (type ID, name, etc...) and collect the - // number of struct members - if (!stream.skip_string () // ID - || !stream.skip_string () // struct name - || !skip_typecode (stream) // discriminant TC - || !stream.get_ulong (members) // default used - || !stream.get_ulong (members)) // real member count - { - // this is a system exception indicating something is wrong with - // the typecode itself. - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - private_state_->tc_member_count_known_ = CORBA::B_TRUE; - private_state_->tc_member_count_ = members; - return private_state_->tc_member_count_; - } - default: - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -// Return the name for the nth member -// Applicable only to CORBA::tk_struct, CORBA::tk_union, and CORBA::tk_except -TAO_CONST CORBA::String -CORBA_TypeCode::member_name (CORBA::ULong, - CORBA::Environment &) const -{ - // not implemented - low priority task - return 0; -} - -// NOTE special calling convention for stream.decode () when we're -// potentially deencapsulating an indirected typecode: the "data2" -// value indicates that this typecode is the parent. See comments at -// stream.decode () for further details. -// -// Applicable only to struct, union, and except -// - -CORBA::TypeCode_ptr -CORBA_TypeCode::private_member_type (CORBA::ULong index, - CORBA::Environment &env) const -{ - CORBA::ULong temp, mcount; - - // Build the de-encapsulating CDR stream, bypassing the stringent - // alignment tests (we're a bit looser in what we need here, and we - // _know_ we're OK). Then skip the byte order code. - CDR stream; - CORBA::TypeCode_ptr tc = 0; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - switch (kind_) - { - case CORBA::tk_except: - case CORBA::tk_struct: // index from 0 - mcount = member_count (env); // clears env - if (env.exception () == 0) - { - // the first time in. Precompute and store types of all members - - // Allocate a list to hold the member typecodes - private_state_->tc_member_type_list_ = new CORBA::TypeCode_ptr [mcount]; - - if (private_state_->tc_member_type_list_) - { - // skip the id, name, and member_count part - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || !stream.get_ulong (temp)) // member count - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return (CORBA::TypeCode_ptr)0; - } - else - { - // 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 - || stream.decode (CORBA::_tc_TypeCode, - // the typecode will be retrieved - // at the i-th location. The decode - // routine will allocate the - // storage to hold a typecode - &private_state_->tc_member_type_list_[i], - this, // pass ourselves since we - // will be - // the parent. This is the - // case where the 3rd - // parameter is used in a - // decode method - env) != CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - } - - private_state_->tc_member_type_list_known_ = CORBA::B_TRUE; - - if (index < mcount) - return private_state_->tc_member_type_list_[index]; - else - { - env.exception (new CORBA::TypeCode::Bounds ()); - return (CORBA::TypeCode_ptr)0; - } - } - } - else // no memory for the member_list - { - env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO)); - return (CORBA::TypeCode_ptr)0; - } - } - else // out of bounds - { - env.exception (new CORBA::TypeCode::Bounds ()); - return (CORBA::TypeCode_ptr)0; - } - case CORBA::tk_union: // index from 0 - mcount = member_count (env); // clears env - if (env.exception () == 0) - { - // the first time in. Precompute and store types of all members - private_state_->tc_member_type_list_ = new CORBA::TypeCode_ptr [mcount]; - if (private_state_->tc_member_type_list_) - { - // skip the id, name, and discrimant type part - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || !skip_typecode (stream)) // skip typecode for discriminant - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return (CORBA::TypeCode_ptr)0; - } - else if (!stream.get_ulong (temp) // default used - || !stream.get_ulong (temp)) // member count - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else - { - CORBA::Long scratch; // always big enough because labels can - // only be of a few different types of - // which "long" has the largest size - - // get the typecode for the discriminator - tc = discriminator_type (env); - // 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.decode (tc, &scratch, this, env) // member label - != CORBA::TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string () // skip the name - || stream.decode (CORBA::_tc_TypeCode, // get the typecode - &private_state_->tc_member_type_list_[i], - this, - env) != - CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - } - private_state_->tc_member_type_list_known_ = CORBA::B_TRUE; - - if (index < mcount) - return private_state_->tc_member_type_list_[index]; - else - { - env.exception (new CORBA::TypeCode::Bounds ()); - return (CORBA::TypeCode_ptr)0; - } - } - } - else // no memory for the member_list - { - env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO)); - return (CORBA::TypeCode_ptr)0; - } - } - else // out of bounds - { - env.exception (new CORBA::TypeCode::Bounds ()); - return (CORBA::TypeCode_ptr)0; - } - - default: - // bad kind - env.exception (new CORBA::TypeCode::BadKind ()); - return (CORBA::TypeCode_ptr)0; - } -} - -// Return member labels for CORBA::tk_union typecodes. -CORBA::Any_ptr -CORBA_TypeCode::private_member_label (CORBA::ULong n, - CORBA::Environment &env) const -{ - env.clear (); - - // this function is only applicable to the CORBA::tk_union TC - if (kind_ == CORBA::tk_union) - { - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip ID and name, and then get the discriminant TC - CORBA::TypeCode_ptr tc = 0; - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || !skip_typecode (stream)) // skip discriminant typecode - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - // skip default used, and get member count - CORBA::ULong member_count; - - if (!stream.get_ulong (member_count) // default used - || !stream.get_ulong (member_count)) // member count - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - dmsg ("TypeCode::private_member_label -- error reading from stream"); - return 0; - } - - // member labels are of type Any. However, the actual types are - // restricted to simple types - private_state_->tc_member_label_list_ = new CORBA::Any_ptr [member_count]; - if (private_state_->tc_member_label_list_) - { - tc = discriminator_type (env); // retrieve the discriminator type as - // this decides what the label is - for (CORBA::ULong i = 0; i < member_count; i++) - { - // allocate buffer to hold the member label value - void *buf = new CORBA::Octet [tc->size (env)]; - if (stream.decode (tc, buf, this, env) - != CORBA::TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string () // member name - || !skip_typecode (stream)) // member type - { // member TC - dmsg1 ("TypeCode::private_member_label -- error getting typecode for member %d",i); - delete [] buf; - // XXXASG: free this list on error - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_member_label_list_[i] = new CORBA::Any (tc, - buf, CORBA::B_TRUE); - } - } - } - else - { - env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO)); - return 0; - } - - private_state_->tc_member_label_list_known_ = CORBA::B_TRUE; - - // If caller asked for the label for a nonexistent member, they get - // an error report! - if (n >= member_count) - { - env.exception (new CORBA::TypeCode::Bounds ()); - return 0; - } - else - return private_state_->tc_member_label_list_[n]; - } - else // wrong typecode - { - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -CORBA::TypeCode_ptr -CORBA_TypeCode::private_discriminator_type (CORBA::Environment &env) const -{ - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip ID and name, and then get the discriminant TC - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || stream.decode (CORBA::_tc_TypeCode, - &private_state_->tc_discriminator_type_, this, env) != - CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_discriminator_type_known_ = CORBA::B_TRUE; - return private_state_->tc_discriminator_type_; - } -} - -CORBA::Long -CORBA_TypeCode::private_default_index (CORBA::Environment &env) const -{ - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip ID and name, and then get the discriminant TC - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || !skip_typecode (stream) // skip discriminant - || !stream.get_long (private_state_->tc_default_index_used_)) - - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_default_index_used_known_ = CORBA::B_TRUE; - return private_state_->tc_default_index_used_; - } -} - -CORBA::Long -CORBA_TypeCode::privatelength_ (CORBA::Environment &env) const -{ - CDR stream; -#if defined(TAO_NEEDS_UNUSED_VARIABLES) - CORBA::TypeCode_ptr tc = 0; -#endif /* TAO_NEEDS_UNUSED_VARIABLES */ - - stream.setup_encapsulation (buffer_, (size_t) length_); - switch (kind_) - { - case CORBA::tk_sequence: - case CORBA::tk_array: - { - // skip the typecode of the element and get the bounds - if (!skip_typecode (stream) // skip typecode - || !stream.get_ulong (private_state_->tc_length_)) - { - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_length_known_ = CORBA::B_TRUE; - return private_state_->tc_length_; - } - case CORBA::tk_string: - case CORBA::tk_wstring: - { - if (stream.get_ulong (private_state_->tc_length_)) - { - private_state_->tc_length_known_ = CORBA::B_TRUE; - return private_state_->tc_length_; - } - else - { - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; - } - } - default: - env.exception (new CORBA::TypeCode::BadKind); - return 0; - } - } -} - -CORBA::TypeCode_ptr -CORBA_TypeCode::private_content_type (CORBA::Environment &env) const -{ - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - switch (kind_) - { - case CORBA::tk_sequence: - case CORBA::tk_array: - { - // retrieve the content type - if (stream.decode (CORBA::_tc_TypeCode, &private_state_->tc_content_type_, - this, env) != - CORBA::TypeCode::TRAVERSE_CONTINUE) // element type - { - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_content_type_known_ = CORBA::B_TRUE; - return private_state_->tc_content_type_; - } - case CORBA::tk_alias: - { - if (!stream.skip_string () // typeID - || !stream.skip_string () // name - || stream.decode (CORBA::_tc_TypeCode, - &private_state_->tc_content_type_, this, env) != - CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; - } - else - { - private_state_->tc_content_type_known_ = CORBA::B_TRUE; - return private_state_->tc_content_type_; - } - } - default: - env.exception (new CORBA::TypeCode::BadKind); - return 0; - } - } -} - -CORBA::ULong -CORBA_TypeCode::private_discrim_pad_size (CORBA::Environment &env) -{ - CDR stream; - size_t discrim_size, - overall_align; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - (void) calc_key_union_attributes (&stream, overall_align, discrim_size, env); - - if (env. exception () == 0) - { - private_state_->tc_discrim_pad_size_known_ = CORBA::B_TRUE; - private_state_->tc_discrim_pad_size_ = discrim_size; - return discrim_size; - } - else - return 0; -} -// ************ The following are deprecated **************** - -// say how many parameters this typecode has; normally a fixed number, -// some are variable length. -// -// NOTE: This refers to "real" parameters, not what shows up in the -// IFR spec !! That is, "hidden" parameters are counted here, this -// doesn't strictly comply with what CORBA says "param_count" -// provides. - -CORBA::ULong -CORBA_TypeCode::param_count (CORBA::Environment &env) const -{ - env.clear (); - - switch (kind_) - { - default: - return 0; - - case CORBA::tk_string: - case CORBA::tk_wstring: - return 1; - - case CORBA::tk_objref: - case CORBA::tk_sequence: - case CORBA::tk_array: - return 2; - - case CORBA::tk_alias: - return 3; - - case CORBA::tk_except: - case CORBA::tk_struct: - { - CORBA::ULong members; - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip rest of header (type ID and name) and collect the - // number of struct members - if (!stream.skip_string () // ID - || !stream.skip_string () // struct name - || !stream.get_ulong (members)) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - return 3 + 2 * members; - } - case CORBA::tk_enum: - { - CORBA::ULong members; - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip rest of header (type ID and name) and collect the - // number of struct members - if (!stream.skip_string () // ID - || !stream.skip_string () // typedef name - || !stream.get_ulong (members)) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - return 3 + members; - } - case CORBA::tk_union: - { - CORBA::ULong members; - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - // skip rest of header (type ID, name, etc...) and collect the - // number of struct members - if (!stream.skip_string () // ID - || !stream.skip_string () // struct name - || !skip_typecode (stream) // discriminant TC - || !stream.get_ulong (members) // default used - || !stream.get_ulong (members)) // real member count - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - return 5 + 3 * members; - } - } -} - - -// Internal hack, used until member_count () and length () are -// implemented. Doesn't support all the types that those routines -// support. - -CORBA::ULong -CORBA_TypeCode::ulong_param (CORBA::ULong n, - CORBA::Environment &env) const -{ - CORBA::ULong temp; - - temp = param_count (env); // clears env - if (env.exception ()) - return 0; - - if (temp < n) - { - env.exception (new CORBA::TypeCode::Bounds); - return 0; - } - - // Get parameters for non-empty typecodes; their parameter lists are - // encapsulated CDR (for complex ones) or inlined (for simple ones). - switch (kind_) - { - default: // most have no long params - break; - - // Array, sequence ... complex parameter lists - case CORBA::tk_array: // param 1 is an integer - case CORBA::tk_sequence: // ... identical content - { - if (n == 0) - break; - - // Build CDR stream for encapsulated params, and skip the - // typecode up front. - CDR stream; - - stream.setup_encapsulation (buffer_, (size_t) length_); - if (!skip_typecode (stream)) - { - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; - } - - // Then comes the "bounds" parameter. - if (!stream.get_ulong (temp)) - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return temp; - } - - // string, wstring ... simple parameter lists, containing just the - // string bounds (zero indicates unbounded). Stored specially - case CORBA::tk_string: - case CORBA::tk_wstring: - if (n != 0) - break; - return length_; - } - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; -} - -// Internal hack, used until member_type (), discriminator_type (), -// and content_type () are implemented. -// -// NOTE special calling convention for stream.decode () when we're -// potentially deencapsulating an indirected typecode: the "data2" -// value indicates that this typecode is the parent. See comments at -// stream.decode () for further details. - -CORBA::TypeCode_ptr -CORBA_TypeCode::typecode_param (CORBA::ULong n, - CORBA::Environment &env) const -{ - CORBA::ULong temp; - - temp = param_count (env); // clears env - if (env.exception ()) - return 0; - - if (temp < n) - { - env.exception (new CORBA::TypeCode::Bounds); - return 0; - } - - // Build the de-encapsulating CDR stream, bypassing the stringent - // alignment tests (we're a bit looser in what we need here, and we - // _know_ we're OK). Then skip the byte order code. - - CDR stream; - CORBA::TypeCode_ptr tc = 0; - - stream.setup_encapsulation (buffer_, (size_t) length_); - - switch (kind_) - { - default: // most have no tc params - break; - - case CORBA::tk_sequence: // param 0 is a tc - case CORBA::tk_array: - if (n != 0) - break; - if (stream.decode (CORBA::_tc_TypeCode, - &tc, - this, - env) != CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - return tc; - - case CORBA::tk_alias: // #1 is a tc - if (n != 2) - break; - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || stream.decode (CORBA::_tc_TypeCode, &tc, this, env) - != CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - return tc; - - case CORBA::tk_except: - case CORBA::tk_struct: // #5 and up are tc, index from 0 - if (n < 4 || n & 0x1) - { // tc is at odd number of param list - env.exception (new CORBA::TypeCode::Bounds); - return 0; - } - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || !stream.get_ulong (temp)) - { // member count - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else - { - temp = (n - 3) / 2; - - // skip member pairs to the one we want - for (CORBA::ULong i = 0; i < temp; i++) - { - // skip to the member being asked - if (!stream.skip_string () // member name - || !skip_typecode (stream)) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - } - - if (!stream.skip_string () - || stream.decode (CORBA::_tc_TypeCode, &tc, this, - env)!= CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - return tc; - } - - case CORBA::tk_union: // #6 and up are tc, index from 0 - if (n != 2 && (n < 7 || (n - 7) % 3)) - { - env.exception (new CORBA::TypeCode::Bounds); - return 0; - } - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || stream.decode (CORBA::_tc_TypeCode, - &tc, this, - env) != CORBA::TypeCode::TRAVERSE_CONTINUE) // TC - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - else if (!stream.get_ulong (temp) // default used - || !stream.get_ulong (temp)) // member count - { - tc->Release (); - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - - if (n == 2) - return tc; - - temp = (n - 7) / 3; - - // skip to the member requested - - CORBA::Long scratch; // always big enough - - for (CORBA::ULong i = 0; i < temp; i++) - { - if (stream.decode (tc, &scratch, this, env) // member label - != CORBA::TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string () // member name - || !skip_typecode (stream)) - { // member typecode - tc->Release (); - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - } - - // member label - if (stream.decode (tc, - &scratch, this, - env) != CORBA::TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string ()) // member name - { - tc->Release (); - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - tc->Release (); - - if (stream.decode (CORBA::_tc_TypeCode, - &tc, this, - env) != CORBA::TypeCode::TRAVERSE_CONTINUE) - { - env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); - return 0; - } - return tc; - } - - env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); - return 0; -} - -// skip a typecode encoding in a given CDR stream -// This is just a helper function -CORBA::Boolean -CORBA_TypeCode::skip_typecode (CDR &stream) -{ - CORBA::ULong kind; - CORBA::ULong temp; - - if (stream.get_ulong (kind) - && (kind < CORBA::TC_KIND_COUNT || kind == ~CORBA::ULong(0))) - { - - switch (kind) - { - // Most TypeCodes have empty parameter lists, nothing to skip - default: - break; - - // Some have single integer parameters, easy to skip. Some have - // preallocated constants that could be used. - case CORBA::tk_string: - case CORBA::tk_wstring: - case ~0: - return stream.get_ulong (temp); - - // The rest have "complex" parameter lists that are - // encoded as bulk octets ... just skip them. - case CORBA::tk_objref: - case CORBA::tk_struct: - case CORBA::tk_union: - case CORBA::tk_enum: - case CORBA::tk_sequence: - case CORBA::tk_array: - case CORBA::tk_alias: - case CORBA::tk_except: - return stream.get_ulong (temp) != CORBA::B_FALSE - && stream.skip_bytes (temp) != CORBA::B_FALSE; - } - - return CORBA::B_TRUE; - } - else - return CORBA::B_FALSE; -} - -// Constructor for CONSTANT typecodes with empty parameter lists. -// These are only created once, and those constants are shared. - -CORBA_TypeCode::CORBA_TypeCode (CORBA::TCKind kind) - : length_ (0), - buffer_ (0), - kind_ (kind), - parent_ (0), - refcount_ (1), - _delete_flag (CORBA::B_FALSE), - _orb_owns (CORBA::B_TRUE), - private_state_ (new TC_Private_State (kind)), - non_aligned_buffer_ (0) -{ -} - -// Return the i-th member typecode if it exists, else raise an -// exception. Possible exceptions are BadKind and Bounds. -// -// Applicable only to struct, union, and except - -CORBA::TypeCode_ptr -CORBA_TypeCode::member_type (CORBA::ULong index, - CORBA::Environment &env) const -{ - if (private_state_->tc_member_count_known_ - && private_state_->tc_member_type_list_known_) - { - if (index < private_state_->tc_member_count_) - return private_state_->tc_member_type_list_[index]; - else - { - env.exception (new CORBA::TypeCode::Bounds ()); - return 0; - } - } - else - return private_member_type (index, env); -} - -// Return the label of the i-th member. Applicable only to CORBA::tk_union -CORBA::Any_ptr -CORBA_TypeCode::member_label (CORBA::ULong index, - CORBA::Environment &env) const -{ - if (private_state_->tc_member_count_known_ - && private_state_->tc_member_label_list_known_) - { - if (index < private_state_->tc_member_count_) - return private_state_->tc_member_label_list_[index]; - else - { - env.exception (new CORBA::TypeCode::Bounds ()); - return 0; - } - } - else - return private_member_label (index, env); -} - -// only applicable to CORBA::tk_unions -CORBA::TypeCode_ptr -CORBA_TypeCode::discriminator_type (CORBA::Environment &env) const -{ - if (kind_ == CORBA::tk_union) - { - if (private_state_->tc_discriminator_type_known_) - return private_state_->tc_discriminator_type_; - else - return private_discriminator_type (env); - } - else - { - env.exception (new CORBA::TypeCode::BadKind ()); - return (CORBA::TypeCode_ptr)0; - } -} - -// only applicable to CORBA::tk_unions -CORBA::Long -CORBA_TypeCode::default_index (CORBA::Environment &env) const -{ - if (kind_ == CORBA::tk_union) - { - if (private_state_->tc_default_index_used_known_) - return private_state_->tc_default_index_used_; - else - return private_default_index (env); - } - else - { - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -// returns the length. Applicable only to string, sequence, and arrays -CORBA::ULong -CORBA_TypeCode::length (CORBA::Environment &env) const -{ - // a switch stmt, unfortunately, doesn't get inlined - if (kind_ == CORBA::tk_sequence - || kind_ == CORBA::tk_array - || kind_ == CORBA::tk_string - || kind_ == CORBA::tk_wstring) - { - if (private_state_->tc_length_known_) - return private_state_->tc_length_; - else - return privatelength_ (env); - } - else - { - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -// returns the length. Applicable only to string, sequence, and arrays -CORBA::TypeCode_ptr -CORBA_TypeCode::content_type (CORBA::Environment &env) const -{ - if (kind_ == CORBA::tk_sequence - || kind_ == CORBA::tk_array - || kind_ == CORBA::tk_alias) - { - if (private_state_->tc_content_type_known_) - return private_state_->tc_content_type_; - else - return private_content_type (env); - } - else - { - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} - -// compute the padded size of the discriminant -CORBA::ULong -CORBA_TypeCode::TAO_discrim_pad_size (CORBA::Environment &env) -{ - if (kind_ == CORBA::tk_union) - { - if (private_state_->tc_discrim_pad_size_known_) - return private_state_->tc_discrim_pad_size_; - else - return private_discrim_pad_size (env); - } - else - { - env.exception (new CORBA::TypeCode::BadKind ()); - return 0; - } -} |