310 lines
12 KiB
C++
310 lines
12 KiB
C++
|
/* Copyright 2016-2020 The MathWorks, Inc. */
|
||
|
|
||
|
#ifndef MATLAB_EXTDATA_REFERENCE_HPP
|
||
|
#define MATLAB_EXTDATA_REFERENCE_HPP
|
||
|
|
||
|
#include "Enumeration.hpp"
|
||
|
#include "String.hpp"
|
||
|
#include "ReferenceHolder.hpp"
|
||
|
#include "ArrayReferenceExt.hpp"
|
||
|
#include "MATLABStringReferenceExt.hpp"
|
||
|
#include "Exception.hpp"
|
||
|
#include "GetArrayType.hpp"
|
||
|
|
||
|
#include "detail/publish_util.hpp"
|
||
|
#include "detail/FunctionType.hpp"
|
||
|
|
||
|
#include "detail/HelperFunctions.hpp"
|
||
|
#include "detail/ReferenceHelpers.hpp"
|
||
|
|
||
|
#include <memory>
|
||
|
#include <type_traits>
|
||
|
|
||
|
namespace matlab {
|
||
|
namespace data {
|
||
|
namespace detail {
|
||
|
class Access;
|
||
|
}
|
||
|
|
||
|
template <typename T> struct GetReferenceExt { using type = ReferenceHolder; };
|
||
|
template <> struct GetReferenceExt<Array> { using type = IndexableArrayRef<false>; };
|
||
|
template <> struct GetReferenceExt<MATLABString> { using type = MATLABStringReferenceExt; };
|
||
|
|
||
|
template <typename T>
|
||
|
class Reference : public GetReferenceExt<T>::type {
|
||
|
public:
|
||
|
|
||
|
typedef typename std::remove_const<T>::type ref_type;
|
||
|
|
||
|
using Parent = typename GetReferenceExt<T>::type;
|
||
|
using Parent::pImpl;
|
||
|
|
||
|
/**
|
||
|
* Cast to element from the array. Makes a copy of the element from the array
|
||
|
*
|
||
|
* @code
|
||
|
* Reference<Array> ref = cell_arr[0];
|
||
|
* Array cpy(ref);
|
||
|
* @endcode
|
||
|
*
|
||
|
* @return ref_type the element being referred to
|
||
|
* @throw ObjectNotAccessibleException - if iterating through an object array and the object in the array cannot be accessed
|
||
|
*/
|
||
|
operator ref_type() const {
|
||
|
return detail::getElement<ref_type>(pImpl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Assign a value into an Array. The Array being indexed must be non-const.
|
||
|
*
|
||
|
* @code
|
||
|
* Reference<Array> ref = cell_arr[0];
|
||
|
* ref = factory.createScalar(false);
|
||
|
* @endcode
|
||
|
*
|
||
|
* @param rhs - value to be assigned into the Array
|
||
|
*
|
||
|
* @return Reference<T>& - this
|
||
|
* @throw InvalidHeterogeneousArrayException - if assigning an object to an ObjectArray that is not valid
|
||
|
*/
|
||
|
Reference<T>& operator= (T rhs) {
|
||
|
static_assert(!std::is_const<T>::value, "Can't modify a Reference to const data");
|
||
|
detail::setElement(pImpl.get(), std::move(rhs), static_cast<int>(GetArrayType<T>::type));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Cast to std::string from the array. Makes a copy of the std::string. Only
|
||
|
* valid for types that can be cast to a std::string
|
||
|
*
|
||
|
* @code
|
||
|
* Reference<String> ref = str_arr[0];
|
||
|
* std::string cpy(ref);
|
||
|
* @endcode
|
||
|
*
|
||
|
* @return std::string - a string representation of the value
|
||
|
*
|
||
|
* @throw std::runtime_error - for a Reference<MATLABString> if the MATLABString is missing
|
||
|
* @throw NonAsciiCharInInputDataException for a Reference<MATLABString> if the MATLABString contains non-ascii characters
|
||
|
*/
|
||
|
operator std::string() const {
|
||
|
static_assert(std::is_same<ref_type, Enumeration>::value ||
|
||
|
std::is_same<ref_type, MATLABString>::value,
|
||
|
"Invalid Reference to get a string");
|
||
|
return detail::getString<ref_type>(pImpl.get());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Assign a std::string into an Array. The Array being indexed must be non-const and allow strings to be assigned
|
||
|
*
|
||
|
* @code
|
||
|
* Reference<String> ref = str_arr[0];
|
||
|
* ref = "MyString";
|
||
|
* @endcode
|
||
|
*
|
||
|
* @param rhs - std::string to be assigned into the Array
|
||
|
*
|
||
|
* @return Reference<T>& - this
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference<T>& operator=(std::string rhs) MW_NOEXCEPT {
|
||
|
static_assert(!std::is_const<T>::value, "Can't modify a Reference to const data");
|
||
|
static_assert(std::is_same<ref_type, Enumeration>::value ||
|
||
|
std::is_same<ref_type, MATLABString>::value,
|
||
|
"Invalid Reference to set a string");
|
||
|
detail::setString<ref_type>(pImpl.get(), std::move(rhs));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Assign a String value into a MATLABString Array. The Array being indexed must be non-const.
|
||
|
*
|
||
|
* @code
|
||
|
* Reference<MATLABString> ref = string_arr[0];
|
||
|
* ref = String(u"hello");
|
||
|
* @endcode
|
||
|
*
|
||
|
* @param rhs - value to be assigned into the Array
|
||
|
*
|
||
|
* @return Reference<T>& - this
|
||
|
*
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference<T>& operator= (String rhs) MW_NOEXCEPT {
|
||
|
static_assert(!std::is_const<T>::value, "Can't modify a Reference to const data");
|
||
|
static_assert(std::is_same<ref_type, MATLABString>::value,
|
||
|
"Invalid Reference to set a String");
|
||
|
detail::setElement(pImpl.get(), std::move(rhs), static_cast<int>(ArrayType::MATLAB_STRING));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Move constructor
|
||
|
*
|
||
|
* @param - rhs Reference value to be moved
|
||
|
* @return - newly constructed Reference
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference(Reference<T>&& rhs) MW_NOEXCEPT :
|
||
|
Parent(std::move(rhs)) {}
|
||
|
|
||
|
/**
|
||
|
* Move assignment
|
||
|
*
|
||
|
* @param - rhs Reference value to be moved
|
||
|
* @return - updated Reference
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference<T>& operator= (Reference<T>&& rhs) MW_NOEXCEPT {
|
||
|
Parent::operator= (std::move(rhs));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copy constructor
|
||
|
*
|
||
|
* @param - rhs Reference value to be copied
|
||
|
* @return - newly constructed Reference
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference(const Reference<T>& rhs) MW_NOEXCEPT :
|
||
|
Parent(rhs) {}
|
||
|
|
||
|
/**
|
||
|
* Copy assignment
|
||
|
*
|
||
|
* @param - rhs Reference value to be copied
|
||
|
* @return - updated Reference
|
||
|
* @throw none
|
||
|
*/
|
||
|
Reference<T>& operator= (const Reference<T>& rhs) MW_NOEXCEPT {
|
||
|
Parent::operator= (rhs);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
Reference(std::shared_ptr<detail::ReferenceImpl> impl) MW_NOEXCEPT :
|
||
|
Parent(impl) {}
|
||
|
|
||
|
Reference(detail::ReferenceImpl* impl) MW_NOEXCEPT :
|
||
|
Parent(impl) {}
|
||
|
|
||
|
private:
|
||
|
friend class detail::Access;
|
||
|
|
||
|
Reference() = delete;
|
||
|
};
|
||
|
|
||
|
inline bool operator ==(Reference<MATLABString> const& lhs, std::string const& rhs) MW_NOEXCEPT {
|
||
|
typedef bool(*ReferenceMATLABStringEqualStringFcnPtr)(detail::ReferenceImpl*, const char*, size_t idx);
|
||
|
static const ReferenceMATLABStringEqualStringFcnPtr fcn = detail::resolveFunction<ReferenceMATLABStringEqualStringFcnPtr>
|
||
|
(detail::FunctionType::REFERENCE_MATLAB_STRING_EQUAL_STRING);
|
||
|
return fcn(detail::Access::getImpl<detail::ReferenceImpl>(lhs), rhs.c_str(), rhs.size());
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(std::string const& lhs, Reference<MATLABString> const& rhs) MW_NOEXCEPT {
|
||
|
typedef bool(*ReferenceMATLABStringEqualStringFcnPtr)(detail::ReferenceImpl*, const char*, size_t idx);
|
||
|
static const ReferenceMATLABStringEqualStringFcnPtr fcn = detail::resolveFunction<ReferenceMATLABStringEqualStringFcnPtr>
|
||
|
(detail::FunctionType::REFERENCE_MATLAB_STRING_EQUAL_STRING);
|
||
|
return fcn(detail::Access::getImpl<detail::ReferenceImpl>(rhs), lhs.c_str(), lhs.size());
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(Reference<MATLABString> const& lhs, String const& rhs) MW_NOEXCEPT {
|
||
|
typedef bool(*ReferenceMATLABStringEqualString16FcnPtr)(detail::ReferenceImpl*, const char16_t*, size_t idx);
|
||
|
static const ReferenceMATLABStringEqualString16FcnPtr fcn = detail::resolveFunction<ReferenceMATLABStringEqualString16FcnPtr>
|
||
|
(detail::FunctionType::REFERENCE_MATLAB_STRING_EQUAL_STRING16);
|
||
|
return fcn(detail::Access::getImpl<detail::ReferenceImpl>(lhs), rhs.c_str(), rhs.size());
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(String const& lhs, Reference<MATLABString> const& rhs) MW_NOEXCEPT {
|
||
|
typedef bool(*ReferenceMATLABStringEqualString16FcnPtr)(detail::ReferenceImpl*, const char16_t*, size_t idx);
|
||
|
static const ReferenceMATLABStringEqualString16FcnPtr fcn = detail::resolveFunction<ReferenceMATLABStringEqualString16FcnPtr>
|
||
|
(detail::FunctionType::REFERENCE_MATLAB_STRING_EQUAL_STRING16);
|
||
|
return fcn(detail::Access::getImpl<detail::ReferenceImpl>(rhs), lhs.c_str(), lhs.size());
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(Reference<MATLABString> const& lhs, MATLABString const& rhs) MW_NOEXCEPT {
|
||
|
if (rhs.has_value()) {
|
||
|
const String& str = *rhs;
|
||
|
return (lhs == str);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(MATLABString const& lhs, Reference<MATLABString> const& rhs) MW_NOEXCEPT {
|
||
|
if (lhs.has_value()) {
|
||
|
const String& str = *lhs;
|
||
|
return (rhs == str);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
inline bool operator ==(Reference<MATLABString> const& lhs, Reference<MATLABString> const& rhs) MW_NOEXCEPT {
|
||
|
typedef bool(*ReferenceMATLABStringEqualReferenceFcnPtr)(detail::ReferenceImpl*, detail::ReferenceImpl*);
|
||
|
static const ReferenceMATLABStringEqualReferenceFcnPtr fcn = detail::resolveFunction<ReferenceMATLABStringEqualReferenceFcnPtr>
|
||
|
(detail::FunctionType::REFERENCE_MATLAB_STRING_EQUAL_REFERENCE);
|
||
|
return fcn(detail::Access::getImpl<detail::ReferenceImpl>(lhs), detail::Access::getImpl<detail::ReferenceImpl>(rhs));
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
inline bool operator !=( T1 const& lhs, T2 const& rhs) MW_NOEXCEPT {
|
||
|
return !(lhs == rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator ==(Reference<T> const& lhs, T const& rhs) MW_NOEXCEPT {
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) == rhs;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator ==(T const& lhs, Reference<T> const& rhs) MW_NOEXCEPT {
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return lhs == static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator ==(Reference<T> const& lhs, Reference<T> const& rhs) MW_NOEXCEPT {
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) == static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
std::ostream& operator <<(std::ostream& os, Reference<T> const& rhs) MW_NOEXCEPT {
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return os << static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator <(Reference<T> const& lhs, Reference<T> const& rhs)
|
||
|
{
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) < static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator >(Reference<T> const& lhs, Reference<T> const& rhs)
|
||
|
{
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) > static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator <=(Reference<T> const& lhs, Reference<T> const& rhs)
|
||
|
{
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) <= static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool operator >=(Reference<T> const& lhs, Reference<T> const& rhs)
|
||
|
{
|
||
|
using ref_type = typename Reference<T>::ref_type;
|
||
|
return static_cast<ref_type>(lhs) >= static_cast<ref_type>(rhs);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|