[coco] Support 'detach' operation (#828)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Thu, 26 Jul 2018 04:50:33 +0000 (13:50 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Thu, 26 Jul 2018 04:50:33 +0000 (13:50 +0900)
This commit implements 'detach' operation for DLinkedList.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/coco/core/include/coco/ADT/DLinkedList.h
contrib/coco/core/src/ADT/DLinkedList.test.cpp

index 20b8d3a..ea46633 100644 (file)
@@ -75,6 +75,26 @@ template<typename Child, typename Parent> struct DLinkedList
     }
 
   public:
+    void delist(Child *child)
+    {
+      assert(child->parent() == _parent);
+      assert(!empty());
+
+      if (child == _head)
+      {
+        _head = child->next();
+      }
+
+      if (child == _tail)
+      {
+        _tail = child->prev();
+      }
+
+      // Update parent-child relation
+      _link->unset(child);
+    }
+
+  public:
     void prepend(Child *child)
     {
       if (empty())
@@ -188,6 +208,34 @@ template<typename Child, typename Parent> struct DLinkedList
       assert(parent() == prev->parent());
     };
 
+  public:
+    void detach(void)
+    {
+      // REQUIRE Child SHOULD inherit Node class
+      auto curr = reinterpret_cast<Child *>(this);
+
+      // Update parent-child relation
+      assert(parent() != nullptr);
+      assert(head() != nullptr);
+      head()->delist(curr);
+      assert(parent() == nullptr);
+
+      // Update the link of sibling nodes
+      if (auto prev = curr->prev())
+      {
+        prev->_next = curr->next();
+      }
+
+      if (auto next = curr->next())
+      {
+        next->_prev = curr->prev();
+      }
+
+      // Update the link of the current node
+      _prev = nullptr;
+      _next = nullptr;
+    }
+
   private:
     const PtrLink<Child, Parent> * const _link;
 
index 0883838..42fef2b 100644 (file)
@@ -140,3 +140,42 @@ TEST(ADT_DLINKED_LINK, prepend_after_append)
   delete parent;
   delete link;
 }
+
+TEST(ADT_DLINKED_LINK, detach)
+{
+  auto link = new coco::PtrLink<::Child, ::Parent>{};
+  auto parent = new ::Parent{link};
+
+  auto child_1 = new ::Child{link};
+  auto child_2 = new ::Child{link};
+
+  parent->children()->append(child_1);
+  parent->children()->append(child_2);
+  
+  child_1->detach();
+
+  ASSERT_EQ(child_1->parent(), nullptr);
+  ASSERT_EQ(child_1->prev(), nullptr);
+  ASSERT_EQ(child_1->next(), nullptr);
+
+  ASSERT_EQ(child_2->parent(), parent);
+  ASSERT_EQ(child_2->prev(), nullptr);
+  
+  ASSERT_EQ(parent->children()->head(), child_2);
+  ASSERT_EQ(parent->children()->tail(), child_2);
+
+  child_2->detach();
+
+  ASSERT_EQ(child_2->parent(), nullptr);
+  ASSERT_EQ(child_2->prev(), nullptr);
+  ASSERT_EQ(child_2->next(), nullptr);
+
+  ASSERT_TRUE(parent->children()->empty());
+  ASSERT_EQ(parent->children()->head(), nullptr);
+  ASSERT_EQ(parent->children()->tail(), nullptr);
+
+  delete child_2;
+  delete child_1;
+  delete parent;
+  delete link;
+}