diff options
Diffstat (limited to 'TAO/tao/Sequence.cpp')
-rw-r--r-- | TAO/tao/Sequence.cpp | 1116 |
1 files changed, 1116 insertions, 0 deletions
diff --git a/TAO/tao/Sequence.cpp b/TAO/tao/Sequence.cpp new file mode 100644 index 00000000000..f39bd28f6ba --- /dev/null +++ b/TAO/tao/Sequence.cpp @@ -0,0 +1,1116 @@ +// $Id$ + +#include "tao/Sequence.h" + +#if !defined (__ACE_INLINE__) +#include "tao/Sequence.i" +#endif /* __ACE_INLINE__ */ + +#include "tao/SystemException.h" + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) +# include "ace/Message_Block.h" +#endif /* (TAO_NO_COPY_OCTET_SEQUENCES == 1) */ + +#include "ace/Log_Msg.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_stdlib.h" +#include "ace/OS_Memory.h" + + +ACE_RCSID (tao, + Sequence, + "$Id$") + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +// ************************************************************* +// Operations for class TAO_Base_Sequence +// ************************************************************* + +TAO_Base_Sequence::~TAO_Base_Sequence (void) +{ +} + +void TAO_Base_Sequence::_shrink_buffer (CORBA::ULong, CORBA::ULong) +{ + + // default is no op. +} + +void +TAO_Base_Sequence::_downcast (void *, + CORBA::Object * + ACE_ENV_ARG_DECL_NOT_USED) +{ + // default is no op. + // @@ TODO Maybe throw an exception? +} + +CORBA::Object * +TAO_Base_Sequence::_upcast (void *) const +{ + return 0; +} + +void +TAO_Base_Sequence::check_bounds (char const * filename, + unsigned long lineno, + CORBA::ULong tao_idx, + CORBA::ULong tao_max) const +{ + // TODO use hook + if (tao_idx >= tao_max) + { + ACE_ERROR ((LM_ERROR, + "Access error in TAO_Base_Sequence file=%s, line=%u, " + "idx=%u, max=%u\n", + ACE_TEXT_TO_TCHAR_IN (filename), + lineno, + tao_idx, + tao_max)); + + // @todo When we have a hook setup, we can totally ignore this or + // even remove this. +#if defined (ACE_HAS_EXCEPTIONS) + ACE_THROW (CORBA::BAD_PARAM ()); +#else + ACE_OS::abort (); +#endif /* ACE_HAS_EXCEPTIONS */ + } +} + +// ************************************************************* +// Operations for class TAO_Unbounded_Base_Sequence +// ************************************************************* + +TAO_Unbounded_Base_Sequence::~TAO_Unbounded_Base_Sequence (void) +{ +} + +// ************************************************************* +// Operations for class TAO_Bounded_Base_Sequence +// ************************************************************* + +TAO_Bounded_Base_Sequence::~TAO_Bounded_Base_Sequence (void) +{ +} + +// ************************************************************* + +// constructor for unbounded string seq +TAO_Unbounded_String_Sequence::TAO_Unbounded_String_Sequence ( + CORBA::ULong maximum + ) + : TAO_Unbounded_Base_Sequence ( + maximum, + TAO_Unbounded_String_Sequence::allocbuf (maximum) + ) +{ +} + +TAO_Unbounded_String_Sequence::TAO_Unbounded_String_Sequence ( + const TAO_Unbounded_String_Sequence & rhs + ) + : TAO_Unbounded_Base_Sequence (rhs) +{ + if (rhs.buffer_ != 0) + { + char* *tmp1 = + TAO_Unbounded_String_Sequence::allocbuf (this->maximum_); + + char ** const tmp2 = + reinterpret_cast<char ** ACE_CAST_CONST> (rhs.buffer_); + + for (CORBA::ULong i = 0; i < rhs.length_; ++i) + { + tmp1[i] = CORBA::string_dup (tmp2[i]); + } + + this->buffer_ = tmp1; + } + else + { + this->buffer_ = 0; + } +} + +TAO_Unbounded_String_Sequence::~TAO_Unbounded_String_Sequence (void) +{ + this->_deallocate_buffer (); +} + +TAO_Unbounded_String_Sequence & +TAO_Unbounded_String_Sequence::operator= ( + const TAO_Unbounded_String_Sequence & rhs + ) +{ + if (this == &rhs) + { + return *this; + } + + if (this->release_) + { + char ** tmp = reinterpret_cast<char **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::string_free (tmp[i]); + tmp[i] = 0; + } + + if (this->maximum_ < rhs.maximum_) + { + // Free the older buffer. + TAO_Unbounded_String_Sequence::freebuf (tmp); + this->buffer_ = + TAO_Unbounded_String_Sequence::allocbuf (rhs.maximum_); + } + } + else + { + if (rhs.maximum_ == 0) + { + this->buffer_ = 0; + } + else + { + this->buffer_ = + TAO_Unbounded_String_Sequence::allocbuf (rhs.maximum_); + } + } + + TAO_Unbounded_Base_Sequence::operator= (rhs); + + char ** tmp1 = reinterpret_cast <char **> (this->buffer_); + char ** const tmp2 = reinterpret_cast<char ** ACE_CAST_CONST> (rhs.buffer_); + + for (CORBA::ULong i = 0; i < rhs.length_; ++i) + { + tmp1[i] = CORBA::string_dup (tmp2[i]); + } + + return *this; +} + +TAO_SeqElem_String_Manager +TAO_Unbounded_String_Sequence::operator[] (CORBA::ULong slot) const +{ + TAO_SEQUENCE_ASSERT (slot, this->maximum_); + char ** const tmp = + reinterpret_cast<char ** ACE_CAST_CONST> (this->buffer_); + return TAO_SeqElem_String_Manager (tmp + slot, + this->release_); +} + +char ** +TAO_Unbounded_String_Sequence::allocbuf (CORBA::ULong nelems) +{ + char ** buf = 0; + ACE_NEW_RETURN (buf, + char * [nelems], + 0); + + for (CORBA::ULong i = 0; i < nelems; ++i) + { + buf[i] = 0; + } + + return buf; +} + +void +TAO_Unbounded_String_Sequence::freebuf (char ** buffer) +{ + if (buffer == 0) + { + return; + } + + // {orbos/97-05-15:16.11} + // The freebuf function ensures that the destructor for each element + // is called before the buffer is destroyed, except for string + // elements, which are freed using string_free(), and object + // reference elements, which are freed using release(). The freebuf + // function will ignore null pointers passed to it. + + // @@ How are we supposed to implement that! We don't know the + // length of the buffer here. + // Mark the length in the first four bytes? For the moment we let + // that be. + + delete [] buffer; +} + +void +TAO_Unbounded_String_Sequence::_tao_any_destructor ( + void * _tao_void_pointer + ) +{ + TAO_Unbounded_String_Sequence * tmp = + static_cast <TAO_Unbounded_String_Sequence *> (_tao_void_pointer); + delete tmp; +} + +char ** +TAO_Unbounded_String_Sequence::get_buffer (CORBA::Boolean orphan) +{ + char ** result = 0; + + if (orphan == 0) + { + // We retain ownership. + if (this->buffer_ == 0) + { + result = allocbuf (this->length_); + this->buffer_ = result; + this->release_ = 1; + } + else + { + result = reinterpret_cast <char **> (this->buffer_); + } + } + else // if (orphan == 1) + { + if (this->release_ != 0) + { + // We set the state back to default and relinquish + // ownership. + result = reinterpret_cast <char **> (this->buffer_); + this->maximum_ = 0; + this->length_ = 0; + this->buffer_ = 0; + this->release_ = 0; + } + } + + return result; +} + +const char ** +TAO_Unbounded_String_Sequence::get_buffer (void) const +{ + return reinterpret_cast<const char ** ACE_CAST_CONST> (this->buffer_); +} + +void +TAO_Unbounded_String_Sequence::_allocate_buffer (CORBA::ULong length) +{ + char ** tmp = TAO_Unbounded_String_Sequence::allocbuf (length); + + if (this->buffer_ != 0) + { + char ** old = reinterpret_cast <char **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + // Only call duplicate when we did not own the previous + // buffer, since after this method we own it we must also + // own the objects. If we already own the objects there is + // no need to copy them, if we did we would also have to + // remove the old instances. + if (!this->release_) + { + tmp [i] = CORBA::string_dup (old[i]); + } + else + { + tmp [i] = old[i]; + } + } + + if (this->release_) + { + delete [] old; + } + } + + this->buffer_ = tmp; +} + +void +TAO_Unbounded_String_Sequence::_deallocate_buffer (void) +{ + if (this->buffer_ == 0 || this->release_ == 0) + { + return; + } + + char ** tmp = reinterpret_cast <char **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::string_free (tmp[i]); + tmp[i] = 0; + } + + TAO_Unbounded_String_Sequence::freebuf (tmp); + this->buffer_ = 0; + this->length_ = 0; + this->release_ = 0; + this->maximum_ = 0; +} + +void +TAO_Unbounded_String_Sequence::_shrink_buffer (CORBA::ULong nl, + CORBA::ULong ol) +{ + char ** tmp = reinterpret_cast <char **> (this->buffer_); + + for (CORBA::ULong i = nl; i < ol; ++i) + { + CORBA::string_free (tmp[i]); + tmp[i] = 0; + } +} + +void +TAO_Unbounded_String_Sequence::replace (CORBA::ULong maximum, + CORBA::ULong length, + char ** data, + CORBA::Boolean release) +{ + if (this->release_ == 1) + { + char ** tmp = reinterpret_cast <char **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::string_free (tmp[i]); + tmp[i] = 0; + } + } + + this->maximum_ = maximum; + this->length_ = length; + + // If 'release' is 1, it is the caller's responsibility to allocate + // 'data' with CORBA::string_alloc. + this->buffer_ = data; + this->release_ = release; +} +// ************************************************************* + +// constructor for unbounded wide string seq +TAO_Unbounded_WString_Sequence::TAO_Unbounded_WString_Sequence ( + CORBA::ULong maximum + ) + : TAO_Unbounded_Base_Sequence ( + maximum, + TAO_Unbounded_WString_Sequence::allocbuf (maximum) + ) +{ +} + +TAO_Unbounded_WString_Sequence::TAO_Unbounded_WString_Sequence ( + const TAO_Unbounded_WString_Sequence & rhs + ) + : TAO_Unbounded_Base_Sequence (rhs) +{ + if (rhs.buffer_ != 0) + { + CORBA::WChar ** tmp1 = + TAO_Unbounded_WString_Sequence::allocbuf (this->maximum_); + + CORBA::WChar ** const tmp2 = + reinterpret_cast<CORBA::WChar ** ACE_CAST_CONST> (rhs.buffer_); + + for (CORBA::ULong i = 0; i < rhs.length_; ++i) + { + tmp1[i] = CORBA::wstring_dup (tmp2[i]); + } + + this->buffer_ = tmp1; + } + else + { + this->buffer_ = 0; + } +} + +TAO_Unbounded_WString_Sequence::~TAO_Unbounded_WString_Sequence (void) +{ + this->_deallocate_buffer (); +} + +TAO_Unbounded_WString_Sequence & +TAO_Unbounded_WString_Sequence::operator= ( + const TAO_Unbounded_WString_Sequence & rhs + ) +{ + if (this == &rhs) + { + return *this; + } + + if (this->release_) + { + CORBA::WChar ** tmp = reinterpret_cast <CORBA::WChar **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::wstring_free (tmp[i]); + tmp[i] = 0; + } + + if (this->maximum_ < rhs.maximum_) + { + // free the older buffer + TAO_Unbounded_WString_Sequence::freebuf (tmp); + this->buffer_ = + TAO_Unbounded_WString_Sequence::allocbuf (rhs.maximum_); + } + } + else + { + if (rhs.maximum_ == 0) + { + this->buffer_ = 0; + } + else + { + this->buffer_ = + TAO_Unbounded_WString_Sequence::allocbuf (rhs.maximum_); + } + } + + TAO_Unbounded_Base_Sequence::operator= (rhs); + + CORBA::WChar ** tmp1 = reinterpret_cast <CORBA::WChar **> (this->buffer_); + CORBA::WChar ** const tmp2 = + reinterpret_cast<CORBA::WChar ** ACE_CAST_CONST> (rhs.buffer_); + + for (CORBA::ULong i=0; i < rhs.length_; ++i) + { + tmp1[i] = CORBA::wstring_dup (tmp2[i]); + } + + return *this; +} + +TAO_SeqElem_WString_Manager +TAO_Unbounded_WString_Sequence::operator[] (CORBA::ULong slot) const +{ + TAO_SEQUENCE_ASSERT (slot, this->maximum_); + CORBA::WChar ** const tmp = + reinterpret_cast<CORBA::WChar ** ACE_CAST_CONST> (this->buffer_); + return TAO_SeqElem_WString_Manager (tmp + slot, + this->release_); +} + +CORBA::WChar ** +TAO_Unbounded_WString_Sequence::allocbuf (CORBA::ULong nelems) +{ + CORBA::WChar ** buf = 0; + ACE_NEW_RETURN (buf, + CORBA::WChar * [nelems], + 0); + + for (CORBA::ULong i = 0; i < nelems; ++i) + { + buf[i] = 0; + } + + return buf; +} + +void +TAO_Unbounded_WString_Sequence::freebuf (CORBA::WChar ** buffer) +{ + if (buffer == 0) + { + return; + } + + // {orbos/97-05-15:16.11} + // The freebuf function ensures that the destructor for each element + // is called before the buffer is destroyed, except for string + // elements, which are freed using wstring_free(), and object + // reference elements, which are freed using release(). The freebuf + // function will ignore null pointers passed to it. + + // @@ How are we supposed to implement that! We don't know the + // length of the buffer here. + // Mark the length in the first four bytes? For the moment we let + // that be. + + delete [] buffer; +} + +void +TAO_Unbounded_WString_Sequence::_tao_any_destructor ( + void * _tao_void_pointer + ) +{ + TAO_Unbounded_WString_Sequence * tmp = + static_cast<TAO_Unbounded_WString_Sequence *> (_tao_void_pointer); + delete tmp; +} + +CORBA::WChar ** +TAO_Unbounded_WString_Sequence::get_buffer (CORBA::Boolean orphan) +{ + CORBA::WChar ** result = 0; + + if (orphan == 0) + { + // We retain ownership. + if (this->buffer_ == 0) + { + result = allocbuf (this->length_); + this->buffer_ = result; + this->release_ = 1; + } + else + { + result = reinterpret_cast<CORBA::WChar **> (this->buffer_); + } + } + else // if (orphan == 1) + { + if (this->release_ != 0) + { + // We set the state back to default and relinquish + // ownership. + result = reinterpret_cast<CORBA::WChar **> (this->buffer_); + this->maximum_ = 0; + this->length_ = 0; + this->buffer_ = 0; + this->release_ = 0; + } + } + + return result; +} + +const CORBA::WChar ** +TAO_Unbounded_WString_Sequence::get_buffer (void) const +{ + return reinterpret_cast<const CORBA::WChar ** ACE_CAST_CONST> (this->buffer_); +} + +void +TAO_Unbounded_WString_Sequence::_allocate_buffer (CORBA::ULong length) +{ + CORBA::WChar ** tmp = TAO_Unbounded_WString_Sequence::allocbuf (length); + + if (this->buffer_ != 0) + { + CORBA::WChar ** old = reinterpret_cast<CORBA::WChar **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + // Only call duplicate when we did not own the previous + // buffer, since after this method we own it we must also + // own the objects. If we already own the objects there is + // no need to copy them, if we did we would also have to + // remove the old instances. + if (!this->release_) + { + tmp [i] = CORBA::wstring_dup (old[i]); + } + else + { + tmp [i] = old[i]; + } + } + + if (this->release_) + { + delete [] old; + } + } + + this->buffer_ = tmp; +} + +void +TAO_Unbounded_WString_Sequence::_deallocate_buffer (void) +{ + if (this->buffer_ == 0 || this->release_ == 0) + { + return; + } + + CORBA::WChar **tmp = reinterpret_cast<CORBA::WChar **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::wstring_free (tmp[i]); + tmp[i] = 0; + } + + TAO_Unbounded_WString_Sequence::freebuf (tmp); + this->buffer_ = 0; + this->length_ = 0; + this->release_ = 0; + this->maximum_ = 0; +} + +void +TAO_Unbounded_WString_Sequence::_shrink_buffer (CORBA::ULong nl, + CORBA::ULong ol) +{ + CORBA::WChar ** tmp = reinterpret_cast<CORBA::WChar **> (this->buffer_); + for (CORBA::ULong i = nl; i < ol; ++i) + { + CORBA::wstring_free (tmp[i]); + tmp[i] = 0; + } +} + +void +TAO_Unbounded_WString_Sequence::replace (CORBA::ULong maximum, + CORBA::ULong length, + CORBA::WChar* *data, + CORBA::Boolean release) +{ + if (this->release_ == 1) + { + CORBA::WChar **tmp = reinterpret_cast<CORBA::WChar **> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + CORBA::wstring_free (tmp[i]); + tmp[i] = 0; + } + } + + this->maximum_ = maximum; + this->length_ = length; + + // If 'release' is 1, it is the caller's responsibility to allocate + // 'data' with CORBA::wstring_alloc. + this->buffer_ = data; + this->release_ = release; +} + +// **************************************************************** + +TAO_Unbounded_Sequence<CORBA::Octet>::TAO_Unbounded_Sequence ( + const TAO_Unbounded_Sequence<CORBA::Octet> &rhs + ) + : TAO_Unbounded_Base_Sequence (rhs) +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + , mb_ (0) +#endif /* (TAO_NO_COPY_OCTET_SEQUENCES == 0) */ +{ + if (rhs.buffer_ != 0) + { + CORBA::Octet * tmp1 = + TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->maximum_); + + + CORBA::Octet * const tmp2 = + reinterpret_cast<CORBA::Octet * ACE_CAST_CONST> (rhs.buffer_); + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + if (rhs.mb_ == 0) + { + ACE_OS::memcpy (tmp1, + tmp2, + this->length_); + } + else + { + size_t offset = 0; + + for (const ACE_Message_Block *i = rhs.mb_; i != 0; i = i->cont ()) + { + ACE_OS::memcpy (tmp1 + offset, + i->rd_ptr (), + i->length ()); + + offset += i->length (); + } + } +#else /* (TAO_NO_COPY_OCTET_SEQUENCES == 0) */ + ACE_OS::memcpy (tmp1, tmp2, this->length_); +#endif /* (TAO_NO_COPY_OCTET_SEQUENCES == 1) */ + + this->buffer_ = tmp1; + } + else + { + this->buffer_ = 0; + } +} + +TAO_Unbounded_Sequence<CORBA::Octet> & +TAO_Unbounded_Sequence<CORBA::Octet>::operator= ( + const TAO_Unbounded_Sequence<CORBA::Octet> & rhs + ) +{ + if (this == &rhs) + { + return *this; + } + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + if (this->mb_ != 0) + { + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; + this->buffer_ = + TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.length_); + } + else +#endif /* (TAO_NO_COPY_OCTET_SEQUENCES == 0) */ + if (this->release_) + { + if (this->maximum_ < rhs.length_) + { + // free the old buffer + CORBA::Octet * tmp = reinterpret_cast<CORBA::Octet *> (this->buffer_); + TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp); + this->buffer_ = + TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.length_); + } + } + else + { + if (rhs.maximum_ == 0) + { + this->buffer_ = 0; + } + else + { + this->buffer_ = + TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.maximum_); + } + } + + TAO_Unbounded_Base_Sequence::operator= (rhs); + + CORBA::Octet * tmp1 = reinterpret_cast<CORBA::Octet *> (this->buffer_); + CORBA::Octet * const tmp2 = + reinterpret_cast<CORBA::Octet * ACE_CAST_CONST> (rhs.buffer_); + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + // for (CORBA::ULong i = 0; i < this->length_; ++i) + // tmp1[i] = tmp2[i]; + if (rhs.mb_ == 0) + { + ACE_OS::memcpy (tmp1, + tmp2, + this->length_); + } + else + { + size_t offset = 0; + + for (const ACE_Message_Block *i = rhs.mb_; i != 0; i = i->cont ()) + { + ACE_OS::memcpy (tmp1 + offset, + i->rd_ptr (), + i->length ()); + offset += i->length (); + } + } +#else /* (TAO_NO_COPY_OCTET_SEQUENCES == 0) */ + ACE_OS::memcpy (tmp1, tmp2, this->length_); +#endif /* (TAO_NO_COPY_OCTET_SEQUENCES == 0) */ + + return *this; +} + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) +TAO_Unbounded_Sequence<CORBA::Octet>::TAO_Unbounded_Sequence ( + CORBA::ULong length, + const ACE_Message_Block * mb + ) + : TAO_Unbounded_Base_Sequence (length, + length, + mb->rd_ptr (), + 0), + mb_ (0) +{ + // Get the message block flags. + ACE_Message_Block::Message_Flags flg = mb->self_flags (); + + // If the DONT_DELETE flag is disabled just a duplicate would + // help. If the DONT_DELETE flag is enabled a deep copy is needed as + // the contents would be on stack. Just incrementing the ref count + // on the stack based data block would only crash the program when + // the stack unwinds + if (ACE_BIT_DISABLED (flg, + ACE_Message_Block::DONT_DELETE)) + { + this->mb_ = ACE_Message_Block::duplicate (mb); + } + else + { + // As we are in CORBA mode, all the data blocks would be aligned + // on an 8 byte boundary + ACE_Message_Block msgb (*mb, + ACE_CDR::MAX_ALIGNMENT); + + // Get the base pointer of the incoming message block + char *start = ACE_ptr_align_binary (mb->base (), + ACE_CDR::MAX_ALIGNMENT); + + // Get the read and write displacements in the incoming stream + size_t rd_pos = mb->rd_ptr () - start; + size_t wr_pos = mb->wr_ptr () - start; + + this->mb_ = ACE_Message_Block::duplicate (&msgb); + + this->mb_->rd_ptr (rd_pos); + this->mb_->wr_ptr (wr_pos); + } +} +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + +TAO_Unbounded_Sequence<CORBA::Octet>::~TAO_Unbounded_Sequence (void) +{ + this->_deallocate_buffer (); +} + +// This function is a little too big to be inlined, but some compilers +// (Sun/CC 4.1?) die if it isn't :-( +CORBA::Octet * +TAO_Unbounded_Sequence<CORBA::Octet>::get_buffer (CORBA::Boolean orphan) +{ + CORBA::Octet * result = 0; + + if (orphan == 0) + { + // We retain ownership. + + if (this->buffer_ == 0) + { + // The buffer was not allocated, we must allocate it now. + result = + TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->length_); + this->buffer_ = result; + this->release_ = 1; + } + else + { + result = + reinterpret_cast<CORBA::Octet*> (this->buffer_); + } + } +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + else if (this->mb_ != 0) // (orphan == 1) + { + // We must create a copy anyway: + // the user is supposed to call freebuf() to release the + // buffer, but the buffer is inside a Message_Block... + // We thought about storing the pointer to the Message_Block + // somewhere at the beginning of the buffer (before the actual + // data), but that will not work in 64 bit machines when the + // buffer comes from a CDR stream. + // + result = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->length_); + ACE_OS::memcpy (result, this->buffer_, this->length_); + } + else if (this->release_ != 0) + { + // We set the state back to default and relinquish + // ownership. + result = reinterpret_cast<CORBA::Octet *> (this->buffer_); + this->maximum_ = 0; + this->length_ = 0; + this->buffer_ = 0; + this->release_ = 0; + } +#else /* TAO_NO_COPY_OCTET_SEQUENCES == 0 */ + else + { + result = reinterpret_cast<CORBA::Octet*> (this->buffer_); + + if (this->release_ != 0) + { + // We set the state back to default and relinquish + // ownership. + this->maximum_ = 0; + this->length_ = 0; + this->buffer_ = 0; + this->release_ = 0; + } + } +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 0 */ + /* else + // Oops, it's not our buffer to relinquish... + return 0; + */ + return result; +} + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) +void +TAO_Unbounded_Sequence<CORBA::Octet>::replace (CORBA::ULong length, + const ACE_Message_Block * mb) +{ + this->_deallocate_buffer (); + + // Get the message block flags. + ACE_Message_Block::Message_Flags flg = mb->self_flags (); + + // If the DONT_DELETE flag is disabled just a duplicate would + // help. If the DONT_DELETE flag is enabled a deep copy is needed as + // the contents would be on stack. Just incrementing the ref count + // on the stack based data block would only crash the program when + // the stack unwinds + if (ACE_BIT_DISABLED (flg, + ACE_Message_Block::DONT_DELETE)) + { + this->mb_ = ACE_Message_Block::duplicate (mb); + } + else + { + // As we are in CORBA mode, all the data blocks would be aligned + // on an 8 byte boundary + ACE_Message_Block msgb (*mb, + ACE_CDR::MAX_ALIGNMENT); + + // Get the base pointer of the incoming message block + char * start = ACE_ptr_align_binary (mb->base (), + ACE_CDR::MAX_ALIGNMENT); + + // Get the read and write displacements in the incoming stream + size_t rd_pos = mb->rd_ptr () - start; + size_t wr_pos = mb->wr_ptr () - start; + + this->mb_ = ACE_Message_Block::duplicate (&msgb); + + this->mb_->rd_ptr (rd_pos); + this->mb_->wr_ptr (wr_pos); + } + + this->buffer_ = this->mb_->rd_ptr (); + this->maximum_ = length; + this->length_ = length; + this->release_ = 0; +} +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + +void +TAO_Unbounded_Sequence<CORBA::Octet>::_tao_any_destructor (void * x) +{ + TAO_Unbounded_Sequence<CORBA::Octet> * tmp = + static_cast<TAO_Unbounded_Sequence<CORBA::Octet> *> (x); + delete tmp; +} + +void +TAO_Unbounded_Sequence<CORBA::Octet>::_allocate_buffer (CORBA::ULong length) +{ + CORBA::Octet *tmp = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (length); + + if (this->buffer_ != 0) + { + CORBA::Octet * old = reinterpret_cast<CORBA::Octet *> (this->buffer_); + + for (CORBA::ULong i = 0; i < this->length_; ++i) + { + tmp[i] = old[i]; + } + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + if (this->mb_ != 0) + { + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; + } + else +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + if (this->release_) + { + TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (old); + } + } + + this->buffer_ = tmp; +} + +void TAO_Unbounded_Sequence<CORBA::Octet>::_deallocate_buffer (void) +{ + if (this->buffer_ != 0 +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + && this->mb_ == 0 +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + && this->release_ != 0) + { + CORBA::Octet * tmp = reinterpret_cast<CORBA::Octet *> (this->buffer_); + TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp); + } +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + else + { + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; + } +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + + this->buffer_ = 0; + this->length_ = 0; + this->release_ = 0; + this->maximum_ = 0; +} + + +void +TAO_Unbounded_Sequence<CORBA::Octet>::replace (CORBA::ULong max, + CORBA::ULong length, + CORBA::Octet * data, + CORBA::Boolean release) +{ + this->maximum_ = max; + this->length_ = length; + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + if (this->mb_ != 0) + { + ACE_Message_Block::release (this->mb_); + this->mb_ = 0; + } + else +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + if (this->buffer_ && this->release_ == 1) + { + CORBA::Octet * tmp = + reinterpret_cast<CORBA::Octet *> (this->buffer_); + TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp); + } + + this->buffer_ = data; + this->release_ = release; +} + +// **************************************************************** + +bool +operator== (const TAO_Unbounded_Sequence<CORBA::Octet> & lhs, + const TAO_Unbounded_Sequence<CORBA::Octet> & rhs) +{ + const CORBA::ULong rlen = rhs.length (); + + if (rlen != lhs.length ()) + { + return false; + } + + for (CORBA::ULong i = 0; i < rlen; ++i) + { + if (rhs[i] != lhs[i]) + { + return false; + } + } + + return true; +} + +bool +operator!= (const TAO_Unbounded_Sequence<CORBA::Octet> & lhs, + const TAO_Unbounded_Sequence<CORBA::Octet> & rhs) +{ + return !(lhs == rhs); +} + +TAO_END_VERSIONED_NAMESPACE_DECL |