diff options
Diffstat (limited to 'TAO')
-rw-r--r-- | TAO/ChangeLog-98c | 32 | ||||
-rw-r--r-- | TAO/tao/Any.cpp | 790 | ||||
-rw-r--r-- | TAO/tao/Any.h | 362 | ||||
-rw-r--r-- | TAO/tao/Any.i | 293 | ||||
-rw-r--r-- | TAO/tao/Arg_Shifter.cpp | 117 | ||||
-rw-r--r-- | TAO/tao/Arg_Shifter.h | 97 | ||||
-rw-r--r-- | TAO/tao/CDR.cpp | 547 | ||||
-rw-r--r-- | TAO/tao/CDR.h | 379 | ||||
-rw-r--r-- | TAO/tao/CDR.i | 394 | ||||
-rw-r--r-- | TAO/tao/NVList.cpp | 275 | ||||
-rw-r--r-- | TAO/tao/NVList.h | 160 | ||||
-rw-r--r-- | TAO/tao/NVList.i | 63 | ||||
-rw-r--r-- | TAO/tao/ORB_Strategies_T.cpp | 46 | ||||
-rw-r--r-- | TAO/tao/ORB_Strategies_T.h | 45 | ||||
-rw-r--r-- | TAO/tao/ORB_Strategies_T.i | 10 | ||||
-rw-r--r-- | TAO/tao/Principal.cpp | 50 | ||||
-rw-r--r-- | TAO/tao/Principal.h | 60 | ||||
-rw-r--r-- | TAO/tao/tao.bld | 58 |
18 files changed, 3738 insertions, 40 deletions
diff --git a/TAO/ChangeLog-98c b/TAO/ChangeLog-98c index d901b80ae3e..12eed9a942e 100644 --- a/TAO/ChangeLog-98c +++ b/TAO/ChangeLog-98c @@ -1,16 +1,13 @@ -Sat Mar 21 20:34:39 1998 Sergio Flores <sergio@lambada.cs.wustl.edu> +Sat Mar 21 11:00:40 1998 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> - * tao/connect.cpp (open): fixed a bug due to wrong parens - location. - * tests/Cubit/TAO/MT_Cubit/server.cpp: - * tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp: - * tests/Cubit/TAO/MT_Cubit/Task_Client.h: - * tests/Cubit/TAO/MT_Cubit/Task_Client.cpp: added option to - disable use of the name service. hacked the code for platforms - that don't support floating point math. Added Quantify start/stop - primitives around CORBA calls. + * tao: Renamed a bunch of files so that the names and + capitalization matches precisely. -Sat Mar 21 11:00:40 1998 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> + * tao/Request.i: Created this file and moved a bunch of inline + methods into here. + + * tao: Renamed the corbacom.* files (since we don't support COM + anyhow) into CORBA.h and the new CORBA.i and CORBA.cpp files. * tao/corbacom.h: Moved the CORBA_SEQUENCE stuff back into the header file since it wasn't linking correctly... @@ -56,6 +53,19 @@ Sat Mar 21 11:00:40 1998 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> * tao/sequence_T.i (replace): Fixed some typos in the template code. Thanks to Ben Eng <ben@jetpen.com> for reporting these. +Sat Mar 21 20:34:39 1998 Sergio Flores <sergio@lambada.cs.wustl.edu> + + * tao/connect.cpp (open): fixed a bug due to wrong parens + location. + + * tests/Cubit/TAO/MT_Cubit/server.cpp: + * tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp: + * tests/Cubit/TAO/MT_Cubit/Task_Client.h: + * tests/Cubit/TAO/MT_Cubit/Task_Client.cpp: added option to + disable use of the name service. hacked the code for platforms + that don't support floating point math. Added Quantify start/stop + primitives around CORBA calls. + Sat Mar 21 17:55:40 1998 Michael Kircher <mk1@cs.wustl.edu> * orbsvcs/test/Simulator/NavWeap.idl: removed typo diff --git a/TAO/tao/Any.cpp b/TAO/tao/Any.cpp new file mode 100644 index 00000000000..eb7ab852c57 --- /dev/null +++ b/TAO/tao/Any.cpp @@ -0,0 +1,790 @@ +// @ (#) $Id$ + +#include "tao/corba.h" + +CORBA::TypeCode_ptr +CORBA_Any::type (void) const +{ + return this->type_; +} + +const void * +CORBA_Any::value (void) const +{ + return this->value_; +} + +// Default "Any" constructor -- initializes to nulls per the +// OMG C++ mapping. + +// NOTE: null (zero) typecode pointers are also treated as the null +// typecode ... + +CORBA_Any::CORBA_Any (void) + : type_ (CORBA::_tc_null), + value_ (0), + orb_owns_data_ (CORBA::B_FALSE), + refcount_ (1) +{ +} + +// The more common "Any" constructor has its own copy of a typecode, +// and either holds or "consumes" an arbitrary data value satisfying +// the normal binary interface rules. + +CORBA_Any::CORBA_Any (CORBA::TypeCode_ptr tc, + void *value, + CORBA::Boolean orb_owns_data) + : type_ (tc), + value_ (value), + orb_owns_data_ (orb_owns_data), + refcount_ (1) +{ + tc->AddRef (); +} + +// Helper routine for "Any" copy constructor ... +// +// "Deep Copy" from source to dest. Memory is always there to be +// copied to ... if this calls itself recursively, it ensures that +// this remains true (only really an issue for sequences) . +// +// This shows the main reason to pass two values to the "visit" +// function used by the TypeCode interpreter: it allows the copy to be +// made without using any additional temporary memory. Most other +// such "visit" routines use only a single value. This is also +// slightly atypical in that it doesn't use the "context". + +static CORBA::TypeCode::traverse_status +deep_copy (CORBA::TypeCode_ptr tc, + const void *source, + const void *dest, + void *, // no context + CORBA::Environment &env) +{ + CORBA::TypeCode::traverse_status retval; + CORBA::TCKind my_kind; + + if (!tc) + { + env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO) ); + return CORBA::TypeCode::TRAVERSE_STOP; + } + + my_kind = tc->kind (env); + + if (env.exception_type () != CORBA::NO_EXCEPTION) + return CORBA::TypeCode::TRAVERSE_STOP; + + // 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. + // + // See the TypeCode interpreter code for more details about the + // representational assumptions here. + + retval = CORBA::TypeCode::TRAVERSE_CONTINUE; + + switch (my_kind) + { + case CORBA::tk_null: + case CORBA::tk_void: + break; + + case CORBA::tk_char: + case CORBA::tk_octet: + *(CORBA::Octet *) dest = *(CORBA::Octet *) source; + break; + + case CORBA::tk_short: + case CORBA::tk_ushort: + *(CORBA::Short *) dest = *(CORBA::Short *) source; + break; + + case CORBA::tk_wchar: + *(CORBA::WChar *) dest = *(CORBA::WChar *) source; + break; + + case CORBA::tk_long: + case CORBA::tk_ulong: + case CORBA::tk_float: + *(CORBA::Long *) dest = *(CORBA::Long *) source; + break; + + case CORBA::tk_longlong: + case CORBA::tk_ulonglong: + case CORBA::tk_double: + *(CORBA::LongLong *) dest = *(CORBA::LongLong *) source; + break; + + case CORBA::tk_longdouble: + *(CORBA::LongDouble *) dest = *(CORBA::LongDouble *) source; + break; + + case CORBA::tk_boolean: + *(CORBA::Boolean *) dest = *(CORBA::Boolean *) source; + break; + + case CORBA::tk_any: + (void) new (dest) CORBA_Any (*(CORBA_Any*) source); + break; + + case CORBA::tk_TypeCode: + if ((*(CORBA::TypeCode_ptr *) source) != 0) + dest = source; + else + dest = CORBA::_tc_null; + ((CORBA::TypeCode_ptr) dest)->AddRef (); + break; + + case CORBA::tk_Principal: + { + CORBA::Principal_ptr src, dst; + + src = *(CORBA::Principal_ptr *) source; + // @@ Andy, please make sure to check for memory failure. + dst = *(CORBA::Principal_ptr *) dest = new CORBA::Principal; + + // 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) + { + // @@ Andy, please make sure to check for memory failure. + dst->id.buffer = new CORBA::Octet [(unsigned) dst->id.length]; + ACE_OS::memcpy (dst->id.buffer, src->id.buffer, + (size_t) dst->id.length); + } + else + dst->id.buffer = 0; + } + break; + + case CORBA::tk_objref: + *(CORBA::Object_ptr *) dest = + CORBA::Object::_duplicate (*(CORBA::Object_ptr *) source); + break; + + case CORBA::tk_sequence: + { + CORBA::OctetSeq *src, *dst; + CORBA::TypeCode_ptr tcp; + size_t size; + + // Rely on binary format of sequences -- all are the same + // except for the type pointed to by "buffer" + + src = (CORBA::OctetSeq *) source; + dst = (CORBA::OctetSeq *) dest; + + assert (src->length <= UINT_MAX); + dst->length = dst->maximum = src->length; + + // Get the size of each "buffer" element + + tcp = tc->typecode_param (0, env); + + if (env.exception () != 0) + { + retval = CORBA::TypeCode::TRAVERSE_STOP; + break; + } + + size = tcp->size (env); + + if (env.exception () != 0) + { + retval = CORBA::TypeCode::TRAVERSE_STOP; + break; + } + tcp->Release (); + + // Now allocate a new (uninitialized) buffer of the right size + // to hold that many elements ... fall through and let a + // general traverse fill in those buffer elements. + + size *= (size_t) src->length; + dst->buffer = new CORBA::Octet[size]; + } + // FALLTHROUGH + + case CORBA::tk_struct: + case CORBA::tk_union: + case CORBA::tk_array: + case CORBA::tk_alias: + return tc->traverse (source, + dest, + (CORBA::TypeCode::VisitRoutine) deep_copy, + 0, + env); + + case CORBA::tk_except: + // 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, the traverse code + // ignores it completely. + + *(CORBA::TypeCode_ptr *) dest = *(CORBA::TypeCode_ptr *) source; + (void) (*(CORBA::TypeCode_ptr *) dest)->AddRef (); + + return tc->traverse (source, + dest, + (CORBA::TypeCode::VisitRoutine) deep_copy, + 0, + env); + + case CORBA::tk_enum: + *(int *) dest = *(int *) source; + break; + + case CORBA::tk_string: + *(CORBA::String *) dest = + CORBA::string_copy (*(CORBA::String *) source); + break; + + case CORBA::tk_wstring: + *(CORBA::WString *) dest = + CORBA::wstring_copy (*(CORBA::WString *) source); + break; + + default: + dmsg ("deep copy default case ?"); + env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO) ); + retval = CORBA::TypeCode::TRAVERSE_STOP; + break; + } + return retval; +} + +// Copy constructor for "Any". + +CORBA_Any::CORBA_Any (const CORBA_Any &src) + : type_ (src.type_ != 0 ? src.type_ : CORBA::_tc_null), + orb_owns_data_ (CORBA::B_TRUE), + refcount_ (1) +{ + CORBA::Environment env; + size_t size; + + this->type_->AddRef (); + + size = this->type_->size (env); // XXX check error status + this->value_ = (char *) calloc (1, size); + +#if 0 + // @@ Andy, can we remove this code if its not needed? + (void) this->type_->traverse (src.value_, + value_, + (CORBA::TypeCode::VisitRoutine) deep_copy, + 0, + env); +#endif /* replaced by our optimizations */ + + (void) DEEP_COPY (this->type_, src.value_, this->value_, env); +} + +//a&a : Added on 14 feb 1998 + +CORBA_Any & +CORBA_Any::operator= (const CORBA_Any &src) +{ + CORBA::Environment env; + size_t size; + + if (this == &src) + { + this->AddRef (); + return *this; + } + + if (this->orb_owns_data_) + DEEP_FREE (this->type_, this->value_, 0, env); + + // @@ Andy, can we remove this code if it's not needed? + // this->Release (); // release any value + typecode we may have + + // Now copy the contents of the source to ourselves. + this->type_ = (src.type_) != 0 ? src.type_ : CORBA::_tc_null; + + this->orb_owns_data_ = CORBA::B_TRUE; + this->refcount_ = 1; + + this->type_->AddRef (); + + size = this->type_->size (env); // XXX check error status + this->value_ = (char *) calloc (1, size); + (void) DEEP_COPY (this->type_, src.value_, this->value_, env); + return *this; +} + +// 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 recurses. +// +// This is one of the simplest typecode interpreter callbacks, since +// in most cases it does nothing. Also, it uses neither the second +// value nor the context parameter. + +static CORBA::TypeCode::traverse_status +deep_free (CORBA::TypeCode_ptr tc, + const void *value, + const void *, // value2 unused + void *, // context unused + CORBA::Environment &env) +{ + // Don't do anything if the value is a null pointer. + + if (!value) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + + CORBA::TypeCode::traverse_status retval; + CORBA::TCKind my_kind; + + if (!tc) + { + env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO) ); + return CORBA::TypeCode::TRAVERSE_STOP; + } + + my_kind = tc->kind (env); + + if (env.exception_type () != CORBA::NO_EXCEPTION) + return CORBA::TypeCode::TRAVERSE_STOP; + + // Free only embedded pointers ... which don't exist in most + // primitive types. + + retval = CORBA::TypeCode::TRAVERSE_CONTINUE; + switch (my_kind) + { + case CORBA::tk_struct: + case CORBA::tk_union: + case CORBA::tk_array: + case CORBA::tk_alias: + return tc->traverse (value, + 0, + (CORBA::TypeCode::VisitRoutine) deep_free, + 0, + env); + + // 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. + // + case CORBA::tk_except: + return retval; + + case CORBA::tk_sequence: + retval = tc->traverse (value, + 0, + (CORBA::TypeCode::VisitRoutine) deep_free, + 0, + env); + // @@ This better be allocated via new[]. + // + // @@ (ANDY) I'm not sure what to do here...should I delete the + // value? It seems that the DTOR for the sequence will insure + // that this buffer goes away. + delete [] ((CORBA::OctetSeq *) value)->buffer; + break; + + case CORBA::tk_TypeCode: + if ((*(CORBA::TypeCode_ptr *) value) != 0) + (*(CORBA::TypeCode_ptr *) value)->Release (); + break; + + case CORBA::tk_Principal: + CORBA::release (*(CORBA::Principal_ptr *) value); + break; + + case CORBA::tk_objref: + CORBA::release (*(CORBA::Object_ptr *) value); + break; + + case CORBA::tk_string: + CORBA::string_free (*(CORBA::String *) value); + *(CORBA::String *)value = 0; + break; + + case CORBA::tk_wstring: + CORBA::wstring_free (*(CORBA::WString *) value); + *(CORBA::WString *)value = 0; + break; + + case CORBA::tk_any: +#ifdef __BORLANDC__ + // XXX BC++ doesn't yet accept explicit calls to destructors + // with this syntax. A simple workaround must exist, though; + // other explicit destructor calls work. + + dmsg ("Delete Any-in-Any ... memory leak with BC++ 4.5"); +#else + ((CORBA_Any *) value)->~CORBA_Any (); +#endif /* __BORLANDC__ */ + break; + + default: + return CORBA::TypeCode::TRAVERSE_CONTINUE; + } + + if (env.exception_type () != CORBA::NO_EXCEPTION) + return CORBA::TypeCode::TRAVERSE_STOP; + else + return retval; +} + +// Destructor for an "Any" deep-frees memory if needed. +// +// NOTE that the assertion below will fire on application programmer +// errors, such as using AddRef/Release out of sync with the true +// lifetime of an Any value allocated on the stack. BUT it involves +// changing the refcounting policy so that it's initialized to zero, +// not one ... which policy affects the whole source base, and not +// just this data type. Get to this later. + +CORBA_Any::~CORBA_Any (void) +{ + CORBA::Environment env; + + // assert (this->refcount_ == 0); + + if (this->orb_owns_data_) + // @@ Andy, do we still need the deep_free() function call? If + // not, can we remove it? + // (void) deep_free (type_, value_, 0, 0, env); + DEEP_FREE (this->type_, this->value_, 0, env); + // @@ Andy, is the following comment still true? If not, can we remove it? + + // TODO: This crashes the server on NT, apparently the previous + // DEEP_FREE does the job and make the delete operator uneeded. + // delete value_; + + if (this->type_) + this->type_->Release (); +} + +// All-at-once replacement of the contents of an "Any." + +void +CORBA_Any::replace (CORBA::TypeCode_ptr tc, + const void *v, + CORBA::Boolean orb_owns_data, + CORBA::Environment &env) +{ + if (this->orb_owns_data_) + { + // @@ Andy, do we still need the deep_free() function call? If + // not, can we remove it? + // (void) deep_free (type_, value_, 0, 0, env); + if (value_) + DEEP_FREE (this->type_, this->value_, 0, env); + // @@ Andy, is this delete ok? The one in the destructor is + // commented out... + delete this->value_; + } + + if (this->type_ != 0) + this->type_->Release (); + + env.clear (); + + this->type_ = tc; + tc->AddRef (); + this->value_ = (void *) v; + this->orb_owns_data_ = orb_owns_data; +} + +// insertion of from_string +void +CORBA_Any::operator<<= (from_string s) +{ + // If the inserted string is bounded, we create a typecode. + static CORBA::Long _oc_string [] = + { // CDR typecode octets + TAO_ENCAP_BYTE_ORDER, // native endian + padding; "tricky" + 0 // ... unbounded string to start with + }; + + CORBA::TypeCode_ptr tc = 0; + if (s.bound_ > 0) + { + // Bounded string. + _oc_string [1] = s.bound_; + ACE_NEW (tc, CORBA::TypeCode (CORBA::tk_string, + sizeof _oc_string, + (char *) &_oc_string, + CORBA::B_TRUE)); + } + else + tc = CORBA::_tc_string; // unbounded. + + if (s.nocopy_) + this->replace (tc, new char* (s.val_), CORBA::B_TRUE); + else // copying + this->replace (tc, new char* (CORBA::string_dup (s.val_)), + CORBA::B_TRUE); +} + +// Extraction: these are safe and hence we have to check that the +// typecode of the Any is equal to the one we are trying to extract +// into + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::Short &s) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_short, env)) + { + s = *(CORBA::Short *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::UShort &s) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_ushort, env)) + { + s = *(CORBA::UShort *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::Long &l) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_long, env)) + { + l = *(CORBA::Long *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::ULong &l) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_ulong, env)) + { + l = *(CORBA::ULong *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::Float &f) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_float, env)) + { + f = *(CORBA::Float *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::Double &d) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_double, env)) + { + d = *(CORBA::Double *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (CORBA::Any &a) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_any, env)) + { + a = *(CORBA::Any *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (char *&s) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_string, env)) + { + s = *(char **) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +// = extraction into the special types + +CORBA::Boolean +CORBA_Any::operator>>= (to_boolean b) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_boolean, env)) + { + b.ref_ = *(CORBA::Boolean *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (to_octet o) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_octet, env)) + { + o.ref_ = *(CORBA::Octet *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (to_char c) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_char, env)) + { + c.ref_ = *(CORBA::Char *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (to_string s) const +{ + CORBA::Environment env; + + // The typecode must be equal. Since we do not readily have access + // to the typecode of the string into which we want to retrieve, we + // emulate the behavior of "equal" + if (this->type_->kind (env) == CORBA::tk_string) + { + CORBA::ULong bound = this->type_->length (env); + if (s.bound_ == bound) // bounds are same + { + s.val_ = *(char **) this->value_; + return CORBA::B_TRUE; + } + } + + // Otherwise. + return CORBA::B_FALSE; +} + +CORBA::Boolean +CORBA_Any::operator>>= (to_object obj) const +{ + CORBA::Environment env; + + if (this->type_->equal (CORBA::_tc_Object, env)) + { + obj.ref_ = *(CORBA::Object_ptr *) this->value_; + return CORBA::B_TRUE; + } + else + return CORBA::B_FALSE; +} + +CORBA::ULong +CORBA_Any::AddRef (void) +{ + return ++refcount_; +} + +CORBA::ULong +CORBA_Any::Release (void) +{ + { + ACE_ASSERT (this != 0); + + if (--refcount_ != 0) + return refcount_; + } + + delete this; + return 0; +} + +// ---------------------------------------------------------------------- +// Any_var type +// ---------------------------------------------------------------------- + +CORBA::Any_var & +CORBA_Any_var::operator= (CORBA::Any *p) +{ + if (this->ptr_ != p) + { + if (this->ptr_ != 0) + delete (this->ptr_); + + this->ptr_ = p; + } + return *this; +} + +CORBA::Any_var & +CORBA_Any_var::operator= (const CORBA::Any_var& r) +{ + if (this->ptr_ != 0) + delete (this->ptr_); + + this->ptr_ = new CORBA::Any (*r.ptr_); + return *this; +} diff --git a/TAO/tao/Any.h b/TAO/tao/Any.h new file mode 100644 index 00000000000..1f9b47b57bd --- /dev/null +++ b/TAO/tao/Any.h @@ -0,0 +1,362 @@ +// This may look like C, but it's really -*- C++ -*- + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// Any.h +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems, Inc. +// and Aniruddha Gokhale. +// +// ============================================================================ + +#if !defined (TAO_ANY_H) +#define TAO_ANY_H + +class TAO_Export CORBA_Any +{ + // = TITLE + // Class "Any" can wrap values of any type, with the assistance + // of a TypeCode to describe that type. + // + // = DESCRIPTION + // This includes three constructors, a destructor, and a "replace" + // method for the "Any" data type. "Any" values pair a pointer to + // a data structure in the native binary representation (e.g. C + // struct) with a TypeCode that describes that data structure. + // + // The copy constructor and the destructor each use the TypeCode + // interpreter with specialized "visit" callback routines. The + // "visit" routines are used respectively to make "deep copies" + // and perform "deep frees" of the aritrary values as described by + // the "Any" value's typecode. + // + // Note that these "visit" routines are called directly, and they + // choose whether or not to use the TypeCode interpreter to + // examine constituents. In the simple cases, the "visit" + // routines can do their work without any further calls; only for + // constructed types is the interpreter's knowledge really + // required. + // + // THREADING NOTE: "Any" is a data structure which must be + // protected by external critical sections. Like simpler numeric + // types, "Any" instances are accessed and modified atomically. + // This implementation is reentrant, so that independent "Any" + // values may be manipulated concurrently when the underlying + // programming environment is itself reentrant. +public: + + // = Minor codes for exceptional returns + enum + { + UNINITIALIZED_type = 0xf000, + VALUE_WITHOUT_TYPE, + UNSUPPORTED_OPERATION + }; + + // = Initialization and termination operations. + CORBA_Any (void); + // Default constructor. + + CORBA_Any (CORBA::TypeCode_ptr type, + void *value = 0, + CORBA::Boolean orb_owns_data = CORBA::B_FALSE); + // Constructor. + + CORBA_Any (const CORBA_Any &a); + // Copy constructor. + + ~CORBA_Any (void); + // Destructor. + + CORBA_Any &operator= (const CORBA_Any &); + // assignment operator + + // = NOTE: 94-9-14 has assignment operator plus many insertion, as + // specified below. + + // =type safe insertion + + void operator<<= (CORBA::Short); + // insert a short + + void operator<<= (CORBA::UShort); + // insert an unsigned short + + void operator<<= (CORBA::Long); + // insert a long + + void operator<<= (CORBA::ULong); + // insert an unsigned long + + void operator<<= (CORBA::Float); + // insert a float + + void operator<<= (CORBA::Double); + // insert a double + + void operator<<= (const CORBA_Any&); + // insert an Any + + void operator<<= (const char*); + // insert unbounded strings + + // =type safe extraction + + CORBA::Boolean operator>>= (CORBA::Short&) const; + // extract a short + + CORBA::Boolean operator>>= (CORBA::UShort&) const; + // extract an unsigned short + + CORBA::Boolean operator>>= (CORBA::Long&) const; + // extract a long + + CORBA::Boolean operator>>= (CORBA::ULong&) const; + // extract an unsigned long + + CORBA::Boolean operator>>= (CORBA::Float&) const; + // extract a float + + CORBA::Boolean operator>>= (CORBA::Double&) const; + // extract a double + + CORBA::Boolean operator>>= (CORBA_Any&) const; + // extract an Any + + CORBA::Boolean operator>>= (char*&) const; + // extract an unbounded string + + // = Special types. + + // These are needed for insertion and extraction of booleans, + // octets, chars, and bounded strings. + + struct from_boolean + { + from_boolean (CORBA::Boolean b); + CORBA::Boolean val_; + }; + + struct from_octet + { + from_octet (CORBA::Octet o); + CORBA::Octet val_; + }; + + struct from_char + { + from_char (CORBA::Char c); + CORBA::Char val_; + }; + + struct from_string + { + from_string (char* s, CORBA::ULong b, + CORBA::Boolean nocopy = CORBA::B_FALSE); + char *val_; + CORBA::ULong bound_; + CORBA::Boolean nocopy_; + }; + + void operator<<= (from_boolean); + // insert a boolean + + void operator<<= (from_char); + // insert a char + + void operator<<= (from_octet); + // insert an octet + + void operator<<= (from_string); + // insert a bounded string + + // = Special types. + + // These extract octets, chars, booleans, bounded strings, and + // object references + + struct to_boolean + { + to_boolean (CORBA::Boolean &b); + CORBA::Boolean &ref_; + }; + + struct to_char + { + to_char (CORBA::Char &c); + CORBA::Char &ref_; + }; + + struct to_octet + { + to_octet (CORBA::Octet &o); + CORBA::Octet &ref_; + }; + + struct to_string + { + to_string (char *&s, CORBA::ULong b); + char *&val_; + CORBA::ULong bound_; + }; + + struct to_object + { + to_object (CORBA::Object_ptr &obj); + CORBA::Object_ptr &ref_; + }; + + // extraction of the special types + CORBA::Boolean operator>>= (to_boolean) const; + CORBA::Boolean operator>>= (to_octet) const; + CORBA::Boolean operator>>= (to_char) const; + CORBA::Boolean operator>>= (to_string) const; + CORBA::Boolean operator>>= (to_object) const; + + // = ALLOCATION + void *operator new (size_t, const void *p); + // Placement new. + void *operator new (size_t s); + // Default new. + void operator delete (void *p); + // Default delete + + void replace (CORBA::TypeCode_ptr type, + const void *value, + CORBA::Boolean orb_owns_data, + CORBA::Environment &env); + // Replace the current typecode and data with the specified one - + // unsafe. + + CORBA::TypeCode_ptr type (void) const; + // Return TypeCode of the element stored in the Any. + + const void *value (void) const; + // Returns 0 if the Any has not been assigned a value, following the + // CORBA spec (TODO: give a reference) it returns a non-zero value + // otherwise. TAO does *not* guarantee that this value may be casted + // to the contained type safely. + + // = Memory management methods. + CORBA::ULong AddRef (void); + CORBA::ULong Release (void); + +private: + CORBA::TypeCode_ptr type_; + // Typecode for the <Any>. + + void *value_; + // Value for the <Any>. + + CORBA::Boolean orb_owns_data_; + // Flag that indicates the ORB is responsible for deleting the data. + + CORBA::ULong refcount_; + // Reference count the <Any> to reduce copying costs. + + void replace (CORBA::TypeCode_ptr type, + const void *value, + CORBA::Boolean orb_owns_data); + // Helper for extraction operators that don't pass an environment + // parameter. + + // 94-9-14 hides unsigned char insert/extract + void operator<<= (unsigned char); + CORBA::Boolean operator>>= (unsigned char&) const; +}; + +class TAO_Export CORBA_Any_var +{ + // = TITLE + // Provide for automatic storage deallocation on going out of + // scope. +public: + CORBA_Any_var (void); + // default constructor + + CORBA_Any_var (CORBA_Any *a); + // construct from an Any pointer + + CORBA_Any_var (const CORBA_Any_var &a); + // copy constructor + + ~CORBA_Any_var (void); + // destructor + + CORBA_Any_var &operator= (CORBA_Any *a); + // assignment from a pointer to Any + + CORBA_Any_var &operator= (const CORBA_Any_var &a); + // assignment from an Any_var + + CORBA_Any *operator-> (void); + // arrow operator (smart pointer) + + operator const CORBA_Any *() const; + // cast + + operator CORBA_Any *&(); + // cast + + const CORBA_Any &in (void) const; + // for in Any parameter + + CORBA_Any &inout (void); + // for inout Any parameter + + CORBA_Any *&out (void); + // for out Any parameter + + CORBA_Any *_retn (void); + // for Any return types + +private: + CORBA_Any *ptr_; + // Holds the Any. +}; + +class TAO_Export CORBA_Any_out + // = TITLE + // @@ (ANDY) Please document me. +{ +public: + // = operations. + + CORBA_Any_out (CORBA_Any *&p); + // construction from a reference to a CORBA_Any + + CORBA_Any_out (CORBA_Any_var &p); + // construction from a var + + CORBA_Any_out (CORBA_Any_out &s); + // copy constructor + + CORBA_Any_out &operator= (CORBA_Any_out &s); + // assignment from a CORBA_Any_out + + CORBA_Any_out &operator= (CORBA_Any *p); + // assignment from a CORBA_Any + + CORBA_Any_out &operator= (const CORBA_Any *p); + // assignment from a const CORBA_Any + + operator CORBA_Any *&(); + // cast + + CORBA_Any *& ptr (void); + // return underlying instance + +private: + CORBA_Any *&ptr_; + // Instance + + void operator= (const CORBA_Any_var &); + // assignment from _var disallowed +}; + +#endif /* TAO_ANY_H */ diff --git a/TAO/tao/Any.i b/TAO/tao/Any.i new file mode 100644 index 00000000000..2b4e36a6afd --- /dev/null +++ b/TAO/tao/Any.i @@ -0,0 +1,293 @@ +// This may look like C, but it's really -*- C++ -*- + +ACE_INLINE void * +CORBA_Any::operator new (size_t, const void *p) +{ + return (void *) p; +} + +ACE_INLINE void * +CORBA_Any::operator new (size_t s) +{ + return ::operator new (s); +} + +ACE_INLINE void +CORBA_Any::operator delete (void *p) +{ + ::operator delete (p); +} + +// Insertion from special types. + +// @@ Andy, please take a look at this method and make sure it's what +// you intended. I couldn't find it defined anywhere. --cjc +ACE_INLINE void +CORBA_Any::replace (CORBA::TypeCode_ptr type, + const void *value, + CORBA::Boolean orb_owns_data) +{ + CORBA_Environment e; + this->replace (type, value, orb_owns_data, e); +} + +// insertion operators + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::Short s) +{ + this->replace (CORBA::_tc_short, new CORBA::Short (s), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::UShort s) +{ + this->replace (CORBA::_tc_ushort, new CORBA::UShort (s), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::Long l) +{ + this->replace (CORBA::_tc_long, new CORBA::Long (l), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::ULong l) +{ + this->replace (CORBA::_tc_ulong, new CORBA::ULong (l), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::Float f) +{ + this->replace (CORBA::_tc_float, new CORBA::Float (f), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (CORBA::Double d) +{ + this->replace (CORBA::_tc_double, new CORBA::Double (d), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (const CORBA_Any& a) +{ + this->replace (CORBA::_tc_any, new CORBA_Any (a), CORBA::B_TRUE); +} + +// this is a copying version for unbounded strings +ACE_INLINE void +CORBA_Any::operator<<= (const char* s) +{ + this->replace (CORBA::_tc_string, new char* (CORBA::string_dup (s)), + CORBA::B_TRUE); +} + +// implementing the special types +ACE_INLINE +CORBA_Any::from_boolean::from_boolean (CORBA::Boolean b) + : val_ (b) +{ +} + +ACE_INLINE +CORBA_Any::to_boolean::to_boolean (CORBA::Boolean &b) + : ref_ (b) +{ +} + +ACE_INLINE +CORBA_Any::from_octet::from_octet (CORBA::Octet o) + : val_ (o) +{ +} + +ACE_INLINE +CORBA_Any::to_octet::to_octet (CORBA::Octet &o) + : ref_ (o) +{ +} + +ACE_INLINE +CORBA_Any::from_char::from_char (CORBA::Char c) + : val_ (c) +{ +} + +ACE_INLINE +CORBA_Any::to_char::to_char (CORBA::Char &c) + : ref_ (c) +{ +} + +ACE_INLINE +CORBA_Any::from_string::from_string (char *s, + CORBA::ULong b, + CORBA::Boolean nocopy) + : val_ (s), + bound_ (b), + nocopy_ (nocopy) +{ +} + +ACE_INLINE +CORBA_Any::to_string::to_string (char *&s, + CORBA::ULong b) + : val_ (s), + bound_ (b) +{ +} + +ACE_INLINE +CORBA_Any::to_object::to_object (CORBA::Object_ptr &obj) + : ref_ (obj) +{ +} + +ACE_INLINE void +CORBA_Any::operator<<= (from_boolean b) +{ + this->replace (CORBA::_tc_boolean, new CORBA::Boolean (b.val_), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (from_octet o) +{ + this->replace (CORBA::_tc_octet, new CORBA::Octet (o.val_), CORBA::B_TRUE); +} + +ACE_INLINE void +CORBA_Any::operator<<= (from_char c) +{ + this->replace (CORBA::_tc_char, new CORBA::Char (c.val_), CORBA::B_TRUE); +} + +// ---------------------------------------------------------------------- +// CORBA_Any_var type +// ---------------------------------------------------------------------- + +ACE_INLINE +CORBA_Any_var::CORBA_Any_var (void) + : ptr_ (0) +{ +} + +ACE_INLINE +CORBA_Any_var::CORBA_Any_var (CORBA_Any *p) + : ptr_ (p) +{ +} + +ACE_INLINE +CORBA_Any_var::CORBA_Any_var (const CORBA_Any_var& r) + : ptr_ (new CORBA::Any (*r.ptr_)) +{ +} + +ACE_INLINE +CORBA_Any_var::~CORBA_Any_var (void) +{ + delete this->ptr_; +} + +ACE_INLINE +CORBA_Any_var::operator CORBA_Any *&() +{ + return this->ptr_; +} + +ACE_INLINE +CORBA_Any_var::operator const CORBA_Any *() const +{ + return this->ptr_; +} + +ACE_INLINE CORBA::Any * +CORBA_Any_var::operator-> (void) +{ + return this->ptr_; +} + +ACE_INLINE const CORBA_Any & +CORBA_Any_var::in (void) const +{ + return *this->ptr_; +} + +ACE_INLINE CORBA_Any & +CORBA_Any_var::inout (void) +{ + return *this->ptr_; +} + +ACE_INLINE CORBA_Any *& +CORBA_Any_var::out (void) +{ + delete this->ptr_; + this->ptr_ = 0; + return this->ptr_; +} + +ACE_INLINE CORBA_Any * +CORBA_Any_var::_retn (void) +{ + CORBA_Any *temp = this->ptr_; + this->ptr_ = 0; + return temp; +} + +// ---------------------------------------------------------------------- +// CORBA_Any_out type +// ---------------------------------------------------------------------- + +ACE_INLINE +CORBA_Any_out::CORBA_Any_out (CORBA_Any *&s) + : ptr_ (s) +{ + this->ptr_ = 0; +} + +ACE_INLINE +CORBA_Any_out::CORBA_Any_out (CORBA_Any_var &s) + : ptr_ (s.out ()) +{ +} + +ACE_INLINE +CORBA_Any_out::CORBA_Any_out (CORBA_Any_out &s) + : ptr_ (s.ptr_) +{ +} + +ACE_INLINE CORBA_Any_out & +CORBA_Any_out::operator= (CORBA_Any_out &s) +{ + this->ptr_ = s.ptr_; + return *this; +} + +ACE_INLINE CORBA_Any_out & +CORBA_Any_out::operator= (CORBA_Any *s) +{ + this->ptr_ = s; + return *this; +} + +ACE_INLINE CORBA_Any_out & +CORBA_Any_out::operator= (const CORBA_Any *s) +{ + this->ptr_ = new CORBA::Any (*s); + return *this; +} + +ACE_INLINE +CORBA_Any_out::operator CORBA_Any *&() +{ + return this->ptr_; +} + +ACE_INLINE CORBA_Any *& +CORBA_Any_out::ptr (void) +{ + return this->ptr_; +} diff --git a/TAO/tao/Arg_Shifter.cpp b/TAO/tao/Arg_Shifter.cpp new file mode 100644 index 00000000000..8e8dc51aa34 --- /dev/null +++ b/TAO/tao/Arg_Shifter.cpp @@ -0,0 +1,117 @@ +// $Id$ + +#include "Arg_Shifter.h" + +Arg_Shifter::Arg_Shifter (int &argc, char **argv, char **temp) + : argc_ (argc), + total_size_ (argc), + temp_ (temp), + argv_ (argv), + current_index_ (0), + back_ (argc - 1), + front_ (0) +{ + // If not provided with one, allocate a temporary array. + if (this->temp_ == 0) + this->temp_ = new char *[this->total_size_]; + + if (this->temp_ != 0) + { + // Fill the temporary array. + this->argc_ = 0; + for (int i = 0; i < this->total_size_; i++) + { + this->temp_[i] = this->argv_[i]; + this->argv_[i] = 0; + } + } + else + { + // Allocation failed, prohibit iteration. + this->current_index_ = this->argc_; + this->front_ = this->argc_; + } +} + +Arg_Shifter::~Arg_Shifter (void) +{ + // Delete the temporary vector. + delete [] temp_; +} + +char * +Arg_Shifter::get_current (void) const +{ + char *return_value = 0; + + if (this->is_anything_left ()) + return_value = this->temp_[current_index_]; + + return return_value; +} + +int +Arg_Shifter::consume_arg (int number) +{ + int return_value = 0; + + // Stick knowns at the end of the vector (consumed). + if (this->is_anything_left() >= number) + { + for (int i = 0, j = this->back_ - (number - 1); + i < number; + i++, j++, this->current_index_++) + this->argv_[j] = this->temp_[this->current_index_]; + + this->back_ -= number; + return_value = 1; + } + + return return_value; +} + +int +Arg_Shifter::ignore_arg (int number) +{ + int return_value = 0; + + // Keep unknowns at the head of the vector. + if (this->is_anything_left () >= number) + { + for (int i = 0; + i < number; + i++, this->current_index_++, this->front_++) + this->argv_[this->front_] = this->temp_[this->current_index_]; + + return_value = 1; + this->argc_ += number; + } + + return return_value; +} + +int +Arg_Shifter::is_anything_left (void) const +{ + return this->total_size_ - this->current_index_; +} + +int +Arg_Shifter::is_option_next (void) const +{ + return this->is_anything_left () && + this->temp_[this->current_index_][0] == '-'; +} + +int +Arg_Shifter::is_parameter_next (void) const +{ + return this->is_anything_left () + && this->temp_[this->current_index_][0] != '-'; +} + +int +Arg_Shifter::num_ignored_args (void) const +{ + return this->front_; +} diff --git a/TAO/tao/Arg_Shifter.h b/TAO/tao/Arg_Shifter.h new file mode 100644 index 00000000000..d0952b48e01 --- /dev/null +++ b/TAO/tao/Arg_Shifter.h @@ -0,0 +1,97 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// ======================================================================== +// +// = LIBRARY +// TAO +// +// = FILENAME +// Arg_Shifter.h +// +// = AUTHOR +// Seth Widoff +// +// ======================================================================== + +#if !defined (TAO_ARG_SHIFTER_H) +#define TAO_ARG_SHIFTER_H + +class Arg_Shifter +{ + // = TITLE + // This ADT shifts known args to the back of the argv vector, so + // deeper levels of argument parsing can locate the yet + // unprocessed arguments at the beginning of the vector. + // + // = DESCRIPTION + // The Arg_Shifter copies the pointers of the argv vector into a + // temporary array. As the Arg_Shifter iterates over the temp, is + // places known arguments in the rear of the argv and unknown + // ones in the beginning. So, after having visited all the + // arguments in the temp vector, Arg_Shifter has placed all the + // unknown arguments in their original order at the front of + // argv. +public: + Arg_Shifter (int &argc, char **argv, char **temp = 0); + // Initialize the Arg_Shifter to the vector over which to iterate, + // also providing the temporary array if the client doesn't want the + // arg_shifter to dynamically allocate its own. If internal dynamic + // allocation fails, the Arg_Shifter will set all the indices to the + // end of the vector, forbidding iteration. Following iteration over + // argv, the argc value will contain the number of unconsumed + // arguments. + + ~Arg_Shifter (void); + + char *get_current (void) const; + // Get the current head of the vector. + + int consume_arg (int number = 1); + // Consume <number> argument(s) by sticking them/it on the end of + // the vector. + + int ignore_arg (int number = 1); + // Place <number> arguments in the same relative order ahead of the + // known arguemnts in the vector. + + int is_anything_left (void) const; + // Returns the number of args left to see in the vector. + + int is_option_next (void) const; + // Returns 1 if there's a next item in the vector and it begins with + // '-'. + + int is_parameter_next (void) const; + // Returns 1 if there's a next item in the vector and it doesn't + // begin with '-'. + + int num_ignored_args (void) const; + // Returns the number of irrelevant args seen. + +private: + int &argc_; + // The size of the argument vector. + + int total_size_; + // The size of argv_. + + char **temp_; + // The temporary array over which we traverse. + + char **argv_; + // The array in which the arguments are reordered. + + int current_index_; + // The element in <temp_> we're currently examining. + + int back_; + // The index of <argv_> in which we'll stick the next unknown + // argument. + + int front_; + // The index of <argv_> in which we'll stick the next known + // argument. +}; + +#endif /* TAO_ARG_SHIFTER_H */ diff --git a/TAO/tao/CDR.cpp b/TAO/tao/CDR.cpp new file mode 100644 index 00000000000..8aadd881f13 --- /dev/null +++ b/TAO/tao/CDR.cpp @@ -0,0 +1,547 @@ +// $Id$ + +// Copyright 1994-1995 by Sun Microsystems Inc. +// All Rights Reserved + +// CDR: Encode/Decode basic machine data types +// +// Implementation of OMG "Common Data Representation" (CDR) ... there +// are one routine each for byte/halfword/word/doubleword put/get, +// which adjust to establish "natural" alignment (the bulk of the +// code) and then put or get with byteswapping as needed. +// +// The implementation knows that native data formats are conformant +// with OMG-IDL's (and hence CDR's) size requirements, and relies on +// the fact that (for example) CORBA_Long is always four bytes long +// even if the environment's "int" is a different size. +// +// char, octet 8 bits (1 byte) +// short, unsigned short 16 bits (2 bytes) +// long, unsigned long, float 32 bits (4 bytes) +// double, (unsigned) long long 64 bits (8 bytes) +// long double 128 bits (16 bytes) +// +// Moreover, this "knows" that the native 'char' represents ISO +// Latin/1 characters (an ASCII superset addressing Western European +// characters) and that "double" and "float" comply with the IEEE +// standards. (The "long double" may not be a native data type, +// though.) +// +// THREADING NOTE: "CDR" is a data structure which must be protected +// by external critical sections. Like simpler numeric types, "CDR" +// instances are accessed and modified atomically. This +// implementation is reentrant, so that independent "CDR" values may +// be manipulated concurrently when the underlying programming +// environment is itself reentrant. + +#include "tao/corba.h" + +// This functions are private, so it is safe to declare them inline in +// the .cpp file, we still use the ACE_INLINE macro to support +// compilations without any inline code. + +ACE_INLINE +void CDR::swap_long(char *orig, CORBA::Long &target) +{ + register char *lp = ACE_reinterpret_cast(char *,&target); + + lp [3] = *orig++; + lp [2] = *orig++; + lp [1] = *orig++; + lp [0] = *orig++; +} + +ACE_INLINE +void CDR::swap_ulonglong(char *orig, CORBA::ULongLong &target) +{ + register char *llp = ACE_reinterpret_cast(char *, &target); + + llp [7] = *orig++; + llp [6] = *orig++; + llp [5] = *orig++; + llp [4] = *orig++; + llp [3] = *orig++; + llp [2] = *orig++; + llp [1] = *orig++; + llp [0] = *orig++; +} + +ACE_INLINE +void CDR::swap_longdouble(char *orig, CORBA::LongDouble &target) +{ + register char *ldp = ACE_reinterpret_cast(char *, &target); + + 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++; +} + +ACE_INLINE void +CDR::mb_align (ACE_Message_Block* mb) +{ + ptr_arith_t temp = (ptr_arith_t) mb->base (); + + temp += MAX_ALIGNMENT - 1; + temp &= ~ ((ptr_arith_t) MAX_ALIGNMENT - 1); + char* start = ACE_reinterpret_cast(char*,temp); + mb->rd_ptr (start); + mb->wr_ptr (start); +} + +ACE_INLINE CORBA::Boolean +CDR::adjust_to_put (size_t size, char*& buf) +{ + buf = ACE_reinterpret_cast (char *, + ptr_align_binary (this->mb_->wr_ptr (), + size)); + char *end = buf + size; + + if (end <= this->mb_->end ()) + { + this->mb_->wr_ptr (end); + return CORBA::B_TRUE; + } + else if (this->grow (0)) + { + // grow(0) may change the value of wr_ptr() so we have to + // recompute the position.... + buf = ACE_reinterpret_cast (char *, + ptr_align_binary (this->mb_->wr_ptr (), + size)); + this->mb_->wr_ptr (buf + size); + return CORBA::B_TRUE; + } + + return CORBA::B_FALSE; +} + +ACE_INLINE CORBA::Boolean +CDR::adjust_to_get (size_t size, + char*& buf) +{ + buf = ACE_reinterpret_cast (char *, + ptr_align_binary (this->mb_->rd_ptr(), + size)); + char *end = buf + size; + if (end <= this->mb_->end ()) + { + this->mb_->rd_ptr (end); + return CORBA::B_TRUE; + } + + return CORBA::B_FALSE; +} + +CDR::CDR (char *buf, + size_t len, + int byte_order, + int consume_buf, + TAO_Marshal_Factory *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]. Yes, that + // complicates the grow () primitive. + : do_byteswap (byte_order != TAO_ENCAP_BYTE_ORDER), + factory_ (f), + mobj_ (0), + good_bit_ (1) +{ + if (buf != 0) + { + ACE_Message_Block::Message_Flags flags = + consume_buf ? 0 : ACE_Message_Block::DONT_DELETE; + ACE_NEW (this->mb_, + ACE_Message_Block + (new ACE_Data_Block (len, + ACE_Message_Block::MB_DATA, + (char *) buf, + 0, + 0, + flags))); + // We cannot trust the buffer to be properly aligned. + CDR::mb_align (this->mb_); + } + else + { + if (len == 0) + len = CDR::DEFAULT_BUFSIZE + CDR::MAX_ALIGNMENT; + ACE_NEW (this->mb_, ACE_Message_Block (len)); + CDR::mb_align (this->mb_); + } + +#if defined(ACE_PURIFY) + if (this->mb_->base () != 0) + (void) ACE_OS::memset (this->mb_->base (), 0, len); +#endif +} + +CDR::CDR (const CDR& rhs) + : do_byteswap (rhs.do_byteswap), + factory_ (rhs.factory_), + mobj_ (rhs.mobj_), + good_bit_ (rhs.good_bit_) +{ + this->mb_ = ACE_Message_Block::duplicate (rhs.mb_); + this->mb_->wr_ptr (rhs.mb_->wr_ptr ()); + this->mb_->rd_ptr (rhs.mb_->rd_ptr ()); +} + +CDR::~CDR (void) +{ + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; +} + +CORBA::Boolean +CDR::get_string (char*& buf) +{ + CORBA::ULong len; + return this->get_encapsulation (buf, len); +} + +CORBA::Boolean +CDR::get_encapsulation (char *&buf, CORBA::ULong& size) +{ + // TODO in some platforms this may not be safe..... + // @@ Carlos, can you please address this? + if (this->get_ulong (size)) + { + buf = this->mb_->rd_ptr (); + this->mb_->rd_ptr (size); + return CORBA::B_TRUE; + } + + return CORBA::B_FALSE; +} + +void +CDR::setup_encapsulation (char *buf, u_int len) +{ + // Also used when interpreting typecodes, but more generally when + // getting ready to read from encapsulations. In such cases the + // buffer alignment guarantees must be provided by the caller, this + // code doesn't verify them. These streams are "read only". + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; + ACE_NEW (this->mb_, + ACE_Message_Block (buf + 1, len - 1)); + do_byteswap = (buf[0] != TAO_ENCAP_BYTE_ORDER); + + this->mb_->wr_ptr (buf + len); + +#if 0 + // @@ TODO This test should be activated in debug version, but it + // seems a bit too conservative, checking for 4 byte boudaries + // should be OK for most cases. + + ptr_arith_t temp = (ptr_arith_t) buf + 1; + + temp += MAX_ALIGNMENT - 1; + temp &= ~ ((ptr_arith_t) MAX_ALIGNMENT - 1); + char* start = ACE_reinterpret_cast(char*,temp); + + if (start != buf + 1) + { + ACE_ERROR ((LM_WARNING, + "unproperly aligned buffer in " + "CDR::setup_encapsulation\n")); + } +#endif /* 0 */ +} + +void +CDR::setup_indirection (CDR& cdr, CORBA::Long offset) +{ + ACE_Message_Block::release (this->mb_); + this->do_byteswap = cdr.do_byteswap; + this->factory_ = cdr.factory_; + this->mobj_ = cdr.mobj_; + this->good_bit_ = 1; + + this->mb_ = ACE_Message_Block::duplicate (cdr.mb_); + this->mb_->wr_ptr (cdr.mb_->wr_ptr ()); + this->mb_->rd_ptr (cdr.mb_->rd_ptr () + offset); + + if (this->mb_->rd_ptr () < this->mb_->base () + || this->mb_->rd_ptr () > this->mb_->wr_ptr () ) + this->good_bit_ = 0; +} + +void +CDR::reset (void) +{ + CDR::mb_align (this->mb_); +} + +// Grow the CDR buffer, either to a known size (incoming message) or +// by a standard increment (creating outgoing message). +// +// We can't use realloc () because of a constraint that the part of the +// buffer into which we marshal be aligned according to MAX_ALIGNMENT, +// which can be a stronger requirement than malloc/realloc places on +// buffer. This makes growing a buffer on the encode side costly, +// since it can need to be done repetitively and copies more data each +// time. +// +// NOTE: this code knows about what's involved in the constructor and +// destructor, as it needs to invoke the constructor and do what the +// destructor would do (and not in the normal order). It also knows +// all other state that's significant. Change with care! +// +// NOTE: arguably this is a good place to ensure that the memory's +// zeroed out to comply with Orange Book C2 "object reuse" (meaning +// data, like I/O buffers) policy. IIOP doesn't mandate such policies +// though. + +CORBA::Boolean +CDR::grow (size_t newsize) +{ + // Calculate the new buffer's length; if growing for encode, we + // don't grow in "small" chunks because of the cost. + + size_t new_len; + + size_t size = this->mb_->size(); + if (newsize == 0) + { + // TODO We should the growth strategy should be controlled using + // the ORB parameters.... + if (size < CDR::EXP_GROWTH_MAX) + new_len = size * 2; + else + new_len = size + CDR::LINEAR_GROWTH_CHUNK; + } + else if (newsize <= size) + return CORBA::B_TRUE; + else + new_len = newsize; + + new_len += MAX_ALIGNMENT - 1; + + ACE_Message_Block *mb; + ACE_NEW_RETURN (mb, + ACE_Message_Block (new_len), + CORBA::B_FALSE); + + CDR::mb_align (mb); + + mb->copy (this->mb_->rd_ptr (), + this->mb_->length()); + ACE_Message_Block::release (this->mb_); + this->mb_ = mb; + + return CORBA::B_TRUE; +} + +// **************************************************************** +// put_ methods + +CORBA::Boolean +CDR::put_short (CORBA::Short s) +{ + char *buf; + + if (this->adjust_to_put (SHORT_SIZE, buf)) + { + // copy the half word, native byte order + *(CORBA::Short *)buf = s; + return CORBA::B_TRUE; + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::put_long (CORBA::Long l) +{ + char *buf; + + if (this->adjust_to_put (LONG_SIZE, buf)) + { + // copy the word, native byte order + *(CORBA::Long *)buf = l; + return CORBA::B_TRUE; + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::put_ulonglong (const CORBA::ULongLong &ull) +{ + char *buf; + + if (this->adjust_to_put (LONGLONG_SIZE, buf)) + { + *(CORBA::ULongLong *)buf = ull; + return CORBA::B_TRUE; + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::put_longdouble (CORBA::LongDouble &ld) +{ + char *buf; + + if (this->adjust_to_put (LONGDOUBLE_SIZE, buf)) + { + // copy the longdouble in native byte order + *(CORBA::LongDouble *)buf = ld; + return CORBA::B_TRUE; + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::put_string (const char *str, CORBA::ULong len) +{ + // Assuming that length is the length of the string. We insert len+1 + // for the additional NUL character. + if (this->put_long (len + 1)) + { + char *buf = this->mb_->wr_ptr (); + char *end = buf + len + 1; + + if (end <= this->mb_->end () + || this->grow (this->size () + len + 1)) + this->mb_->copy (str, len + 1); + + return CORBA::B_TRUE; + } + return CORBA::B_FALSE; +} + +// **************************************************************** +// get_ + +CORBA::Boolean +CDR::get_short (CORBA::Short &s) +{ + char *buf; + if (this->adjust_to_get (SHORT_SIZE, buf)) + { + // decode halfword, swapping as needed + if (!do_byteswap) + { + s = *(CORBA::Short *)buf; + return CORBA::B_TRUE; // put a return here to avoid a jump + } + else + { + // do swapping + register char *sp = ACE_reinterpret_cast(char *, &s); + + sp [1] = buf[0]; + sp [0] = buf[1]; + return CORBA::B_TRUE; + } + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::get_long (CORBA::Long &l) +{ + char *buf; + if (this->adjust_to_get (LONG_SIZE, buf)) + { + if (!do_byteswap) + { + l = *(CORBA::Long *)buf; + 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 (buf, l); + return CORBA::B_TRUE; + } + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::get_ulonglong (CORBA::ULongLong &ull) +{ + char *buf; + + if (this->adjust_to_get (LONGLONG_SIZE, buf)) + { + if (!do_byteswap) + { + ull = *(CORBA::ULongLong *)buf; + return CORBA::B_TRUE; + } + else + { + swap_ulonglong (buf, ull); + return CORBA::B_TRUE; + } + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::get_longdouble (CORBA::LongDouble &ld) +{ + char *buf; + + if (this->adjust_to_get (LONGDOUBLE_SIZE, buf)) + { + if (!do_byteswap) + { + ld = *(CORBA::LongDouble *)buf; + return CORBA::B_TRUE; + } + else + { + swap_longdouble (buf, ld); + return CORBA::B_TRUE; + } + } + + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +CORBA::Boolean +CDR::get_string (char *&str, CORBA::ULong len) +{ + // len includes the terminating 0 + char *end = this->mb_->rd_ptr () + len; + + if (end <= this->mb_->end ()) + { + ACE_OS::memcpy (str, this->mb_->rd_ptr (), len); + this->mb_->rd_ptr (end); + return CORBA::B_TRUE; + } + + return CORBA::B_FALSE; +} diff --git a/TAO/tao/CDR.h b/TAO/tao/CDR.h new file mode 100644 index 00000000000..b8812720e5f --- /dev/null +++ b/TAO/tao/CDR.h @@ -0,0 +1,379 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// cdr.h +// +// = DESCRIPTION +// Common Data Representation (CDR) marshaling streams. +// +// This implementation assumes that the native numeric +// representation is two's complement for integers, IEEE +// single/double for floats. Also that characters are in ISO +// Latin/1. +// +// Note that CDR itself makes no such assumptions, but this +// implementation makes such assumptions for reasons of +// efficiency. Careful enhancements could preserve that +// efficiency where the assumptions are true, yet still allow the +// code to work when they aren't true. +// +// The implementation expects that buffers are aligned according +// to the strongest CDR alignment restriction. +// +// NOTE: this does everything "CDR 1.1" does ... that is, it +// supports the five extended OMG-IDL data types in UNO Appendix +// A, which provide richer arithmetic types (64 bit integers, +// "quad precision" FP) and UNICODE-based characters and strings. +// Those types are not standard parts of OMG-IDL at this time. +// +// THREADING NOTE: CDR data structures must be protected against +// concurrent access by their owning thread. +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems, Inc. +// Many enhancements added by Andy Gokhake and Carlos O'Ryan. +// +// ============================================================================ + +#if !defined (TAO_CDR_H) +#define TAO_CDR_H + +class TAO_Export CDR +{ + // = TITLE + // The core marshaling primitive: a memory buffer, into which all + // the basic OMG-IDL datatypes can be placed ... or from which + // they can be retreived. + // + // = DESCRIPTION + // A particularly useful static member function for this buffer is + // an interpretive encoding routine, usable as a typecode + // interpreter callback. Ditto for decoding. These are used to + // support all OMG-IDL datatypes, even those not supported + // directly by put/get primitives. + // + // Struct members are intentionally exposed; the functionality of + // this class, and hence the appropriate abstactions for them, + // hasn't quite settled down enough to settle on fast abstractions + // that let data be hidden without pointlessly sacrificing speed. +public: + // = Constants defined by the CDR protocol. + + // By defining these constants as enums we ensure they get inlined + // and avoid pointless static memory allocations. + + enum + { + // Note that some of these get reused as part of the standard + // binary format: unsigned is the same size as its signed cousin, + // float is CDR_LONG_SIZE, and double is CDR_LONGLONG_SIZE. + + SHORT_SIZE = 2, + LONG_SIZE = 4, + LONGLONG_SIZE = 8, + LONGDOUBLE_SIZE = 16, + + MAX_ALIGNMENT = 16, + // Maximal CDR 1.1 alignment: "quad precision" FP (i.e. "long + // double", size as above). + + DEFAULT_BUFSIZE = 1430, + // Ethernet MTU, less headers. Default buffer size for + // request/response messages. These are normally stack-allocated, + // and tuning may cause you to want to change this value. The + // best value depends on your particular application mix; you can + // also change how buffers grow(). Most remote invocations + // (statistically) are "small", and the default used here is + // perhaps larger than most such messages. + // + // If this size is "too small" you need to heap-allocate buffers too + // often. "Too large" is mostly a waste of stackspace, but stack + // frames as large as the system page size (often 4Kb) can easily + // overrun the "redzone" at the bottom of most VM-based stacks. + + EXP_GROWTH_MAX = 4096, + // The buffer size grows exponentially until it reaches this size; + // afterwards it grows linearly using the next constant + + LINEAR_GROWTH_CHUNK = 4096 + // Once exponential growth is ruled out the buffer size increases + // in chunks of this size, note that this constants have the same + // value right now, but it does not need to be so. + }; + // = ENCODING SUPPORT + + // = Adjust pointers as needed, then store in the native byte order. + // + // There exist only routines to put byte, halfword (2 bytes), word + // (4 bytes), doubleword (8 bytes) and quadword (16 byte) entities, + // 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 (CORBA::Float f); + // encode a float into the CDR stream + + CORBA::Boolean put_double (const CORBA::Double &d); + // encode a double into the CDR stream + + CORBA::Boolean put_longdouble (CORBA::LongDouble &ld); + // encode a longdouble into the CDR stream + + CORBA::Boolean put_string (const char *str, CORBA::ULong len); + // encode a string of length len + + CORBA::TypeCode::traverse_status encode (CORBA::TypeCode_ptr tc, + const void *data, + const void *, + CORBA::Environment &env); + // Marshaling. ... <context> really points to a <CDR>. + + // = DECODING SUPPORT + + // Same assumptions are made as above, but a flag is tested to + // determine whether decode should byteswap or not. It's cheaper to + // 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 (CORBA::ULongLong &ull); + // decode an unsigned longlong from the CDR stream + + CORBA::Boolean get_float (CORBA::Float &f); + // decode a float from the CDR stream + + CORBA::Boolean get_double (CORBA::Double &d); + // decode a double from the CDR stream + + CORBA::Boolean get_longdouble (CORBA::LongDouble &ld); + // decode a longdouble from the CDR stream + + CORBA::Boolean get_string (char *&str, CORBA::ULong len); + // decode a string. Length includes the terminating 0 + + CORBA::TypeCode::traverse_status decode (CORBA::TypeCode_ptr tc, + const void *data, + const void *, + CORBA::Environment &env); + // Unmarshaling interpreter ... <context> really points to a <CDR>. + + CDR (char *buf = 0, + size_t len = 0, + int byte_order = TAO_ENCAP_BYTE_ORDER, + int consume_buf = 0, + TAO_Marshal_Factory *f = TAO_Marshal::DEFAULT_MARSHAL_FACTORY); + // constructor + + CDR (const CDR& rhs); + // Copy constructor, build a new stream that points to the same data + // as <rhs>. + // Using this new stream for writing results in undefined behavior. + + ~CDR (void); + // destructor + + // = Used mostly when interpreting typecodes. + + // These may change the state of a CDR buffer even when errors are + // reported. + + CORBA::Boolean skip_string (void); + // skip a string field in a typecode + + // TODO: This methods should be private and the classes that need it + // (TypeCode, Exception, etc.) would be declared friend. + + CORBA::Boolean get_encapsulation (char*& buf, CORBA::ULong& len); + // Returns an encapsulated buffer (such as a string) stored inside + // the CDR. + // TODO: This method should be private and the classes that need it + // (TypeCode, Exception, etc.) would be declared friend. + + CORBA::Boolean get_string (char*& buf); + // Returns an encapsulated string stored inside the CDR; but without + // any copying. + + CORBA::Boolean rd_ptr (size_t n); + // Move the read pointer <n> bytes ahead, it is used to skip + // portions of the stream, specially in typecodes. + + CORBA::Boolean wr_ptr (size_t n); + // Move the write pointer <n> bytes ahead, it is used to when the + // CDR is read from a socket to set the end of the message. + + void setup_encapsulation (char *buf, u_int len); + // Also used when interpreting typecodes, but more generally when + // getting ready to read from encapsulations. In such cases the + // buffer alignment guarantees must be provided by the caller, this + // code doesn't verify them. These streams are "read only". + + void setup_indirection (CDR& cdr, CORBA::Long offset); + // Set the CDR to point to the stream in <cdr>. + // The stream is read-only from then on. + + CORBA::Boolean grow (size_t newlength); + // Grow the buffer to the identified size ... if it's zero, just + // grow it by a standard quantum (e.g. when encoding we can't know + // in advance how big it will need to become). + + size_t bytes_remaining (void); + // Some code needs to know how much is left on encode or decode. + + int good_bit (void) const; + // If zero then some error has ocurred. + + char *buffer (void) const; + // Return the internal buffer. + + size_t length (void) const; + // Return the internal buffer length (how many bytes in the buffer + // contain useful data). + + size_t size (void) const; + // Return the internal buffer capacity. + + void reset (void); + // Reset the read and write pointers to the start of the buffer. + + int do_byteswap; + // for decoding only. + // TODO: It could be used for encoding also, for instance, if all + // the machines in a network but one are little endian it makes + // sense to make that machine swap the bytes on write. At least + // some people would like such a feature. + +private: + static void swap_long (char *orig, CORBA::Long &target); + // do byte swapping for longs + + static void swap_ulonglong (char *orig, CORBA::ULongLong &target); + // do byte swapping for longlongs + + static void swap_longdouble (char *orig, CORBA::LongDouble &target); + // do byte swapping for longdoubles + + static void mb_align (ACE_Message_Block* mb); + + CORBA::Boolean adjust_to_put (size_t size, + char*& buf); + // Returns (in <buf>) the next position in the buffer aligned to + // <size>, it advances the Message_Block wr_ptr past the data + // (i.e. <buf> + <size>). If necessary it grows the Message_Block + // buffer. Returns B_FALSE on failure. + + CORBA::Boolean adjust_to_get (size_t size, + char*& buf); + // Returns (in <buf>) the next position in the buffer aligned to + // <size>, it sets the Message_Block rd_ptr past the data + // (i.e. <buf> + <size>). Returns B_FALSE on failure. + +private: + ACE_Message_Block *mb_; + // The buffer is stored in a Message_Block, future implementations + // will take advantage of the chaining features of it to provide + // minimal copying encapsulation. + + TAO_Marshal_Factory *factory_; + // Maintain a factory that can make specialized marshaling objects. + + TAO_Marshal_Object *mobj_; + // Maintain an instance of a marshaling object. The CDR stream + // delegates the marshaling activity to mobj_. + + int good_bit_; + // Set to 0 when an error ocurrs. +}; + +#if !defined(__ACE_INLINE__) +extern CDR &operator<< (CDR &cdr, CORBA::Boolean x); +extern CDR &operator<< (CDR &cdr, CORBA::Octet x); +extern CDR &operator<< (CDR &cdr, CORBA::Short x); +extern CDR &operator<< (CDR &cdr, CORBA::UShort x); +extern CDR &operator<< (CDR &cdr, CORBA::Long x); +extern CDR &operator<< (CDR &cdr, CORBA::ULong x); +extern CDR &operator<< (CDR &cdr, CORBA::LongLong x); +extern CDR &operator<< (CDR &cdr, CORBA::ULongLong x); +extern CDR &operator<< (CDR &cdr, CORBA::Float x); +extern CDR &operator<< (CDR &cdr, CORBA::Double x); +extern CDR &operator<< (CDR &cdr, CORBA::Char x); +extern CDR &operator<< (CDR &cdr, CORBA::WChar x); +extern CDR &operator>> (CDR &cdr, CORBA::Boolean &x); +extern CDR &operator>> (CDR &cdr, CORBA::Octet &x); +extern CDR &operator>> (CDR &cdr, CORBA::Short &x); +extern CDR &operator>> (CDR &cdr, CORBA::UShort &x); +extern CDR &operator>> (CDR &cdr, CORBA::Long &x); +extern CDR &operator>> (CDR &cdr, CORBA::ULong &x); +extern CDR &operator>> (CDR &cdr, CORBA::LongLong &x); +extern CDR &operator>> (CDR &cdr, CORBA::ULongLong &x); +extern CDR &operator>> (CDR &cdr, CORBA::Float &x); +extern CDR &operator>> (CDR &cdr, CORBA::Double &x); +extern CDR &operator>> (CDR &cdr, CORBA::Char &x); +extern CDR &operator>> (CDR &cdr, CORBA::WChar &x); +#endif /* __ACE_INLINE */ + +#endif /* TAO_CDR_H */ diff --git a/TAO/tao/CDR.i b/TAO/tao/CDR.i new file mode 100644 index 00000000000..475ba9eaf5b --- /dev/null +++ b/TAO/tao/CDR.i @@ -0,0 +1,394 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// 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, env); + + if (this->mobj_) + return this->mobj_->decode (tc, data, data2, this, env); + else + return CORBA::TypeCode::TRAVERSE_STOP; +} + +// Encode data into CDR stream. + +ACE_INLINE CORBA::Boolean +CDR::skip_string (void) +{ + char *dummy0; + CORBA::ULong dummy1; + return this->get_encapsulation (dummy0, dummy1); +} + +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, env); + + if (this->mobj_) + return this->mobj_->encode (tc, data, data2, this, env); + else + return CORBA::TypeCode::TRAVERSE_STOP; +} + +ACE_INLINE size_t +CDR::bytes_remaining (void) +{ + return this->mb_->length(); +} + +ACE_INLINE int +CDR::good_bit (void) const +{ + return this->good_bit_; +} + +ACE_INLINE char* +CDR::buffer (void) const +{ + return this->mb_->rd_ptr(); +} + +ACE_INLINE size_t +CDR::length (void) const +{ + return this->mb_->length (); +} + +ACE_INLINE size_t +CDR::size (void) const +{ + return this->mb_->size (); +} + +// **************************************************************** +// put_ routines + +ACE_INLINE CORBA::Boolean +CDR::put_byte (char c) +{ + if (this->mb_->wr_ptr () + 1 <= this->mb_->end () + || grow (0) == CORBA::B_TRUE) + { + this->mb_->copy (&c, 1); + return CORBA::B_TRUE; + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +ACE_INLINE CORBA::Boolean +CDR::put_char (CORBA::Char c) +{ + return put_byte ((char) c); +} + +ACE_INLINE CORBA::Boolean +CDR::put_wchar (CORBA::WChar wc) +{ + // "wchar_t" isn't always 2 bytes, such systems might need further + // conversion (e.g. hosts with multibyte characters native, rather + // than UNICODE) + + return put_short ((short) wc); +} + +ACE_INLINE CORBA::Boolean +CDR::put_boolean (CORBA::Boolean b) +{ + return put_byte ((char) (b != CORBA::B_FALSE)); +} + +ACE_INLINE CORBA::Boolean +CDR::put_octet (CORBA::Octet o) +{ + return put_byte ((char) o); +} + +ACE_INLINE CORBA::Boolean +CDR::put_ushort (CORBA::UShort s) +{ + return put_short ((CORBA::Short) s); +} + +ACE_INLINE CORBA::Boolean +CDR::put_ulong (CORBA::ULong l) +{ + return put_long ((CORBA::Long) l); +} + +ACE_INLINE CORBA::Boolean +CDR::put_longlong (const CORBA::LongLong &ll) +{ + return put_ulonglong ((CORBA::ULongLong &) ll); +} + +ACE_INLINE CORBA::Boolean +CDR::put_float (CORBA::Float f) +{ + return put_long (*(CORBA::Long *) &f); +} + +ACE_INLINE CORBA::Boolean +CDR::put_double (const CORBA::Double &d) +{ + return put_ulonglong (*(CORBA::ULongLong *) &d); +} + +// **************************************************************** +// DECODING routines ... adjust pointer, then byteswap as needed. + +ACE_INLINE CORBA::Boolean +CDR::get_byte (char &c) +{ + if (this->mb_->rd_ptr () + 1 <= this->mb_->end ()) + { + c = (char) *this->mb_->rd_ptr (); + this->mb_->rd_ptr (1); + return CORBA::B_TRUE; + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +ACE_INLINE CORBA::Boolean +CDR::get_char (CORBA::Char &o) +{ + return this->get_byte ((char &) o); +} + +ACE_INLINE CORBA::Boolean +CDR::get_wchar (CORBA::WChar &wc) +{ + short s; + + // wchar_t isn't always "short" + + CORBA::Boolean retval = this->get_short (s); + wc = s; + return retval; +} + +ACE_INLINE CORBA::Boolean +CDR::get_boolean (CORBA::Boolean &b) +{ + CORBA::Char c; + + // CORBA::Boolean is rarely 'char' + CORBA::Boolean retval = this->get_char (c); + b = (c == 1); + return retval; +} + +ACE_INLINE CORBA::Boolean +CDR::get_octet (CORBA::Octet &o) +{ + return this->get_byte ((char &) o); +} + +ACE_INLINE CORBA::Boolean +CDR::get_ushort (CORBA::UShort &s) +{ + return this->get_short ((short&) s); +} + +ACE_INLINE CORBA::Boolean +CDR::get_ulong (CORBA::ULong &l) +{ + return this->get_long ((CORBA::Long &) l); +} + +ACE_INLINE CORBA::Boolean +CDR::get_longlong (CORBA::LongLong &ll) +{ + return this->get_ulonglong ((CORBA::ULongLong &) ll); +} + +ACE_INLINE CORBA::Boolean +CDR::get_float (float &f) +{ + return this->get_long ((CORBA::Long &) f); +} + +ACE_INLINE CORBA::Boolean +CDR::get_double (double &d) +{ + return this->get_ulonglong ((CORBA::ULongLong &) d); +} + +ACE_INLINE CORBA::Boolean +CDR::rd_ptr (size_t n) +{ + if (this->mb_->rd_ptr () + n <= this->mb_->end ()) + { + this->mb_->rd_ptr (n); + return CORBA::B_TRUE; + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +ACE_INLINE CORBA::Boolean +CDR::wr_ptr (size_t n) +{ + if (this->mb_->wr_ptr () + n <= this->mb_->end ()) + { + this->mb_->wr_ptr (n); + return CORBA::B_TRUE; + } + this->good_bit_ = 0; + return CORBA::B_FALSE; +} + +// **************************************************************** +// TODO: Use the CORBA_* types when they become available. + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Octet x) +{ + cdr.put_octet (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Short x) +{ + cdr.put_short (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::UShort x) +{ + cdr.put_short (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Long x) +{ + cdr.put_long (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::ULong x) +{ + cdr.put_long (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::LongLong x) +{ + cdr.put_longlong (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::ULongLong x) +{ + cdr.put_ulonglong (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Float x) +{ + cdr.put_float (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Double x) +{ + cdr.put_double (x); + return cdr; +} + +ACE_INLINE CDR & +operator<< (CDR &cdr, CORBA::Char x) +{ + cdr.put_char (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Octet &x) +{ + cdr.get_octet (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Short &x) +{ + cdr.get_short (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::UShort &x) +{ + cdr.get_ushort (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Long &x) +{ + cdr.get_long (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::ULong &x) +{ + cdr.get_ulong (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::LongLong &x) +{ + cdr.get_longlong (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::ULongLong &x) +{ + cdr.get_ulonglong (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Float &x) +{ + cdr.get_float (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Double &x) +{ + cdr.get_double (x); + return cdr; +} + +ACE_INLINE CDR & +operator>> (CDR &cdr, CORBA::Char &x) +{ + cdr.get_char (x); + return cdr; +} diff --git a/TAO/tao/NVList.cpp b/TAO/tao/NVList.cpp new file mode 100644 index 00000000000..313c2fa764f --- /dev/null +++ b/TAO/tao/NVList.cpp @@ -0,0 +1,275 @@ +// This may look like C, but it's really -*- C++ -*- + +// Implementation of Named Value List and NamedValue classes + +#include "tao/corba.h" + +CORBA::ULong +CORBA_NamedValue::AddRef (void) +{ + return refcount_++; +} + +CORBA::ULong +CORBA_NamedValue::Release (void) +{ + { + ACE_ASSERT (this != 0); + + if (--this->refcount_ != 0) + return this->refcount_; + } + + // delete this; + // this is causing free mismatched memory error + this->~CORBA_NamedValue (); + ACE_OS::free (this); + return 0; +} + +// Reference counting for DII Request object + +void +CORBA::release (CORBA::NamedValue_ptr nv) +{ + if (nv) + nv->Release (); +} + +CORBA::Boolean +CORBA::is_nil (CORBA::NamedValue_ptr nv) +{ + return (CORBA::Boolean) (nv == 0); +} + +CORBA_NamedValue::~CORBA_NamedValue (void) +{ + if (this->name_) + { + CORBA::string_free (this->name_); + this->name_ = 0; + } + // the Any will be destroyed on its own as we hold an instance and not a + // pointer to Any +} + + +// =Methods on class NVList + +CORBA::ULong +CORBA_NVList::AddRef (void) +{ + return this->refcount_++; +} + +CORBA::ULong +CORBA_NVList::Release (void) +{ + { + ACE_ASSERT (this != 0); + + if (--this->refcount_ != 0) + return this->refcount_; + } + + delete this; + return 0; +} + +// Reference counting for DII Request object + +void +CORBA::release (CORBA::NVList_ptr nvl) +{ + if (nvl) + nvl->Release (); +} + +CORBA::Boolean +CORBA::is_nil (CORBA::NVList_ptr nvl) +{ + return (CORBA::Boolean) (nvl == 0); +} + +CORBA_NVList::~CORBA_NVList (void) +{ + // destroy each NamedValue element + for (CORBA::ULong i = 0; i < this->max_; i++) + (&this->values_[i])->~CORBA_NamedValue (); + + if (this->values_) + ACE_OS::free ((char *)values_); + + this->values_ = 0; + this->len_ = this->max_ = 0; +} + +// add an element and just initialize its flags +CORBA::NamedValue_ptr +CORBA_NVList::add (CORBA::Flags flags, + CORBA::Environment &env) +{ + CORBA::ULong len = this->len_; // next slot + + // call the helper to allocate a NamedValue element (if necessary) + if (!this->add_element (flags, env)) + return 0; + + // now initialize the fields + this->values_[len].flags_ = flags; + return &this->values_[len]; +} + +// add an element and just initialize its flags and name +CORBA::NamedValue_ptr +CORBA_NVList::add_item (const char *name, + CORBA::Flags flags, + CORBA::Environment &env) +{ + CORBA::ULong len = this->len_; // next slot + + // call the helper to allocate a NamedValue element (if necessary) + if (!this->add_element (flags, env)) + return 0; + + // now initialize the fields + this->values_[len].flags_ = flags; + this->values_[len].name_ = CORBA::string_dup (name); + return &this->values_[len]; +} + +// add a value. If necessary, increment the list +CORBA::NamedValue_ptr +CORBA_NVList::add_value (const char *name, + const CORBA::Any &value, + CORBA::Flags flags, + CORBA::Environment &env) +{ + CORBA::ULong len = this->len_; // next slot + + // call the helper to allocate a NamedValue element (if necessary) + if (!this->add_element (flags, env)) + return 0; + + // now initialize the fields + this->values_[len].flags_ = flags; + this->values_[len].name_ = CORBA::string_dup (name); // make a copy + + if (ACE_BIT_ENABLED (flags, CORBA::IN_COPY_VALUE)) + // IN_COPY_VALUE means that the parameter is not "borrowed" by + // the ORB, but rather that the ORB copies its value. + // + // Initialize the newly allocated memory using a copy + // constructor that places the new "Any" value at just the right + // place, and makes a "deep copy" of the data. + (void) new (&this->values_[len].any_) CORBA::Any (value); + else + + // The normal behaviour for parameters is that the ORB "borrows" + // their memory for the duration of calls. + // + // Initialize the newly allocated "Any" using a normal + // constructor that places the new "Any" value at just the right + // place, yet doesn't copy the memory (except for duplicating + // the typecode). + // + // NOTE: DSI has yet to be updated so that it's OK to use such + // application-allocated memory. It needs at least a "send the + // response now" call. + // + (void) new (&this->values_[len].any_) CORBA::Any (value.type (), + (void *)value.value (), + CORBA::B_FALSE); // does + // not + // own + + // return pointer to the newly inserted member + return &this->values_[len]; +} + +// add an element and just initialize its flags and name +CORBA::NamedValue_ptr +CORBA_NVList::add_item_consume (char *name, + CORBA::Flags flags, + CORBA::Environment &env) +{ + CORBA::ULong len = this->len_; // next slot + + // call the helper to allocate a NamedValue element (if necessary) + if (!this->add_element (flags, env)) + return 0; + + // now initialize the fields + this->values_[len].flags_ = flags; + this->values_[len].name_ = name; // we consume it + return &this->values_[len]; +} + +// add a value. If necessary, increment the list +CORBA::NamedValue_ptr +CORBA_NVList::add_value_consume (char * /*name*/, + CORBA::Any * /*value*/, + CORBA::Flags /*flags*/, + CORBA::Environment &/*env*/) +{ + // not implemented because we need to see how we can consume the value + // One soln is to make the any_ member of NamedValue to be a Any_ptr or + // Any_var + // XXXASG- TODO + return 0; +} + +//CORBA::Status +void +CORBA_NVList::remove (CORBA::ULong /*n*/, CORBA::Environment &/*env*/) +{ + // not implemented + // XXXASG - TODO + +} + +// Helper method +CORBA::Boolean +CORBA_NVList::add_element (CORBA::Flags flags, CORBA::Environment &env) +{ + env.clear (); + if (ACE_BIT_DISABLED (flags, CORBA::ARG_IN | CORBA::ARG_OUT | CORBA::ARG_INOUT)) + { + env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO)); + return 0; + } + + // We track "len_" and "max_" like sequences do; mixing the + // "add_arg" and nvlist[i] style accessors produces undefined + // behaviour. + CORBA::ULong len = this->len_++; // len_ points to the next available + // slot. Access is by zero based indexing + + // Extend the array with an _initialized_ element ... relying on + // zeroed memory to be sufficiently initialized. + // + + if (this->values_ == 0) // list was created as an empty list + { + this->values_ = (CORBA::NamedValue_ptr) + ACE_OS::calloc (this->len_, sizeof (CORBA::NamedValue)); + this->max_ = this->len_; + } + else if (len >= max_) // need reallocation + { + // reallocate a larger buffer + this->values_ = (CORBA::NamedValue_ptr) ACE_OS::realloc + ((char *)this->values_, sizeof (CORBA::NamedValue) * this->len_); + // now zero the elements that have been newly allocated + (void) ACE_OS::memset (&this->values_[this->max_], 0, + sizeof (values_[this->max_]) * (this->len_ - this->max_)); + this->max_ = this->len_; // set the new maximum size + } + if (!this->values_) + { + env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO)); + return 0; + } + + return 1; // success +} diff --git a/TAO/tao/NVList.h b/TAO/tao/NVList.h new file mode 100644 index 00000000000..5dff27b1220 --- /dev/null +++ b/TAO/tao/NVList.h @@ -0,0 +1,160 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// NVList.h +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// and +// Aniruddha Gokhale (additions, missing operations) +// +// ============================================================================ + +#if !defined (TAO_NVLIST_H) +# define TAO_NVLIST_H + +class TAO_Export CORBA_NamedValue +{ + // = TITLE + // NamedValue ... these occur only in "NVList" (named value list) data + // structures. The binary form of the data structure is frozen and + // visible to programs using it (e.g. from C). The C++ class supports + // some programming discipline, e.g. to avoid memory leaks. + // + // They just represent parameters to calls. The name is optional, and + // the value is packaged as an Any. The flags indicate parameter + // mode, and some ownership rules for "top level" memory. +public: + const char *name (void) const; + // optional name + + CORBA::Any_ptr value (void) const; + // return the value + + CORBA::Flags flags (void) const; + // return the parameter mode flag + + ~CORBA_NamedValue (void); + // destructor - manages the name and value + + // = Methods required for COM IUnknown support. + + CORBA::ULong AddRef (void); + CORBA::ULong Release (void); + +private: + u_int refcount_; + // refcount used in release + + CORBA::Any any_; + // holds the value + + CORBA::Flags flags_; + // parameter mode flags + + char *name_; + // optional IDL name of the parameter + + CORBA_NamedValue (void); + // private constructor. Cannot be directly instantiated other than by its + // friends. + + friend class CORBA_ORB; + friend class CORBA_NVList; + friend class CORBA_Request; +}; + +class TAO_Export CORBA_NVList +{ + // = TITLE + // NVList ... this is used in the (client side) DII (Dynamic + // Invocation Interface) to hold parameters, except for the return + // parameter. It's used in the same role in the (server side) DSI + // (Dynamic Skeleton Interface). + // + // = DESCRIPTION + // Each user (client, server) provides the typecode and memory for + // each parameter using an NVList, then talks to the ORB using a + // Request or ServerRequest pseudo-object. The ORB copies data + // to/from the IPC messages (e.g. IIOP::Request, IIOP::Response) + // as appropriate. +public: + ~CORBA_NVList (void); + // destructor + + CORBA::ULong count (void) const; + // return the current number of elements in the list + + CORBA::NamedValue_ptr add (CORBA::Flags, + CORBA::Environment &); + // add an element and just initialize the flags + + CORBA::NamedValue_ptr add_item (const char *, + CORBA::Flags, + CORBA::Environment &); + // add an element and initialize its name and flags + + CORBA::NamedValue_ptr add_value (const char *, + const CORBA::Any &, + CORBA::Flags, + CORBA::Environment &); + // initializes a value, name, and flags + + CORBA::NamedValue_ptr add_item_consume (char *, + CORBA::Flags, + CORBA::Environment &); + // just like add_item. In addition, memory management of char * name is taken + // over by the NVList + + CORBA::NamedValue_ptr add_value_consume (char *, + CORBA::Any_ptr, + CORBA::Flags, + CORBA::Environment &); + // just like add_value. In addition, the NVList controls the memory + // management of the char *name and Any *value parameter + + CORBA::NamedValue_ptr item (CORBA::ULong n, CORBA::Environment &env); + // retrieve the item at the nth location. Raises Bounds + + + // CORBA::Status + void remove (CORBA::ULong n, CORBA::Environment &env); + // remove element at index n. Raises Bounds + + // = Methods required for COM IUnknown support + + CORBA::ULong AddRef (void); + CORBA::ULong Release (void); + +private: + CORBA_NVList (void); + // constructor - cannot be instantiated directly other than through the + // ORB::create_list method + + CORBA::Boolean add_element (CORBA::Flags, CORBA::Environment &); + // helper to increase the list size. This is used by all the add_ methods of + // the NVList class + + CORBA::NamedValue *values_; + // list of parameters stored as NamedValues + + CORBA::ULong max_; + // maximum length of list + + CORBA::ULong len_; + // current length of list + + CORBA::ULong refcount_; + // maintains how many references exist to this object + + friend class CORBA_ORB; + friend class CORBA_Request; +}; + +#endif /* TAO_NVLIST_H */ diff --git a/TAO/tao/NVList.i b/TAO/tao/NVList.i new file mode 100644 index 00000000000..9cf97b1efcb --- /dev/null +++ b/TAO/tao/NVList.i @@ -0,0 +1,63 @@ +// This may look like C, but it's really -*- C++ -*- + +// constructor +ACE_INLINE +CORBA_NamedValue::CORBA_NamedValue (void) + : refcount_ (1), + flags_ (0), + name_ (0) +{ +} + +// return the name +ACE_INLINE const char* +CORBA_NamedValue::name (void) const +{ + return this->name_; +} + +// return the value +ACE_INLINE CORBA::Any_ptr +CORBA_NamedValue::value (void) const +{ + return ACE_const_cast(CORBA::Any_ptr,&this->any_); +} + +// return the flags +ACE_INLINE CORBA::Flags +CORBA_NamedValue::flags (void) const +{ + return this->flags_; +} + + +// = methods for the NVList class + +// constructor +ACE_INLINE +CORBA_NVList::CORBA_NVList (void) + : values_ (0), + max_ (0), + len_ (0), + refcount_ (1) +{ +} + +ACE_INLINE CORBA::ULong +CORBA_NVList::count (void) const +{ + return this->max_; +} + +ACE_INLINE CORBA::NamedValue_ptr +CORBA_NVList::item (CORBA::ULong n, CORBA::Environment &env) +{ + env.clear (); + if (n >= this->max_) // 0 based indexing + { + env.exception (new CORBA::TypeCode::Bounds ()); + return 0; + } + else + return &this->values_ [n]; +} diff --git a/TAO/tao/ORB_Strategies_T.cpp b/TAO/tao/ORB_Strategies_T.cpp new file mode 100644 index 00000000000..4e236326a95 --- /dev/null +++ b/TAO/tao/ORB_Strategies_T.cpp @@ -0,0 +1,46 @@ +// $Id$ + +#include "tao/ORB_Strategies_T.h" + +#if !defined (__ACE_INLINE__) +#include "tao/ORB_Strategies_T.i" +#endif /* __ACE_INLINE__ */ + +template <class SH> int +TAO_Reactive_Strategy<SH>::activate_svc_handler (SH *svc_handler, void *arg) +{ + ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::activate_svc_handler"); + + ACE_Reactor *r = TAO_ORB_Core_instance ()->reactor (); + + int result = 0; + + if (r == 0) + result = -1; + + // Register with the Reactor with the appropriate <mask>. + else if (r->register_handler (svc_handler, this->mask_) == -1) + result = -1; + + // If the implementation of the reactor uses event associations + else if (r->uses_event_associations ()) + { + // If we don't have non-block on, it won't work with + // WFMO_Reactor + // This maybe too harsh + // if (!ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK)) + // goto failure; + if (svc_handler->open ((void *) this) != -1) + return 0; + else + result = -1; + } + else + // Call up to our parent to do the SVC_HANDLER initialization. + return this->inherited::activate_svc_handler (svc_handler, arg); + + if (result == -1) + svc_handler->close (0); + + return result; +} diff --git a/TAO/tao/ORB_Strategies_T.h b/TAO/tao/ORB_Strategies_T.h new file mode 100644 index 00000000000..9f7dde2000a --- /dev/null +++ b/TAO/tao/ORB_Strategies_T.h @@ -0,0 +1,45 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// ORB_Strategies_T.h +// +// = AUTHOR +// Chris Cleeland +// +// ============================================================================ + +#if !defined (TAO_ORB_STRATEGIES_T_H) +# define TAO_ORB_STRATEGIES_T_H + +#include "ace/Strategies_T.h" + +template <class SH> +class TAO_Reactive_Strategy : public ACE_Reactive_Strategy<SH> +{ + // @@ Please document me. +public: + TAO_Reactive_Strategy (void); + ~TAO_Reactive_Strategy (void); + + virtual int activate_svc_handler (SH *sh, void *arg); +}; + +#if defined (__ACE_INLINE__) +#include "tao/ORB_Strategies_T.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "tao/ORB_Strategies_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("ORB_Strategies_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* TAO_ORB_STRATEGIES_T_H */ diff --git a/TAO/tao/ORB_Strategies_T.i b/TAO/tao/ORB_Strategies_T.i new file mode 100644 index 00000000000..9655ecf55a0 --- /dev/null +++ b/TAO/tao/ORB_Strategies_T.i @@ -0,0 +1,10 @@ +template <class SH> ACE_INLINE +TAO_Reactive_Strategy<SH>::TAO_Reactive_Strategy (void) +{ +} + +template <class SH> ACE_INLINE +TAO_Reactive_Strategy<SH>::~TAO_Reactive_Strategy (void) +{ +} + diff --git a/TAO/tao/Principal.cpp b/TAO/tao/Principal.cpp new file mode 100644 index 00000000000..877c01ddacb --- /dev/null +++ b/TAO/tao/Principal.cpp @@ -0,0 +1,50 @@ +// $Id$ + +// Copyright 1994-1995 by Sun Microsystems Inc. +// All Rights Reserved +// ORB: Principal identifier pseudo-objref + +#include "tao/corba.h" + +void +CORBA::release (CORBA::Principal_ptr principal) +{ + if (principal) + principal->Release (); +} + +CORBA::Boolean +CORBA::is_nil (CORBA::Principal_ptr principal) +{ + return (CORBA::Boolean) (principal == 0); +} + +CORBA_Principal::CORBA_Principal (void) +{ +} + +CORBA_Principal::~CORBA_Principal (void) +{ + assert (refcount_ == 0); + + if (id.buffer) + delete [] id.buffer; +} + +CORBA::ULong +CORBA_Principal::AddRef (void) +{ + return ++refcount_; +} + +CORBA::ULong +CORBA_Principal::Release (void) +{ + { + if (--refcount_ != 0) + return refcount_; + } + + delete this; + return 0; +} diff --git a/TAO/tao/Principal.h b/TAO/tao/Principal.h new file mode 100644 index 00000000000..0de5dde1404 --- /dev/null +++ b/TAO/tao/Principal.h @@ -0,0 +1,60 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// principal.h +// +// = DESCRIPTION +// The CORBA_Principal pseudo-object implementation. +// +// = AUTHOR +// Copyright 1994-1995 by Sun Microsystems Inc. +// +// ============================================================================ + +#if !defined (TAO_PRINCIPAL_H) +# define TAO_PRINCIPAL_H + +class TAO_Export CORBA_Principal +{ + // = TITLE + // A "Principal" identifies an authenticated entity in the + // network administration framework. Identities are used to + // control acccess (authorization) as well as in audit trails + // (accountability). +public: + // To applications, the identifier is an opaque ID. + + // CORBA::SEQUENCE <CORBA::Octet> id; + CORBA::OctetSeq id; + + // @@ add "==", "<", ">" operators + + // = Stuff required for memory management. + CORBA::ULong AddRef (void); + CORBA::ULong Release (void); + + CORBA_Principal (void); + +private: + CORBA::ULong refcount_; + + ~CORBA_Principal (void); + + // = these are not provided + CORBA_Principal &operator = (const CORBA::Principal_ptr &); + CORBA_Principal (const CORBA::Principal_ptr &); + +#if defined (__GNUG__) + // G++ (even 2.6.3) stupidly thinks instances can't be created. + // This de-warns. + friend class everyone_needs_a_friend; +#endif /* __GNUG__ */ +}; + +#endif /* TAO_PRINCIPAL_H */ diff --git a/TAO/tao/tao.bld b/TAO/tao/tao.bld index d9f475cfde4..d54ad9f554e 100644 --- a/TAO/tao/tao.bld +++ b/TAO/tao/tao.bld @@ -2,17 +2,17 @@ default: library :defines=DEBUG -any.cpp +Any.cpp C++ -arg_shifter.cpp +Arg_Shifter.cpp C++ -cdr.cpp +CDR.cpp C++ -client_factory.cpp +Client_Strategy_Factory.cpp C++ -connect.cpp +Connect.cpp C++ -corbacom.cpp +CORBA.cpp C++ debug.cpp C++ @@ -28,55 +28,55 @@ default_server.cpp C++ encode.cpp C++ -except.cpp +Exception.cpp C++ -giop.cpp +GIOP.cpp C++ -iiopobj.cpp +IIOP_Object.cpp C++ -iioporb.cpp +IIOP_ORB.cpp C++ interp.cpp C++ -marshal.cpp +Marshal.cpp C++ -nvlist.cpp +NVList.cpp C++ -object.cpp +Object.cpp C++ -objkeyC.cpp +Object_KeyC.cpp C++ -objtable.cpp +Object_Table.cpp C++ -optable.cpp +Operation_Table.cpp C++ -orbobj.cpp +ORB.cpp C++ -orb_core.cpp +ORB_Core.cpp C++ params.cpp C++ -poa.cpp +POA.cpp C++ -poaC.cpp +POAC.cpp C++ -poaS.cpp +POAS.cpp C++ -principa.cpp +Principal.cpp C++ -request.cpp +Request.cpp C++ -sequence.cpp +Sequence.cpp C++ -servant_base.cpp +Servant_Base.cpp C++ server_factory.cpp C++ -svrrqst.cpp +Server_Request.cpp C++ -tao_internals.cpp +Tao_Internal.cpp C++ -tc_const.cpp +Typecode_Constants.cpp C++ -typecode.cpp +Typecode.cpp C++ |