openpilot/phonelibs/snpe/include/DlSystem/DlOptional.hpp

226 lines
5.7 KiB
C++

//==============================================================================
//
// 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_