Home | History | Annotate | Download | only in fxcrt
      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:
     24   MaybeOwned() : m_pObj(nullptr) {}
     25   explicit MaybeOwned(T* ptr) : m_pObj(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;
     30   MaybeOwned(MaybeOwned&& that) noexcept
     31       : m_pOwnedObj(that.m_pOwnedObj.release()), m_pObj(that.m_pObj) {
     32     that.m_pObj = nullptr;
     33   }
     34 
     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 
     44   bool IsOwned() const { return !!m_pOwnedObj; }
     45   T* Get() const { return m_pObj; }
     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