Split retain_tree_node.h into non-retained tree_node.h version.

Enables a smaller follow-on CL in XFA.

Change-Id: I971ea6254eaefa2bf61bde9a56874d12bb5f7bfe
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53492
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index 2221af1..f74c3d3 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -61,6 +61,7 @@
     "string_data_template.h",
     "string_pool_template.h",
     "string_view_template.h",
+    "tree_node.h",
     "unowned_ptr.h",
     "weak_ptr.h",
     "widestring.cpp",
diff --git a/core/fxcrt/retained_tree_node.h b/core/fxcrt/retained_tree_node.h
index 8b29e69..e091fb5 100644
--- a/core/fxcrt/retained_tree_node.h
+++ b/core/fxcrt/retained_tree_node.h
@@ -6,6 +6,7 @@
 #define CORE_FXCRT_RETAINED_TREE_NODE_H_
 
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/tree_node.h"
 #include "third_party/base/logging.h"
 
 namespace fxcrt {
@@ -14,95 +15,36 @@
 // and the parent node also "retains" its children but doesn't always have
 // a direct pointer to them.
 template <typename T>
-class RetainedTreeNode {
+class RetainedTreeNode : public TreeNode<T> {
  public:
   template <typename U, typename... Args>
   friend RetainPtr<U> pdfium::MakeRetain(Args&&... args);
 
-  T* GetParent() const { return m_pParent; }
-  T* GetFirstChild() const { return m_pFirstChild; }
-  T* GetLastChild() const { return m_pLastChild; }
-  T* GetNextSibling() const { return m_pNextSibling; }
-  T* GetPrevSibling() const { return m_pPrevSibling; }
-
   void AppendFirstChild(const RetainPtr<T>& child) {
-    BecomeParent(child);
-    if (m_pFirstChild) {
-      m_pFirstChild->m_pPrevSibling = child.Get();
-      child->m_pNextSibling = m_pFirstChild;
-      m_pFirstChild = child.Get();
-    } else {
-      m_pFirstChild = child.Get();
-      m_pLastChild = child.Get();
-    }
+    TreeNode<T>::AppendFirstChild(child.Get());
   }
 
   void AppendLastChild(const RetainPtr<T>& child) {
-    BecomeParent(child);
-    if (m_pLastChild) {
-      m_pLastChild->m_pNextSibling = child.Get();
-      child->m_pPrevSibling = m_pLastChild;
-      m_pLastChild = child.Get();
-    } else {
-      m_pFirstChild = child.Get();
-      m_pLastChild = child.Get();
-    }
+    TreeNode<T>::AppendLastChild(child.Get());
   }
 
   void InsertBefore(const RetainPtr<T>& child, T* other) {
-    if (!other) {
-      AppendLastChild(child);
-      return;
-    }
-    CHECK(other->m_pParent == this);
-    BecomeParent(child);
-    child->m_pNextSibling = other;
-    child->m_pPrevSibling = other->m_pPrevSibling;
-    if (other->m_pPrevSibling)
-      other->m_pPrevSibling->m_pNextSibling = child.Get();
-    else
-      m_pFirstChild = child.Get();
-    other->m_pPrevSibling = child.Get();
+    TreeNode<T>::InsertBefore(child.Get(), other);
   }
 
   void InsertAfter(const RetainPtr<T>& child, T* other) {
-    if (!other) {
-      AppendFirstChild(child);
-      return;
-    }
-    CHECK(other->m_pParent == this);
-    BecomeParent(child);
-    child->m_pNextSibling = other->m_pNextSibling;
-    child->m_pPrevSibling = other;
-    if (other->m_pNextSibling)
-      other->m_pNextSibling->m_pPrevSibling = child.Get();
-    else
-      m_pLastChild = child.Get();
-    other->m_pNextSibling = child.Get();
+    TreeNode<T>::InsertAfter(child.Get(), other);
   }
 
   void RemoveChild(const RetainPtr<T>& child) {
-    CHECK(child->m_pParent == this);
-    if (child->m_pNextSibling)
-      child->m_pNextSibling->m_pPrevSibling = child->m_pPrevSibling;
-    else
-      m_pLastChild = child->m_pPrevSibling;
-
-    if (child->m_pPrevSibling)
-      child->m_pPrevSibling->m_pNextSibling = child->m_pNextSibling;
-    else
-      m_pFirstChild = child->m_pNextSibling;
-
-    child->m_pParent = nullptr;
-    child->m_pPrevSibling = nullptr;
-    child->m_pNextSibling = nullptr;
+    TreeNode<T>::RemoveChild(child.Get());
   }
 
  protected:
   RetainedTreeNode() = default;
-  virtual ~RetainedTreeNode() {
-    while (m_pFirstChild)
-      RemoveChild(pdfium::WrapRetain(m_pFirstChild));
+  ~RetainedTreeNode() override {
+    while (auto* pChild = TreeNode<T>::GetFirstChild())
+      RemoveChild(pdfium::WrapRetain(pChild));
   }
 
  private:
@@ -118,25 +60,11 @@
   void Retain() { ++m_nRefCount; }
   void Release() {
     ASSERT(m_nRefCount > 0);
-    if (--m_nRefCount == 0 && !m_pParent)
+    if (--m_nRefCount == 0 && !TreeNode<T>::GetParent())
       delete this;
   }
 
-  // Child left in state where sibling members need subsequent adjustment.
-  void BecomeParent(const RetainPtr<T>& child) {
-    if (child->m_pParent)
-      child->m_pParent->RemoveChild(child);
-    child->m_pParent = static_cast<T*>(this);
-    ASSERT(!child->m_pNextSibling);
-    ASSERT(!child->m_pPrevSibling);
-  }
-
   intptr_t m_nRefCount = 0;
-  T* m_pParent = nullptr;       // Raw, intra-tree pointer.
-  T* m_pFirstChild = nullptr;   // Raw, intra-tree pointer.
-  T* m_pLastChild = nullptr;    // Raw, intra-tree pointer.
-  T* m_pNextSibling = nullptr;  // Raw, intra-tree pointer
-  T* m_pPrevSibling = nullptr;  // Raw, intra-tree pointer
 };
 
 }  // namespace fxcrt
diff --git a/core/fxcrt/tree_node.h b/core/fxcrt/tree_node.h
new file mode 100644
index 0000000..7bded93
--- /dev/null
+++ b/core/fxcrt/tree_node.h
@@ -0,0 +1,120 @@
+// Copyright 2019 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CORE_FXCRT_TREE_NODE_H_
+#define CORE_FXCRT_TREE_NODE_H_
+
+#include "core/fxcrt/fx_system.h"
+#include "third_party/base/logging.h"
+
+namespace fxcrt {
+
+// Implements the usual DOM/XML-ish trees.
+template <typename T>
+class TreeNode {
+ public:
+  TreeNode() = default;
+  virtual ~TreeNode() = default;
+
+  T* GetParent() const { return m_pParent; }
+  T* GetFirstChild() const { return m_pFirstChild; }
+  T* GetLastChild() const { return m_pLastChild; }
+  T* GetNextSibling() const { return m_pNextSibling; }
+  T* GetPrevSibling() const { return m_pPrevSibling; }
+
+  void AppendFirstChild(T* child) {
+    BecomeParent(child);
+    if (m_pFirstChild) {
+      m_pFirstChild->m_pPrevSibling = child;
+      child->m_pNextSibling = m_pFirstChild;
+      m_pFirstChild = child;
+    } else {
+      m_pFirstChild = child;
+      m_pLastChild = child;
+    }
+  }
+
+  void AppendLastChild(T* child) {
+    BecomeParent(child);
+    if (m_pLastChild) {
+      m_pLastChild->m_pNextSibling = child;
+      child->m_pPrevSibling = m_pLastChild;
+      m_pLastChild = child;
+    } else {
+      m_pFirstChild = child;
+      m_pLastChild = child;
+    }
+  }
+
+  void InsertBefore(T* child, T* other) {
+    if (!other) {
+      AppendLastChild(child);
+      return;
+    }
+    CHECK(other->m_pParent == this);
+    BecomeParent(child);
+    child->m_pNextSibling = other;
+    child->m_pPrevSibling = other->m_pPrevSibling;
+    if (other->m_pPrevSibling)
+      other->m_pPrevSibling->m_pNextSibling = child;
+    else
+      m_pFirstChild = child;
+    other->m_pPrevSibling = child;
+  }
+
+  void InsertAfter(T* child, T* other) {
+    if (!other) {
+      AppendFirstChild(child);
+      return;
+    }
+    CHECK(other->m_pParent == this);
+    BecomeParent(child);
+    child->m_pNextSibling = other->m_pNextSibling;
+    child->m_pPrevSibling = other;
+    if (other->m_pNextSibling)
+      other->m_pNextSibling->m_pPrevSibling = child;
+    else
+      m_pLastChild = child;
+    other->m_pNextSibling = child;
+  }
+
+  void RemoveChild(T* child) {
+    CHECK(child->m_pParent == this);
+    if (child->m_pNextSibling)
+      child->m_pNextSibling->m_pPrevSibling = child->m_pPrevSibling;
+    else
+      m_pLastChild = child->m_pPrevSibling;
+
+    if (child->m_pPrevSibling)
+      child->m_pPrevSibling->m_pNextSibling = child->m_pNextSibling;
+    else
+      m_pFirstChild = child->m_pNextSibling;
+
+    child->m_pParent = nullptr;
+    child->m_pPrevSibling = nullptr;
+    child->m_pNextSibling = nullptr;
+  }
+
+ private:
+  // Child left in state where sibling members need subsequent adjustment.
+  void BecomeParent(T* child) {
+    if (child->m_pParent)
+      child->m_pParent->TreeNode<T>::RemoveChild(child);
+    child->m_pParent = static_cast<T*>(this);
+    ASSERT(!child->m_pNextSibling);
+    ASSERT(!child->m_pPrevSibling);
+  }
+
+  T* m_pParent = nullptr;       // Raw, intra-tree pointer.
+  T* m_pFirstChild = nullptr;   // Raw, intra-tree pointer.
+  T* m_pLastChild = nullptr;    // Raw, intra-tree pointer.
+  T* m_pNextSibling = nullptr;  // Raw, intra-tree pointer
+  T* m_pPrevSibling = nullptr;  // Raw, intra-tree pointer
+};
+
+}  // namespace fxcrt
+
+using fxcrt::TreeNode;
+
+#endif  // CORE_FXCRT_TREE_NODE_H_