Browse Source

Add RBNode::getUpperNode()

Mukund Sivaraman 12 years ago
parent
commit
5d3e852877
2 changed files with 62 additions and 0 deletions
  1. 26 0
      src/lib/datasrc/rbtree.h
  2. 36 0
      src/lib/datasrc/tests/rbtree_unittest.cc

+ 26 - 0
src/lib/datasrc/rbtree.h

@@ -182,6 +182,9 @@ public:
     /// empty nodes anywhere.
     bool isEmpty() const { return (data_.get() == NULL); }
 
+    /// \brief return whether the node is a null node.
+    bool isNull() const { return (this == NULL_NODE()); }
+
     //@}
 
     /// \name Setter functions.
@@ -285,6 +288,18 @@ private:
         return ((flags_ & FLAG_SUBTREE_ROOT) != 0);
     }
 
+public:
+    /// \brief returns the parent of the root of its subtree
+    ///
+    /// This method takes a node and returns the parent of the root of
+    /// its subtree (i.e, it returns the node's immediate ancestor in
+    /// the tree-of-tree hierarchy). If the node is at the top level
+    /// (which should be absolute), it will return \c NULL_NODE().
+    ///
+    /// This method never throws an exception.
+    const RBNode<T>* getUpperNode() const;
+
+private:
     /// \brief return the next node which is bigger than current node
     /// in the same subtree
     ///
@@ -441,6 +456,17 @@ RBNode<T>::~RBNode() {
 
 template <typename T>
 const RBNode<T>*
+RBNode<T>::getUpperNode() const {
+    const RBNode<T>* current = this;
+    while (!current->isSubTreeRoot()) {
+        current = current->getParent();
+    }
+
+    return (current->getParent());
+}
+
+template <typename T>
+const RBNode<T>*
 RBNode<T>::abstractSuccessor(typename RBNode<T>::RBNodePtr RBNode<T>::*left,
                              typename RBNode<T>::RBNodePtr RBNode<T>::*right)
     const

+ 36 - 0
src/lib/datasrc/tests/rbtree_unittest.cc

@@ -374,6 +374,42 @@ const char* const names[] = {
     "g.h", "i.g.h", "k.g.h"};
 const size_t name_count(sizeof(names) / sizeof(*names));
 
+const char* const upper_node_names[] = {
+    NULL, NULL, NULL, NULL, "d.e.f", "d.e.f", "w.y.d.e.f",
+    "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
+    NULL, "g.h", "g.h"};
+
+TEST_F(RBTreeTest, getUpperNode) {
+    RBTreeNodeChain<int> node_path;
+    const RBNode<int>* node = NULL;
+    EXPECT_EQ(RBTree<int>::EXACTMATCH,
+              rbtree_expose_empty_node.find(Name(names[0]),
+                                            &node,
+                                            node_path));
+    for (int i = 0; i < name_count; ++i) {
+        EXPECT_NE(static_cast<void*>(NULL), node);
+
+        const RBNode<int>* upper_node = node->getUpperNode();
+        EXPECT_NE(static_cast<void*>(NULL), upper_node);
+
+        if (upper_node_names[i] != NULL) {
+            const RBNode<int>* upper_node2 = NULL;
+            EXPECT_EQ(RBTree<int>::EXACTMATCH,
+                      rbtree_expose_empty_node.find(Name(upper_node_names[i]),
+                                                    &upper_node2));
+            EXPECT_NE(static_cast<void*>(NULL), upper_node2);
+            EXPECT_FALSE(upper_node2->isNull());
+
+            EXPECT_EQ(upper_node, upper_node2);
+        }
+
+        node = rbtree_expose_empty_node.nextNode(node_path);
+    }
+
+    // We should have reached the end of the tree.
+    EXPECT_EQ(static_cast<void*>(NULL), node);
+}
+
 TEST_F(RBTreeTest, nextNode) {
     RBTreeNodeChain<int> node_path;
     const RBNode<int>* node = NULL;