Add more helper methods to tree_node.h
Adds RemoveSelfIfParented(), RemoveAllChildren() and GetNthChild(). The
last two are expected to be useful for converting CFX_XMLNode over
to TreeNodes.
Change-Id: Ib03464e994416156a9d79c4c229af77e413b64c3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/54350
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/tree_node.h b/core/fxcrt/tree_node.h
index 7f1f46a..656d743 100644
--- a/core/fxcrt/tree_node.h
+++ b/core/fxcrt/tree_node.h
@@ -27,6 +27,15 @@
return child != this && child->m_pParent == this;
}
+ T* GetNthChild(size_t n) {
+ T* result = GetFirstChild();
+ while (n && result) {
+ result = result->GetNextSibling();
+ --n;
+ }
+ return result;
+ }
+
void AppendFirstChild(T* child) {
BecomeParent(child);
if (m_pFirstChild) {
@@ -110,6 +119,16 @@
child->m_pNextSibling = nullptr;
}
+ void RemoveAllChildren() {
+ while (T* child = GetFirstChild())
+ RemoveChild(child);
+ }
+
+ void RemoveSelfIfParented() {
+ if (T* parent = GetParent())
+ parent->RemoveChild(static_cast<T*>(this));
+ }
+
private:
// Child left in state where sibling members need subsequent adjustment.
void BecomeParent(T* child) {
diff --git a/core/fxcrt/tree_node_unittest.cpp b/core/fxcrt/tree_node_unittest.cpp
index f2334cf..748c1be 100644
--- a/core/fxcrt/tree_node_unittest.cpp
+++ b/core/fxcrt/tree_node_unittest.cpp
@@ -67,4 +67,56 @@
EXPECT_DEATH(pBadParent->RemoveChild(pNode.get()), "");
}
+TEST(TreeNode, SafeRemove) {
+ auto pParent = pdfium::MakeUnique<TestTreeNode>();
+ auto pChild = pdfium::MakeUnique<TestTreeNode>();
+ pParent->AppendFirstChild(pChild.get());
+ pChild->RemoveSelfIfParented();
+ EXPECT_EQ(nullptr, pParent->GetFirstChild());
+ EXPECT_EQ(nullptr, pChild->GetParent());
+}
+
+TEST(TreeNode, SafeRemoveParentless) {
+ auto pNode = pdfium::MakeUnique<TestTreeNode>();
+ pNode->RemoveSelfIfParented();
+ EXPECT_EQ(nullptr, pNode->GetParent());
+}
+
+TEST(TreeNode, RemoveAllChildren) {
+ auto pParent = pdfium::MakeUnique<TestTreeNode>();
+ pParent->RemoveAllChildren();
+ EXPECT_EQ(nullptr, pParent->GetFirstChild());
+
+ auto p0 = pdfium::MakeUnique<TestTreeNode>();
+ auto p1 = pdfium::MakeUnique<TestTreeNode>();
+ auto p2 = pdfium::MakeUnique<TestTreeNode>();
+ auto p3 = pdfium::MakeUnique<TestTreeNode>();
+ pParent->AppendLastChild(p0.get());
+ pParent->AppendLastChild(p1.get());
+ pParent->AppendLastChild(p2.get());
+ pParent->AppendLastChild(p3.get());
+ pParent->RemoveAllChildren();
+ EXPECT_EQ(nullptr, pParent->GetFirstChild());
+}
+
+TEST(TreeNode, NthChild) {
+ auto pParent = pdfium::MakeUnique<TestTreeNode>();
+ EXPECT_EQ(nullptr, pParent->GetNthChild(0));
+
+ auto p0 = pdfium::MakeUnique<TestTreeNode>();
+ auto p1 = pdfium::MakeUnique<TestTreeNode>();
+ auto p2 = pdfium::MakeUnique<TestTreeNode>();
+ auto p3 = pdfium::MakeUnique<TestTreeNode>();
+ pParent->AppendLastChild(p0.get());
+ pParent->AppendLastChild(p1.get());
+ pParent->AppendLastChild(p2.get());
+ pParent->AppendLastChild(p3.get());
+ EXPECT_EQ(p0.get(), pParent->GetNthChild(0));
+ EXPECT_EQ(p1.get(), pParent->GetNthChild(1));
+ EXPECT_EQ(p2.get(), pParent->GetNthChild(2));
+ EXPECT_EQ(p3.get(), pParent->GetNthChild(3));
+ EXPECT_EQ(nullptr, pParent->GetNthChild(4));
+ pParent->RemoveAllChildren();
+}
+
} // namespace fxcrt
diff --git a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
index 12e8a28..0a22d25 100644
--- a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
@@ -804,8 +804,7 @@
CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem;
if (pLayoutItem) {
m_pLayoutItem = ToContentLayoutItem(pLayoutItem->GetNextSibling());
- if (pLayoutItem->GetParent())
- pLayoutItem->GetParent()->RemoveChild(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
}
if (m_nCurChildNodeStage != Stage::kDone || !m_pOldLayoutItem)
return pLayoutItem;
@@ -821,8 +820,7 @@
if (pToDeleteItem == pLayoutItem)
break;
pNotify->OnLayoutItemRemoving(pDocLayout, pToDeleteItem);
- if (pToDeleteItem->GetParent())
- pToDeleteItem->GetParent()->RemoveChild(pToDeleteItem);
+ pToDeleteItem->RemoveSelfIfParented();
delete pToDeleteItem;
}
return pLayoutItem;
@@ -1598,8 +1596,7 @@
while (pLayoutNextTemp) {
CXFA_ContentLayoutItem* pSaveLayoutNext =
ToContentLayoutItem(pLayoutNextTemp->GetNextSibling());
- if (pLayoutNextTemp->GetParent())
- pLayoutNextTemp->GetParent()->RemoveChild(pLayoutNextTemp);
+ pLayoutNextTemp->RemoveSelfIfParented();
pLayoutNextTemp = pSaveLayoutNext;
}
pLastChild = nullptr;
diff --git a/xfa/fxfa/layout/cxfa_layoutitem.cpp b/xfa/fxfa/layout/cxfa_layoutitem.cpp
index a59da61..f39ba88 100644
--- a/xfa/fxfa/layout/cxfa_layoutitem.cpp
+++ b/xfa/fxfa/layout/cxfa_layoutitem.cpp
@@ -29,8 +29,7 @@
pNotify->OnPageEvent(ToViewLayoutItem(pLayoutItem),
XFA_PAGEVIEWEVENT_PostRemoved);
}
- if (pLayoutItem->GetParent())
- pLayoutItem->GetParent()->RemoveChild(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
delete pLayoutItem;
}
@@ -44,8 +43,7 @@
if (pLayoutItem->GetFormNode()->GetElementType() == XFA_Element::PageArea)
return;
- if (pLayoutItem->GetParent())
- pLayoutItem->GetParent()->RemoveChild(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
delete pLayoutItem;
}
diff --git a/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp b/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
index d9c4e11..700eba5 100644
--- a/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
+++ b/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
@@ -167,14 +167,6 @@
pParentLayoutItem->AppendLastChild(pLayoutItem);
}
-void RemoveLayoutItem(CXFA_LayoutItem* pLayoutItem) {
- CXFA_LayoutItem* pParentLayoutItem = pLayoutItem->GetParent();
- if (!pParentLayoutItem)
- return;
-
- pParentLayoutItem->RemoveChild(pLayoutItem);
-}
-
CXFA_Node* ResolveBreakTarget(CXFA_Node* pPageSetRoot,
bool bNewExprStyle,
WideString* pTargetAll) {
@@ -262,7 +254,7 @@
SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);
pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem);
- RemoveLayoutItem(pCurLayoutItem);
+ pCurLayoutItem->RemoveSelfIfParented();
delete pCurLayoutItem;
pCurLayoutItem = pNextLayoutItem;
}
@@ -388,7 +380,7 @@
ASSERT(m_pTemplatePageSetRoot);
if (m_pPageSetLayoutItemRoot) {
- RemoveLayoutItem(m_pPageSetLayoutItemRoot);
+ m_pPageSetLayoutItemRoot->RemoveSelfIfParented();
} else {
m_pPageSetLayoutItemRoot =
new CXFA_ViewLayoutItem(m_pTemplatePageSetRoot, nullptr);
@@ -522,15 +514,15 @@
if (!pNewRecord || !pPrevRecord)
return;
if (pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) {
- RemoveLayoutItem(pNewRecord->pCurPageSet);
+ pNewRecord->pCurPageSet->RemoveSelfIfParented();
return;
}
if (pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) {
- RemoveLayoutItem(pNewRecord->pCurPageArea);
+ pNewRecord->pCurPageArea->RemoveSelfIfParented();
return;
}
if (pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) {
- RemoveLayoutItem(pNewRecord->pCurContentArea);
+ pNewRecord->pCurContentArea->RemoveSelfIfParented();
return;
}
}
@@ -1622,7 +1614,7 @@
SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);
pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem);
- RemoveLayoutItem(pCurLayoutItem);
+ pCurLayoutItem->RemoveSelfIfParented();
delete pCurLayoutItem;
pCurLayoutItem = pNextLayoutItem;
continue;
@@ -1641,7 +1633,7 @@
if (pCurLayoutItem->GetFirstChild())
SaveLayoutItem(pCurLayoutItem);
- RemoveLayoutItem(pCurLayoutItem);
+ pCurLayoutItem->RemoveSelfIfParented();
if (!pCurLayoutItem->IsContentLayoutItem() &&
pCurLayoutItem->GetFormNode()->GetElementType() !=
XFA_Element::PageArea) {
@@ -1768,7 +1760,7 @@
pIter->JSObject()->GetLayoutItem();
if (pLayoutItem) {
pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem);
- RemoveLayoutItem(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
delete pLayoutItem;
}
}
@@ -1834,7 +1826,7 @@
pChildNode->JSObject()->GetLayoutItem();
if (pLayoutItem) {
pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem);
- RemoveLayoutItem(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
delete pLayoutItem;
}
}
@@ -1842,7 +1834,7 @@
CXFA_LayoutItem* pLayoutItem = pNode->JSObject()->GetLayoutItem();
if (pLayoutItem) {
pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem);
- RemoveLayoutItem(pLayoutItem);
+ pLayoutItem->RemoveSelfIfParented();
delete pLayoutItem;
}
}
@@ -1971,7 +1963,7 @@
for (; pRootLayoutItem; pRootLayoutItem = pNextLayout) {
pNextLayout = ToViewLayoutItem(pRootLayoutItem->GetNextSibling());
SaveLayoutItem(pRootLayoutItem);
- RemoveLayoutItem(pRootLayoutItem);
+ pRootLayoutItem->RemoveSelfIfParented();
delete pRootLayoutItem;
}
m_pPageSetLayoutItemRoot = nullptr;