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 <algorithm> 9 #include <memory> 10 #include <utility> 11 12 #include "core/fxcrt/fx_memory.h" 13 #include "core/fxcrt/fx_system.h" 14 15 namespace fxcrt { 16 17 // A template that can hold either owned or unowned references, and cleans up 18 // appropriately. Possibly the most pernicious anti-pattern imaginable, but 19 // it crops up throughout the codebase due to a desire to avoid copying-in 20 // objects or data. 21 template <typename T, typename D = std::default_delete<T>> 22 class MaybeOwned { 23 public: MaybeOwned()24 MaybeOwned() : m_pObj(nullptr) {} MaybeOwned(T * ptr)25 explicit MaybeOwned(T* ptr) : m_pObj(ptr) {} 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_pOwnedObj = std::move(ptr); 37 m_pObj = m_pOwnedObj.get(); 38 } 39 void Reset(T* ptr = nullptr) { 40 m_pOwnedObj.reset(); 41 m_pObj = ptr; 42 } 43 IsOwned()44 bool IsOwned() const { return !!m_pOwnedObj; } Get()45 T* Get() const { return m_pObj; } Release()46 std::unique_ptr<T, D> Release() { 47 ASSERT(IsOwned()); 48 return std::move(m_pOwnedObj); 49 } 50 51 MaybeOwned& operator=(const MaybeOwned& that) = delete; 52 MaybeOwned& operator=(MaybeOwned&& that) { 53 m_pOwnedObj = std::move(that.m_pOwnedObj); 54 m_pObj = that.m_pObj; 55 that.m_pObj = nullptr; 56 return *this; 57 } 58 MaybeOwned& operator=(T* ptr) { 59 Reset(ptr); 60 return *this; 61 } 62 MaybeOwned& operator=(std::unique_ptr<T, D> ptr) { 63 Reset(std::move(ptr)); 64 return *this; 65 } 66 67 bool operator==(const MaybeOwned& that) const { return Get() == that.Get(); } 68 bool operator==(const std::unique_ptr<T, D>& ptr) const { 69 return Get() == ptr.get(); 70 } 71 bool operator==(T* ptr) const { return Get() == ptr; } 72 73 bool operator!=(const MaybeOwned& that) const { return !(*this == that); } 74 bool operator!=(const std::unique_ptr<T, D> ptr) const { 75 return !(*this == ptr); 76 } 77 bool operator!=(T* ptr) const { return !(*this == ptr); } 78 79 explicit operator bool() const { return !!m_pObj; } 80 T& operator*() const { return *m_pObj; } 81 T* operator->() const { return m_pObj; } 82 83 private: 84 std::unique_ptr<T, D> m_pOwnedObj; 85 T* m_pObj; 86 }; 87 88 } // namespace fxcrt 89 90 using fxcrt::MaybeOwned; 91 92 #endif // CORE_FXCRT_MAYBE_OWNED_H_ 93