summaryrefslogtreecommitdiff
path: root/TAO/tao/CDR_Encaps_Codec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/CDR_Encaps_Codec.cpp')
-rw-r--r--TAO/tao/CDR_Encaps_Codec.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/TAO/tao/CDR_Encaps_Codec.cpp b/TAO/tao/CDR_Encaps_Codec.cpp
new file mode 100644
index 00000000000..211a9cb1d7c
--- /dev/null
+++ b/TAO/tao/CDR_Encaps_Codec.cpp
@@ -0,0 +1,292 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "CDR.h"
+#include "OctetSeqC.h"
+#include "Any.h"
+#include "Typecode.h"
+#include "Marshal.h"
+
+#include "CDR_Encaps_Codec.h"
+
+ACE_RCSID (TAO_CodecFactory,
+ CDR_Encaps_Codec,
+ "$Id$")
+
+
+TAO_CDR_Encaps_Codec::TAO_CDR_Encaps_Codec (CORBA::Octet major,
+ CORBA::Octet minor)
+ : major_ (major),
+ minor_ (minor)
+{
+}
+
+TAO_CDR_Encaps_Codec::~TAO_CDR_Encaps_Codec (void)
+{
+}
+
+CORBA::OctetSeq *
+TAO_CDR_Encaps_Codec::encode (const CORBA::Any & data,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ IOP::Codec::InvalidTypeForEncoding))
+{
+ this->check_type_for_encoding (data,
+ ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0);
+
+ // ----------------------------------------------------------------
+
+ TAO_OutputCDR cdr;
+ if ((cdr << TAO_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER))
+ && (cdr << data))
+ {
+ CORBA::OctetSeq * octet_seq = 0;
+
+ ACE_NEW_THROW_EX (octet_seq,
+ CORBA::OctetSeq,
+ CORBA::NO_MEMORY (
+ CORBA_SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ CORBA::OctetSeq_var safe_octet_seq = octet_seq;
+
+ octet_seq->length (cdr.total_length ());
+ CORBA::Octet *buf = octet_seq->get_buffer ();
+
+ for (const ACE_Message_Block *i = cdr.begin ();
+ i != 0;
+ i = i->cont ())
+ {
+ size_t len = i->length ();
+ ACE_OS_String::memcpy (buf, i->rd_ptr (), len);
+ buf += len;
+ }
+
+ return safe_octet_seq._retn ();
+ }
+
+ ACE_THROW_RETURN (CORBA::MARSHAL (), 0);
+}
+
+CORBA::Any *
+TAO_CDR_Encaps_Codec::decode (const CORBA::OctetSeq & data,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ IOP::Codec::FormatMismatch))
+{
+ // @todo How do we check for a format mismatch so that we can throw
+ // a IOP::Codec::FormatMismatch exception?
+ // @todo Is this the best way to extract the Any from the OctetSeq?
+
+ // Notice that we need to extract the TypeCode and the value from
+ // the octet sequence, and place them into the Any. We can't just
+ // insert the octet sequence into the Any.
+
+ TAO_InputCDR cdr (ACE_reinterpret_cast (const char*,
+ data.get_buffer ()),
+ data.length ());
+
+ CORBA::Boolean byte_order;
+ if (cdr >> TAO_InputCDR::to_boolean (byte_order))
+ {
+ cdr.reset_byte_order (ACE_static_cast (int, byte_order));
+
+ CORBA::Any * any = 0;
+ ACE_NEW_THROW_EX (any,
+ CORBA::Any,
+ CORBA::NO_MEMORY (
+ CORBA_SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ CORBA::Any_var safe_any = any;
+
+ if (cdr >> (*any))
+ return safe_any._retn ();
+ }
+
+ ACE_THROW_RETURN (IOP::Codec::FormatMismatch (), 0);
+}
+
+CORBA::OctetSeq *
+TAO_CDR_Encaps_Codec::encode_value (const CORBA::Any & data,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ IOP::Codec::InvalidTypeForEncoding))
+{
+ this->check_type_for_encoding (data,
+ ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0);
+
+ // ----------------------------------------------------------------
+ TAO_OutputCDR cdr;
+
+ if ((cdr << TAO_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)))
+ {
+ CORBA::TypeCode_var tc = data.type ();
+
+ TAO_InputCDR input (data._tao_get_cdr (),
+ data._tao_byte_order ());
+
+ TAO_Marshal_Object::perform_append (tc.in (),
+ &input,
+ &cdr,
+ ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0);
+
+ // TAO extension: replace the contents of the octet sequence with
+ // the CDR stream.
+ CORBA::OctetSeq * octet_seq = 0;
+
+ ACE_NEW_THROW_EX (octet_seq,
+ CORBA::OctetSeq,
+ CORBA::NO_MEMORY (
+ CORBA_SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ CORBA::OctetSeq_var safe_octet_seq = octet_seq;
+
+ octet_seq->length (cdr.total_length ());
+ CORBA::Octet *buf = octet_seq->get_buffer ();
+
+ for (const ACE_Message_Block *i = cdr.begin ();
+ i != 0;
+ i = i->cont ())
+ {
+ size_t len = i->length ();
+ ACE_OS_String::memcpy (buf, i->rd_ptr (), len);
+ buf += len;
+ }
+
+ return safe_octet_seq._retn ();
+ }
+
+ ACE_THROW_RETURN (CORBA::MARSHAL (), 0);
+}
+
+CORBA::Any *
+TAO_CDR_Encaps_Codec::decode_value (const CORBA::OctetSeq & data,
+ CORBA::TypeCode_ptr tc,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ IOP::Codec::FormatMismatch,
+ IOP::Codec::TypeMismatch))
+{
+ // @todo How do we check for a type mismatch so that we can
+ // throw a IOP::Codec::TypeMismatch exception?
+ // @@ I added a check below. See the comment. I'm not sure
+ // if it is a valid check.
+ // -Ossama
+
+ // @todo Most of this code was copied from
+ // operator>> (TAO_InputCDR &cdr, CORBA::Any &x)
+ // in Any.cpp. Rather than copy the code, the code should be
+ // refactored to make it possible to use the given TypeCode
+ // rather than attempt to extract it from the CDR
+ // encapsulation.
+
+ CORBA::ULong sequence_length = data.length ();
+ TAO_InputCDR cdr (ACE_reinterpret_cast (const char*,
+ data.get_buffer ()),
+ sequence_length);
+
+ CORBA::Boolean byte_order;
+ if (cdr >> TAO_InputCDR::to_boolean (byte_order))
+ {
+ cdr.reset_byte_order (ACE_static_cast (int, byte_order));
+
+ // @@ (JP) The following code depends on the fact that
+ // TAO_InputCDR does not contain chained message blocks,
+ // otherwise <begin> and <end> could be part of
+ // different buffers!
+
+ // This will be the start of a new message block.
+ char *begin = cdr.rd_ptr ();
+
+ // Skip over the next argument.
+ CORBA::TypeCode::traverse_status status =
+ TAO_Marshal_Object::perform_skip (tc, &cdr, ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0); // @@ Should we throw a
+ // IOP::Codec::TypeMismatch exception
+ // here if this fails?
+
+ if (status == CORBA::TypeCode::TRAVERSE_CONTINUE)
+ {
+ // This will be the end of the new message block.
+ char *end = cdr.rd_ptr ();
+
+ size_t size = end - begin;
+
+ // @@ I added the following check, but I'm not sure if it is
+ // a valid check. Can someone verify this?
+ // -Ossama
+
+ // If the unaligned buffer size is not equal to the octet
+ // sequence length (minus the "byte order byte") then the
+ // TypeCode does not correspond to the data in the CDR
+ // encapsulation. However, even if they do match it is
+ // still uncertain if the TypeCode corresponds to the data
+ // in the octet sequence. With this test, it is only
+ // possible to determine if the TypeCode does *not* match
+ // the data, not if it does match.
+ if (size != sequence_length - 1)
+ ACE_THROW_RETURN (IOP::Codec::TypeMismatch (), 0);
+
+ ACE_Message_Block mb (size + ACE_CDR::MAX_ALIGNMENT);
+ ACE_CDR::mb_align (&mb);
+ ptr_arith_t offset =
+ ptr_arith_t (begin) % ACE_CDR::MAX_ALIGNMENT;
+ mb.rd_ptr (offset);
+ mb.wr_ptr (offset + size);
+
+ ACE_OS::memcpy (mb.rd_ptr (), begin, size);
+
+ CORBA::Any * any = 0;
+ ACE_NEW_THROW_EX (any,
+ CORBA::Any,
+ CORBA::NO_MEMORY (
+ CORBA_SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ CORBA::Any_var safe_any = any;
+
+ // Stick it into the Any. It gets duplicated there.
+ any->_tao_replace (tc,
+ cdr.byte_order (),
+ &mb);
+
+ return safe_any._retn ();
+ }
+ else
+ ACE_THROW_RETURN (IOP::Codec::TypeMismatch (), 0);
+ }
+
+ ACE_THROW_RETURN (IOP::Codec::FormatMismatch (), 0);
+}
+
+void
+TAO_CDR_Encaps_Codec::check_type_for_encoding (
+ const CORBA::Any & data,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // @@ TODO: Are there any other conditions we need to check?
+
+ CORBA::TypeCode_var typecode = data.type ();
+ if (this->major_ == 1
+ && this->minor_ == 0
+ && typecode->equivalent (CORBA::_tc_wstring))
+ ACE_THROW (IOP::Codec::InvalidTypeForEncoding ());
+}