You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							225 lines
						
					
					
						
							5.7 KiB
						
					
					
				
			
		
		
	
	
							225 lines
						
					
					
						
							5.7 KiB
						
					
					
				| //==============================================================================
 | |
| //
 | |
| //  Copyright (c) 2016, 2020 Qualcomm Technologies, Inc.
 | |
| //  All Rights Reserved.
 | |
| //  Confidential and Proprietary - Qualcomm Technologies, Inc.
 | |
| //
 | |
| //==============================================================================
 | |
| 
 | |
| #ifndef _DL_SYSTEM_OPTIONAL_HPP_
 | |
| #define _DL_SYSTEM_OPTIONAL_HPP_
 | |
| 
 | |
| #include <cstdio>
 | |
| #include <utility>
 | |
| #include <stdexcept>
 | |
| 
 | |
| #include "DlSystem/ZdlExportDefine.hpp"
 | |
| 
 | |
| namespace zdl {
 | |
| namespace DlSystem {
 | |
| 
 | |
| template <typename T>
 | |
| 
 | |
| /** @addtogroup c_plus_plus_apis C++
 | |
| @{ */
 | |
| 
 | |
| /**
 | |
|  * @brief .
 | |
|  *
 | |
|  * Class to manage a value that may or may not exist. The boolean value
 | |
|  * of the Optional class is true if the object contains a value and false
 | |
|  * if it does not contain a value.
 | |
|  *
 | |
|  * The class must be evaluated and confirmed as true (containing a value)
 | |
|  * before being dereferenced.
 | |
|  */
 | |
| class ZDL_EXPORT Optional final {
 | |
| public:
 | |
|    enum class LIFECYCLE {
 | |
|       NONE = 0,
 | |
|       REFERENCE_OWNED = 1,
 | |
|       POINTER_OWNED = 2,
 | |
|       POINTER_NOT_OWNED = 3
 | |
|    };
 | |
| 
 | |
|    struct ReferenceCount {
 | |
|       size_t count = 0;
 | |
| 
 | |
|       void increment() { count++; }
 | |
| 
 | |
|       size_t decrement() {
 | |
|          if (count > 0) {
 | |
|             count--;
 | |
|          }
 | |
|          return count;
 | |
|       }
 | |
|    };
 | |
| 
 | |
|    using U = typename std::remove_pointer<T>::type;
 | |
| 
 | |
|    /**
 | |
|     * The default constructor is set to not have any value, and is
 | |
|     * therefore evaluated as false.
 | |
|     */
 | |
|    // Do not explicit it so we can return {}
 | |
|    Optional() {
 | |
|       m_Type = LIFECYCLE::NONE;
 | |
|    }
 | |
| 
 | |
|    /**
 | |
|     * Construct an Optional class using an object.
 | |
|     * @param[in] Reference to an object v
 | |
|     * @param[out] Optional instance of object v
 | |
|     */
 | |
|    template <typename Q = T>
 | |
|    Optional (const T& v, typename std::enable_if<!std::is_pointer<Q>::value>::type* = 0)
 | |
|            : m_Type(LIFECYCLE::REFERENCE_OWNED) {
 | |
|       try {
 | |
|          m_StoragePtr = new T(v);
 | |
|       } catch (...) {
 | |
|          m_StoragePtr = nullptr;
 | |
|          m_Type = LIFECYCLE::NONE;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    template <typename Q = T>
 | |
|    Optional(U* v, LIFECYCLE type, typename std::enable_if<std::is_pointer<Q>::value>::type* = 0)
 | |
|            : m_Type(type) {
 | |
|       switch (m_Type) {
 | |
|          case LIFECYCLE::POINTER_OWNED:
 | |
|             m_StoragePtr = v;
 | |
|             m_Count = new ReferenceCount();
 | |
|             m_Count->increment();
 | |
|             break;
 | |
|          case LIFECYCLE::POINTER_NOT_OWNED:
 | |
|             m_StoragePtr = v;
 | |
|             break;
 | |
|          case LIFECYCLE::REFERENCE_OWNED:
 | |
|             throw std::bad_exception();
 | |
|          case LIFECYCLE::NONE:
 | |
|             break;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    Optional(const Optional &other) : m_Type(other.m_Type), m_Count(other.m_Count) {
 | |
|       if (isReference()) {
 | |
|          m_StoragePtr = new U(*other.m_StoragePtr);
 | |
|       } else if (isPointer()) {
 | |
|          m_StoragePtr = other.m_StoragePtr;
 | |
|          if (isOwned()) {
 | |
|             m_Count->increment();
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    Optional& operator=(const Optional& other) noexcept {
 | |
|       Optional tmp(other);
 | |
|       swap(std::move(tmp));
 | |
|       return *this;
 | |
|    }
 | |
| 
 | |
|    Optional(Optional&& other) noexcept {
 | |
|       swap(std::move(other));
 | |
|    }
 | |
| 
 | |
|    Optional& operator=(Optional&& other) noexcept {
 | |
|       swap(std::move(other));
 | |
|       return *this;
 | |
|    }
 | |
| 
 | |
|    ~Optional() {
 | |
|       if (isOwned()) {
 | |
|          if (isReference() || (isPointer() && m_Count->decrement() == 0)) {
 | |
|             delete m_StoragePtr;
 | |
|             delete m_Count;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /**
 | |
|     * Boolean value of Optional class is only true when there exists a value.
 | |
|     */
 | |
|    operator bool() const noexcept { return isValid(); }
 | |
| 
 | |
|    bool operator!() const noexcept { return !isValid(); }
 | |
| 
 | |
|    /**
 | |
|     * Get reference of Optional object
 | |
|     * @warning User must validate Optional has value before.
 | |
|     */
 | |
|    const T& operator*() { return this->GetReference(); }
 | |
| 
 | |
|    /**
 | |
|     * Get reference of Optional object
 | |
|     * @warning User must validate Optional has value before.
 | |
|     */
 | |
|    const T& operator*() const { return this->GetReference(); }
 | |
| 
 | |
|    operator T&() { return this->GetReference(); }
 | |
| 
 | |
|    T operator->() {
 | |
|       T self = this->GetReference();
 | |
|       return self;
 | |
|    }
 | |
| private:
 | |
|    void swap(Optional&& other) {
 | |
|       m_Type = other.m_Type;
 | |
|       m_StoragePtr = other.m_StoragePtr;
 | |
|       m_Count = other.m_Count;
 | |
| 
 | |
|       other.m_Type = LIFECYCLE::NONE;
 | |
|       other.m_StoragePtr = nullptr;
 | |
|       other.m_Count = nullptr;
 | |
|    }
 | |
| 
 | |
|    template <typename Q = T>
 | |
|    typename std::enable_if<std::is_same<U, Q>::value, const Q&>::type GetReference() const noexcept {
 | |
|       if (!isReference()) std::terminate();
 | |
|       return *static_cast<const Q*>(m_StoragePtr);
 | |
|    }
 | |
| 
 | |
|    template <typename Q = T>
 | |
|    typename std::enable_if<std::is_same<U*, Q>::value, const Q&>::type GetReference() const noexcept {
 | |
|       if (!isPointer()) std::terminate();
 | |
|       return static_cast<const Q&>(m_StoragePtr);
 | |
|    }
 | |
| 
 | |
|    template <typename Q = T>
 | |
|    typename std::enable_if<std::is_same<U, Q>::value, Q&>::type GetReference() noexcept {
 | |
|       if (!isReference()) std::terminate();
 | |
|       return *m_StoragePtr;
 | |
|    }
 | |
| 
 | |
|    template <typename Q = T>
 | |
|    typename std::enable_if<std::is_same<U*, Q>::value, Q&>::type GetReference() noexcept {
 | |
|       if (!isPointer()) std::terminate();
 | |
|       return m_StoragePtr;
 | |
|    }
 | |
| 
 | |
|    bool isPointer() const {
 | |
|       return m_Type == LIFECYCLE::POINTER_OWNED || m_Type == LIFECYCLE::POINTER_NOT_OWNED;
 | |
|    }
 | |
| 
 | |
|    bool isOwned() const {
 | |
|       return m_Type == LIFECYCLE::REFERENCE_OWNED || m_Type == LIFECYCLE::POINTER_OWNED;
 | |
|    }
 | |
| 
 | |
|    bool isReference() const {
 | |
|       return m_Type == LIFECYCLE::REFERENCE_OWNED;
 | |
|    }
 | |
| 
 | |
|    bool isValid() const {
 | |
|       return m_Type != LIFECYCLE::NONE;
 | |
|    }
 | |
| 
 | |
|    U* m_StoragePtr = nullptr;
 | |
|    LIFECYCLE m_Type;
 | |
|    ReferenceCount *m_Count = nullptr;
 | |
| };
 | |
| 
 | |
| } // ns DlSystem
 | |
| } // ns zdl
 | |
| 
 | |
| /** @} */ /* end_addtogroup c_plus_plus_apis C++ */
 | |
| 
 | |
| #endif // _DL_SYSTEM_OPTIONAL_HPP_
 | |
| 
 |