1 // Copyright 2016 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_MAYBE_OWNED_H_ 6 #define CORE_FXCRT_MAYBE_OWNED_H_ 7 8 #include <memory> 9 #include <utility> 10 11 #include "core/fxcrt/fx_system.h" 12 #include "core/fxcrt/unowned_ptr.h" 13 14 namespace fxcrt { 15 16 // A template that can hold either owned or unowned references, and cleans up 17 // appropriately. Possibly the most pernicious anti-pattern imaginable, but 18 // it crops up throughout the codebase due to a desire to avoid copying-in 19 // objects or data. 20 template <typename T, typename D = std::default_delete<T>> 21 class MaybeOwned { 22 public: 23 MaybeOwned() = default; MaybeOwned(T * ptr)24 explicit MaybeOwned(T* ptr) : m_pObj(ptr) {} MaybeOwned(const UnownedPtr<T> & ptr)25 explicit MaybeOwned(const UnownedPtr<T>& ptr) : m_pObj(ptr.Get()) {} MaybeOwned(std::unique_ptr<T,D> ptr)26 explicit MaybeOwned(std::unique_ptr<T, D> ptr) 27 : m_pOwnedObj(std::move(ptr)), m_pObj(m_pOwnedObj.get()) {} 28 29 MaybeOwned(const MaybeOwned& that) = delete; MaybeOwned(MaybeOwned && that)30 MaybeOwned(MaybeOwned&& that) noexcept 31 : m_pOwnedObj(that.m_pOwnedObj.release()), m_pObj(that.m_pObj) { 32 that.m_pObj = nullptr; 33 } 34 Reset(std::unique_ptr<T,D> ptr)35 void Reset(std::unique_ptr<T, D> ptr) { 36 m_pObj = ptr.get(); 37 m_pOwnedObj = std::move(ptr); 38 } 39 void Reset(T* ptr = nullptr) { 40 m_pObj = ptr; 41 m_pOwnedObj.reset(); 42 } 43 // Helpful for untangling a collection of intertwined MaybeOwned<>. ResetIfUnowned()44 void ResetIfUnowned() { 45 if (!IsOwned()) 46 Reset(); 47 } 48 Get()49 T* Get() const { return m_pObj.Get(); } IsOwned()50 bool IsOwned() const { return !!m_pOwnedObj; } 51 52 // Downgrades to unowned, caller takes ownership. Release()53 std::unique_ptr<T, D> Release() { 54 ASSERT(IsOwned()); 55 return std::move(m_pOwnedObj); 56 } 57 58 // Downgrades to empty, caller takes ownership. ReleaseAndClear()59 std::unique_ptr<T, D> ReleaseAndClear() { 60 ASSERT(IsOwned()); 61 m_pObj = nullptr; 62 return std::move(m_pOwnedObj); 63 } 64 65 MaybeOwned& operator=(const MaybeOwned& that) = delete; 66 MaybeOwned& operator=(MaybeOwned&& that) { 67 m_pObj = that.m_pObj; 68 m_pOwnedObj = std::move(that.m_pOwnedObj); 69 that.m_pObj = nullptr; 70 return *this; 71 } 72 MaybeOwned& operator=(T* ptr) { 73 Reset(ptr); 74 return *this; 75 } 76 MaybeOwned& operator=(const UnownedPtr<T>& ptr) { 77 Reset(ptr.Get()); 78 return *this; 79 } 80 MaybeOwned& operator=(std::unique_ptr<T, D> ptr) { 81 Reset(std::move(ptr)); 82 return *this; 83 } 84 85 bool operator==(const MaybeOwned& that) const { return Get() == that.Get(); } 86 bool operator==(const std::unique_ptr<T, D>& ptr) const { 87 return Get() == ptr.get(); 88 } 89 bool operator==(T* ptr) const { return Get() == ptr; } 90 91 bool operator!=(const MaybeOwned& that) const { return !(*this == that); } 92 bool operator!=(const std::unique_ptr<T, D> ptr) const { 93 return !(*this == ptr); 94 } 95 bool operator!=(T* ptr) const { return !(*this == ptr); } 96 97 explicit operator bool() const { return !!m_pObj; } 98 T& operator*() const { return *m_pObj; } 99 T* operator->() const { return m_pObj.Get(); } 100 101 private: 102 std::unique_ptr<T, D> m_pOwnedObj; 103 UnownedPtr<T> m_pObj; 104 }; 105 106 } // namespace fxcrt 107 108 using fxcrt::MaybeOwned; 109 110 #endif // CORE_FXCRT_MAYBE_OWNED_H_ 111