1 // Copyright 2019 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CORE_FXCRT_RETAINED_TREE_NODE_H_
6 #define CORE_FXCRT_RETAINED_TREE_NODE_H_
7 
8 #include "core/fxcrt/retain_ptr.h"
9 #include "core/fxcrt/tree_node.h"
10 #include "third_party/base/logging.h"
11 
12 namespace fxcrt {
13 
14 // For DOM/XML-ish trees, where references outside the tree are RetainPtr<T>,
15 // and the parent node also "retains" its children but doesn't always have
16 // a direct pointer to them.
17 template <typename T>
18 class RetainedTreeNode : public TreeNode<T> {
19  public:
20   template <typename U, typename... Args>
21   friend RetainPtr<U> pdfium::MakeRetain(Args&&... args);
22 
AppendFirstChild(const RetainPtr<T> & child)23   void AppendFirstChild(const RetainPtr<T>& child) {
24     TreeNode<T>::AppendFirstChild(child.Get());
25   }
26 
AppendLastChild(const RetainPtr<T> & child)27   void AppendLastChild(const RetainPtr<T>& child) {
28     TreeNode<T>::AppendLastChild(child.Get());
29   }
30 
InsertBefore(const RetainPtr<T> & child,T * other)31   void InsertBefore(const RetainPtr<T>& child, T* other) {
32     TreeNode<T>::InsertBefore(child.Get(), other);
33   }
34 
InsertAfter(const RetainPtr<T> & child,T * other)35   void InsertAfter(const RetainPtr<T>& child, T* other) {
36     TreeNode<T>::InsertAfter(child.Get(), other);
37   }
38 
RemoveChild(const RetainPtr<T> & child)39   void RemoveChild(const RetainPtr<T>& child) {
40     TreeNode<T>::RemoveChild(child.Get());
41   }
42 
RemoveSelfIfParented()43   void RemoveSelfIfParented() {
44     if (T* parent = TreeNode<T>::GetParent()) {
45       parent->TreeNode<T>::RemoveChild(
46           pdfium::WrapRetain(static_cast<T*>(this)).Get());
47     }
48   }
49 
50  protected:
51   RetainedTreeNode() = default;
~RetainedTreeNode()52   ~RetainedTreeNode() override {
53     while (auto* pChild = TreeNode<T>::GetFirstChild())
54       RemoveChild(pdfium::WrapRetain(pChild));
55   }
56 
57  private:
58   template <typename U>
59   friend struct ReleaseDeleter;
60 
61   template <typename U>
62   friend class RetainPtr;
63 
64   RetainedTreeNode(const RetainedTreeNode& that) = delete;
65   RetainedTreeNode& operator=(const RetainedTreeNode& that) = delete;
66 
Retain()67   void Retain() { ++m_nRefCount; }
Release()68   void Release() {
69     ASSERT(m_nRefCount > 0);
70     if (--m_nRefCount == 0 && !TreeNode<T>::GetParent())
71       delete this;
72   }
73 
74   intptr_t m_nRefCount = 0;
75 };
76 
77 }  // namespace fxcrt
78 
79 using fxcrt::RetainedTreeNode;
80 
81 #endif  // CORE_FXCRT_RETAINED_TREE_NODE_H_
82