summaryrefslogtreecommitdiff
path: root/TAO
diff options
context:
space:
mode:
authorJohnny Willemsen <jwillemsen@remedy.nl>2009-03-23 09:55:43 +0000
committerJohnny Willemsen <jwillemsen@remedy.nl>2009-03-23 09:55:43 +0000
commit01bfd7c8a6335013cf9c385dc53b7f48101c0c96 (patch)
treeafec899c0e18bd892d0e1cb01d66ee23d1319da1 /TAO
parent28c1208615a2f9ed300cfccd4488d8f889d1e0ab (diff)
downloadATCD-01bfd7c8a6335013cf9c385dc53b7f48101c0c96.tar.gz
Mon Mar 23 09:55:22 UTC 2009 Johnny Willemsen <jwillemsen@remedy.nl>
* tao/Bounded_Basic_String_Sequence_T.h * tao/Bounded_Object_Reference_Sequence_T.h * tao/Generic_Sequence_T.h * tao/Makefile.am * tao/MM_Sequence_Iterator_T.h * tao/orbconf.h * tao/tao.mpc * tao/Unbounded_Basic_String_Sequence_T.h * tao/Unbounded_Object_Reference_Sequence_T.h * tao/Unbounded_Value_Sequence_T.h * tests/Sequence_Iterators/* Added support for STL iterators for the CORBA sequences. This has been developed by Joe Hoffert <jhoffert at dre dot vanderbilt dot edu> The code is not 100% finished yet, some last memory leaks and portability issues are left. By merging this to svn head it is much easier to test the code on all the platforms. This feature is disabled by default, you have to define TAO_HAS_SEQUENCE_ITERATORS to 1 in your config.h file to enable this feature. Be aware that these STL iterators are a TAO specific addition and are not part of the CORBA C++ mapping
Diffstat (limited to 'TAO')
-rw-r--r--TAO/ChangeLog23
-rw-r--r--TAO/tao/Bounded_Basic_String_Sequence_T.h72
-rw-r--r--TAO/tao/Bounded_Object_Reference_Sequence_T.h72
-rw-r--r--TAO/tao/Generic_Sequence_T.h985
-rw-r--r--TAO/tao/MM_Sequence_Iterator_T.h959
-rw-r--r--TAO/tao/Makefile.am1
-rw-r--r--TAO/tao/Unbounded_Basic_String_Sequence_T.h108
-rw-r--r--TAO/tao/Unbounded_Object_Reference_Sequence_T.h72
-rw-r--r--TAO/tao/Unbounded_Value_Sequence_T.h65
-rw-r--r--TAO/tao/orbconf.h4
-rw-r--r--TAO/tao/tao.mpc1
-rw-r--r--TAO/tests/Sequence_Iterators/Bounded_String.cpp707
-rw-r--r--TAO/tests/Sequence_Iterators/Sequence_Iterators.mpc31
-rw-r--r--TAO/tests/Sequence_Iterators/StringSeq.cpp977
-rw-r--r--TAO/tests/Sequence_Iterators/Unbounded_Objectref.cpp676
-rw-r--r--TAO/tests/Sequence_Iterators/Unbounded_Value.cpp690
-rw-r--r--TAO/tests/Sequence_Iterators/mock_reference.cpp90
-rw-r--r--TAO/tests/Sequence_Iterators/mock_reference.hpp102
-rwxr-xr-xTAO/tests/Sequence_Iterators/run_test.pl68
-rw-r--r--TAO/tests/Sequence_Iterators/testing_counters.hpp106
-rw-r--r--TAO/tests/Sequence_Iterators/testing_exception.hpp15
21 files changed, 5824 insertions, 0 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index 7550475b748..09bb9f2b1c5 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,3 +1,26 @@
+Mon Mar 23 09:55:22 UTC 2009 Johnny Willemsen <jwillemsen@remedy.nl>
+
+ * tao/Bounded_Basic_String_Sequence_T.h
+ * tao/Bounded_Object_Reference_Sequence_T.h
+ * tao/Generic_Sequence_T.h
+ * tao/Makefile.am
+ * tao/MM_Sequence_Iterator_T.h
+ * tao/orbconf.h
+ * tao/tao.mpc
+ * tao/Unbounded_Basic_String_Sequence_T.h
+ * tao/Unbounded_Object_Reference_Sequence_T.h
+ * tao/Unbounded_Value_Sequence_T.h
+ * tests/Sequence_Iterators/*
+ Added support for STL iterators for the CORBA sequences. This
+ has been developed by Joe Hoffert <jhoffert at dre dot vanderbilt dot edu>
+ The code is not 100% finished yet, some last memory leaks and
+ portability issues are left. By merging this to svn head it
+ is much easier to test the code on all the platforms. This
+ feature is disabled by default, you have to define
+ TAO_HAS_SEQUENCE_ITERATORS to 1 in your config.h file to enable
+ this feature. Be aware that these STL iterators are a TAO specific
+ addition and are not part of the CORBA C++ mapping
+
Sat Mar 21 17:53:17 UTC 2009 Phil Mesnier <mesnier_p@ociweb.com>
* orbsvcs/orbsvcs/Notify/XML_Saver.cpp:
diff --git a/TAO/tao/Bounded_Basic_String_Sequence_T.h b/TAO/tao/Bounded_Basic_String_Sequence_T.h
index c056bc2c60c..14ca643f6e3 100644
--- a/TAO/tao/Bounded_Basic_String_Sequence_T.h
+++ b/TAO/tao/Bounded_Basic_String_Sequence_T.h
@@ -14,6 +14,7 @@
#include "tao/Generic_Sequence_T.h"
#include "tao/String_Sequence_Element_T.h"
#include "tao/String_Const_Sequence_Element_T.h"
+#include "tao/MM_Sequence_Iterator_T.h"
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -105,6 +106,77 @@ public:
implementation_type::freebuf(buffer);
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO unbounded basic
+ /// string sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef MM_Sequence_Iterator<bounded_basic_string_sequence<charT, MAX> > iterator;
+ typedef Const_MM_Sequence_Iterator<bounded_basic_string_sequence<charT, MAX> > const_iterator;
+ typedef MM_Sequence_Reverse_Iterator<bounded_basic_string_sequence<charT, MAX> > reverse_iterator;
+ typedef Const_MM_Sequence_Reverse_Iterator<bounded_basic_string_sequence<charT, MAX> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ inline iterator begin (void)
+ {
+ return iterator (&this->impl_);
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ inline const_iterator begin (void) const
+ {
+ return const_iterator (&this->impl_);
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ inline iterator end (void)
+ {
+ return iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ inline const_iterator end (void) const
+ {
+ return const_iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ inline reverse_iterator rbegin (void)
+ {
+ return reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ inline const_reverse_iterator rbegin (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a reverse iterator that points to one before the beginning
+ // of the sequence.
+ inline reverse_iterator rend (void)
+ {
+ return reverse_iterator (&this->impl_,
+ -1);
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ inline const_reverse_iterator rend (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ -1);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
implementation_type impl_;
};
diff --git a/TAO/tao/Bounded_Object_Reference_Sequence_T.h b/TAO/tao/Bounded_Object_Reference_Sequence_T.h
index 5d367a816e2..2a4af14b14f 100644
--- a/TAO/tao/Bounded_Object_Reference_Sequence_T.h
+++ b/TAO/tao/Bounded_Object_Reference_Sequence_T.h
@@ -14,6 +14,7 @@
#include "Generic_Sequence_T.h"
#include "Object_Reference_Sequence_Element_T.h"
#include "Object_Reference_Const_Sequence_Element_T.h"
+#include "tao/MM_Sequence_Iterator_T.h"
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -106,6 +107,77 @@ public:
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO bounded object
+ /// reference sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef MM_Sequence_Iterator<bounded_object_reference_sequence<object_t, object_t_var, MAX> > iterator;
+ typedef Const_MM_Sequence_Iterator<bounded_object_reference_sequence<object_t, object_t_var, MAX> > const_iterator;
+ typedef MM_Sequence_Reverse_Iterator<bounded_object_reference_sequence<object_t, object_t_var, MAX> > reverse_iterator;
+ typedef Const_MM_Sequence_Reverse_Iterator<bounded_object_reference_sequence<object_t, object_t_var, MAX> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ iterator begin (void)
+ {
+ return iterator (&this->impl_);
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ const_iterator begin (void) const
+ {
+ return const_iterator (&this->impl_);
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ iterator end (void)
+ {
+ return iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ const_iterator end (void) const
+ {
+ return const_iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ reverse_iterator rbegin (void)
+ {
+ return reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ const_reverse_iterator rbegin (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a reverse iterator that points to one before the beginning
+ // of the sequence.
+ reverse_iterator rend (void)
+ {
+ return reverse_iterator (&this->impl_,
+ -1);
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ const_reverse_iterator rend (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ -1);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
implementation_type impl_;
};
diff --git a/TAO/tao/Generic_Sequence_T.h b/TAO/tao/Generic_Sequence_T.h
index 34b817b12ba..032fe5e6e0b 100644
--- a/TAO/tao/Generic_Sequence_T.h
+++ b/TAO/tao/Generic_Sequence_T.h
@@ -68,11 +68,38 @@ namespace TAO
namespace details
{
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+// Forward declare the iterators
+template<typename T>
+class Generic_Sequence_Iterator;
+
+template<typename T>
+class Const_Generic_Sequence_Iterator;
+
+template<typename T>
+class Generic_Sequence_Reverse_Iterator;
+
+template<typename T>
+class Const_Generic_Sequence_Reverse_Iterator;
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
template<typename T,
class ALLOCATION_TRAITS,
class ELEMENT_TRAITS>
class generic_sequence
{
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ friend class Generic_Sequence_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> >;
+ friend class Const_Generic_Sequence_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> >;
+ friend class Generic_Sequence_Reverse_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> >;
+ friend class Const_Generic_Sequence_Reverse_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> >;
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
public:
typedef T value_type;
typedef ALLOCATION_TRAITS allocation_traits;
@@ -325,6 +352,80 @@ public:
allocation_traits::freebuf(buffer);
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef Generic_Sequence_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> > iterator;
+ typedef Const_Generic_Sequence_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> > const_iterator;
+ typedef Generic_Sequence_Reverse_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> > reverse_iterator;
+ typedef Const_Generic_Sequence_Reverse_Iterator<generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ iterator begin (void)
+ {
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::iterator (this);
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ const_iterator begin (void) const
+ {
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::const_iterator (this);
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ iterator end (void)
+ {
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::iterator (this,
+ this->length_);
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ const_iterator end (void) const
+ {
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::const_iterator (this,
+ this->length_);
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ reverse_iterator rbegin (void)
+ {
+ // Here we need to be at the last element - not one past.
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::reverse_iterator (this,
+ this->length_ - 1);
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ const_reverse_iterator rbegin (void) const
+ {
+ // Here we need to be at the last element - not one past.
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::const_reverse_iterator (this,
+ this->length_ - 1);
+ }
+
+ // Get a reverse iterator that points to one before the
+ // beginning of the sequence.
+ reverse_iterator rend (void)
+ {
+ // Here we need to be at one before the first element - not the first.
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::reverse_iterator (this,
+ -1);
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ const_reverse_iterator rend (void) const
+ {
+ // Here we need to be at one before the first element - not the first.
+ return typename generic_sequence<T, ALLOCATION_TRAITS, ELEMENT_TRAITS>::const_reverse_iterator (this,
+ -1);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
/// The maximum number of elements the buffer can contain.
CORBA::ULong maximum_;
@@ -337,6 +438,890 @@ private:
mutable CORBA::Boolean release_;
};
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+/**
+ * @class Generic_Sequence_Iterator
+ * @brief Implements a random access iterator for generic sequence type
+ * classes.
+ */
+template <typename SEQUENCE_T>
+ class Generic_Sequence_Iterator
+{
+ friend class Const_Generic_Sequence_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef CORBA::Long difference_type;
+
+ /// Construct a Generic_Sequence_Iterator at position pos.
+ Generic_Sequence_Iterator (generic_sequence<value_type,
+ allocation_traits,
+ element_traits> *sequence,
+ size_t pos = 0)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ Generic_Sequence_Iterator (Generic_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Generic_Sequence_Iterator & operator= (
+ Generic_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Generic_Sequence_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// typecast operator to Const_Generic_Sequence_Iterator
+ operator Const_Generic_Sequence_Iterator<SEQUENCE_T> ()
+ {
+ return Const_Generic_Sequence_Iterator<SEQUENCE_T> (*this);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ value_type & operator* (void)
+ {
+ // Access the underlying element in the sequence.
+ return (*(this->sequence_))[this->pos_];
+ }
+
+ /// Returns a const reference to the item contained at the current position
+ const value_type & operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return (*(this->sequence_))[this->pos_];
+ }
+
+ /// Preincrement operator
+ Generic_Sequence_Iterator<SEQUENCE_T> &operator++ (void)
+ {
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ Generic_Sequence_Iterator<SEQUENCE_T> operator++ (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ Generic_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ Generic_Sequence_Iterator<SEQUENCE_T> &operator-- (void)
+ {
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ Generic_Sequence_Iterator<SEQUENCE_T> operator-- (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ Generic_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ Generic_Sequence_Iterator<SEQUENCE_T> &operator+= (difference_type n)
+ {
+ // Move ahead n elements.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator addition
+ Generic_Sequence_Iterator<SEQUENCE_T> operator+ (difference_type n)
+ {
+ // Create a temporary to return and move it ahead n elements.
+ return Generic_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Iterator subtraction
+ Generic_Sequence_Iterator<SEQUENCE_T> &operator-= (difference_type n)
+ {
+ // Move back n elements.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ Generic_Sequence_Iterator<SEQUENCE_T> operator- (difference_type n)
+ {
+ // Create a temporary to return and move it back n elements.
+ return Generic_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Difference
+ difference_type operator- (const Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return this->pos_ - rhs.pos_;
+ }
+
+ /// Difference
+ difference_type operator- (const Const_Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return this->pos_ - rhs.pos_;
+ }
+
+
+ /// Element operator/assignment
+ value_type & operator[] (difference_type n)
+ {
+ // Return the element at position n
+ return (*(this->sequence_))[this->pos_ + n];
+ }
+
+ /// Less than
+ bool operator< (const Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+ /// Less than
+ bool operator< (const Const_Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+
+ /// Equality operator
+ bool operator== (const Generic_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Generic_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the sequence with which we are dealing
+ generic_sequence<value_type, allocation_traits, element_traits> *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Generic_Sequence_Iterator<SEQUENCE_T>
+ operator+ (typename Generic_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ const Generic_Sequence_Iterator<SEQUENCE_T> & iter)
+ {
+ // Create an iter and move it ahead n elements.
+ return Generic_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Generic_Sequence_Iterator<SEQUENCE_T> operator-
+ (typename Generic_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ Generic_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements.
+ return Generic_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+
+/**
+ * @class Const_Generic_Sequence_Iterator
+ * @brief Implements a constant random access iterator for generic sequence
+ * type classes.
+ *
+ * Note: Having a const Iterator does not guarantee that the current
+ * *position* that it points to will not change, it only guarantees that
+ * you cannot change the underlying array!
+ */
+template <typename SEQUENCE_T>
+class Const_Generic_Sequence_Iterator
+{
+ friend class Generic_Sequence_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef int difference_type;
+
+ /// Construct a Const_Generic_Sequence_Iterator at position pos from
+ /// a const sequence.
+ Const_Generic_Sequence_Iterator (const generic_sequence<value_type,
+ allocation_traits,
+ element_traits> *sequence,
+ size_t pos = 0)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ virtual ~Const_Generic_Sequence_Iterator ()
+ {
+ }
+
+ /// Copy constructor
+ Const_Generic_Sequence_Iterator (
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Copy constructor initializing by a Generic_Sequence_Iterator
+ Const_Generic_Sequence_Iterator (
+ Generic_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Const_Generic_Sequence_Iterator & operator= (
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Const_Generic_Sequence_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Const_Generic_Sequence_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ const value_type & operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return (*(this->sequence_))[this->pos_];
+ }
+
+ /// Preincrement operator
+ const Const_Generic_Sequence_Iterator<SEQUENCE_T> &operator++ (void) const
+ {
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return * this;
+ }
+
+ /// Postincrement operator
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator++ (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ const Const_Generic_Sequence_Iterator<SEQUENCE_T> &operator-- (void) const
+ {
+ --this->pos_;
+ return * this;
+ }
+
+ /// Postdecrement operator
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator-- (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ const Const_Generic_Sequence_Iterator<SEQUENCE_T> &operator+= (difference_type n) const
+ {
+ // Move ahead n elements.
+ this->pos_ += n;
+ return * this;
+ }
+
+ /// Iterator addition
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator+ (difference_type n) const
+ {
+ // Create a temporary to return and move it ahead n elements.
+ return Const_Generic_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Iterator subtraction
+ const Const_Generic_Sequence_Iterator<SEQUENCE_T> &operator-= (difference_type n) const
+ {
+ // Move back n elements.
+ this->pos_ -= n;
+ return * this;
+ }
+
+ /// Iterator subtraction
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator- (difference_type n) const
+ {
+ // Create a temporary to return and move it back n elements.
+ return Const_Generic_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Difference
+ difference_type operator- (const Const_Generic_Sequence_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // I think the order is important here (i.e., rhs before this).
+ return this->pos_ - rhs.pos_;
+ }
+
+ /// Element operator/assignment
+ const value_type & operator[] (difference_type n) const
+ {
+ // Return the element at position n
+ return (*(this->sequence_))[this->pos_ + n];
+ }
+
+ /// Less than
+ virtual bool operator< (const Const_Generic_Sequence_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_Generic_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_Generic_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the array we are dealing with
+ const generic_sequence<value_type, allocation_traits, element_traits> *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator+
+ (typename Generic_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements.
+ return Const_Generic_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> operator-
+ (typename Generic_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ Const_Generic_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements.
+ return Const_Generic_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+
+/**
+ * @class Generic_Sequence_Reverse_Iterator
+ * @brief Implements a reverse random access iterator for generic sequence
+ * type classes.
+ */
+template <typename SEQUENCE_T>
+class Generic_Sequence_Reverse_Iterator
+{
+ friend class Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef int difference_type;
+
+ /// Construct a Generic_Sequence_Reverse_Iterator at position pos with before_start flag.
+ Generic_Sequence_Reverse_Iterator (generic_sequence<value_type,
+ allocation_traits,
+ element_traits> *sequence,
+ size_t pos)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ Generic_Sequence_Reverse_Iterator (
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Generic_Sequence_Reverse_Iterator & operator= (
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Generic_Sequence_Reverse_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ value_type & operator* (void)
+ {
+ // Access the underlying element in the sequence.
+ return (*(this->sequence_))[this->pos_];
+ }
+
+ /// Returns a const reference to the item contained at the current position
+ const value_type& operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return (*(this->sequence_))[this->pos_];
+ }
+
+ /// Preincrement operator
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator++ (void)
+ {
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator++ (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now past the end.
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-- (void)
+ {
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator-- (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator+= (difference_type n)
+ {
+ // Move back n elements for reverse iterators.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator addition
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator+ (difference_type n)
+ {
+ // Create a temporary to return and move it back n elements for
+ // reverse iterators.
+ return Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Iterator subtraction
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-= (difference_type n)
+ {
+ // Move ahead n elements for reverse iterators.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator- (difference_type n)
+ {
+ // Create a temporary to return and move it ahead n elements for
+ // reverse iterators.
+ return Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Difference
+ difference_type operator- (const Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+ /// Difference
+ difference_type operator- (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+
+ /// Element operator/assignment
+ value_type & operator[] (difference_type n)
+ {
+ // Return the element at position n
+ return (*(this->sequence_))[this->pos_ - n];
+ }
+
+ /// Less than
+ bool operator< (const Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+ /// Less than
+ bool operator< (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+
+ /// Equality operator
+ bool operator== (const Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// The sequence with which we are dealing
+ generic_sequence<value_type, allocation_traits, element_traits> *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator+
+ (typename Generic_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements for reverse iterators.
+ return Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator-
+ (typename Generic_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements for reverse iterators.
+ return Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+
+/**
+ * @class Const_Generic_Sequence_Reverse_Iterator
+ * @brief Implements a constant reverse random access iterator for generic
+ * sequence type classes.
+ *
+ * Note: Having a const Iterator does not guarantee that the current
+ * *position* that it points to will not change, it only guarantees that
+ * you cannot change the underlying array!
+ */
+template <typename SEQUENCE_T>
+class Const_Generic_Sequence_Reverse_Iterator
+{
+ friend class Generic_Sequence_Reverse_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef int difference_type;
+
+ /// Construct a Const_Generic_Sequence_Reverse_Iterator at position pos
+ /// using a const sequence.
+ Const_Generic_Sequence_Reverse_Iterator (const generic_sequence<value_type,
+ allocation_traits,
+ element_traits> *sequence,
+ size_t pos)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ Const_Generic_Sequence_Reverse_Iterator (
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Copy constructor
+ Const_Generic_Sequence_Reverse_Iterator (
+ Generic_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Const_Generic_Sequence_Reverse_Iterator & operator= (
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Const_Generic_Sequence_Reverse_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// typecast operator to Generic_Sequence_Reverse_Iterator
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ const value_type& operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return (*this->sequence_)[this->pos_];
+ }
+
+ /// Preincrement operator
+ const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator++ (void) const
+ {
+ // Decrement the position for reveres iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator++ (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-- (void) const
+ {
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator-- (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator+= (difference_type n) const
+ {
+ // Move back n elements for reverse iterators.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator addition
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator+ (difference_type n) const
+ {
+ // Create a temporary to return and move it back n elements for
+ // reverse iterators.
+ return Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Iterator subtraction
+ const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-= (difference_type n) const
+ {
+ // Move ahead n elements for reverse iterators.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator- (difference_type n) const
+ {
+ // Create a temporary to return and move it ahead n elements for
+ // reverse iterators.
+ return Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Difference
+ difference_type operator- (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+ /// Element operator/assignment
+ const value_type & operator[] (difference_type n) const
+ {
+ // Return the element at position n
+ return (*(this->sequence_))[this->pos_ - n];
+ }
+
+ /// Less than
+ bool operator< (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the array we are dealing with
+ const generic_sequence<value_type, allocation_traits, element_traits> *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator+
+ (typename Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements for reverse iterators.
+ return Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> operator-
+ (typename Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements for reverse iterators.
+ return Const_Generic_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
} // namespace details
} // namespace TAO
diff --git a/TAO/tao/MM_Sequence_Iterator_T.h b/TAO/tao/MM_Sequence_Iterator_T.h
new file mode 100644
index 00000000000..4e7d854cb30
--- /dev/null
+++ b/TAO/tao/MM_Sequence_Iterator_T.h
@@ -0,0 +1,959 @@
+#ifndef mm_sequence_iterator_h
+#define mm_sequence_iterator_h
+
+/**
+ * @file
+ *
+ * @brief Implement the iterator for CORBA sequences that need
+ * memory management.
+ *
+ * There are some CORBA sequences that need to manage memory (e.g.,
+ * string sequences). Iterators for these classes also need to
+ * manage memory and therefore do not use the iterators defined
+ * for the generic sequences.
+ *
+ * Essentially, only the iterators operators that reference and return
+ * elements (e.g.,operator*, operator[]) need to be overridden from the
+ * behavior provided by the generic sequence iterators. Template
+ * specialization code is appropriate here but I couldn't figure out how
+ * to make the compiler happy.
+ *
+ * In lieu of template specialization code separate iterators exist
+ * for sequences that manage memory. Here are those iterators.
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert
+ */
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+namespace TAO
+{
+
+// Forward declare the iterators
+template<typename T>
+class MM_Sequence_Iterator;
+
+template<typename T>
+class Const_MM_Sequence_Iterator;
+
+template<typename T>
+class MM_Sequence_Reverse_Iterator;
+
+template<typename T>
+class Const_MM_Sequence_Reverse_Iterator;
+
+
+/**
+ * @class MM_Sequence_Iterator
+ * @brief Implements a random access iterator for generic sequence type
+ * classes that need to manage memory. MM stands for memory managed.
+ */
+template <typename SEQUENCE_T>
+ class MM_Sequence_Iterator
+{
+ friend class Const_MM_Sequence_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::element_type element_type;
+ typedef typename SEQUENCE_T::const_element_type const_element_type;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef typename SEQUENCE_T::implementation_type implementation_type;
+ typedef CORBA::Long difference_type;
+
+ /// Construct a MM_Sequence_Iterator at position pos.
+ MM_Sequence_Iterator (implementation_type *sequence,
+ size_t pos = 0)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ MM_Sequence_Iterator (MM_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ MM_Sequence_Iterator & operator= (MM_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ {
+ MM_Sequence_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// typecast operator to Const_MM_Sequence_Iterator
+ operator Const_MM_Sequence_Iterator<SEQUENCE_T> ()
+ {
+ return Const_MM_Sequence_Iterator<SEQUENCE_T> (*this);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ element_type operator* (void)
+ {
+ // Access the underlying element in the sequence.
+ return element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Returns a const reference to the item contained at the current position
+ const_element_type operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return const_element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Preincrement operator
+ MM_Sequence_Iterator<SEQUENCE_T> &operator++ (void)
+ {
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ MM_Sequence_Iterator<SEQUENCE_T> operator++ (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ MM_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ MM_Sequence_Iterator<SEQUENCE_T> &operator-- (void)
+ {
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ MM_Sequence_Iterator<SEQUENCE_T> operator-- (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ MM_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ MM_Sequence_Iterator<SEQUENCE_T> &operator+= (difference_type n)
+ {
+ // Move ahead n elements.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator addition
+ MM_Sequence_Iterator<SEQUENCE_T> operator+ (difference_type n)
+ {
+ // Create a temporary to return and move it ahead n elements.
+ return MM_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Iterator subtraction
+ MM_Sequence_Iterator<SEQUENCE_T> &operator-= (difference_type n)
+ {
+ // Move back n elements.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ MM_Sequence_Iterator<SEQUENCE_T> operator- (difference_type n)
+ {
+ // Create a temporary to return and move it back n elements.
+ return MM_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Difference
+ difference_type operator- (const MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., this before rhs).
+ return this->pos_ - rhs.pos_;
+ }
+
+ /// Difference
+ difference_type operator- (const Const_MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., this before rhs).
+ return this->pos_ - rhs.pos_;
+ }
+
+ /// Element operator/assignment
+ element_type operator[] (difference_type n)
+ {
+ // Return the element at position pos_ + n
+ return element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Element operator/assignment
+ const_element_type operator[] (difference_type n) const
+ {
+ // Return the element at position pos_ + n
+ return const_element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Less than
+ bool operator< (const MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+ /// Less than
+ bool operator< (const Const_MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+
+ /// Equality operator
+ bool operator== (const MM_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const MM_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the sequence with which we are dealing
+ implementation_type *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ MM_Sequence_Iterator<SEQUENCE_T>
+ operator+ (typename MM_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ const MM_Sequence_Iterator<SEQUENCE_T> & iter)
+ {
+ // Create an iter and move it ahead n elements.
+ return MM_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ MM_Sequence_Iterator<SEQUENCE_T> operator-
+ (typename MM_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ MM_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements.
+ return MM_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+
+/**
+ * @class Const_MM_Sequence_Iterator
+ * @brief Implements a constant random access iterator for generic sequence
+ * type classes that need to manage memory. MM stands for memory
+ * managed.
+ *
+ * Note: Having a const Iterator does not guarantee that the current
+ * *position* that it points to will not change, it only guarantees that
+ * you cannot change the underlying array!
+ */
+template <typename SEQUENCE_T>
+class Const_MM_Sequence_Iterator
+{
+ friend class MM_Sequence_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::const_element_type const_element_type;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef typename SEQUENCE_T::implementation_type implementation_type;
+ typedef int difference_type;
+
+ /// Construct a Const_MM_Sequence_Iterator at position pos from
+ /// a const sequence.
+ Const_MM_Sequence_Iterator (const implementation_type *sequence,
+ size_t pos = 0)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ virtual ~Const_MM_Sequence_Iterator ()
+ {
+ }
+
+ /// Copy constructor
+ Const_MM_Sequence_Iterator (
+ Const_MM_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Copy constructor initializing by a MM_Sequence_Iterator
+ Const_MM_Sequence_Iterator (
+ MM_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Const_MM_Sequence_Iterator & operator= (
+ Const_MM_Sequence_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Const_MM_Sequence_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Const_MM_Sequence_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ const_element_type operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return const_element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Preincrement operator
+ const Const_MM_Sequence_Iterator<SEQUENCE_T> &operator++ (void) const
+ {
+ // Increment the position.
+ ++this->pos_;
+ return * this;
+ }
+
+ /// Postincrement operator
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator++ (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_MM_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position.
+ // We also need to check if we're now past the end.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ const Const_MM_Sequence_Iterator<SEQUENCE_T> &operator-- (void) const
+ {
+ --this->pos_;
+ return * this;
+ }
+
+ /// Postdecrement operator
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator-- (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_MM_Sequence_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ const Const_MM_Sequence_Iterator<SEQUENCE_T> &operator+= (difference_type n) const
+ {
+ // Move ahead n elements.
+ this->pos_ += n;
+ return * this;
+ }
+
+ /// Iterator addition
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator+ (difference_type n) const
+ {
+ // Create a temporary to return and move it ahead n elements.
+ return Const_MM_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Iterator subtraction
+ const Const_MM_Sequence_Iterator<SEQUENCE_T> &operator-= (difference_type n) const
+ {
+ // Move back n elements.
+ this->pos_ -= n;
+ return * this;
+ }
+
+ /// Iterator subtraction
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator- (difference_type n) const
+ {
+ // Create a temporary to return and move it back n elements.
+ return Const_MM_Sequence_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Difference
+ difference_type operator- (const Const_MM_Sequence_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // I think the order is important here (i.e., this before rhs).
+ return this->pos_ - rhs.pos_;
+ }
+
+ /// Element operator
+ const_element_type operator[] (difference_type n) const
+ {
+ // Return the element at position pos_ + n
+ return const_element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Less than
+ virtual bool operator< (const Const_MM_Sequence_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // Return if this iterator is less than the passed in iterator.
+ return this->pos_ < rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_MM_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_MM_Sequence_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the sequence with which we are dealing
+ const implementation_type *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator+
+ (typename MM_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ Const_MM_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements.
+ return Const_MM_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_MM_Sequence_Iterator<SEQUENCE_T> operator-
+ (typename MM_Sequence_Iterator<SEQUENCE_T>::difference_type n,
+ Const_MM_Sequence_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements.
+ return Const_MM_Sequence_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+
+/**
+ * @class MM_Sequence_Reverse_Iterator
+ * @brief Implements a reverse random access iterator for generic sequence type
+ * classes that need to manage memory. MM stands for memory managed.
+ */
+template <typename SEQUENCE_T>
+class MM_Sequence_Reverse_Iterator
+{
+ friend class Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::element_type element_type;
+ typedef typename SEQUENCE_T::const_element_type const_element_type;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef typename SEQUENCE_T::implementation_type implementation_type;
+ typedef int difference_type;
+
+ /// Construct a MM_Sequence_Reverse_Iterator at position pos
+ MM_Sequence_Reverse_Iterator (implementation_type *sequence,
+ size_t pos)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ MM_Sequence_Reverse_Iterator (
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ MM_Sequence_Reverse_Iterator & operator= (
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ {
+ MM_Sequence_Reverse_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ element_type operator* (void)
+ {
+ // Access the underlying element in the sequence.
+ return element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Returns a const reference to the item contained at the current position
+ const_element_type operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return const_element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Preincrement operator
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator++ (void)
+ {
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator++ (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now past the end.
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-- (void)
+ {
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator-- (int)
+ {
+ // Create a temporary to return so that it's not modified.
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator+= (difference_type n)
+ {
+ // Move back n elements for reverse iterators.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator addition
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator+ (difference_type n)
+ {
+ // Create a temporary to return and move it back n elements for
+ // reverse iterators.
+ return MM_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Iterator subtraction
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-= (difference_type n)
+ {
+ // Move ahead n elements for reverse iterators.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator- (difference_type n)
+ {
+ // Create a temporary to return and move it ahead n elements for
+ // reverse iterators.
+ return MM_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Difference
+ difference_type operator- (const MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+ /// Difference
+ difference_type operator- (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+ /// Element operator/assignment
+ element_type operator[] (difference_type n)
+ {
+ // Return the element at position pos_ + n
+ return element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Element operator/assignment
+ const_element_type operator[] (difference_type n) const
+ {
+ // Return the element at position pos_ + n
+ return const_element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Less than
+ bool operator< (const MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+ /// Less than
+ bool operator< (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+
+ /// Equality operator
+ bool operator== (const MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// The sequence with which we are dealing
+ implementation_type *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator+
+ (typename MM_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements for reverse iterators.
+ return MM_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator-
+ (typename MM_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements for reverse iterators.
+ return MM_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+
+/**
+ * @class Const_MM_Sequence_Reverse_Iterator
+ * @brief Implements a constant reverse random access iterator for generic
+ * sequence type classes that need to manage memory. MM stands for
+ * memory managed.
+ *
+ * Note: Having a const Iterator does not guarantee that the current
+ * *position* that it points to will not change, it only guarantees that
+ * you cannot change the underlying array!
+ */
+template <typename SEQUENCE_T>
+class Const_MM_Sequence_Reverse_Iterator
+{
+ friend class MM_Sequence_Reverse_Iterator<SEQUENCE_T>;
+
+public:
+ // = Necessary traits
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename SEQUENCE_T::value_type value_type;
+ typedef typename SEQUENCE_T::value_type *pointer;
+ typedef typename SEQUENCE_T::value_type &reference;
+ typedef typename SEQUENCE_T::const_element_type const_element_type;
+ typedef typename SEQUENCE_T::allocation_traits allocation_traits;
+ typedef typename SEQUENCE_T::element_traits element_traits;
+ typedef typename SEQUENCE_T::implementation_type implementation_type;
+ typedef int difference_type;
+
+ /// Construct a Const_MM_Sequence_Reverse_Iterator at position pos
+ /// using a const sequence.
+ Const_MM_Sequence_Reverse_Iterator (const implementation_type *sequence,
+ size_t pos)
+ : sequence_ (sequence),
+ pos_ (pos)
+ {
+ }
+
+ /// Copy constructor
+ Const_MM_Sequence_Reverse_Iterator (
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Copy constructor
+ Const_MM_Sequence_Reverse_Iterator (
+ MM_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ : sequence_ (rhs.sequence_),
+ pos_ (rhs.pos_)
+ {
+ }
+
+ /// Assignment operator
+ Const_MM_Sequence_Reverse_Iterator & operator= (
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> const & rhs)
+ {
+ Const_MM_Sequence_Reverse_Iterator tmp(rhs);
+ swap (tmp);
+ return * this;
+ }
+
+ /// swaps all members
+ void swap(Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs)
+ throw()
+ {
+ std::swap (sequence_, rhs.sequence_);
+ std::swap (this->pos_, rhs.pos_);
+ }
+
+ /// typecast operator to MM_Sequence_Reverse_Iterator
+
+ /// Dereference operator returns a reference to the item contained
+ /// at the current position
+ const_element_type operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ return const_element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+
+ /// Preincrement operator
+ const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator++ (void) const
+ {
+ // Decrement the position for reveres iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return *this;
+ }
+
+ /// Postincrement operator
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator++ (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Decrement the position for reverse iterators.
+ // We also need to check if we're now before the start.
+ --this->pos_;
+ return temp_iter;
+ }
+
+ /// Predecrement operator
+ const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-- (void) const
+ {
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return *this;
+ }
+
+ /// Postdecrement operator
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator-- (int) const
+ {
+ // Create a temporary to return so that it's not modified.
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> temp_iter (this->sequence_, this->pos_);
+ // Increment the position for reverse iterators.
+ ++this->pos_;
+ return temp_iter;
+ }
+
+ /// Iterator addition
+ const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator+= (difference_type n) const
+ {
+ // Move back n elements for reverse iterators.
+ this->pos_ -= n;
+ return *this;
+ }
+
+ /// Iterator addition
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator+ (difference_type n) const
+ {
+ // Create a temporary to return and move it back n elements for
+ // reverse iterators.
+ return Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ - n);
+ }
+
+ /// Iterator subtraction
+ const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &operator-= (difference_type n) const
+ {
+ // Move ahead n elements for reverse iterators.
+ this->pos_ += n;
+ return *this;
+ }
+
+ /// Iterator subtraction
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator- (difference_type n) const
+ {
+ // Create a temporary to return and move it ahead n elements for
+ // reverse iterators.
+ return Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> (this->sequence_, this->pos_ + n);
+ }
+
+ /// Difference
+ difference_type operator- (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // I think order is important here (i.e., rhs before this).
+ return rhs.pos_ - this->pos_;
+ }
+
+ /// Element operator/assignment
+ const_element_type operator[] (difference_type n) const
+ {
+ // Return the element at position pos_ + n
+ return const_element_type ((*(this->sequence_))[this->pos_ + n],
+ this->sequence_->release ());
+ }
+
+ /// Less than
+ bool operator< (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> & rhs) const
+ {
+ // Return if this iterator is less than the passed in iterator.
+ // For reverse iterators reverse the logic.
+ return this->pos_ > rhs.pos_;
+ }
+
+ /// Equality operator
+ bool operator== (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ // Compare all the data members for equality.
+ return this->sequence_ == rhs.sequence_
+ && this->pos_ == rhs.pos_;
+ }
+
+ /// Nonequality operator
+ bool operator!= (const Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+private:
+ /// the sequence with which we are dealing
+ const implementation_type *sequence_;
+
+ /// Our current position in the sequence.
+ mutable difference_type pos_;
+};
+
+/// Iterator addition with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator+
+ (typename Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it back n elements for reverse iterators.
+ return Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ - n);
+ }
+
+/// Iterator subtraction with the difference_type being the first argument.
+template<typename SEQUENCE_T>
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> operator-
+ (typename Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T>::difference_type n,
+ Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> iter)
+ {
+ // Create an iter and move it ahead n elements for reverse iterators.
+ return Const_MM_Sequence_Reverse_Iterator<SEQUENCE_T> (iter.sequence_, iter.pos_ + n);
+ }
+
+
+} // namespace TAO
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS == 1 */
+
+#endif // mm_sequence_iterator_h
diff --git a/TAO/tao/Makefile.am b/TAO/tao/Makefile.am
index dd2983c525e..2b3c526cee3 100644
--- a/TAO/tao/Makefile.am
+++ b/TAO/tao/Makefile.am
@@ -1229,6 +1229,7 @@ nobase_include_HEADERS = \
MCAST_Parser.h \
MCAST_Parser.inl \
MMAP_Allocator.h \
+ MM_Sequence_Iterator_T.h \
MProfile.h \
MProfile.inl \
Messaging_PolicyValue.pidl \
diff --git a/TAO/tao/Unbounded_Basic_String_Sequence_T.h b/TAO/tao/Unbounded_Basic_String_Sequence_T.h
index b43ef6764f6..9f7fbd31546 100644
--- a/TAO/tao/Unbounded_Basic_String_Sequence_T.h
+++ b/TAO/tao/Unbounded_Basic_String_Sequence_T.h
@@ -14,6 +14,7 @@
#include "tao/Generic_Sequence_T.h"
#include "tao/String_Sequence_Element_T.h"
#include "tao/String_Const_Sequence_Element_T.h"
+#include "tao/MM_Sequence_Iterator_T.h"
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -113,9 +114,116 @@ public:
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO unbounded basic
+ /// string sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef MM_Sequence_Iterator<unbounded_basic_string_sequence<charT> > iterator;
+ typedef Const_MM_Sequence_Iterator<unbounded_basic_string_sequence<charT> > const_iterator;
+ typedef MM_Sequence_Reverse_Iterator<unbounded_basic_string_sequence<charT> > reverse_iterator;
+ typedef Const_MM_Sequence_Reverse_Iterator<unbounded_basic_string_sequence<charT> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ inline iterator begin (void)
+ {
+ return iterator (&this->impl_);
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ inline const_iterator begin (void) const
+ {
+ return const_iterator (&this->impl_);
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ inline iterator end (void)
+ {
+ return iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ inline const_iterator end (void) const
+ {
+ return const_iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ inline reverse_iterator rbegin (void)
+ {
+ return reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ inline const_reverse_iterator rbegin (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a reverse iterator that points to one before the beginning
+ // of the sequence.
+ inline reverse_iterator rend (void)
+ {
+ return reverse_iterator (&this->impl_,
+ -1);
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ inline const_reverse_iterator rend (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ -1);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
implementation_type impl_;
};
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+/*
+// Below is an attempt at template specialization that would
+// not compile. It might be useful later.
+// Generic_Sequence_Iterator template specializations for
+// Unbounded_Basic_String_Sequence. These are needed since
+// Unbounded_Basic_String_Sequence does some memory management with
+// the strings. Without these specialization we leak memory.
+
+/// Dereference operator returns a reference to the item contained
+/// at the current position. This dereference implies string
+/// memory management.
+// template<typename charT>
+ unbounded_basic_string_sequence<char>::element_type&
+ details::Generic_Sequence_Iterator<unbounded_basic_string_sequence<char>, unbounded_basic_string_sequence::allocation_traits, unbounded_basic_string_sequence::element_traits >::operator* (void)
+ {
+ // Access the underlying element in the sequence.
+ //return element_type (impl_[i], release());
+ return element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release());
+ }
+
+ /// Returns a const reference to the item contained at the current position
+ // template<typename charT>
+ unbounded_basic_string_sequence<char>::const_element_type&
+ details::Generic_Sequence_Iterator<unbounded_basic_string_sequence<char> >::operator* (void) const
+ {
+ // Access the underlying element in the sequence.
+ //return const_element_type (impl_[i], release());
+ return const_element_type ((*(this->sequence_))[this->pos_],
+ this->sequence_->release ());
+ }
+*/
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
} // namespace TAO
TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/tao/Unbounded_Object_Reference_Sequence_T.h b/TAO/tao/Unbounded_Object_Reference_Sequence_T.h
index 50d1ae9fd9b..5b91e166852 100644
--- a/TAO/tao/Unbounded_Object_Reference_Sequence_T.h
+++ b/TAO/tao/Unbounded_Object_Reference_Sequence_T.h
@@ -14,6 +14,7 @@
#include "Generic_Sequence_T.h"
#include "Object_Reference_Sequence_Element_T.h"
#include "Object_Reference_Const_Sequence_Element_T.h"
+#include "tao/MM_Sequence_Iterator_T.h"
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -108,6 +109,77 @@ public:
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO unbounded object reference
+ /// sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef MM_Sequence_Iterator<unbounded_object_reference_sequence<object_t, object_t_var> > iterator;
+ typedef Const_MM_Sequence_Iterator<unbounded_object_reference_sequence<object_t, object_t_var> > const_iterator;
+ typedef MM_Sequence_Reverse_Iterator<unbounded_object_reference_sequence<object_t, object_t_var> > reverse_iterator;
+ typedef Const_MM_Sequence_Reverse_Iterator<unbounded_object_reference_sequence<object_t, object_t_var> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ iterator begin (void)
+ {
+ return iterator (&this->impl_);
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ const_iterator begin (void) const
+ {
+ return const_iterator (&this->impl_);
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ iterator end (void)
+ {
+ return iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ const_iterator end (void) const
+ {
+ return const_iterator (&this->impl_,
+ this->impl_.length ());
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ reverse_iterator rbegin (void)
+ {
+ return reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ const_reverse_iterator rbegin (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ this->impl_.length () - 1);
+ }
+
+ // Get a reverse iterator that points to one before the beginning
+ // of the sequence.
+ reverse_iterator rend (void)
+ {
+ return reverse_iterator (&this->impl_,
+ -1);
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ const_reverse_iterator rend (void) const
+ {
+ return const_reverse_iterator (&this->impl_,
+ -1);
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
implementation_type impl_;
};
diff --git a/TAO/tao/Unbounded_Value_Sequence_T.h b/TAO/tao/Unbounded_Value_Sequence_T.h
index e39893e1f5c..dd52a85eeac 100644
--- a/TAO/tao/Unbounded_Value_Sequence_T.h
+++ b/TAO/tao/Unbounded_Value_Sequence_T.h
@@ -89,6 +89,71 @@ public:
implementation_type::freebuf(buffer);
}
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ ///
+ /// Additions to support iterator semantics for TAO unbounded value
+ /// sequences.
+ ///
+
+ // = Traits and factory methods that create iterators.
+ typedef details::Generic_Sequence_Iterator<details::generic_sequence<value_type, allocation_traits, element_traits> > iterator;
+ typedef details::Const_Generic_Sequence_Iterator<details::generic_sequence<value_type, allocation_traits, element_traits> > const_iterator;
+ typedef details::Generic_Sequence_Reverse_Iterator<details::generic_sequence<value_type, allocation_traits, element_traits> > reverse_iterator;
+ typedef details::Const_Generic_Sequence_Reverse_Iterator<details::generic_sequence<value_type, allocation_traits, element_traits> > const_reverse_iterator;
+
+ // Get an iterator that points to the beginning of the sequence.
+ iterator begin (void)
+ {
+ return impl_.begin ();
+ }
+
+ // Get a const iterator that points to the beginning of the sequence.
+ const_iterator begin (void) const
+ {
+ return impl_.begin ();
+ }
+
+ // Get an iterator that points to the end of the sequence.
+ iterator end (void)
+ {
+ return impl_.end ();
+ }
+
+ // Get a const iterator that points to the end of the sequence.
+ const_iterator end (void) const
+ {
+ return impl_.end ();
+ }
+
+ // Get a reverse iterator that points to the end of the sequence.
+ reverse_iterator rbegin (void)
+ {
+ return impl_.rbegin ();
+ }
+
+ // Get a const reverse iterator that points to the end of the sequence.
+ const_reverse_iterator rbegin (void) const
+ {
+ return impl_.rbegin ();
+ }
+
+ // Get a reverse iterator that points to one before the beginning
+ // of the sequence.
+ reverse_iterator rend (void)
+ {
+ return impl_.rend ();
+ }
+
+ // Get a const reverse iterator that points to one before the
+ // beginning of the sequence.
+ const_reverse_iterator rend (void) const
+ {
+ return impl_.rend ();
+ }
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS==1 */
+
private:
implementation_type impl_;
};
diff --git a/TAO/tao/orbconf.h b/TAO/tao/orbconf.h
index 4f0d9f92bf7..b980e3b1e5c 100644
--- a/TAO/tao/orbconf.h
+++ b/TAO/tao/orbconf.h
@@ -911,6 +911,10 @@ enum TAO_Policy_Scope
# endif
#endif
+#if !defined (TAO_HAS_SEQUENCE_ITERATORS)
+# define TAO_HAS_SEQUENCE_ITERATORS 0
+#endif
+
TAO_END_VERSIONED_NAMESPACE_DECL
#include /**/ "ace/post.h"
diff --git a/TAO/tao/tao.mpc b/TAO/tao/tao.mpc
index 73279335587..71ecf2a7e51 100644
--- a/TAO/tao/tao.mpc
+++ b/TAO/tao/tao.mpc
@@ -457,6 +457,7 @@ project(TAO) : acelib, install, tao_output, taodefaults, pidl, extra_core, taoid
Message_Semantics.h
Messaging_PolicyValueC.h
Messaging_SyncScopeC.h
+ MM_Sequence_Iterator_T.h
MMAP_Allocator.h
MProfile.h
Muxed_TMS.h
diff --git a/TAO/tests/Sequence_Iterators/Bounded_String.cpp b/TAO/tests/Sequence_Iterators/Bounded_String.cpp
new file mode 100644
index 00000000000..42321198b08
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/Bounded_String.cpp
@@ -0,0 +1,707 @@
+/**
+ * @file Unbounded_String.cpp
+ *
+ * @brief test for STL iterator behaviour of CORBA bounded string sequence
+ *
+ * $Id$
+ *
+ * @author Friedhelm Wolf (fwolf@dre.vanderbilt.edu)
+ */
+
+#include <tao/Bounded_Basic_String_Sequence_T.h>
+#include <tao/CORBA_String.h>
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+typedef TAO::bounded_basic_string_sequence<char, 4> s_sequence;
+
+#define FAIL_RETURN_IF(CONDITION) \
+ if (CONDITION) \
+ { \
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("\tFailed at %N:%l\n"))); \
+ return 1; \
+ }
+
+template <typename ITERATOR_T>
+int test_sequence ()
+{
+ s_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+ a.length (4);
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //char* value0 = *a_it;
+ //FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem0_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem0_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem1_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[0]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[2]) != 0);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // NOTE: This does not work for const_iterators
+ // a_it[0] = CORBA::string_dup (elem0_cstr);
+ // FAIL_RETURN_IF (ACE_OS::strcmp (a[2],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ //a[2] = CORBA::string_dup (elem2_cstr);
+
+ // test for loop behaviour
+ s_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ s_sequence test;
+ test.length (4);
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<s_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_const_sequence ()
+{
+ // setup of an example sequence
+ s_sequence setup;
+ setup.length (4);
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ setup[0] = CORBA::string_dup (elem0_cstr);
+ setup[1] = CORBA::string_dup (elem1_cstr);
+ setup[2] = CORBA::string_dup (elem2_cstr);
+ setup[3] = CORBA::string_dup (elem3_cstr);
+
+ const s_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //char* value0 = *a_it;
+ //FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem0_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem0_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem1_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[0]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[2]) != 0);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // NOTE: This does not work for const_iterators
+ // a_it[0] = CORBA::string_dup (elem0_cstr);
+ // FAIL_RETURN_IF (ACE_OS::strcmp (a[2],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ //a[2] = CORBA::string_dup (elem2_cstr);
+
+ // test for loop behaviour
+ s_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ s_sequence test;
+ test.length (4);
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<s_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_sequence_reverse ()
+{
+ s_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+ a.length (4);
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a.length (4);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //char* value0 = *a_it;
+ //FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem3_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem3_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem2_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[3]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[1]) != 0);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // this is not possible for const iterators
+ // a_it[0] = CORBA::string_dup (elem0_cstr);
+ // FAIL_RETURN_IF (ACE_OS::strcmp (a[1],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ //a[1] = CORBA::string_dup (elem1_cstr);
+
+ // test for loop behaviour
+ s_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ s_sequence test;
+ test.length (a.length ());
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<s_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_const_sequence_reverse ()
+{
+ // setup of an example sequence
+ s_sequence setup;
+ setup.length (4);
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ setup[0] = CORBA::string_dup (elem0_cstr);
+ setup[1] = CORBA::string_dup (elem1_cstr);
+ setup[2] = CORBA::string_dup (elem2_cstr);
+ setup[3] = CORBA::string_dup (elem3_cstr);
+
+ const s_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //char* value0 = *a_it;
+ //FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem3_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem3_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem2_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[3]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[1]) != 0);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // this is not possible for const iterators
+ // a_it[0] = CORBA::string_dup (elem0_cstr);
+ // FAIL_RETURN_IF (ACE_OS::strcmp (a[1],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ //a[1] = CORBA::string_dup (elem1_cstr);
+
+ // test for loop behaviour
+ s_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ s_sequence test;
+ test.length (a.length ());
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<s_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+int ACE_TMAIN(int,ACE_TCHAR*[])
+{
+ int status = 0;
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ // Test Generic_Sequence_Iterator.
+ status += test_sequence<s_sequence::iterator> ();
+
+#ifndef ACE_WIN32
+ // g++ seems to make the conversion from iterator to const_iterator
+ // and Windows doesn't. Not sure why.
+ // Test Const_Generic_Sequence_Iterator with non-const sequence.
+ status += test_sequence<s_sequence::const_iterator> ();
+#endif
+
+ // Test Const_Generic_Sequence_Iterator with const sequence.
+ status += test_const_sequence<s_sequence::const_iterator> ();
+
+ // Test Generic_Sequence_Reverse_Iterator.
+ status += test_sequence_reverse<s_sequence::reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with non-const sequence.
+ status += test_sequence_reverse<s_sequence::const_reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with const sequence.
+ status += test_const_sequence_reverse<s_sequence::const_reverse_iterator> ();
+
+#endif
+
+ return status;
+} \ No newline at end of file
diff --git a/TAO/tests/Sequence_Iterators/Sequence_Iterators.mpc b/TAO/tests/Sequence_Iterators/Sequence_Iterators.mpc
new file mode 100644
index 00000000000..2750d6ef2a3
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/Sequence_Iterators.mpc
@@ -0,0 +1,31 @@
+// -*- MPC -*-
+// $Id$
+
+project(StringSeq) : taoexe {
+ exename = StringSeq
+ Source_Files {
+ StringSeq.cpp
+ }
+}
+
+project(Bounded_String) : taoexe {
+ exename = Bounded_String
+ Source_Files {
+ Bounded_String.cpp
+ }
+}
+
+project(Unbounded_Value) : taoexe {
+ exename = Unbounded_Value
+ Source_Files {
+ Unbounded_Value.cpp
+ }
+}
+
+project(Unbounded_Objectref) : taoexe {
+ exename = Unbounded_Objectref
+ Source_Files {
+ mock_reference.cpp
+ Unbounded_Objectref.cpp
+ }
+}
diff --git a/TAO/tests/Sequence_Iterators/StringSeq.cpp b/TAO/tests/Sequence_Iterators/StringSeq.cpp
new file mode 100644
index 00000000000..f947f8b2dd8
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/StringSeq.cpp
@@ -0,0 +1,977 @@
+/**
+ * @file StringSeq.cpp
+ *
+ * @brief test for STL iterator behaviour of CORBA unbounded string sequence
+ *
+ * $Id$
+ *
+ * @author Friedhelm Wolf (fwolf@dre.vanderbilt.edu)
+ */
+
+#include "tao/StringSeqC.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+#define FAIL_RETURN_IF(CONDITION) \
+ if (CONDITION) \
+ { \
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("\tFailed at %N:%l\n"))); \
+ return 1; \
+ }
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_sequence ()
+{
+ ::CORBA::StringSeq a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a.length (4);
+ // Create a case to test for memory leaks
+ // in the sequence.
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+
+ // Create a case to test for memory leaks
+ // in the iterator.
+ *a_it = CORBA::string_dup (elem0_cstr);
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // I'm not sure this test makes sense since what's returned from
+ // dereferencing the iterator is an r value.
+ const char* value_seq = a[0];
+ FAIL_RETURN_IF (ACE_OS::strcmp (value_seq, elem0_cstr) != 0);
+ const char* value0 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem0_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem0_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem1_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[0]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[2]) != 0);
+
+ // test operator[] write
+ // NOTE: This assignment actually modifies the third element
+ // in the sequence since the iterator was previously positioned
+ // at the third element. I believe these are the proper semantics
+ // for using the bracket operator with an iterator. The number
+ // in the brackets is additive - not absolute.
+ a_it[0] = CORBA::string_dup (elem2_cstr);
+ FAIL_RETURN_IF (ACE_OS::strcmp (a[2], elem2_cstr) != 0);
+
+ // reset content of sequence a
+ a[1] = CORBA::string_dup (elem1_cstr);
+
+ // test for loop behaviour
+ ::CORBA::StringSeq b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ std::ostream_iterator<CORBA::StringSeq::const_value_type> (ostream,
+ "\n"));
+
+ // The third sequence element has been modified. Either we need to restore
+ // the original sequence values or modify the test here. I modified the
+ // test since it's easier.
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_sequence_const_iterator ()
+{
+ ::CORBA::StringSeq a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a.length (4);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // I'm not sure non-const deferencing makes sense since
+ // we are getting an r value.
+ const char * value0 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem0_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem0_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem1_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[0]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[2]) != 0);
+
+ // test for loop behaviour
+ ::CORBA::StringSeq b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ std::ostream_iterator<CORBA::StringSeq::const_value_type>(ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_const_sequence ()
+{
+ // setup of an example sequence
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ ::CORBA::StringSeq setup;
+ setup.length (4);
+ setup[0] = CORBA::string_dup (elem0_cstr);
+ setup[1] = CORBA::string_dup (elem1_cstr);
+ setup[2] = CORBA::string_dup (elem2_cstr);
+ setup[3] = CORBA::string_dup (elem3_cstr);
+
+ const ::CORBA::StringSeq a = setup;
+
+ // test equality operator
+ // JWH2 - Below are (failed) attempts to make the compiler happy.
+ // The compiler wants to construct a UBS_Sequence_Iterator and
+ // complains about the constructor being passed a const sequence
+ // pointer when it expects a non-const pointer. Why is the compiler
+ // trying to construct a UBS_Sequence_Iterator rather than a
+ // Const_UBS_Sequence_Iterator??
+ //
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+ //ITERATOR_T c_iter1 (a.begin ());
+ //::CORBA::StringSeq::const_iterator c_iter1 (a.begin ());
+ //::TAO::Const_UBS_Sequence_Iterator<TAO::unbounded_basic_string_sequence<char> > c_iter1 = a.begin ();
+ //ITERATOR_T c_iter2 = a.begin ();
+ //FAIL_RETURN_IF (!(c_iter1 == c_iter2));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // JWH2 - I guess this test shouldn't be done since we are dealing with
+ // a const iterator. Is that right?
+ //typename ITERATOR_T::element_type value0 = *a_it;
+ //FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem0_cstr) != 0);
+
+ // test const dereferencing
+ typename ITERATOR_T::const_element_type value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem0_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem1_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem3_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[0]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[2]) != 0);
+
+ // test for loop behaviour
+ const ::CORBA::StringSeq b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ std::ostream_iterator<CORBA::StringSeq::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_sequence_reverse ()
+{
+ ::CORBA::StringSeq a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a.length (4);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+
+ // Create a case to test for memory leaks
+ // in the iterator.
+ *a_it = CORBA::string_dup (elem3_cstr);
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ typename REVERSE_ITERATOR_T::element_type value0 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem3_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem3_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem2_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[3]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[1]) != 0);
+
+ // test operator[] write
+ a_it[0] = CORBA::string_dup (elem0_cstr);
+ FAIL_RETURN_IF (ACE_OS::strcmp (a[1],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ a[1] = CORBA::string_dup (elem1_cstr);
+
+ // test for loop behaviour
+ ::CORBA::StringSeq b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ std::ostream_iterator<CORBA::StringSeq::element_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_sequence_reverse_const_iterator ()
+{
+ ::CORBA::StringSeq a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ a.length (4);
+ a[0] = CORBA::string_dup (elem0_cstr);
+ a[1] = CORBA::string_dup (elem1_cstr);
+ a[2] = CORBA::string_dup (elem2_cstr);
+ a[3] = CORBA::string_dup (elem3_cstr);
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ typename REVERSE_ITERATOR_T::const_element_type value0 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem3_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem3_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem2_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[3]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[1]) != 0);
+
+ // test for loop behaviour
+ ::CORBA::StringSeq b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ std::ostream_iterator<CORBA::StringSeq::element_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_const_sequence_reverse ()
+{
+ // setup of an example sequence
+ const char * elem0_cstr = "elem0";
+ const char * elem1_cstr = "elem1";
+ const char * elem2_cstr = "elem2";
+ const char * elem3_cstr = "elem3";
+
+ ::CORBA::StringSeq setup;;
+ setup.length (4);
+ setup[0] = CORBA::string_dup (elem0_cstr);
+ setup[1] = CORBA::string_dup (elem1_cstr);
+ setup[2] = CORBA::string_dup (elem2_cstr);
+ setup[3] = CORBA::string_dup (elem3_cstr);
+
+ const ::CORBA::StringSeq a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ typename REVERSE_ITERATOR_T::const_element_type value0 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value0, elem3_cstr) != 0);
+
+ // test const dereferencing
+ const char* const value1 = *a_it;
+ FAIL_RETURN_IF (ACE_OS::strcmp (value1, elem3_cstr) != 0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem2_cstr) != 0);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, elem0_cstr) != 0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[3]) != 0);
+ a_it += 2;
+ FAIL_RETURN_IF (ACE_OS::strcmp (a_it[0],a[1]) != 0);
+
+ // test for loop behaviour
+ ::CORBA::StringSeq b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*a_it, *b_it) != 0);
+ }
+
+ ::CORBA::StringSeq test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (ACE_OS::strcmp (*copya_iter, *copytest_iter) != 0);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ std::ostream_iterator<CORBA::StringSeq::const_element_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+int ACE_TMAIN(int,ACE_TCHAR*[])
+{
+ int status = 0;
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ // Test Generic_Sequence_Iterator.
+ status += test_sequence< ::CORBA::StringSeq::iterator> ();
+
+#ifndef ACE_WIN32
+ // g++ seems to make the conversion from iterator to const_iterator
+ // and Windows doesn't. Not sure why.
+ // Test Const_Generic_Sequence_Iterator with non-const sequence.
+ status += test_sequence_const_iterator <
+ ::CORBA::StringSeq::const_iterator> ();
+#endif
+
+ // Test Const_Generic_Sequence_Iterator with const sequence.
+ status += test_const_sequence< ::CORBA::StringSeq::const_iterator> ();
+
+ // Test Generic_Sequence_Reverse_Iterator.
+ status += test_sequence_reverse< ::CORBA::StringSeq::reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with non-const sequence.
+ status += test_sequence_reverse_const_iterator<
+ ::CORBA::StringSeq::const_reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with const sequence.
+ status += test_const_sequence_reverse<
+ ::CORBA::StringSeq::const_reverse_iterator> ();
+#endif
+
+ return status;
+}
diff --git a/TAO/tests/Sequence_Iterators/Unbounded_Objectref.cpp b/TAO/tests/Sequence_Iterators/Unbounded_Objectref.cpp
new file mode 100644
index 00000000000..06b45ff5e60
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/Unbounded_Objectref.cpp
@@ -0,0 +1,676 @@
+/**
+ * @file Unbounded_Objectref.cpp
+ *
+ * @brief test for STL iterator behaviour of CORBA unbounded object reference
+ * sequence
+ *
+ * $Id$
+ *
+ * @author Friedhelm Wolf (fwolf@dre.vanderbilt.edu)
+ */
+
+#include "ace/Log_Msg.h"
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+#include "tao/Object_Reference_Traits_T.h"
+#include "mock_reference.hpp"
+#include "tao/Unbounded_Object_Reference_Sequence_T.h"
+
+#define FAIL_RETURN_IF(CONDITION) \
+ if (CONDITION) \
+ { \
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("\tFailed at %N:%l\n"))); \
+ return 1; \
+ }
+
+typedef TAO::unbounded_object_reference_sequence<mock_reference, mock_reference_var> tested_sequence;
+
+template <typename ITERATOR_T>
+int test_sequence ()
+{
+ tested_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ mock_reference* elem0 = mock_reference::allocate (0);
+ mock_reference* elem1 = mock_reference::allocate (1);
+ mock_reference* elem2 = mock_reference::allocate (2);
+ mock_reference* elem3 = mock_reference::allocate (3);
+
+ // setup of an example sequence
+ a.length (4);
+
+ a[0] = elem0;
+ a[1] = elem1;
+ a[2] = elem2;
+ a[3] = elem3;
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ mock_reference* value0 = *a_it;
+ FAIL_RETURN_IF (value0->id () != elem0->id ());
+
+ // test const dereferencing
+ const mock_reference* const value1 = *a_it;
+ FAIL_RETURN_IF (value1->id () != elem0->id ());
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF ((*a_it)->id () != elem1->id ());
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem3->id ());
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem3->id ());
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it[0]->id () != a[0]->id ());
+ a_it += 2;
+ FAIL_RETURN_IF (a_it[0]->id () != a[2]->id ());
+
+ // test for loop behaviour
+ tested_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF ((*a_it)->id () != (*b_it)->id ());
+ }
+
+ tested_sequence test;
+ test.length (a.length ());
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF ((*copya_iter)->id () != (*copytest_iter)->id ());
+ }
+
+ /// Testing - using ostream_iterator
+ /// JWH2 - I don't think the ostream test makes sense for object references.
+ /*
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ std::ostream_iterator<tested_sequence::value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+ */
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_const_sequence ()
+{
+ // setup of an example sequence
+ tested_sequence setup;
+ setup.length (4);
+
+ mock_reference* elem0 = mock_reference::allocate (0);
+ mock_reference* elem1 = mock_reference::allocate (1);
+ mock_reference* elem2 = mock_reference::allocate (2);
+ mock_reference* elem3 = mock_reference::allocate (3);
+
+ // setup of an example sequence
+ setup[0] = elem0;
+ setup[1] = elem1;
+ setup[2] = elem2;
+ setup[3] = elem3;
+
+ const tested_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ mock_reference* value0 = *a_it;
+ FAIL_RETURN_IF (value0->id () != elem0->id ());
+
+ // test const dereferencing
+ const mock_reference* const value1 = *a_it;
+ FAIL_RETURN_IF (value1->id () != elem0->id ());
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF ((*a_it)->id () != elem1->id ());
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem3->id ());
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem3->id ());
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF ((a_it[0])->id () != a[0]->id ());
+ a_it += 2;
+ FAIL_RETURN_IF ((a_it[0])->id () != a[2]->id ());
+
+ // test for loop behaviour
+ tested_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF ((*a_it)->id () != (*b_it)->id ());
+ }
+
+ tested_sequence test;
+ test.length (4);
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ /*
+ * The copy call below causes double deletes and seg faults.
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF ((*copya_iter)->id () != (*copytest_iter)->id ());
+ }
+ */
+
+ /// Testing - using ostream_iterator
+ /// JWH2 - I don't think the ostream test makes sense for object references.
+ /*
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ std::ostream_iterator<tested_sequence::value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem0\nelem1\nelem2\nelem3\n") != 0);
+ */
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_sequence_reverse ()
+{
+ tested_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+ a.length (4);
+
+ mock_reference* elem0 = mock_reference::allocate (0);
+ mock_reference* elem1 = mock_reference::allocate (1);
+ mock_reference* elem2 = mock_reference::allocate (2);
+ mock_reference* elem3 = mock_reference::allocate (3);
+
+ // setup of an example sequence
+ a.length (4);
+ a[0] = elem0;
+ a[1] = elem1;
+ a[2] = elem2;
+ a[3] = elem3;
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ mock_reference* value0 = *a_it;
+ FAIL_RETURN_IF (value0->id () != elem3->id ());
+
+ // test const dereferencing
+ const mock_reference* const value1 = *a_it;
+ FAIL_RETURN_IF (value1->id () != elem3->id ());
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF ((*a_it)->id () != elem2->id ());
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem0->id ());
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem0->id ());
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF ((a_it[0])->id () != a[3]->id ());
+ a_it += 2;
+ FAIL_RETURN_IF ((a_it[0])->id () != a[1]->id ());
+
+ // test for loop behaviour
+ tested_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF ((*a_it)->id () != (*b_it)->id ());
+ }
+
+ tested_sequence test;
+ test.length (a.length ());
+
+ // Memory is leaked here from
+ // TAO::details::string_traits_base<char>::default_initializer()
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF ((*copya_iter)->id () != (*copytest_iter)->id ());
+ }
+
+ /// Testing - using ostream_iterator
+ /// JWH2 - I don't think the ostream test makes sense for object references.
+ /*
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ std::ostream_iterator<tested_sequence::value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+ */
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_const_sequence_reverse ()
+{
+ // setup of an example sequence
+ tested_sequence setup;
+ setup.length (4);
+
+ mock_reference* elem0 = mock_reference::allocate (0);
+ mock_reference* elem1 = mock_reference::allocate (1);
+ mock_reference* elem2 = mock_reference::allocate (2);
+ mock_reference* elem3 = mock_reference::allocate (3);
+
+ // setup of an example sequence
+ setup[0] = elem0;
+ setup[1] = elem1;
+ setup[2] = elem2;
+ setup[3] = elem3;
+
+ const tested_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ mock_reference* value0 = *a_it;
+ FAIL_RETURN_IF (value0->id () != elem3->id ());
+
+ // test const dereferencing
+ const mock_reference* const value1 = *a_it;
+ FAIL_RETURN_IF (value1->id () != elem3->id ());
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF ((*a_it)->id () != elem2->id ());
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem0->id ());
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF ((*a_it)->id () != elem0->id ());
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF ((a_it[0])->id () != a[3]->id ());
+ a_it += 2;
+ FAIL_RETURN_IF ((a_it[0])->id () != a[1]->id ());
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // this is not possible for const iterators
+ // a_it[0] = CORBA::string_dup (elem0_cstr);
+ // FAIL_RETURN_IF (ACE_OS::strcmp (a[1],elem0_cstr) != 0);
+
+ // reset content of sequence a
+ //a[1] = CORBA::string_dup (elem1_cstr);
+
+ // test for loop behaviour
+ tested_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF ((*a_it)->id () != (*b_it)->id ());
+ }
+
+ tested_sequence test;
+ test.length (a.length ());
+
+ /*
+ * The copy call below causes double deletes and seg faults.
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF ((*copya_iter)->id () != (*copytest_iter)->id ());
+ }
+ */
+
+ /// Testing - using ostream_iterator
+ /// JWH2 - I don't think the ostream test makes sense for object references.
+ /*
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ std::ostream_iterator<tested_sequence::value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("elem3\nelem2\nelem1\nelem0\n") != 0);
+ */
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+int ACE_TMAIN(int,ACE_TCHAR*[])
+{
+ int status = 0;
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ // Test Generic_Sequence_Iterator.
+ status += test_sequence< tested_sequence::iterator> ();
+
+#ifndef ACE_WIN32
+ // g++ seems to make the conversion from iterator to const_iterator
+ // and Windows doesn't. Not sure why.
+ // Test Const_Generic_Sequence_Iterator with non-const sequence.
+ status += test_sequence< tested_sequence::const_iterator> ();
+#endif
+
+ // Test Const_Generic_Sequence_Iterator with const sequence.
+ status += test_const_sequence< tested_sequence::const_iterator> ();
+
+ // Test Generic_Sequence_Reverse_Iterator.
+ status += test_sequence_reverse< tested_sequence::reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with non-const sequence.
+ status += test_sequence_reverse< tested_sequence::const_reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with const sequence.
+ status += test_const_sequence_reverse< tested_sequence::const_reverse_iterator> ();
+
+#endif /* TAO_HAS_SEQUENCE_ITERATORS == 1 */
+
+ return status;
+}
diff --git a/TAO/tests/Sequence_Iterators/Unbounded_Value.cpp b/TAO/tests/Sequence_Iterators/Unbounded_Value.cpp
new file mode 100644
index 00000000000..e9ec297e9d8
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/Unbounded_Value.cpp
@@ -0,0 +1,690 @@
+/**
+ * @file Unbounded_String.cpp
+ *
+ * @brief test for STL iterator behaviour of CORBA bounded string sequence
+ *
+ * $Id$
+ *
+ * @author Friedhelm Wolf (fwolf@dre.vanderbilt.edu)
+ */
+
+#include <tao/Unbounded_Value_Sequence_T.h>
+#include "ace/Log_Msg.h"
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+typedef TAO::unbounded_value_sequence<int> v_sequence;
+
+#define FAIL_RETURN_IF(CONDITION) \
+ if (CONDITION) \
+ { \
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("\tFailed at %N:%l\n"))); \
+ return 1; \
+ }
+
+template <typename ITERATOR_T>
+int test_sequence ()
+{
+ v_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+ a.length (4);
+
+ int elem0 = 0;
+ int elem1 = 1;
+ int elem2 = 2;
+ int elem3 = 3;
+
+ a[0] = elem0;
+ a[1] = elem1;
+ a[2] = elem2;
+ a[3] = elem3;
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //int value0 = *a_it;
+ //FAIL_RETURN_IF (value0 != elem0);
+
+ // test const dereferencing
+ int value1 = *a_it;
+ FAIL_RETURN_IF (value1 != elem0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (*a_it != elem1);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem3);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem3);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it[0] != a[0]);
+ a_it += 2;
+ FAIL_RETURN_IF (a_it[0] != a[2]);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // NOTE: This does not work for const_iterators
+ // a_it[0] = elem0;
+ // FAIL_RETURN_IF (a[2] != elem0);
+
+ // reset content of sequence a
+ //a[2] = elem2;
+
+ // test for loop behaviour
+ v_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (*a_it != *b_it);
+ }
+
+ v_sequence test;
+ test.length (4);
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (*copya_iter != *copytest_iter);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<v_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("0\n1\n2\n3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename ITERATOR_T>
+int test_const_sequence ()
+{
+ // setup of an example sequence
+ v_sequence setup;
+ setup.length (4);
+
+ int elem0 = 0;
+ int elem1 = 1;
+ int elem2 = 2;
+ int elem3 = 3;
+
+ setup[0] = elem0;
+ setup[1] = elem1;
+ setup[2] = elem2;
+ setup[3] = elem3;
+
+ const v_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ ITERATOR_T a_it (a.begin ());
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test assignment operator
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it != a.begin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //char* value0 = *a_it;
+ //FAIL_RETURN_IF (value0 != elem0);
+
+ // test const dereferencing
+ int value1 = *a_it;
+ FAIL_RETURN_IF (value1 != elem0);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.begin());
+ FAIL_RETURN_IF (*a_it != elem1);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.begin () < a_it));
+ FAIL_RETURN_IF (a_it < a.begin ());
+
+ // test difference type
+ int a_diff = a_it - a.begin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.end ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem3);
+
+ // test pre-decrement operator
+ a_it = a.end ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.end ());
+ FAIL_RETURN_IF ((a.end () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem3);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.begin ();
+ FAIL_RETURN_IF (a_it[0] != a[0]);
+ a_it += 2;
+ FAIL_RETURN_IF (a_it[0] != a[2]);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // NOTE: This does not work for const_iterators
+ // a_it[0] = elem0;
+ // FAIL_RETURN_IF (a[2] != elem0);
+
+ // reset content of sequence a
+ //a[2] = elem2;
+
+ // test for loop behaviour
+ v_sequence b = a;
+ ITERATOR_T b_it = b.begin ();
+
+ for (a_it = a.begin ();
+ a_it != a.end ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (*a_it != *b_it);
+ }
+
+ v_sequence test;
+ test.length (4);
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ ITERATOR_T copytest_iter = test.begin ();
+ for (ITERATOR_T copya_iter = a.begin ();
+ copya_iter != a.end ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (*copya_iter != *copytest_iter);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.begin (),
+ a.end (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<v_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("0\n1\n2\n3\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_sequence_reverse ()
+{
+ v_sequence a;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test for correct behaviour for empty sequence
+
+ FAIL_RETURN_IF (a.begin() != a.end ());
+
+ // setup of an example sequence
+ a.length (4);
+
+ int elem0 = 0;
+ int elem1 = 1;
+ int elem2 = 2;
+ int elem3 = 3;
+
+ a[0] = elem0;
+ a[1] = elem1;
+ a[2] = elem2;
+ a[3] = elem3;
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //int value0 = *a_it;
+ //FAIL_RETURN_IF (value0 != elem3);
+
+ // test const dereferencing
+ int value1 = *a_it;
+ FAIL_RETURN_IF (value1 != elem3);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (*a_it != elem2);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it[0] != a[3]);
+ a_it += 2;
+ FAIL_RETURN_IF (a_it[0] != a[1]);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // this is not possible for const iterators
+ // a_it[0] = elem0;
+ // FAIL_RETURN_IF (a[1] != elem0);
+
+ // reset content of sequence a
+ //a[1] = elem1;
+
+ // test for loop behaviour
+ v_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (*a_it != *b_it);
+ }
+
+ v_sequence test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (*copya_iter != *copytest_iter);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<v_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("3\n2\n1\n0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename REVERSE_ITERATOR_T>
+int test_const_sequence_reverse ()
+{
+ // setup of an example sequence
+ v_sequence setup;
+ setup.length (4);
+
+ int elem0 = 0;
+ int elem1 = 1;
+ int elem2 = 2;
+ int elem3 = 3;
+
+ setup[0] = elem0;
+ setup[1] = elem1;
+ setup[2] = elem2;
+ setup[3] = elem3;
+
+ const v_sequence a = setup;
+
+ // test equality operator
+ FAIL_RETURN_IF (!(a.begin () == a.begin ()));
+
+ // test non-equality operator
+ FAIL_RETURN_IF (a.end () != a.end ());
+
+ // test iterator copy constructor
+ REVERSE_ITERATOR_T a_it (a.rbegin ());
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test assignment operator
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it != a.rbegin ());
+
+ // test non const dereferencing
+ // JWH2 - I don't think this test makes sense. I believe the compiler
+ // will always return a const value since the dereference is on
+ // the right hand side of the assignment (i.e., r value).
+ //int value0 = *a_it;
+ //FAIL_RETURN_IF (value0 != elem3);
+
+ // test const dereferencing
+ int value1 = *a_it;
+ FAIL_RETURN_IF (value1 != elem3);
+
+ // test increment operation
+ a_it++;
+ FAIL_RETURN_IF (a_it == a.rbegin());
+ FAIL_RETURN_IF (*a_it != elem2);
+
+ // test < operator
+ FAIL_RETURN_IF (!(a.rbegin () < a_it));
+ FAIL_RETURN_IF (a_it < a.rbegin ());
+
+ // test difference type
+ int a_diff = a_it - a.rbegin ();
+ FAIL_RETURN_IF (a_diff != 1);
+
+ // test copy constructor
+ REVERSE_ITERATOR_T a_it1 (a_it);
+ FAIL_RETURN_IF (a_it1 != a_it);
+
+ // test preincrement operator
+ ++a_it1;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 1);
+
+ // test = and += operator
+ REVERSE_ITERATOR_T a_it2 = a_it += 3;
+ FAIL_RETURN_IF (a_it2 != a_it);
+ FAIL_RETURN_IF ((a_it - a_it1) != 2);
+
+ // test + operator
+ a_it2 = a_it1 + 3;
+ FAIL_RETURN_IF ((a_it2 - a_it1) != 3);
+
+ // test post-decrement operation
+ a_it = a.rend ();
+ a_it--;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem0);
+
+ // test pre-decrement operator
+ a_it = a.rend ();
+ --a_it;
+ FAIL_RETURN_IF (a_it == a.rend ());
+ FAIL_RETURN_IF ((a.rend () - a_it) != 1);
+ FAIL_RETURN_IF (*a_it != elem0);
+
+ // test -= operator
+ a_it -= 3;
+ FAIL_RETURN_IF ((a_it1 - a_it) != 2);
+
+ // test - operator
+ a_it2 = a_it1 - 2;
+ FAIL_RETURN_IF ((a_it1 - a_it2) != 2);
+
+ // test operator[] read
+ a_it = a.rbegin ();
+ FAIL_RETURN_IF (a_it[0] != a[3]);
+ a_it += 2;
+ FAIL_RETURN_IF (a_it[0] != a[1]);
+
+ // test operator[] write
+ // NOTE: This now changes the sequence a.
+ // this is not possible for const iterators
+ // a_it[0] = elem0;
+ // FAIL_RETURN_IF (a[1] != elem0);
+
+ // reset content of sequence a
+ //a[1] = elem1;
+
+ // test for loop behaviour
+ v_sequence b = a;
+ REVERSE_ITERATOR_T b_it = b.rbegin ();
+
+ for (a_it = a.rbegin ();
+ a_it != a.rend ();
+ a_it++, b_it++)
+ {
+ FAIL_RETURN_IF (*a_it != *b_it);
+ }
+
+ v_sequence test;
+ test.length (a.length ());
+
+ std::copy (a.begin (),
+ a.end (),
+ test.begin ());
+
+ FAIL_RETURN_IF (test.length () != a.length ());
+
+ REVERSE_ITERATOR_T copytest_iter = test.rbegin ();
+ for (REVERSE_ITERATOR_T copya_iter = a.rbegin ();
+ copya_iter != a.rend ();
+ ++copya_iter, ++copytest_iter)
+ {
+ FAIL_RETURN_IF (*copya_iter != *copytest_iter);
+ }
+
+ /// Testing - using ostream_iterator
+
+ std::ostringstream ostream;
+ std::copy (a.rbegin (),
+ a.rend (),
+ // JWH2 - I changed value_type to const_value_type. Is that
+ // the correct approach?
+ std::ostream_iterator<v_sequence::const_value_type> (ostream,
+ "\n"));
+
+ FAIL_RETURN_IF (
+ ostream.str ().compare ("3\n2\n1\n0\n") != 0);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+int ACE_TMAIN(int,ACE_TCHAR*[])
+{
+ int status = 0;
+
+#if defined TAO_HAS_SEQUENCE_ITERATORS && TAO_HAS_SEQUENCE_ITERATORS == 1
+
+ // Test Generic_Sequence_Iterator.
+ status += test_sequence<v_sequence::iterator> ();
+
+#ifndef ACE_WIN32
+ // g++ seems to make the conversion from iterator to const_iterator
+ // and Windows doesn't. Not sure why.
+ // Test Const_Generic_Sequence_Iterator with non-const sequence.
+ status += test_sequence<v_sequence::const_iterator> ();
+#endif
+
+ // Test Const_Generic_Sequence_Iterator with const sequence.
+ status += test_const_sequence<v_sequence::const_iterator> ();
+
+ // Test Generic_Sequence_Reverse_Iterator.
+ status += test_sequence_reverse<v_sequence::reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with non-const sequence.
+ status += test_sequence_reverse<v_sequence::const_reverse_iterator> ();
+
+ // Test Const_Generic_Sequence_Reverse_Iterator with const sequence.
+ status += test_const_sequence_reverse<v_sequence::const_reverse_iterator> ();
+#endif
+
+ return status;
+}
diff --git a/TAO/tests/Sequence_Iterators/mock_reference.cpp b/TAO/tests/Sequence_Iterators/mock_reference.cpp
new file mode 100644
index 00000000000..a1115c0f094
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/mock_reference.cpp
@@ -0,0 +1,90 @@
+/**
+ * @file
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@atdesk.com>
+ */
+#include "mock_reference.hpp"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+mock_reference::
+~mock_reference()
+{
+}
+
+mock_reference * mock_reference::
+allocate(int id)
+{
+ return new mock_reference(id);
+}
+
+mock_reference * mock_reference::
+_nil()
+{
+ return 0;
+}
+
+mock_reference * mock_reference::
+_duplicate(mock_reference * rhs)
+{
+ if (rhs == 0)
+ {
+ return 0;
+ }
+ return new mock_reference(*rhs);
+}
+
+void mock_reference::
+_tao_release(mock_reference * rhs)
+{
+ delete rhs;
+}
+
+void CORBA::release(mock_reference * r)
+{
+ mock_reference::_tao_release(r);
+}
+
+mock_reference *
+TAO::Objref_Traits<mock_reference>::duplicate (
+ mock_reference_ptr p
+ )
+{
+ return mock_reference::_duplicate (p);
+}
+
+void
+TAO::Objref_Traits<mock_reference>::release (
+ mock_reference_ptr p
+ )
+{
+ CORBA::release (p);
+}
+
+mock_reference_ptr
+TAO::Objref_Traits<mock_reference>::nil (void)
+{
+ return mock_reference::_nil ();
+}
+
+CORBA::Boolean
+TAO::Objref_Traits<mock_reference>::marshal (
+ const mock_reference_ptr,
+ TAO_OutputCDR &
+ )
+{
+ return true;
+}
+
+CORBA::Boolean operator<< (TAO_OutputCDR &, const mock_reference *)
+{
+ return true;
+}
+CORBA::Boolean operator>> (TAO_InputCDR &, mock_reference *&)
+{
+ return true;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/tests/Sequence_Iterators/mock_reference.hpp b/TAO/tests/Sequence_Iterators/mock_reference.hpp
new file mode 100644
index 00000000000..ecac1eb6eb1
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/mock_reference.hpp
@@ -0,0 +1,102 @@
+#ifndef guard_mock_reference_hpp
+#define guard_mock_reference_hpp
+/**
+ * @file
+ *
+ * @brief Mock an object reference so we can test the sequences in
+ * isolation.
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan
+ */
+#include "ace/config-all.h"
+
+#include "tao/Basic_Types.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+// Forward declare the class a CORBA::release function for it. That
+// avoids having to introduce CORBA::Object into the tests.
+// Ideally the T_var and T_out types should accept mock objects
+// too, but that is too much to bite in the current iteration.
+class mock_reference;
+namespace CORBA
+{
+void release(mock_reference*);
+}
+
+class mock_stream;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include "tao/Objref_VarOut_T.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef mock_reference *mock_reference_ptr;
+typedef TAO_Objref_Var_T<mock_reference> mock_reference_var;
+typedef TAO_Objref_Out_T<mock_reference> mock_reference_out;
+
+/**
+ * @class mock_reference
+ *
+ * @brief Implement a concrete class with the right interface for an
+ * object reference.
+ */
+class mock_reference
+{
+public:
+ virtual ~mock_reference();
+
+ typedef mock_reference_var _var_type;
+ typedef mock_reference_out _out_type;
+
+ static mock_reference * allocate(int id);
+ static mock_reference * _nil();
+
+ static mock_reference * _duplicate(mock_reference * rhs);
+ static void _tao_release(mock_reference * rhs);
+
+ inline bool operator==(mock_reference const & rhs) const
+ {
+ return id_ == rhs.id_;
+ }
+
+ inline bool operator!=(mock_reference const & rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ inline int id() const
+ {
+ return id_;
+ }
+
+private:
+ mock_reference ();
+
+ inline mock_reference(int id)
+ : id_(id)
+ {}
+
+private:
+ int id_;
+};
+
+CORBA::Boolean operator<< (TAO_OutputCDR &, const mock_reference *);
+CORBA::Boolean operator>> (TAO_InputCDR &, mock_reference *&);
+
+namespace TAO
+{
+ template<>
+ struct Objref_Traits< mock_reference>
+ {
+ static mock_reference_ptr duplicate (mock_reference_ptr);
+ static void release (mock_reference_ptr);
+ static mock_reference_ptr nil (void);
+ static CORBA::Boolean marshal (const mock_reference_ptr p, TAO_OutputCDR & cdr);
+ };
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+#endif // guard_mock_reference_hpp
diff --git a/TAO/tests/Sequence_Iterators/run_test.pl b/TAO/tests/Sequence_Iterators/run_test.pl
new file mode 100755
index 00000000000..e0c7ed6afcb
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/run_test.pl
@@ -0,0 +1,68 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "$ENV{ACE_ROOT}/bin";
+use PerlACE::Run_Test;
+use strict;
+
+if ($ARGV[0] =~ /^-h/i || $ARGV[0] =~ /^-\?/i) {
+ print "Usage: run_test.pl [-boost|-noboost]\n".
+ "\tDefault is to run all tests, specifying -boost or -noboost will\n".
+ "\teither run the tests that require the boost unit test library or\n".
+ "\tthe other tests, respectively.\n";
+ exit 0;
+}
+
+my $final_result = 0;
+
+my @testsToRun = qw(
+ StringSeq
+ Bounded_String
+ Unbounded_Value
+ Unbounded_Objectref
+ );
+
+foreach my $process (@testsToRun) {
+
+ my $P = 0;
+ if (PerlACE::is_vxworks_test()) {
+ $P = new PerlACE::ProcessVX ($process,
+ '--log_level=nothing '
+ .'--report_level=no');
+ }
+ else {
+ $P = new PerlACE::Process ($process,
+ '--log_level=nothing '
+ .'--report_level=no');
+ }
+ my $executable = $P->Executable;
+
+ # Not all the binaries are generated in all configurations.
+ if (PerlACE::is_vxworks_test()) {
+ next unless -e $executable;
+ }
+ else {
+ next unless -x $executable;
+ }
+
+ print "Running $process ...";
+ my $result = $P->Spawn;
+ if ($result != 0) {
+ print "FAILED\n";
+ $final_result = 1;
+ next;
+ }
+ $result = $P->WaitKill($PerlACE::wait_interval_for_process_creation);
+ if ($result != 0) {
+ print "FAILED\n";
+ $final_result = 1;
+ next;
+ }
+ print "SUCCESS\n";
+}
+
+exit $final_result;
diff --git a/TAO/tests/Sequence_Iterators/testing_counters.hpp b/TAO/tests/Sequence_Iterators/testing_counters.hpp
new file mode 100644
index 00000000000..e5f20bb8ee1
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/testing_counters.hpp
@@ -0,0 +1,106 @@
+#ifndef guard_testing_counters_hpp
+#define guard_testing_counters_hpp
+/**
+ * @file
+ *
+ * @brief Some unit tests need to count how many times a function is
+ * called. Here we implement some simple helper classes for that
+ * purpose.
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan
+ */
+
+#include "testing_exception.hpp"
+
+#include <boost/utility.hpp>
+
+#include <iostream>
+
+/**
+ * @brief Used to count how many times a function gets called. The
+ * unit test should create one instance per function.
+ */
+class call_counter
+{
+public:
+ inline call_counter()
+ : count_(0)
+ , failure_countdown_(0)
+ {}
+
+ inline long current_count() const
+ {
+ return count_;
+ }
+
+ inline void failure_countdown(long countdown)
+ {
+ failure_countdown_ = countdown;
+ }
+
+ inline void operator()()
+ {
+ ++count_;
+ if (--failure_countdown_ == 0)
+ {
+ throw testing_exception();
+ }
+ }
+
+private:
+ long count_;
+ long failure_countdown_;
+};
+
+/**
+ * @brief Used to detect if a testing_counter is "called" the right
+ * number of times.
+ */
+class expected_calls
+ : private boost::noncopyable
+{
+public:
+ inline expected_calls(call_counter const & counter)
+ : current_count_(counter.current_count())
+ , previous_count_(counter.current_count())
+ , counter_(counter)
+ { }
+
+ inline bool expect(long n)
+ {
+ reset();
+ return (previous_count_ + n == current_count_);
+ }
+
+ inline void reset()
+ {
+ previous_count_ = current_count_;
+ current_count_ = counter_.current_count();
+ }
+
+ inline long current_count() const
+ {
+ return current_count_;
+ }
+
+ inline long previous_count() const
+ {
+ return previous_count_;
+ }
+
+private:
+ long current_count_;
+ long previous_count_;
+ call_counter const & counter_;
+};
+
+inline std::ostream & operator<<(std::ostream & os, expected_calls const & x)
+{
+ return os << "current=" << x.current_count()
+ << ",previous=" << x.previous_count();
+
+}
+
+#endif // guard_testing_counters_hpp
diff --git a/TAO/tests/Sequence_Iterators/testing_exception.hpp b/TAO/tests/Sequence_Iterators/testing_exception.hpp
new file mode 100644
index 00000000000..2fc4c540197
--- /dev/null
+++ b/TAO/tests/Sequence_Iterators/testing_exception.hpp
@@ -0,0 +1,15 @@
+#ifndef guard_testing_exception_hpp
+#define guard_testing_exception_hpp
+/**
+ * @file
+ *
+ * @brief Simple exception to raise in the tests.
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan
+ */
+
+struct testing_exception {};
+
+#endif // guard_testing_exception_hpp