summaryrefslogtreecommitdiff
path: root/TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp')
-rw-r--r--TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp b/TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp
new file mode 100644
index 00000000000..043f24add9a
--- /dev/null
+++ b/TAO/tests/Sequence_Unit_Tests/unbounded_octet_sequence.hpp
@@ -0,0 +1,284 @@
+#ifndef guard_unbounded_octet_sequence_hpp
+#define guard_unbounded_octet_sequence_hpp
+/**
+ * @file
+ *
+ * @brief Implement octet sequences
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen
+ */
+#include "tao/orbconf.h"
+
+#if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
+
+#include "unbounded_value_allocation_traits.hpp"
+#include "value_traits.hpp"
+#include "unbounded_value_sequence.hpp"
+#include "range_checking.hpp"
+
+#include "tao/Basic_Types.h"
+#include "ace/Message_Block.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+template<>
+class unbounded_value_sequence<CORBA::Octet>
+{
+public:
+ typedef CORBA::Octet value_type;
+ typedef CORBA::Octet element_type;
+ typedef CORBA::Octet const const_value_type;
+
+ typedef details::unbounded_value_allocation_traits<value_type,true> allocation_traits;
+ typedef details::value_traits<value_type,true> element_traits;
+ typedef details::generic_sequence<value_type, allocation_traits, element_traits> implementation_type;
+ typedef details::range_checking<value_type,true> range;
+
+ inline unbounded_value_sequence<CORBA::Octet>()
+ : maximum_ (allocation_traits::default_maximum())
+ , length_ (0)
+ , buffer_ (allocation_traits::default_buffer_allocation())
+ , release_ (true)
+ , mb_ (0)
+ {}
+ inline explicit unbounded_value_sequence<CORBA::Octet>(CORBA::ULong maximum)
+ : maximum_(maximum)
+ , length_(0)
+ , buffer_(allocbuf(maximum_))
+ , release_(true)
+ , mb_ (0)
+ {}
+ inline unbounded_value_sequence<CORBA::Octet>(
+ CORBA::ULong maximum,
+ CORBA::ULong length,
+ value_type * data,
+ CORBA::Boolean release = false)
+ : maximum_ (maximum),
+ length_ (length),
+ buffer_ (data),
+ release_ (release),
+ mb_ (0)
+ {}
+ inline ~unbounded_value_sequence<CORBA::Octet>() {
+ if (mb_)
+ ACE_Message_Block::release (mb_);
+ if (release_)
+ freebuf(buffer_);
+ }
+ /// Create a sequence of octets from a single message block (i.e. it
+ /// ignores any chaining in the meesage block).
+ inline unbounded_value_sequence<CORBA::Octet> (CORBA::ULong length,
+ const ACE_Message_Block* mb)
+ : maximum_ (length)
+ , length_ (length)
+ , buffer_ (reinterpret_cast <CORBA::Octet *>(mb->rd_ptr ()))
+ , release_ (false)
+ , 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);
+ }
+ }
+ inline CORBA::ULong maximum() const {
+ return maximum_;
+ }
+ inline CORBA::Boolean release() const {
+ return release_;
+ }
+ inline CORBA::ULong length() const {
+ return length_;
+ }
+ inline void length(CORBA::ULong length) {
+ if (length <= maximum_ || length <= length_)
+ {
+ if (length_ < length)
+ {
+ // TODO This code does not provide the strong-exception
+ // guarantee, but it does provide the weak-exception
+ // guarantee. The problem would appear when
+ // initialize_range() raises an exception after several
+ // elements have been modified. One could argue that
+ // this problem is irrelevant, as the elements already
+ // modified are unreachable to conforming applications.
+ element_traits::initialize_range(
+ buffer_ + length_, buffer_ + length);
+ }
+ length_ = length;
+ return;
+ }
+
+ unbounded_value_sequence<CORBA::Octet> tmp(length);
+ tmp.length_ = length;
+ element_traits::copy_range(
+ buffer_, buffer_ + length_, tmp.buffer_);
+ element_traits::initialize_range(
+ tmp.buffer_ + length_, tmp.buffer_ + length);
+ swap(tmp);
+ }
+ inline value_type const & operator[](CORBA::ULong i) const {
+ range::check(i, length_, maximum_, "operator[]() const");
+ return buffer_[i];
+ }
+ inline value_type & operator[](CORBA::ULong i) {
+ range::check(i, length_, maximum_, "operator[]() non-const");
+ return buffer_[i];
+ }
+ inline void replace(
+ CORBA::ULong maximum,
+ CORBA::ULong length,
+ value_type * data,
+ CORBA::Boolean release = false) {
+ unbounded_value_sequence<CORBA::Octet> tmp(maximum, length, data, release);
+ swap(tmp);
+ }
+ inline value_type const * get_buffer() const {
+ if (buffer_ == 0)
+ {
+ buffer_ = allocbuf(maximum_);
+ }
+ return buffer_;
+ }
+ inline value_type * get_buffer(CORBA::Boolean orphan = false) {
+ if (orphan && !release_)
+ {
+ return 0;
+ }
+ if (buffer_ == 0)
+ {
+ buffer_ = allocbuf(maximum_);
+ }
+ if (!orphan)
+ {
+ return buffer_;
+ }
+
+ unbounded_value_sequence<CORBA::Octet> tmp;
+ swap(tmp);
+ tmp.release_ = false;
+
+ return tmp.buffer_;
+ }
+ inline void swap(unbounded_value_sequence & rhs) throw() {
+ std::swap (mb_, rhs.mb_);
+ std::swap (maximum_, rhs.maximum_);
+ std::swap (length_, rhs.length_);
+ std::swap (buffer_, rhs.buffer_);
+ std::swap (release_, rhs.release_);
+ }
+ static value_type * allocbuf(CORBA::ULong maximum) {
+ return allocation_traits::allocbuf(maximum);
+ }
+ static void freebuf(value_type * buffer) {
+ allocation_traits::freebuf(buffer);
+ }
+
+ /// Returns the underlying message block, the caller must *not*
+ /// release the copy.
+ inline ACE_Message_Block* mb (void) const {
+ return mb_;
+ }
+
+ /// Replaces the current buffer with <mb>, using only <length> bytes.
+ /// It takes a duplicate of <mb> so the user still owns it.
+ inline void replace (CORBA::ULong length, const ACE_Message_Block* mb) {
+ unbounded_value_sequence<CORBA::Octet> s (length, mb);
+ swap (s);
+ }
+
+ unbounded_value_sequence<CORBA::Octet> (
+ const unbounded_value_sequence<CORBA::Octet> &rhs)
+ : maximum_ (0)
+ , length_ (0)
+ , buffer_(0)
+ , release_(false)
+ , mb_ (0)
+ {
+ unbounded_value_sequence<CORBA::Octet> tmp(rhs.maximum_);
+ tmp.length_ = rhs.length_;
+ if (rhs.mb_ == 0)
+ {
+ ACE_OS::memcpy (tmp.buffer_,
+ rhs.buffer_,
+ rhs.length_);
+ }
+ else
+ {
+ size_t offset = 0;
+ for (const ACE_Message_Block *i = rhs.mb_; i != 0; i = i->cont ())
+ {
+ ACE_OS::memcpy (tmp.buffer_ + offset,
+ i->rd_ptr (),
+ i->length ());
+
+ offset += i->length ();
+ }
+ }
+ swap(tmp);
+ }
+
+ unbounded_value_sequence<CORBA::Octet> &
+ operator= (const unbounded_value_sequence<CORBA::Octet> & rhs)
+ {
+ unbounded_value_sequence<CORBA::Octet> tmp(rhs);
+ swap(tmp);
+ return * this;
+ }
+
+private:
+ /// The maximum number of elements the buffer can contain.
+ CORBA::ULong maximum_;
+
+ /// The current number of elements in the buffer.
+ CORBA::ULong length_;
+
+ /// The buffer with all the elements, casting must be done in derived
+ /// classes.
+ mutable value_type * buffer_;
+
+ /// If true then the sequence should release the buffer when it is
+ /// destroyed.
+ CORBA::Boolean release_;
+ ACE_Message_Block* mb_;
+};
+
+} // namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+#endif
+
+#endif // guard_unbounded_octet_sequence_hpp