DYTSrouce/Tool/matlab/include/MatlabDataArray/ArrayReferenceExt.hpp
2024-11-22 23:19:31 +08:00

225 lines
9.8 KiB
C++

/* Copyright 2014-2017 The MathWorks, Inc. */
#ifndef MATLAB_EXTDATA_ARRAY_REF_EXT_HPP
#define MATLAB_EXTDATA_ARRAY_REF_EXT_HPP
#include "MDArray.hpp"
#include "Enumeration.hpp"
#include "String.hpp"
#include "ReferenceHolder.hpp"
#include "detail/FunctionType.hpp"
#include "detail/HelperFunctions.hpp"
#include "detail/ReferenceHelpers.hpp"
#include "detail/ExceptionHelpers.hpp"
#include <memory>
#include <type_traits>
namespace matlab {
namespace data {
namespace detail {
class Access;
}
/**
* The ArrayReferenceExt class is a base class for all reference types that refer to Arrays.
* It provides basic Array information.
*/
class ArrayReferenceExt : public ReferenceHolder {
public:
/**
* Returns the ArrayType of the array
*
* @return ArrayType the ArrayType
*
* @throw InvalidArrayIndexException - if one of the indices is out of range for this Array
* @throw NotEnoughIndicesProvidedException - if not enough indices were provided
* @throw InvalidArrayTypeException - if data type returned is not recognized
*/
ArrayType getType() const {
int retVal;
typedef int(*ArrayReferenceGetTypeFcnPtr)(detail::ReferenceImpl*, int*);
static const ArrayReferenceGetTypeFcnPtr fcn = detail::resolveFunction<ArrayReferenceGetTypeFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_GET_TYPE);
detail::throwIfError(fcn(pImpl.get(),
&retVal));
return ArrayType(retVal);
}
/**
* Get the array's dimensions.
*
* @return ArrayDimensions
*
* @throw InvalidArrayIndexException - if one of the indices is out of range for this Array
* @throw NotEnoughIndicesProvidedException - if not enough indices were provided
*/
ArrayDimensions getDimensions() const {
size_t numDims = 0;
size_t* dims = nullptr;
typedef int(*ArrayReferenceGetDimensionsFcnPtr)(detail::ReferenceImpl*, size_t*, size_t**);
static const ArrayReferenceGetDimensionsFcnPtr fcn = detail::resolveFunction<ArrayReferenceGetDimensionsFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_GET_DIMENSIONS);
detail::throwIfError(fcn(pImpl.get(), &numDims, &dims));
return ArrayDimensions(dims, dims+numDims);
}
/**
* Get the number of elements in the Array that this reference refers to
*
* @return the number of elements in the Array
*
* @throw InvalidArrayIndexException - if one of the indices is out of range for this Array
* @throw NotEnoughIndicesProvidedException - if not enough indices were provided
*/
size_t getNumberOfElements() const {
size_t retVal;
typedef int(*ArrayReferenceGetNumElementsFcnPtr)(detail::ReferenceImpl*, size_t*);
static const ArrayReferenceGetNumElementsFcnPtr fcn = detail::resolveFunction<ArrayReferenceGetNumElementsFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_GET_NUM_ELEMENTS);
detail::throwIfError(fcn(pImpl.get(), &retVal));
return retVal;
}
/**
* Determine if this array is empty
*
* @return bool - true if empty, otherwise false
*
* @throw InvalidArrayIndexException - if one of the indices is out of range for this Array
* @throw NotEnoughIndicesProvidedException - if not enough indices were provided
*/
bool isEmpty() const {
bool retVal;
typedef int(*ArrayReferenceIsEmptyFcnPtr)(detail::ReferenceImpl*, bool*);
static const ArrayReferenceIsEmptyFcnPtr fcn = detail::resolveFunction<ArrayReferenceIsEmptyFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_IS_EMPTY);
detail::throwIfError(fcn(pImpl.get(), &retVal));
return retVal;
}
protected:
friend class detail::Access;
ArrayReferenceExt(detail::ReferenceImpl* impl) MW_NOEXCEPT :
ReferenceHolder(impl) {}
ArrayReferenceExt(std::shared_ptr<detail::ReferenceImpl> impl) MW_NOEXCEPT :
ReferenceHolder(impl) {}
ArrayReferenceExt(ArrayReferenceExt&& rhs) MW_NOEXCEPT :
ReferenceHolder(std::move(rhs)) {}
ArrayReferenceExt& operator= (ArrayReferenceExt&& rhs) MW_NOEXCEPT {
ReferenceHolder::operator= (std::move(rhs));
return *this;
}
ArrayReferenceExt(const ArrayReferenceExt& rhs) MW_NOEXCEPT :
ReferenceHolder(rhs) {}
ArrayReferenceExt& operator= (const ArrayReferenceExt& rhs) MW_NOEXCEPT {
ReferenceHolder::operator= (rhs);
return *this;
}
private:
ArrayReferenceExt() = delete;
};
/**
* The IndexableArrayRef class is a base class for Reference<Array> to enable the reference
* to be further indexed.
*/
template <bool is_const_ref>
class IndexableArrayRef : public ArrayReferenceExt {
public:
/**
* Enables [] indexing on a reference to an Array.
*
* The return value ArrayElementRef<is_const_ref> allows the element of the array to be
* modified or retrieved: For example:
* auto cell_arr = factory.createArray<Array>({2,2});
* cell_arr[0][0] = factory.createArray<double>({3,3});
* Reference<Array> ref = cell_arr[0][0];
* ref[0][0] = 5.5;
*
* @param idx - the first array index
*
* @return ArrayElementRef<is_const_ref> - contains the index specified
*
* @throw InvalidFieldNameException if the Reference<Array> was created with an invalid fieldname for a struct
* @throw CantIndexIntoEmptyArrayException - if the array is empty
*/
ArrayElementRef<is_const_ref> operator[](size_t idx) {
detail::ReferenceImpl* newRef = nullptr;
typedef int(*ArrayReferenceGetReferenceFcnPtr)(detail::ReferenceImpl*,
bool,
size_t,
detail::ReferenceImpl**);
static const ArrayReferenceGetReferenceFcnPtr fcn = detail::resolveFunction<ArrayReferenceGetReferenceFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_GET_REFERENCE);
detail::throwIfError(fcn(pImpl.get(), !is_const_ref, idx, &newRef));
return detail::Access::createObj<ArrayElementRef<is_const_ref>>(newRef);
}
/**
* Enables [] indexing on a reference to an Array.
*
* The return value ArrayElementRef<true> allows the element of the array to be
* modified or retrieved: For example:
* auto cell_arr = factory.createArray<Array>({2,2});
* cell_arr[0][0] = factory.createScalar(5.5);
* Reference<Array const> ref = cell_arr[0][0];
* double val = ref[0];
*
* @param idx - the first array index
*
* @return ArrayElementRef<true> - contains the index specified
*
* @throw InvalidFieldNameException if the Reference<Array> was created with an invalid fieldname for a struct
* @throw CantIndexIntoEmptyArrayException - if the array is empty
*/
ArrayElementRef<true> operator[](size_t idx) const {
detail::ReferenceImpl* newRef = nullptr;
typedef int(*ArrayReferenceGetReferenceFcnPtr)(detail::ReferenceImpl*,
bool,
size_t,
detail::ReferenceImpl**);
static const ArrayReferenceGetReferenceFcnPtr fcn = detail::resolveFunction<ArrayReferenceGetReferenceFcnPtr>
(detail::FunctionType::ARRAY_REFERENCE_GET_REFERENCE);
detail::throwIfError(fcn(pImpl.get(), false, idx, &newRef));
return detail::Access::createObj<ArrayElementRef<true>>(newRef);
}
protected:
IndexableArrayRef(detail::ReferenceImpl* impl) MW_NOEXCEPT :
ArrayReferenceExt(impl) {}
IndexableArrayRef(std::shared_ptr<detail::ReferenceImpl> impl) MW_NOEXCEPT :
ArrayReferenceExt(impl) {}
IndexableArrayRef(IndexableArrayRef<is_const_ref>&& rhs) MW_NOEXCEPT :
ArrayReferenceExt(std::move(rhs)) {}
IndexableArrayRef<is_const_ref>& operator= (IndexableArrayRef<is_const_ref>&& rhs) MW_NOEXCEPT {
ArrayReferenceExt::operator= (std::move(rhs));
return *this;
}
IndexableArrayRef(const IndexableArrayRef<is_const_ref>& rhs) MW_NOEXCEPT :
ArrayReferenceExt(rhs) {}
IndexableArrayRef<is_const_ref>& operator= (const IndexableArrayRef<is_const_ref>& rhs) MW_NOEXCEPT {
ArrayReferenceExt::operator= (rhs);
return *this;
}
};
}
}
#endif