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
			| 
								 
											4 years ago
										 
									 | 
							
								//==============================================================================
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//  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_
							 |