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_CFX_MAYBE_OWNED_H_ 6 #define CORE_FXCRT_CFX_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 // A template that can hold either owned or unowned references, and cleans up 16 // appropriately. Possibly the most pernicious anti-pattern imaginable, but 17 // it crops up throughout the codebase due to a desire to avoid copying-in 18 // objects or data. 19 template <typename T, typename D = std::default_delete<T>> 20 class CFX_MaybeOwned { 21 public: CFX_MaybeOwned()22 CFX_MaybeOwned() : m_pObj(nullptr) {} CFX_MaybeOwned(T * ptr)23 explicit CFX_MaybeOwned(T* ptr) : m_pObj(ptr) {} CFX_MaybeOwned(std::unique_ptr<T,D> ptr)24 explicit CFX_MaybeOwned(std::unique_ptr<T, D> ptr) 25 : m_pOwnedObj(std::move(ptr)), m_pObj(m_pOwnedObj.get()) {} 26 27 CFX_MaybeOwned(const CFX_MaybeOwned& that) = delete; CFX_MaybeOwned(CFX_MaybeOwned && that)28 CFX_MaybeOwned(CFX_MaybeOwned&& that) 29 : m_pOwnedObj(that.m_pOwnedObj.release()), m_pObj(that.m_pObj) { 30 that.m_pObj = nullptr; 31 } 32 Reset(std::unique_ptr<T,D> ptr)33 void Reset(std::unique_ptr<T, D> ptr) { 34 m_pOwnedObj = std::move(ptr); 35 m_pObj = m_pOwnedObj.get(); 36 } 37 void Reset(T* ptr = nullptr) { 38 m_pOwnedObj.reset(); 39 m_pObj = ptr; 40 } 41 IsOwned()42 bool IsOwned() const { return !!m_pOwnedObj; } Get()43 T* Get() const { return m_pObj; } Release()44 std::unique_ptr<T, D> Release() { 45 ASSERT(IsOwned()); 46 return std::move(m_pOwnedObj); 47 } 48 49 CFX_MaybeOwned& operator=(const CFX_MaybeOwned& that) = delete; 50 CFX_MaybeOwned& operator=(CFX_MaybeOwned&& that) { 51 m_pOwnedObj = std::move(that.m_pOwnedObj); 52 m_pObj = that.m_pObj; 53 that.m_pObj = nullptr; 54 return *this; 55 } 56 CFX_MaybeOwned& operator=(T* ptr) { 57 Reset(ptr); 58 return *this; 59 } 60 CFX_MaybeOwned& operator=(std::unique_ptr<T, D> ptr) { 61 Reset(std::move(ptr)); 62 return *this; 63 } 64 65 bool operator==(const CFX_MaybeOwned& that) const { 66 return Get() == that.Get(); 67 } 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 CFX_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 #endif // CORE_FXCRT_CFX_MAYBE_OWNED_H_ 89