// bslalg_rbtreeutil.h                                                -*-C++-*-
#ifndef INCLUDED_BSLALG_RBTREEUTIL
#define INCLUDED_BSLALG_RBTREEUTIL

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

//@PURPOSE: Provide a suite of primitive algorithms on red-black trees.
//
//@CLASSES:
//  bslalg::RbTreeUtil: namespace for red-black tree functions
//  bslalg::RbTreeUtilTreeProctor: proctor to manage all nodes in a tree
//
//@SEE_ALSO: bslalg_rbtreenode
//
//@DESCRIPTION: This component provides a variety of algorithms that operate
// on nodes forming a red-black binary search tree.
//
// This implementation is adapted from Cormen, Leiserson, Rivest,
// "Introduction to Algorithms" [MIT Press, 1997].
//
///Summary
///-------
// The following section provides a short synopsis describing observable
// behavior of functions supplied in this component.  See the full
// function-level contract for detailed description.
//
///Navigation
/// - - - - -
// The following algorithms search a tree for a value, or iterate over the
// nodes in a tree:
//..
//  leftmost            Return the leftmost node.
//
//  rightmost           Return the rightmost node.
//
//  next                Return the next node in an in-order traversal.
//
//  previous            Return the previous node in an in-order traversal.
//
//  find                Find the node with the supplied value.
//
//  lowerBound          Find the first node not less-than the supplied value.
//
//  upperBound          Find the first node greater than the supplied value.
//..
//
///Modification
/// - - - - - -
// The following algorithms are used in the process of manipulating the
// structure of a tree:
//..
//  copyTree            Return a deep-copy of the supplied tree.
//
//  deleteTree          Delete all the nodes of the supplied tree.
//
//  findInsertLocation  Find the location where a value may be inserted.
//
//  findUniqueInsertLocation
//                      Find the location where a unique value may be inserted.
//
//  insert              Insert the supplied node into the tree.
//
//  insertAt            Insert the supplied node at the indicated position.
//
//  remove              Remove the supplied node from the tree.
//
//  swap                Swap the contents of two trees.
//..
//
///Utility
///- - - -
// The following algorithms are typically used when implementing higher-level
// algorithms (and are not generally used by clients):
//..
//  isLeftChild         Return 'true' if the supplied node is a left child.
//
//  isRightChild        Return 'true' if the supplied node is a right child.
//
//  rotateLeft          Perform a counter-clockwise rotation on a node.
//
//  rotateRight         Perform a clockwise rotation on a node.
//..
//
///Testing
///- - - -
// The following algorithms are used for testing and debugging, and
// generally should not be used in production code:
//..
//  printTreeStructure  Print, to a file, the structure of the supplied tree.
//
//  validateRbTree      Indicate if a tree is a valid red-black tree.
//
//  isWellFormed        Indicate if the 'RbTreeAnchor' object is well-formed.
//..
//
///Well-Formed 'RbTreeAnchor' Objects
///----------------------------------
// Many of the algorithms defined in this component operate over a complete
// tree of nodes, rather than a (possible) subtree referred to through a
// pointer to a node.  These operations refer to a complete tree through a
// 'RbTreeAnchor' object, which maintains references to the first, root, and
// sentinel nodes for the tree, as well as a count of the number of nodes in
// the tree.  'RbTreeAnchor' objects supplied to 'RbTreeUtil' are frequently
// required to meet a series of constraints that are not enforced by the
// 'RbTreeAnchor' type itself.  An 'RbTreeAnchor' object meeting these
// constraints is said to be "well-formed", and 'RbTreeUtil::isWellFormed'
// will return 'true' for such an object.  A 'RbTreeAnchor' object is
// considered well-formed if all of the following are true:
//
//: 1 The root node refers to a valid red-black tree (see 'validateRbTree').
//:
//: 2 The first node refers to the leftmost node in the tree, or the sentinel
//:   node if the tree is empty.
//:
//: 3 The node count is the number of nodes in the tree (not counting the
//:   sentinel node).
//:
//: 4 The sentinel node refers to the root node as its left child, and the
//:   root node refers to the sentinel as its parent.
//:
//: 5 The root node is either 0 or is colored black.
//
// The manipulation functions of 'RbTreeUtil' guarantee that these properties
// are maintained for any supplied tree.  Note that 'RbTreeUtil::isWellFormed'
// has linear complexity with respect to the number of nodes in the tree, and
// is typically used for debugging and testing purposes only.  Note also that
// the final condition, that the root node be either 0 or colored black, is
// not a canonical requirement of a red-black tree but an additional invariant
// enforced by the methods of 'RbTreeUtil' to simplify the implementations.
//
///The Sentinel Node
///- - - - - - - - -
// The sentinel node is 'RbTreeNode' object (unique to an 'RbTreeAnchor'
// instance) which does not have a value, and provides a fixed end-point for
// navigation over the tree (which is distinct from the 'rightmost' node of
// that tree).  The sentinel node will be returned by 'next' if the supplied
// node is the rightmost node in the tree, as well as by search operations
// when no nodes meet the supplied search-criteria.  In addition, the sentinel
// node may be supplied as a 'hint' to 'findInsertLocation' and
// 'findUniqueInsertLocation', as well as supplied to 'previous' to obtain the
// rightmost node of a (non-empty) tree.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Creating and Using a Tree with 'RbTreeUtil'
/// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates how to create a tree of integers using
// 'RbTreeUtil'.
//
// First, we define a type 'SimpleIntNode' that will represent a nodes in our
// tree of integer values.  'SimpleIntNode' contains an 'int' payload, and
// inherits from 'RbTreeNode', allowing it to be operated on by
// 'RbTreeUtil'.
//..
//  struct SimpleIntNode : public RbTreeNode {
//      int d_value;
//  };
//..
// Then, we define a comparison function for 'SimpleIntNode' objects (note
// that we static-cast 'RBTreeNode' objects to the actual node type,
// 'SimpleIntNode', for comparison purposes):
//..
//  struct SimpleIntNodeValueComparator {
//      // This class defines a comparator providing comparison operations
//      // between 'SimpleIntNode' objects, and 'int' values.
//
//      bool operator()(const RbTreeNode& lhs, int rhs) const
//      {
//          return static_cast<const SimpleIntNode&>(lhs).d_value < rhs;
//      }
//
//      bool operator()(int lhs, const RbTreeNode& rhs) const
//      {
//          return lhs < static_cast<const SimpleIntNode&>(rhs).d_value;
//      }
//  };
//
//..
// Next, we begin to define the example function that will build a tree of
// nodes holding integer values:
//..
//  void createTestTreeExample()
//  {
//..
// Then, within this function, we define a 'RbTreeAnchor' object that will
// hold the root, first, last, and sentinel nodes of tree, as well a count of
// the number of nodes in the tree:
//..
//      RbTreeAnchor tree;
//..
// Next, we define an array of 5 'SimpleIntNode' objects that we will insert
// into the tree; in practice, nodes are more often allocated on the heap (see
// example 2):
//..
//      const int NUM_NODES = 5;
//      SimpleIntNode nodes[NUM_NODES];
//..
// Then, we assign unique values to each of the 'nodes':
//..
//      for (int i = 0; i < NUM_NODES; ++i) {
//          nodes[i].d_value = i;
//      }
//..
// Now, for each node in the tree, we use 'RbTreeUtil' to first find the
// location at which the node should be inserted, and then insert that node
// into the tree:
//..
//      for (int i = 0; i < NUM_NODES; ++i) {
//          int comparisonResult;
//          SimpleIntNodeValueComparator comparator;
//          RbTreeNode *insertLocation = RbTreeUtil::findUniqueInsertLocation(
//                                              &comparisonResult,
//                                              &tree,
//                                              comparator,
//                                              nodes[i].d_value);
//          BSLS_ASSERT(comparisonResult);
//          RbTreeUtil::insertAt(&tree,
//                               insertLocation,
//                               comparisonResult < 0,
//                               &nodes[i]);
//      }
//..
// And verify the resulting 'tree' holds 5 nodes, and the first node has
// the value 0:
//..
//      assert(5 == tree.numNodes());
//      assert(0 == static_cast<SimpleIntNode *>(tree.firstNode())->d_value);
//..
// Finally, we use 'RbTreeUtil' to iterate through the nodes of 'tree', and
// write the value of each node to the console:
//..
//      const RbTreeNode *nodeIterator = tree.firstNode();
//      while (tree.sentinel() != nodeIterator) {
//          printf("Node value: %d\n",
//                 static_cast<const SimpleIntNode *>(nodeIterator)->d_value);
//          nodeIterator = RbTreeUtil::next(nodeIterator);
//      }
//  }
//..
// Notice that each of the 'RbTreeNode' objects must be 'static_cast' to the
// derived type, 'SimpleIntNode', in order to access their values.
//
// The resulting output is displayed on the console:
//..
//  Node value: 0
//  Node value: 1
//  Node value: 2
//  Node value: 3
//  Node value: 4
//..
//
///Example 2: Implementing a Set of Integers
///- - - - - - - - - - - - - - - - - - - - -
// This example demonstrates how to use 'RbTreeUtil' to implement a simple
// container holding a set of (unique) integer values as a red-black binary
// search tree.
//
// Before defining the 'IntSet' class, we need to define a series of
// associated helper types:
//: 1 The node-type, for the nodes in the tree.
//: 2 An iterator, for iterating over nodes in the tree.
//: 3 A comparison functor for comparing nodes and values.
//: 4 A factory for creating and destroying nodes.
//
// First, we define a type, 'IntSet_Node', that will represent the nodes in our
// tree of integer values; it contains an 'int' payload, and inherits from
// 'RbTreeNode', allowing it to be operated on by 'RbTreeUtil' (note that the
// underscore "_" indicates that this type is a private implementation type of
// 'IntSet', and not for use by clients of 'IntSet'):
//..
//  class IntSet_Node : public RbTreeNode {
//      // A red-black tree node containing an integer data-value.
//
//      // 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 iterator over 'IntSet_Node' objects.  We use the 'next'
// function of 'RbTreeUtil' to increment the iterator (note that, for
// simplicity, this iterator is *not* a fully STL compliant iterator
// implementation):
//..
//  class IntSetConstIterator {
//      // This class defines an STL-style iterator over a non-modifiable tree
//      // of 'IntSet_Node' objects.
//
//      // DATA
//      const RbTreeNode *d_node_p;  // current location of this iterator
//
//    public:
//      IntSetConstIterator() : d_node_p(0) {}
//          // Create an iterator that does not refer to a node.
//
//      IntSetConstIterator(const RbTreeNode *node) : d_node_p(node) {}
//          // Create an iterator referring to the specified 'node'.
//
//  //  IntSetConstIterator(const IntSetConstIterator&) = default;
//
//      // MANIPULATOR
//  //  IntSetConstIterator& operator=(const IntSetConstIterator&) = default;
//
//..
// Here, we implement the prefix-increment operator using the 'next' function
// of 'RbTreeUtil:
//..
//      IntSetConstIterator& operator++()
//         // Advance this iterator to the subsequent value it the 'IntSet',
//         // and return a reference providing modifiable access to this
//         // iterator.   The behavior is undefined unless this iterator
//         // refers to a element in an 'IntSet'.
//      {
//          d_node_p = RbTreeUtil::next(d_node_p);
//          return *this;
//      }
//
//      // ACCESSORS
//      const int& operator*() const
//          // Return a reference providing non-modifiable access to the value
//          // referred to by this iterator.
//      {
//          return static_cast<const IntSet_Node *>(d_node_p)->value();
//      }
//
//      const int *operator->() const
//          // Return an address providing non-modifiable access to the value
//          // referred to by this iterator.
//      {
//          return &(static_cast<const IntSet_Node *>(d_node_p)->value());
//      }
//
//      const IntSet_Node *nodePtr() const
//          // Return the address of the non-modifiable int-set node referred
//          // to by this iterator
//      {
//          return static_cast<const IntSet_Node *>(d_node_p);
//      }
//  };
//
//  // FREE OPERATORS
//  bool operator==(const IntSetConstIterator &lhs,
//                  const IntSetConstIterator &rhs)
//      // Return 'true' if the 'lhs' and 'rhs' objects have the same value,
//      // and 'false' otherwise.  Two 'IntSetConstIterator' objects have the
//      // same value if they refer to the same node.
//  {
//      return lhs.nodePtr() == rhs.nodePtr();
//  }
//
//  bool operator!=(const IntSetConstIterator &lhs,
//                  const IntSetConstIterator &rhs)
//      // Return 'true' if the specified 'lhs' and 'rhs' objects do not have
//      // the same value, and 'false' otherwise.  Two 'IntSetConstIterator'
//      // objects do not have the same value if they refer to different nodes.
//  {
//      return lhs.nodePtr() != rhs.nodePtr();
//  }
//..
// Next, we define a comparison functor for 'IntSet_Node' objects, which will
// be supplied to 'RbTreeUtil' functions that must compare nodes with values
// -- i.e., those with a 'NODE_VALUE_COMPARATOR' template parameter (e.g.,
// 'find' and 'findInsertLocation'):
//..
//  struct IntSet_NodeValueComparator {
//      // This class defines a comparator providing comparison operations
//      // between 'IntSet_Node' objects, and 'int' values.
//
//      bool operator()(const RbTreeNode& lhs, int rhs) const
//      {
//          return static_cast<const IntSet_Node&>(lhs).value() < rhs;
//      }
//
//      bool operator()(int lhs, const RbTreeNode& rhs) const
//      {
//          return lhs < static_cast<const IntSet_Node&>(rhs).value();
//      }
//  };
//..
// Notice that we static-cast 'RbTreeNode' objects to the actual node type,
// 'IntSet_Node' for comparison.
//
// Next, we define a factory for creating and destroying 'IntSet_Node'
// objects.  This factory provides the operations 'createNode' and
// 'deleteNode'.  These operations will be used directly by our container
// implementation, and they are also required by 'RbTreeUtil' functions taking
// a 'FACTORY' template parameter (e.g., 'copyTree' and 'deleteTree'):
//..
//  class IntSet_NodeFactory {
//      // This class defines a creator object, that when invoked, creates a
//      // new 'IntSet_Node' (either from a int value, or an existing
//      // 'IntSet_Node' object) using the allocator supplied at construction.
//
//      bslma::Allocator *d_allocator_p;  // allocator, (held, not owned)
//
//    public:
//
//      IntSet_NodeFactory(bslma::Allocator *allocator)
//      : d_allocator_p(allocator)
//      {
//          BSLS_ASSERT_SAFE(allocator);
//      }
//
//      RbTreeNode *createNode(int value) const
//      {
//          IntSet_Node *newNode = new (*d_allocator_p) IntSet_Node;
//          newNode->value() = value;
//          return newNode;
//      }
//
//      RbTreeNode *createNode(const RbTreeNode& node) const
//      {
//          IntSet_Node *newNode = new (*d_allocator_p) IntSet_Node;
//          newNode->value() = static_cast<const IntSet_Node&>(node).value();
//          return newNode;
//      }
//      void deleteNode(RbTreeNode *node) const
//      {
//          d_allocator_p->deleteObject(static_cast<IntSet_Node *>(node));
//      }
//
//      bslma::Allocator *allocator() const
//      {
//          return d_allocator_p;
//      }
//  };
//..
// Then, having defined the requisite helper types, we define the public
// interface for our 'IntSet' type.  Note that for the purposes of
// illustrating the use of 'RbTreeUtil' a number of simplifications have been
// made.  For example, this implementation provides only a minimal set of
// critical operations, and it does not use the empty base-class optimization
// for the comparator, etc.  We define the interface of 'IntSet' as follows:
//..
//  class IntSet {
//      // This class implements a set of (unique) 'int' values.
//
//      // DATA
//      RbTreeAnchor           d_tree;         // root, first, and last tree
//                                             // nodes
//
//      IntSet_NodeValueComparator
//                             d_comparator;   // comparison functor for ints
//
//      IntSet_NodeFactory     d_nodeFactory;  // factory for creating and
//                                             // destroying nodes
//
//      // FRIENDS
//      friend bool operator==(const IntSet& lhs, const IntSet& rhs);
//
//    public:
//      // PUBLIC TYPES
//      typedef IntSetConstIterator const_iterator;
//
//      // CREATORS
//      IntSet(bslma::Allocator *basicAllocator = 0);
//          // Create a empty 'IntSet'.  Optionally specify a 'basicAllocator'
//          // used to supply memory.  If 'basicAllocator' is 0, the currently
//          // installed default allocator is used.
//
//      IntSet(const IntSet& original, bslma::Allocator *basicAllocator = 0);
//          // Create a 'IntSet' object having the same value as the specified
//          // 'original' object.  If 'basicAllocator' is 0, the currently
//          // installed default allocator is used.
//
//      ~IntSet();
//          // Destroy this object.
//
//      // MANIPULATORS
//      IntSet& operator=(const IntSet& rhs);
//          // Assign to this object the value of the specified 'rhs' object,
//          // and return a reference providing modifiable access to this
//          // object.
//
//      const_iterator insert(int value);
//          // If the specified 'value' is not already a member of this set,
//          // insert it into this set, returning an iterator referring to the
//          // newly added value, and return an iterator referring to the
//          // existing instance of 'value' in this set, with no other effect,
//          // otherwise.
//
//      const_iterator erase(const_iterator iterator);
//          // Remove the value referred to by the specified 'iterator' from
//          // this set, and return an iterator referring to the value
//          // subsequent to 'iterator' (prior to its removal).  The behavior
//          // is undefined unless 'iterator' refers to a valid value in this
//          // set.
//
//      void clear();
//          // Remove all the elements from this set.
//
//      void swap(IntSet& other);
//          // Efficiently exchange the value of this object with the value of
//          // the specified 'other' object.
//
//      // ACCESSORS
//      const_iterator begin() const;
//          // Return an iterator referring leftmost node value in this set, or
//          // 'end()' if this set is empty.
//
//      const_iterator end() const;
//          // Return an iterator referring to the value one past the
//          // rightmost value in this set.
//
//      const_iterator find(int value) const;
//          // Return a iterator referring to the specified 'value' in this
//          // set, or 'end()' if 'value' is not a member of this set.
//
//      int size() const;
//          // Return the number of elements in this set.
//  };
//
//  // FREE OPERATORS
//  bool operator==(const IntSet& lhs, const IntSet& rhs);
//      // Return 'true' if the 'lhs' and 'rhs' objects have the same value,
//      // and 'false' otherwise.  Two 'IntSet' objects have the same value if
//      // they contain the same number of elements, and if for each element
//      // in 'lhs' there is a corresponding element in 'rhs' with the same
//      // value.
//
//  bool operator!=(const IntSet& lhs, const IntSet& rhs);
//      // Return 'true' if the specified 'lhs' and 'rhs' objects do not have
//      // the same value, and 'false' otherwise.  Two 'IntSet' objects do not
//      // have the same value if they differ in the number of elements they
//      // contain, or if for any element in 'lhs' there is not a
//      // corresponding element in 'rhs' with the same value.
//..
// Now, we implement the methods of 'IntSet' using 'RbTreeUtil' and the
// helper types we defined earlier:
//..
//  // CREATORS
//  IntSet::IntSet(bslma::Allocator *basicAllocator)
//  : d_tree()
//  , d_comparator()
//  , d_nodeFactory(bslma::Default::allocator(basicAllocator))
//  {
//  }
//
//  IntSet::IntSet(const IntSet& original, bslma::Allocator *basicAllocator)
//  : d_tree()
//  , d_comparator()
//  , d_nodeFactory(bslma::Default::allocator(basicAllocator))
//  {
//      if (original.d_tree.rootNode()) {
//          RbTreeUtil::copyTree(&d_tree, original.d_tree, &d_nodeFactory);
//      }
//  }
//
//  IntSet::~IntSet()
//  {
//      clear();
//  }
//
//  // MANIPULATORS
//  IntSet& IntSet::operator=(const IntSet& rhs)
//  {
//      IntSet temp(rhs, d_nodeFactory.allocator());
//      swap(temp);
//      return *this;
//  }
//
//..
// Here, we implement 'insert' by using the 'RbTreeUtil' algorithms
// 'findUniqueInsertLocation' and 'insertAt':
//..
//  IntSet::const_iterator IntSet::insert(int value)
//  {
//      // To insert a value into the tree, we first find the location where
//      // the node would be added, and whether 'value' is unique.  If 'value'
//      // is not unique we do not want to incur the expense of allocating
//      // memory for a node.
//
//      int comparisonResult;
//      RbTreeNode *insertLocation =
//                    RbTreeUtil::findUniqueInsertLocation(&comparisonResult,
//                                                         &d_tree,
//                                                         d_comparator,
//                                                         value);
//      if (0 == comparisonResult) {
//          // 'value' already exists in 'd_tree'.
//
//          return const_iterator(insertLocation);                    // RETURN
//      }
//
//      // If 'value' is unique, we create a new node and supply it to
//      // 'insertAt', along with the tree location returned by
//      // 'findUniqueInsertLocation'.
//
//      RbTreeNode *newNode = d_nodeFactory.createNode(value);
//      RbTreeUtil::insertAt(&d_tree,
//                           insertLocation,
//                           comparisonResult < 0,
//                           newNode);
//      return const_iterator(newNode);
//  }
//
//  IntSet::const_iterator IntSet::erase(const_iterator iterator)
//  {
//      BSLS_ASSERT(iterator.nodePtr());
//      IntSet_Node *node = const_cast<IntSet_Node *>(iterator.nodePtr());
//
//      // Before removing the node, we first find the subsequent node to which
//      // we will return an iterator.
//
//      RbTreeNode *next = RbTreeUtil::next(node);
//      RbTreeUtil::remove(&d_tree, node);
//      d_nodeFactory.deleteNode(node);
//      return const_iterator(next);
//  }
//
//  void IntSet::clear()
//  {
//      if (d_tree.rootNode()) {
//          RbTreeUtil::deleteTree(&d_tree, &d_nodeFactory);
//      }
//  }
//
//  void IntSet::swap(IntSet& other) {
//      BSLS_ASSERT(d_nodeFactory.allocator() ==
//                  other.d_nodeFactory.allocator());
//      RbTreeUtil::swap(&d_tree, &other.d_tree);
//  }
//
//  // ACCESSORS
//  IntSet::const_iterator IntSet::begin() const
//  {
//      return const_iterator(d_tree.firstNode());
//  }
//
//  IntSet::const_iterator IntSet::end() const
//  {
//      return const_iterator(d_tree.sentinel());
//  }
//
//  IntSet::const_iterator IntSet::find(int value) const
//  {
//      return const_iterator(RbTreeUtil::find(d_tree, d_comparator, value));
//  }
//
//  int IntSet::size() const
//  {
//      return d_tree.numNodes();
//  }
//..
// Finally, we implement the free operators on 'IntSet':
//..
//  // FREE OPERATORS
//  bool operator==(const IntSet& lhs, const IntSet& rhs)
//  {
//      return bslalg::RangeCompare::equal(lhs.begin(),
//                                        lhs.end(),
//                                        lhs.size(),
//                                        rhs.begin(),
//                                        rhs.end(),
//                                        rhs.size());
//  }
//
//  bool operator!=(const IntSet& lhs, const IntSet& rhs)
//  {
//      return !(lhs == rhs);
//  }
//..

#include <bslscm_version.h>

#include <bslalg_rbtreeanchor.h>
#include <bslalg_rbtreenode.h>

#include <bslma_allocatortraits.h>

#include <bslmf_movableref.h>

#include <bsls_assert.h>

#include <stdio.h>

namespace BloombergLP {
namespace bslalg {

                        // ================
                        // class RbTreeUtil
                        // ================

struct RbTreeUtil {
    // This 'struct' provides a namespace for a suite of utility functions that
    // operate on elements of type 'RbTreeNode'.
    //
    // Each method of this class, other than 'copyTree', provides the
    // *no-throw* exception guarantee if the client-supplied comparator
    // provides the no-throw guarantee, and provides the *strong* guarantee
    // otherwise (see 'bsldoc_glossary').  'copyTree' provides the *strong*
    // guarantee.

    // CLASS METHODS
                                 // Navigation

    static const RbTreeNode *leftmost(const RbTreeNode *subtree);
    static       RbTreeNode *leftmost(      RbTreeNode *subtree);
        // Return the address of the leftmost node in the specified 'subtree',
        // and 'subtree' if 'subtree' has no left child.  The behavior is
        // undefined unless '0 != subtree', and 'subtree' refers to a valid
        // binary tree.  Note that the value held by the returned node will not
        // compare greater than that of any other node in 'subtree' (as
        // determined by the comparator used to organize the red-black subtree
        // data).

    static const RbTreeNode *rightmost(const RbTreeNode *subtree);
    static       RbTreeNode *rightmost(      RbTreeNode *subtree);
        // Return the address of the rightmost node in the specified
        // 'subtree', and 'subtree' if 'subtree' has no right child.  The
        // behavior is undefined unless '0 != subtree' and 'subtree' refers to
        // a valid binary tree.  Note that the value held by the returned node
        // will not compare less than that of any other node in 'subtree' (as
        // determined by the comparator used to organize the red-black subtree
        // data).

    static const RbTreeNode *next(const RbTreeNode *node);
    static       RbTreeNode *next(      RbTreeNode *node);
        // Return the address of the node that follows the specified 'node' in
        // an in-order traversal of the binary tree to which 'node' belongs, or
        // the tree's sentinel node if 'node' is the rightmost node in the
        // tree.  The behavior is undefined unless 'node' is a member of a
        // valid binary tree, and is not a sentinel node.  Note that if the
        // tree does not contain duplicate values, then the returned node will
        // have the smallest value greater than that of 'node'.

    static const RbTreeNode *previous(const RbTreeNode *node);
    static       RbTreeNode *previous(      RbTreeNode *node);
        // Return the address of the node that precedes the specified 'node' in
        // an in-order traversal of the binary tree to which 'node' belongs, or
        // the tree's rightmost node if 'node' is the sentinel node of the
        // tree.  The behavior is undefined unless or 'node' is a non-leftmost
        // member of a valid binary tree or is a sentinel 'node'.  Note that if
        // the tree does not contain duplicate values, then the returned node
        // will have the largest value less than that of 'node'.

                                 // Search

    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static const RbTreeNode *find(const RbTreeAnchor&    tree,
                                  NODE_VALUE_COMPARATOR& comparator,
                                  const VALUE&           value);
    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static       RbTreeNode *find(RbTreeAnchor&          tree,
                                  NODE_VALUE_COMPARATOR& comparator,
                                  const VALUE&           value);
        // Return the address of the leftmost node holding the specified
        // 'value' in the specified 'tree' (organized according to the
        // specified 'comparator) if found, and return 'tree.sentinel()'
        // otherwise.  'COMPARATOR' shall be a functor providing two methods
        // that can be called as if they had the following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const VALUE&) const;
        //  bool operator()(const VALUE&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', and 'tree' is well-formed
        // (see 'isWellFormed').

    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static const RbTreeNode *lowerBound(const RbTreeAnchor&    tree,
                                        NODE_VALUE_COMPARATOR& comparator,
                                        const VALUE&           value);
    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static       RbTreeNode *lowerBound(RbTreeAnchor&         tree,
                                        NODE_VALUE_COMPARATOR& comparator,
                                        const VALUE&           value);
        // Return the address of the leftmost node holding the smallest
        // value greater-than or equal-to 'value' in the specified 'tree'
        // (organized according to the specified 'comparator) if found, and
        // return 'tree.sentinel()' if 'value' is greater-than the rightmost
        // node in 'tree'.  'COMPARATOR' shall be a functor providing two
        // methods that can be called as if they had the following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const VALUE&) const;
        //  bool operator()(const VALUE&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', and 'tree' is well-formed
        // ('isWellFormed').   Note that this function returns the *first*
        // position before which 'value' could be inserted into 'tree' while
        // preserving its ordering.

    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static const RbTreeNode *upperBound(const RbTreeAnchor&    tree,
                                        NODE_VALUE_COMPARATOR& comparator,
                                        const VALUE&           value);
    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static       RbTreeNode *upperBound(RbTreeAnchor&          tree,
                                        NODE_VALUE_COMPARATOR& comparator,
                                        const VALUE&           value);
        // Return the address of the leftmost node holding the smallest
        // value greater-than 'value' in the specified 'tree' (organized
        // according to the specified 'comparator) if found, and return
        // 'tree.sentinel()' if 'value' is greater-than or equal-to the
        // rightmost node in 'tree'.  'COMPARATOR' shall be a functor
        // providing two methods that can be called as if they had the
        // following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const VALUE&) const;
        //  bool operator()(const VALUE&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', and 'tree' is well-formed
        // ('isWellFormed').   Note that this function returns the *last*
        // position before which 'value' could be inserted into 'tree' while
        // preserving its ordering.

                                 // Modification

    template <class FACTORY>
    static void copyTree(RbTreeAnchor        *result,
                         const RbTreeAnchor&  original,
                         FACTORY             *nodeFactory);
        // Load, into the specified 'result', a collection of newly created
        // nodes having the same red-black tree structure as that of the
        // specified 'original' tree, where each node in the returned tree is
        // created by invoking 'nodeFactory->createNode' on the corresponding
        // 'original' node; if an exception occurs, use
        // 'nodeFactory->deleteNode' to destroy any newly created nodes, and
        // propagate the exception to the caller (i.e., this operation provides
        // the *strong* exception guarantee).  'FACTORY' shall be a class
        // providing two methods that can be called as if they had the
        // following signatures:
        //..
        //  RbTreeNode *createNode(const RbTreeNode&);
        //  void deleteNode(RbTreeNode *);
        //..
        // The behavior is undefined unless 'result' is an empty tree,
        // 'original' is a well-formed (see 'isWellFormed'), and
        // 'nodeFactory->deleteNode' does not throw.

    template <class FACTORY>
    static void moveTree(RbTreeAnchor *result,
                         RbTreeAnchor *original,
                         FACTORY      *nodeFactory,
                         FACTORY      *originalNodeFactory);
        // Load into the specified 'result', using the specified 'nodeFactory'
        // to create and delete nodes, a collection of newly created nodes with
        // the same (red-black) tree structure as that of the specified
        // 'original' tree, which uses the specified 'originalNodeFactory' to
        // create and delete nodes, where the 'value' attribute of each node in
        // 'result' is constructed from explicitly moving the 'value' attribute
        // of the corresponding node in 'original'.  'original' is left in a
        // valid but unspecified state.  If an exception occurs, both 'result'
        // and 'original' are left in a valid but unspecified state.  The
        // behavior is undefined unless 'result' is an empty tree,  'original'
        // is well-formed (see 'isWellFormed'), and 'nodeFactory->deleteNode'
        // and 'originalNodeFactory->deleteNode' do not throw.

    template <class FACTORY>
    static void deleteTree(RbTreeAnchor *tree, FACTORY *nodeFactory);
        // Call 'nodeFactory->deleteNode' on each node in 'tree' and reset
        // 'tree' to an empty state.  'FACTORY' shall be a class providing a
        // method that can be called as if it has the following signature:
        //..
        //  void deleteNode(RbTreeNode *);
        //..
        // The behavior is undefined unless 'tree' is a valid binary tree, and
        // 'nodeFactory->deleteNode' does not throw.

    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static RbTreeNode *findInsertLocation(
                                 bool                   *insertAsLeftChildFlag,
                                 RbTreeAnchor           *tree,
                                 NODE_VALUE_COMPARATOR&  comparator,
                                 const VALUE&            value);
    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static RbTreeNode *findInsertLocation(
                                 bool                   *insertAsLeftChildFlag,
                                 RbTreeAnchor           *tree,
                                 NODE_VALUE_COMPARATOR&  comparator,
                                 const VALUE&            value,
                                 RbTreeNode             *hint);
        // Return the address of the node that would be the parent a node
        // holding the specified 'value', if it were to be inserted into the
        // specified 'tree' (organized according to the specified
        // 'comparator'), and load, into the specified 'insertAsLeftChildFlag',
        // 'true' if 'value' would be held as the returned node's left child,
        // and 'false' if 'value' would be held in its right child, unless
        // 'tree' is empty, in which case return 'tree->sentinel()' and load
        // 'true' into 'insertAsLeftChildFlag'.  Optionally specify a 'hint',
        // suggesting a node in 'tree' that might be the immediate successor of
        // a node holding 'value' if it were to be inserted into 'tree'.  If
        // the supplied 'hint' is the successor, this operation will take
        // amortized constant time; otherwise, it will take O(log(N))
        // operations, where N is the number of nodes in the tree.  If a node
        // holding 'value' is inserted as suggested by this method, the
        // resulting tree will be an ordered binary tree, but may require
        // rebalancing (and re-coloring) to again be a valid red-black tree.
        // 'COMPARATOR' shall be a functor providing two methods that can be
        // called as if they have the following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const VALUE&) const;
        //  bool operator()(const VALUE&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', 'tree' is well-formed
        // (see 'isWellFormed'), and 'hint', if supplied, is a node in 'tree'.
        // Note that this operation is intended to be used in conjunction with
        // the 'insertAt' method.

    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static RbTreeNode *findUniqueInsertLocation(
                                      int                    *comparisonResult,
                                      RbTreeAnchor           *tree,
                                      NODE_VALUE_COMPARATOR&  comparator,
                                      const VALUE&            value);
    template <class NODE_VALUE_COMPARATOR, class VALUE>
    static RbTreeNode *findUniqueInsertLocation(
                                      int                    *comparisonResult,
                                      RbTreeAnchor           *tree,
                                      NODE_VALUE_COMPARATOR&  comparator,
                                      const VALUE&            value,
                                      RbTreeNode             *hint);
        // Return the address of the node holding the specified 'value' in the
        // specified 'tree' (organized according to the specified 'comparator')
        // if found, and the address of the node that would be the parent for
        // 'value' otherwise; load, into the specified 'comparisonResult', 0 if
        // 'value' is found, a negative number if 'value' would be held in its
        // left child, and a positive number if 'value' would be held in its
        // right child, unless 'tree' is empty, in which case load a negative
        // number into 'comparisonResult' and return 'tree->sentinel()'.
        // Optionally specify a 'hint', suggesting a node in 'tree' that might
        // be the immediate successor of a node holding 'value' if it were to
        // be inserted into 'tree'.  If the supplied 'hint' is the successor,
        // this operation will take amortized constant time; otherwise, it will
        // take O(log(N)) operations, where N is the number of nodes in the
        // tree.  If a node holding 'value' is inserted as suggested by this
        // method, the resulting tree will be an ordered binary tree, but may
        // require rebalancing (and re-coloring) to again be a valid red-black
        // tree.  'COMPARATOR' shall be a functor providing two methods that
        // can be called as if they have the following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const VALUE&) const;
        //  bool operator()(const VALUE&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', 'tree' is well-formed
        // (see 'isWellFormed'), and 'hint', if supplied, is a node in 'tree'.
        // Note that this operation is intended to be used in conjunction with
        // the 'insertAt' method.

    template <class NODE_COMPARATOR>
    static void insert(RbTreeAnchor           *tree,
                       const NODE_COMPARATOR&  comparator,
                       RbTreeNode             *newNode);
        // Insert the specified 'newNode' into the specified 'tree', organized
        // according to the specified 'comparator'.  The resulting tree will
        // be well-formed (see 'isWellFormed').  'NODE_COMPARATOR' shall be a
        // functor providing a method that can be called as if it had the
        // following signatures:
        //..
        //  bool operator()(const RbTreeNode&, const RbTreeNode&) const;
        //..
        // The behavior is undefined unless 'comparator' provides a strict
        // weak ordering on objects of type 'VALUE', and 'tree' is well-formed
        // (see 'isWellFormed').

    static void insertAt(RbTreeAnchor *tree,
                         RbTreeNode   *parentNode,
                         bool          leftChildFlag,
                         RbTreeNode   *newNode);
        // Insert the specified 'newNode' into the specified 'tree' as either
        // the left or right child of the specified 'parentNode', as indicated
        // by the specified 'leftChildFlag', and then rebalance the tree so
        // that it is a valid red-black tree (see 'validateRbTree').  The
        // behavior is undefined unless 'tree' is well-formed (see
        // 'isWellFormed'), and, if 'tree' is empty, 'parentNode' is
        // 'tree->sentinel()' and 'leftChildFlag' is 'true', or, if 'tree' is
        // not empty, 'parentNode' is a node in 'tree' whose left or right
        // child (as indicated by 'leftChildFlag') is 0 where if 'newNode' were
        // attached as that child (without rebalancing) 'tree' would still
        // form an ordered binary tree (though not necessarily a valid
        // red-black tree).  Note that this operation is intended to be used in
        // conjunction with the 'findInsertLocation' or
        // 'findUniqueInsertLocation' methods.

    static void remove(RbTreeAnchor *tree, RbTreeNode *node);
        // Remove the specified 'node' from the specified 'tree', and then
        // rebalance 'tree' so that it again forms a valid red-black tree (see
        // 'validateRbTree').  The behavior is undefined unless 'tree' is
        // well-formed (see 'isWellFormed').

    static void swap(RbTreeAnchor *a, RbTreeAnchor *b);
        // Efficiently exchange the nodes in the specified 'a' tree with the
        // nodes in the specified 'b' tree.  This method provides the no-throw
        // exception-safety guarantee.  The behavior is undefined unless 'a'
        // and 'b' are well-formed (see 'isWellFormed').

                                 // Utility

    static bool isLeftChild(const RbTreeNode *node);
        // Return 'true' if the specified 'node' is the left child of its
        // parent, and 'false' otherwise.  The behavior is undefined unless
        // '0 != node->parent()'.

    static bool isRightChild(const RbTreeNode *node);
        // Return 'true' if the specified 'node' is the left child of its
        // parent, and 'false' otherwise.  The behavior is undefined unless
        // '0 != node->parent()'.

    static void rotateLeft(RbTreeNode *node);
        // Perform counter-clockwise rotation on the specified 'node': Rotate
        // the node's right child (the pivot) to be the node's parent, and
        // attach the pivot's left child as the node's right child.
        //..
        //     (node)              (pivot)
        //     /    \              /     \.
        //    a   (pivot)  --->  (node)   c
        //         /   \         /    \.
        //        b     c       a      b
        //..
        // The behavior is undefined unless 'node->rightChild()' is not 0,
        // 'node->parent()' is not 0, and node's parent refers to 'node' as one
        // of its children.  Note that this operation maintains the ordering
        // of the subtree rooted at 'node'.  Also note this operation will
        // successfully rotate the root node of an unbalanced, but otherwise
        // well-formed, tree referred to by a 'RbTreeAnchor' object (see
        // 'isWellFormed') because the parent of the root node is the tree's
        // sentinel node (i.e., not 0), which refers to the root node as its
        // left child, and an 'RbTreeAnchor' object returns the left child of
        // the sentinel node as the root of the tree.

    static void rotateRight(RbTreeNode *node);
        // Perform clockwise rotation on the specified 'node': Rotate the
        // node's left child (the pivot) to be the node's parent, and attach
        // the pivot's right child as the node's left child.
        //..
        //       (node)            (pivot)
        //       /    \            /     \.
        //   (pivot)   c   --->   a     (node)
        //    /  \                      /    \.
        //   a    b                    b      c
        //..
        // The behavior is undefined unless 'node->leftChild()' is not 0,
        // 'node->parent()' is not 0, and node's parent refers to 'node' as one
        // of its children.  Note that this operation maintains the ordering
        // of the subtree rooted at 'node'.  Also note this operation will
        // successfully rotate the root node of an unbalanced, but otherwise
        // well-formed, tree referred to by a 'RbTreeAnchor' object (see
        // 'isWellFormed') because the parent of the root node is the tree's
        // sentinel node (i.e., not 0), which refers to the root node as its
        // left child, and an 'RbTreeAnchor' object returns the left child of
        // the sentinel node as the root of the tree.

                                 // Testing

    static void printTreeStructure(
                    FILE                   *file,
                    const RbTreeNode       *subtree,
                    void (*printNodeValueCallback)(FILE *, const RbTreeNode *),
                    int                     level = 0,
                    int                     spacesPerLevel = 4);
        // Write a description of the structure of the specified 'subtree' to
        // the specified output 'file' in a human-readable format, using the
        // specified 'printValueCallback' to render the value of each node.
        // Optionally specify an initial indentation 'level', whose absolute
        // value is incremented recursively for nested objects.  If 'level' is
        // specified, optionally specify 'spacesPerLevel', whose absolute value
        // indicates the number of spaces per indentation level for this and
        // all of its nested objects.  If 'level' is negative, suppress
        // indentation of the first line.  If 'spacesPerLevel' is negative,
        // format the entire output on one line, suppressing all but the
        // initial indentation (as governed by 'level').  The behavior
        // is undefined unless 'node' is 0, or the root of a valid binary
        // tree.  Note that the implementation of this function is recursive
        // and expensive to perform, it is intended for debugging purposes
        // only.  Also note that the format is not fully specified, and can
        // change without notice.

    template <class NODE_COMPARATOR>
    static int validateRbTree(const RbTreeNode       *rootNode,
                              const NODE_COMPARATOR&  comparator);
    template <class NODE_COMPARATOR>
    static int validateRbTree(const RbTreeNode       **errorNode,
                              const char             **errorDescription,
                              const RbTreeNode        *rootNode,
                              const NODE_COMPARATOR&   comparator);
        // Return the (common) number of black nodes on each path from the
        // specified 'rootNode' to a leaf in the tree, 0 if 'rootNode' is 0,
        // and a negative number if 'rootNode' does not refer to a valid
        // red-black binary search tree, ordered according to the specified
        // 'comparator'.  Optionally specify 'errorNode' and 'errorDescription'
        // in which to load the address of a node violating a red-black tree
        // constraint and a description of that violation, respectively.  The
        // behavior is undefined unless 'rootNode' is 0, or refers to a valid
        // binary tree.
        //
        // Each node of a red-black tree is colored either red or black; null
        // nodes are considered black.  Four requirements must be satisfied
        // for 'rootNode' to refer to a valid red-black binary search tree:
        //
        //: 1 For each node in the tree, no descendents to the left of that
        //:   node would order after that node (according to the 'comparator'),
        //:   and no descendents to the right of that node would order before
        //:   it.
        //:
        //: 2 For each node in the tree, each non-null child of that node
        //:   refers to that node as its parent.
        //:
        //: 3 If a node in the tree is colored red, all its children are
        //:   colored black or are null (which is considered black).
        //:
        //: 4 For each node in the tree, every path from that node to a leaf
        //:   contains the same number of black nodes, where null children are
        //:   considered black leaf nodes.
        //
        // The behavior is undefined unless 'rootNode' is 0, or refers to a
        // valid binary tree.  Note that the implementation of this function
        // is recursive and has linear complexity with respect to the number of
        // nodes in 'tree', it is intended for debugging purposes only.

    template <class NODE_COMPARATOR>
    static bool isWellFormed(const RbTreeAnchor&    tree,
                             const NODE_COMPARATOR& comparator);
        // Return 'true' if the specified 'tree' is well-formed and refers to
        // a valid red-black tree, and 'false' otherwise.  For a
        // 'RbTreeAnchor' to be considered well-formed *all* of the following
        // must be true:
        //
        //: 1 'tree.rootNode()' must refer to a valid red-black tree, whose
        //:   nodes are organized according to 'comparator' (see
        //:   'validateRbTree').
        //:
        //: 2 'tree.firstNode()' must refer to 'tree.sentinel()' if
        //:   'tree.rootNode()' is 0, and leftmost(tree.rootNode())' otherwise.
        //:
        //: 3 'tree.nodeCount()' must be the count of nodes in 'tree' (not
        //:   including the sentinel node).
        //:
        //: 4 'tree.sentinel()->leftchild()' is 'tree.rootNode()', and (if
        //:   'tree.rootNode()' is not 0) 'tree.rootNode()->parent()' is
        //:   'tree.sentinel()'.
        //:
        //: 5 'tree.rootNode()' is 0 or 'tree.rootNode().isBlack()' is 'true'
        //
        // The behavior is undefined unless 'tree.rootNode()' is 0 or refers
        // to a valid binary tree.  Note that the implementation of this
        // function is recursive and has linear complexity with respect to the
        // number of nodes in 'tree', it is intended for debugging purposes
        // only.  Note also that the final condition, that the root node be
        // either 0 or colored black, is not a canonical requirement of a
        // red-black tree but an additional invariant enforced by the methods
        // of 'RbTreeUtil' to simplify the implementations.
};

                      // ==========================
                      // class RbTreeUtil_Validator
                      // ==========================

struct RbTreeUtil_Validator {
    // This 'struct' provides a namespace for auxiliary functions used to
    // validate a red-black binary search tree.

    // CLASS METHODS
    template <class NODE_COMPARATOR>
    static int validateRbTree(const RbTreeNode       **errorNode,
                              const char             **errorDescription,
                              const RbTreeNode        *rootNode,
                              const RbTreeNode        *minNodeValue,
                              const RbTreeNode        *maxNodeValue,
                              const NODE_COMPARATOR&   comparator);
        // Return the (common) number of black nodes on each path from the
        // specified 'rootNode' to a leaf in the tree, 0 if 'rootNode' is 0,
        // and a negative number if 'rootNode' does not refer to a valid
        // red-black binary search tree (ordered according to the specified
        // 'comparator') that contains no nodes whose value is less than the
        // specified 'minNodeValue' (if not 0) or greater-than the specified
        // 'maxNodeValue' (if not 0).  If 'rootNode' does not refer to a valid
        // red-black tree containing nodes whose values are between the
        // specified 'minNodeValue' and 'maxNodeValue' (inclusively) then load
        // 'errorNode' and 'errorDescription' with the address of a node
        // violating a red-black tree constraint and a description of that
        // violation, respectively.  The behavior is undefined unless
        // 'rootNode' is 0, or refers to a valid binary tree.

    static bool isWellFormedAnchor(const RbTreeAnchor& tree);
        // Return 'true' if the specified 'tree' is well-formed, without
        // confirming that it refers to a valid-red-black tree, and
        // 'false' otherwise.  This method will return 'true' if *all* of the
        // following are true:
        //
        //: 1 'tree.firstNode()' must refer to 'tree.sentinel()' if
        //:   'tree.rootNode()' is 0, and leftmost(tree.rootNode())' otherwise.
        //:
        //: 2 'tree.nodeCount()' must be the count of nodes in 'tree' (not
        //:   including the sentinel node).
        //:
        //: 3 'tree.sentinel()->leftchild()' is 'tree.rootNode()', and (if
        //:   'tree.rootNode()' is not 0), 'tree.rootNode()->parent()' is
        //:   'tree.sentinel().
        //:
        //: 4 'tree.rootNode()' is 0 or 'tree.rootNode().isBlack()' is 'true'
        //
        // The behavior is undefined unless 'tree.rootNode()' is 0, or refers
        // to a valid binary tree.  Note that this function provides a
        // non-templatized implementation for several criteria of a
        // well-formed tree (but not the complete set verified by
        // 'RbTreeUtil::isWellFormed').
};

                        // ============================
                        // struct RbTreeUtilTreeProctor
                        // ============================

template <class DELETER>
class RbTreeUtilTreeProctor {
    // This class implements a proctor that, unless 'release' is called,
    // invokes the parameterized 'DELETER' on each node in the tree supplied at
    // construction.

    // DATA
    RbTreeAnchor *d_tree_p;     // address of root node (held, not owned)

    DELETER      *d_deleter_p;  // address of deleter used to destroy each
                                // node (held, not owned)

  public:
    // CREATORS
    RbTreeUtilTreeProctor(RbTreeAnchor *tree, DELETER *deleter);
        // Create a proctor object that, unless 'release' is called, will,
        // on destruction, invoke the specified 'deleter' on each node in
        // 'tree'.

    ~RbTreeUtilTreeProctor();
        // Unless 'release' has been called, invoke the deleter supplied at
        // construction on each node in the tree supplied at construction.

    // MANIPULATORS
    void release();
        // Release from management the tree supplied at construction.
};

// ============================================================================
//                      INLINE FUNCTION DEFINITIONS
// ============================================================================

                        // ----------------
                        // class RbTreeUtil
                        // ----------------

// CLASS METHODS
inline
RbTreeNode *RbTreeUtil::leftmost(RbTreeNode *subtree)
{
    return const_cast<RbTreeNode *>(
                            leftmost(const_cast<const RbTreeNode *>(subtree)));
}

inline
RbTreeNode *RbTreeUtil::rightmost(RbTreeNode *subtree)
{
    return const_cast<RbTreeNode *>(
                           rightmost(const_cast<const RbTreeNode *>(subtree)));
}

inline
RbTreeNode *RbTreeUtil::next(RbTreeNode *node)
{
    return const_cast<RbTreeNode *>(
                                   next(const_cast<const RbTreeNode *>(node)));
}

inline
RbTreeNode *RbTreeUtil::previous(RbTreeNode *node)
{
    return const_cast<RbTreeNode *>(
                               previous(const_cast<const RbTreeNode *>(node)));
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
inline
RbTreeNode *RbTreeUtil::find(RbTreeAnchor&          tree,
                             NODE_VALUE_COMPARATOR& comparator,
                             const VALUE&           value)
{
    return const_cast<RbTreeNode *>(
               find(const_cast<const RbTreeAnchor&>(tree), comparator, value));
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
inline
const RbTreeNode *RbTreeUtil::find(const RbTreeAnchor&    tree,
                                   NODE_VALUE_COMPARATOR& comparator,
                                   const VALUE&           value)
{
    const RbTreeNode *lowBound = lowerBound(tree, comparator, value);

    // Note that a Solaris compiler bug prevents using a ternary ('?:')
    // operator here in certain contexts.

    if (lowBound != tree.sentinel() && !comparator(value, *lowBound)) {
        return lowBound;                                              // RETURN
    }
    return tree.sentinel();
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
RbTreeNode *RbTreeUtil::lowerBound(RbTreeAnchor&          tree,
                                   NODE_VALUE_COMPARATOR& comparator,
                                   const VALUE&           value)
{
    return const_cast<RbTreeNode *>(
         lowerBound(const_cast<const RbTreeAnchor&>(tree), comparator, value));
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
inline
const RbTreeNode *RbTreeUtil::lowerBound(const RbTreeAnchor&    tree,
                                         NODE_VALUE_COMPARATOR& comparator,
                                         const VALUE&           value)
{
    const RbTreeNode *nextLargestNode = tree.sentinel();
    const RbTreeNode *node            = tree.rootNode();
    while (node) {
        if (comparator(*node, value)) {
            node = node->rightChild();
        }
        else {
            nextLargestNode = node;
            node = node->leftChild();
        }
    }
    return nextLargestNode;
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
inline
RbTreeNode *RbTreeUtil::upperBound(RbTreeAnchor&          tree,
                                   NODE_VALUE_COMPARATOR& comparator,
                                   const VALUE&           value)
{
    return const_cast<RbTreeNode *>(
        upperBound(const_cast<const RbTreeAnchor&>(tree), comparator, value));
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
inline
const RbTreeNode *RbTreeUtil::upperBound(const RbTreeAnchor&    tree,
                                         NODE_VALUE_COMPARATOR& comparator,
                                         const VALUE&           value)
{
    const RbTreeNode *nextLargestNode = tree.sentinel();
    const RbTreeNode *node            = tree.rootNode();
    while (node) {
        if (comparator(value, *node)) {
            nextLargestNode = node;
            node = node->leftChild();
        }
        else {
            node = node->rightChild();
        }
    }
    return nextLargestNode;
}

template <class FACTORY>
void RbTreeUtil::copyTree(RbTreeAnchor        *result,
                          const RbTreeAnchor&  original,
                          FACTORY             *nodeFactory)
{
    BSLS_ASSERT_SAFE(result);
    BSLS_ASSERT_SAFE(0 == result->rootNode());
    BSLS_ASSERT_SAFE(nodeFactory);

    if (!original.rootNode()) {
        result->reset(0, result->sentinel(), 0);
        return;                                                       // RETURN
    }

    // Perform an pre-order traversal of the nodes of the tree, invoking
    // 'nodeFactory->createNode()' on each node.

    const RbTreeNode *originalNode = original.rootNode();

    RbTreeNode   *copiedRoot = nodeFactory->cloneNode(*originalNode);
    RbTreeAnchor  tree(copiedRoot, 0, 1);

    RbTreeUtilTreeProctor<FACTORY> proctor(&tree, nodeFactory);

    RbTreeNode *copiedNode = copiedRoot;

    copiedNode->setColor(originalNode->color());
    copiedNode->setParent(result->sentinel());
    copiedNode->setLeftChild(0);
    copiedNode->setRightChild(0);
    do {
        if (0 != originalNode->leftChild() && 0 == copiedNode->leftChild()) {
            originalNode = originalNode->leftChild();
            RbTreeNode *newNode = nodeFactory->cloneNode(*originalNode);
            copiedNode->setLeftChild(newNode);
            newNode->setColor(originalNode->color());
            newNode->setParent(copiedNode);
            newNode->setLeftChild(0);
            newNode->setRightChild(0);

            copiedNode = newNode;
        }
        else if (0 != originalNode->rightChild() &&
                 0 == copiedNode->rightChild()) {
            originalNode = originalNode->rightChild();
            RbTreeNode *newNode = nodeFactory->cloneNode(*originalNode);
            copiedNode->setRightChild(newNode);
            newNode->setColor(originalNode->color());
            newNode->setParent(copiedNode);
            newNode->setLeftChild(0);
            newNode->setRightChild(0);

            copiedNode = newNode;
        }
        else {
            originalNode = originalNode->parent();
            copiedNode   = copiedNode->parent();
        }
    } while (original.sentinel() != originalNode);

    proctor.release();

    result->reset(copiedRoot,
                  leftmost(copiedRoot),
                  original.numNodes());
}

template <class FACTORY>
void RbTreeUtil::moveTree(RbTreeAnchor *result,
                          RbTreeAnchor *original,
                          FACTORY      *nodeFactory,
                          FACTORY      *originalNodeFactory)
{
    BSLS_ASSERT_SAFE(result);
    BSLS_ASSERT_SAFE(0 == result->rootNode());
    BSLS_ASSERT_SAFE(nodeFactory);
    BSLS_ASSERT_SAFE(originalNodeFactory);

    if (!original->rootNode()) {
        result->reset(0, result->sentinel(), 0);
        return;                                                       // RETURN
    }

    // Perform an pre-order traversal of the nodes of the tree, invoking
    // 'nodeFactory->createNode()' on each node.

    RbTreeNode *originalNode = original->rootNode();

    RbTreeNode *copiedRoot = nodeFactory->moveIntoNewNode(originalNode);

    RbTreeAnchor  tree(copiedRoot, 0, 1);

    RbTreeUtilTreeProctor<FACTORY> proctor(&tree, nodeFactory);
    RbTreeUtilTreeProctor<FACTORY> oproctor(original, originalNodeFactory);

    RbTreeNode *copiedNode = copiedRoot;

    copiedNode->setColor(originalNode->color());
    copiedNode->setParent(result->sentinel());
    copiedNode->setLeftChild(0);
    copiedNode->setRightChild(0);
    do {
        if (0 != originalNode->leftChild() && 0 == copiedNode->leftChild()) {
            originalNode = originalNode->leftChild();
            RbTreeNode *newNode = nodeFactory->moveIntoNewNode(originalNode);
            copiedNode->setLeftChild(newNode);
            newNode->setColor(originalNode->color());
            newNode->setParent(copiedNode);
            newNode->setLeftChild(0);
            newNode->setRightChild(0);

            copiedNode = newNode;
        }
        else if (0 != originalNode->rightChild() &&
                 0 == copiedNode->rightChild()) {
            originalNode = originalNode->rightChild();
            RbTreeNode *newNode = nodeFactory->moveIntoNewNode(originalNode);
            copiedNode->setRightChild(newNode);
            newNode->setColor(originalNode->color());
            newNode->setParent(copiedNode);
            newNode->setLeftChild(0);
            newNode->setRightChild(0);

            copiedNode = newNode;
        }
        else {
            originalNode = originalNode->parent();
            copiedNode   = copiedNode->parent();
        }
    } while (original->sentinel() != originalNode);

    proctor.release();

    result->reset(copiedRoot,
                  leftmost(copiedRoot),
                  original->numNodes());

    // 'oproctor' takes care of clearing 'original', even when an exception is
    // not thrown, since the tree is no longer valid if the elements have been
    // moved from.
}

template <class FACTORY>
void RbTreeUtil::deleteTree(RbTreeAnchor *tree, FACTORY *nodeFactory)
{
    BSLS_ASSERT_SAFE(tree);
    BSLS_ASSERT_SAFE(nodeFactory);

    if (0 == tree->rootNode()) {
        BSLS_ASSERT_SAFE(tree->sentinel() == tree->firstNode());
        return;                                                       // RETURN
    }

    // Perform a post-order traversal of the nodes of the tree, invoking
    // 'nodeFactory->deleteNode()' on each node.

    RbTreeNode *node = tree->firstNode();
    do {
        // At each iteration through this loop, we are at a leftmost (i.e.,
        // minimum) node of some sub-tree.  Note that 'node->leftChild()' may
        // not be 0 if we've simply deleted the left sub-tree of this node.

        if (node->rightChild()) {
            // If this node has a right child, then navigate to the first node
            // in the subtree to remove, and set 'node->rightChild()' to 0 so
            // we know this sub-tree has been removed when we iterate back up
            // parent pointers of the tree to this node.

            RbTreeNode *rightChild = node->rightChild();
            node->setRightChild(0);
            node = leftmost(rightChild);
        }
        else {
            RbTreeNode *parent = node->parent();
            nodeFactory->deleteNode(node);
            node = parent;
        }
    } while (tree->sentinel() != node);
    tree->reset(0, tree->sentinel(), 0);
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
RbTreeNode *RbTreeUtil::findInsertLocation(
                                 bool                   *insertAsLeftChildFlag,
                                 RbTreeAnchor           *tree,
                                 NODE_VALUE_COMPARATOR&  comparator,
                                 const VALUE&            value)
{
    BSLS_ASSERT_SAFE(insertAsLeftChildFlag);
    BSLS_ASSERT_SAFE(tree);

    RbTreeNode *parent = tree->sentinel();
    RbTreeNode *node   = tree->rootNode();
    *insertAsLeftChildFlag = true;
    while (node) {
        // Find the leaf node that would be the parent of 'newNode'.

        parent = node;
        *insertAsLeftChildFlag = comparator(value, *node);
        if (*insertAsLeftChildFlag) {
            node = node->leftChild();
        }
        else {
            node = node->rightChild();
        }
    }
    return parent;
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
RbTreeNode *RbTreeUtil::findInsertLocation(
                                 bool                   *insertAsLeftChildFlag,
                                 RbTreeAnchor           *tree,
                                 NODE_VALUE_COMPARATOR&  comparator,
                                 const VALUE&            value,
                                 RbTreeNode             *hint)
{
    BSLS_ASSERT_SAFE(insertAsLeftChildFlag);
    BSLS_ASSERT_SAFE(tree);
    BSLS_ASSERT_SAFE(hint);

    // 'hint' is valid if it is equal to, or the smallest value greater than,
    // 'value'.

    if (tree->sentinel() == hint || !comparator(*hint, value)) {
        // 'hint' is greater-than or equal-to 'value', if the previous node,
        // 'prev' is less-than or equal-to 'value', then we have a valid hint.

        RbTreeNode *prev = (tree->firstNode() == hint) ? hint : previous(hint);
        if (tree->firstNode() == hint || !comparator(value, *prev)) {
            // There will be an empty position for a child node between every
            // two consecutive nodes (in an in-order traversal) of a binary
            // tree.  Determine whether that empty position is the left child
            // of 'hint' or the right child of 'prev'.

            if (0 == hint->leftChild()) {
                *insertAsLeftChildFlag = true;
                return hint;                                          // RETURN
            }
            BSLS_ASSERT_SAFE(prev);
            *insertAsLeftChildFlag = false;
            return prev;                                              // RETURN
        }
        // 'prev' is greater than 'value', so this is not a valid hint.

    }
    // If 'hint' was less than 'value', it is not a valid hint.

    // The 'hint' is not valid, fall-back and search the entire tree.

    return findInsertLocation(insertAsLeftChildFlag, tree, comparator, value);
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
RbTreeNode *RbTreeUtil::findUniqueInsertLocation(
                                      int                    *comparisonResult,
                                      RbTreeAnchor           *tree,
                                      NODE_VALUE_COMPARATOR&  comparator,
                                      const VALUE&            value)
{
    BSLS_ASSERT_SAFE(comparisonResult);
    BSLS_ASSERT_SAFE(tree);

    // Note that 'nextSmallestNode' is used, rather than 'nextLargestNode' (as
    // seen in 'upperBound' and 'lowerBound') to avoid an unnecessary
    // negation.

    RbTreeNode *parent           = tree->sentinel();
    RbTreeNode *nextSmallestNode = 0;
    RbTreeNode *node             = tree->rootNode();

    bool leftChild = true;
    while (node) {
        // Find the leaf node that would be the parent of 'newNode'.

        parent = node;
        leftChild = comparator(value, *node);
        if (leftChild) {
            node = node->leftChild();
        }
        else {
            nextSmallestNode = node;
            node = node->rightChild();
        }
    }

    if (nextSmallestNode && !comparator(*nextSmallestNode, value)) {
        *comparisonResult = 0;
        return nextSmallestNode;                                      // RETURN
    }
    *comparisonResult = leftChild ? -1 : 1;
    return parent;
}

template <class NODE_VALUE_COMPARATOR, class VALUE>
RbTreeNode *RbTreeUtil::findUniqueInsertLocation(
                                      int                    *comparisonResult,
                                      RbTreeAnchor           *tree,
                                      NODE_VALUE_COMPARATOR&  comparator,
                                      const VALUE&            value,
                                      RbTreeNode             *hint)
{
    BSLS_ASSERT_SAFE(comparisonResult);
    BSLS_ASSERT_SAFE(tree);
    BSLS_ASSERT_SAFE(hint);

    enum { LEFT_CHILD = -1, NODE_FOUND = 0, RIGHT_CHILD = 1 };

    // 'hint' is valid if it is first value greater than 'value' in the tree.

    if (tree->sentinel() == hint || comparator(value, *hint)) {
        // 'hint' is greater than 'value'.  If the previous node, 'prev' is
        // less than the value, then we have a valid hint.

        RbTreeNode *prev = (tree->firstNode() == hint) ? hint : previous(hint);
        if (tree->firstNode() == hint || comparator(*prev, value)) {
            // There will be an empty position for a child node between every
            // two consecutive nodes (in an in-order traversal) of a binary
            // tree.  Determine whether that empty position is the left child
            // of 'hint' or the right child of 'prev'.

            if (0 == hint->leftChild()) {
                *comparisonResult = LEFT_CHILD;
                return hint;                                          // RETURN
            }

            BSLS_ASSERT_SAFE(prev);
            *comparisonResult = RIGHT_CHILD;
            return prev;                                              // RETURN
        }
        // 'value' is ordered before 'hint', but 'prev' is not ordered before
        // 'value', so either: (1) 'value' is equal to 'prev' or (2) 'hint' is
        // not a valid hint.  Optimize for (1), by handling it as a special
        // case, as this may reasonably occur using 'upperBound' on 'value' to
        // determine a hint.

        if (!comparator(value, *prev)) {
            *comparisonResult = NODE_FOUND;
            return prev;                                              // RETURN
        }

        // 'prev' is greater than 'value', so this is not a valid hint.
    }
    // If 'value' is not ordered before 'hint', either: (1) 'value' is equal
    // to 'hint', or (2) 'hint' is not a valid hint.  Optimize for (1).

    else if (tree->sentinel() != hint && !comparator(*hint, value)) {
        *comparisonResult = NODE_FOUND;
        return hint;                                                  // RETURN
    }
    // The 'hint' is not valid, fall-back and search the entire tree.

    return findUniqueInsertLocation(comparisonResult,
                                    tree,
                                    comparator,
                                    value);
}

template <class NODE_COMPARATOR>
void RbTreeUtil::insert(RbTreeAnchor           *tree,
                        const NODE_COMPARATOR&  comparator,
                        RbTreeNode             *newNode)
{
    BSLS_ASSERT_SAFE(tree);
    BSLS_ASSERT_SAFE(newNode);

    // Note that the following logic is the same as 'findInsertLocation'
    // except that the comparator required for this operation compares two
    // nodes, rather than comparing a value to a node.

    RbTreeNode *parent        = tree->sentinel();
    RbTreeNode *node          = tree->rootNode();
    bool        leftChildFlag = true;
    while (node) {
        // Find the leaf node that would be the parent of 'newNode'.

        parent = node;
        leftChildFlag = comparator(*newNode, *node);
        if (leftChildFlag) {
            node = node->leftChild();
        }
        else {
            node = node->rightChild();
        }
    }
    return insertAt(tree, parent, leftChildFlag, newNode);
}

inline
bool RbTreeUtil::isLeftChild(const RbTreeNode *node)
{
    BSLS_ASSERT_SAFE(node);
    BSLS_ASSERT_SAFE(node->parent());

    return node->parent()->leftChild() == node;
}

inline
bool RbTreeUtil::isRightChild(const RbTreeNode *node)
{
    BSLS_ASSERT_SAFE(node);
    BSLS_ASSERT_SAFE(node->parent());

    return node->parent()->rightChild() == node;
}

template <class NODE_COMPARATOR>
inline
int RbTreeUtil::validateRbTree(const RbTreeNode       *rootNode,
                               const NODE_COMPARATOR&  comparator)
{
    const RbTreeNode *errorNode;
    const char       *errorDescription;
    return validateRbTree(&errorNode, &errorDescription, rootNode, comparator);
}

template <class NODE_COMPARATOR>
int RbTreeUtil::validateRbTree(const RbTreeNode       **errorNode,
                               const char             **errorDescription,
                               const RbTreeNode        *rootNode,
                               const NODE_COMPARATOR&   comparator)
{
    BSLS_ASSERT(errorNode);
    BSLS_ASSERT(errorDescription);

    return RbTreeUtil_Validator::validateRbTree(errorNode,
                                                errorDescription,
                                                rootNode,
                                                0,
                                                0,
                                                comparator);
}

template <class NODE_COMPARATOR>
inline
bool RbTreeUtil::isWellFormed(const RbTreeAnchor&    tree,
                              const NODE_COMPARATOR& comparator)
{
    if (!RbTreeUtil_Validator::isWellFormedAnchor(tree)) {
        return false;                                                 // RETURN
    }
    return 0 <= validateRbTree(tree.rootNode(), comparator);
}

                      // --------------------------
                      // class RbTreeUtil_Validator
                      // --------------------------

// CLASS METHODS
template <class NODE_COMPARATOR>
int RbTreeUtil_Validator::validateRbTree(
                                     const RbTreeNode       **errorNode,
                                     const char             **errorDescription,
                                     const RbTreeNode        *rootNode,
                                     const RbTreeNode        *minNodeValue,
                                     const RbTreeNode        *maxNodeValue,
                                     const NODE_COMPARATOR&   comparator)
{
    BSLS_ASSERT_SAFE(errorNode);
    BSLS_ASSERT_SAFE(errorDescription);

    //: 1 All the descendents to the left of each node are ordered that at or
    //:   before that node, and all descendents to the right of each node are
    //:   ordered at or after that node, as determined by 'comparator'.
    //:
    //: 2 Both children of every node refer to 'node' as a parent.
    //:
    //: 3 If a node in the tree has no children, it is black.
    //:
    //: 4 If a node in the tree is red, its children are either black or 0.
    //:
    //: 5 For each node in the tree, every path from that node to a leaf
    //:   contains the same number of black nodes.

    enum { INVALID_RBTREE = -1};

    // 'NIL' nodes are considered black

    if (!rootNode) {
        return 0;                                                     // RETURN
    }

    // Rule 1.

    if ((minNodeValue && comparator(*rootNode, *minNodeValue)) ||
        (maxNodeValue && comparator(*maxNodeValue, *rootNode))) {
        *errorNode        = rootNode;
        *errorDescription = "Invalid binary search tree.";
        return INVALID_RBTREE;                                        // RETURN
    }

    const RbTreeNode *left  = rootNode->leftChild();
    const RbTreeNode *right = rootNode->rightChild();
    if ((left != 0 || right != 0) && left == right) {
        *errorNode        = rootNode;
        *errorDescription = "Invalid children";
        return INVALID_RBTREE;                                        // RETURN
    }

    // Rule 2.

    if ((left  && left->parent()  != rootNode) ||
        (right && right->parent() != rootNode)) {
        *errorNode        = rootNode;
        *errorDescription = "Invalid parent pointers for children";
        return INVALID_RBTREE;                                        // RETURN
    }

    // Rule 4.

    if (RbTreeNode::BSLALG_RED == rootNode->color()) {
        if ((left  && left->color()  != RbTreeNode::BSLALG_BLACK) ||
            (right && right->color() != RbTreeNode::BSLALG_BLACK)) {
            *errorNode        = rootNode;
            *errorDescription = "Red node with a red child.";
            return INVALID_RBTREE;                                    // RETURN
        }
    }

    int leftDepth  = validateRbTree(errorNode,
                                    errorDescription,
                                    rootNode->leftChild(),
                                    minNodeValue,
                                    rootNode,
                                    comparator);
    int rightDepth = validateRbTree(errorNode,
                                    errorDescription,
                                    rootNode->rightChild(),
                                    rootNode,
                                    maxNodeValue,
                                    comparator);

    if (leftDepth < 0 || rightDepth < 0) {
        return INVALID_RBTREE;                                        // RETURN
    }

    // Rule 5.

    if (leftDepth != rightDepth) {
        *errorNode        = rootNode;
        *errorDescription =
            "Black violation (unequal black depth from node to leaves).";
        return INVALID_RBTREE;                                        // RETURN
    }

    return (rootNode->color() == RbTreeNode::BSLALG_BLACK)
          ? leftDepth + 1
          : leftDepth;
}

                        // ----------------------------
                        // struct RbTreeUtilTreeProctor
                        // ----------------------------

template <class DELETER>
inline
RbTreeUtilTreeProctor<DELETER>::RbTreeUtilTreeProctor(RbTreeAnchor *tree,
                                                      DELETER      *deleter)
: d_tree_p(tree)
, d_deleter_p(deleter)
{
    BSLS_ASSERT_SAFE(deleter);
}

template <class DELETER>
inline
RbTreeUtilTreeProctor<DELETER>::~RbTreeUtilTreeProctor()
{
    if (d_tree_p && d_tree_p->rootNode()) {
        d_tree_p->rootNode()->setParent(d_tree_p->sentinel());

        d_tree_p->setFirstNode(RbTreeUtil::leftmost(d_tree_p->rootNode()));
        RbTreeUtil::deleteTree(d_tree_p, d_deleter_p);
    }
}

template <class DELETER>
inline
void RbTreeUtilTreeProctor<DELETER>::release()
{
    d_tree_p = 0;
}

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

#endif

// ----------------------------------------------------------------------------
// Copyright 2013 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 ----------------------------------