// bslstl_treeiterator.h                                              -*-C++-*-
#ifndef INCLUDED_BSLSTL_TREEITERATOR
#define INCLUDED_BSLSTL_TREEITERATOR

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide an STL compliant iterator for a tree of 'TreeNode' objects.
//
//@CLASSES:
//   bslstl::TreeIterator: an STL compliant bidirectional binary tree iterator
//
//@SEE_ALSO: bslstl_treenode, bslalg_rbtreeutil, bslstl_map
//
//@DESCRIPTION: This component provides an STL-compliant bidirectional iterator
// over a binary tree of 'bslstl::TreeNode' objects.  The requirements of a
// bidirectional STL iterator are outlined in the C++11 standard in section
// [24.2.6] under the tag [bidirectional.iterators].  A 'TreeIterator' object
// is parameterized on 'VALUE', 'NODE', and 'DIFFERENCE_TYPE'.  The
// parameterized 'VALUE' indicates the type of the value value to which this
// iterator provides a references, and may be const-qualified for
// const-iterators.  The parameterized 'NODE' indicates the type of the node
// objects in this tree.  Note that 'NODE' is not necessarily 'TreeNode<VALUE>'
// as 'VALUE' may be const-qualified.  Finally, the parameterized
// 'DIFFERENCE_TYPE' determines the, standard required, 'difference_type' for
// the iterator.  'NODE' must derives from 'bslalg::RbTreeNode', and contains a
// 'value' method that returns a reference providing modifiable access to a
// type that is convertible to the parameterized 'VALUE' (e.g., a
// 'bslstl::TreeNode' object).
//
///Usage
///-----
// In this section we show intended use of this component.
//
///Example 1: Navigating a Tree Using 'TreeIterator'
///- - - - - - - - - - - - - - - - - - - - - - - - -
// In the following example we create a simple tree and then use a
// 'TreeIterator' to navigate its elements.
//
// First, we define a type 'IntNode' for the nodes of our tree.  'IntNode'
// inherits from 'bslalg::RbTreeNode' (allowing it to be operated on by
// 'bslalg::RbTreeUtil'), and supplies an integer payload:
//..
//  class IntNode : public bslalg::RbTreeNode {
//      // DATA
//      int d_value;  // actual value represented by the node
//
//    public:
//      // MANIPULATORS
//  int& value() { return d_value; }
//      // Return a reference providing modifiable access to the 'value' of
//      // this object.
//
//  // ACCESSORS
//  const int& value() const { return d_value; }
//      // Return a reference providing non-modifiable access to the
//      // 'value' of this object.
//  };
//..
// Then, we define a comparison function for 'IntNode' objects.  This type is
// designed to be supplied to functions in 'bslalg::RbTreeUtil':
//..
//  class IntNodeComparator {
//    public:
//      // CREATORS
//      IntNodeComparator() {}
//          // Create a node-value comparator.
//
//      // ACCESSORS
//      bool operator()(const bslalg::RbTreeNode& node, int value) const {
//          return static_cast<const IntNode&>(node).value() < value;
//      }
//
//      bool operator()(int value, const bslalg::RbTreeNode& node) const {
//         return value < static_cast<const IntNode&>(node).value();
//      }
//  };
//..
// Next, we define the signature of the example function where we will
// navigate a tree using a 'TreeIterator':
//..
//  void exampleTreeNavigationFunction()
//  {
//..
// Then, we define a 'bslalg::RbTreeAnchor' object to hold our tree, and a
// series of nodes that we will use to populate the tree:
//..
//      enum { NUM_NODES = 5 };
//
//      bslalg::RbTreeAnchor tree;
//      IntNode              nodes[NUM_NODES];
//..
// Next, we assign values to each of the 'nodes' and insert them into 'tree'
// using 'bslalg::RbTreeUtil', supplying the 'insert' function an instance of
// the comparator we defined earlier:
//..
//      for (int i = 0; i < NUM_NODES; ++i) {
//          nodes[i].value() = i;
//          bslalg::RbTreeUtil::insert(&tree, IntNodeComparator(), &nodes[i]);
//      }
//
//      assert(5 == tree.numNodes());
//..
// Then, we create a type alias for a 'TreeIterator' providing non-modifiable
// access to elements in the tree.  Note that in this instance, the iterator
// must provide non-modifiable access as modifying the key value for a node
// would invalidate ordering of the binary search tree:
//..
//      typedef TreeIterator<const int, IntNode, std::ptrdiff_t>
//                                                           ConstTreeIterator;
//..
// Now, we create an instance of the 'TreeIterator' and use it to navigate the
// elements of 'tree', printing their values to the console:
//..
//      ConstTreeIterator iterator(tree.firstNode());
//      ConstTreeIterator endIterator(tree.sentinel());
//      for (; iterator != endIterator; ++iterator) {
//          printf("Node value: %d\n", *iterator);
//      }
//  }
//..
// Finally, we observe the following console output:
//..
//  Node value: 0
//  Node value: 1
//  Node value: 2
//  Node value: 3
//  Node value: 4
//..

#include <bslscm_version.h>

#include <bslstl_iterator.h>

#include <bslalg_rbtreenode.h>
#include <bslalg_rbtreeutil.h>

#include <bslmf_enableif.h>
#include <bslmf_isconvertible.h>
#include <bslmf_issame.h>
#include <bslmf_istriviallycopyable.h>
#include <bslmf_removecv.h>

#include <bsls_assert.h>
#include <bsls_libraryfeatures.h>
#include <bsls_platform.h>
#include <bsls_util.h>

#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
#include <bslmf_removecvq.h>
#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDE

namespace BloombergLP {
namespace bslstl {

                     // ==================
                     // class TreeIterator
                     // ==================

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
class TreeIterator
#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
    : public std::iterator<std::bidirectional_iterator_tag, VALUE>
// On Solaris just to keep studio12-v4 happy, since algorithms takes only
// iterators inheriting from 'std::iterator'.
#endif
{
    // This class provides an STL-conforming bidirectional iterator over the
    // ordered 'bslalg::RbTreeNode' objects in a binary tree (see section
    // [24.2.6 bidirectional.iterators] of the C++11 standard).  A
    // 'TreeIterator' provides access to values of the parameterized 'VALUE',
    // over a binary tree composed of nodes of the parameterized 'NODE' (which
    // must derive from 'bslalg::RbTreeNode').  The parameterized
    // 'DIFFERENCE_TYPE' determines the standard required 'difference_type' of
    // the iterator, without requiring access to the allocator-traits for the
    // node.  The behavior of the 'operator*' method is undefined unless the
    // iterator is at a valid position in the tree (i.e., not the 'end') and
    // the referenced element has not been removed since the iterator was
    // constructed.  'NODE' must derives from 'bslalg::RbTreeNode', and
    // contains a 'value' method that returns a reference providing modifiable
    // access to a type that is convertible to the parameterized 'VALUE' (e.g.,
    // a 'bslstl::TreeNode' object).

    // PRIVATE TYPES
    typedef typename bsl::remove_cv<VALUE>::type        NcType;
    typedef TreeIterator<NcType, NODE, DIFFERENCE_TYPE> NcIter;

    // DATA
    bslalg::RbTreeNode *d_node_p;  // current iterator position

  private:
    // FRIENDS
    template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
    friend bool operator==(const TreeIterator<VALUE1, NODEPTR, DIFF>&,
                           const TreeIterator<VALUE2, NODEPTR, DIFF>&);
    template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
    friend bool operator!=(const TreeIterator<VALUE1, NODEPTR, DIFF>&,
                           const TreeIterator<VALUE2, NODEPTR, DIFF>&);

    template <class OTHER_VALUE, class OTHER_NODE, class OTHER_DIFFERENCE_TYPE>
    friend class TreeIterator;

  public:
    // PUBLIC TYPES
    typedef bsl::bidirectional_iterator_tag iterator_category;
    typedef NcType                          value_type;
    typedef DIFFERENCE_TYPE                 difference_type;
    typedef VALUE*                          pointer;
    typedef VALUE&                          reference;
        // Standard iterator defined types [24.4.2].

    // CREATORS
    TreeIterator();
        // Create an uninitialized iterator.

    explicit TreeIterator(const bslalg::RbTreeNode *node);
        // Create an iterator at the specified 'position'.  The behavior is
        // undefined unless 'node' is of the parameterized 'NODE', which is
        // derived from 'bslalg::RbTreeNode.  Note that this constructor is an
        // implementation detail and is not part of the C++ standard.

#ifndef BSLS_PLATFORM_CMP_SUN
    template <class NON_CONST_ITERATOR>
    TreeIterator(
           const NON_CONST_ITERATOR& original,
           typename bsl::enable_if<bsl::is_convertible<NON_CONST_ITERATOR,
                                                       NcIter>::value,
                                   int>::type = 0)
        // Create an iterator at the same position as the specified 'original'
        // iterator.  Note that this constructor enables converting from
        // modifiable to const iterator types.
        : d_node_p(static_cast<const NcIter&>(original).d_node_p)
        {
            // This constructor template must be defined inline inside the
            // class definition, as Microsoft Visual C++ does not recognize the
            // definition as matching this signature when placed out-of-line.
        }
#else
    TreeIterator(const NcIter& original)
        // Create an iterator at the same position as the specified 'original'
        // iterator.  Note that this constructor enables converting from
        // modifiable to const iterator types.
        : d_node_p(original.d_node_p)
        {
        }

#endif

    //! TreeIterator(const TreeIterator& original) = default;
        // Create an iterator having the same value as the specified
        // 'original'.  Note that this operation is either defined by the
        // constructor taking 'NcIter' (if 'NcType' is the same as 'VALUE'), or
        // generated automatically by the compiler.  Also note that this
        // construct cannot be defined explicitly (without using
        // 'bsls_enableif') to avoid a duplicate declaration when 'NcType' is
        // the same as 'VALUE'.

    //! ~TreeIterator() = default;
        // Destroy this object.

    // MANIPULATORS
    //! TreeIterator& operator=(const TreeIterator& rhs) = default;
        // Assign to this object the value of the specified 'rhs' object, and
        // a return a reference providing modifiable access to this object.

    TreeIterator& operator++();
        // Move this iterator to the next element in the tree and return a
        // reference providing modifiable access to this iterator.  The
        // behavior is undefined unless the iterator refers to an element in
        // the tree.

    TreeIterator& operator--();
        // Move this iterator to the previous element in the tree and return a
        // reference providing modifiable access to this iterator.  The
        // behavior is undefined unless the iterator refers to the past-the-end
        // address or the non-leftmost element in the tree.

    // ACCESSORS
    reference operator*() const;
        // Return a reference providing modifiable access to the value (of the
        // parameterized 'VALUE') of the element at which this iterator is
        // positioned.  The behavior is undefined unless this iterator is at a
        // valid position in the tree.

    pointer operator->() const;
        // Return the address of the value (of the parameterized 'VALUE') of
        // the element at which this iterator is positioned.  The behavior is
        // undefined unless this iterator is at a valid position in the tree.

    const bslalg::RbTreeNode *node() const;
        // Return the address of the non-modifiable tree node at which this
        // iterator is positioned, or 0 if this iterator is not at a valid
        // position in the tree.  Note that this method is an implementation
        // detail and is not part of the C++ standard.
};

// FREE OPERATORS
template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
bool operator==(const TreeIterator<VALUE1, NODEPTR, DIFF>& lhs,
                const TreeIterator<VALUE2, NODEPTR, DIFF>& rhs);
    // Return 'true' if the specified 'lhs' and the specified 'rhs' iterators
    // have the same value and 'false' otherwise.  Two iterators have the same
    // value if they refer to the same position in the same tree, or if both
    // iterators are at an invalid position in the tree (i.e., the 'end' of the
    // tree, or the default constructed value).

template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
bool operator!=(const TreeIterator<VALUE1, NODEPTR, DIFF>& lhs,
                const TreeIterator<VALUE2, NODEPTR, DIFF>& rhs);
    // Return 'true' if the specified 'lhs' and the specified 'rhs' iterators
    // do not have the same value and 'false' otherwise.  Two iterators do not
    // have the same value if they differ in either the tree to which they
    // refer or the position in that tree.


template <class VALUE, class NODE, class DIFFERENCE_TYPE>
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>
operator++(TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>& iter, int);
    // Move the specified 'iter' to the next element in the tree and return the
    // value of 'iter' prior to this call.  The behavior is undefined unless
    // the iterator refers to an element in the tree.

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>
operator--(TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>& iter, int);
    // Move the specified 'iter' to the previous element in the tree and return
    // the value of 'iter' prior to this call.  The behavior is undefined
    // unless the iterator refers to the past-the-end or the non-leftmost
    // element in the tree.

// ============================================================================
//                  TEMPLATE AND INLINE FUNCTION DEFINITIONS
// ============================================================================

                     // ------------------
                     // class TreeIterator
                     // ------------------

// CREATORS
template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::TreeIterator()
: d_node_p(0)
{
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::
TreeIterator(const bslalg::RbTreeNode *node)
: d_node_p(const_cast<bslalg::RbTreeNode *>(node))
{
}

// MANIPULATORS
template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>&
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::operator++()
{
    d_node_p = bslalg::RbTreeUtil::next(d_node_p);
    return *this;
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>&
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::operator--()
{
    d_node_p = bslalg::RbTreeUtil::previous(d_node_p);
    return *this;
}

// ACCESSORS
template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
typename TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::reference
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::operator*() const
{
    BSLS_ASSERT_SAFE(d_node_p);

    return static_cast<NODE *>(d_node_p)->value();
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
typename TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::pointer
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::operator->() const
{
    BSLS_ASSERT_SAFE(d_node_p);

    return bsls::Util::addressOf(static_cast<NODE *>(d_node_p)->value());
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
const bslalg::RbTreeNode*
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>::node() const
{
    return d_node_p;
}

// FREE OPERATORS
template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
inline
bool operator==(const TreeIterator<VALUE1, NODEPTR, DIFF>& lhs,
                const TreeIterator<VALUE2, NODEPTR, DIFF>& rhs)
{
    return lhs.d_node_p == rhs.d_node_p;
}

template <class VALUE1, class VALUE2, class NODEPTR, class DIFF>
inline
bool operator!=(const TreeIterator<VALUE1, NODEPTR, DIFF>& lhs,
                const TreeIterator<VALUE2, NODEPTR, DIFF>& rhs)
{
    return lhs.d_node_p != rhs.d_node_p;
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>
operator++(TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>& iter, int)
{
    TreeIterator<VALUE, NODE, DIFFERENCE_TYPE> temp = iter;
    ++iter;
    return temp;
}

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
inline
TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>
operator--(TreeIterator<VALUE, NODE, DIFFERENCE_TYPE>& iter, int)
{
    TreeIterator<VALUE, NODE, DIFFERENCE_TYPE> temp = iter;
    --iter;
    return temp;
}

}  // close package namespace
}  // close enterprise namespace

#ifndef BSLS_PLATFORM_CMP_SUN
# ifndef BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION
namespace bsl {

template <class VALUE, class NODE, class DIFFERENCE_TYPE>
struct is_trivially_copyable<
              BloombergLP::bslstl::TreeIterator<VALUE, NODE, DIFFERENCE_TYPE> >
    : bsl::true_type {
};

}  // close namespace bsl
# endif // BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION
#endif  // BSLS_PLATFORM_CMP_SUN

#endif

// ----------------------------------------------------------------------------
// Copyright 2019 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------