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