diff options
Diffstat (limited to 'TAO/IIOP/lib')
34 files changed, 8095 insertions, 1636 deletions
diff --git a/TAO/IIOP/lib/align.h b/TAO/IIOP/lib/align.h index cf75fb1bafe..cf11ac0447e 100644 --- a/TAO/IIOP/lib/align.h +++ b/TAO/IIOP/lib/align.h @@ -46,6 +46,7 @@ typedef u_long long ptr_arith_t; // boundaries are binary powers and that we're using two's complement // arithmetic. +#if 0 static inline ptr_arith_t align_binary (const ptr_arith_t value, size_t alignment) @@ -54,6 +55,9 @@ align_binary (const ptr_arith_t value, return (value + temp) & ~temp; } +#endif +#define align_binary(ptr, align_sub_1) \ + ((ptr + (align_sub_1)) & (~(align_sub_1))) // Efficiently round "ptr" up to an "alignment" boundary, knowing that // all such boundaries are binary powers and that we're using two's @@ -62,11 +66,15 @@ align_binary (const ptr_arith_t value, // XXX Returned as "byte pointer" -- CDR module would change to be // seen as a "void *". May want to change this to add XDR cleanly. +#if 0 static inline u_char * ptr_align_binary (const u_char *ptr, size_t alignment) { return (u_char *) align_binary ((ptr_arith_t) ptr, alignment); } +#endif +#define ptr_align_binary(ptr, alignment) \ + ((u_char *) align_binary(((ptr_arith_t) (ptr)), ((alignment)-1))) #endif /* TAO_ALIGN_H */ diff --git a/TAO/IIOP/lib/any.cpp b/TAO/IIOP/lib/any.cpp index ac50068f043..1c2c02eae12 100644 --- a/TAO/IIOP/lib/any.cpp +++ b/TAO/IIOP/lib/any.cpp @@ -35,9 +35,8 @@ #include <assert.h> #include <limits.h> #include <string.h> -#include <orb.h> -#include "debug.h" +#include "orb.h" #include <initguid.h> diff --git a/TAO/IIOP/lib/boa.cpp b/TAO/IIOP/lib/boa.cpp index 5979fce8316..facd571aa53 100644 --- a/TAO/IIOP/lib/boa.cpp +++ b/TAO/IIOP/lib/boa.cpp @@ -14,10 +14,8 @@ #include <stdio.h> #include <string.h> -#include <orb.h> -#include <boa.h> - -#include "debug.h" +#include "orb.h" +#include "boa.h" // XXX this should not know implementation or other details of any // protocol modules! This is an implementation shortcut only. diff --git a/TAO/IIOP/lib/cdr.cpp b/TAO/IIOP/lib/cdr.cpp index c22e4643383..1ec3a87872a 100644 --- a/TAO/IIOP/lib/cdr.cpp +++ b/TAO/IIOP/lib/cdr.cpp @@ -37,318 +37,62 @@ #include <limits.h> #include <string.h> -#include <orb.h> - -#include "debug.h" +#include "orb.h" #include "cdr.h" -// ENCODING routines ... pad, store. Never swap. Padding uses -// whatever value is already in the buffer. - -CORBA_Boolean -CDR::put_byte (char c) +#if !defined(ACE_INLINE) +inline +#endif +void CDR::swap_long(unsigned char *orig, CORBA_Long &target) { - if (remaining < sizeof (char) && grow (0) == CORBA_B_FALSE) - return CORBA_B_FALSE; + register unsigned char *lp = (unsigned char *) ⌖ - *next++ = (u_char) c; - remaining--; - return CORBA_B_TRUE; + lp [ 3] = *orig++; + lp [ 2] = *orig++; + lp [ 1] = *orig++; + lp [ 0] = *orig++; } -CORBA_Boolean -CDR::put_short (CORBA_Short s) +#if !defined(ACE_INLINE) +inline +#endif +void CDR::swap_longlong(unsigned char *orig, CORBA_LongLong &target) { - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes; maybe - // grow the buffer if there's not enough left - - tmp_next = ptr_align_binary (next, SHORT_SIZE); - temp = SHORT_SIZE + (tmp_next - next); - - if (temp > remaining) - { - if (grow (0) == CORBA_B_FALSE) - return CORBA_B_FALSE; - tmp_next = next + temp - SHORT_SIZE; - } - - remaining -= temp; - - // copy the half word, native byte order - - *(CORBA_Short *) tmp_next = s; - next = tmp_next + SHORT_SIZE; - return CORBA_B_TRUE; + register unsigned char *llp = (unsigned char *) ⌖ + + llp [ 7] = *orig++; + llp [ 6] = *orig++; + llp [ 5] = *orig++; + llp [ 4] = *orig++; + llp [ 3] = *orig++; + llp [ 2] = *orig++; + llp [ 1] = *orig++; + llp [ 0] = *orig++; } -CORBA_Boolean -CDR::put_long (CORBA_Long l) +#if !defined(ACE_INLINE) +inline +#endif +void CDR::swap_longdouble(unsigned char *orig, CORBA_LongDouble &target) { - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes; maybe - // grow the buffer if there's not enough left - - tmp_next = ptr_align_binary (next, LONG_SIZE); - temp = LONG_SIZE + (tmp_next - next); - - if (temp > remaining) - { - if (grow (0) == CORBA_B_FALSE) - return CORBA_B_FALSE; - tmp_next = next + temp - LONG_SIZE; - } - - remaining -= temp; - - // copy the word, native byte order - - *(CORBA_Long *) tmp_next = l; - - next = tmp_next + LONG_SIZE; - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::put_longlong (const CORBA_LongLong &ll) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes; maybe grow the - // buffer if there's not enough left - - tmp_next = ptr_align_binary (next, LONGLONG_SIZE); - temp = LONGLONG_SIZE + (tmp_next - next); - - if (temp > remaining) - { - if (grow (0) == CORBA_B_FALSE) - return CORBA_B_FALSE; - tmp_next = next + temp - LONGLONG_SIZE; - } - remaining -= temp; - - // copy the double word in "native" byte order. - - *(CORBA_LongLong *) tmp_next = ll; - next = tmp_next + LONGLONG_SIZE; - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::put_longdouble (CORBA_LongDouble &ld) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes; maybe - // grow the buffer if there's not enough left - - tmp_next = ptr_align_binary (next, LONGDOUBLE_SIZE); - temp = LONGDOUBLE_SIZE + (tmp_next - next); - - if (temp > remaining) - { - if (grow (0) == CORBA_B_FALSE) - return CORBA_B_FALSE; - tmp_next = next + temp - LONGDOUBLE_SIZE; - } - remaining -= temp; - - // copy the long double in "native" byte order. - *(CORBA_LongDouble *) tmp_next = ld; - next = tmp_next + LONGDOUBLE_SIZE; - return CORBA_B_TRUE; -} - -// DECODING routines ... adjust pointer, then byteswap as needed. - -CORBA_Boolean -CDR::get_byte (char &c) -{ - if (remaining < sizeof (char)) - return CORBA_B_FALSE; - - c = (char) *next++; - remaining--; - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::get_short (CORBA_Short &s) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes - - tmp_next = ptr_align_binary (next, SHORT_SIZE); - temp = SHORT_SIZE + (tmp_next - next); - - if (temp > remaining) - return CORBA_B_FALSE; - remaining -= temp; - - // decode halfword, swapping as needed - - if (!do_byteswap) - { - s = *(CORBA_Short *) tmp_next; - next = tmp_next + SHORT_SIZE; - } - else - { - register u_char *sp = (u_char *) &s; - - sp [1] = *tmp_next++; - sp [0] = *tmp_next++; - next = tmp_next; - } - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::get_long (CORBA_Long &l) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes - - tmp_next = ptr_align_binary (next, LONG_SIZE); - temp = LONG_SIZE + (tmp_next - next); - if (temp > remaining) - return CORBA_B_FALSE; - remaining -= temp; - - // decode word, swapping as needed - - if (!do_byteswap) - { - l = *(CORBA_Long *) tmp_next; - next = tmp_next + LONG_SIZE; - } - else - { - register u_char *lp = (u_char *) &l; - - // NOTE: environment-specific speedups abound for this kind of - // stuff. This generic code takes advanage of none of them. - - lp [3] = *tmp_next++; - lp [2] = *tmp_next++; - lp [1] = *tmp_next++; - lp [0] = *tmp_next++; - next = tmp_next; - } - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::get_longlong (CORBA_LongLong &ll) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes - - tmp_next = ptr_align_binary (next, LONGLONG_SIZE); - temp = LONGLONG_SIZE + (tmp_next - next); - if (temp > remaining) - return CORBA_B_FALSE; - remaining -= temp; - - // decode doubleword, swapping as needed - - if (!do_byteswap) - { - ll = *(CORBA_LongLong *) tmp_next; - next = tmp_next + LONGLONG_SIZE; - } - else - { - register u_char *llp = (u_char *) ≪ - - // NOTE: environment-specific speedups abound for this kind - // of stuff. This generic code takes advanage of none of them. - - llp [7] = *tmp_next++; - llp [6] = *tmp_next++; - llp [5] = *tmp_next++; - llp [4] = *tmp_next++; - llp [3] = *tmp_next++; - llp [2] = *tmp_next++; - llp [1] = *tmp_next++; - llp [0] = *tmp_next++; - next = tmp_next; - } - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::get_longdouble (CORBA_LongDouble &ld) -{ - register u_char *tmp_next; - register u_int temp; - - // Adjust pointer and count of remaining bytes - - tmp_next = ptr_align_binary (next, LONGDOUBLE_SIZE); - temp = LONGDOUBLE_SIZE + (tmp_next - next); - if (temp > remaining) - return CORBA_B_FALSE; - remaining -= temp; - - // copy the long double, swapping bytes as needed - - if (!do_byteswap) - { - ld = *(CORBA_LongDouble *) tmp_next; - next = tmp_next + LONGDOUBLE_SIZE; - } - else - { - register u_char *ldp = (u_char *) &ld; - - // NOTE: this is a single SPARC V9 instruction - - ldp [15] = *tmp_next++; - ldp [14] = *tmp_next++; - ldp [13] = *tmp_next++; - ldp [12] = *tmp_next++; - ldp [11] = *tmp_next++; - ldp [10] = *tmp_next++; - ldp [ 9] = *tmp_next++; - ldp [ 8] = *tmp_next++; - ldp [ 7] = *tmp_next++; - ldp [ 6] = *tmp_next++; - ldp [ 5] = *tmp_next++; - ldp [ 4] = *tmp_next++; - ldp [ 3] = *tmp_next++; - ldp [ 2] = *tmp_next++; - ldp [ 1] = *tmp_next++; - ldp [ 0] = *tmp_next++; - next = tmp_next; - } - return CORBA_B_TRUE; -} - -CORBA_Boolean -CDR::skip_string (void) // ISO/1 or octet string -{ - CORBA_ULong len; - - if (get_ulong (len) == CORBA_B_FALSE || len > remaining) - return CORBA_B_FALSE; // buffer's changed - - next += (u_int) len; - remaining -= (u_int) len; - return CORBA_B_TRUE; + register unsigned char *ldp = (unsigned char *) ⌖ + + ldp [15] = *orig++; + ldp [14] = *orig++; + ldp [13] = *orig++; + ldp [12] = *orig++; + ldp [11] = *orig++; + ldp [10] = *orig++; + ldp [ 9] = *orig++; + ldp [ 8] = *orig++; + ldp [ 7] = *orig++; + ldp [ 6] = *orig++; + ldp [ 5] = *orig++; + ldp [ 4] = *orig++; + ldp [ 3] = *orig++; + ldp [ 2] = *orig++; + ldp [ 1] = *orig++; + ldp [ 0] = *orig++; } // Grow the CDR buffer, either to a known size (incoming message) or @@ -438,3 +182,4 @@ CDR::grow (size_t newsize) return CORBA_B_TRUE; } + diff --git a/TAO/IIOP/lib/cdr.h b/TAO/IIOP/lib/cdr.h index 1b48b18f2be..9072fcce750 100644 --- a/TAO/IIOP/lib/cdr.h +++ b/TAO/IIOP/lib/cdr.h @@ -48,14 +48,16 @@ #include <assert.h> #include "ace/OS.h" +#include "align.h" + #if defined(__IIOP_BUILD) # include "orb.h" +# include "marshal.h" #else # include <corba/orb.h> +# include <marshal.h> #endif -#include <align.h> - // Identify byte order ... this is basically dependent on processor, // but some processors support different byte orders (e.g. MIPS, // UltraSPARC, PowerPC) as required for different software @@ -148,7 +150,6 @@ struct ACE_Svc_Export CDR // frames as large as the system page size (often 4Kb) can easily // overrun the "redzone" at the bottom of most VM-based stacks. }; - // = ENCODING SUPPORT // Adjust pointers as needed, then store in the native byte order. @@ -158,26 +159,53 @@ struct ACE_Svc_Export CDR // plus the interpretive encoder. CORBA_Boolean put_byte (char c); + // encode a byte in the CDR stream + CORBA_Boolean put_short (CORBA_Short s); + // encode a short in the CDR stream + CORBA_Boolean put_long (CORBA_Long l); + // encode a long into the CDR stream + CORBA_Boolean put_longlong (const CORBA_LongLong &ll); + // encode a longlong into the CDR stream + CORBA_Boolean put_char (CORBA_Char c); + // encode a char into the CDR stream + CORBA_Boolean put_wchar (CORBA_WChar wc); + // encode a wide char into the CDR stream + CORBA_Boolean put_boolean (CORBA_Boolean b); + // encode a boolean into the CDR stream + CORBA_Boolean put_octet (CORBA_Octet o); + // encode a octet into the CDR stream + CORBA_Boolean put_ushort (CORBA_UShort s); + // encode an unsigned short into the CDR stream + CORBA_Boolean put_ulong (CORBA_ULong l); + // encode an unsigned long into the CDR stream + CORBA_Boolean put_ulonglong (const CORBA_ULongLong &ll); + // encode an unsigned longlong into the CDR stream + CORBA_Boolean put_float (float f); + // encode a float into the CDR stream + CORBA_Boolean put_double (const double &d); + // encode a double into the CDR stream + CORBA_Boolean put_longdouble (CORBA_LongDouble &ld); + // encode a longdouble into the CDR stream + - static CORBA_TypeCode::traverse_status encoder (CORBA_TypeCode_ptr tc, + CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, const void *data, const void *, - void *context, CORBA_Environment &env); - // Marshaling interpreter ... <context> really points to a <CDR>. + // Marshaling. ... <context> really points to a <CDR>. // = DECODING SUPPORT @@ -186,34 +214,76 @@ struct ACE_Svc_Export CDR // do it that way than to use virtual functions. CORBA_Boolean get_byte (char &c); + // decode a byte from the CDR stream + CORBA_Boolean get_short (CORBA_Short &s); + // decode a short from the CDR stream + CORBA_Boolean get_long (CORBA_Long &l); + // decode a long from the CDR stream + CORBA_Boolean get_longlong (CORBA_LongLong &ll); + // decode a longlong from the CDR stream + CORBA_Boolean get_char (CORBA_Char &o); + // decode a char from the CDR stream + CORBA_Boolean get_wchar (CORBA_WChar &wc); + // decode a wide char from the CDR stream + CORBA_Boolean get_boolean (CORBA_Boolean &b); + // decode a boolean from the CDR stream + CORBA_Boolean get_octet (CORBA_Octet &o); + // decode an octet from the CDR stream + CORBA_Boolean get_ushort (CORBA_UShort &s); + // decode an unsigned short from the CDR stream + CORBA_Boolean get_ulong (CORBA_ULong &l); + // decode an unsigned long from the CDR stream + CORBA_Boolean get_ulonglong (const CORBA_ULongLong &ull); + // decode an unsigned longlong from the CDR stream + CORBA_Boolean get_float (float &f); + // decode a float from the CDR stream + CORBA_Boolean get_double (double &d); + // decode a double from the CDR stream + CORBA_Boolean get_longdouble (CORBA_LongDouble &ld); + // decode a longdouble from the CDR stream + - static CORBA_TypeCode::traverse_status decoder (CORBA_TypeCode_ptr tc, + CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, const void *data, const void *, - void *context, CORBA_Environment &env); // Unmarshaling interpreter ... <context> really points to a <CDR>. + CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env); + // Does a deep copy for hierarchical data types + + CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env); + // Deallocates memory for hierarchical data structures + CDR (u_char *buf = 0, u_int len = 0, int byte_order = MY_BYTE_SEX, - int consume_buf = 0); + int consume_buf = 0, + TAO_MarshalFactory *f = TAO_DEFAULT_MARSHAL_FACTORY); + // constructor ~CDR (void); + // destructor void *operator new (size_t, void *_FAR p); void *operator new (size_t s); @@ -225,7 +295,10 @@ struct ACE_Svc_Export CDR // reported. CORBA_Boolean skip_string (void); + // skip a string field in a typecode + CORBA_Boolean skip_bytes (u_int nbytes); + // skip given number of bytes in a typecode void setup_encapsulation (u_char *buf, u_int len); // Also used when interpreting typecodes, but more generally when @@ -263,7 +336,24 @@ struct ACE_Svc_Export CDR // Length of the dynamically allocated memory. int do_byteswap; - // Decode ONLY. + // for decoding only. + +private: + static void swap_long(unsigned char *orig, CORBA_Long &target); + // do byte swapping for longs + + static void swap_longlong(unsigned char *orig, CORBA_LongLong &target); + // do byte swapping for longlongs + + static void swap_longdouble(unsigned char *orig, CORBA_LongDouble &target); + // do byte swapping for longdoubles + + TAO_MarshalFactory *factory_; + // maintain a factory that can make specialized marshaling objects + + TAO_MarshalObject *mobj_; + // maintain an instance of a marshaling object. The CDR stream delegates the + // marshaling activity to mobj_; }; // In this ONE case, we make a substantial exception to how inline @@ -281,7 +371,6 @@ struct ACE_Svc_Export CDR # endif # include "cdr.i" - # if defined(do_undef_on_ACE_INLINE) # undef do_undef_on_ACE_INLINE # undef ACE_INLINE diff --git a/TAO/IIOP/lib/cdr.i b/TAO/IIOP/lib/cdr.i index d05e798e87e..2e10ab48a48 100644 --- a/TAO/IIOP/lib/cdr.i +++ b/TAO/IIOP/lib/cdr.i @@ -2,7 +2,8 @@ ACE_INLINE CDR::CDR (u_char *buf, u_int len, int byte_order, - int consume_buf) + int consume_buf, + TAO_MarshalFactory *f) // Constructor ... buffer must be aligned for the strictest CDR // alignment requirement, since the algorithms used here only // maintain alignment with respect to &buffer [0]. @@ -10,7 +11,9 @@ CDR::CDR (u_char *buf, // Yes, that complicates the grow() primitive. : real_buffer(buf), do_free(consume_buf), - do_byteswap(byte_order != MY_BYTE_SEX) + do_byteswap(byte_order != MY_BYTE_SEX), + factory_(f), + mobj_(0) { ptr_arith_t temp = (ptr_arith_t) buf; @@ -76,6 +79,20 @@ CDR::put_octet (CORBA_Octet o) } ACE_INLINE CORBA_Boolean +CDR::put_byte ( + char c +) +{ + if (remaining < sizeof (char) && grow (0) == CORBA_B_FALSE) + return CORBA_B_FALSE; + + *next++ = (unsigned char) c; + remaining--; + return CORBA_B_TRUE; +} + + +ACE_INLINE CORBA_Boolean CDR::put_ushort (CORBA_UShort s) { return put_short ((CORBA_Short) s); @@ -175,11 +192,47 @@ CDR::get_double (double &d) ACE_INLINE CORBA_Boolean CDR::skip_bytes (u_int nbytes) { - if (remaining < nbytes) - return CORBA_B_FALSE; - remaining -= nbytes; - next += nbytes; - return CORBA_B_TRUE; + if (remaining >= nbytes) + { + remaining -= nbytes; + next += nbytes; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; +} + +ACE_INLINE CORBA_Boolean +CDR::skip_string () // ISO/1 or octet string +{ + CORBA_ULong len; + + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes + // + tmp_next = ptr_align_binary (next, LONG_SIZE); + temp = LONG_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + + // + // decode word, swapping as needed + // + if (!do_byteswap) { + len = *(CORBA_Long *)tmp_next; + next = tmp_next + LONG_SIZE; + } else { + swap_long(tmp_next, *(CORBA_Long *)&len); + } + + // skip that many bytes + next += (unsigned) len; + remaining -= (unsigned) len; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; } ACE_INLINE void @@ -200,3 +253,386 @@ CDR::bytes_remaining (void) { return remaining; } + +ACE_INLINE CORBA_Boolean +CDR::put_short ( + CORBA_Short s + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes; maybe + // grow the buffer if there's not enough left + // + tmp_next = ptr_align_binary (next, SHORT_SIZE); + temp = SHORT_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + + // + // copy the half word, native byte order + // + *(CORBA_Short *)tmp_next = s; + next = tmp_next + SHORT_SIZE; + return CORBA_B_TRUE; + } else { + if (grow (0) == CORBA_B_TRUE) { + tmp_next = next + temp - SHORT_SIZE; + remaining -= temp; + + // + // copy the half word, native byte order + // + *(CORBA_Short *)tmp_next = s; + next = tmp_next + SHORT_SIZE; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; + } +} + +ACE_INLINE CORBA_Boolean +CDR::put_long ( + CORBA_Long l + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes; maybe + // grow the buffer if there's not enough left + // + tmp_next = ptr_align_binary (next, LONG_SIZE); + temp = LONG_SIZE + (tmp_next - next); + if (temp <= remaining) + { + remaining -= temp; + + // + // copy the word, native byte order + // + *(CORBA_Long *)tmp_next = l; + + next = tmp_next + LONG_SIZE; + return CORBA_B_TRUE; + } + else + { + if (grow (0) == CORBA_B_TRUE) + { + tmp_next = next + temp - LONG_SIZE; + remaining -= temp; + + // + // copy the word, native byte order + // + *(CORBA_Long *)tmp_next = l; + + next = tmp_next + LONG_SIZE; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; + } +} + +ACE_INLINE CORBA_Boolean +CDR::put_longlong ( + const CORBA_LongLong &ll + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes; maybe + // grow the buffer if there's not enough left + // + tmp_next = ptr_align_binary (next, LONGLONG_SIZE); + temp = LONGLONG_SIZE + (tmp_next - next); + if (temp <= remaining) + { + remaining -= temp; + // + // copy the double word in "native" byte order. + // + *(CORBA_LongLong *)tmp_next = ll; + next = tmp_next + LONGLONG_SIZE; + return CORBA_B_TRUE; + } + else + { + if (grow (0) == CORBA_B_TRUE) + { + tmp_next = next + temp - LONGLONG_SIZE; + remaining -= temp; + // + // copy the double word in "native" byte order. + // + *(CORBA_LongLong *)tmp_next = ll; + next = tmp_next + LONGLONG_SIZE; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; + } +} + +ACE_INLINE CORBA_Boolean +CDR::put_longdouble ( + CORBA_LongDouble &ld + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes; maybe + // grow the buffer if there's not enough left + // + tmp_next = ptr_align_binary (next, LONGDOUBLE_SIZE); + temp = LONGDOUBLE_SIZE + (tmp_next - next); + if (temp <= remaining) + { + remaining -= temp; + // + // copy the longdouble in native byte order + // + *(CORBA_LongDouble *)tmp_next = ld; + next = tmp_next + LONGDOUBLE_SIZE; + return CORBA_B_TRUE; + } + else + { + if (grow (0) == CORBA_B_TRUE) + { + tmp_next = next + temp - LONGDOUBLE_SIZE; + remaining -= temp; + // + // copy the longdouble in native byte order + // + *(CORBA_LongDouble *)tmp_next = ld; + next = tmp_next + LONGDOUBLE_SIZE; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; + } +} + + +// +// DECODING routines ... adjust pointer, then byteswap as needed. +// + +ACE_INLINE CORBA_Boolean +CDR::get_byte ( + char &c + ) +{ + if (remaining >= sizeof (char)) + { + c = (char) *next++; + remaining--; + return CORBA_B_TRUE; + } + return CORBA_B_FALSE; +} + +ACE_INLINE CORBA_Boolean +CDR::get_short ( + CORBA_Short &s + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes + // + tmp_next = ptr_align_binary (next, SHORT_SIZE); + temp = SHORT_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + // + // decode halfword, swapping as needed + // + if (!do_byteswap) { + s = *(CORBA_Short *)tmp_next; + next = tmp_next + SHORT_SIZE; + return CORBA_B_TRUE; // put a return here to avoid a jump + } else { + // do swapping + register unsigned char *sp = (unsigned char *) &s; + + sp [1] = *tmp_next++; + sp [0] = *tmp_next++; + next = tmp_next; + return CORBA_B_TRUE; + } + } + return CORBA_B_FALSE; +} + +ACE_INLINE CORBA_Boolean +CDR::get_long ( + CORBA_Long &l + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes + // + tmp_next = ptr_align_binary (next, LONG_SIZE); + temp = LONG_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + // + // decode word, swapping as needed + // + if (!do_byteswap) { + l = *(CORBA_Long *)tmp_next; + next = tmp_next + LONG_SIZE; + return CORBA_B_TRUE; + } else { + // + // NOTE: environment-specific speedups abound for this kind + // of stuff. This generic code takes advantage of none of them. + // + swap_long(tmp_next, l); + next = tmp_next + LONG_SIZE; + return CORBA_B_TRUE; + } + } + return CORBA_B_FALSE; +} + +ACE_INLINE CORBA_Boolean +CDR::get_longlong ( + CORBA_LongLong &ll + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes + // + tmp_next = ptr_align_binary (next, LONGLONG_SIZE); + temp = LONGLONG_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + // + // decode doubleword, swapping as needed + // + if (!do_byteswap) { + ll = *(CORBA_LongLong *)tmp_next; + next = tmp_next + LONGLONG_SIZE; + return CORBA_B_TRUE; + } else { + swap_longlong(tmp_next, ll); + next = tmp_next + LONGLONG_SIZE; + return CORBA_B_TRUE; + } + } + return CORBA_B_FALSE; +} + +ACE_INLINE CORBA_Boolean +CDR::get_longdouble ( + CORBA_LongDouble &ld + ) +{ + register unsigned char *tmp_next; + register unsigned temp; + + // + // Adjust pointer and count of remaining bytes + // + tmp_next = ptr_align_binary (next, LONGDOUBLE_SIZE); + temp = LONGDOUBLE_SIZE + (tmp_next - next); + if (temp <= remaining) { + remaining -= temp; + + // + // copy the long double, swapping bytes as needed + // + if (!do_byteswap) { + ld = *(CORBA_LongDouble *)tmp_next; + next = tmp_next + LONGDOUBLE_SIZE; + return CORBA_B_TRUE; + } else { + swap_longdouble(tmp_next, ld); + next = tmp_next + LONGDOUBLE_SIZE; + return CORBA_B_TRUE; + } + } + return CORBA_B_FALSE; +} + +// Encode data into CDR stream +ACE_INLINE CORBA_TypeCode::traverse_status +CDR::encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env) +{ + this->mobj_ = this->factory_->make_marshal_object(tc); + if (this->mobj_) + { + return this->mobj_->encode(tc, data, data2, this, env); + } + else + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// Decode the CDR stream +ACE_INLINE CORBA_TypeCode::traverse_status +CDR::decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env) +{ + this->mobj_ = this->factory_->make_marshal_object(tc); + if (this->mobj_) + { + return this->mobj_->decode(tc, data, data2, this, env); + } + else + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +#if 0 +// allocate buffers and make a deep copy +ACE_INLINE CORBA_TypeCode::traverse_status +CDR::deep_copy (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env) +{ + this->mobj_ = this->factory_->make_marshal_object(tc); + return this->mobj_->deep_copy(tc, data, data2, this, env); +} + +// free the buffers allocated for the specified data structure +ACE_INLINE CORBA_TypeCode::traverse_status +CDR::deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env) +{ + this->mobj_ = this->factory_->make_marshal_object(tc); + return this->mobj_->deep_free(tc, data, data2, this, env); +} +#endif + + + diff --git a/TAO/IIOP/lib/debug.cpp b/TAO/IIOP/lib/debug.cpp index 89c5b2487b5..2b542132c9c 100644 --- a/TAO/IIOP/lib/debug.cpp +++ b/TAO/IIOP/lib/debug.cpp @@ -65,7 +65,7 @@ static pid_t my_pid; // static pthread_once_t debug_init = PTHREAD_ONCE_INIT; -#define setup () pthread_once (&debug_init, setup_once) +#define setup() pthread_once (&debug_init, setup_once) static void setup_once () diff --git a/TAO/IIOP/lib/debug.h b/TAO/IIOP/lib/debug.h index 57459eb9af2..97bd08664a8 100644 --- a/TAO/IIOP/lib/debug.h +++ b/TAO/IIOP/lib/debug.h @@ -33,7 +33,7 @@ extern "C" char *strerror (int); // "tao_debug_level", etc. to protect the namespace. // 0 to ??; higher == more -extern u_int TAO_debug_level; +extern unsigned int TAO_debug_level; // set by getopt extern char *TAO_debug_filter; diff --git a/TAO/IIOP/lib/decode.cpp b/TAO/IIOP/lib/decode.cpp new file mode 100644 index 00000000000..814c17e0eef --- /dev/null +++ b/TAO/IIOP/lib/decode.cpp @@ -0,0 +1,1611 @@ +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// decode.cpp +// +// = DESCRIPTION +// Code for decoding different data types +// +// The original code had a single static decoder function defined on the CDR +// class that called traverse to interpret the data types. This version +// defines a virtual method "decode" on each class and avoids calling traverse. +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale +// +// ============================================================================ + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "orb.h" +#include "cdr.h" +#include "giop.h" + +#if defined (HAVE_WIDEC_H) +# include <widec.h> +#else +extern "C" +{ + u_int wslen (const CORBA_WChar *); + CORBA_WChar *wscpy (CORBA_WChar *, const CORBA_WChar *); +} +#endif + +extern CORBA_TypeCode TC_opaque; + +// The decoder is exactly the reverse of the encoder, except that: +// +// * Unmarshaling some data types involve allocating memory. Such +// types include sequences (the buffer), objrefs, Principals, Anys, +// TypeCodes, and strings. +// +// * The decoder is used when retrieving typecode parameters from +// encapsulations. This means it must deal with "tk_indirect", +// the magic value (~0) signifying typecode indirection. +// +// This second case is identified by a bit of a hack: the second +// "data" value is used to hold the parent typecode, rather than being +// ignored. This means that all other invocations of decoder() ** +// MUST ** pass zero for the second data parameter, in case they +// decode a TypeCode. If they didn't, this case might be signified +// inappropriately. +// +// XXX desirable to have a less hacky solution to that ... pull that +// code out into a separate routine called both by CDR::decoder() and +// by the code retrieving typecode parameters from encapsulations. + +CORBA_TypeCode_ptr __tc_consts [TC_KIND_COUNT] = +{ + _tc_CORBA_Null + , _tc_CORBA_Void + , _tc_CORBA_Short + , _tc_CORBA_Long + , _tc_CORBA_UShort + + , _tc_CORBA_ULong + , _tc_CORBA_Float + , _tc_CORBA_Double + , _tc_CORBA_Boolean + , _tc_CORBA_Char + + , _tc_CORBA_Octet + , _tc_CORBA_Any + , _tc_CORBA_TypeCode + , _tc_CORBA_Principal + , 0 // _tc_CORBA_Object ... type ID is CORBA::Object + + , 0 // tk_struct + , 0 // tk_union + , 0 // tk_enum + , 0 // _tc_CORBA_String ... unbounded + , 0 // tk_sequence + + , 0 // tk_array + + , 0 // tk_alias + , 0 // tk_except + + , _tc_CORBA_LongLong + , _tc_CORBA_ULongLong + , _tc_CORBA_LongDouble + , _tc_CORBA_WChar + , 0 // _tc_CORBA_WString ... unbounded +}; + +CORBA_TypeCode::traverse_status +TAO_Marshal_Primitive::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + + switch(tc->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_decoding = stream->get_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_decoding = stream->get_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_decoding = stream->get_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_decoding = stream->get_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_decoding = stream->get_wchar(*(wchar_t *)data); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + // we are not a primitive type + } + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_decoding == + CORBA_B_TRUE)) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Primitive::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +CORBA_TypeCode::traverse_status +TAO_Marshal_Any::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Any *any = (CORBA_Any *)data; + CORBA_TypeCode_ptr elem_tc; // typecode of the element that makes the Any + void *value; // value maintained by the Any + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + + // encode the typecode description for the element + if (stream->decode(_tc_CORBA_TypeCode, &elem_tc, 0, env) + == CORBA_TypeCode::TRAVERSE_CONTINUE) { + value = new CORBA_Octet[elem_tc->size(env)]; + if (env.exception() == 0) + { + // switch on the data type and handle the cases for primitives here for + // efficiency rather than calling + switch(elem_tc->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_decoding = stream->get_short (*(CORBA_Short *)value); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_decoding = stream->get_long(*(CORBA_Long *)value); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)value); + break; + case tk_boolean: + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)value); + break; + case tk_char: + case tk_octet: + continue_decoding = stream->get_char(*(CORBA_Char *)value); + break; + case tk_longdouble: + continue_decoding = stream->get_longdouble(*(CORBA_LongDouble *)value); + break; + case tk_wchar: + continue_decoding = stream->get_wchar(*(wchar_t *)value); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->decode(elem_tc, value, 0, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_decoding == + CORBA_B_TRUE)) + { + // allocate an Any and populate it with the value and typecode. This + // eventually appears as "data" + (void) new (any) CORBA_Any (elem_tc, value, CORBA_B_TRUE); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + // free the allocated storage and release the typecode + delete value; + CORBA_release(elem_tc); + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Any::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +CORBA_TypeCode::traverse_status +TAO_Marshal_TypeCode::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode_ptr *tcp; // typecode to be encoded + CORBA_ULong kind; + + // decode the "kind" field of the typecode + continue_decoding = stream->get_ulong ((CORBA_ULong) kind); + if (continue_decoding == CORBA_B_TRUE) + { + tcp = (CORBA_TypeCode_ptr *) data; // the data has to be a TypeCode_ptr + // Typecodes with empty parameter lists all have preallocated + // constants. We use those to reduce memory consumption and + // heap access ... also, to speed things up! + + if (((*tcp) = __tc_consts [(u_int) kind]) != 0) + { + *tcp = __tc_consts [(u_int) kind]; + } + else + { + switch (kind) + { + // Need special handling for all kinds of typecodes that have + // nonempty parameter lists ... + default: // error: missed a case! + env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + + // Some have "simple" parameter lists ... some of these also + // have preallocated constants that could be used. + case tk_string: + case tk_wstring: + { + CORBA_ULong bound; + + continue_decoding = stream->get_ulong (bound); + if (continue_decoding) + { + if (bound == 0) + { + if (kind == tk_string) + *tcp = _tc_CORBA_String; + else + *tcp = _tc_CORBA_WString; + } + else + { + *tcp = new CORBA_TypeCode ((CORBA_TCKind) kind, + bound, 0, CORBA_B_TRUE); + } + } + } + break; + + // Indirected typecodes, illegal at "top level" but we + // allow unmarshaling of them here because we use the same + // code to read "off the wire" (where they're illegal) and + // to read out of an encapsulation stream. We distinguish + // the case where this is legal as described above. + case ~0: + { + CORBA_TypeCode_ptr parent; + + if (parent_typecode == 0) + { + env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + parent = (CORBA_TypeCode_ptr) parent_typecode; + + // Get the long indicating the encapsulation offset, + // then set up indirection stream that's like "stream" + // but has space enough only for the typecode and the + // length for the encapsulated parameters. + CDR indir_stream; + CORBA_Long offset; + + continue_decoding = stream->get_long (offset); + if (continue_decoding) + continue_decoding = (offset < 0); + if (continue_decoding) + { + indir_stream.buffer = indir_stream.next + = stream->next + offset; + indir_stream.remaining = indir_stream.length = 8; + + // Reject indirections outside parent's scope. + if (indir_stream.next < parent->_buffer) + continue_decoding = CORBA_B_FALSE; + } + + // Get "kind" and length of target typecode + // + // XXX this currently assumes the TCKind to which we + // indirect is the same byte order as the "parent" + // typecode -- not the right assumption; see how the + // TypeCode interpreter does it. + + CORBA_ULong indir_kind; + CORBA_ULong indir_len; + + if (continue_decoding) + continue_decoding = stream->get_ulong (indir_kind); + if (continue_decoding + && indir_kind >= TC_KIND_COUNT) + continue_decoding = CORBA_B_FALSE; + if (continue_decoding) + continue_decoding = stream->get_ulong (indir_len); + + // Now construct indirected typecode. This shares the + // typecode octets with the "parent" typecode, + // increasing the amount of memory sharing and + // reducing the cost of getting typecodes. + if (continue_decoding) + { + *tcp = new CORBA_TypeCode ((CORBA_TCKind) indir_kind, + indir_len, + indir_stream.next, + CORBA_B_FALSE); + (*tcp)->_parent = parent; + parent->AddRef (); + } + } + break; + + // The rest have "complex" parameter lists that are + // encoded as bulk octets ... + case tk_objref: + case tk_struct: + case tk_union: + case tk_enum: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + { + u_int len; + u_int i; + CORBA_ULong length; + CORBA_Octet *buffer; + + continue_decoding = stream->get_ulong (length); + if (!continue_decoding) + break; + + // if length > MAXUNSIGNED, error ... + len = (u_int) length; + + buffer = new CORBA_Octet [len]; + + for (i = 0; i < len && continue_decoding; i++) + continue_decoding = stream->get_octet (buffer [i]); + + if (!continue_decoding) { + delete buffer; + break; + } + *tcp = new CORBA_TypeCode ((CORBA_TCKind) kind, + len, + buffer, + CORBA_B_TRUE); + } + } + } + + } + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode Principal +CORBA_TypeCode::traverse_status +TAO_Marshal_Principal::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_Principal_ptr *pp = (CORBA_Principal_ptr *) data; + CORBA_ULong len; + + continue_decoding = stream->get_ulong (len); + if (len == 0) + *pp = 0; // null principal + else + { + // allocate storage for Principal and its buffer + *pp = new CORBA_Principal; + (*pp)->id.buffer = new CORBA_Octet [(size_t) len]; + (*pp)->id.maximum = (*pp)->id.length = len; + + for (u_int i = 0; + continue_decoding != CORBA_B_FALSE && i < len; + i++) + continue_decoding = stream->get_octet ((*pp)->id.buffer [i]); + } + + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Principal::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// decode obj ref +CORBA_TypeCode::traverse_status +TAO_Marshal_ObjRef::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_String type_hint; + + // First, read the type hint. This will be the type_id encoded in an object + // reference. + stream->decode (_tc_CORBA_String, &type_hint, 0, env); + + // Read the profiles, discarding all until an IIOP profile + // comes by. Once we see an IIOP profile, ignore any further + // ones. + // + // XXX this will need to change someday to let different + // protocol code be accessed, not just IIOP. Protocol modules + // will be dynamically loaded from shared libraries via + // ORB_init(), and we just need to be able to access such + // preloaded libraries here as we unmarshal objrefs. + + CORBA_ULong profiles; + IIOP_Object *objdata = 0; + + // get the count of profiles that follow + continue_decoding = stream->get_ulong (profiles); + + // No profiles means a NIL objref. + + if (profiles == 0) + { + *(CORBA_Object_ptr *) data = CORBA_Object::_nil (); + delete type_hint; + } + else + { + while (profiles-- != 0 && continue_decoding) + { + CORBA_ULong tmp; + + // get the profile ID tag + stream->get_ulong (tmp); + if (tmp != IOP::TAG_INTERNET_IOP || objdata != 0) + { + continue_decoding = stream->skip_string (); + continue; + } + + // OK, we've got an IIOP profile. It's going to be + // encapsulated ProfileData. Create a new decoding stream + // and context for it, and tell the "parent" stream that + // this data isn't part of it any more. + + // ProfileData is encoded as a sequence of octet. So first get the + // length of the sequence + continue_decoding = stream->get_ulong (tmp); + assert (stream->remaining >= tmp); + + // Create the decoding stream from the encapsulation in + // the buffer, and skip the encapsulation. + CDR str; + + str.setup_encapsulation (stream->next, (size_t) tmp); + + stream->next += (u_int) tmp; + stream->remaining -= (u_int) tmp; + + objdata = new IIOP_Object (type_hint); + + IIOP::ProfileBody *profile = &objdata->profile; + + // Read and verify major, minor versions, ignoring IIOP + // profiles whose versions we don't understand. + // + // XXX this doesn't actually go back and skip the whole + // encapsulation... + if (!(str.get_octet (profile->iiop_version.major) + && profile->iiop_version.major == IIOP::MY_MAJOR + && str.get_octet (profile->iiop_version.minor) + && profile->iiop_version.minor <= IIOP::MY_MINOR)) + { + dmsg2 ("detected new v%d.%d IIOP profile", + profile->iiop_version.major, + profile->iiop_version.minor); + objdata->type_id = 0; + objdata->Release (); + objdata = 0; + continue; + } + + // Get host and port + if (str.decode (_tc_CORBA_String, &profile->host, 0, env) + != CORBA_TypeCode::TRAVERSE_CONTINUE + || !str.get_ushort (profile->port)) + { + env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); + dmsg ("error decoding IIOP host/port"); + objdata->Release (); + return CORBA_TypeCode::TRAVERSE_STOP; + } + + // ... and object key + + continue_decoding = str.decode (&TC_opaque, + &profile->object_key, + 0, + env) == CORBA_TypeCode::TRAVERSE_CONTINUE; + + if (str.remaining != 0) + { + env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); + dmsg ("extra data at end of IIOP profile data"); + objdata->Release (); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + } + if (objdata == 0) + { + env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); + dmsg2 ("no IIOP v%d.%d (or earlier) profile in IOR!", + IIOP::MY_MAJOR, IIOP::MY_MINOR); + return CORBA_TypeCode::TRAVERSE_STOP; + } + else + { + // retrieve the CORBA_Object from the IIOP_Object we created before. + if (objdata->QueryInterface (IID_CORBA_Object, + (void **) data) != NOERROR) + continue_decoding = CORBA_B_FALSE; + objdata->Release (); + } + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE && continue_decoding == + CORBA_B_TRUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } else { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("marshaling encode_struct detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// decode structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Struct::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CDR *stream = (CDR *)context; + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE && continue_decoding == + CORBA_B_TRUE; i++){ + param = tc->member_type(i, env); + if (env.exception() == 0){ + size = param->size(env); + if (env.exception() == 0){ + alignment = param->alignment(env); + if (env.exception() == 0){ + data = ptr_align_binary(data, alignment); + switch(param->_kind){ + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_decoding = stream->get_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_decoding = stream->get_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_decoding = stream->get_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_decoding = stream->get_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_decoding = stream->get_wchar(*(wchar_t *)data); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->decode(param, data, 0, env); + break; + default: + break; + } + data = (char *)data + size; + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE && continue_decoding == + CORBA_B_TRUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } else { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("marshaling encode_struct detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode unions +CORBA_TypeCode::traverse_status +TAO_Marshal_Union::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + CORBA_TypeCode_ptr discrim_tc; + CORBA_TypeCode_ptr member_tc; + CORBA_Any_ptr member_label; + CORBA_ULong discrim_size_with_pad; + const void *discrim_val; + CORBA_ULong member_count; + CORBA_Long default_index; + CORBA_ULong i; + CORBA_TypeCode_ptr default_tc = 0; + CORBA_Boolean discrim_matched = CORBA_B_FALSE; + + discrim_tc = tc->discriminator_type(env); + // get the discriminator type + if (env.exception() == 0) + { + // decode the discriminator value + retval = stream->decode(discrim_tc, data, data2, env); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + discrim_size_with_pad = tc->TAO_discrim_pad_size(env); + if (env.exception() == 0) + { + discrim_val = data; // save the pointer to the discriminator + // value + // move the pointer to point to the actual value + data = (char *)data + discrim_size_with_pad; + data2 = (char *)data2 + discrim_size_with_pad; + // now get ready to marshal the actual union value + default_index = tc->default_index(env); + if (env.exception() == 0) + { + member_count = tc->member_count(env); + if (env.exception () == 0) + { + // check which label value matches with the discriminator + // value. Accordingly, marshal the corresponding + // member_type. If none match, check if default exists + // and marshal accordingly. Otherwise it is an error. + i = 0; + while (member_count-- != 0) + { + member_label = tc->member_label(i, env); + if (env.exception() == 0) + { + // do the matching + switch (member_label->type()->kind(env)) + { + case tk_short: + case tk_ushort: + if (*(CORBA_Short *)member_label->value() == + *(CORBA_Short *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_long: + case tk_ulong: + case tk_enum: + if (*(CORBA_ULong *)member_label->value() == + *(CORBA_ULong *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_char: + if (*(CORBA_Char *)member_label->value() == + *(CORBA_Char *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_wchar: + if (*(CORBA_WChar *)member_label->value() == + *(CORBA_WChar *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_boolean: + if (*(CORBA_Boolean *)member_label->value() == + *(CORBA_Boolean *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + }// end of switch + + // get the member typecode + member_tc = tc->member_type (i, env); + if (env.exception() == 0) + { + if (default_index >= 0 && default_index-- == 0) + { + // have we reached the default label?, if so, + // save a handle to the typecode for the default + default_tc = member_tc; + } + if (discrim_matched) + { + // marshal according to the matched typecode + return stream->decode(member_tc, data, + data2, env); + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + i++; + } // end of while + // we are here only if there was no match + if (default_tc) + { + return stream->decode(default_tc, data, data2, env); + } + else + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// decode string +CORBA_TypeCode::traverse_status +TAO_Marshal_String::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_ULong len = 0; + CORBA_ULong bounds; + CORBA_String str; + + // On decode, omit the check against specified string bounds, + // and cope with illegal "zero length" strings (all lengths on + // the wire must include a NUL). + // + // This is on the principle of being gracious in what we + // accept; we don't generate messages that fail to comply with + // protocol specs, but we will accept them when it's clear how + // to do so. + + continue_decoding = stream->get_ulong (len); + *((CORBA_String*) data) = str = new CORBA_Char [(size_t) (len)]; + + if (len != 0) + while (continue_decoding != CORBA_B_FALSE && len-- != 0) + { + continue_decoding = stream->get_char (*(CORBA_Char *) str); + str++; + } + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// decode sequence +CORBA_TypeCode::traverse_status +TAO_Marshal_Sequence::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *)context; + CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data; + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + CORBA_ULong len; + char *value; + + // First unmarshal the sequence length ... we trust it to be + // right here, on the "be gracious in what you accept" + // principle. We don't generate illegal sequences + // (i.e. length > bounds). + + continue_decoding = stream->get_ulong (seq->length); + seq->maximum = seq->length; + seq->buffer = 0; + + if (continue_decoding) + { + // no point decoding an empty sequence + if (seq->length > 0) + { + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + size = tc2->size (env); + if (env.exception() == 0) + { + bounds = seq->length; + // allocate a buffer to hold the sequence + seq->buffer = new CORBA_Octet [size * (size_t) seq->maximum]; + value = (char *)seq->buffer; + switch(tc2->_kind) + { + case tk_null: + case tk_void: + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_short (*(CORBA_Short *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_long: + case tk_ulong: + case tk_float: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_boolean: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_char: + case tk_octet: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_char (*(CORBA_Char *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_longdouble: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_longdouble (*(CORBA_LongDouble *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_wchar: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_wchar (*(CORBA_WChar *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_enum: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + // handle all aggregate types here + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + // For those aggregate types whose size is constant, we + // compute it only once + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = stream->decode(tc2, value, 0, env); + value += size; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + default: + break; + } // end of switch + } // no exception computing size + } // no exception computing content type + } // length is > 0 + else + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; +} + +// decode array +CORBA_TypeCode::traverse_status +TAO_Marshal_Array::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *)context; + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + char *value = (char *)data; + + // retrieve the bounds of the array + bounds = tc->length (env); + if (env.exception () == 0) + { + + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + size = tc2->size (env); + if (env.exception() == 0) + { + switch(tc2->_kind) + { + case tk_null: + case tk_void: + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_short (*(CORBA_Short *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_long: + case tk_ulong: + case tk_float: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_boolean: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_char: + case tk_octet: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_char (*(CORBA_Char *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_longdouble: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_longdouble (*(CORBA_LongDouble *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_wchar: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_wchar (*(CORBA_WChar *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_enum: + // For primitives, compute the size only once + while (bounds-- && continue_decoding == CORBA_B_TRUE) + { + continue_decoding = stream->get_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + // handle all aggregate types here + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + // For those aggregate types whose size is constant, we + // compute it only once + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = stream->decode(tc2, value, 0, env); + value += size; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + default: + break; + } // end of switch + } // no exception computing size + } // no exception computing content type + } // no exception computing bounds + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; +} + +// decode alias +CORBA_TypeCode::traverse_status +TAO_Marshal_Alias::decode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_TypeCode_ptr tc2; // typecode of the aliased type + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of decode operation + char *value = (char *)data; + + tc2 = tc->content_type(env); + if (env.exception() == 0) + { + // switch on the data type and handle the cases for primitives here for + // efficiency rather than calling + switch(tc2->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_decoding = stream->get_short (*(CORBA_Short *)value); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_decoding = stream->get_long(*(CORBA_Long *)value); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)value); + break; + case tk_boolean: + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)value); + break; + case tk_char: + case tk_octet: + continue_decoding = stream->get_char(*(CORBA_Char *)value); + break; + case tk_longdouble: + continue_decoding = stream->get_longdouble(*(CORBA_LongDouble *)value); + break; + case tk_wchar: + continue_decoding = stream->get_wchar(*(wchar_t *)value); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->decode(tc2, value, 0, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + tc2->Release(); + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_decoding == + CORBA_B_TRUE)) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Alias::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + + +// decode exception +// For exceptions, the "hidden" type ID near the front of the +// on-wire representation was previously unmarshaled and mapped +// to the "tc" typcode we're using to traverse the memory ... +// at the same time its vtable, refcount, and other state was +// established. +// +// NOTE: This is asymmetric with respect to encoding exceptions. +CORBA_TypeCode::traverse_status +TAO_Marshal_Except::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CDR *stream = (CDR *)context; + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + + data = (char *)data + sizeof(CORBA_Exception); + + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE && continue_decoding == + CORBA_B_TRUE; i++){ + param = tc->member_type(i, env); + if (env.exception() == 0){ + size = param->size(env); + if (env.exception() == 0){ + alignment = param->alignment(env); + if (env.exception() == 0){ + data = ptr_align_binary(data, alignment); + switch(param->_kind){ + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_decoding = stream->get_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_decoding = stream->get_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_decoding = stream->get_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_decoding = stream->get_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_decoding = stream->get_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_decoding = stream->get_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_decoding = stream->get_wchar(*(wchar_t *)data); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->decode(param, data, 0, env); + break; + default: + break; + } + data = (char *)data + size; + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE && continue_decoding == + CORBA_B_TRUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } else { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Except detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + + +// decode wstring +CORBA_TypeCode::traverse_status +TAO_Marshal_WString::decode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_decoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_WChar *str = *(CORBA_WChar **) data; + CORBA_ULong len; + CORBA_ULong bounds; + + // On decode, omit the check against specified wstring bounds, + // and cope with illegal "zero length" strings (all lengths on + // the wire must include a NUL). + // + // This is on the principle of being gracious in what we + // accept; we don't generate messages that fail to comply with + // protocol specs, but we will accept them when it's clear how + // to do so. + + continue_decoding = stream->get_ulong (len); + + *((CORBA_WChar **) data) = str = new CORBA_WChar [(size_t) (len)]; + + if (len != 0) + while (continue_decoding != CORBA_B_FALSE && len--) + { + continue_decoding = stream->get_wchar (*str); + str++; + } + if (continue_decoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + diff --git a/TAO/IIOP/lib/deep_copy.cpp b/TAO/IIOP/lib/deep_copy.cpp new file mode 100644 index 00000000000..4bd71c70eea --- /dev/null +++ b/TAO/IIOP/lib/deep_copy.cpp @@ -0,0 +1,1309 @@ +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// deep_copy.cpp +// +// = DESCRIPTION +// Code for deep_copy +// The original code had a single static deep_copy function that called +// traverse to interpret the data types. This version defines a static method +// "deep_copy" on each class and avoids calling traverse. +// +// +// Helper routine for "Any" copy constructor ... +// +// "Deep Copy" from source to dest. Memory is always there to be +// copied to ... if this calls other deep_copy methods, it ensures that +// this remains true (only really an issue for sequences) . +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale +// +// ============================================================================ + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "orb.h" +#include "cdr.h" +#include "giop.h" + +#if defined (HAVE_WIDEC_H) +# include <widec.h> +#else +extern "C" +{ + u_int wslen (const CORBA_WChar *); + CORBA_WChar *wscpy (CORBA_WChar *, const CORBA_WChar *); +} +#endif + +extern CORBA_TypeCode TC_opaque; + + // Deep copy from "source" to "dest" ... this code "knows" a bit + // about representations, verify it when porting to oddball + // platforms with non-IEEE floating point values or atypical byte + // and word sizes. + // + + +static CORBA_TypeCode::traverse_status +DEEP_COPY( + CORBA_TypeCode_ptr param, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + switch(param->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + *(CORBA_Short *)dest = *(CORBA_Short *)source; + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *)dest = *(CORBA_Long *)source; + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + *(CORBA_LongLong *)dest = *(CORBA_LongLong *)source; + break; + case tk_boolean: + *(CORBA_Boolean *)dest = *(CORBA_Boolean *)source; + break; + case tk_char: + case tk_octet: + *(CORBA_Char *)dest = *(CORBA_Char *)source; + break; + case tk_longdouble: + *(CORBA_LongDouble *)dest = *(CORBA_LongDouble *)source; + break; + case tk_wchar: + *(CORBA_WChar *)dest = *(CORBA_WChar *)source; + break; + case tk_any: + retval = TAO_Marshal_Any::deep_copy(param, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_copy(param, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_copy(param, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_copy(param, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_copy(param, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_copy(param, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_copy(param, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_copy(param, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_copy(param, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_copy(param, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_copy(param, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_copy(param, source, dest, env); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + } // end of switch + return retval; +} + +// deep copy for primitives +CORBA_TypeCode::traverse_status +TAO_Marshal_Primitive::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TCKind my_kind; + + if (tc) + { + my_kind = tc->kind (env); + + if (env.exception() == 0) + { + + switch (my_kind) + { + case tk_null: + case tk_void: + break; + + case tk_char: + case tk_octet: + *(CORBA_Octet *) dest = *(CORBA_Octet *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_short: + case tk_ushort: + *(CORBA_Short *) dest = *(CORBA_Short *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_wchar: + *(CORBA_WChar *) dest = *(CORBA_WChar *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *) dest = *(CORBA_Long *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_longlong: + case tk_ulonglong: + case tk_double: + *(CORBA_LongLong *) dest = *(CORBA_LongLong *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_longdouble: + *(CORBA_LongDouble *) dest = *(CORBA_LongDouble *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + case tk_boolean: + *(CORBA_Boolean *) dest = *(CORBA_Boolean *) source; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Primitive::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + dmsg ("TAO_Marshal_Primitive::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_MAYBE) ); + dmsg ("TAO_Marshal_Primitive::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy for Principal +CORBA_TypeCode::traverse_status +TAO_Marshal_Principal::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + CORBA_Principal_ptr src, dst; + + if (tc) + { + src = *(CORBA_Principal_ptr *) source; + dst = *(CORBA_Principal_ptr *) dest = new CORBA_Principal; + + if (dst) + { + // Principals are just opaque IDs ... copy them + assert (src->id.length <= UINT_MAX); + dst->id.length = dst->id.maximum = src->id.length; + + if (dst->id.length > 0) + { + dst->id.buffer = new CORBA_Octet [ (unsigned) dst->id.length]; + if (dst->id.buffer) + { + ACE_OS::memcpy (dst->id.buffer, src->id.buffer, + (size_t) dst->id.length); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_NO_MEMORY (COMPLETED_MAYBE) ); + dmsg ("TAO_Marshal_Principal::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + dst->id.buffer = 0; + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + else + { + env.exception (new CORBA_NO_MEMORY (COMPLETED_MAYBE) ); + dmsg ("TAO_Marshal_Principal::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_MAYBE) ); + dmsg ("TAO_Marshal_Primitive::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Struct::deep_copy ( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + CDR stream; + + if (tc) + { + // compute the number of fields in the struct + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE; i++) + { + // get the typecode for the ith field + param = tc->member_type(i, env); + if (env.exception() == 0) + { + // get the size of the field + size = param->size(env); + if (env.exception() == 0) + { + // get the alignment of the field + alignment = param->alignment(env); + if (env.exception() == 0) + { + switch(param->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + *(CORBA_Short *)dest = *(CORBA_Short *)source; + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *)dest = *(CORBA_Long *)source; + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + *(CORBA_LongLong *)dest = *(CORBA_LongLong *)source; + break; + case tk_boolean: + *(CORBA_Boolean *)dest = *(CORBA_Boolean *)source; + break; + case tk_char: + case tk_octet: + *(CORBA_Char *)dest = *(CORBA_Char *)source; + break; + case tk_longdouble: + *(CORBA_LongDouble *)dest = *(CORBA_LongDouble *)source; + break; + case tk_wchar: + *(CORBA_WChar *)dest = *(CORBA_WChar *)source; + break; + case tk_any: + retval = TAO_Marshal_Any::deep_copy(param, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_copy(param, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_copy(param, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_copy(param, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_copy(param, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_copy(param, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_copy(param, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_copy(param, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_copy(param, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_copy(param, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_copy(param, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_copy(param, source, dest, env); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + } // end of switch + source = (char *)source + size; + dest = (char *)dest + size; + } + else // exception computing alignment + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing size + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing typecode + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // end of loop + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting member count + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy for union +CORBA_TypeCode::traverse_status +TAO_Marshal_Union::deep_copy( + CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr discrim_tc; + CORBA_TypeCode_ptr member_tc; + CORBA_Any_ptr member_label; + CORBA_ULong discrim_size_with_pad; + const void *discrim_val; + CORBA_ULong member_count; + CORBA_Long default_index; + CORBA_ULong i; + CORBA_TypeCode_ptr default_tc = 0; + CORBA_Boolean discrim_matched = CORBA_B_FALSE; + + discrim_tc = tc->discriminator_type(env); + // get the discriminator type + if (env.exception() == 0) + { + // deep_copy the discriminator value + retval = DEEP_COPY(discrim_tc, data, data2, env); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + discrim_size_with_pad = tc->TAO_discrim_pad_size(env); + if (env.exception() == 0) + { + discrim_val = data; // save the pointer to the discriminator + // value + // move the pointer to point to the actual value + data = (char *)data + discrim_size_with_pad; + data2 = (char *)data2 + discrim_size_with_pad; + // now get ready to marshal the actual union value + default_index = tc->default_index(env); + if (env.exception() == 0) + { + member_count = tc->member_count(env); + if (env.exception () == 0) + { + // check which label value matches with the discriminator + // value. Accordingly, marshal the corresponding + // member_type. If none match, check if default exists + // and marshal accordingly. Otherwise it is an error. + i = 0; + while (member_count-- != 0) + { + member_label = tc->member_label(i, env); + if (env.exception() == 0) + { + // do the matching + switch (member_label->type()->kind(env)) + { + case tk_short: + case tk_ushort: + if (*(CORBA_Short *)member_label->value() == + *(CORBA_Short *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_long: + case tk_ulong: + case tk_enum: + if (*(CORBA_ULong *)member_label->value() == + *(CORBA_ULong *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_char: + if (*(CORBA_Char *)member_label->value() == + *(CORBA_Char *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_wchar: + if (*(CORBA_WChar *)member_label->value() == + *(CORBA_WChar *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_boolean: + if (*(CORBA_Boolean *)member_label->value() == + *(CORBA_Boolean *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + }// end of switch + + // get the member typecode + member_tc = tc->member_type (i, env); + if (env.exception() == 0) + { + if (default_index >= 0 && default_index-- == 0) + { + // have we reached the default label?, if so, + // save a handle to the typecode for the default + default_tc = member_tc; + } + if (discrim_matched) + { + // marshal according to the matched typecode + return DEEP_COPY(member_tc, data, + data2, env); + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + i++; + } // end of while + // we are here only if there was no match + if (default_tc) + { + return DEEP_COPY(default_tc, data, data2, env); + } + else + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + +} + +// deep_copy for Sequence +CORBA_TypeCode::traverse_status +TAO_Marshal_Sequence::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + char *value1, *value2; + CORBA_OctetSeq *src, *dst; + CDR stream; // used only to access the marshal_object factory + + // Rely on binary format of sequences -- all are the same + // except for the type pointed to by "buffer" + + if (tc) + { + src = (CORBA_OctetSeq *) source; + dst = (CORBA_OctetSeq *) dest; + + assert (src->length <= UINT_MAX); + dst->length = dst->maximum = src->length; + + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + // get the size of the element + size = tc2->size (env); + if (env.exception() == 0) + { + // compute the length of the sequence + bounds = src->length; + + // allocate a buffer to hold the sequence + dst->buffer = new CORBA_Octet [size * (size_t) src->maximum]; + if (dst->buffer) + { + value1 = (char *)src->buffer; + value2 = (char *)dst->buffer; + + switch(tc2->_kind) + { + case tk_null: + case tk_void: + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + case tk_enum: + // just do a memcpy rather than copying each element + ACE_OS::memcpy(value2, value1, size*bounds); + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + // handle all aggregate types here + case tk_any: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_TypeCode: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_TypeCode::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_Principal: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Principal::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_objref: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_ObjRef::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_struct: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Struct::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_union: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Union::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_string: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + retval = TAO_Marshal_String::deep_copy(tc2, source, dest, env); + break; + case tk_sequence: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Sequence::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_array: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Array::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_alias: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Alias::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_except: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Except::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + case tk_wstring: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_WString::deep_copy(tc2, source, dest, env); + value1 = (char *)value1 + size; + value2 = (char *)value2 + size; + } + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + break; + } // end of switch + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + // error exit + CORBA_release(tc2); + env.exception (new CORBA_NO_MEMORY(COMPLETED_MAYBE)); + dmsg ("marshaling TAO_Marshal_Sequence::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing size + { + CORBA_release(tc2); + dmsg ("marshaling TAO_Marshal_Sequence::deep_copy detected error"); + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing content type + { + dmsg ("marshaling TAO_Marshal_Sequence::deep_copy detected error"); + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy for Array +CORBA_TypeCode::traverse_status +TAO_Marshal_Array::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + CDR stream; // used only to access the marshal_object factory + + // Rely on binary format of sequences -- all are the same + // except for the type pointed to by "buffer" + + if (tc) + { + bounds = tc->length(env); + if (env.exception() == 0) + { + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + // get the size of the element type + size = tc2->size (env); + if (env.exception() == 0) + { + switch(tc2->_kind) + { + case tk_null: + case tk_void: + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + case tk_enum: + // just do a memcpy rather than copying each element + ACE_OS::memcpy((char *)dest, (char *)source, size*bounds); + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + // handle all aggregate types here + case tk_any: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_TypeCode: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_TypeCode::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_Principal: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Principal::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_objref: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_ObjRef::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_struct: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Struct::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_union: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Union::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_string: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + retval = TAO_Marshal_String::deep_copy(tc2, source, dest, env); + break; + case tk_sequence: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Sequence::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_array: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Array::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_alias: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Alias::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_except: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Except::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + case tk_wstring: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_WString::deep_copy(tc2, source, dest, env); + source = (char *)source + size; + dest = (char *)dest + size; + } + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + break; + } // end of switch + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // no exception computing size + else + { + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // no exception computing content type + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // bounds are fine + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy alias +CORBA_TypeCode::traverse_status +TAO_Marshal_Alias::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode_ptr tc2; // typecode of the aliased type + CDR stream; // to access the marshal object + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of deep_copy operation + + if (tc) + { + // get element type + tc2 = tc->content_type(env); + if (env.exception() == 0) + { + // switch on the data type and handle the cases for primitives here for + // efficiency + switch(tc2->_kind) + { + case tk_null: + case tk_void: + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + *(CORBA_Short *)dest = *(CORBA_Short *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *)dest = *(CORBA_Long *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_double: + case tk_longlong: + case tk_ulonglong: + *(CORBA_LongLong *)dest = *(CORBA_LongLong *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_boolean: + *(CORBA_Boolean *)dest = *(CORBA_Boolean *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_char: + case tk_octet: + *(CORBA_Char *)dest = *(CORBA_Char *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_longdouble: + *(CORBA_LongDouble *)dest = *(CORBA_LongDouble *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_wchar: + *(CORBA_WChar *)dest = *(CORBA_WChar *)source; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_any: + retval = TAO_Marshal_Any::deep_copy(tc2, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_copy(tc2, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_copy(tc2, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_copy(tc2, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_copy(tc2, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_copy(tc2, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_copy(tc2, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_copy(tc2, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_copy(tc2, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_copy(tc2, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_copy(tc2, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_copy(tc2, source, dest, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Alias::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting content_type + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_copy structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Except::deep_copy ( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + CDR stream; + + if (tc) + { + // Exceptions in memory have a "hidden" typecode up front, used + // to ensure that memory is appropriately freed and to hold the + // exception ID. We just copy that typecode + + *(CORBA_TypeCode_ptr *) dest = *(CORBA_TypeCode_ptr *) source; + (void) (*(CORBA_TypeCode_ptr *) dest)->AddRef (); + + // compute the number of fields in the struct + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE; i++) + { + // get the typecode for the ith field + param = tc->member_type(i, env); + if (env.exception() == 0) + { + // get the size of the field + size = param->size(env); + if (env.exception() == 0) + { + // get the alignment of the field + alignment = param->alignment(env); + if (env.exception() == 0) + { + switch(param->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + *(CORBA_Short *)dest = *(CORBA_Short *)source; + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *)dest = *(CORBA_Long *)source; + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + *(CORBA_LongLong *)dest = *(CORBA_LongLong *)source; + break; + case tk_boolean: + *(CORBA_Boolean *)dest = *(CORBA_Boolean *)source; + break; + case tk_char: + case tk_octet: + *(CORBA_Char *)dest = *(CORBA_Char *)source; + break; + case tk_longdouble: + *(CORBA_LongDouble *)dest = *(CORBA_LongDouble *)source; + break; + case tk_wchar: + *(CORBA_WChar *)dest = *(CORBA_WChar *)source; + break; + case tk_any: + retval = TAO_Marshal_Any::deep_copy(param, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_copy(param, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_copy(param, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_copy(param, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_copy(param, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_copy(param, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_copy(param, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_copy(param, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_copy(param, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_copy(param, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_copy(param, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_copy(param, source, dest, env); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + } // end of switch + source = (char *)source + size; + dest = (char *)dest + size; + } + else // exception computing alignment + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing size + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing typecode + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // end of loop + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting member count + { + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_copy detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} diff --git a/TAO/IIOP/lib/deep_free.cpp b/TAO/IIOP/lib/deep_free.cpp new file mode 100644 index 00000000000..f451154b821 --- /dev/null +++ b/TAO/IIOP/lib/deep_free.cpp @@ -0,0 +1,1028 @@ +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// deep_free.cpp +// +// = DESCRIPTION +// Code for deep_free +// The original code had a single static deep_free function that called +// traverse to interpret the data types. This version defines a static method +// "deep_free" on each class and avoids calling traverse. +// +// Helper routine for "Any" destructor. +// +// This frees all the memory pointed to by any given value held inside +// of an "Any". For most data types it does nothing, since most data +// types don't hold any memory. For a few, it calls other deep_free methods +// to free the memory +// + +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale +// +// ============================================================================ + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "orb.h" +#include "cdr.h" +#include "giop.h" + +#if defined (HAVE_WIDEC_H) +# include <widec.h> +#else +extern "C" +{ + u_int wslen (const CORBA_WChar *); + CORBA_WChar *wscpy (CORBA_WChar *, const CORBA_WChar *); +} +#endif + +extern CORBA_TypeCode TC_opaque; + + // Deep copy from "source" to "dest" ... this code "knows" a bit + // about representations, verify it when porting to oddball + // platforms with non-IEEE floating point values or atypical byte + // and word sizes. + // + + +static CORBA_TypeCode::traverse_status +DEEP_FREE( + CORBA_TypeCode_ptr param, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + switch(param->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + *(CORBA_Short *)dest = *(CORBA_Short *)source; + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + *(CORBA_Long *)dest = *(CORBA_Long *)source; + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + *(CORBA_LongLong *)dest = *(CORBA_LongLong *)source; + break; + case tk_boolean: + *(CORBA_Boolean *)dest = *(CORBA_Boolean *)source; + break; + case tk_char: + case tk_octet: + *(CORBA_Char *)dest = *(CORBA_Char *)source; + break; + case tk_longdouble: + *(CORBA_LongDouble *)dest = *(CORBA_LongDouble *)source; + break; + case tk_wchar: + *(CORBA_WChar *)dest = *(CORBA_WChar *)source; + break; + case tk_any: + retval = TAO_Marshal_Any::deep_free(param, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_free(param, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_free(param, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_free(param, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_free(param, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_free(param, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_free(param, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_free(param, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_free(param, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_free(param, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_free(param, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_free(param, source, dest, env); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + } // end of switch + return retval; +} + +// deep copy for primitives +CORBA_TypeCode::traverse_status +TAO_Marshal_Primitive::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TCKind my_kind; + + if (tc) + { + my_kind = tc->kind (env); + + if (env.exception() == 0) + { + + switch (my_kind) + { + case tk_null: + case tk_void: + case tk_char: + case tk_octet: + case tk_short: + case tk_ushort: + case tk_wchar: + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + case tk_longlong: + case tk_ulonglong: + case tk_double: + case tk_longdouble: + case tk_boolean: + return CORBA_TypeCode::TRAVERSE_CONTINUE; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Primitive::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + dmsg ("TAO_Marshal_Primitive::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_MAYBE) ); + dmsg ("TAO_Marshal_Primitive::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Struct::deep_free ( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + CDR stream; + + if (tc) + { + // compute the number of fields in the struct + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE; i++) + { + // get the typecode for the ith field + param = tc->member_type(i, env); + if (env.exception() == 0) + { + // get the size of the field + size = param->size(env); + if (env.exception() == 0) + { + // get the alignment of the field + alignment = param->alignment(env); + if (env.exception() == 0) + { + switch(param->_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + break; + case tk_any: + retval = TAO_Marshal_Any::deep_free(param, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_free(param, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_free(param, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_free(param, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_free(param, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_free(param, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_free(param, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_free(param, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_free(param, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_free(param, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_free(param, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_free(param, source, dest, env); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + } // end of switch + source = (char *)source + size; + } + else // exception computing alignment + { + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing size + { + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing typecode + { + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // end of loop + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting member count + { + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free for union +CORBA_TypeCode::traverse_status +TAO_Marshal_Union::deep_free( + CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr discrim_tc; + CORBA_TypeCode_ptr member_tc; + CORBA_Any_ptr member_label; + CORBA_ULong discrim_size_with_pad; + const void *discrim_val; + CORBA_ULong member_count; + CORBA_Long default_index; + CORBA_ULong i; + CORBA_TypeCode_ptr default_tc = 0; + CORBA_Boolean discrim_matched = CORBA_B_FALSE; + + discrim_tc = tc->discriminator_type(env); + // get the discriminator type + if (env.exception() == 0) + { + // deep_free the discriminator value + retval = DEEP_FREE(discrim_tc, data, data2, env); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + discrim_size_with_pad = tc->TAO_discrim_pad_size(env); + if (env.exception() == 0) + { + discrim_val = data; // save the pointer to the discriminator + // value + // move the pointer to point to the actual value + data = (char *)data + discrim_size_with_pad; + data2 = (char *)data2 + discrim_size_with_pad; + // now get ready to marshal the actual union value + default_index = tc->default_index(env); + if (env.exception() == 0) + { + member_count = tc->member_count(env); + if (env.exception () == 0) + { + // check which label value matches with the discriminator + // value. Accordingly, marshal the corresponding + // member_type. If none match, check if default exists + // and marshal accordingly. Otherwise it is an error. + i = 0; + while (member_count-- != 0) + { + member_label = tc->member_label(i, env); + if (env.exception() == 0) + { + // do the matching + switch (member_label->type()->kind(env)) + { + case tk_short: + case tk_ushort: + if (*(CORBA_Short *)member_label->value() == + *(CORBA_Short *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_long: + case tk_ulong: + case tk_enum: + if (*(CORBA_ULong *)member_label->value() == + *(CORBA_ULong *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_char: + if (*(CORBA_Char *)member_label->value() == + *(CORBA_Char *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_wchar: + if (*(CORBA_WChar *)member_label->value() == + *(CORBA_WChar *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_boolean: + if (*(CORBA_Boolean *)member_label->value() == + *(CORBA_Boolean *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + }// end of switch + + // get the member typecode + member_tc = tc->member_type (i, env); + if (env.exception() == 0) + { + if (default_index >= 0 && default_index-- == 0) + { + // have we reached the default label?, if so, + // save a handle to the typecode for the default + default_tc = member_tc; + } + if (discrim_matched) + { + // marshal according to the matched typecode + return DEEP_FREE(member_tc, data, + data2, env); + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + i++; + } // end of while + // we are here only if there was no match + if (default_tc) + { + return DEEP_FREE(default_tc, data, data2, env); + } + else + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free for Sequence +CORBA_TypeCode::traverse_status +TAO_Marshal_Sequence::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + char *value1; + CORBA_OctetSeq *src; + CDR stream; // used only to access the marshal_object factory + + // Rely on binary format of sequences -- all are the same + // except for the type pointed to by "buffer" + + if (tc) + { + src = (CORBA_OctetSeq *) source; + + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + // get the size of the element + size = tc2->size (env); + if (env.exception() == 0) + { + // compute the length of the sequence + bounds = src->length; + + value1 = (char *)src->buffer; + switch(tc2->_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + case tk_enum: + delete src->buffer; + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + // handle all aggregate types here + case tk_any: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_TypeCode: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_TypeCode::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_Principal: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Principal::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_objref: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_ObjRef::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_struct: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Struct::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_union: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Union::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_string: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + retval = TAO_Marshal_String::deep_free(tc2, source, dest, env); + break; + case tk_sequence: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Sequence::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_array: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Array::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_alias: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Alias::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_except: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Except::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + case tk_wstring: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_WString::deep_free(tc2, source, dest, env); + value1 = (char *)value1 + size; + } + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + break; + } // end of switch + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing size + { + CORBA_release(tc2); + dmsg ("marshaling TAO_Marshal_Sequence::deep_free detected error"); + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing content type + { + dmsg ("marshaling TAO_Marshal_Sequence::deep_free detected error"); + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free for Array +CORBA_TypeCode::traverse_status +TAO_Marshal_Array::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + CDR stream; // used only to access the marshal_object factory + + // Rely on binary format of sequences -- all are the same + // except for the type pointed to by "buffer" + + if (tc) + { + bounds = tc->length(env); + if (env.exception() == 0) + { + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + // get the size of the element type + size = tc2->size (env); + if (env.exception() == 0) + { + switch(tc2->_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + case tk_enum: + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + + // handle all aggregate types here + case tk_any: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Any::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_TypeCode: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_TypeCode::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_Principal: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Principal::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_objref: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_ObjRef::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_struct: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Struct::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_union: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Union::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_string: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_String::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_sequence: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Sequence::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_array: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Array::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_alias: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Alias::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_except: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_Except::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + case tk_wstring: + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = TAO_Marshal_WString::deep_free(tc2, source, dest, env); + source = (char *)source + size; + } + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + break; + } // end of switch + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } // no exception computing size + else + { + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception computing content type + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting bounds + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free alias +CORBA_TypeCode::traverse_status +TAO_Marshal_Alias::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_TypeCode_ptr tc2; // typecode of the aliased type + CDR stream; // to access the marshal object + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + + if (tc) + { + // get element type + tc2 = tc->content_type(env); + if (env.exception() == 0) + { + // switch on the data type and handle the cases for primitives here for + // efficiency + switch(tc2->_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + CORBA_release(tc2); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_any: + retval = TAO_Marshal_Any::deep_free(tc2, source, dest, env); + break; + case tk_TypeCode: + retval = TAO_Marshal_TypeCode::deep_free(tc2, source, dest, env); + break; + case tk_Principal: + retval = TAO_Marshal_Principal::deep_free(tc2, source, dest, env); + break; + case tk_objref: + retval = TAO_Marshal_ObjRef::deep_free(tc2, source, dest, env); + break; + case tk_struct: + retval = TAO_Marshal_Struct::deep_free(tc2, source, dest, env); + break; + case tk_union: + retval = TAO_Marshal_Union::deep_free(tc2, source, dest, env); + break; + case tk_string: + retval = TAO_Marshal_String::deep_free(tc2, source, dest, env); + break; + case tk_sequence: + retval = TAO_Marshal_Sequence::deep_free(tc2, source, dest, env); + break; + case tk_array: + retval = TAO_Marshal_Array::deep_free(tc2, source, dest, env); + break; + case tk_alias: + retval = TAO_Marshal_Alias::deep_free(tc2, source, dest, env); + break; + case tk_except: + retval = TAO_Marshal_Except::deep_free(tc2, source, dest, env); + break; + case tk_wstring: + retval = TAO_Marshal_WString::deep_free(tc2, source, dest, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Alias::decode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // exception getting content_type + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// deep_free structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Except::deep_free ( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + CDR stream; + + if (tc) + { + // XXX: Exceptions are currently leaked because of bugs lurking + // in this area. Keep in mind that there are two things to + // free: (a) the typecode in the exception base class; (b) any + // pointers held by a user-defined exception, such as an objref + // or string. + // + // Since this code does nothing, it should leak BOTH of those + // kinds of memory. Since it's not supposed to be called except + // when the exception really is being freed, it should only be + // called when the reference count in the exception base class + // is zero. + // + // It's not clear which of those assertions actually hold. + // + // The code SHOULD be just like the traverse () call for a + // structure, with (a) a precondition that the reference count + // is zero, (b) an assertion that the typecode in the exception + // and "tc" are equivalent, (c) releasing that typecode found + // within the exception. + // + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else // no typecode + { + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Struct::deep_free detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} diff --git a/TAO/IIOP/lib/encode.cpp b/TAO/IIOP/lib/encode.cpp new file mode 100644 index 00000000000..8d316292690 --- /dev/null +++ b/TAO/IIOP/lib/encode.cpp @@ -0,0 +1,1423 @@ +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// encode.cpp +// +// = DESCRIPTION +// Code for encoding different data types +// +// The original code had a single static encoder function defined on the CDR +// class that called traverse to interpret the data types. This version +// defines a virtual method "encode" on each class and avoids calling traverse. +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale +// +// ============================================================================ + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "orb.h" +#include "cdr.h" +#include "giop.h" + +#if defined (HAVE_WIDEC_H) +# include <widec.h> +#else +extern "C" +{ + u_int wslen (const CORBA_WChar *); + CORBA_WChar *wscpy (CORBA_WChar *, const CORBA_WChar *); +} +#endif + +extern CORBA_TypeCode TC_opaque; + +// Encode instances of arbitrary data types based only on typecode. +// "data" points to the data type; if it's not a primitve data type, +// the TypeCode interpreter is used to recursively encode its +// components. "context" is the marshaling stream on which to encode +// the data value. +// + +CORBA_TypeCode::traverse_status +TAO_Marshal_Primitive::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + + switch(tc->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_encoding = stream->put_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_encoding = stream->put_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_encoding = stream->put_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_encoding = stream->put_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_encoding = stream->put_wchar(*(wchar_t *)data); + break; + default: + retval = CORBA_TypeCode::TRAVERSE_STOP; + // we are not a primitive type + } + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_encoding == + CORBA_B_TRUE)) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Primitive::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +CORBA_TypeCode::traverse_status +TAO_Marshal_Any::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Any *any = (CORBA_Any *)data; + CORBA_TypeCode_ptr elem_tc; // typecode of the element that makes the Any + void *value; // value maintained by the Any + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + + elem_tc = any->type(); + // encode the typecode description for the element + if (stream->encode(_tc_CORBA_TypeCode, &elem_tc, 0, env) + == CORBA_TypeCode::TRAVERSE_CONTINUE) { + value = any->value(); + // switch on the data type and handle the cases for primitives here for + // efficiency rather than calling + switch(elem_tc->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_encoding = stream->put_short (*(CORBA_Short *)value); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_encoding = stream->put_long(*(CORBA_Long *)value); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)value); + break; + case tk_boolean: + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)value); + break; + case tk_char: + case tk_octet: + continue_encoding = stream->put_char(*(CORBA_Char *)value); + break; + case tk_longdouble: + continue_encoding = stream->put_longdouble(*(CORBA_LongDouble *)value); + break; + case tk_wchar: + continue_encoding = stream->put_wchar(*(wchar_t *)value); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->encode(elem_tc, value, 0, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_encoding == + CORBA_B_TRUE)) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Any::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +CORBA_TypeCode::traverse_status +TAO_Marshal_TypeCode::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode_ptr tc2; // typecode to be encoded + + tc2 = *(CORBA_TypeCode_ptr *) data; // the data has to be a TypeCode_ptr + + // encode the "kind" field of the typecode + continue_encoding = stream->put_ulong ((CORBA_ULong) tc2->_kind); + if (continue_encoding == CORBA_B_TRUE) + { + // now encode the parameters, if any + switch (tc2->_kind) + { + // Most TypeCodes have empty parameter lists + default: + break; + + // A few have "simple" parameter lists + case tk_string: + case tk_wstring: + continue_encoding = stream->put_ulong (tc2->_length); + break; + + // Indirected typecodes can't occur at "top level" like + // this, only nested inside others! + case ~0: + dmsg ("indirected typecode at top level!"); + continue_encoding = CORBA_B_FALSE; + break; + + // The rest have "complex" parameter lists that are + // already encoded as bulk octets ... put length, then + // octets. + case tk_objref: + case tk_struct: + case tk_union: + case tk_enum: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + { + continue_encoding = stream->put_ulong (tc2->_length); + + for (u_int i = 0; i < tc2->_length && continue_encoding; i++) + continue_encoding = stream->put_octet (tc2->_buffer [i]); + } + } + } + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode Principal +CORBA_TypeCode::traverse_status +TAO_Marshal_Principal::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + CORBA_Principal_ptr p = *(CORBA_Principal_ptr *) data; + + if (p != 0) + { + continue_encoding = stream->put_long (p->id.length); + + for (u_int i = 0; continue_encoding && i < p->id.length; i++) + continue_encoding = stream->put_octet (p->id.buffer [i]); + } + else + { + continue_encoding = stream->put_long (0); + } + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Principal::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode obj ref +CORBA_TypeCode::traverse_status +TAO_Marshal_ObjRef::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + // Current version: objref is really an IIOP_Object. + // + // This will change in the future; STUB_Object knows how to + // marshal itself, that will be used. + // + // XXX this doesn't actually verify that the stuff got written + // OK to the "wire" ... + CORBA_Object_ptr obj = *(CORBA_Object_ptr *) data; + + // NIL objrefs ... marshal as empty type hint, no elements. + + if (CORBA_is_nil (obj)) + { + continue_encoding = + stream->put_ulong (1) // strlen + && stream->put_char (0) // NUL + && stream->put_ulong (0); // no profiles + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + + // All other objrefs ... narrow to a "real type" that we + // recognize, then marshal. + // + // XXX this will be changed so it narrows to STUB_Object and + // then asks that surrogate/proxy to marshal itself. + // + // For now, the original code is minimally changed. + + IIOP_Object *objdata; + IIOP::ProfileBody *profile; + + if (obj->QueryInterface (IID_IIOP_Object, + (void **) &objdata) != NOERROR) + { + env.exception (new CORBA_MARSHAL (COMPLETED_NO)); + return CORBA_TypeCode::TRAVERSE_STOP; + } + obj->Release (); + profile = &objdata->profile; + + // STRING, a type ID hint + stream->encode(_tc_CORBA_String, &objdata->type_id, 0, env); + + // UNSIGNED LONG, value one, count of the sequence of + // encapsulated protocol profiles; + stream->put_ulong (1); + + // UNSIGNED LONG, tag for this protocol profile; + stream->put_ulong (IOP::TAG_INTERNET_IOP); + + // UNSIGNED LONG, number of succeeding bytes in the + // encapsulation. We don't actually need to make the + // encapsulation, as nothing needs stronger alignment than + // this longword; it guarantees the rest is aligned for us. + u_int hostlen; + + hostlen = ACE_OS::strlen ((char *) profile->host); + stream->put_ulong (1 // byte order + + 3 // version + pad byte + + 4 // sizeof (strlen) + + hostlen + 1 // strlen + null + + (~hostlen & 01) // optional pad byte + + 2 // port + + (hostlen & 02) // optional pad short + + 4 // sizeof (key length) + + profile->object_key.length); // key length + + // CHAR describing byte order, starting the encapsulation + + stream->put_char (MY_BYTE_SEX); + + // IIOP::Version, two characters (version 1.0) padding + stream->put_char (profile->iiop_version.major); + stream->put_char (profile->iiop_version.minor); + + // STRING hostname from profile + stream->encode(_tc_CORBA_String, &profile->host, 0, env); + + // UNSIGNED SHORT port number + stream->put_ushort (profile->port); + + // OCTET SEQUENCE for object key + stream->encode (&TC_opaque, &profile->object_key, 0, env); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } +} + +// encode structs +CORBA_TypeCode::traverse_status +TAO_Marshal_Struct::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CDR *stream = (CDR *)context; + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE && continue_encoding == + CORBA_B_TRUE; i++){ + param = tc->member_type(i, env); + if (env.exception() == 0){ + size = param->size(env); + if (env.exception() == 0){ + alignment = param->alignment(env); + if (env.exception() == 0){ + data = ptr_align_binary(data, alignment); + switch(param->_kind){ + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_encoding = stream->put_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_encoding = stream->put_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_encoding = stream->put_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_encoding = stream->put_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_encoding = stream->put_wchar(*(wchar_t *)data); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->encode(param, data, 0, env); + break; + default: + break; + } + data = (char *)data + size; + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE && continue_encoding == + CORBA_B_TRUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } else { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("marshaling encode_struct detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode unions +CORBA_TypeCode::traverse_status +TAO_Marshal_Union::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *data2, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + + CORBA_TypeCode_ptr discrim_tc; + CORBA_TypeCode_ptr member_tc; + CORBA_Any_ptr member_label; + CORBA_ULong discrim_size_with_pad; + const void *discrim_val; + CORBA_ULong member_count; + CORBA_Long default_index; + CORBA_ULong i; + CORBA_TypeCode_ptr default_tc = 0; + CORBA_Boolean discrim_matched = CORBA_B_FALSE; + + discrim_tc = tc->discriminator_type(env); + // get the discriminator type + if (env.exception() == 0) + { + // encode the discriminator value + retval = stream->encode(discrim_tc, data, data2, env); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + discrim_size_with_pad = tc->TAO_discrim_pad_size(env); + if (env.exception() == 0) + { + discrim_val = data; // save the pointer to the discriminator + // value + // move the pointer to point to the actual value + data = (char *)data + discrim_size_with_pad; + data2 = (char *)data2 + discrim_size_with_pad; + // now get ready to marshal the actual union value + default_index = tc->default_index(env); + if (env.exception() == 0) + { + member_count = tc->member_count(env); + if (env.exception () == 0) + { + // check which label value matches with the discriminator + // value. Accordingly, marshal the corresponding + // member_type. If none match, check if default exists + // and marshal accordingly. Otherwise it is an error. + i = 0; + while (member_count-- != 0) + { + member_label = tc->member_label(i, env); + if (env.exception() == 0) + { + // do the matching + switch (member_label->type()->kind(env)) + { + case tk_short: + case tk_ushort: + if (*(CORBA_Short *)member_label->value() == + *(CORBA_Short *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_long: + case tk_ulong: + case tk_enum: + if (*(CORBA_ULong *)member_label->value() == + *(CORBA_ULong *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_char: + if (*(CORBA_Char *)member_label->value() == + *(CORBA_Char *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_wchar: + if (*(CORBA_WChar *)member_label->value() == + *(CORBA_WChar *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + case tk_boolean: + if (*(CORBA_Boolean *)member_label->value() == + *(CORBA_Boolean *)discrim_val) + { + discrim_matched = CORBA_B_TRUE; + } + break; + default: + env.exception (new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg("Union::encode - Bad discriminant type"); + return CORBA_TypeCode::TRAVERSE_STOP; + }// end of switch + + // get the member typecode + member_tc = tc->member_type (i, env); + if (env.exception() == 0) + { + if (default_index >= 0 && default_index-- == 0) + { + // have we reached the default label?, if so, + // save a handle to the typecode for the default + default_tc = member_tc; + } + if (discrim_matched) + { + // marshal according to the matched typecode + return stream->encode(member_tc, data, + data2, env); + } + } + else // error getting member type + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg1 ("Union::encode - error getting member type:%d",i); + return CORBA_TypeCode::TRAVERSE_STOP; + } + + } + else // error getting member label + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg1("Union::encode - error member label : %d", i); + return CORBA_TypeCode::TRAVERSE_STOP; + } + i++; + } // end of while + // we are here only if there was no match + if (default_tc) + { + return stream->encode(default_tc, data, data2, env); + } + else + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + else // error getting member count + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("Union::encode - error getting member count"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // error getting default index + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg ("Union::encode - error getting default used"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // error getting discrim_pad_size + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg ("Union::encode - error getting discrim padded size"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // error encoding discriminant + { + env.exception(new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("Union::encode - error encoding discriminant"); + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else // error getting the discriminant + { + env.exception(new CORBA_BAD_TYPECODE(COMPLETED_NO)); + dmsg ("Union::encode - error getting the discriminant typecode"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + +// encode string +CORBA_TypeCode::traverse_status +TAO_Marshal_String::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_String str = *(CORBA_String *) data; + CORBA_ULong len; + CORBA_ULong bounds; + + // Be nice to programmers: treat nulls as empty strings not + // errors. (OMG-IDL supports languages that don't use the + // C/C++ notion of null v. empty strings; nulls aren't part of + // the OMG-IDL string model.) + if (str != 0) + { + + // Verify string satisfies bounds requirements. We're not so + // permissive as to send messages violating the interface spec + // by having excessively long strings! + bounds = tc->length(env); + if (env.exception () == 0) + { + // get the actual length of the string + len = ACE_OS::strlen ((char *) str); + + // if it is an unbounded string or if the length is less than the + // bounds for an unbounded string + if ((bounds == 0) || (len <= bounds)) + { + + // Encode the string, followed by a NUL character. + + for (continue_encoding = stream->put_ulong (len + 1); + continue_encoding != CORBA_B_FALSE && *str; + continue_encoding = stream->put_char (*str++)) + continue; + + stream->put_char (0); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + // empty string + stream->put_ulong (1); + stream->put_char (0); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } +} + +// encode sequence +CORBA_TypeCode::traverse_status +TAO_Marshal_Sequence::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *)context; + CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data; + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + CORBA_ULong len = seq ? seq->length : 0; + char *value; + + // + // First marshal the sequence length, verifying that + // it's within the sequence bounds ... + // + if (len > 0) + { + // retrieve the bounds of the sequence + bounds = tc->length (env); + if (env.exception () == 0) + { + // encode only if it is an unbounded sequence or if length is + // less/equal to the bounds + if (bounds == 0 || len <= bounds) + { + bounds = len; // number of times you encode + continue_encoding = stream->put_ulong (seq->length); + if (continue_encoding && seq->length != 0) + { + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + size = tc2->size (env); + if (env.exception() == 0) + { + value = (char *)seq->buffer; + switch(tc2->_kind) + { + case tk_null: + case tk_void: + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_short (*(CORBA_Short *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_long: + case tk_ulong: + case tk_float: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_boolean: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_char: + case tk_octet: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_char (*(CORBA_Char *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_longdouble: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_longdouble (*(CORBA_LongDouble *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_wchar: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_wchar (*(CORBA_WChar *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_enum: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + // handle all aggregate types here + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + // For those aggregate types whose size is constant, we + // compute it only once + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = stream->encode(tc2, value, 0, env); + value += size; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + default: + break; + } // end of switch + } // no exception computing size + } // no exception computing content type + } // seq length not 0 + } // within bounds or unbounded + } // no exception computing bounds + } // length is > 0 + else + { + // length is 0, encode it + continue_encoding = stream->put_ulong (len); + if (continue_encoding == CORBA_B_TRUE) { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + } + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; +} + +// encode array +CORBA_TypeCode::traverse_status +TAO_Marshal_Array::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *)context; + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // return status + CORBA_TypeCode_ptr tc2; // typecode of the element + size_t size; // size of element + CORBA_ULong bounds; + char *value = (char *)data; + + // retrieve the bounds of the array + bounds = tc->length (env); + if (env.exception () == 0) + { + + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + size = tc2->size (env); + if (env.exception() == 0) + { + switch(tc2->_kind) + { + case tk_null: + case tk_void: + return CORBA_TypeCode::TRAVERSE_CONTINUE; + case tk_short: + case tk_ushort: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_short (*(CORBA_Short *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_long: + case tk_ulong: + case tk_float: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_boolean: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_char: + case tk_octet: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_char (*(CORBA_Char *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_longdouble: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_longdouble (*(CORBA_LongDouble *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_wchar: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_wchar (*(CORBA_WChar *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + case tk_enum: + // For primitives, compute the size only once + while (bounds-- && continue_encoding == CORBA_B_TRUE) + { + continue_encoding = stream->put_long (*(CORBA_Long *)value); + value += size; + } + CORBA_release(tc2); + if (continue_encoding == CORBA_B_TRUE) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + // handle all aggregate types here + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + // For those aggregate types whose size is constant, we + // compute it only once + while (bounds-- && retval == CORBA_TypeCode::TRAVERSE_CONTINUE) + { + retval = stream->encode(tc2, value, 0, env); + value += size; + } + CORBA_release(tc2); + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + break; + default: + break; + } // end of switch + } // no exception computing size + } // no exception computing content type + } // no exception computing bounds + // error exit + env.exception (new CORBA_MARSHAL(COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; +} + +CORBA_TypeCode::traverse_status +TAO_Marshal_Alias::encode( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_TypeCode_ptr tc2; // typecode of the aliased type + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = + CORBA_TypeCode::TRAVERSE_CONTINUE; // status of encode operation + char *value = (char *)data; + + tc2 = tc->content_type(env); + if (env.exception() == 0) + { + // switch on the data type and handle the cases for primitives here for + // efficiency rather than calling + switch(tc2->_kind) + { + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_encoding = stream->put_short (*(CORBA_Short *)value); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_encoding = stream->put_long(*(CORBA_Long *)value); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)value); + break; + case tk_boolean: + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)value); + break; + case tk_char: + case tk_octet: + continue_encoding = stream->put_char(*(CORBA_Char *)value); + break; + case tk_longdouble: + continue_encoding = stream->put_longdouble(*(CORBA_LongDouble *)value); + break; + case tk_wchar: + continue_encoding = stream->put_wchar(*(wchar_t *)value); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->encode(tc2, value, 0, env); + break; + default: + // anything else is an error + retval = CORBA_TypeCode::TRAVERSE_STOP; + } + } + tc2->Release(); + if ((retval == CORBA_TypeCode::TRAVERSE_CONTINUE) && (continue_encoding == + CORBA_B_TRUE)) + { + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Alias::encode detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + + +// encode exception +CORBA_TypeCode::traverse_status +TAO_Marshal_Except::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CDR *stream = (CDR *)context; + CORBA_Long i, + member_count; // number of fields in the struct + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CORBA_TypeCode_ptr param; + CORBA_Long size, alignment; + + data = (char *)data + sizeof(CORBA_Exception); + + member_count = tc->member_count(env); + if (env.exception() == 0) + { + for(i=0; i < member_count && retval == + CORBA_TypeCode::TRAVERSE_CONTINUE && continue_encoding == + CORBA_B_TRUE; i++){ + param = tc->member_type(i, env); + if (env.exception() == 0){ + size = param->size(env); + if (env.exception() == 0){ + alignment = param->alignment(env); + if (env.exception() == 0){ + data = ptr_align_binary(data, alignment); + switch(param->_kind){ + case tk_null: + case tk_void: + break; + case tk_short: + case tk_ushort: + continue_encoding = stream->put_short (*(CORBA_Short *)data); + break; + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + continue_encoding = stream->put_long(*(CORBA_Long *)data); + break; + case tk_double: + case tk_longlong: + case tk_ulonglong: + continue_encoding = stream->put_longlong (*(CORBA_LongLong *)data); + break; + case tk_boolean: + continue_encoding = stream->put_boolean (*(CORBA_Boolean *)data); + break; + case tk_char: + case tk_octet: + continue_encoding = stream->put_char(*(CORBA_Char *)data); + break; + case tk_longdouble: + continue_encoding = stream->put_longdouble(*(CORBA_LongDouble *)data); + break; + case tk_wchar: + continue_encoding = stream->put_wchar(*(wchar_t *)data); + break; + case tk_any: + case tk_TypeCode: + case tk_Principal: + case tk_objref: + case tk_struct: + case tk_union: + case tk_string: + case tk_sequence: + case tk_array: + case tk_alias: + case tk_except: + case tk_wstring: + retval = stream->encode(param, data, 0, env); + break; + default: + break; + } + data = (char *)data + size; + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + } else { + return CORBA_TypeCode::TRAVERSE_STOP; + } + if (retval == CORBA_TypeCode::TRAVERSE_CONTINUE && continue_encoding == + CORBA_B_TRUE){ + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } else { + env.exception (new CORBA_MARSHAL(COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Except detected error"); + return CORBA_TypeCode::TRAVERSE_STOP; + } +} + + +// encode wstring +CORBA_TypeCode::traverse_status +TAO_Marshal_WString::encode ( + CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env + ) +{ + CORBA_Boolean continue_encoding = CORBA_B_TRUE; + CDR *stream = (CDR *) context; // context is the CDR stream + CORBA_TypeCode::traverse_status retval = CORBA_TypeCode::TRAVERSE_CONTINUE; + CORBA_WChar *str = *(CORBA_WChar **) data; + CORBA_ULong len; + CORBA_ULong bounds; + + // Be nice to programmers: treat nulls as empty strings not + // errors. (OMG-IDL supports languages that don't use the + // C/C++ notion of null v. empty strings; nulls aren't part of + // the OMG-IDL string model.) + if (str != 0) + { + + // Verify string satisfies bounds requirements. We're not so + // permissive as to send messages violating the interface spec + // by having excessively long strings! + bounds = tc->length(env); + if (env.exception () == 0) + { + // get the actual length of the string + len = wslen ((CORBA_WChar *) str); + + // if it is an unbounded string or if the length is less than the + // bounds for an unbounded string + if ((bounds == 0) || (len <= bounds)) + { + + // Encode the string, followed by a NUL character. + + for (continue_encoding = stream->put_ulong (len + 1); + continue_encoding != CORBA_B_FALSE && *str; + continue_encoding = stream->put_wchar (*str++)) + continue; + + stream->put_wchar (0); + } + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + return CORBA_TypeCode::TRAVERSE_STOP; + } + } + else + { + // empty string + stream->put_ulong (1); + stream->put_wchar (0); + return CORBA_TypeCode::TRAVERSE_CONTINUE; + } +} + diff --git a/TAO/IIOP/lib/except.cpp b/TAO/IIOP/lib/except.cpp index 27c6c6b1f8f..faa4bbe4157 100644 --- a/TAO/IIOP/lib/except.cpp +++ b/TAO/IIOP/lib/except.cpp @@ -17,7 +17,6 @@ #include <orb.h> #include "cdr.h" -#include "debug.h" #include <initguid.h> @@ -240,25 +239,25 @@ make_standard_typecode (CORBA_TypeCode_ptr tcp, assert (strlen (full_id) <= sizeof full_id); if (stream.put_byte (MY_BYTE_SEX) != CORBA_B_TRUE - || CDR::encoder (_tc_CORBA_String, + || stream.encode (_tc_CORBA_String, &strptr, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_String, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_String, &name, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE + env) != CORBA_TypeCode::TRAVERSE_CONTINUE || stream.put_ulong (2L) != CORBA_B_TRUE - || CDR::encoder (_tc_CORBA_String, + || stream.encode (_tc_CORBA_String, &minor, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_TypeCode, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_TypeCode, &_tc_CORBA_ULong, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_String, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_String, &completion, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_TypeCode, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_TypeCode, &completion_status, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_INITIALIZE (COMPLETED_NO)); return; } diff --git a/TAO/IIOP/lib/giop.cpp b/TAO/IIOP/lib/giop.cpp index 44f0ae30fc5..8e531fe881f 100644 --- a/TAO/IIOP/lib/giop.cpp +++ b/TAO/IIOP/lib/giop.cpp @@ -49,13 +49,12 @@ #include "ace/Log_Msg.h" #include "ace/SOCK_Stream.h" +#include "orb.h" + #include "orbobj.h" #include "factories.h" -#include <orb.h> - #include "cdr.h" -#include "debug.h" #include "giop.h" // defined by GIOP 1.0 protocol @@ -159,8 +158,9 @@ GIOP::send_message (CDR &stream, writelen = peer.send ((char _FAR *) buf, buflen); #ifdef DEBUG - dmsg_filter (6, "wrote %d bytes to connection %d", - writelen, connection); + // dmsg_filter (6, "wrote %d bytes to connection %d", + // writelen, connection); + dmsg_filter (6, "wrote %d bytes", writelen); #endif // DEBUG assert ((writelen >= 0 @@ -707,7 +707,7 @@ GIOP::Invocation::start (CORBA_Environment &env) static CORBA_Principal_ptr anybody = 0; static ServiceContextList svc_ctx; // all zeroes - if (CDR::encoder (&TC_ServiceContextList, 0, &svc_ctx, &stream, env) + if (stream.encode (&TC_ServiceContextList, 0, &svc_ctx, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) return; @@ -718,15 +718,15 @@ GIOP::Invocation::start (CORBA_Environment &env) return; } - if (CDR::encoder (&TC_opaque, + if (stream.encode (&TC_opaque, key, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_String, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_String, &opname, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE - || CDR::encoder (_tc_CORBA_Principal, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || stream.encode (_tc_CORBA_Principal, &anybody, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) return; // right after fault else return; // no fault reported @@ -879,7 +879,7 @@ GIOP::Invocation::invoke (CORBA_ExceptionList &exceptions, CORBA_ULong request_id; CORBA_ULong reply_status; // GIOP::ReplyStatusType - if (CDR::decoder (&TC_ServiceContextList, &reply_ctx, 0, &stream, env) + if (stream.decode (&TC_ServiceContextList, &reply_ctx, 0, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { send_error (handler_->peer()); @@ -993,7 +993,7 @@ GIOP::Invocation::invoke (CORBA_ExceptionList &exceptions, exception = new (new char [size]) CORBA_Exception (*tcp); - if (CDR::decoder (*tcp, exception, 0, &stream, env) + if (stream.decode (*tcp, exception, 0, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { delete exception; @@ -1035,9 +1035,9 @@ GIOP::Invocation::invoke (CORBA_ExceptionList &exceptions, // one of the facets of this object will be an IIOP invocation // profile. - if (CDR::decoder (_tc_CORBA_Object, + if (stream.decode (_tc_CORBA_Object, &obj, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE + env) != CORBA_TypeCode::TRAVERSE_CONTINUE || obj->QueryInterface (IID_IIOP_Object, (void **)&obj2) != NOERROR) { @@ -1156,30 +1156,26 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, // security environment. It may be required even when using // IPSEC security infrastructure. - hdr_status = CDR::decoder (&TC_ServiceContextList, + hdr_status = msg.decode (&TC_ServiceContextList, &req.service_info, 0, - &msg, env); // Get the rest of the request header ... hdr_status = hdr_status && msg.get_ulong (req.request_id); hdr_status = hdr_status && msg.get_boolean (req.response_expected); - hdr_status = hdr_status && CDR::decoder (&TC_opaque, + hdr_status = hdr_status && msg.decode (&TC_opaque, &req.object_key, 0, - &msg, env); - hdr_status = hdr_status && CDR::decoder (_tc_CORBA_String, + hdr_status = hdr_status && msg.decode (_tc_CORBA_String, &req.operation, 0, - &msg, env); - hdr_status = hdr_status && CDR::decoder (_tc_CORBA_Principal, + hdr_status = hdr_status && msg.decode (_tc_CORBA_Principal, &req.requesting_principal, 0, - &msg, env); // XXX check whether hdr_status identifies a header @@ -1226,10 +1222,9 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, start_message (Reply, response); resp_ctx.length = 0; - CDR::encoder (&TC_ServiceContextList, + response.encode (&TC_ServiceContextList, &resp_ctx, 0, - &response, env); response.put_ulong (req.request_id); @@ -1248,10 +1243,9 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, { ACE_DEBUG((LM_DEBUG, "(%P|%t) forwarding Request message\n")); response.put_ulong (LOCATION_FORWARD); - CDR::encoder (_tc_CORBA_Object, + response.encode (_tc_CORBA_Object, &fwd_ref, 0, - &response, env); CORBA_release (fwd_ref); (void) send_message (response, peer); @@ -1264,10 +1258,9 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, response.put_ulong (SYSTEM_EXCEPTION); - (void) CDR::encoder (_tc_CORBA_OBJECT_NOT_EXIST, + (void) response.encode (_tc_CORBA_OBJECT_NOT_EXIST, &exc, 0, - &response, env); (void) send_message (response, peer); @@ -1290,10 +1283,9 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, start_message (Reply, response); resp_ctx.length = 0; - CDR::encoder (&TC_ServiceContextList, + response.encode (&TC_ServiceContextList, &resp_ctx, 0, - &response, env); response.put_ulong (req.request_id); @@ -1320,7 +1312,7 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, opaque key; msg.get_ulong (request_id); - CDR::decoder (&TC_opaque, &key, 0, &msg, env); + msg.decode (&TC_opaque, &key, 0, env); // we've read the request header; send a LocateReply @@ -1346,8 +1338,7 @@ GIOP::incoming_message (ACE_SOCK_Stream &peer, if (status == OBJECT_FORWARD) { ACE_DEBUG((LM_DEBUG, "LocateRequest response: forward requests\n")); - CDR::encoder (_tc_CORBA_Object, &fwd_ref, 0, - &response, env); + response.encode (_tc_CORBA_Object, &fwd_ref, 0, env); } else if (status == OBJECT_HERE) ACE_DEBUG((LM_DEBUG, "LocateRequest response: object is here!\n")); diff --git a/TAO/IIOP/lib/giop.h b/TAO/IIOP/lib/giop.h index fec7f0b086d..b3d14501528 100644 --- a/TAO/IIOP/lib/giop.h +++ b/TAO/IIOP/lib/giop.h @@ -248,7 +248,7 @@ public: void *value, CORBA_Environment &env) { - (void) CDR::encoder (tc, value, 0, &stream, env); + (void) stream.encode(tc, value, 0, env); } ReplyStatusType invoke (CORBA_ExceptionList &exceptions, @@ -258,7 +258,7 @@ public: void *value, CORBA_Environment &env) { - (void) CDR::decoder (tc, value, 0, &stream, env); + (void) stream.decode (tc, value, 0, env); } // No CORBA_Context support (deprecated). diff --git a/TAO/IIOP/lib/iioporb.cpp b/TAO/IIOP/lib/iioporb.cpp index d54d30da4b0..2b67378bb70 100644 --- a/TAO/IIOP/lib/iioporb.cpp +++ b/TAO/IIOP/lib/iioporb.cpp @@ -78,9 +78,9 @@ IIOP_ORB::object_to_string (CORBA_Object_ptr obj, // Marshal the objref into an encapsulation bytestream. (void) cdr.put_char (MY_BYTE_SEX); - if (CDR::encoder (_tc_CORBA_Object, + if (cdr.encode (_tc_CORBA_Object, &obj, 0, - &cdr, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) return 0; // Now hexify the encapsulated CDR data into a string, and @@ -215,9 +215,9 @@ ior_string_to_object (CORBA_String str, CORBA_Object_ptr objref; stream.setup_encapsulation (buffer, len); - if (CDR::decoder (_tc_CORBA_Object, + if (stream.decode (_tc_CORBA_Object, &objref, 0, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) objref = 0; delete [] buffer; diff --git a/TAO/IIOP/lib/interp.cpp b/TAO/IIOP/lib/interp.cpp index 2bfeb77d337..c38a3550ff9 100644 --- a/TAO/IIOP/lib/interp.cpp +++ b/TAO/IIOP/lib/interp.cpp @@ -69,9 +69,8 @@ #include <assert.h> #include <limits.h> #include <string.h> -#include <orb.h> -#include "debug.h" +#include "orb.h" #include "cdr.h" // Utility routines are used to manipulate CDR-encapsulated TypeCode @@ -612,7 +611,7 @@ 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. -static size_t +size_t calc_key_union_attributes (CDR *stream, size_t &overall_alignment, size_t &discrim_size_with_pad, @@ -1382,7 +1381,7 @@ CORBA_TypeCode::traverse (const void *value1, // this typecode ... typically used to allocate memory. size_t -CORBA_TypeCode::size (CORBA_Environment &env) +CORBA_TypeCode::prv_size (CORBA_Environment &env) { if (_kind >= TC_KIND_COUNT) { @@ -1407,7 +1406,7 @@ CORBA_TypeCode::size (CORBA_Environment &env) // completeness. size_t -CORBA_TypeCode::alignment (CORBA_Environment &env) +CORBA_TypeCode::prv_alignment (CORBA_Environment &env) { if (_kind >= TC_KIND_COUNT) { diff --git a/TAO/IIOP/lib/invoke.cpp b/TAO/IIOP/lib/invoke.cpp index b803f491f25..b0824d84c64 100644 --- a/TAO/IIOP/lib/invoke.cpp +++ b/TAO/IIOP/lib/invoke.cpp @@ -32,10 +32,9 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> -#include <orb.h> +#include "orb.h" #include "cdr.h" -#include "debug.h" #include "giop.h" class ACE_Synchronous_Cancellation_Required diff --git a/TAO/IIOP/lib/marshal.cpp b/TAO/IIOP/lib/marshal.cpp index f37af656c17..64931e8ba78 100644 --- a/TAO/IIOP/lib/marshal.cpp +++ b/TAO/IIOP/lib/marshal.cpp @@ -1,56 +1,32 @@ -// @(#)marshal.cpp 1.7 95/11/04 -// Copyright 1994-1995 by Sun Microsystems Inc. -// All Rights Reserved +// ============================================================================ // -// CDR: Marshaling interpreter +// = LIBRARY +// TAO +// +// = FILENAME +// marshal.cpp // -// This marshaling interpreter is driven by the typecode interpreter. -// The typecode interpreter understands each compiler environment's -// rules for data structure layout; this understands CDR's rules for -// on-the-wire data structure layout. +// = DESCRIPTION +// Implements the MarshalObject class and the factory // -// Apart from some high level rules related to construction of complex -// data types, the marshaling interpreter just knows how to encode -// primitive data types and allocate memory on decode. +// The original encoder and decoder code now appears in files encode.cpp and +// decode.cpp // -// NOTE: to reduce the amount of compiled code, this "knows" facts -// like native float/long/ulong being in legal CDR format, and that -// "char" is native in ISO Latin/1 (so no transformation is needed, -// and octet/char marshaling code is identical). On exotic platforms -// where this is not true, some of the merged "switch" branches will -// need to be split. -// -// REMEMBER: goal is to have the typecode interpreter plus one side of -// the marshaling interpreter reside in a CPU's code cache; or at -// least to have as litle as possible _outside_ cache when marshaling. -// Compiled marshaling code will have a few less instructions, but -// most will of them will be outside the instruction cache; access -// time to get at them will be high. -// -// NOTE: One interesting optimization is inlining the primitive -// put/get calls ... it'd typically save at least 40% in terms of -// instruction count on each of these critical paths by eliminating -// subroutine call overhead. Since it would increase code size, such -// changes might not be desirable on machines with small caches. -// Also, with network I/O being today's most significant bottleneck, -// such optimizations haven't been well explored. -// -// THREADING NOTE: The only threading concern is as always, that data -// structures being manipulated by any given thread must be reserved -// to it by some mechanism (e.g. mutex). This uses no mutable data -// outside of the thread stack, so the onus is entirely on the caller. -// - -#include <assert.h> -#include <limits.h> -#include <string.h> -#include <orb.h> - -#include "debug.h" +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale +// +// ============================================================================ + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "orb.h" +#include "align.h" #include "cdr.h" -#include "giop.h" - #if defined (HAVE_WIDEC_H) # include <widec.h> #else @@ -61,1012 +37,89 @@ extern "C" } #endif -extern CORBA_TypeCode TC_opaque; - -// Encode instances of arbitrary data types based only on typecode. -// "data" points to the data type; if it's not a primitve data type, -// the TypeCode interpreter is used to recursively encode its -// components. "context" is the marshaling stream on which to encode -// the data value. -// -// This is a fairly typical TypeCode interpreter visit() routine; it -// works on a single data value in conjunction with context -// information, and must handle all IDL data types. - -CORBA_TypeCode::traverse_status -CDR::encoder (CORBA_TypeCode_ptr tc, - const void *data, - const void *, - void *context, - CORBA_Environment &env) +// cosntructor for the factory +TAO_MarshalFactory::TAO_MarshalFactory() + : m_primitive_(TAO_MARSHAL_PRIMITIVE::instance()), + m_any_(TAO_MARSHAL_ANY::instance()), + m_typecode_(TAO_MARSHAL_TYPECODE::instance()), + m_principal_(TAO_MARSHAL_PRINCIPAL::instance()), + m_objref_(TAO_MARSHAL_OBJREF::instance()), + m_struct_(TAO_MARSHAL_STRUCT::instance()), + m_union_(TAO_MARSHAL_UNION::instance()), + m_string_(TAO_MARSHAL_STRING::instance()), + m_sequence_(TAO_MARSHAL_SEQUENCE::instance()), + m_array_(TAO_MARSHAL_ARRAY::instance()), + m_alias_(TAO_MARSHAL_ALIAS::instance()), + m_except_(TAO_MARSHAL_EXCEPT::instance()), + m_wstring_(TAO_MARSHAL_WSTRING::instance()) { - CORBA_Boolean continue_encoding = CORBA_B_TRUE; - CDR *stream = (CDR *) context; - - switch (tc->_kind) - { - case tk_null: - case tk_void: - // nothing to encode! - break; - - case tk_char: - case tk_octet: - continue_encoding = stream->put_char (*(char *) data); - break; - - case tk_short: - case tk_ushort: - continue_encoding = stream->put_short (*(short *) data); - break; - - case tk_long: - case tk_ulong: - case tk_float: - continue_encoding = stream->put_long (*(CORBA_Long *) data); - break; - - case tk_double: - case tk_longlong: - case tk_ulonglong: - continue_encoding = stream->put_longlong (*(CORBA_LongLong *) data); - break; - - case tk_boolean: - continue_encoding = stream->put_boolean (*(CORBA_Boolean *) data); - break; - - case tk_enum: - { - // NOTE assumption that this is in-range. - // - // XXX should check this, it's a hard-to-recover error for the - // other side - - u_int value = *(u_int *) data; - continue_encoding = stream->put_ulong (value); - } - break; - - case tk_any: - { - CORBA_Any *any = (CORBA_Any *) data; - - tc = any->type (); - if (encoder (_tc_CORBA_TypeCode, &tc, 0, context, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE) - return CORBA_TypeCode::TRAVERSE_STOP; - - data = any->value (); - return encoder (tc, data, 0, context, env); - } - // NOTREACHED - - case tk_TypeCode: - { - CORBA_TypeCode_ptr tc2; - - tc2 = *(CORBA_TypeCode_ptr *) data; - - continue_encoding = stream->put_ulong ((CORBA_ULong) tc2->_kind); - if (continue_encoding == CORBA_B_FALSE) - break; - - switch (tc2->_kind) - { - // Most TypeCodes have empty parameter lists - default: - break; - - // A few have "simple" parameter lists - case tk_string: - case tk_wstring: - continue_encoding = stream->put_ulong (tc2->_length); - break; - - // Indirected typecodes can't occur at "top level" like - // this, only nested inside others! - case ~0: - dmsg ("indirected typecode at top level!"); - continue_encoding = CORBA_B_FALSE; - break; - - // The rest have "complex" parameter lists that are - // already encoded as bulk octets ... put length, then - // octets. - case tk_objref: - case tk_struct: - case tk_union: - case tk_enum: - case tk_sequence: - case tk_array: - case tk_alias: - case tk_except: - { - continue_encoding = stream->put_ulong (tc2->_length); - - for (u_int i = 0; i < tc2->_length && continue_encoding; i++) - continue_encoding = stream->put_octet (tc2->_buffer [i]); - } - } - } - break; - - case tk_Principal: - { - CORBA_Principal_ptr p = *(CORBA_Principal_ptr *) data; - - if (p != 0) - { - continue_encoding = stream->put_long (p->id.length); - - for (u_int i = 0; continue_encoding && i < p->id.length; i++) - continue_encoding = stream->put_octet (p->id.buffer [i]); - } - else - continue_encoding = stream->put_long (0); - } - break; - - case tk_objref: - - // Current version: objref is really an IIOP_Object. - // - // This will change in the future; STUB_Object knows how to - // marshal itself, that will be used. - // - // XXX this doesn't actually verify that the stuff got written - // OK to the "wire" ... - { - CORBA_Object_ptr obj = *(CORBA_Object_ptr *) data; - - // NIL objrefs ... marshal as empty type hint, no elements. - - if (CORBA_is_nil (obj)) - { - continue_encoding = - stream->put_ulong (1) // strlen - && stream->put_char (0) // NUL - && stream->put_ulong (0); // no profiles - break; - } - - // All other objrefs ... narrow to a "real type" that we - // recognize, then marshal. - // - // XXX this will be changed so it narrows to STUB_Object and - // then asks that surrogate/proxy to marshal itself. - // - // For now, the original code is minimally changed. - - IIOP_Object *objdata; - IIOP::ProfileBody *profile; - - if (obj->QueryInterface (IID_IIOP_Object, - (void **) &objdata) != NOERROR) - { - env.exception (new CORBA_MARSHAL (COMPLETED_NO)); - return CORBA_TypeCode::TRAVERSE_STOP; - } - obj->Release (); - profile = &objdata->profile; - - // STRING, a type ID hint - encoder (_tc_CORBA_String, &objdata->type_id, 0, context, env); - - // UNSIGNED LONG, value one, count of the sequence of - // encapsulated protocol profiles; - stream->put_ulong (1); - - // UNSIGNED LONG, tag for this protocol profile; - stream->put_ulong (IOP::TAG_INTERNET_IOP); - - // UNSIGNED LONG, number of succeeding bytes in the - // encapsulation. We don't actually need to make the - // encapsulation, as nothing needs stronger alignment than - // this longword; it guarantees the rest is aligned for us. - u_int hostlen; - - hostlen = ACE_OS::strlen ((char *) profile->host); - stream->put_ulong (1 // byte order - + 3 // version + pad byte - + 4 // sizeof (strlen) - + hostlen + 1 // strlen + null - + (~hostlen & 01) // optional pad byte - + 2 // port - + (hostlen & 02) // optional pad short - + 4 // sizeof (key length) - + profile->object_key.length); // key length - - // CHAR describing byte order, starting the encapsulation - - stream->put_char (MY_BYTE_SEX); - - // IIOP::Version, two characters (version 1.0) padding - stream->put_char (profile->iiop_version.major); - stream->put_char (profile->iiop_version.minor); - - // STRING hostname from profile - encoder (_tc_CORBA_String, &profile->host, 0, context, env); - - // UNSIGNED SHORT port number - stream->put_ushort (profile->port); - - // OCTET SEQUENCE for object key - encoder (&TC_opaque, &profile->object_key, 0, context, env); - } - break; - - case tk_sequence: - { - // First marshal the sequence length, verifying that it's - // within the sequence bounds ... - CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data; - CORBA_ULong len = seq ? seq->length : 0; - - if (len > 0) - { - CORBA_ULong bounds; - - bounds = tc->ulong_param (1, env); - if (env.exception () != 0) - return CORBA_TypeCode::TRAVERSE_STOP; - - if (bounds != 0 && len > bounds) - { - env.exception (new CORBA_BAD_PARAM (COMPLETED_MAYBE)); - return CORBA_TypeCode::TRAVERSE_STOP; - } - } - continue_encoding = stream->put_ulong (len); - - // Fast exit on error or empty sequence - if (!continue_encoding || len == 0) - break; - } - // FALLTHROUGH - - case tk_struct: - case tk_union: - case tk_array: - case tk_alias: - // Marshal each member in order. - return tc->traverse (data, 0, encoder, context, env); - - case tk_except: - // Convert the the "hidden" TypeCode at the beginning of the - // exception into an on-the-wire ID, then marshal the members in - // order (traversal skips that hidden typecode, and more). - // - // NOTE: This is asymmetric with respect to decoding the - // exception, since whoever decodes must pull off the ID and map - // it to the typecode to be used to unmarshal it (search among - // legal choices). - { - CORBA_String id = tc->id (env); - - if (env.exception () == 0) - { - continue_encoding = - encoder (_tc_CORBA_String, &id, 0, context, env) - == CORBA_TypeCode::TRAVERSE_CONTINUE - && tc->traverse (data, 0, encoder, context, env); - } - else - continue_encoding = CORBA_B_FALSE; - } - break; - - case tk_string: - { - CORBA_String str = *(CORBA_String *) data; - CORBA_ULong len; - CORBA_ULong bounds; - - // Be nice to programmers: treat nulls as empty strings not - // errors. (OMG-IDL supports languages that don't use the - // C/C++ notion of null v. empty strings; nulls aren't part of - // the OMG-IDL string model.) - if (str == 0) - { - stream->put_ulong (1); - stream->put_char (0); - break; - } - - // Verify string satisfies bounds requirements. We're not so - // permissive as to send messages violating the interface spec - // by having excessively long strings! - bounds = tc->ulong_param (0, env); - if (env.exception () != 0) - return CORBA_TypeCode::TRAVERSE_STOP; - len = ACE_OS::strlen ((char *) str); - - if (bounds != 0 && len > bounds) - { - continue_encoding = CORBA_B_FALSE; - break; - } - - // Encode the string, followed by a NUL character. - - for (continue_encoding = stream->put_ulong (len + 1); - continue_encoding != CORBA_B_FALSE && *str; - continue_encoding = stream->put_char (*str++)) - continue; - - stream->put_char (0); - } - break; - - case tk_wstring: - { - CORBA_WChar *str = *(CORBA_WChar **) data; - CORBA_ULong len; - CORBA_ULong bounds; - - // Be nice to programmers: treat nulls as empty strings not - // errors. (OMG-IDL supports languages that don't use the - // C/C++ notion of null v. empty strings; nulls aren't part of - // the OMG-IDL string model.) - - if (str == 0) - { - stream->put_ulong (1); - stream->put_wchar (0); - break; - } - - // Verify wide string satisfies bounds requirements. We're - // not so permissive as to send messages violating the - // interface spec by having excessively long strings! - - bounds = tc->ulong_param (0, env); - if (env.exception () != 0) - return CORBA_TypeCode::TRAVERSE_STOP; - len = wslen (str); - if (bounds != 0 && len > bounds) - { - continue_encoding = CORBA_B_FALSE; - break; - } - - // Encode the wide string, followed by a NUL character. - - for (continue_encoding = stream->put_ulong (wslen (str) + 1); - continue_encoding != CORBA_B_FALSE && *str; - continue_encoding = stream->put_wchar (*str++)) - continue; - - stream->put_wchar (0); - } - break; - - case tk_longdouble: - continue_encoding = stream->put_longdouble (*(CORBA_LongDouble *) data); - break; - - case tk_wchar: - continue_encoding = stream->put_wchar (*(CORBA_WChar *) data); - break; - - // case ~0: - default: - dmsg ("encoder default case ?"); - continue_encoding = CORBA_B_FALSE; - break; - } - - if (continue_encoding == CORBA_B_FALSE) - { - env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); - dmsg ("marshaling encoder detected error"); - return CORBA_TypeCode::TRAVERSE_STOP; - } - return CORBA_TypeCode::TRAVERSE_CONTINUE; } -// This table of TypeCode constants lets us unmarshal most typecodes -// using the predefined constants, rather than constantly reallocating -// them. -// -// XXX CFRONT-based compilers can't cope with this table -// initialization, and need some kind of init function. Luckily, -// they're increasingly rare in any "production" environment. - -#if THE_COMPILER_CAN_FIND_THIS_PROPERLY -// The extern reference in onc/xdr.cpp doesn't seem to be able to find -// this decl with as long as the const is part of it. I even tried -// changing the ref decl to have 'const' in it, to no avail. --cjc -const -#endif -CORBA_TypeCode_ptr __tc_consts [TC_KIND_COUNT] = +TAO_MarshalFactory::~TAO_MarshalFactory() { - _tc_CORBA_Null - , _tc_CORBA_Void - , _tc_CORBA_Short - , _tc_CORBA_Long - , _tc_CORBA_UShort - - , _tc_CORBA_ULong - , _tc_CORBA_Float - , _tc_CORBA_Double - , _tc_CORBA_Boolean - , _tc_CORBA_Char - - , _tc_CORBA_Octet - , _tc_CORBA_Any - , _tc_CORBA_TypeCode - , _tc_CORBA_Principal - , 0 // _tc_CORBA_Object ... type ID is CORBA::Object - - , 0 // tk_struct - , 0 // tk_union - , 0 // tk_enum - , 0 // _tc_CORBA_String ... unbounded - , 0 // tk_sequence - - , 0 // tk_array - - , 0 // tk_alias - , 0 // tk_except - - , _tc_CORBA_LongLong - , _tc_CORBA_ULongLong - , _tc_CORBA_LongDouble - , _tc_CORBA_WChar - , 0 // _tc_CORBA_WString ... unbounded -}; +} -// The decoder is exactly the reverse of the encoder, except that: -// -// * Unmarshaling some data types involve allocating memory. Such -// types include sequences (the buffer), objrefs, Principals, Anys, -// TypeCodes, and strings. +// factory method // -// * The decoder is used when retrieving typecode parameters from -// encapsulations. This means it must deal with "tk_indirect", -// the magic value (~0) signifying typecode indirection. -// -// This second case is identified by a bit of a hack: the second -// "data" value is used to hold the parent typecode, rather than being -// ignored. This means that all other invocations of decoder() ** -// MUST ** pass zero for the second data parameter, in case they -// decode a TypeCode. If they didn't, this case might be signified -// inappropriately. -// -// XXX desirable to have a less hacky solution to that ... pull that -// code out into a separate routine called both by CDR::decoder() and -// by the code retrieving typecode parameters from encapsulations. - -CORBA_TypeCode::traverse_status -CDR::decoder (CORBA_TypeCode_ptr tc, - const void *data, - const void *parent_typecode, - void *context, - CORBA_Environment &env) +// Based on the kind of the typecode, return the appropriate marshal object +TAO_MarshalObject* TAO_MarshalFactory::make_marshal_object(CORBA_TypeCode_ptr tc) { - CORBA_Boolean continue_decoding = CORBA_B_TRUE; - CDR *stream = (CDR *) context; - - switch (tc->_kind) + if (tc) { - case tk_null: - case tk_void: - // nothing to decode! - break; - - case tk_char: - case tk_octet: - continue_decoding = stream->get_char (*(CORBA_Char *) data); - break; - - case tk_short: - case tk_ushort: - continue_decoding = stream->get_short (*(short *) data); - break; - - case tk_long: - case tk_ulong: - case tk_float: - continue_decoding = stream->get_long (*(CORBA_Long *) data); - break; - - case tk_longlong: - case tk_ulonglong: - case tk_double: - continue_decoding = stream->get_longlong (*(CORBA_LongLong *) data); - break; - - case tk_boolean: - continue_decoding = stream->get_boolean (*(CORBA_Boolean *) data); - break; - - case tk_enum: - { - CORBA_ULong val; - - // NOTE assumption that this is in-range. - // - // XXX should check this, it's rather hard to recover from - // such errors since they "do not occur" and are essentially - // never tested for. - continue_decoding = stream->get_ulong (val); - *(u_int *) data = (u_int) val; - } - break; - - case tk_any: - { - CORBA_Any *any = (CORBA_Any *) data; - CORBA_TypeCode_ptr tc2; - void *value; - - if (decoder (_tc_CORBA_TypeCode, - &tc2, 0, - context, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) - return CORBA_TypeCode::TRAVERSE_STOP; - - value = new CORBA_Octet[tc2->size (env)]; - - if (decoder (tc2, - value, 0, - context, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) - { - delete value; - CORBA_release (tc2); - return CORBA_TypeCode::TRAVERSE_STOP; - } - (void) new (any) CORBA_Any (tc2, value, CORBA_B_TRUE); - } - break; - - case tk_TypeCode: - { - CORBA_ULong kind; - CORBA_TypeCode_ptr *tcp; - - continue_decoding = stream->get_ulong (kind); - if (continue_decoding == CORBA_B_FALSE) - break; - if (kind >= TC_KIND_COUNT) - { - continue_decoding = CORBA_B_FALSE; - break; - } - - tcp = (CORBA_TypeCode_ptr *) data; - - // Typecodes with empty parameter lists all have preallocated - // constants. We use those to reduce memory consumption and - // heap access ... also, to speed things up! - - if (((*tcp) = __tc_consts [(u_int) kind]) != 0) - { - *tcp = __tc_consts [(u_int) kind]; - break; - } - else - switch (kind) - { - // Need special handling for all kinds of typecodes that have - // nonempty parameter lists ... - default: // error: missed a case! - env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE)); - return CORBA_TypeCode::TRAVERSE_STOP; - - // Some have "simple" parameter lists ... some of these also - // have preallocated constants that could be used. - case tk_string: - case tk_wstring: - { - CORBA_ULong bound; - - continue_decoding = stream->get_ulong (bound); - if (continue_decoding) { - if (bound == 0) { - if (kind == tk_string) - *tcp = _tc_CORBA_String; - else - *tcp = _tc_CORBA_WString; - } else { - *tcp = new CORBA_TypeCode ((CORBA_TCKind) kind, - bound, 0, CORBA_B_TRUE); - } - } - } - break; - - // Indirected typecodes, illegal at "top level" but we - // allow unmarshaling of them here because we use the same - // code to read "off the wire" (where they're illegal) and - // to read out of an encapsulation stream. We distinguish - // the case where this is legal as described above. - case ~0: - { - CORBA_TypeCode_ptr parent; - - if (parent_typecode == 0) - { - env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE)); - return CORBA_TypeCode::TRAVERSE_STOP; - } - parent = (CORBA_TypeCode_ptr) parent_typecode; - - // Get the long indicating the encapsulation offset, - // then set up indirection stream that's like "stream" - // but has space enough only for the typecode and the - // length for the encapsulated parameters. - CDR indir_stream; - CORBA_Long offset; - - continue_decoding = stream->get_long (offset); - if (continue_decoding) - continue_decoding = (offset < 0); - if (continue_decoding) - { - indir_stream.buffer = indir_stream.next - = stream->next + offset; - indir_stream.remaining = indir_stream.length = 8; - - // Reject indirections outside parent's scope. - if (indir_stream.next < parent->_buffer) - continue_decoding = CORBA_B_FALSE; - } - - // Get "kind" and length of target typecode - // - // XXX this currently assumes the TCKind to which we - // indirect is the same byte order as the "parent" - // typecode -- not the right assumption; see how the - // TypeCode interpreter does it. - - CORBA_ULong indir_kind; - CORBA_ULong indir_len; - - if (continue_decoding) - continue_decoding = stream->get_ulong (indir_kind); - if (continue_decoding - && indir_kind >= TC_KIND_COUNT) - continue_decoding = CORBA_B_FALSE; - if (continue_decoding) - continue_decoding = stream->get_ulong (indir_len); - - // Now construct indirected typecode. This shares the - // typecode octets with the "parent" typecode, - // increasing the amount of memory sharing and - // reducing the cost of getting typecodes. - if (continue_decoding) - { - *tcp = new CORBA_TypeCode ((CORBA_TCKind) indir_kind, - indir_len, - indir_stream.next, - CORBA_B_FALSE); - (*tcp)->_parent = parent; - parent->AddRef (); - } - } - break; - - // The rest have "complex" parameter lists that are - // encoded as bulk octets ... - case tk_objref: - case tk_struct: - case tk_union: - case tk_enum: - case tk_sequence: - case tk_array: - case tk_alias: - case tk_except: - { - u_int len; - u_int i; - CORBA_ULong length; - CORBA_Octet *buffer; - - continue_decoding = stream->get_ulong (length); - if (!continue_decoding) - break; - - // if length > MAXUNSIGNED, error ... - len = (u_int) length; - - buffer = new CORBA_Octet [len]; - - for (i = 0; i < len && continue_decoding; i++) - continue_decoding = stream->get_octet (buffer [i]); - - if (!continue_decoding) { - delete buffer; - break; - } - *tcp = new CORBA_TypeCode ((CORBA_TCKind) kind, - len, - buffer, - CORBA_B_TRUE); - } - } - } - break; - - case tk_Principal: - { - CORBA_Principal_ptr *pp = (CORBA_Principal_ptr *) data; - CORBA_ULong len; - - continue_decoding = stream->get_ulong (len); - if (len == 0) - *pp = 0; - else - { - *pp = new CORBA_Principal; - (*pp)->id.buffer = new CORBA_Octet [(size_t) len]; - (*pp)->id.maximum = (*pp)->id.length = len; - - for (u_int i = 0; - continue_decoding != CORBA_B_FALSE && i < len; - i++) - continue_decoding = stream->get_octet ((*pp)->id.buffer [i]); - } - } - break; - - case tk_objref: - { - // First, read the type hint. - - CORBA_String type_hint; - - decoder (_tc_CORBA_String, &type_hint, 0, context, env); - - // Read the profiles, discarding all until an IIOP profile - // comes by. Once we see an IIOP profile, ignore any further - // ones. - // - // XXX this will need to change someday to let different - // protocol code be accessed, not just IIOP. Protocol modules - // will be dynamically loaded from shared libraries via - // ORB_init(), and we just need to be able to access such - // preloaded libraries here as we unmarshal objrefs. - - CORBA_ULong profiles; - IIOP_Object *objdata = 0; - - stream->get_ulong (profiles); - - // No profiles means a NIL objref. - - if (profiles == 0) - { - *(CORBA_Object_ptr *) data = CORBA_Object::_nil (); - delete type_hint; - break; - } - - while (profiles-- != 0 && continue_decoding) - { - CORBA_ULong tmp; - - stream->get_ulong (tmp); - - if (tmp != IOP::TAG_INTERNET_IOP || objdata != 0) - { - continue_decoding = stream->skip_string (); - continue; - } - - // OK, we've got an IIOP profile. It's going to be - // encapsulated ProfileData. Create a new decoding stream - // and context for it, and tell the "parent" stream that - // this data isn't part of it any more. - - continue_decoding = stream->get_ulong (tmp); - assert (stream->remaining >= tmp); - - // Create the decoding stream from the encapsulation in - // the buffer, and skip the encapsulation. - CDR str; - - str.setup_encapsulation (stream->next, (size_t) tmp); - - stream->next += (u_int) tmp; - stream->remaining -= (u_int) tmp; - - objdata = new IIOP_Object (type_hint); - - IIOP::ProfileBody *profile = &objdata->profile; - - // Read and verify major, minor versions, ignoring IIOP - // profiles whose versions we don't understand. - // - // XXX this doesn't actually go back and skip the whole - // encapsulation... - if (!(str.get_octet (profile->iiop_version.major) - && profile->iiop_version.major == IIOP::MY_MAJOR - && str.get_octet (profile->iiop_version.minor) - && profile->iiop_version.minor <= IIOP::MY_MINOR)) - { - dmsg2 ("detected new v%d.%d IIOP profile", - profile->iiop_version.major, - profile->iiop_version.minor); - objdata->type_id = 0; - objdata->Release (); - objdata = 0; - continue; - } - - // Get host and port - if (decoder (_tc_CORBA_String, &profile->host, 0, &str, env) - != CORBA_TypeCode::TRAVERSE_CONTINUE - || !str.get_ushort (profile->port)) - { - env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); - dmsg ("error decoding IIOP host/port"); - objdata->Release (); - return CORBA_TypeCode::TRAVERSE_STOP; - } - - // ... and object key - - continue_decoding = decoder (&TC_opaque, - &profile->object_key, - 0, - &str, - env) == CORBA_TypeCode::TRAVERSE_CONTINUE; - - if (str.remaining != 0) - { - env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); - dmsg ("extra data at end of IIOP profile data"); - objdata->Release (); - return CORBA_TypeCode::TRAVERSE_STOP; - } - } - if (objdata == 0) - { - env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE)); - dmsg2 ("no IIOP v%d.%d (or earlier) profile in IOR!", - IIOP::MY_MAJOR, IIOP::MY_MINOR); - return CORBA_TypeCode::TRAVERSE_STOP; - } - else - { - if (objdata->QueryInterface (IID_CORBA_Object, - (void **) data) != NOERROR) - continue_decoding = CORBA_B_FALSE; - objdata->Release (); - } - } - break; - - case tk_sequence: - { - // First unmarshal the sequence length ... we trust it to be - // right here, on the "be gracious in what you accept" - // principle. We don't generate illegal sequences - // (i.e. length > bounds). - - CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data; - - continue_decoding = stream->get_ulong (seq->length); - seq->maximum = seq->length; - seq->buffer = 0; - - // Fast exit on empty sequences or errors - if (!continue_decoding || seq->length == 0) - break; - - // ... then allocate the memory into which we'll unmarshal - CORBA_TypeCode_ptr tc2; - size_t size; - - tc2 = tc->typecode_param (0, env); - if (env.exception ()) - return CORBA_TypeCode::TRAVERSE_STOP; - - size = tc2->size (env); - if (env.exception ()) - return CORBA_TypeCode::TRAVERSE_STOP; - - tc2->Release (); - - seq->buffer = new CORBA_Octet [size * (size_t) seq->maximum]; - } - // FALLTHROUGH - - case tk_struct: - case tk_union: - case tk_array: - case tk_alias: - // Unmarshal all the individual elements using the per-member - // description held in the "parent" TypeCode. - - // FALLTHROUGH - - case tk_except: - // For exceptions, the "hidden" type ID near the front of the - // on-wire representation was previously unmarshaled and mapped - // to the "tc" typcode we're using to traverse the memory ... - // at the same time its vtable, refcount, and other state was - // established. - // - // NOTE: This is asymmetric with respect to encoding exceptions. - return tc->traverse (data, 0, decoder, context, env); - - case tk_string: - { - CORBA_String str; - CORBA_ULong len = 0; - - // On decode, omit the check against specified string bounds, - // and cope with illegal "zero length" strings (all lengths on - // the wire must include a NUL). - // - // This is on the principle of being gracious in what we - // accept; we don't generate messages that fail to comply with - // protocol specs, but we will accept them when it's clear how - // to do so. - - continue_decoding = stream->get_ulong (len); - *((CORBA_String*) data) = str = new CORBA_Char [(size_t) (len)]; - - if (len != 0) - while (continue_decoding != CORBA_B_FALSE && len-- != 0) - { - continue_decoding = stream->get_char (*(CORBA_Char *) str); - str++; - } - break; - } - - case tk_wstring: - { - CORBA_WChar *str; - CORBA_ULong len = 0; - - // On decode, omit the check against specified wstring bounds, - // and cope with illegal "zero length" strings (all lengths on - // the wire must include a NUL). - // - // This is on the principle of being gracious in what we - // accept; we don't generate messages that fail to comply with - // protocol specs, but we will accept them when it's clear how - // to do so. - - continue_decoding = stream->get_ulong (len); - - *((CORBA_WChar **) data) = str = new CORBA_WChar [(size_t) (len)]; - - if (len != 0) - while (continue_decoding != CORBA_B_FALSE && len--) - { - continue_decoding = stream->get_wchar (*str); - str++; - } - } - break; - - case tk_longdouble: - continue_decoding = stream->get_longdouble (*(CORBA_LongDouble *) data); - break; - - case tk_wchar: - continue_decoding = stream->get_wchar (*(CORBA_WChar *) data); - break; - - // case ~0: - default: - continue_decoding = CORBA_B_FALSE; - dmsg ("decode, default case?"); - break; + switch(tc->_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_enum: + case tk_double: + case tk_longlong: + case tk_ulonglong: + case tk_boolean: + case tk_char: + case tk_octet: + case tk_longdouble: + case tk_wchar: + return m_primitive_; + case tk_any: + return m_any_; + case tk_TypeCode: + return m_typecode_; + case tk_Principal: + return m_principal_; + case tk_objref: + return m_objref_; + case tk_struct: + return m_struct_; + case tk_union: + return m_union_; + case tk_string: + return m_string_; + case tk_sequence: + return m_sequence_; + case tk_array: + return m_array_; + case tk_alias: + return m_alias_; + case tk_except: + return m_except_; + case tk_wstring: + return m_wstring_; + default: + // anything else is an error + return (TAO_MarshalObject *)0; + } } - - if (continue_decoding == CORBA_B_FALSE) + else { - env.exception (new CORBA_MARSHAL (COMPLETED_NO)); - dmsg ("marshaling decoder detected error"); - return CORBA_TypeCode::TRAVERSE_STOP; + return (TAO_MarshalObject *)0; } - return CORBA_TypeCode::TRAVERSE_CONTINUE; } + +// define a default factory +TAO_MarshalFactory *TAO_DEFAULT_MARSHAL_FACTORY = TAO_MARSHAL_FACTORY::instance(); diff --git a/TAO/IIOP/lib/marshal.h b/TAO/IIOP/lib/marshal.h new file mode 100644 index 00000000000..8c1714488eb --- /dev/null +++ b/TAO/IIOP/lib/marshal.h @@ -0,0 +1,520 @@ +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// marshal.h +// +// = DESCRIPTION +// Classes that marshal various IDL data types. +// +// = AUTHOR +// Aniruddha S. Gokhale +// +// ============================================================================ + +#if !defined (TAO_MARSHAL_H) +#define TAO_MARSHAL_H + +#include <assert.h> +#include "ace/OS.h" +#include "ace/Synch.h" +#include "ace/Singleton.h" + +class TAO_MarshalObject; +class TAO_Marshal_Primitive; +class TAO_Marshal_Any; +class TAO_Marshal_TypeCode; +class TAO_Marshal_Principal; +class TAO_Marshal_ObjRef; +class TAO_Marshal_Struct; +class TAO_Marshal_Union; +class TAO_Marshal_String; +class TAO_Marshal_Sequence; +class TAO_Marshal_Array; +class TAO_Marshal_Alias; +class TAO_Marshal_Except; +class TAO_Marshal_WString; + +class TAO_MarshalFactory +{ + // = TITLE + // A Factory for generating specialized marshaling objects + // + // = DESCRIPTION + // +public: + TAO_MarshalFactory(void); + // constructor + + ~TAO_MarshalFactory(); + // destructor + + virtual TAO_MarshalObject *make_marshal_object(CORBA_TypeCode_ptr tc); + // factory method that returns the appropriate marshal object +private: + // define data members that are instances of various MarshalObject classes + TAO_Marshal_Primitive *m_primitive_; + TAO_Marshal_Any *m_any_; + TAO_Marshal_TypeCode *m_typecode_; + TAO_Marshal_Principal *m_principal_; + TAO_Marshal_ObjRef *m_objref_; + TAO_Marshal_Struct *m_struct_; + TAO_Marshal_Union *m_union_; + TAO_Marshal_String *m_string_; + TAO_Marshal_Sequence *m_sequence_; + TAO_Marshal_Array *m_array_; + TAO_Marshal_Alias *m_alias_; + TAO_Marshal_Except *m_except_; + TAO_Marshal_WString *m_wstring_; +}; + +// Create a type for the singleton factory +typedef ACE_Singleton<TAO_MarshalFactory, ACE_Thread_Mutex> TAO_MARSHAL_FACTORY; + +// define a default marshal factory to be used by the interpretive marshaling +// engine +extern TAO_MarshalFactory *TAO_DEFAULT_MARSHAL_FACTORY; + +class TAO_MarshalObject +{ + // = TITLE + // The Marshaling object that provides a common interface to the CDR object + // for marshaling different IDL data types + // = DESCRIPTION + // Provides a set of virtual methods for encoding, decoding, + // deep_copying, and deep_freeing. +public: + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env) = 0; + // encoding operation + + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env) = 0; + // decoding operation + + TAO_MarshalObject(void); + // constructor + + virtual ~TAO_MarshalObject(); + // destructor +}; + +class TAO_Marshal_Primitive: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Primitive(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Primitive, ACE_Thread_Mutex> TAO_MARSHAL_PRIMITIVE; + +class TAO_Marshal_Any: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Any(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *source, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Any, ACE_Thread_Mutex> TAO_MARSHAL_ANY; + +class TAO_Marshal_TypeCode: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_TypeCode(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_TypeCode, ACE_Thread_Mutex> TAO_MARSHAL_TYPECODE; + +class TAO_Marshal_Principal: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Principal(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Principal, ACE_Thread_Mutex> TAO_MARSHAL_PRINCIPAL; + +class TAO_Marshal_ObjRef: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_ObjRef(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_ObjRef, ACE_Thread_Mutex> TAO_MARSHAL_OBJREF; + +class TAO_Marshal_Struct: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Struct(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Struct, ACE_Thread_Mutex> TAO_MARSHAL_STRUCT; + +class TAO_Marshal_Union: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Union(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Union, ACE_Thread_Mutex> TAO_MARSHAL_UNION; + +class TAO_Marshal_String: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_String(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_String, ACE_Thread_Mutex> TAO_MARSHAL_STRING; + +class TAO_Marshal_Sequence: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Sequence(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Sequence, ACE_Thread_Mutex> TAO_MARSHAL_SEQUENCE; + +class TAO_Marshal_Array: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Array(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Array, ACE_Thread_Mutex> TAO_MARSHAL_ARRAY; + +class TAO_Marshal_Alias: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Alias(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Alias, ACE_Thread_Mutex> TAO_MARSHAL_ALIAS; + +class TAO_Marshal_Except: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_Except(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_Except, ACE_Thread_Mutex> TAO_MARSHAL_EXCEPT; + +class TAO_Marshal_WString: public TAO_MarshalObject +{ + // = TITLE + // = DESCRIPTION +public: + TAO_Marshal_WString(void); + + virtual CORBA_TypeCode::traverse_status encode (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + void *context, + CORBA_Environment &env); + virtual CORBA_TypeCode::traverse_status decode (CORBA_TypeCode_ptr tc, + const void *data, + const void *parent_typecode, + void *context, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_copy (CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env); + static CORBA_TypeCode::traverse_status deep_free (CORBA_TypeCode_ptr tc, + const void *data, + const void *, + CORBA_Environment &env); +}; + +// Create a type for the singleton +typedef ACE_Singleton<TAO_Marshal_WString, ACE_Thread_Mutex> TAO_MARSHAL_WSTRING; + +// In this case, we make a substantial exception to how inline +// files are included. Normally, we would conditionally include the +// inline file iff __ACE_INLINE__ is defined. But, in the original, +// highly optimized Sun IIOP code, much of what is in the inline file +// was here ready to be inlined at a moments notice and ALWAYS. So, +// in this ONE file, we defer to David Brownell's considerable prowess +// at creating typecode interpreters as well as to the ACE convention +// of placing inline functions into separate files. +# if !defined(__ACE_INLINE__) +# undef ACE_INLINE +# define ACE_INLINE inline +# define do_undef_on_ACE_INLINE +# endif +# include "marshal.i" +# if defined(do_undef_on_ACE_INLINE) +# undef do_undef_on_ACE_INLINE +# undef ACE_INLINE +# define ACE_INLINE +# endif + +#endif diff --git a/TAO/IIOP/lib/marshal.i b/TAO/IIOP/lib/marshal.i new file mode 100644 index 00000000000..346dbfaf479 --- /dev/null +++ b/TAO/IIOP/lib/marshal.i @@ -0,0 +1,216 @@ +// constructor for the various MarshalObject classes +ACE_INLINE TAO_MarshalObject::TAO_MarshalObject() +{ +} + +ACE_INLINE TAO_Marshal_Primitive::TAO_Marshal_Primitive() +{ +} + +ACE_INLINE TAO_Marshal_Any::TAO_Marshal_Any() +{ +} + +ACE_INLINE TAO_Marshal_Principal::TAO_Marshal_Principal() +{ +} + +ACE_INLINE TAO_Marshal_TypeCode::TAO_Marshal_TypeCode() +{ +} + +ACE_INLINE TAO_Marshal_ObjRef::TAO_Marshal_ObjRef() +{ +} + +ACE_INLINE TAO_Marshal_Struct::TAO_Marshal_Struct() +{ +} + +ACE_INLINE TAO_Marshal_Union::TAO_Marshal_Union() +{ +} + +ACE_INLINE TAO_Marshal_String::TAO_Marshal_String() +{ +} + +ACE_INLINE TAO_Marshal_Sequence::TAO_Marshal_Sequence() +{ +} + +ACE_INLINE TAO_Marshal_Array::TAO_Marshal_Array() +{ +} + +ACE_INLINE TAO_Marshal_Alias::TAO_Marshal_Alias() +{ +} + +ACE_INLINE TAO_Marshal_Except::TAO_Marshal_Except() +{ +} + +ACE_INLINE TAO_Marshal_WString::TAO_Marshal_WString() +{ +} + +//destructor for the MarshalObject class +ACE_INLINE TAO_MarshalObject::~TAO_MarshalObject() +{ +} + +// the deep_copy methods + +// deep_copy for any +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_Any::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + (void) new (dest) CORBA_Any (*(CORBA_Any*) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_copy for TypeCode +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_TypeCode::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + if ((*(CORBA_TypeCode_ptr *) source) != 0) + dest = source; + else + dest = _tc_CORBA_Null; + + ((CORBA_TypeCode_ptr) dest)->AddRef (); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_copy for ObjRef +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_ObjRef::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + *(CORBA_Object_ptr *) dest = CORBA_Object::_duplicate (*(CORBA_Object_ptr *) + source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_copy for string +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_String::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + *(CORBA_String *) dest = CORBA_string_copy (*(CORBA_String *) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_copy for wstring +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_WString::deep_copy( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + *(CORBA_WString *) dest = CORBA_wstring_copy (*(CORBA_WString *) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// *************** deep_free methods ****************** + +// deep_free for Any +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_Any::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + ((CORBA_Any *) source)->~CORBA_Any (); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_free for TypeCode +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_TypeCode::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + if ((*(CORBA_TypeCode_ptr *) source) != 0) + (*(CORBA_TypeCode_ptr *) source)->Release (); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_free for Principal +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_Principal::deep_free( + CORBA_TypeCode_ptr tc, + const void *value, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_release (*(CORBA_Principal_ptr *) value); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_free for ObjRef +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_ObjRef::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_release (*(CORBA_Object_ptr *) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_free for string +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_String::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_string_free (*(CORBA_String *) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + +// deep_free for wstring +ACE_INLINE CORBA_TypeCode::traverse_status +TAO_Marshal_WString::deep_free( + CORBA_TypeCode_ptr tc, + const void *source, + const void *dest, + CORBA_Environment &env + ) +{ + CORBA_wstring_free (*(CORBA_WString *) source); + return CORBA_TypeCode::TRAVERSE_CONTINUE; +} + diff --git a/TAO/IIOP/lib/nvlist.cpp b/TAO/IIOP/lib/nvlist.cpp index f9fe2742640..52eb8c6379c 100644 --- a/TAO/IIOP/lib/nvlist.cpp +++ b/TAO/IIOP/lib/nvlist.cpp @@ -8,12 +8,10 @@ #if !defined (VXWORKS) #include <memory.h> #endif -#include <orb.h> +#include "orb.h" #include <initguid.h> -#include "debug.h" - // COM's IUnknown support // {77420087-F276-11ce-9598-0000C07CA898} diff --git a/TAO/IIOP/lib/object.cpp b/TAO/IIOP/lib/object.cpp index 8c561584ddf..4feb6ec201d 100644 --- a/TAO/IIOP/lib/object.cpp +++ b/TAO/IIOP/lib/object.cpp @@ -8,12 +8,11 @@ #include <assert.h> #include <limits.h> #include <string.h> + #include "orb.h" #include "object.h" #include "optable.h" - -#include <stub.h> -#include "debug.h" +#include "stub.h" #include <initguid.h> diff --git a/TAO/IIOP/lib/object.h b/TAO/IIOP/lib/object.h index 2e586d32fb7..19403020dbd 100644 --- a/TAO/IIOP/lib/object.h +++ b/TAO/IIOP/lib/object.h @@ -138,8 +138,24 @@ private: // XXX need CORBA_Object_var class typedef -#if defined(__ACE_INLINE__) +// In this case, we make a substantial exception to how inline +// files are included. Normally, we would conditionally include the +// inline file iff __ACE_INLINE__ is defined. But, in the original, +// highly optimized Sun IIOP code, much of what is in the inline file +// was here ready to be inlined at a moments notice and ALWAYS. So, +// in this ONE file, we defer to David Brownell's considerable prowess +// at creating typecode interpreters as well as to the ACE convention +// of placing inline functions into separate files. +# if !defined(__ACE_INLINE__) +# undef ACE_INLINE +# define ACE_INLINE inline +# define do_undef_on_ACE_INLINE +# endif # include "object.i" -#endif +# if defined(do_undef_on_ACE_INLINE) +# undef do_undef_on_ACE_INLINE +# undef ACE_INLINE +# define ACE_INLINE +# endif #endif /* CORBA_OBJECT_H */ diff --git a/TAO/IIOP/lib/orb.h b/TAO/IIOP/lib/orb.h index 2d2be34bb92..5047e71227f 100644 --- a/TAO/IIOP/lib/orb.h +++ b/TAO/IIOP/lib/orb.h @@ -111,8 +111,9 @@ typedef void (*TAO_Skeleton)(CORBA_ServerRequest &, #include "any.h" #include "nvlist.h" #include "request.h" -#include "svrrqst.h" #include "object.h" +#include "svrrqst.h" +#include "debug.h" // gets included only if the DEBUG flag is set #if !defined(__IIOP_BUILD) # include "boa.h" diff --git a/TAO/IIOP/lib/orbobj.cpp b/TAO/IIOP/lib/orbobj.cpp index c99a417f169..4f77c2cff18 100644 --- a/TAO/IIOP/lib/orbobj.cpp +++ b/TAO/IIOP/lib/orbobj.cpp @@ -16,7 +16,6 @@ #include "orb.h" #include "stub.h" -#include "debug.h" #include "iioporb.h" // XXX #include "params.h" diff --git a/TAO/IIOP/lib/request.cpp b/TAO/IIOP/lib/request.cpp index 73d96e1d111..520193508a6 100644 --- a/TAO/IIOP/lib/request.cpp +++ b/TAO/IIOP/lib/request.cpp @@ -4,12 +4,10 @@ // // Implementation of Dynamic Invocation Interface // -#include <orb.h> -#include <stub.h> - +#include "orb.h" +#include "stub.h" #include <initguid.h> -#include "debug.h" #include "cdr.h" // {77420085-F276-11ce-9598-0000C07CA898} diff --git a/TAO/IIOP/lib/roa.cpp b/TAO/IIOP/lib/roa.cpp index d57a246bfda..e0f4e4ca483 100644 --- a/TAO/IIOP/lib/roa.cpp +++ b/TAO/IIOP/lib/roa.cpp @@ -1,7 +1,6 @@ // $Id$ #include "orb.h" -#include "debug.h" #include "roa.h" #include "boa.h" #include "cdr.h" @@ -579,7 +578,7 @@ request_dispatcher (GIOP::RequestHeader &req, CORBA_TypeCode_ptr except_tc = x->type (); reply->put_ulong (GIOP::SYSTEM_EXCEPTION); - (void) CDR::encoder (except_tc, x, 0, reply, env2); + (void) reply->encode (except_tc, x, 0, env2); } else if (svr_req._exception) { // any exception at all @@ -597,7 +596,7 @@ request_dispatcher (GIOP::RequestHeader &req, else reply->put_ulong (GIOP::USER_EXCEPTION); - (void) CDR::encoder (except_tc, x, 0, reply, env); + (void) reply->encode (except_tc, x, 0, env); } else { // normal reply @@ -609,7 +608,7 @@ request_dispatcher (GIOP::RequestHeader &req, { tc = svr_req._retval->type (); value = svr_req._retval->value (); - (void) CDR::encoder (tc, value, 0, reply, env); + (void) reply->encode (tc, value, 0, env); } // ... followed by "inout" and "out" parameters, left to right @@ -624,7 +623,7 @@ request_dispatcher (GIOP::RequestHeader &req, any = nv->value (); tc = any->type (); value = any->value (); - (void) CDR::encoder (tc, value, 0, reply, env); + (void) reply->encode (tc, value, 0, env); } } } diff --git a/TAO/IIOP/lib/svrrqst.cpp b/TAO/IIOP/lib/svrrqst.cpp index 4dc7c3cbdba..a259739c65c 100644 --- a/TAO/IIOP/lib/svrrqst.cpp +++ b/TAO/IIOP/lib/svrrqst.cpp @@ -4,13 +4,9 @@ // // Implementation of the Dynamic Server Skeleton Interface -#include <orb.h> - +#include "orb.h" #include <initguid.h> - -#include "debug.h" #include "cdr.h" - #include "svrrqst.h" // {77420086-F276-11ce-9598-0000C07CA898} @@ -132,7 +128,7 @@ IIOP_ServerRequest::params (CORBA_NVList_ptr list, tc->Release (); // Then just unmarshal the value. - (void) CDR::decoder (tc, value, 0, _incoming, env); + (void) _incoming->decode (tc, value, 0, env); } // If any data is left over, it'd be context values ... else error. diff --git a/TAO/IIOP/lib/t-xdr.cpp b/TAO/IIOP/lib/t-xdr.cpp index 4729082975e..8a4d82132bd 100644 --- a/TAO/IIOP/lib/t-xdr.cpp +++ b/TAO/IIOP/lib/t-xdr.cpp @@ -168,12 +168,12 @@ do_test (int use_XDR, ; if (status) - status = CDR::encoder (&TC_opaque, &key, 0, &stream, env) + status = stream.encode (&TC_opaque, &key, 0, env) == CORBA_TypeCode::TRAVERSE_CONTINUE; if (status) - status = CDR::encoder (_tc_CORBA_String, &opname, - 0, &stream, env) + status = stream.encode (_tc_CORBA_String, &opname, + 0, env) == CORBA_TypeCode::TRAVERSE_CONTINUE; /* @@ -188,12 +188,12 @@ do_test (int use_XDR, && stream.put_long (99) && stream.put_long (-3455); if (status) - status = CDR::encoder (_tc_CORBA_String, &opname, - 0, &stream, env) + status = stream.encode (_tc_CORBA_String, &opname, + 0, env) == CORBA_TypeCode::TRAVERSE_CONTINUE; // Gratuitous extra "interesting" data - status = CDR::encoder (tc, data, 0, &stream, env) + status = stream.encode (tc, data, 0, env) == CORBA_TypeCode::TRAVERSE_CONTINUE; diff --git a/TAO/IIOP/lib/tc_const.cpp b/TAO/IIOP/lib/tc_const.cpp index 20b22c79508..d398044a5ce 100644 --- a/TAO/IIOP/lib/tc_const.cpp +++ b/TAO/IIOP/lib/tc_const.cpp @@ -83,10 +83,27 @@ const CORBA_TypeCode_ptr _tc_CORBA_Char = &tc_char; static CORBA_TypeCode tc_wchar (tk_wchar); const CORBA_TypeCode_ptr _tc_CORBA_WChar = &tc_wchar; -static CORBA_TypeCode tc_string (tk_string); +// a string/wstring have a simple parameter list that indicates the length +static const CORBA_Long _oc_string [] = +{ // CDR typecode octets + 1, // native endian + padding; "tricky" + 0 // ... unbounded string +}; +static CORBA_TypeCode tc_string (tk_string, + sizeof _oc_string, + (u_char *) &_oc_string, + CORBA_B_FALSE); const CORBA_TypeCode_ptr _tc_CORBA_String = &tc_string; -static CORBA_TypeCode tc_wstring (tk_wstring); +static const CORBA_Long _oc_wstring [] = +{ // CDR typecode octets + 1, // native endian + padding; "tricky" + 0 // ... unbounded string +}; +static CORBA_TypeCode tc_wstring (tk_wstring, + sizeof _oc_wstring, + (u_char *) &_oc_wstring, + CORBA_B_FALSE); const CORBA_TypeCode_ptr _tc_CORBA_WString = &tc_wstring; // diff --git a/TAO/IIOP/lib/typecode.cpp b/TAO/IIOP/lib/typecode.cpp index a8a7d7624c8..92ad1cdd3c0 100644 --- a/TAO/IIOP/lib/typecode.cpp +++ b/TAO/IIOP/lib/typecode.cpp @@ -19,42 +19,48 @@ #include <assert.h> #include <limits.h> #include <string.h> -#include <orb.h> - -#include "debug.h" -#include "cdr.h" #if !defined (VXWORKS) #include <memory.h> #endif #include <sys/types.h> +#include "orb.h" +#include "cdr.h" #include <initguid.h> - -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) +size_t calc_key_union_attributes(CDR *stream, + size_t &alignment, + size_t &size_with_pad, + CORBA_Environment &env); + + +// constructor for the private state +TC_PRV_State::TC_PRV_State() + : 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) { } @@ -70,7 +76,8 @@ CORBA_TypeCode::CORBA_TypeCode (CORBA_TCKind kind, _kind (kind), _parent (0), _refcount (1), - _orb_owns (orb_owns_tc) + _orb_owns (orb_owns_tc), + _prv_state (new TC_PRV_State) { // The CDR code used to interpret TypeCodes requires in-memory // alignments to match the "on-the-wire" alignments, simplifying @@ -95,21 +102,22 @@ CORBA_TypeCode::CORBA_TypeCode (CORBA_TCKind kind, temp &= ~0x03; _buffer = (CORBA_Octet *) temp; - (void) ACE_OS::memcpy (_buffer, buffer, (size_t) length); + (void) ACE_OS::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. +// decreases the refcount and deletes when refcount reaches 0 +void CORBA_release (CORBA_TypeCode_ptr tc) +{ + if (tc) + tc->Release (); +} -CORBA_TypeCode::~CORBA_TypeCode (void) +// returns true if the typecode is NULL +CORBA_Boolean CORBA_is_nil (CORBA_TypeCode_ptr tc) { - if (_parent) - _parent->Release (); - else if (_orb_owns) - delete _buffer; + return (CORBA_Boolean) tc == 0; } // COM's IUnknown support @@ -118,6 +126,7 @@ CORBA_TypeCode::~CORBA_TypeCode (void) DEFINE_GUID (IID_CORBA_TypeCode, 0xa201e4c1, 0xf258, 0x11ce, 0x95, 0x98, 0x0, 0x0, 0xc0, 0x7c, 0xa8, 0x98); +// COM stuff ULONG __stdcall CORBA_TypeCode::AddRef (void) { @@ -126,6 +135,7 @@ CORBA_TypeCode::AddRef (void) return _refcount++; } +// COM stuff ULONG __stdcall CORBA_TypeCode::Release (void) { @@ -140,6 +150,7 @@ CORBA_TypeCode::Release (void) return 0; } +// COM stuff HRESULT __stdcall CORBA_TypeCode::QueryInterface (REFIID riid, void **ppv) @@ -156,134 +167,640 @@ CORBA_TypeCode::QueryInterface (REFIID riid, return NOERROR; } -// just fetch the 'kind' field out of the typecode - -CORBA_TCKind -CORBA_TypeCode::kind (CORBA_Environment &env) const +CORBA_Boolean +CORBA_TypeCode::prv_equal(CORBA_TypeCode_ptr tc, CORBA_Environment &env) const { - env.clear (); - return _kind; + // We come in here only if the typecode kinds of both are same + // Handle each complex typecode separately + switch (_kind) + { + case tk_null: + case tk_void: + case tk_short: + case tk_ushort: + case tk_long: + case tk_ulong: + case tk_float: + case tk_double: + case tk_longlong: + case tk_longdouble: + case tk_boolean: + case tk_octet: + case tk_char: + case tk_wchar: + case tk_TypeCode: + case tk_Principal: + // all these are simple typecodes and the comparison is based solely on + // the _kind field + return CORBA_B_TRUE; + case tk_objref: + // return prv_equal_objref(tc, env); + case tk_struct: + // return prv_equal_struct(tc, env); + case tk_union: + // return prv_equal_union(tc, env); + case tk_enum: + // return prv_equal_enum(tc, env); + case tk_string: + // return prv_equal_string(tc, env); + case tk_wstring: + // return prv_equal_string(tc, env); + case tk_sequence: + // return prv_equal_sequence(tc, env); + case tk_array: + // return prv_equal_array(tc, env); + case tk_alias: + // return prv_equal_alias(tc, env); + case tk_except: + // return prv_equal_except(tc, env); + // Not implemented yet + return CORBA_B_FALSE; + } } -// skip a typecode encoding in a given CDR stream - -static CORBA_Boolean -skip_typecode (CDR &stream) +// 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. +const CORBA_String +CORBA_TypeCode::prv_id (CORBA_Environment &env) const { - CORBA_ULong kind; - CORBA_ULong temp; - - if (!stream.get_ulong (kind) || kind >= TC_KIND_COUNT) - return CORBA_B_FALSE; + env.clear (); - switch (kind) + switch (_kind) { - // Most TypeCodes have empty parameter lists, nothing to skip + // 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: + _prv_state->tc_id_known_ = CORBA_B_TRUE; + _prv_state->tc_id_ = (CORBA_String) (_buffer + + 4 // skip byte order flag and padding + + 4 // skip (strlen + 1) + ); + return _prv_state->tc_id_; + // No other typecodes ever have type IDs default: - break; + env.exception (new CORBA_BadKind ()); + return 0; + } +} - // Some have single integer parameters, easy to skip. Some have - // preallocated constants that could be used. - case tk_string: - case tk_wstring: - case ~0: - return stream.get_ulong (temp); +// return the name. The string is owned by the typecode +const CORBA_String +CORBA_TypeCode::prv_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! - // 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; + { + CORBA_ULong len; + CDR stream; + + stream.setup_encapsulation (_buffer, (size_t)_length); + + // skip the typecode ID + if (stream.skip_string ()) // ID + { + _prv_state->tc_name_known_ = CORBA_B_TRUE; + _prv_state->tc_name_ = (CORBA_String)(stream.next + + + CDR::LONG_SIZE); // skip past the length field + return _prv_state->tc_name_; + } + else + { + env.exception(new CORBA_INTERNAL(COMPLETED_NO)); + return (CORBA_String)0; + } + // No other typecodes ever have type IDs + } + break; + default: + env.exception (new CORBA_BadKind ()); + return 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::prv_member_count (CORBA_Environment &env) const +{ + env.clear (); + + switch (_kind) + { + case tk_alias: + // tc_member_count_known_ = CORBA_B_TRUE; + //tc_member_count_ = 1; + return 1; + + case tk_enum: + 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; + } + + _prv_state->tc_member_count_known_ = CORBA_B_TRUE; + _prv_state->tc_member_count_ = members; + return _prv_state->tc_member_count_; + } + 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 + { + // this is a system exception indicating something is wrong with + // the typecode itself. + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + return 0; + } - return CORBA_B_TRUE; + _prv_state->tc_member_count_known_ = CORBA_B_TRUE; + _prv_state->tc_member_count_ = members; + return _prv_state->tc_member_count_; + } + default: + env.exception(new CORBA_BadKind()); + return 0; + } } +// Return the name for the nth member +// Applicable only to tk_struct, tk_union, and tk_except +const CORBA_String +CORBA_TypeCode::member_name(CORBA_ULong index, CORBA_Environment &env) const +{ + return 0; +} -// Return member labels for tk_union typecodes. +// 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_Any_ptr -CORBA_TypeCode::member_label (CORBA_ULong n, - CORBA_Environment &env) const +CORBA_TypeCode_ptr +CORBA_TypeCode::prv_member_type (CORBA_ULong index, CORBA_Environment &env) const { - env.clear (); + 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 tk_except: + case 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 + _prv_state->tc_member_type_list_ = new CORBA_TypeCode_ptr [mcount]; + if (_prv_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 (COMPLETED_NO)); + return (CORBA_TypeCode_ptr)0; + } + else + { + CORBA_ULong i; + + // compute the typecodes for all the members and return the + // required one + for (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 (_tc_CORBA_TypeCode, + &_prv_state->tc_member_type_list_[i], + this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE) + { + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + return 0; + } + } + _prv_state->tc_member_type_list_known_ = CORBA_B_TRUE; + if (index >= 0 && index < mcount) + { + return CORBA_TypeCode::_duplicate(_prv_state->tc_member_type_list_[index]); + } + else + { + env.exception(new CORBA_Bounds()); + return (CORBA_TypeCode_ptr)0; + } + } + } + else // no memory for the member_list + { + env.exception(new CORBA_NO_MEMORY(COMPLETED_NO)); + return (CORBA_TypeCode_ptr)0; + } + } + else // out of bounds + { + env.exception (new CORBA_Bounds()); + return (CORBA_TypeCode_ptr)0; + } + case 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 + _prv_state->tc_member_type_list_ = new CORBA_TypeCode_ptr [mcount]; + if (_prv_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 + || stream.decode (_tc_CORBA_TypeCode, + &tc, this, + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) // TC + { // member count + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + return (CORBA_TypeCode_ptr)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; + } + else + { + CORBA_ULong i; + CORBA_Long scratch; // always big enough + // compute the typecodes for all the members and return the + // required one + for (i = 0; i < temp; 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 (_tc_CORBA_TypeCode, // get the typecode + &_prv_state->tc_member_type_list_[i], + this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE) + { + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + return 0; + } + } + _prv_state->tc_member_type_list_known_ = CORBA_B_TRUE; + if (index >= 0 && index < mcount) + { + return CORBA_TypeCode::_duplicate(_prv_state->tc_member_type_list_[index]); + } + else + { + env.exception(new CORBA_Bounds()); + return (CORBA_TypeCode_ptr)0; + } + } + } + else // no memory for the member_list + { + env.exception(new CORBA_NO_MEMORY(COMPLETED_NO)); + return (CORBA_TypeCode_ptr)0; + } + } + else // out of bounds + { + env.exception (new CORBA_Bounds()); + return (CORBA_TypeCode_ptr)0; + } + + default: + // bad kind + env.exception(new CORBA_BadKind()); + return (CORBA_TypeCode_ptr)0; + } +} + +// Return member labels for tk_union typecodes. +CORBA_Any_ptr +CORBA_TypeCode::prv_member_label (CORBA_ULong n, + CORBA_Environment &env) const +{ + env.clear (); + // this function is only applicable to the tk_union TC - if (_kind != tk_union) + if (_kind == tk_union) { - env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + 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 + || stream.decode (_tc_CORBA_TypeCode, &tc, this, 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)); + dmsg ("TypeCode::prv_member_label -- error reading from stream"); + return 0; + } + + _prv_state->tc_member_label_list_ = new CORBA_Any_ptr [member_count]; + if (_prv_state->tc_member_label_list_) + { + 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::prv_member_label -- error getting typecode\ +for member %d",i); + delete [] buf; + // XXX-Andy: free this list on error + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); + return 0; + } + else + { + _prv_state->tc_member_label_list_[i] = new CORBA_Any (tc, buf, CORBA_B_TRUE); + } + } + } + else + { + env.exception(new CORBA_NO_MEMORY(COMPLETED_NO)); + return 0; + } + + _prv_state->tc_member_label_list_known_ = CORBA_B_TRUE; + tc->Release (); + + // If caller asked for the label for a nonexistent member, they get + // an error report! + if (n >= member_count) + { + env.exception (new CORBA_Bounds ()); + return 0; + } + else + { + return _prv_state->tc_member_label_list_[n]; + } + } + else // wrong typecode + { + env.exception(new CORBA_BadKind()); return 0; } +} - // skip ID and name, and then get the discriminant TC - CORBA_TypeCode_ptr tc = 0; +CORBA_TypeCode_ptr +CORBA_TypeCode::prv_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 - || 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)) + || !stream.skip_string () // typedef name + || stream.decode (_tc_CORBA_TypeCode, + &_prv_state->tc_discriminator_type_, this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); return 0; } + else + { + _prv_state->tc_discriminator_type_known_ = CORBA_B_TRUE; + return CORBA_TypeCode::_duplicate(_prv_state->tc_discriminator_type_); + } +} + +CORBA_Long +CORBA_TypeCode::prv_default_index (CORBA_Environment &env) const +{ + CDR stream; + CORBA_TypeCode_ptr tc = 0; + + stream.setup_encapsulation (_buffer, (size_t)_length); - // If caller asked for the label for a nonexistent member, they get - // an error report! - if (n >= member_count) + // skip ID and name, and then get the discriminant TC + + if (!stream.skip_string () // type ID, hidden + || !stream.skip_string () // typedef name + || stream.decode (_tc_CORBA_TypeCode, + &tc, this, env) != CORBA_TypeCode::TRAVERSE_CONTINUE + || !stream.get_long(_prv_state->tc_default_index_used_)) + { - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); + env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); return 0; } + else + { + _prv_state->tc_default_index_used_known_ = CORBA_B_TRUE; + return _prv_state->tc_default_index_used_; + } +} - // 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. +CORBA_Long +CORBA_TypeCode::prv_length (CORBA_Environment &env) const +{ + CDR stream; + CORBA_TypeCode_ptr tc = 0; - void *buf = new CORBA_Octet [tc->size (env)]; + stream.setup_encapsulation (_buffer, (size_t)_length); + switch (_kind) + { + case tk_sequence: + case tk_array: + { + // skip the typecode of the element and get the bounds + if (stream.decode (_tc_CORBA_TypeCode, &tc, this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE // skip typecode + || !stream.get_ulong(_prv_state->tc_length_)) + { + env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); + return 0; + } + else + { + _prv_state->tc_length_known_ = CORBA_B_TRUE; + return _prv_state->tc_length_; + } + break; + case tk_string: + case tk_wstring: + { + if (stream.get_ulong(_prv_state->tc_length_)) + { + _prv_state->tc_length_known_ = CORBA_B_TRUE; + return _prv_state->tc_length_; + } + else + { + env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); + return 0; + } + } + default: + env.exception (new CORBA_BadKind); + return 0; + } + } +} - if (env.exception () != 0) - return 0; +CORBA_TypeCode_ptr +CORBA_TypeCode::prv_content_type (CORBA_Environment &env) const +{ + CDR stream; + CORBA_TypeCode_ptr tc = 0; - for (CORBA_ULong i = 0; i <= n; i++) + stream.setup_encapsulation (_buffer, (size_t)_length); + switch (_kind) { - 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; + case tk_sequence: + case tk_array: + { + // skip the typecode of the element and get the bounds + if (stream.decode (_tc_CORBA_TypeCode, &_prv_state->tc_content_type_, + this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE) // element type + { + env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); + return 0; + } + else + { + _prv_state->tc_content_type_known_ = CORBA_B_TRUE; + return CORBA_TypeCode::_duplicate(_prv_state->tc_content_type_); + } + break; + case tk_alias: + { + if (!stream.skip_string() // typeID + || !stream.skip_string() // name + || stream.decode (_tc_CORBA_TypeCode, + &_prv_state->tc_content_type_, this, env) != + CORBA_TypeCode::TRAVERSE_CONTINUE) + { + env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); + return 0; + } + else + { + _prv_state->tc_content_type_known_ = CORBA_B_TRUE; + return CORBA_TypeCode::_duplicate(_prv_state->tc_content_type_); + } } + default: + env.exception (new CORBA_BadKind); + return 0; + } } +} - // return the member label as an any - CORBA_Any *retval; +CORBA_ULong +CORBA_TypeCode::prv_discrim_pad_size (CORBA_Environment &env) +{ + CDR stream; + size_t discrim_size, + overall_align; - retval = new CORBA_Any (tc, buf, CORBA_B_TRUE); - tc->Release (); - return retval; + stream.setup_encapsulation (_buffer, (size_t)_length); + + (void) calc_key_union_attributes (&stream, overall_align, discrim_size, env); + if (env. exception () == 0) + { + _prv_state->tc_discrim_pad_size_known_ = CORBA_B_TRUE; + _prv_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. @@ -445,10 +962,10 @@ CORBA_TypeCode::ulong_param (CORBA_ULong n, // Internal hack, used until member_type (), discriminator_type (), // and content_type () are implemented. // -// NOTE special calling convention for CDR::decoder () when we're +// 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 -// CDR::decoder () for further details. +// stream.decode () for further details. CORBA_TypeCode_ptr CORBA_TypeCode::typecode_param (CORBA_ULong n, @@ -484,9 +1001,9 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, case tk_array: if (n != 0) break; - if (CDR::decoder (_tc_CORBA_TypeCode, + if (stream.decode (_tc_CORBA_TypeCode, &tc, this, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); return 0; @@ -498,7 +1015,7 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, break; if (!stream.skip_string () // type ID, hidden || !stream.skip_string () // typedef name - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, env) + || stream.decode (_tc_CORBA_TypeCode, &tc, this, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); @@ -538,7 +1055,7 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, } if (!stream.skip_string () - || CDR::decoder (_tc_CORBA_TypeCode, &tc, this, &stream, + || stream.decode (_tc_CORBA_TypeCode, &tc, this, env)!= CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); @@ -556,9 +1073,9 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, if (!stream.skip_string () // type ID, hidden || !stream.skip_string () // typedef name - || CDR::decoder (_tc_CORBA_TypeCode, + || stream.decode (_tc_CORBA_TypeCode, &tc, this, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) // TC + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) // TC { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); return 0; @@ -583,7 +1100,7 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, for (i = 0; i < temp; i++) { - if (CDR::decoder (tc, &scratch, this, &stream, env) // member label + if (stream.decode (tc, &scratch, this, env) // member label != CORBA_TypeCode::TRAVERSE_CONTINUE || !stream.skip_string () // member name || !skip_typecode (stream)) @@ -595,9 +1112,9 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, } // member label - if (CDR::decoder (tc, + if (stream.decode (tc, &scratch, this, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE + env) != CORBA_TypeCode::TRAVERSE_CONTINUE || !stream.skip_string ()) // member name { tc->Release (); @@ -606,9 +1123,9 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, } tc->Release (); - if (CDR::decoder (_tc_CORBA_TypeCode, + if (stream.decode (_tc_CORBA_TypeCode, &tc, this, - &stream, env) != CORBA_TypeCode::TRAVERSE_CONTINUE) + env) != CORBA_TypeCode::TRAVERSE_CONTINUE) { env.exception (new CORBA_BAD_TYPECODE (COMPLETED_NO)); return 0; @@ -620,37 +1137,50 @@ CORBA_TypeCode::typecode_param (CORBA_ULong n, 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 +// skip a typecode encoding in a given CDR stream +// This is just a helper function +CORBA_Boolean +CORBA_TypeCode::skip_typecode (CDR &stream) { - env.clear (); + CORBA_ULong kind; + CORBA_ULong temp; - switch (_kind) + if (stream.get_ulong (kind) && (kind < TC_KIND_COUNT || kind == ~0)) { - // 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) - ); + switch (kind) + { + // Most TypeCodes have empty parameter lists, nothing to skip + default: + break; - // No other typecodes ever have type IDs - default: - env.exception (new CORBA_BAD_PARAM (COMPLETED_NO)); - return 0; + // Some have single integer parameters, easy to skip. Some 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; + } + else + { + return CORBA_B_FALSE; } } + diff --git a/TAO/IIOP/lib/typecode.h b/TAO/IIOP/lib/typecode.h index 726c4a1e783..f7128bbcccd 100644 --- a/TAO/IIOP/lib/typecode.h +++ b/TAO/IIOP/lib/typecode.h @@ -29,6 +29,9 @@ # define TAO_TYPECODE_H # include "ace/OS.h" +# include "any.h" + +class CDR; enum CORBA_TCKind { @@ -100,35 +103,81 @@ void CORBA_release (CORBA_TypeCode_ptr); CORBA_Boolean CORBA_is_nil (CORBA_TypeCode_ptr obj); extern const IID IID_CORBA_TypeCode; +class TC_PRV_State; class ACE_Svc_Export CORBA_TypeCode : public IUnknown { + // = TITLE + // The CORBA TypeCode class. It maintains the in-memory representation of any + // OMG CORBA IDL data type. + // + // = DESCRIPTION + // Implements the CORBA::TypeCode interface specified by CORBA 2.0 spec public: + // Special Note: + // Many of the methods on this class should have been "const" + // methods. However, we are not able to do so due to our precompute + // optimizations that change the state of the object whenever a quantify is + // not yet precomputed + + static CORBA_TypeCode_ptr _duplicate(CORBA_TypeCode_ptr tc); + static CORBA_TypeCode_ptr _nil(); + + CORBA_Boolean equal (const CORBA_TypeCode_ptr, CORBA_Environment &env) const; + // compares two typecodes + CORBA_TCKind kind (CORBA_Environment &) const; - // For all TypeCode kinds + // For all TypeCode kinds, returns the "kind" of the typecode - CORBA_ULong param_count (CORBA_Environment &) const; - // Deprecated, CORBA 1.2, not fully usable + const CORBA_String id (CORBA_Environment &) const; + // For tk_{objref,struct,union,enum,alias,except}. Returns the repository ID, + // raises BadKind. - CORBA_String id (CORBA_Environment &) const; - // For tk_{objref,struct,union,enum,alias,except} + const CORBA_String name (CORBA_Environment &) const; + // returns name (), raises (BadKind) + + CORBA_ULong member_count (CORBA_Environment &) const; + // returns member_count (), raises (BadKind). Useful for tk_struct, tk_union, + // tk_enum, tk_alias, and tk_except. + + const CORBA_String member_name (CORBA_ULong index, CORBA_Environment &) const; + // returns member_name (...), raises (BadKind, Bounds); Useful for tk_struct, tk_union, + // tk_enum, tk_alias, and tk_except. + + CORBA_TypeCode_ptr member_type (CORBA_ULong index, CORBA_Environment &) const; + // returns member_type (...), raises (BadKind, Bounds); Useful for tk_struct, + // tk_union, and tk_except CORBA_Any_ptr member_label (CORBA_ULong n, CORBA_Environment&) const; - // Other CORBA 2.0 IFR updates -- not yet implemented/needed - // - // String name () raises (BadKind); - // ULong member_count () raises (BadKind); - // String member_name (...) raises (BadKind, Bounds); - // TypeCode_ptr member_type (...) raises (BadKind, Bounds); + // For tk_union. Returns the label. Raises BadKind, Bounds. + + CORBA_TypeCode_ptr discriminator_type (CORBA_Environment &) const; + // returns the discriminator type for tk_union. raises (BadKind); - // TypeCode_ptr discriminator_type () raises (BadKind); - // Long default_index () raises (BadKind); + CORBA_Long default_index (CORBA_Environment &) const; + // returns the default index for the tk_union. Raises (BadKind); - // Long length () raises (BadKind); - // TypeCode_ptr content_type () raises (BadKind); + CORBA_ULong length (CORBA_Environment &) const; + // returns length, raises (BadKind). Used for tk_string, tk_sequence, and + // tk_array + + CORBA_TypeCode_ptr content_type (CORBA_Environment &) const; + // returns the content type (element type). Raises (BadKind); Useful for + // tk_sequence, tk_array, and tk_alias + + CORBA_ULong TAO_discrim_pad_size(CORBA_Environment &); + // Calculates the padded size of discriminant type + // TAO Extension + + // Following three are deprecated + + CORBA_ULong param_count (CORBA_Environment &) const; + // Deprecated, CORBA 1.2, not fully usable. Returns the number of parameters + // that the typecode takes. CORBA_ULong ulong_param (CORBA_ULong n, CORBA_Environment &) const; + CORBA_TypeCode_ptr typecode_param (CORBA_ULong n, CORBA_Environment &) const; // Internal utilities, pending CORBA 2.0 IFR APIs; just enough @@ -208,12 +257,13 @@ public: // recursion. size_t size (CORBA_Environment &env); - size_t alignment (CORBA_Environment &env); + // returns the size. Used by the IIOP marshaling engine. - static CORBA_TypeCode_ptr _nil (void); + size_t alignment (CORBA_Environment &env); + // returns the alignment requirements for this typecode. used by the IIOP + // marshaling engine. // Stuff required for COM IUnknown support - ULONG __stdcall AddRef (void); ULONG __stdcall Release (void); HRESULT __stdcall QueryInterface (REFIID riid, @@ -234,9 +284,68 @@ public: // reference to that parent to ensure its memory is not freed // inappropriately. + static CORBA_Boolean CORBA_TypeCode::skip_typecode (CDR &stream); + // skip a typecode encoding in a given CDR stream + // This is just a helper function + private: + // All the private/helper methods + + CORBA_Boolean prv_equal (CORBA_TypeCode_ptr tc, CORBA_Environment &env) const; + // compares the typecodes + + const CORBA_String prv_id (CORBA_Environment &) const; + // For tk_{objref,struct,union,enum,alias,except}. Returns the repository ID, + // raises BadKind. + + const CORBA_String prv_name (CORBA_Environment &) const; + // returns name (), raises (BadKind) + + CORBA_ULong prv_member_count (CORBA_Environment &) const; + // returns member_count (), raises (BadKind). Useful for tk_struct, tk_union, + // tk_enum, tk_alias, and tk_except. + + CORBA_TypeCode_ptr prv_member_type (CORBA_ULong index, + CORBA_Environment &) const; + // returns member_type (...), raises (BadKind, Bounds); Useful for tk_struct, + // tk_union, and tk_except + + // CORBA_TypeCode_ptr prv_member_label (CORBA_ULong index, + // CORBA_Environment &) const; + // returns member_label (...), raises (BadKind, Bounds); Useful for tk_union + + CORBA_Any_ptr prv_member_label (CORBA_ULong n, CORBA_Environment&) const; + // For tk_union. Returns the label. Raises BadKind, Bounds. + + CORBA_TypeCode_ptr prv_discriminator_type (CORBA_Environment &) const; + // returns the discriminator type for tk_union. raises (BadKind); + + CORBA_Long prv_default_index (CORBA_Environment &) const; + // returns the default index for the tk_union. Raises (BadKind); + + CORBA_Long prv_length (CORBA_Environment &) const; + // returns length, raises (BadKind). Used for tk_string, tk_sequence, and + // tk_array + + CORBA_TypeCode_ptr prv_content_type (CORBA_Environment &) const; + // returns the content type (element type). Raises (BadKind); Useful for + // tk_sequence, tk_array, and tk_alias + + size_t prv_size (CORBA_Environment &env); + // returns the size. Used by the IIOP marshaling engine. + + size_t prv_alignment (CORBA_Environment &env); + // returns the alignment requirements for this typecode. used by the IIOP + // marshaling engine. + + CORBA_ULong prv_discrim_pad_size(CORBA_Environment &); + // Calculates the padded size of discriminant type + // TAO Extension + ACE_Thread_Mutex lock_; + u_int _refcount; + // if refcount reaches 0, free this typecode CORBA_Boolean _orb_owns; // If "orb_owns" is false, the value is a constant typecode with @@ -246,6 +355,15 @@ private: // // "orb owns" is always set, except for TypeCode constants. + TC_PRV_State *_prv_state; + // maintains precomputed state. We need a separate class that maintains the + // precomputed state since most of the TypeCode class operations keep the + // state of the object constant. However, for the purpose of precomputation, + // we need to update the state. We cannot update state directly in the + // TypeCode class as that defeats the constness. However, we can keep an + // object in our typecode class that remains constant, but we can update its + // state. + // = No copy constructor or assignment operator supported; // Use TypeCode_ptr values, duplicate(), release(). @@ -253,6 +371,41 @@ private: CORBA_TypeCode &operator = (const CORBA_TypeCode &src); }; +// private state of the TypeCode. Used to store precomputed values +class TC_PRV_State +{ +public: + TC_PRV_State(); + + // data members that indicate if the desired quantify was precomputed or not. + CORBA_Boolean tc_id_known_; + CORBA_Boolean tc_name_known_; + CORBA_Boolean tc_member_count_known_; + CORBA_Boolean tc_member_type_list_known_; + CORBA_Boolean tc_member_label_list_known_; + CORBA_Boolean tc_discriminator_type_known_; + CORBA_Boolean tc_default_index_used_known_; + CORBA_Boolean tc_length_known_; + CORBA_Boolean tc_content_type_known_; + CORBA_Boolean tc_size_known_; + CORBA_Boolean tc_alignment_known_; + CORBA_Boolean tc_discrim_pad_size_known_; + + // These data members store the precomputed values + CORBA_String tc_id_; + CORBA_String tc_name_; + CORBA_ULong tc_member_count_; + CORBA_TypeCode_ptr *tc_member_type_list_; + CORBA_Any_ptr *tc_member_label_list_; + CORBA_TypeCode_ptr tc_discriminator_type_; + CORBA_Long tc_default_index_used_; + CORBA_ULong tc_length_; + CORBA_TypeCode_ptr tc_content_type_; + CORBA_ULong tc_size_; + CORBA_ULong tc_alignment_; + CORBA_ULong tc_discrim_pad_size_; +}; + // TypeCode constants, which are always accessible in all ORB runtimes. extern const CORBA_TypeCode_ptr _tc_CORBA_Null; @@ -282,4 +435,25 @@ extern const CORBA_TypeCode_ptr _tc_CORBA_Principal; extern const CORBA_TypeCode_ptr _tc_CORBA_Object; +// In this case, we make a substantial exception to how inline +// files are included. Normally, we would conditionally include the +// inline file iff __ACE_INLINE__ is defined. But, in the original, +// highly optimized Sun IIOP code, much of what is in the inline file +// was here ready to be inlined at a moments notice and ALWAYS. So, +// in this ONE file, we defer to David Brownell's considerable prowess +// at creating typecode interpreters as well as to the ACE convention +// of placing inline functions into separate files. + +# if !defined(__ACE_INLINE__) +# undef ACE_INLINE +# define ACE_INLINE inline +# define do_undef_on_ACE_INLINE +# endif +# include "typecode.i" +# if defined(do_undef_on_ACE_INLINE) +# undef do_undef_on_ACE_INLINE +# undef ACE_INLINE +# define ACE_INLINE +# endif + #endif /* TAO_TYPECODE_H */ diff --git a/TAO/IIOP/lib/typecode.i b/TAO/IIOP/lib/typecode.i new file mode 100644 index 00000000000..007c170ec44 --- /dev/null +++ b/TAO/IIOP/lib/typecode.i @@ -0,0 +1,309 @@ +ACE_INLINE CORBA_TypeCode_ptr +CORBA_TypeCode::_duplicate(CORBA_TypeCode_ptr tc) +{ + if (tc) + { + tc->AddRef(); + } + return tc; +} + +// Constructor for CONSTANT typecodes with empty parameter lists. +// These are only created once, and those constants are shared. + +ACE_INLINE CORBA_TypeCode::CORBA_TypeCode (CORBA_TCKind kind) + : _length (0), + _buffer (0), + _kind (kind), + _parent (0), + _refcount (1), + _orb_owns (CORBA_B_FALSE), + _prv_state (new TC_PRV_State) +{ +} + +// 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. + +ACE_INLINE CORBA_TypeCode::~CORBA_TypeCode (void) +{ + delete _prv_state; + + if (_parent) + _parent->Release (); + else if (_orb_owns) + delete _buffer; +} + +// Returns true if the two typecodes are identical +ACE_INLINE CORBA_Boolean +CORBA_TypeCode::equal(const CORBA_TypeCode_ptr tc, + CORBA_Environment &env) const +{ + if (this->_kind != tc->kind(env)) + { + // simple case + return CORBA_B_FALSE; + } + else + { + return this->prv_equal(tc, env); + } +} + +// just fetch the 'kind' field out of the typecode +ACE_INLINE CORBA_TCKind +CORBA_TypeCode::kind (CORBA_Environment &env) const +{ + env.clear (); + return _kind; +} + +// returns the Repository ID +ACE_INLINE const CORBA_String +CORBA_TypeCode::id(CORBA_Environment &env) const +{ + env.clear(); + + // if already precomputed + if (_prv_state->tc_id_known_) + { + return _prv_state->tc_id_; + } + else + { + return prv_id(env); + } +} + +// returns the string name +ACE_INLINE const CORBA_String +CORBA_TypeCode::name(CORBA_Environment &env) const +{ + env.clear(); + + // if already precomputed + if (_prv_state->tc_name_known_) + { + return _prv_state->tc_name_; + } + else + { + return prv_name(env); + } +} + +// 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. + +ACE_INLINE CORBA_ULong +CORBA_TypeCode::member_count (CORBA_Environment &env) const +{ + env.clear (); + + // if already precomputed + if (_prv_state->tc_member_count_known_) + { + return _prv_state->tc_member_count_; + } + else + { + return prv_member_count(env); + } +} + +// 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 +// + +ACE_INLINE CORBA_TypeCode_ptr +CORBA_TypeCode::member_type (CORBA_ULong index, CORBA_Environment &env) const +{ + if (_prv_state->tc_member_count_known_ && _prv_state->tc_member_type_list_known_) + { + if (index >= 0 && index < _prv_state->tc_member_count_) + { + return CORBA_TypeCode::_duplicate(_prv_state->tc_member_type_list_[index]); + } + else + { + env.exception(new CORBA_Bounds()); + return 0; + } + } + else + { + return prv_member_type(index, env); + } +} + + +// Return the label of the i-th member. +// Applicable only to tk_union +ACE_INLINE CORBA_Any_ptr +CORBA_TypeCode::member_label (CORBA_ULong index, CORBA_Environment &env) const +{ + if (_prv_state->tc_member_count_known_ && _prv_state->tc_member_label_list_known_) + { + if (index >= 0 && index < _prv_state->tc_member_count_) + { + (void)_prv_state->tc_member_label_list_[index]->AddRef(); + return _prv_state->tc_member_label_list_[index]; + } + else + { + env.exception(new CORBA_Bounds()); + return 0; + } + } + else + { + return prv_member_label(index, env); + } +} + +// only applicable to tk_unions +ACE_INLINE CORBA_TypeCode_ptr +CORBA_TypeCode::discriminator_type (CORBA_Environment &env) const +{ + if (_kind == tk_union) + { + if (_prv_state->tc_discriminator_type_known_) + { + return CORBA_TypeCode::_duplicate(_prv_state->tc_discriminator_type_); + } + else + { + return prv_discriminator_type(env); + } + } + else + { + env.exception( new CORBA_BadKind()); + return (CORBA_TypeCode_ptr)0; + } +} + +// only applicable to tk_unions +ACE_INLINE CORBA_Long +CORBA_TypeCode::default_index (CORBA_Environment &env) const +{ + if (_kind == tk_union) + { + if (_prv_state->tc_default_index_used_known_) + { + return _prv_state->tc_default_index_used_; + } + else + { + return prv_default_index (env); + } + } + else + { + env.exception( new CORBA_BadKind()); + return 0; + } +} + +// returns the length. Applicable only to string, sequence, and arrays +ACE_INLINE CORBA_ULong +CORBA_TypeCode::length (CORBA_Environment &env) const +{ + switch (_kind) + { + case tk_sequence: + case tk_array: + case tk_string: + case tk_wstring: + if (_prv_state->tc_length_known_) + { + return _prv_state->tc_length_; + } + else + { + return prv_length(env); + } + default: + env.exception( new CORBA_BadKind()); + return 0; + } +} + +// returns the length. Applicable only to string, sequence, and arrays +ACE_INLINE CORBA_TypeCode_ptr +CORBA_TypeCode::content_type (CORBA_Environment &env) const +{ + switch (_kind) + { + case tk_sequence: + case tk_array: + case tk_alias: + if (_prv_state->tc_content_type_known_) + { + return CORBA_TypeCode::_duplicate(_prv_state->tc_content_type_); + } + else + { + return prv_content_type(env); + } + default: + env.exception( new CORBA_BadKind()); + return 0; + } +} + +// calculate size of the typecode +ACE_INLINE size_t +CORBA_TypeCode::size (CORBA_Environment &env) +{ + if (_prv_state->tc_size_known_) + { + return _prv_state->tc_size_; + } + else + { + return prv_size (env); + } +} + +// calculate alignment requirements of the typecode +ACE_INLINE size_t +CORBA_TypeCode::alignment (CORBA_Environment &env) +{ + if (_prv_state->tc_alignment_known_) + { + return _prv_state->tc_alignment_; + } + else + { + return prv_alignment (env); + } +} + +// compute the padded size of the discriminant +ACE_INLINE CORBA_ULong +CORBA_TypeCode::TAO_discrim_pad_size (CORBA_Environment &env) +{ + if (_kind == tk_union) + { + if (_prv_state->tc_discrim_pad_size_known_) + { + return _prv_state->tc_discrim_pad_size_; + } + else + { + return prv_discrim_pad_size (env); + } + } + else + { + env.exception (new CORBA_BadKind()); + return 0; + } +} |