summaryrefslogtreecommitdiff
path: root/TAO
diff options
context:
space:
mode:
Diffstat (limited to 'TAO')
-rw-r--r--TAO/tao/corbacom.cpp2
-rw-r--r--TAO/tao/except.cpp16
-rw-r--r--TAO/tao/interp.cpp428
-rw-r--r--TAO/tao/interp.h142
-rw-r--r--TAO/tao/typecode.cpp261
5 files changed, 475 insertions, 374 deletions
diff --git a/TAO/tao/corbacom.cpp b/TAO/tao/corbacom.cpp
index b71fb663fd4..f90beba63e5 100644
--- a/TAO/tao/corbacom.cpp
+++ b/TAO/tao/corbacom.cpp
@@ -153,7 +153,7 @@ CORBA::ORB_init (int &argc,
// @@ Andy, can you please make sure it's ok for the following 3
// initialization routines to be called multiple times?!
- TAO_Interp::init_table ();
+ TAO_IIOP_Interpreter::init_table ();
TAO_Marshal::initialize ();
TAO_Exception::init_standard_exceptions (env);
diff --git a/TAO/tao/except.cpp b/TAO/tao/except.cpp
index 992183f1765..a94ea1a74bc 100644
--- a/TAO/tao/except.cpp
+++ b/TAO/tao/except.cpp
@@ -15,6 +15,11 @@
#include "except.i"
#endif /* __ACE_INLINE__ */
+// Static initializers.
+CORBA::TypeCode_ptr TAO_Exception::sys_exceptions[NUM_SYS_EXCEPTIONS];
+
+CORBA::ExceptionList TAO_Exception::system_exceptions;
+
CORBA_Exception::CORBA_Exception (CORBA::TypeCode_ptr tc)
: type_ (tc),
refcount_ (0)
@@ -159,17 +164,6 @@ CORBA_SystemException::_narrow (CORBA_Exception* exception)
return 0;
}
-// Static initializers.
-
-const int TAO_Exception::NUM_SYS_EXCEPTIONS = 26;
-
-// Preallocated tc buffer.
-const int TAO_Exception::TC_BUFLEN = 160;
-
-CORBA::TypeCode_ptr TAO_Exception::sys_exceptions[NUM_SYS_EXCEPTIONS];
-
-CORBA::ExceptionList TAO_Exception::system_exceptions;
-
// Note that "buffer" holds the (unscoped) name originally, and is
// then overwritten.
diff --git a/TAO/tao/interp.cpp b/TAO/tao/interp.cpp
index 199f0b4e800..9a6aa612475 100644
--- a/TAO/tao/interp.cpp
+++ b/TAO/tao/interp.cpp
@@ -173,7 +173,7 @@ declare_entry (CORBA::WChar, tk_wchar);
declare_entry (CORBA::WString, tk_wstring);
void
-CORBA_TypeCode::init_table (void)
+TAO_IIOP_Interpreter::init_table (void)
{
setup_entry (CORBA::Short, tk_short);
setup_entry (CORBA::Long, tk_long);
@@ -211,34 +211,14 @@ CORBA_TypeCode::init_table (void)
#undef setup
-// Utility routines are used to manipulate CDR-encapsulated TypeCode
-// parameter lists, calculating the size and alignment of the data
-// type being described. The TCKind value has always been removed
-// from the CDR stream when these calculator routines get called.
-
-typedef size_t attribute_calculator (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env);
-
-static attribute_calculator calc_struct_attributes;
-static attribute_calculator calc_exception_attributes;
-static attribute_calculator calc_union_attributes;
-static attribute_calculator calc_alias_attributes;
-static attribute_calculator calc_array_attributes;
-
-// Other utility routines are used to skip the parameter lists when
-// they're not needed.
-
-typedef CORBA::Boolean param_skip_rtn (CDR *);
-
-static CORBA::Boolean
-skip_encapsulation (CDR *stream)
+CORBA::Boolean
+TAO_IIOP_Interpreter::skip_encapsulation (CDR *stream)
{
return stream->skip_string ();
}
-static CORBA::Boolean
-skip_long (CDR *stream)
+CORBA::Boolean
+TAO_IIOP_Interpreter::skip_long (CDR *stream)
{
CORBA::ULong scratch;
@@ -264,11 +244,11 @@ skip_long (CDR *stream)
// but it would need more than that to make it as speedy as struct
// traversal.
-static size_t
-calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
- CDR *original_stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
+ CDR *original_stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
// Get the "kind" ... if this is an indirection, this is a guess
// which will soon be updated.
@@ -343,9 +323,9 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
// lists that affect the size and alignment of "top level" memory
// needed to hold an instance of this type.
- if (TAO_Interp::table_[kind].calc != 0)
+ if (TAO_IIOP_Interpreter::table_[kind].calc != 0)
{
- assert (TAO_Interp::table_[kind].size == 0);
+ assert (TAO_IIOP_Interpreter::table_[kind].size == 0);
// Pull encapsulation length out of the stream.
if (stream->get_ulong (temp) == CORBA::B_FALSE)
@@ -372,7 +352,7 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
assert (temp <= UINT_MAX);
sub_encapsulation.setup_encapsulation (stream->buffer(), temp);
- size = TAO_Interp::table_[kind].calc (&sub_encapsulation, alignment, env);
+ size = TAO_IIOP_Interpreter::table_[kind].calc (&sub_encapsulation, alignment, env);
// Check for garbage at end of parameter lists, or other cases
// where parameters and the size allocated to them don't jive.
@@ -385,7 +365,7 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
}
return size;
}
- assert (TAO_Interp::table_[kind].size != 0); // fixed size data type
+ assert (TAO_IIOP_Interpreter::table_[kind].size != 0); // fixed size data type
// Reinitialize the TypeCode if requested; this consumes any
// TypeCode parameters in the stream. They only exist for TCKind
@@ -401,7 +381,7 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
switch (kind)
{
default:
- assert (TAO_Interp::table_[kind].skipper == 0);
+ assert (TAO_IIOP_Interpreter::table_[kind].skipper == 0);
break;
case CORBA::tk_string:
@@ -433,16 +413,16 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
// Otherwise, consume any parameters without stuffing them into
// a temporary TypeCode.
}
- else if (TAO_Interp::table_[kind].skipper != 0
- && TAO_Interp::table_[kind].skipper (stream) == CORBA::B_FALSE)
+ else if (TAO_IIOP_Interpreter::table_[kind].skipper != 0
+ && TAO_IIOP_Interpreter::table_[kind].skipper (stream) == CORBA::B_FALSE)
{
env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
return 0;
}
// Return statically known values.
- alignment = TAO_Interp::table_[kind].alignment_;
- return TAO_Interp::table_[kind].size;
+ alignment = TAO_IIOP_Interpreter::table_[kind].alignment_;
+ return TAO_IIOP_Interpreter::table_[kind].size;
}
// Given typecode bytes for a structure (or exception), figure out its
@@ -460,11 +440,11 @@ calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
// taught about compiler-specific representation of that additional
// "RTTI" data.
-static size_t
-calc_struct_and_except_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Boolean is_exception,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_struct_and_except_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Boolean is_exception,
+ CORBA::Environment &env)
{
CORBA::ULong members;
size_t size;
@@ -482,7 +462,7 @@ calc_struct_and_except_attributes (CDR *stream,
if (is_exception)
{
size = sizeof (CORBA::Exception);
- alignment = TAO_Interp::table_[CORBA::tk_TypeCode].alignment_;
+ alignment = TAO_IIOP_Interpreter::table_[CORBA::tk_TypeCode].alignment_;
}
else
{
@@ -546,10 +526,10 @@ calc_struct_and_except_attributes (CDR *stream,
// Calculate size and alignment for a structure.
-static size_t
-calc_struct_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_struct_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
return calc_struct_and_except_attributes (stream,
alignment,
@@ -559,10 +539,10 @@ calc_struct_attributes (CDR *stream,
// Calculate size and alignment for an exception.
-static size_t
-calc_exception_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_exception_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
return calc_struct_and_except_attributes (stream,
alignment,
@@ -577,14 +557,11 @@ calc_exception_attributes (CDR *stream,
// over the typecode: the inter-element padding changes depending on
// the strictest alignment required by _any_ arm of the union.
-// @@ Andy, this function is static because it's used in typecode.cpp.
-// Is there anyway to alleviate this coupling?!
-
size_t
-calc_key_union_attributes (CDR *stream,
- size_t &overall_alignment,
- size_t &discrim_size_with_pad,
- CORBA::Environment &env)
+TAO_IIOP_Interpreter::calc_key_union_attributes (CDR *stream,
+ size_t &overall_alignment,
+ size_t &discrim_size_with_pad,
+ CORBA::Environment &env)
{
CORBA::ULong members;
CORBA::ULong temp;
@@ -740,10 +717,10 @@ calc_key_union_attributes (CDR *stream,
// of the union have the same initial address (adequately aligned for
// any of the members).
-static size_t
-calc_union_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_union_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
size_t scratch;
@@ -752,10 +729,10 @@ calc_union_attributes (CDR *stream,
// Calculate size and alignment for a typedeffed type.
-static size_t
-calc_alias_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_alias_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
// Skip type ID and name in the parameter stream
@@ -775,10 +752,10 @@ calc_alias_attributes (CDR *stream,
// specify a multidimensional array ... such arrays are treated as
// nested single dimensional arrays.)
-static size_t
-calc_array_attributes (CDR *stream,
- size_t &alignment,
- CORBA::Environment &env)
+size_t
+TAO_IIOP_Interpreter::calc_array_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
{
size_t member_size;
CORBA::ULong member_count;
@@ -804,18 +781,18 @@ calc_array_attributes (CDR *stream,
// Visit each of the elements of a structure.
-static CORBA::TypeCode::traverse_status
-struct_traverse (CDR *stream,
- const void *value1,
- const void *value2,
- CORBA::TypeCode::traverse_status (_FAR *visit)
- (CORBA::TypeCode_ptr tc,
- const void *value1,
- const void *value2,
- void *context,
- CORBA::Environment &env),
- void *context,
- CORBA::Environment &env)
+CORBA::TypeCode::traverse_status
+TAO_IIOP_Interpreter::struct_traverse (CDR *stream,
+ const void *value1,
+ const void *nvalue2,
+ CORBA::TypeCode::traverse_status (_FAR *visit)
+ (CORBA::TypeCode_ptr tc,
+ const void *value1,
+ const void *value2,
+ void *context,
+ CORBA::Environment &env),
+ void *context,
+ CORBA::Environment &env)
{
// Skip over the type ID and type name in the parameters, then get
// the number of members.
@@ -890,13 +867,13 @@ struct_traverse (CDR *stream,
return retval;
}
-// cast the discriminant values to the right type and compare them.
+// Cast the discriminant values to the right type and compare them.
-static CORBA::Boolean
-match_value (CORBA::TCKind kind,
- CDR *tc_stream,
- const void *value,
- CORBA::Environment &env)
+CORBA::Boolean
+TAO_IIOP_Interpreter::match_value (CORBA::TCKind kind,
+ CDR *tc_stream,
+ const void *value,
+ CORBA::Environment &env)
{
CORBA::Boolean retval = CORBA::B_FALSE;
@@ -980,18 +957,18 @@ match_value (CORBA::TCKind kind,
// Visit the two elements of the union: the discrminant, and then any
// specific value as indicated by the discriminant of value1.
-static CORBA::TypeCode::traverse_status
-union_traverse (CDR *stream,
- const void *value1,
- const void *value2,
- CORBA::TypeCode::traverse_status (_FAR *visit)
- (CORBA::TypeCode_ptr tc,
- const void *value1,
- const void *value2,
- void *context,
- CORBA::Environment &env),
- void *context,
- CORBA::Environment &env)
+CORBA::TypeCode::traverse_status
+TAO_IIOP_Interpreter::union_traverse (CDR *stream,
+ const void *value1,
+ const void *value2,
+ CORBA::TypeCode::traverse_status (_FAR *visit)
+ (CORBA::TypeCode_ptr tc,
+ const void *value1,
+ const void *value2,
+ void *context,
+ CORBA::Environment &env),
+ void *context,
+ CORBA::Environment &env)
{
size_t discrim_size_with_pad;
@@ -1151,250 +1128,3 @@ union_traverse (CDR *stream,
return CORBA::TypeCode::TRAVERSE_CONTINUE;
}
-// For each node in "data", visit it. For singleton nodes that's all
-// but a NOP; for structs, unions, etc it's more interesting. The
-// visit routine can descend, if it chooses.
-//
-// NOTE: this does no memory allocation or deallocation except through
-// use of the stack. Or at least, it should do none -- if you find
-// that just traversing a data value allocates any memory, that's a
-// bug to fix!
-
-CORBA::TypeCode::traverse_status
-CORBA::TypeCode::traverse (const void *value1,
- const void *value2,
- CORBA::TypeCode::traverse_status (_FAR *visit)
- (CORBA::TypeCode_ptr tc,
- const void *value1,
- const void *value2,
- void *context,
- CORBA::Environment &env),
- void *context,
- CORBA::Environment &env)
-{
- env.clear ();
-
- // Quickly accomodate the bulk of cases, which are just (tail) calls
- // to the visit() routine. We take advantage of the fact that these
- // are largely in a convenient numeric range to work around poor
- // optimization of "switch" code in some compilers. This
- // improvement has in some cases been more than 5% faster
- // (significant).
- //
- // NOTE: if for some reason the constants in the protocol spec
- // (including Appendix A) change, this logic may need to be verified
- // again. Luckily, changing protocol constants is quite rare; they
- // normally just get added to (at the end).
- //
- if (kind_ <= CORBA::tk_objref
- || (CORBA::tk_longlong <= kind_ && kind_ <= CORBA::tk_wstring))
- return visit (this, value1, value2, context, env);
-
- // Handle the cases that aren't in convenient numeric ranges.
-
- traverse_status retval;
-
- switch (kind_)
- {
- case CORBA::tk_string:
- case CORBA::tk_enum:
- return visit (this, value1, value2, context, env);
-
- // Typedefs just add a delay, while we skip the typedef ID
- // and name ...
-
- case CORBA::tk_alias:
- {
- CORBA::TypeCode_ptr tcp;
- CORBA::Environment env2;
-
- // XXX rework for efficiency, this doesn't need to allocate
- // memory during the traversal!
-
- tcp = typecode_param (2, env);
- if (env.exception () != 0)
- return TRAVERSE_STOP;
-
- retval = tcp->traverse (value1, value2, visit, context, env);
-
- tcp->Release ();
- }
- return retval;
-
- // Exceptions in-memory are structures, except that there are data
- // members "hidden" in front: vtable, typecode, refcount. We skip
- // them, and allow the traversal code to account for the internal
- // padding before the other elements of the exception.
- //
- // NOTE: see header comment re treatment of these values as "real"
- // C++ exceptions. C++ RTTI data might need to be skipped. Also,
- // see the comments in unmarshaling code: hard to throw these
- // values.
- //
- // Not enough of the exception runtime is public for binary
- // standards to exist for C++ exceptions yet. Compiler-specific
- // code will need to handle examining, unmarshaling, and throwing
- // of CORBA exceptions (in C++ environments) for some time.
- case CORBA::tk_except:
- value1 = sizeof (CORBA::Exception) + (char *) value1;
- value2 = sizeof (CORBA::Exception) + (char *) value2;
- // FALLTHROUGH
-
- case CORBA::tk_struct:
- // XXX for OLE Automation, we'll probably need BOTH exceptions
- // and structs to inherit IUnknown, hence we'll need to be
- // skipping the vtable pointer ...
- {
- // Create the sub-encapsulation stream that holds the
- // parameters for the typecode.
-
- CDR stream;
-
- stream.setup_encapsulation (buffer_, (size_t) length_);
-
- return struct_traverse (&stream, value1, value2,
- visit, context, env);
- }
-
- case CORBA::tk_union:
- {
- // visit the discriminant, then search the typecode for the
- // relevant union member and then visit that member.
- CDR stream;
-
- stream.setup_encapsulation (buffer_, (size_t) length_);
-
- return union_traverse (&stream, value1, value2,
- visit, context, env);
- }
-
- // Sequences are just arrays with bound determined at runtime,
- // rather than compile time. Multidimensional arrays are nested
- // C-style: the leftmost dimension in the IDL definition is
- // "outermost", etc.
- {
- CORBA::TypeCode_ptr tc2;
- size_t size;
- CORBA::ULong bounds;
- CORBA::OctetSeq *seq;
-
- case CORBA::tk_sequence:
- // Find out how many elements there are, and adjust the data
- // pointers to point to those elements rather than to the
- // sequence itself.
- seq = (CORBA::OctetSeq *)value1;
-
- bounds = seq->length;
- value1 = seq->buffer;
-
- if (value2)
- {
- seq = (CORBA::OctetSeq *)value2;
- value2 = seq->buffer;
- }
- goto shared_seq_array_code;
-
- case CORBA::tk_array:
- // Array bounds are in the typecode itself.
- bounds = ulong_param (1, env);
- if (env.exception () != 0)
- return TRAVERSE_STOP;
-
- shared_seq_array_code:
- // Find element's type, and size ...
- tc2 = typecode_param (0, env);
- if (env.exception () != 0)
- return TRAVERSE_STOP;
-
- size = tc2->size (env);
- if (env.exception () != 0)
- return TRAVERSE_STOP;
-
- // ... then visit the elements in order.
- //
- // NOTE: for last element, could turn visit() call into
- // something subject to compiler's tail call optimization and
- // thus save a stack frame
- while (bounds--)
- {
- if (visit (tc2, value1, value2, context, env) == TRAVERSE_STOP)
- return TRAVERSE_STOP;
-
- value1 = size + (char *) value1;
- value2 = size + (char *) value2;
- }
- CORBA::release (tc2);
- env.clear ();
- }
- return TRAVERSE_CONTINUE;
-
- // case ~0: // indirection, illegal at top level
- default: // invalid/illegal
- break;
- } // end switch on typecode "kind"
-
- env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
- return TRAVERSE_STOP;
-}
-
-// Tell user the size of an instance of the data type described by
-// this typecode ... typically used to allocate memory.
-
-size_t
-CORBA::TypeCode::private_size (CORBA::Environment &env)
-{
- if (kind_ >= CORBA::TC_KIND_COUNT)
- {
- env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
- return 0;
- }
- env.clear ();
-
- if (TAO_Interp::table_[kind_].calc == 0)
- {
- private_state_->tc_size_known_ = CORBA::B_TRUE;
- private_state_->tc_size_ = TAO_Interp::table_[kind_].size;
- return private_state_->tc_size_;
- }
-
- size_t alignment;
- CDR stream;
-
- stream.setup_encapsulation (buffer_, (size_t) length_);
-
- private_state_->tc_size_known_ = CORBA::B_TRUE;
- private_state_->tc_size_ = TAO_Interp::table_[kind_].calc (&stream, alignment, env);
- return private_state_->tc_size_;
-}
-
-// Tell user the alignment restriction for the data type described by
-// an instance of this data type. Rarely used; provided for
-// completeness.
-
-size_t
-CORBA::TypeCode::private_alignment (CORBA::Environment &env)
-{
- if (kind_ >= CORBA::TC_KIND_COUNT)
- {
- env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
- return 0;
- }
- env.clear ();
-
- if (TAO_Interp::table_[kind_].calc == 0)
- {
- private_state_->tc_alignment_known_ = CORBA::B_TRUE;
- private_state_->tc_alignment_ = TAO_Interp::table_[kind_].alignment;
- return private_state_->tc_alignment_;
- }
-
- size_t alignment;
- CDR stream;
-
- stream.setup_encapsulation (buffer_, (size_t) length_);
-
- (void) TAO_Interp::table_[kind_].calc (&stream, alignment, env);
- private_state_->tc_alignment_known_ = CORBA::B_TRUE;
- private_state_->tc_alignment_ = alignment;
- return alignment;
-}
diff --git a/TAO/tao/interp.h b/TAO/tao/interp.h
index c56e41a73a1..769cc1547a5 100644
--- a/TAO/tao/interp.h
+++ b/TAO/tao/interp.h
@@ -20,7 +20,13 @@
#if !defined (TAO_INTERP_H)
#define TAO_INTERP_H
-class TAO_Export TAO_Interp
+// Useful typedefs.
+typedef size_t TAO_attribute_calculator (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+typedef CORBA::Boolean TAO_param_skip_rtn (CDR *);
+
+class TAO_Export TAO_IIOP_Interpreter
{
// = TITLE
// TAO's CORBA TypeCode interpreter, which traverses GIOP/IIOP
@@ -95,15 +101,143 @@ public:
static void init_table (void);
// Initialize TAO's TypeCode table.
+ static size_t calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
+ CDR *original_stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // For a given typecode, figure out its size and alignment needs.
+ // This version is used mostly when traversing other typecodes, and
+ // follows these rules:
+ //
+ // - Some typecodes are illegal (can't be nested inside others);
+ // - Indirections are allowed;
+ // - The whole typecode (including TCKind enum) is in the stream
+ //
+ // When the routine returns, the stream has skipped this TypeCode.
+ //
+ // "size" is returned, "alignment" is an 'out' parameter. If it is
+ // non-null, "tc" is initialized to hold the contents of the TypeCode;
+ // it depends on the contents of the original stream to be valid.
+ //
+ // XXX explore splitting apart returning the size/alignment data and
+ // the TypeCode initialization; union traversal would benefit a bit,
+ // but it would need more than that to make it as speedy as struct
+ // traversal.
+
+ // = Static visitor methods.
+
+ // These methods manipulate CDR-encapsulated TypeCode parameter
+ // lists, calculating the size and alignment of the data type being
+ // described. The TCKind value has always been removed from the CDR
+ // stream when these calculator routines get called.
+
+ static size_t calc_struct_and_except_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Boolean is_exception,
+ CORBA::Environment &env);
+ // Given typecode bytes for a structure (or exception), figure out
+ // its alignment and size; return size, alignment is an 'out'
+ // parameter. Only "CORBA::tk_struct" (or "CORBA::tk_except") has
+ // been taken out of the stream parameter holding the bytes.
+ //
+ // We use a one-pass algorithm, calculating size and inter-element
+ // padding while recording the strongest alignment restriction.
+ // Then we correct the size to account for tail-padding.
+ //
+ // This routine recognizes that exceptions are just structs with
+ // some additional information. Different environments may differ
+ // in what that additional information is, so this routine may need
+ // to be taught about compiler-specific representation of that
+ // additional "RTTI" data.
+
+ static size_t calc_struct_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment for a structure.
+
+
+ static size_t calc_exception_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment for an exception.
+
+
+ static size_t calc_union_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment for a CORBA discriminated union.
+ //
+ // Note that this is really a two-element structure. The first
+ // element is the discriminator; the second is the value. All normal
+ // structure padding/alignment rules apply. In particular, all arms
+ // of the union have the same initial address (adequately aligned for
+ // any of the members).
+
+
+ static size_t calc_alias_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment for a typedeffed type.
+
+ static size_t calc_array_attributes (CDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment of an array. (All such arrays are
+ // described as single dimensional, even though the IDL definition
+ // may specify a multidimensional array ... such arrays are treated
+ // as nested single dimensional arrays.)
+
+ static CORBA::TypeCode::traverse_status
+ struct_traverse (CDR *stream,
+ const void *value1,
+ const void *value2,
+ CORBA::TypeCode::traverse_status (_FAR *visit)
+ (CORBA::TypeCode_ptr tc,
+ const void *value1,
+ const void *value2,
+ void *context,
+ CORBA::Environment &env),
+ void *context,
+ CORBA::Environment &env);
+ // Visit each of the elements of a structure.
+
+ static CORBA::Boolean match_value (CORBA::TCKind kind,
+ CDR *tc_stream,
+ const void *value,
+ CORBA::Environment &env);
+ // Cast the discriminant values to the right type and compare them.
+
+ static CORBA::TypeCode::traverse_status
+ union_traverse (CDR *stream,
+ const void *value1,
+ const void *value2,
+ CORBA::TypeCode::traverse_status (_FAR *visit)
+ (CORBA::TypeCode_ptr tc,
+ const void *value1,
+ const void *value2,
+ void *context,
+ CORBA::Environment &env),
+ void *context,
+ CORBA::Environment &env);
+ // Visit the two elements of the union: the discrminant, and then
+ // any specific value as indicated by the discriminant of value1.
+
+ static size_t
+ calc_key_union_attributes (CDR *stream,
+ size_t &overall_alignment,
+ size_t &discrim_size_with_pad,
+ CORBA::Environment &env);
+ // = Utility routines that skip unneeded parameter lists.
+ static CORBA::Boolean skip_encapsulation (CDR *stream);
+ static CORBA::Boolean skip_long (CDR *stream);
-private:
struct Table_Element
{
size_t size_;
size_t alignment_;
- attribute_calculator *calc_;
- param_skip_rtn *skipper_;
+ TAO_attribute_calculator *calc_;
+ TAO_param_skip_rtn *skipper_;
};
static Table_Element table_[CORBA::TC_KIND_COUNT];
diff --git a/TAO/tao/typecode.cpp b/TAO/tao/typecode.cpp
index 1d7e0d5347b..6a7e2c8434e 100644
--- a/TAO/tao/typecode.cpp
+++ b/TAO/tao/typecode.cpp
@@ -19,14 +19,6 @@
#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 CONSTANT typecodes with empty parameter lists.
// These are only created once, and those constants are shared.
@@ -1890,7 +1882,10 @@ CORBA_TypeCode::private_discrim_pad_size (CORBA::Environment &env)
stream.setup_encapsulation (this->buffer_, (size_t) this->length_);
- (void) calc_key_union_attributes (&stream, overall_align, discrim_size, env);
+ (void) TAO_IIOP_Interpeter::calc_key_union_attributes (&stream,
+ overall_align,
+ discrim_size,
+ env);
if (env. exception () == 0)
{
@@ -2237,3 +2232,251 @@ CORBA_TypeCode::typecode_param (CORBA::ULong n,
env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO));
return 0;
}
+
+// For each node in "data", visit it. For singleton nodes that's all
+// but a NOP; for structs, unions, etc it's more interesting. The
+// visit routine can descend, if it chooses.
+//
+// NOTE: this does no memory allocation or deallocation except through
+// use of the stack. Or at least, it should do none -- if you find
+// that just traversing a data value allocates any memory, that's a
+// bug to fix!
+
+CORBA::TypeCode::traverse_status
+CORBA::TypeCode::traverse (const void *value1,
+ const void *value2,
+ CORBA::TypeCode::traverse_status (_FAR *visit)
+ (CORBA::TypeCode_ptr tc,
+ const void *value1,
+ const void *value2,
+ void *context,
+ CORBA::Environment &env),
+ void *context,
+ CORBA::Environment &env)
+{
+ env.clear ();
+
+ // Quickly accomodate the bulk of cases, which are just (tail) calls
+ // to the visit() routine. We take advantage of the fact that these
+ // are largely in a convenient numeric range to work around poor
+ // optimization of "switch" code in some compilers. This
+ // improvement has in some cases been more than 5% faster
+ // (significant).
+ //
+ // NOTE: if for some reason the constants in the protocol spec
+ // (including Appendix A) change, this logic may need to be verified
+ // again. Luckily, changing protocol constants is quite rare; they
+ // normally just get added to (at the end).
+ //
+ if (kind_ <= CORBA::tk_objref
+ || (CORBA::tk_longlong <= kind_ && kind_ <= CORBA::tk_wstring))
+ return visit (this, value1, value2, context, env);
+
+ // Handle the cases that aren't in convenient numeric ranges.
+
+ traverse_status retval;
+
+ switch (kind_)
+ {
+ case CORBA::tk_string:
+ case CORBA::tk_enum:
+ return visit (this, value1, value2, context, env);
+
+ // Typedefs just add a delay, while we skip the typedef ID
+ // and name ...
+
+ case CORBA::tk_alias:
+ {
+ CORBA::TypeCode_ptr tcp;
+ CORBA::Environment env2;
+
+ // XXX rework for efficiency, this doesn't need to allocate
+ // memory during the traversal!
+
+ tcp = typecode_param (2, env);
+ if (env.exception () != 0)
+ return TRAVERSE_STOP;
+
+ retval = tcp->traverse (value1, value2, visit, context, env);
+
+ tcp->Release ();
+ }
+ return retval;
+
+ // Exceptions in-memory are structures, except that there are data
+ // members "hidden" in front: vtable, typecode, refcount. We skip
+ // them, and allow the traversal code to account for the internal
+ // padding before the other elements of the exception.
+ //
+ // NOTE: see header comment re treatment of these values as "real"
+ // C++ exceptions. C++ RTTI data might need to be skipped. Also,
+ // see the comments in unmarshaling code: hard to throw these
+ // values.
+ //
+ // Not enough of the exception runtime is public for binary
+ // standards to exist for C++ exceptions yet. Compiler-specific
+ // code will need to handle examining, unmarshaling, and throwing
+ // of CORBA exceptions (in C++ environments) for some time.
+ case CORBA::tk_except:
+ value1 = sizeof (CORBA::Exception) + (char *) value1;
+ value2 = sizeof (CORBA::Exception) + (char *) value2;
+ // FALLTHROUGH
+
+ case CORBA::tk_struct:
+ // XXX for OLE Automation, we'll probably need BOTH exceptions
+ // and structs to inherit IUnknown, hence we'll need to be
+ // skipping the vtable pointer ...
+ {
+ // Create the sub-encapsulation stream that holds the
+ // parameters for the typecode.
+
+ CDR stream;
+
+ stream.setup_encapsulation (buffer_, (size_t) length_);
+
+ return struct_traverse (&stream, value1, value2,
+ visit, context, env);
+ }
+
+ case CORBA::tk_union:
+ {
+ // visit the discriminant, then search the typecode for the
+ // relevant union member and then visit that member.
+ CDR stream;
+
+ stream.setup_encapsulation (buffer_, (size_t) length_);
+
+ return union_traverse (&stream, value1, value2,
+ visit, context, env);
+ }
+
+ // Sequences are just arrays with bound determined at runtime,
+ // rather than compile time. Multidimensional arrays are nested
+ // C-style: the leftmost dimension in the IDL definition is
+ // "outermost", etc.
+ {
+ CORBA::TypeCode_ptr tc2;
+ size_t size;
+ CORBA::ULong bounds;
+ CORBA::OctetSeq *seq;
+
+ case CORBA::tk_sequence:
+ // Find out how many elements there are, and adjust the data
+ // pointers to point to those elements rather than to the
+ // sequence itself.
+ seq = (CORBA::OctetSeq *)value1;
+
+ bounds = seq->length;
+ value1 = seq->buffer;
+
+ if (value2)
+ {
+ seq = (CORBA::OctetSeq *)value2;
+ value2 = seq->buffer;
+ }
+ goto shared_seq_array_code;
+
+ case CORBA::tk_array:
+ // Array bounds are in the typecode itself.
+ bounds = ulong_param (1, env);
+ if (env.exception () != 0)
+ return TRAVERSE_STOP;
+
+ shared_seq_array_code:
+ // Find element's type, and size ...
+ tc2 = typecode_param (0, env);
+ if (env.exception () != 0)
+ return TRAVERSE_STOP;
+
+ size = tc2->size (env);
+ if (env.exception () != 0)
+ return TRAVERSE_STOP;
+
+ // ... then visit the elements in order.
+ //
+ // NOTE: for last element, could turn visit() call into
+ // something subject to compiler's tail call optimization and
+ // thus save a stack frame
+ while (bounds--)
+ {
+ if (visit (tc2, value1, value2, context, env) == TRAVERSE_STOP)
+ return TRAVERSE_STOP;
+
+ value1 = size + (char *) value1;
+ value2 = size + (char *) value2;
+ }
+ CORBA::release (tc2);
+ env.clear ();
+ }
+ return TRAVERSE_CONTINUE;
+
+ // case ~0: // indirection, illegal at top level
+ default: // invalid/illegal
+ break;
+ } // end switch on typecode "kind"
+
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return TRAVERSE_STOP;
+}
+
+// Tell user the size of an instance of the data type described by
+// this typecode ... typically used to allocate memory.
+
+size_t
+CORBA::TypeCode::private_size (CORBA::Environment &env)
+{
+ if (kind_ >= CORBA::TC_KIND_COUNT)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+ env.clear ();
+
+ if (TAO_IIOP_Interpreter::table_[kind_].calc == 0)
+ {
+ private_state_->tc_size_known_ = CORBA::B_TRUE;
+ private_state_->tc_size_ = TAO_IIOP_Interpreter::table_[kind_].size;
+ return private_state_->tc_size_;
+ }
+
+ size_t alignment;
+ CDR stream;
+
+ stream.setup_encapsulation (buffer_, (size_t) length_);
+
+ private_state_->tc_size_known_ = CORBA::B_TRUE;
+ private_state_->tc_size_ = TAO_IIOP_Interpreter::table_[kind_].calc (&stream, alignment, env);
+ return private_state_->tc_size_;
+}
+
+// Tell user the alignment restriction for the data type described by
+// an instance of this data type. Rarely used; provided for
+// completeness.
+
+size_t
+CORBA::TypeCode::private_alignment (CORBA::Environment &env)
+{
+ if (kind_ >= CORBA::TC_KIND_COUNT)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+ env.clear ();
+
+ if (TAO_IIOP_Interpreter::table_[kind_].calc == 0)
+ {
+ private_state_->tc_alignment_known_ = CORBA::B_TRUE;
+ private_state_->tc_alignment_ = TAO_IIOP_Interpreter::table_[kind_].alignment;
+ return private_state_->tc_alignment_;
+ }
+
+ size_t alignment;
+ CDR stream;
+
+ stream.setup_encapsulation (buffer_, (size_t) length_);
+
+ (void) TAO_IIOP_Interpreter::table_[kind_].calc (&stream, alignment, env);
+ private_state_->tc_alignment_known_ = CORBA::B_TRUE;
+ private_state_->tc_alignment_ = alignment;
+ return alignment;
+}