diff options
Diffstat (limited to 'TAO/IIOP/lib/runtime/typecode.cpp')
-rw-r--r-- | TAO/IIOP/lib/runtime/typecode.cpp | 712 |
1 files changed, 0 insertions, 712 deletions
diff --git a/TAO/IIOP/lib/runtime/typecode.cpp b/TAO/IIOP/lib/runtime/typecode.cpp deleted file mode 100644 index c18806cf639..00000000000 --- a/TAO/IIOP/lib/runtime/typecode.cpp +++ /dev/null @@ -1,712 +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 <assert.h> -#include <limits.h> -#include <string.h> -#include <corba/orb.hh> - -#include "runtime/debug.hh" -#include "runtime/cdr.hh" -#include "runtime/thread.hh" - -#include <memory.h> -#include <sys/types.h> - -#include <initguid.h> - - -#ifdef _POSIX_THREADS -// -// If POSIX threads are available, set up lock covering refcounts. -// -static pthread_mutex_t refcnt_lock = PTHREAD_MUTEX_INITIALIZER; -#endif // _POSIX_THREADS - - -void -CORBA_release (CORBA_TypeCode_ptr tc) -{ - if (tc) - tc->Release (); -} - -CORBA_Boolean -CORBA_is_nil (CORBA_TypeCode_ptr tc) -{ - return (CORBA_Boolean) (tc == 0); -} - -// -// 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), - _orb_owns (CORBA_B_FALSE) -{ -} - - -// -// 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 -) : - _length (length), - _buffer (buffer), - _kind (kind), - _parent (0), - _refcount (1), - _orb_owns (orb_owns_tc) -{ - // - // 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 ((((ptr_arith_t)buffer) & 0x03) != 0) { - ptr_arith_t temp; - - temp = (ptr_arith_t) malloc (length + 4); - temp += 3; - temp &= ~0x03; - _buffer = (CORBA_Octet *) temp; - - (void) memcpy (_buffer, buffer, (size_t) length); - _orb_owns = CORBA_B_FALSE; // XXX may leak - } -} - - -// -// Destructor. For "indirected" typecodes, the typecode reuses the buffer -// owned by its parent, and so rather than deleting the buffer it just drops -// the parent's refcount. -// -CORBA_TypeCode::~CORBA_TypeCode () -{ - if (_parent) - _parent->Release (); - else if (_orb_owns) - delete _buffer; -} - - -// -// 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); - - -ULONG -__stdcall -CORBA_TypeCode::AddRef () -{ -#ifdef _POSIX_THREADS - Critical region (&refcnt_lock); -#endif - - return _refcount++; -} - -ULONG -__stdcall -CORBA_TypeCode::Release () -{ -#ifdef _POSIX_THREADS - Critical region (&refcnt_lock); -#endif - - assert (this != 0); - - if (--_refcount != 0) - return _refcount; - if (_orb_owns) - delete this; - return 0; -} - -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; -} - - -// -// just fetch the 'kind' field out of the typecode -// -CORBA_TCKind -CORBA_TypeCode::kind ( - CORBA_Environment &env -) const -{ - env.clear (); - return _kind; -} - - -// -// skip a typecode encoding in a given CDR stream -// -static CORBA_Boolean -skip_typecode( - CDR &stream -) -{ - CORBA_ULong kind; - CORBA_ULong temp; - - if (!stream.get_ulong (kind) - || kind >= TC_KIND_COUNT) - return CORBA_B_FALSE; - - switch (kind) { - // - // Most TypeCodes have empty parameter lists, nothing to skip - // - default: - break; - - // - // Some have single integer parameters, easy to skip. - // - // have preallocated constants that could be used. - // - case tk_string: - case 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 tk_objref: - case tk_struct: - case tk_union: - case tk_enum: - case tk_sequence: - case tk_array: - case tk_alias: - case tk_except: - return stream.get_ulong (temp) != CORBA_B_FALSE - && stream.skip_bytes (temp) != CORBA_B_FALSE; - } - - return CORBA_B_TRUE; -} - - -// -// Return member labels for tk_union typecodes. -// -CORBA_Any_ptr -CORBA_TypeCode::member_label ( - CORBA_ULong n, - CORBA_Environment &env -) const -{ - env.clear (); - - CDR stream; - - stream.setup_encapsulation(_buffer, (size_t)_length); - - // - // this function is only applicable to the tk_union TC - // - if (_kind != tk_union) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - - // - // 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 - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE) { - env.exception (new CORBA_BAD_TYPECODE (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) - ) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - - // - // If caller asked for the label for a nonexistent member, they - // get an error report! - // - if (n >= member_count) { - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); - return 0; - } - - // - // Get the n-th member label; they're all the same size and have - // no nested pointers, so we just overwrite each one with the - // enxt parameter. - // - void *buf = new CORBA_Octet [tc->size (env)]; - - if (env.exception () != 0) - return 0; - - for (CORBA_ULong i = 0; i <= n; i++) { - if (CDR::decoder (tc, buf, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string () // member name - || !skip_typecode (stream)) { // member TC - delete buf; - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - } - - // - // return the member label as an any - // - CORBA_Any *retval; - - retval = new CORBA_Any(tc, buf, CORBA_B_TRUE); - tc->Release (); - return retval; -} - - -// -// 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 tk_string: - case tk_wstring: - return 1; - - case tk_objref: - case tk_sequence: - case tk_array: - return 2; - - case tk_alias: - return 3; - - case tk_except: - case 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 (COMPLETED_NO)); - return 0; - } - - return 3 + 2 * members; - } - case 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 (COMPLETED_NO)); - return 0; - } - - return 3 + members; - } - case 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 (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_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 tk_array: // param 1 is an integer - case 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 (COMPLETED_NO)); - return 0; - } - - // - // Then comes the "bounds" parameter. - // - if (!stream.get_ulong (temp)) - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return temp; - } - - // - // string, wstring ... simple parameter lists, containing just - // the string bounds (zero indicates unbounded). Stored specially - // - case tk_string: - case tk_wstring: - if (n != 0) - break; - return _length; - } - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); - return 0; -} - - -// -// Internal hack, used until member_type(), discriminator_type(), -// and content_type() are implemented. -// -// NOTE special calling convention for CDR::decoder() when we're -// potentially deencapsulating an indirected typecode: the "data2" -// value indicates that this typecode is the parent. See comments -// at CDR::decoder() 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_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 tk_sequence: // param 0 is a tc - case tk_array: - if (n != 0) - break; - if (CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - return tc; - - case tk_alias: // #1 is a tc - if (n != 2) - break; - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - return tc; - - case tk_except: - case 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_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 (COMPLETED_NO)); - return 0; - } else { - CORBA_ULong i; - temp = (n - 3) / 2; - - // skip member pairs to the one we want - for (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 (COMPLETED_NO)); - return 0; - } - } - - if (!stream.skip_string () - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, - env)!= CORBA_TypeCode::TRAVERSE_CONTINUE) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - return tc; - } - - case tk_union: // #6 and up are tc, index from 0 - if (n != 2 && (n < 7 || (n - 7) % 3)) { - env.exception (new CORBA_Bounds); - return 0; - } - - if (!stream.skip_string () // type ID, hidden - || !stream.skip_string () // typedef name - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE // TC - ) { - env.exception (new CORBA_BAD_TYPECODE (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 (COMPLETED_NO)); - return 0; - } - - if (n == 2) - return tc; - - temp = (n - 7) / 3; - - // - // skip to the member requested - // - CORBA_ULong i; - CORBA_Long scratch; // always big enough - - for (i = 0; i < temp; i++) { - - if (CDR::decoder (tc, &scratch, this, &stream, 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 (COMPLETED_NO)); - return 0; - } - } - - if (CDR::decoder (tc, &scratch, this, &stream, env) // member label - != CORBA_TypeCode::TRAVERSE_CONTINUE - || !stream.skip_string () // member name - ) { - tc->Release (); - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - tc->Release (); - - if (CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); - return 0; - } - return tc; - } - - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); - return 0; -} - - -// -// Return the type ID (RepositoryId) for the TypeCode; it may be empty. -// -// NOTE the string returned here is owned by the typecode!! -// -CORBA_String -CORBA_TypeCode::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 tk_objref: - case tk_struct: - case tk_union: - case tk_enum: - case tk_alias: - case tk_except: - return (CORBA_String) (_buffer - + 4 // skip byte order flag and padding - + 4 // skip (strlen + 1) - ); - - // - // No other typecodes ever have type IDs - // - default: - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); - return 0; - } -} - |