225 lines
9.8 KiB
C++
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
|
|
|