// 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_RETAINED_TREE_NODE_H_ #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 { // For DOM/XML-ish trees, where references outside the tree are RetainPtr, // and the parent node also "retains" its children but doesn't always have // a direct pointer to them. template class RetainedTreeNode : public TreeNode { public: template friend RetainPtr pdfium::MakeRetain(Args&&... args); void AppendFirstChild(const RetainPtr& child) { TreeNode::AppendFirstChild(child.Get()); } void AppendLastChild(const RetainPtr& child) { TreeNode::AppendLastChild(child.Get()); } void InsertBefore(const RetainPtr& child, T* other) { TreeNode::InsertBefore(child.Get(), other); } void InsertAfter(const RetainPtr& child, T* other) { TreeNode::InsertAfter(child.Get(), other); } void RemoveChild(const RetainPtr& child) { TreeNode::RemoveChild(child.Get()); } void RemoveSelfIfParented() { if (T* parent = TreeNode::GetParent()) { parent->TreeNode::RemoveChild( pdfium::WrapRetain(static_cast(this)).Get()); } } protected: RetainedTreeNode() = default; ~RetainedTreeNode() override { while (auto* pChild = TreeNode::GetFirstChild()) RemoveChild(pdfium::WrapRetain(pChild)); } private: template friend struct ReleaseDeleter; template friend class RetainPtr; RetainedTreeNode(const RetainedTreeNode& that) = delete; RetainedTreeNode& operator=(const RetainedTreeNode& that) = delete; void Retain() { ++m_nRefCount; } void Release() { ASSERT(m_nRefCount > 0); if (--m_nRefCount == 0 && !TreeNode::GetParent()) delete this; } intptr_t m_nRefCount = 0; }; } // namespace fxcrt using fxcrt::RetainedTreeNode; #endif // CORE_FXCRT_RETAINED_TREE_NODE_H_