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.
		
		
		
		
			
				
					226 lines
				
				5.7 KiB
			
		
		
			
		
	
	
					226 lines
				
				5.7 KiB
			| 
											6 years ago
										 | //==============================================================================
 | ||
|  | //
 | ||
| 
											5 years ago
										 | //  Copyright (c) 2016, 2020 Qualcomm Technologies, Inc.
 | ||
| 
											6 years ago
										 | //  All Rights Reserved.
 | ||
|  | //  Confidential and Proprietary - Qualcomm Technologies, Inc.
 | ||
|  | //
 | ||
|  | //==============================================================================
 | ||
|  | 
 | ||
|  | #ifndef _DL_SYSTEM_OPTIONAL_HPP_
 | ||
|  | #define _DL_SYSTEM_OPTIONAL_HPP_
 | ||
|  | 
 | ||
|  | #include <cstdio>
 | ||
|  | #include <utility>
 | ||
| 
											5 years ago
										 | #include <stdexcept>
 | ||
| 
											6 years ago
										 | 
 | ||
|  | #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 {
 | ||
| 
											6 years ago
										 |       NONE = 0,
 | ||
|  |       REFERENCE_OWNED = 1,
 | ||
|  |       POINTER_OWNED = 2,
 | ||
|  |       POINTER_NOT_OWNED = 3
 | ||
| 
											6 years ago
										 |    };
 | ||
|  | 
 | ||
|  |    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 {
 | ||
| 
											5 years ago
										 |       if (!isReference()) std::terminate();
 | ||
| 
											6 years ago
										 |       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 {
 | ||
| 
											5 years ago
										 |       if (!isPointer()) std::terminate();
 | ||
| 
											6 years ago
										 |       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 {
 | ||
| 
											5 years ago
										 |       if (!isReference()) std::terminate();
 | ||
| 
											6 years ago
										 |       return *m_StoragePtr;
 | ||
|  |    }
 | ||
|  | 
 | ||
|  |    template <typename Q = T>
 | ||
|  |    typename std::enable_if<std::is_same<U*, Q>::value, Q&>::type GetReference() noexcept {
 | ||
| 
											5 years ago
										 |       if (!isPointer()) std::terminate();
 | ||
| 
											6 years ago
										 |       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_
 |