// bslalg_rbtreenode.h                                                -*-C++-*-
#ifndef INCLUDED_BSLALG_RBTREENODE
#define INCLUDED_BSLALG_RBTREENODE

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

//@PURPOSE: Provide a base class for a red-black binary tree node.
//
//@CLASSES:
//  bslalg::RbTreeNode: base class for a red-black binary tree node
//
//@SEE_ALSO: bslalg_rbtreeutil
//
//@DESCRIPTION: This component provides a single POD-like class, 'RbTreeNode',
// used to represent a node in a red-black binary search tree.  An 'RbTreeNode'
// provides the address to its parent, left-child, and right-child nodes, as
// well as providing a "color" (red or black).  'RbTreeNode' does not, however,
// contain "payload" data (e.g., a value), as it is intended to work with
// generalized tree operations (see 'bslalg_rbtreenodeutil').  Clients creating
// a red-black binary search tree must define their own node type that
// incorporates 'RbTreeNode' (generally via inheritance), and that maintains
// the "key" value and any associated data.
//
///Storing Color Information
///-------------------------
// To reduce the memory footprint of the 'RbTreeNode', the color information is
// stored at the least-significant-bit (LSB) of the parent node.  The address
// of the parent node and the color can be accessed through bit-wise
// operations.  This is possible because all memory addresses are at least
// 4-bytes aligned, therefore, the 2 LSB of any pointer are always 0.
//
///Usage
///-----
// This section illustrates intended usage of this component.
//
///Example 1: Creating a Function to Print a Red Black Tree
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates creating a function that prints, to a 'FILE', a
// tree of 'RbTreeNode' objects.
//
// First, we define the signature of a function, 'printTree', that accepts, in
// addition to an output file and root node, a function pointer argument
// (supplied by clients) used to print each node's value, note that a node's
// value is not accessible through 'RbTreeNode':
//..
//  void printTree(FILE             *output,
//                 const RbTreeNode *rootNode,
//                 void (*printNodeValueCallback)(FILE *, const RbTreeNode *))
//  {
//..
// Now, we define the body of 'printTree', which is a recursive function that
// performs a prefix traversal of the supplied binary tree, printing the value
// and color of 'rootNode' before recursively printing its left and then right
// sub-trees.
//..
//      if (0 == rootNode) {
//          return;                                                   // RETURN
//      }
//      fprintf(output, " [ ");
//
//      // Print the value and color of 'rootNode'.
//
//      printNodeValueCallback(output, rootNode);
//      fprintf(output,
//              ": %s",
//              rootNode->color() == RbTreeNode::BSLALG_RED ? "RED" : "BLACK");
//
//      // Recursively call 'printTree' on the left and right sub-trees.
//
//      printTree(output, rootNode->leftChild(), printNodeValueCallback);
//      printTree(output, rootNode->rightChild(), printNodeValueCallback);
//      fprintf(output, " ]");
//  }
//..
// Notice that we use 'FILE' in the context of this usage example to avoid a
// dependency of standard library streams.  Finally, we will use 'printTree' to
// print a description of a tree in the next example.
//
///Example 2: Creating a Simple Red-Black Tree
///- - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates creating a simple tree of integer values using
// 'RbTreeNode'.  Note that, in practice, clients should use associated
// utilities to manage such a tree (see 'bslalg_rbtreenodeutil').
//
// First, we define a node-type, 'IntTreeNode', that inherits from
//'RbTreeNode':
//..
//  struct IntTreeNode : public RbTreeNode {
//      // A red-black tree node containing an integer data-value.
//
//      int d_value;  // "payload" value represented by the node
//  };
//..
// Then, we define a function 'printIntNodeValue' to print the value of an
// integer node.  Note that this function's signature matches that
// required by 'printTree' (defined in the preceding example):
//..
//  void printIntTreeNodeValue(FILE *output, const RbTreeNode *node)
//  {
//     BSLS_ASSERT(0 != node);
//
//     fprintf(output, "%d", static_cast<const IntTreeNode*>(node)->d_value);
//  }
//..
// Next, we define 'main' for our test, and create three nodes that we'll use
// to construct a tree:
//..
//  int main(int argc, const char *argv[])
//  {
//      IntTreeNode A, B, C;
//..
// Then, we describe the structure of the tree we wish to construct.
//..
//
//                A (value: 2, BLACK)
//              /       \.
//             /         \.
//  B (value: 1, RED)   C ( value: 3, RED )
//..
// Now, we set the properties for the nodes 'A', 'B', and 'C' to form a valid
// tree whose structure matches that description:
//..
//      A.d_value = 2;
//      A.setColor(RbTreeNode::BSLALG_BLACK);
//      A.setParent(0);
//      A.setLeftChild(&B);
//      A.setRightChild(&C);
//
//      B.d_value = 1;
//      B.setColor(RbTreeNode::BSLALG_RED);
//      B.setParent(&A);
//      B.setLeftChild(0);
//      B.setRightChild(0);
//
//      C.d_value = 3;
//      C.setColor(RbTreeNode::BSLALG_RED);
//      C.setParent(&A);
//      C.setLeftChild(0);
//      C.setRightChild(0);
//..
// Finally, we use the 'printTree' function with the 'printIntTreeNodeValue'
// function to print the structure of our tree to 'stdout':
//..
//      printTree(stdout, &A, printIntTreeNodeValue);
//  }
//..
// Resulting in a single line of console output:
//..
//  [ 2: BLACK [ 1: RED ] [ 3: RED ] ]
//..
//
///Example 3: Creating a Function To Validate a Red-Black Tree
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates creating a function to validate the properties of
// a red-black tree.
//
// First, we declare the signature of a function 'validateRbTree', which takes
// two arguments: (1) the address to the root node of a tree, and (2) a
// comparator function, which is used to compare the payload values of the tree
// nodes.  Note that the parameterized comparator is needed because a node's
// value is not accessible through the supplied 'RbTreeNode'.
//..
//  template <class NODE_COMPARATOR>
//  int validateRbTree(const RbTreeNode       *rootNode,
//                     const NODE_COMPARATOR&  comparator);
//      // Return the uniform number of black nodes between every leaf node in
//      // the tree and the specified 'rootNode', 0 if 'rootNode' is 0, and a
//      // negative value if 'rootNode' does not refer to a valid red-black
//      // binary-search tree that is ordered according to the specified
//      // 'comparator'.  'rootNode' is considered a valid red-black binary
//      // search-tree if it obeys the following rules:
//      //
//      //: 1 All nodes in the left sub-tree of 'rootNode' are ordered at or
//      //:   before 'rootNode' (as determined by 'comparator'), and all nodes
//      //:   in the right sub-tree are ordered at or after 'rootNode'.
//      //:
//      //: 2 Both children of 'rootNode' refer to 'rootNode' as a parent.
//      //:
//      //: 3 If 'rootNode' is red, its children are either black or 0.
//      //:
//      //: 4 Every path from 'rootNode' to a leaf contains the same number of
//      //:   black nodes (the uniform number of black nodes in every path is
//      //:   returned by this function if valid).
//      //:
//      //: 5 Rules (1-4) are obeyed, recursively, by the left and right
//      //:   sub-trees of 'rootNode'.
//      //
//      // Note that this particular specification of the constraints of a
//      // red-black tree does not require the presense of black-colored NIL
//      // leaf-nodes; instead NULL children are implicitly assumed to be NIL
//      // leaf-nodes (as is typically the case for C/C++ implementations).
//      // This specification also does not require the root node to be
//      // colored black, as there's no practical benefit to enforcing that
//      // constraint.
//..
// Then, we declare the signature for an auxiliary function,
// 'validateRbTreeRaw', that accepts, additionally, the address of minimum
// and maximum value nodes, and is needed to recursively apply rule 1:
//..
//  template <class NODE_COMPARATOR>
//  int validateRbTreeRaw(const RbTreeNode *rootNode,
//                        const RbTreeNode *minNodeValue,
//                        const RbTreeNode *maxNodeValue,
//                        NODE_COMPARATOR   comparator);
//
//      // Return the uniform number of black nodes between every leaf node in
//      // the tree and the specified 'rootNode', 0 if 'rootNode' is 0, and a
//      // negative value if (1) 'rootNode' does not refer to a valid red-black
//      // binary search tree that is ordered according to the specified
//      // 'comparator', (2) the specified 'minNodeValue' is not 0 and there is
//      // at least 1 node in the tree ordered before 'minNodeValue', or (3)
//      // the specified 'maxNodeValue' is not 0 and there is at least 1 node
//      // in the tree ordered after 'maxNodeValue'.
//..
// Now, we define the implementation of 'validateRbTree', which simply
// delegates to 'validateRbTreeRaw'.
//..
//  template <class NODE_COMPARATOR>
//  int validateRbTree(const RbTreeNode *rootNode,
//                     NODE_COMPARATOR   comparator)
//  {
//      return validateRbTreeRaw(rootNode, 0, 0, comparator);
//  }
//..
// Finally, we define the implementation of 'validateRbTreeRaw', which tests if
// 'rootNode' violates any of the rules defined in the 'validateRbTree' method
// documentation, and then recursively calls 'validateRbTreeRaw' on the left
// and right sub-trees or 'rootNode':
//..
//  template <class NODE_COMPARATOR>
//  int validateRbTreeRaw(const RbTreeNode *rootNode,
//                        const RbTreeNode *minNodeValue,
//                        const RbTreeNode *maxNodeValue,
//                        NODE_COMPARATOR   comparator)
//  {
//      enum { INVALID_RBTREE = -1 };
//
//      // The black-height of a empty tree is considered 0.
//
//      if (0 == rootNode) {
//          return 0;                                                 // RETURN
//      }
//
//      // Rule 1.
//
//      if ((minNodeValue && comparator(*rootNode, *minNodeValue)) ||
//          (maxNodeValue && comparator(*maxNodeValue, *rootNode))) {
//          return INVALID_RBTREE;                                    // RETURN
//      }
//
//      // Rule 2.
//
//      const RbTreeNode *left  = rootNode->leftChild();
//      const RbTreeNode *right = rootNode->rightChild();
//      if ((left  && left->parent()  != rootNode) ||
//          (right && right->parent() != rootNode)) {
//          return INVALID_RBTREE;                                    // RETURN
//      }
//
//      // Rule 3.
//
//      if (RbTreeNode::BSLALG_RED == rootNode->color()) {
//          if ((left  && left->color()  != RbTreeNode::BSLALG_BLACK) ||
//              (right && right->color() != RbTreeNode::BSLALG_BLACK)) {
//              return INVALID_RBTREE;                                // RETURN
//          }
//      }
//
//      // Recursively validate the left and right sub-tree's and obtain their
//      // black-height in order to apply rule 5.
//
//      int leftDepth  = validateRbTreeRaw(rootNode->leftChild(),
//                                         minNodeValue,
//                                         rootNode,
//                                         comparator);
//
//      int rightDepth = validateRbTreeRaw(rootNode->rightChild(),
//                                         rootNode,
//                                         maxNodeValue,
//                                         comparator);
//
//      if (leftDepth < 0 || rightDepth < 0) {
//          return INVALID_RBTREE;                                    // RETURN
//      }
//
//      // Rule 4.
//
//      if (leftDepth != rightDepth) {
//          return INVALID_RBTREE;                                    // RETURN
//      }
//
//      return (rootNode->color() == RbTreeNode::BSLALG_BLACK)
//          ? leftDepth + 1
//          : leftDepth;
//  }
//..

#include <bslscm_version.h>

#include <bslmf_assert.h>

#include <bsls_types.h>
#include <bsls_assert.h>

namespace BloombergLP {
namespace bslalg {

                        // ================
                        // class RbTreeNode
                        // ================

class RbTreeNode {
    // This POD-like 'class' describes a node suitable for use in a red-black
    // binary search tree, holding the addresses of the parent, left-child, and
    // right-child nodes (any of which may be 0), as well as a "color" (red or
    // black).  This class is a "POD-like" to facilitate efficient allocation
    // and use in the context of a container implementation.  In order to meet
    // the essential requirements of a POD type, this 'class' does not define a
    // constructor or destructor.  However its data members are private.  Since
    // this class will be aligned to a word boundary, a pointer type will be a
    // multiple of 4.  This class use this property to reduce its size by
    // storing the color information in the least significant bit of the parent
    // pointer.  Note that this type does not contain any "payload" member
    // data: Clients creating a red-black binary search tree must define an
    // appropriate node type that incorporates 'RbTreeNode' (generally via
    // inheritance), and that holds the "key" value and any associated data.

  public:
    // TYPES
    enum Color{
        BSLALG_RED   = 0,
        BSLALG_BLACK = 1
    };

  private:
    // DATA
    RbTreeNode *d_parentWithColor_p;  // parent of this node (may be 0) with
                                      // the color information stored in the
                                      // least significant bit

    RbTreeNode *d_left_p;             // left-child of this node (may be 0)

    RbTreeNode *d_right_p;            // right-child of this node (may be 0)


  private:
    // PRIVATE CLASS METHODS
    static bsls::Types::UintPtr toInt(RbTreeNode *value);
        // Return the specified 'value' as an 'unsigned int'.

    static RbTreeNode *toNode(bsls::Types::UintPtr value);
        // Return the specified 'value' as 'RbTreeNode *'.

  public:
    //! RbTreeNode() = default;
        // Create a 'RbTreeNode' object having uninitialized values.

    //! RbTreeNode(const RbTreeNode& original) = default;
        // Create a 'RbTreeNode' object having the same value as the specified
        // 'original' object.

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

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

    void makeBlack();
        // Set the color of this node to black.  Note that this operation is
        // at least as fast as (and potentially faster than) 'setColor'.

    void makeRed();
        // Set the color of this node to red.    Note that this operation is
        // at least as fast as (and potentially faster than) 'setColor'.

    void setParent(RbTreeNode *address);
        // Set the parent of this node to the specified 'address'.  If
        // 'address' is 0, then this node will have not have a parent node
        // (i.e., it will be the root node).  The behavior is undefined unless
        // 'address' is aligned to at least two bytes.

    void setLeftChild(RbTreeNode *address);
        // Set the left child of this node to the specified 'address'.  If
        // 'address' is 0, then this node will not have a left child.

    void setRightChild(RbTreeNode *address);
        // Set the right child of this node to the specified 'address'.  If
        // 'address' is 0, then this node will not have a right child.

    void setColor(Color value);
        // Set the color of this node to the specified 'value'.

    void toggleColor();
        // Set the color of this node to the alternative color.  If this
        // node's color is red, set it to black, and set it to red otherwise.
        // Note that this operation is at least as fast as (and potentially
        // faster than) 'setColor'.

    void reset(RbTreeNode *parent,
               RbTreeNode *leftChild,
               RbTreeNode *rightChild,
               Color       color);
        // Reset this object to have the specified 'parent', 'leftChild',
        // 'rightChild', and 'color' property values.

    RbTreeNode *parent();
        // Return the address of the (modifiable) parent of this node if one
        // exists, and 0 otherwise.

    RbTreeNode *leftChild();
        // Return the address of the (modifiable) left child of this node if
        // one exists, and 0 otherwise.

    RbTreeNode *rightChild();
        // Return the address of the (modifiable) right child of this node if
        // one exists, and 0 otherwise.

    // ACCESSORS
    const RbTreeNode *parent() const;
        // Return the address of the parent of this node if one exists, and 0
        // otherwise.

    bool isBlack() const;
        // Return 'true' if this node is black.

    bool isRed() const;
        // Return 'true' if this node is red.

    const RbTreeNode *leftChild() const;
        // Return the address of the left child of this node if one exists,
        // and 0 otherwise.

    const RbTreeNode *rightChild() const;
        // Return the address of the right child of this node if one exists,
        // and 0 otherwise.

    Color color() const;
        // Return the color of this node.
};

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

// PRIVATE METHODS
inline
bsls::Types::UintPtr RbTreeNode::toInt(RbTreeNode *value)
{
    return reinterpret_cast<bsls::Types::UintPtr>(value);
}

inline
RbTreeNode *RbTreeNode::toNode(bsls::Types::UintPtr value)
{
    return reinterpret_cast<RbTreeNode *>(value);
}

// MANIPULATORS
inline
void RbTreeNode::makeBlack()
{
    d_parentWithColor_p = toNode(toInt(d_parentWithColor_p) | 0x01);
}

inline
void RbTreeNode::makeRed()
{
    d_parentWithColor_p = toNode(toInt(d_parentWithColor_p) & ~0x01);
}

inline
void RbTreeNode::setParent(RbTreeNode *address)
{
    BSLS_ASSERT_SAFE(0 == (toInt(address) & 0x01));

    d_parentWithColor_p =
                  toNode(toInt(address) | (toInt(d_parentWithColor_p) & 0x01));
}

inline
void RbTreeNode::setLeftChild(RbTreeNode *address)
{
    d_left_p = address;
}

inline
void RbTreeNode::setRightChild(RbTreeNode *address)
{
    d_right_p = address;
}

inline
void RbTreeNode::setColor(Color value)
{
    d_parentWithColor_p = toNode((toInt(d_parentWithColor_p) & ~0x01) | value);
}

inline
void RbTreeNode::toggleColor()
{
    BSLMF_ASSERT(0 == BSLALG_RED);
    BSLMF_ASSERT(1 == BSLALG_BLACK);

    d_parentWithColor_p = toNode(toInt(d_parentWithColor_p) ^ 0x01);
}

inline
void RbTreeNode::reset(RbTreeNode *parent,
                       RbTreeNode *leftChild,
                       RbTreeNode *rightChild,
                       Color       color)
{
    BSLS_ASSERT_SAFE(0 == (toInt(parent) & 0x01));

    d_parentWithColor_p = toNode(toInt(parent) | color);
    d_left_p = leftChild;
    d_right_p = rightChild;
}

inline
RbTreeNode *RbTreeNode::parent()
{
    return toNode(toInt(d_parentWithColor_p) & ~0x01);
}

inline
RbTreeNode *RbTreeNode::leftChild()
{
    return d_left_p;
}

inline
RbTreeNode *RbTreeNode::rightChild()
{
    return d_right_p;
}

// ACCESSORS
inline
const RbTreeNode *RbTreeNode::parent() const
{
    return toNode(toInt(d_parentWithColor_p) & ~0x01);
}

inline
bool RbTreeNode::isBlack() const
{
    return toInt(d_parentWithColor_p) & 0x01;
}

inline
bool RbTreeNode::isRed() const
{
    return !isBlack();
}

inline
const RbTreeNode *RbTreeNode::leftChild() const
{
    return d_left_p;
}

inline
const RbTreeNode *RbTreeNode::rightChild() const
{
    return d_right_p;
}

inline
RbTreeNode::Color RbTreeNode::color() const
{
    return static_cast<Color>(toInt(d_parentWithColor_p) & 0x01);
}

}  // 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 ----------------------------------