/* Copyright 2016-2017 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/reference_interface.hpp" #include "detail/HelperFunctions.hpp" #include "detail/ReferenceHelpers.hpp" #include #include namespace matlab { namespace data { namespace detail { class Access; } template struct GetReferenceExt { using type = ReferenceHolder; }; template <> struct GetReferenceExt { using type = IndexableArrayRef; }; template <> struct GetReferenceExt { using type = MATLABStringReferenceExt; }; template class Reference : public GetReferenceExt::type { public: typedef typename std::remove_const::type ref_type; using Parent = typename GetReferenceExt::type; using Parent::pImpl; /** * Cast to element from the array. Makes a copy of the element from the array * * @code * Reference ref = cell_arr[0]; * Array cpy(ref); * @endcode * * @return ref_type the element being referred to * @throw none */ operator ref_type() const MW_NOEXCEPT { return detail::getElement(pImpl); } /** * Assign a value into an Array. The Array being indexed must be non-const. * * @code * Reference ref = cell_arr[0]; * ref = factory.createScalar(false); * @endcode * * @param rhs - value to be assigned into the Array * * @return Reference& - this * @throw none */ Reference& operator= (T rhs) MW_NOEXCEPT { static_assert(!std::is_const::value, "Can't modify a Reference to const data"); detail::setElement(pImpl.get(), std::move(rhs), static_cast(GetArrayType::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 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 if the MATLABString is missing * @throw NonAsciiCharInInputDataException for a Reference if the MATLABString contains non-ascii characters */ operator std::string() const { static_assert(std::is_same::value || std::is_same::value, "Invalid Reference to get a string"); return detail::getString(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 ref = str_arr[0]; * ref = "MyString"; * @endcode * * @param rhs - std::string to be assigned into the Array * * @return Reference& - this * @throw none */ Reference& operator=(std::string rhs) MW_NOEXCEPT { static_assert(!std::is_const::value, "Can't modify a Reference to const data"); static_assert(std::is_same::value || std::is_same::value, "Invalid Reference to set a string"); detail::setString(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 ref = string_arr[0]; * ref = String(u"hello"); * @endcode * * @param rhs - value to be assigned into the Array * * @return Reference& - this * * @throw none */ Reference& operator= (String rhs) MW_NOEXCEPT { static_assert(!std::is_const::value, "Can't modify a Reference to const data"); static_assert(std::is_same::value, "Invalid Reference to set a String"); detail::setElement(pImpl.get(), std::move(rhs), static_cast(ArrayType::MATLAB_STRING)); return *this; } /** * Move constructor * * @param - rhs Reference value to be moved * @return - newly constructed Reference * @throw none */ Reference(Reference&& rhs) MW_NOEXCEPT : Parent(std::move(rhs)) {} /** * Move assignment * * @param - rhs Reference value to be moved * @return - updated Reference * @throw none */ Reference& operator= (Reference&& 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& rhs) MW_NOEXCEPT : Parent(rhs) {} /** * Copy assignment * * @param - rhs Reference value to be copied * @return - updated Reference * @throw none */ Reference& operator= (const Reference& rhs) MW_NOEXCEPT { Parent::operator= (rhs); return *this; } protected: Reference(std::shared_ptr impl) MW_NOEXCEPT : Parent(impl) {} Reference(detail::ReferenceImpl* impl) MW_NOEXCEPT : Parent(impl) {} private: friend class detail::Access; Reference() = delete; }; inline bool operator ==(Reference const& lhs, std::string const& rhs) MW_NOEXCEPT { return reference_matlab_string_equal_string(detail::Access::getImpl(lhs), rhs.c_str(), rhs.size()); } inline bool operator ==(std::string const& lhs, Reference const& rhs) MW_NOEXCEPT { return reference_matlab_string_equal_string(detail::Access::getImpl(rhs), lhs.c_str(), lhs.size()); } inline bool operator ==(Reference const& lhs, String const& rhs) MW_NOEXCEPT { return reference_matlab_string_equal_string16(detail::Access::getImpl(lhs), rhs.c_str(), rhs.size()); } inline bool operator ==(String const& lhs, Reference const& rhs) MW_NOEXCEPT { return reference_matlab_string_equal_string16(detail::Access::getImpl(rhs), lhs.c_str(), lhs.size()); } inline bool operator ==(Reference 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 const& rhs) MW_NOEXCEPT { if (lhs.has_value()) { const String& str = *lhs; return (rhs == str); } return false; } inline bool operator ==(Reference const& lhs, Reference const& rhs) MW_NOEXCEPT { return reference_matlab_string_equal_reference(detail::Access::getImpl(lhs), detail::Access::getImpl(rhs)); } template bool operator ==(Reference const& lhs, T const& rhs) MW_NOEXCEPT { using ref_type = typename Reference::ref_type; return static_cast(lhs) == rhs; } template bool operator ==(T const& lhs, Reference const& rhs) MW_NOEXCEPT { using ref_type = typename Reference::ref_type; return lhs == static_cast(rhs); } template bool operator ==(Reference const& lhs, Reference const& rhs) MW_NOEXCEPT { using ref_type = typename Reference::ref_type; return static_cast(lhs) == static_cast(rhs); } template std::ostream& operator <<(std::ostream& os, Reference const& rhs) MW_NOEXCEPT { using ref_type = typename Reference::ref_type; return os << static_cast(rhs); } } } #endif