summaryrefslogtreecommitdiff
path: root/trunk/TAO/tao/AnyTypeCode/NVList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/TAO/tao/AnyTypeCode/NVList.cpp')
-rw-r--r--trunk/TAO/tao/AnyTypeCode/NVList.cpp501
1 files changed, 501 insertions, 0 deletions
diff --git a/trunk/TAO/tao/AnyTypeCode/NVList.cpp b/trunk/TAO/tao/AnyTypeCode/NVList.cpp
new file mode 100644
index 00000000000..56528db0c81
--- /dev/null
+++ b/trunk/TAO/tao/AnyTypeCode/NVList.cpp
@@ -0,0 +1,501 @@
+// $Id$
+
+
+// Implementation of Named Value List and NamedValue classes
+
+#include "tao/AnyTypeCode/NVList.h"
+#include "tao/AnyTypeCode/BoundsC.h"
+#include "tao/AnyTypeCode/TypeCode.h"
+#include "tao/AnyTypeCode/Marshal.h"
+#include "tao/AnyTypeCode/Any_Impl.h"
+
+#include "tao/SystemException.h"
+#include "tao/CORBA_String.h"
+#include "tao/CDR.h"
+#include "tao/debug.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+# include "tao/AnyTypeCode/NVList.inl"
+#endif /* ! __ACE_INLINE__ */
+
+ACE_RCSID (AnyTypeCode,
+ NVList,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Reference counting for DII Request object
+
+CORBA::ULong
+CORBA::NamedValue::_incr_refcnt (void)
+{
+ return ++this->refcount_;
+}
+
+CORBA::ULong
+CORBA::NamedValue::_decr_refcnt (void)
+{
+ const CORBA::ULong new_count = --this->refcount_;
+
+ if (new_count == 0)
+ delete this;
+
+ return new_count;
+}
+
+CORBA::NamedValue::~NamedValue (void)
+{
+ if (this->name_)
+ {
+ CORBA::string_free (this->name_);
+ this->name_ = 0;
+ }
+ // the any will be destroyed by itself
+}
+
+// ****************************************************************
+
+CORBA::ULong
+CORBA::NVList::_incr_refcnt (void)
+{
+ return ++this->refcount_;
+}
+
+CORBA::ULong
+CORBA::NVList::_decr_refcnt (void)
+{
+ const CORBA::ULong new_count = --this->refcount_;
+
+ if (new_count == 0)
+ delete this;
+
+ return new_count;
+}
+
+CORBA::NVList::~NVList (void)
+{
+ // initialize an iterator and delete each NamedValue
+ ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> iter (this->values_);
+
+ for (iter.first (); !iter.done (); iter.advance ())
+ {
+ CORBA::NamedValue_ptr *nv = 0;
+ (void) iter.next (nv);
+ delete *nv;
+ }
+
+ this->max_ = 0;
+
+ // Remove the CDR stream if it is present.
+ delete this->incoming_;
+}
+
+// add an element and just initialize its flags
+CORBA::NamedValue_ptr
+CORBA::NVList::add (CORBA::Flags flags
+ ACE_ENV_ARG_DECL)
+{
+ // call the helper to allocate a NamedValue element (if necessary)
+ return this->add_element (flags
+ ACE_ENV_ARG_PARAMETER);
+}
+
+// add an element and just initialize its flags and name
+CORBA::NamedValue_ptr
+CORBA::NVList::add_item (const char *name,
+ CORBA::Flags flags
+ ACE_ENV_ARG_DECL)
+{
+ // call the helper to allocate a NamedValue element
+ CORBA::NamedValue_ptr nv = this->add_element (flags
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (nv)
+ {
+ // now initialize the fields
+ nv->name_ = CORBA::string_dup (name);
+ return nv;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// 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
+ ACE_ENV_ARG_DECL)
+{
+ // Call the helper to allocate a NamedValue element.
+ CORBA::NamedValue_ptr nv = this->add_element (flags
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (nv)
+ {
+ nv->name_ = CORBA::string_dup (name);
+
+ // With the original Any implementation, we had alternate
+ // paths for the assignment based on the IN_COPY_VALUE flag.
+ // Now that the Any's contained Any_Impl is refcounted, the
+ // distinction between the ORB "copying" or "borrowing" the
+ // memory is irrelevant. The IN_COPY_VALUE flag was not
+ // checked anywhere else in the ORB anyway.
+ nv->any_ = value;
+ return nv;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// add an element and just initialize its flags and name
+CORBA::NamedValue_ptr
+CORBA::NVList::add_item_consume (char *name,
+ CORBA::Flags flags
+ ACE_ENV_ARG_DECL)
+{
+
+ // call the helper to allocate a NamedValue element
+ CORBA::NamedValue_ptr nv = this->add_element (flags
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (nv)
+ {
+ // now initialize the fields
+
+ // consume the name
+ nv->name_ = name;
+ return nv;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// add a value. If necessary, increment the list
+CORBA::NamedValue_ptr
+CORBA::NVList::add_value_consume (char * name,
+ CORBA::Any * value,
+ CORBA::Flags flags
+ ACE_ENV_ARG_DECL)
+{
+ // call the helper to allocate a NamedValue element
+ CORBA::NamedValue_ptr nv = this->add_element (flags
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (nv)
+ {
+ // now initialize the fields
+
+ // consume name
+ nv->name_ = name;
+
+ // consume the value @@ (ASG) have we? we may need to destroy
+ // the in parameter
+ nv->any_ = *value;
+ return nv;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+//CORBA::Status
+void
+CORBA::NVList::remove (CORBA::ULong /* n */
+ ACE_ENV_ARG_DECL_NOT_USED)
+{
+ // not implemented
+ // @@ (ASG) - TODO
+}
+
+// Helper method
+CORBA::NamedValue_ptr
+CORBA::NVList::add_element (CORBA::Flags flags
+ ACE_ENV_ARG_DECL)
+{
+ this->evaluate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::NamedValue::_nil ());
+
+ if (ACE_BIT_DISABLED (flags,
+ CORBA::ARG_IN | CORBA::ARG_OUT | CORBA::ARG_INOUT))
+ {
+ ACE_THROW_RETURN (CORBA::BAD_PARAM (),
+ CORBA::NamedValue::_nil ());
+ }
+
+ CORBA::NamedValue_ptr nv;
+
+ // allocate a new NamedValue
+ ACE_NEW_THROW_EX (nv,
+ CORBA::NamedValue,
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (CORBA::NamedValue::_nil ());
+
+ // set the flags and enqueue in the queue
+ nv->flags_ = flags;
+
+ if (this->values_.enqueue_tail (nv) == -1)
+ {
+ delete nv;
+ return 0;
+ }
+
+ this->max_++;
+ return nv; // success
+}
+
+// return the item at location n
+CORBA::NamedValue_ptr
+CORBA::NVList::item (CORBA::ULong n
+ ACE_ENV_ARG_DECL)
+{
+ this->evaluate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::NamedValue::_nil ());
+
+ if (n >= this->max_)
+ {
+ ACE_THROW_RETURN (CORBA::Bounds (),
+ CORBA::NamedValue::_nil ());
+ }
+
+ CORBA::NamedValue_ptr *nv = 0;
+
+ this->values_.get (nv, n);
+ return *nv;
+}
+
+void
+CORBA::NVList::_tao_incoming_cdr (TAO_InputCDR &cdr,
+ int flag,
+ bool &lazy_evaluation
+ ACE_ENV_ARG_DECL)
+{
+ // If the list is empty then using lazy evaluation is the only
+ // choice.
+ // @@ There are other cases where we can use lazy evaluation, for
+ // example if the list is not empty but the anys own all their
+ // objects.
+ if (lazy_evaluation == false && this->max_ == 0)
+ {
+ lazy_evaluation = true;
+ }
+
+ if (lazy_evaluation == false)
+ {
+ this->_tao_decode (cdr,
+ flag
+ ACE_ENV_ARG_PARAMETER);
+ return;
+ }
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock_);
+
+ if (this->incoming_ != 0)
+ {
+ delete this->incoming_;
+ this->incoming_ = 0;
+ }
+
+ ACE_NEW (this->incoming_, TAO_InputCDR (cdr));
+ this->incoming_flag_ = flag;
+}
+
+void
+CORBA::NVList::_tao_encode (TAO_OutputCDR &cdr,
+ int flag
+ ACE_ENV_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX,
+ ace_mon,
+ this->lock_);
+
+ if (this->incoming_ != 0)
+ {
+ if (this->max_ == 0)
+ {
+ // The list is empty aggresively reduce copies and just send
+ // the CDR stream, we assume that
+ // TAO_Server_Request::init_reply
+ // has inserted appropiated padding already to make this
+ // operation correct
+ cdr.write_octet_array_mb (this->incoming_->start ());
+ return;
+ }
+
+ // Then unmarshal each "in" and "inout" parameter.
+ ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
+
+ for (i.first (); !i.done (); i.advance ())
+ {
+ CORBA::NamedValue_ptr *item = 0;
+ (void) i.next (item);
+
+ CORBA::NamedValue_ptr nv = *item;
+
+ if (ACE_BIT_DISABLED (nv->flags (), flag))
+ {
+ continue;
+ }
+
+ if (TAO_debug_level > 3)
+ {
+ const char* arg = nv->name ();
+
+ if (arg == 0)
+ {
+ arg = "(nil)";
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("NVList::_tao_encode - parameter <%s>\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (arg)));
+ }
+ CORBA::TypeCode_ptr tc = nv->value ()->_tao_get_typecode ();
+ (void) TAO_Marshal_Object::perform_append (tc,
+ this->incoming_,
+ &cdr
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ delete this->incoming_;
+ this->incoming_ = 0;
+ return;
+ }
+
+ // The list is already evaluated, we cannot optimize the copies, go
+ // ahead with the slow way to do things.
+
+ // Then marshal each "in" and "inout" parameter.
+ ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
+
+ for (i.first (); !i.done (); i.advance ())
+ {
+ CORBA::NamedValue_ptr *item = 0;
+ (void) i.next (item);
+
+ CORBA::NamedValue_ptr nv = *item;
+
+ if (ACE_BIT_DISABLED (nv->flags (), flag))
+ {
+ continue;
+ }
+
+ nv->value ()->impl ()->marshal_value (cdr);
+ }
+}
+
+void
+CORBA::NVList::_tao_decode (TAO_InputCDR &incoming,
+ int flag
+ ACE_ENV_ARG_DECL)
+{
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) : NVList::_tao_decode\n")));
+ }
+
+ // Then unmarshal each "in" and "inout" parameter.
+ ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
+
+ for (i.first (); !i.done (); i.advance ())
+ {
+ CORBA::NamedValue_ptr *item = 0;
+ (void) i.next (item);
+
+ CORBA::NamedValue_ptr nv = *item;
+
+ // check if it is an in or inout parameter
+ // @@ this is where we assume that the NVList is coming from
+ // a Server-side request, we could probably handle both
+ // cases with a flag, but there is no clear need for that.
+ if (ACE_BIT_DISABLED (nv->flags (), flag))
+ {
+ continue;
+ }
+
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) : NVList::_tao_decode - %s\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (nv->name ()? nv->name () : "(no name given)" )));
+ }
+
+ CORBA::Any_ptr any = nv->value ();
+ any->impl ()->_tao_decode (incoming
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+}
+
+ptrdiff_t
+CORBA::NVList::_tao_target_alignment (void)
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ ace_mon,
+ this->lock_,
+ ACE_CDR::MAX_ALIGNMENT);
+
+ if (this->incoming_ == 0)
+ {
+ return ACE_CDR::MAX_ALIGNMENT;
+ }
+
+ const char* rd = this->incoming_->start ()->rd_ptr ();
+ ptrdiff_t t = ptrdiff_t (rd) % ACE_CDR::MAX_ALIGNMENT;
+
+ if (t < 0)
+ {
+ t += ACE_CDR::MAX_ALIGNMENT;
+ }
+
+ return t;
+}
+
+void
+CORBA::NVList::evaluate (ACE_ENV_SINGLE_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock_);
+
+ if (this->incoming_ == 0)
+ {
+ return;
+ }
+
+ auto_ptr<TAO_InputCDR> incoming (this->incoming_);
+ this->incoming_ = 0;
+
+ this->_tao_decode (*(incoming.get ()),
+ this->incoming_flag_
+ ACE_ENV_ARG_PARAMETER);
+}
+
+CORBA::Boolean
+CORBA::NVList::_lazy_has_arguments (void) const
+{
+ if (this->incoming_ != 0)
+ {
+ return this->incoming_->length () <= 1 ? false : true;
+ }
+ else
+ {
+ return this->count () <= 1 ? false : true;
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL