699 lines
32 KiB
C++
699 lines
32 KiB
C++
|
/* Copyright 2014-2020 The MathWorks, Inc. */
|
||
|
|
||
|
#ifndef MATLAB_DATA_ARRAY_FACTORY_HPP_
|
||
|
#define MATLAB_DATA_ARRAY_FACTORY_HPP_
|
||
|
|
||
|
#include "TypedArray.hpp"
|
||
|
#include "ArrayDimensions.hpp"
|
||
|
#include "CharArray.hpp"
|
||
|
#include "StructArray.hpp"
|
||
|
#include "SparseArray.hpp"
|
||
|
#include "ObjectArray.hpp"
|
||
|
#include "Object.hpp"
|
||
|
#include "Enumeration.hpp"
|
||
|
#include "EnumArray.hpp"
|
||
|
#include "Exception.hpp"
|
||
|
#include "GetArrayType.hpp"
|
||
|
#include "String.hpp"
|
||
|
#include "matlab_extdata_defs.hpp"
|
||
|
#include "TypedIterator.hpp"
|
||
|
#include "Optional.hpp"
|
||
|
#include "GetReturnType.hpp"
|
||
|
#include "MemoryLayout.hpp"
|
||
|
|
||
|
#include "detail/ArrayFactoryHelpers.hpp"
|
||
|
#include "detail/StringHelpers.hpp"
|
||
|
#include "detail/HelperFunctions.hpp"
|
||
|
#include "detail/FunctionType.hpp"
|
||
|
#include "detail/ExceptionHelpers.hpp"
|
||
|
#include "detail/publish_util.hpp"
|
||
|
|
||
|
#include <string>
|
||
|
#include <initializer_list>
|
||
|
#include <stdint.h>
|
||
|
#include <iterator>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace matlab {
|
||
|
namespace data {
|
||
|
namespace impl {
|
||
|
class ArrayFactoryImpl;
|
||
|
class ObjectImpl;
|
||
|
}
|
||
|
|
||
|
namespace detail {
|
||
|
class NameListImpl;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The ArrayFactory base class provides all of the general APIs that
|
||
|
* each of the concrete factories needs to support.
|
||
|
*/
|
||
|
class ArrayFactory {
|
||
|
public:
|
||
|
/**
|
||
|
* Construct an ArrayFactory
|
||
|
*
|
||
|
* @throw FailedToLoadLibMatlabDataArrayException if necessary libraries are not found
|
||
|
*/
|
||
|
ArrayFactory() {
|
||
|
typedef int (*CreateArrayFactoryFcnPtr)(typename impl::ArrayFactoryImpl**);
|
||
|
static const CreateArrayFactoryFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateArrayFactoryFcnPtr>(
|
||
|
detail::FunctionType::CREATE_ARRAY_FACTORY);
|
||
|
|
||
|
impl::ArrayFactoryImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(&impl));
|
||
|
pImpl = std::shared_ptr<impl::ArrayFactoryImpl>(impl, [](impl::ArrayFactoryImpl* ptr) {
|
||
|
typedef void (*DestroyArrayFactoryFcnPtr)(typename impl::ArrayFactoryImpl*);
|
||
|
static const DestroyArrayFactoryFcnPtr destroyFcn =
|
||
|
detail::resolveFunction<DestroyArrayFactoryFcnPtr>(
|
||
|
detail::FunctionType::DESTROY_ARRAY_FACTORY);
|
||
|
destroyFcn(ptr);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ArrayFactory destructor
|
||
|
*
|
||
|
* @throw none
|
||
|
*/
|
||
|
~ArrayFactory() MW_NOEXCEPT {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a TypedArray<T> with the given dimensions
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type and dimensions
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
template <typename T>
|
||
|
TypedArray<T> createArray(ArrayDimensions dims) {
|
||
|
typedef int (*CreateArrayWithDimsFcnPtr)(typename impl::ArrayFactoryImpl*, int, size_t*, size_t,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateArrayWithDimsFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateArrayWithDimsFcnPtr>(
|
||
|
detail::FunctionType::CREATE_ARRAY_WITH_DIMS);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(pImpl.get(), static_cast<int>(GetArrayType<T>::type), &dims[0],
|
||
|
dims.size(), &impl));
|
||
|
return detail::Access::createObj<TypedArray<T>>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a TypedArray<T> with the given dimensions and filled in with the
|
||
|
* data specified by the begin and end iterators. Data is copied and must be in column major
|
||
|
* order. The data type for the array is determined by the value_type of the iterator.
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param begin - start of the user supplied data
|
||
|
* @param end - end of the user supplied data
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type, dimensions and data
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
template <typename ItType,
|
||
|
typename T =
|
||
|
typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type>
|
||
|
TypedArray<typename GetReturnType<T>::type> createArray(ArrayDimensions dims,
|
||
|
ItType begin,
|
||
|
ItType end) {
|
||
|
return detail::createArrayWithIterator(pImpl.get(), std::move(dims), begin, end);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a TypedArray<T> with the given dimensions and filled in with the
|
||
|
* supplied data in the initializer list. Data must be in column major order.
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param data - initializer list containing the data
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type, dimensions and data
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
template <typename T>
|
||
|
TypedArray<typename GetReturnType<T>::type> createArray(ArrayDimensions dims,
|
||
|
std::initializer_list<T> data) {
|
||
|
return detail::createArrayWithIterator(pImpl.get(), std::move(dims), data.begin(),
|
||
|
data.end());
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Creates a TypedArray<T> with the given dimensions and filled in with the
|
||
|
* data specified by C-style begin and end pointers. Data is copied and must be in column major
|
||
|
* order. This methods supports all arithmetic types.
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param T* - start of the user supplied data
|
||
|
* @param T* - end of the user supplied data
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type, dimensions and data
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
template <typename T>
|
||
|
typename std::enable_if<std::is_arithmetic<T>::value || is_complex<T>::value, TypedArray<T>>::type
|
||
|
createArray(ArrayDimensions dims, const T* const begin, const T* const end) {
|
||
|
typedef int (*CreateArrayWithDimsAndDataFcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, int arrayType, size_t* dims, size_t numDims,
|
||
|
const void* const dataStart, size_t numEl, typename impl::ArrayImpl**);
|
||
|
static const CreateArrayWithDimsAndDataFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateArrayWithDimsAndDataFcnPtr>(
|
||
|
detail::FunctionType::CREATE_ARRAY_WITH_DIMS_AND_DATA);
|
||
|
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(pImpl.get(), static_cast<int>(GetArrayType<T>::type), &dims[0],
|
||
|
dims.size(), begin, (end - begin), &impl));
|
||
|
return detail::Access::createObj<TypedArray<T>>(impl);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar TypedArray<T> with the given value. This methods supports
|
||
|
* all arithmetic types.
|
||
|
*
|
||
|
* @param val - the value to be inserted into the scalar
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type and data
|
||
|
*
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
template <typename T>
|
||
|
typename std::enable_if<std::is_arithmetic<T>::value, TypedArray<T>>::type createScalar(
|
||
|
const T val) {
|
||
|
typedef int (*CreateScalarArrayFcnPtr)(typename impl::ArrayFactoryImpl * impl, int arrayType,
|
||
|
const void* data, typename impl::ArrayImpl**);
|
||
|
static const CreateScalarArrayFcnPtr fcn = detail::resolveFunction<CreateScalarArrayFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SCALAR_ARRAY);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(
|
||
|
fcn(pImpl.get(), static_cast<int>(GetArrayType<T>::type), &val, &impl));
|
||
|
return detail::Access::createObj<TypedArray<T>>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar TypedArray<T> with the given value. This methods supports
|
||
|
* all complex types.
|
||
|
*
|
||
|
* @param val - the value to be inserted into the scalar
|
||
|
*
|
||
|
* @return TypedArray<T> - an Array with the appropriate type and data
|
||
|
*
|
||
|
* @throw InvalidArrayType - if array type of the new array is not recognized as valid
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
template <typename T>
|
||
|
typename std::enable_if<is_complex<T>::value, TypedArray<T>>::type createScalar(const T val) {
|
||
|
auto arr = createArray<T>({1, 1});
|
||
|
arr[0] = val;
|
||
|
return arr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar TypedArray<MATLABString> with the given value
|
||
|
*
|
||
|
* @param val - the string to be inserted into the scalar
|
||
|
*
|
||
|
* @return TypedArray<MATLABString> - a newly created TypedArray of MATLABString
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
TypedArray<MATLABString> createScalar(const String val) {
|
||
|
typedef int (*CreateScalarStringFcnPtr)(typename impl::ArrayFactoryImpl * impl, const char16_t* data,
|
||
|
size_t strlen, typename impl::ArrayImpl**);
|
||
|
static const CreateScalarStringFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateScalarStringFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SCALAR_STRING);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(pImpl.get(), val.c_str(), val.size(), &impl));
|
||
|
return detail::Access::createObj<TypedArray<MATLABString>>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar TypedArray<MATLABString> with the given value
|
||
|
*
|
||
|
* @param val - the string to be inserted into the scalar
|
||
|
*
|
||
|
* @return TypedArray<MATLABString> - an Array containing data of MATLABString type
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
TypedArray<MATLABString> createScalar(const MATLABString val) {
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
if (val) {
|
||
|
typedef int (*CreateScalarStringFcnPtr)(typename impl::ArrayFactoryImpl * impl,
|
||
|
const char16_t* data, size_t strlen,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateScalarStringFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateScalarStringFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SCALAR_STRING);
|
||
|
String str = *val;
|
||
|
detail::throwIfError(fcn(pImpl.get(), str.c_str(), str.size(), &impl));
|
||
|
} else {
|
||
|
typedef int (*CreateScalarMissingStringFcnPtr)(typename impl::ArrayFactoryImpl * impl,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateScalarMissingStringFcnPtr fcn2 =
|
||
|
detail::resolveFunction<CreateScalarMissingStringFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SCALAR_MISSING_STRING);
|
||
|
detail::throwIfError(fcn2(pImpl.get(), &impl));
|
||
|
}
|
||
|
return detail::Access::createObj<TypedArray<MATLABString>>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a CellArray with specified dimensions.
|
||
|
*
|
||
|
* @param dims - the dimensions of the CellArray
|
||
|
*
|
||
|
* @return CellArray - newly created Cell Array
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
CellArray createCellArray(ArrayDimensions dims) {
|
||
|
return createArray<Array>(std::move(dims));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a CellArray with the data specified. Data is specified in column major order
|
||
|
*
|
||
|
* @param dims - the dimensions of the CellArray
|
||
|
* @params data - elements to be inserted into the cell array. Primitive types, strings and
|
||
|
* Arrays are allowable inputs.
|
||
|
*
|
||
|
* @return CellArray - newly created Cell Array
|
||
|
*
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
template <typename... Targs>
|
||
|
TypedArray<Array> createCellArray(ArrayDimensions dims, Targs... data) {
|
||
|
auto retVal = createArray<Array>(std::move(dims));
|
||
|
if (retVal.getNumberOfElements() != 0) {
|
||
|
setCellValues(retVal.begin(), retVal.end(), data...);
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar TypedArray<MATLABString> from 7-bit ascii input data
|
||
|
* Input is converted to UTF16 prior to creating a TypedArray<MATLABString>
|
||
|
*
|
||
|
* @param val - std::string to be inserted into the scalar StringArray
|
||
|
*
|
||
|
* @return TypedArray<MATLABString> - a TypedArray with data of type MATLABString
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw NonAsciiCharInInputDataException - if input contains non-ascii data
|
||
|
*/
|
||
|
TypedArray<MATLABString> createScalar(const std::string& val) {
|
||
|
if (!detail::isAscii7(val)) {
|
||
|
throw NonAsciiCharInInputDataException(
|
||
|
std::string("Input data can only contain ASCII characters"));
|
||
|
}
|
||
|
return createScalar(String(val.begin(), val.end()));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a scalar ObjectArray
|
||
|
*
|
||
|
* @param val - val Object to be used to create the ObjectArray scalar
|
||
|
*
|
||
|
* @return ObjectArray - ObjectArray containing the object
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
ObjectArray createScalar(const Object& val) {
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
typedef int (*CreateScalarObjectFcnPtr)(typename impl::ArrayFactoryImpl* impl,
|
||
|
impl::ObjectImpl* objImpl,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateScalarObjectFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateScalarObjectFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SCALAR_OBJECT);
|
||
|
detail::throwIfError(fcn(pImpl.get(),
|
||
|
detail::Access::getImpl<impl::ObjectImpl>(val),
|
||
|
&impl));
|
||
|
return detail::Access::createObj<ObjectArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a 1xn CharArray from the specified char16_t string, where n is the
|
||
|
* string length
|
||
|
*
|
||
|
* @param str - String containing the data to be filled into the Array
|
||
|
*
|
||
|
* @return CharArray - a CharArray object containing data copied from str
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
CharArray createCharArray(String str) {
|
||
|
typedef int (*CreateCharArrayFromChar16FcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, const char16_t* data, size_t strlen,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateCharArrayFromChar16FcnPtr fcn =
|
||
|
detail::resolveFunction<CreateCharArrayFromChar16FcnPtr>(
|
||
|
detail::FunctionType::CREATE_CHAR_ARRAY_FROM_CHAR16);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(pImpl.get(), str.c_str(), str.size(), &impl));
|
||
|
return detail::Access::createObj<CharArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a 1xn CharArray from the specified std::string, where n is the
|
||
|
* string length. Data is checked for 7-bit ascii and converted from
|
||
|
* std::string<char> to std::string<CHAR16_T>.
|
||
|
*
|
||
|
* @param str - std::string containing the data to be filled into the Array
|
||
|
*
|
||
|
* @return CharArray - a CharArray object containing data copied from str
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw NonAsciiCharInInputDataException - if data contains non-ascii characters
|
||
|
*/
|
||
|
CharArray createCharArray(const std::string& str) {
|
||
|
if (!detail::isAscii7(str)) {
|
||
|
throw NonAsciiCharInInputDataException(
|
||
|
std::string("Input data can only contain ASCII characters"));
|
||
|
}
|
||
|
typedef int (*CreateCharArrayFromStringFcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, const char* data, size_t strlen,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateCharArrayFromStringFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateCharArrayFromStringFcnPtr>(
|
||
|
detail::FunctionType::CREATE_CHAR_ARRAY_FROM_STRING);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(fcn(pImpl.get(), str.c_str(), str.size(), &impl));
|
||
|
return detail::Access::createObj<CharArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a StructArray with the given dimensions and fieldnames
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param fieldNames - vector of the field names for the struct
|
||
|
*
|
||
|
* @return StructArray - an Array with the appropriate dimensions and fieldNames
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
* @throw DuplicateFieldNameInStructArrayException - if duplicate field names are specified
|
||
|
*/
|
||
|
StructArray createStructArray(ArrayDimensions dims, std::vector<std::string> fieldNames) {
|
||
|
typedef detail::NameListImpl* (*CreateNamesFcnPtr)(size_t num);
|
||
|
static const CreateNamesFcnPtr fcn3 =
|
||
|
detail::resolveFunction<CreateNamesFcnPtr>(detail::FunctionType::CREATE_NAMES);
|
||
|
NameList field_names(fcn3(fieldNames.size()));
|
||
|
for (const auto& field : fieldNames) {
|
||
|
typedef void (*AddNameFcnPtr)(typename detail::NameListImpl * impl, const char* name,
|
||
|
size_t nameLen);
|
||
|
static const AddNameFcnPtr fcn =
|
||
|
detail::resolveFunction<AddNameFcnPtr>(detail::FunctionType::ADD_NAME);
|
||
|
fcn(field_names.getImpl(), field.c_str(), field.size());
|
||
|
}
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
typedef int (*CreateStructArrayFcnPtr)(typename impl::ArrayFactoryImpl * impl, size_t * dims,
|
||
|
size_t numDims, typename detail::NameListImpl * names,
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateStructArrayFcnPtr fcn2 =
|
||
|
detail::resolveFunction<CreateStructArrayFcnPtr>(
|
||
|
detail::FunctionType::CREATE_STRUCT_ARRAY);
|
||
|
detail::throwIfError(
|
||
|
fcn2(pImpl.get(), &dims[0], dims.size(), field_names.getImpl(), &impl));
|
||
|
return detail::Access::createObj<StructArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an Enumeration array. The class of the EnumArray is indicated by className.
|
||
|
* The array is initialized with the list of enumeration names provided by the caller.
|
||
|
*
|
||
|
* @param dims array dimensions
|
||
|
* @param className class name of the enumeration array
|
||
|
* @param enums List of the enumeration names
|
||
|
*
|
||
|
* @return EnumArray - the EnumArray that was created
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw MustSpecifyClassNameException - if an empty class name is specified
|
||
|
* @throw WrongNumberOfEnumsSuppliedException - if the wrong number of enumerations is provided
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
*/
|
||
|
EnumArray createEnumArray(ArrayDimensions dims,
|
||
|
std::string className,
|
||
|
std::vector<std::string> enums) {
|
||
|
typedef detail::NameListImpl* (*CreateNamesFcnPtr)(size_t num);
|
||
|
static const CreateNamesFcnPtr fcn3 =
|
||
|
detail::resolveFunction<CreateNamesFcnPtr>(detail::FunctionType::CREATE_NAMES);
|
||
|
NameList enum_names(fcn3(enums.size()));
|
||
|
for (const auto& e : enums) {
|
||
|
typedef void (*AddNameFcnPtr)(typename detail::NameListImpl * impl, const char* name,
|
||
|
size_t nameLen);
|
||
|
static const AddNameFcnPtr fcn =
|
||
|
detail::resolveFunction<AddNameFcnPtr>(detail::FunctionType::ADD_NAME);
|
||
|
fcn(enum_names.getImpl(), e.c_str(), e.size());
|
||
|
}
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
typedef int (*CreateEnumArrayWithEnumsFcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, size_t * dims, size_t numDims, const char* cls,
|
||
|
size_t clsSize, typename detail::NameListImpl* names, typename impl::ArrayImpl** retVal);
|
||
|
static const CreateEnumArrayWithEnumsFcnPtr fcn2 =
|
||
|
detail::resolveFunction<CreateEnumArrayWithEnumsFcnPtr>(
|
||
|
detail::FunctionType::CREATE_ENUM_ARRAY_WITH_ENUMS);
|
||
|
detail::throwIfError(fcn2(pImpl.get(), &dims[0], dims.size(), className.c_str(),
|
||
|
className.size(), enum_names.getImpl(), &impl));
|
||
|
return detail::Access::createObj<EnumArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an Enumeration array. The class of the EnumArray is indicated by className.
|
||
|
*
|
||
|
* @param dims array dimensions
|
||
|
* @param className class name of the enumeration array
|
||
|
*
|
||
|
* @return EnumArray - the EnumArray that was created
|
||
|
*
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
* @throw NumberOfElementsExceedsMaximumException - if the ArrayDimensions create an Array which exceeds the max
|
||
|
* @throw MustSpecifyClassNameException - if an empty class name is specified
|
||
|
*/
|
||
|
EnumArray createEnumArray(ArrayDimensions dims, std::string className) {
|
||
|
typedef int (*CreateEnumArrayFcnPtr)(typename impl::ArrayFactoryImpl*, size_t*, size_t, const char*,
|
||
|
size_t, typename impl::ArrayImpl**);
|
||
|
static const CreateEnumArrayFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateEnumArrayFcnPtr>(detail::FunctionType::CREATE_ENUM_ARRAY);
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
detail::throwIfError(
|
||
|
fcn(pImpl.get(), &dims[0], dims.size(), className.c_str(), className.size(), &impl));
|
||
|
return detail::Access::createObj<EnumArray>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an empty Array. It contains no elements.
|
||
|
*
|
||
|
* @return Array - an empty Array
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
Array createEmptyArray() {
|
||
|
return createArray<double>({0, 0});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a buffer which can be passed into createArrayFromBuffer()
|
||
|
* No data copies are made when creating an Array from a buffer. Data
|
||
|
* must be in column major order.
|
||
|
*
|
||
|
* @param numberOfElements - the number of elements, not the actual buffer size
|
||
|
*
|
||
|
* @return buffer_ptr<T> - unique_ptr containing the buffer
|
||
|
*
|
||
|
* @throw InvalidArrayTypeException - if buffer type is not recognized as valid
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
template <typename T>
|
||
|
buffer_ptr_t<T> createBuffer(size_t numberOfElements) {
|
||
|
void* buffer = nullptr;
|
||
|
buffer_deleter_t deleter = nullptr;
|
||
|
typedef int (*CreateBufferFcnPtr)(typename impl::ArrayFactoryImpl * impl, void** buffer,
|
||
|
void (**deleter)(void*), int dataType,
|
||
|
size_t numElements);
|
||
|
static const CreateBufferFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateBufferFcnPtr>(detail::FunctionType::CREATE_BUFFER);
|
||
|
detail::throwIfError(fcn(pImpl.get(), &buffer, &deleter,
|
||
|
static_cast<int>(GetArrayType<T>::type), numberOfElements));
|
||
|
return buffer_ptr_t<T>(static_cast<T*>(buffer), deleter);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a TypedArray<T> using the given buffer
|
||
|
* No data copies are made when creating an Array from a buffer. The TypedArray<T>
|
||
|
* takes ownership of the buffer.
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param buffer - buffer containing the data. Buffer will not be copied. Array takes ownership
|
||
|
*
|
||
|
* @return TypedArray<T> - TypedArray<T> which wraps the buffer
|
||
|
*
|
||
|
* @throw InvalidArrayTypeException - if buffer type is not recognized as valid
|
||
|
* @throw FeatureNotSupportedException - if creating an array with a row major layout using a release prior to R2019a
|
||
|
* @throw matlab::InvalidMemoryLayoutException - if the array could not be allocated
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*/
|
||
|
template <typename T>
|
||
|
TypedArray<T> createArrayFromBuffer(ArrayDimensions dims,
|
||
|
buffer_ptr_t<T> buffer,
|
||
|
MemoryLayout memoryLayout = MemoryLayout::COLUMN_MAJOR) {
|
||
|
buffer_deleter_t deleter = buffer.get_deleter();
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
typedef int (*CreateArrayFromBufferV2FcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, int arrayType, size_t* dims, size_t numDims,
|
||
|
void* buffer, void (*deleter)(void*), typename impl::ArrayImpl**, int memoryLayout);
|
||
|
static const CreateArrayFromBufferV2FcnPtr fcn =
|
||
|
detail::resolveFunctionNoExcept<CreateArrayFromBufferV2FcnPtr>(
|
||
|
detail::FunctionType::CREATE_ARRAY_FROM_BUFFER_V2);
|
||
|
if (fcn != nullptr) {
|
||
|
detail::throwIfError(fcn(pImpl.get(), static_cast<int>(GetArrayType<T>::type), &dims[0],
|
||
|
dims.size(), buffer.release(), deleter, &impl,
|
||
|
static_cast<int>(memoryLayout)));
|
||
|
}
|
||
|
else {
|
||
|
// new version is not available
|
||
|
// if asking for a row-major need to throw
|
||
|
if (memoryLayout == MemoryLayout::ROW_MAJOR) {
|
||
|
throw FeatureNotSupportedException(std::string("Row-major buffers require ") +
|
||
|
std::string("2019a"));
|
||
|
}
|
||
|
typedef int (*CreateArrayFromBufferFcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, int arrayType, size_t* dims, size_t numDims,
|
||
|
void* buffer, void (*deleter)(void*), typename impl::ArrayImpl**);
|
||
|
static const CreateArrayFromBufferFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateArrayFromBufferFcnPtr>(
|
||
|
detail::FunctionType::CREATE_ARRAY_FROM_BUFFER);
|
||
|
|
||
|
detail::throwIfError(fcn(pImpl.get(), static_cast<int>(GetArrayType<T>::type), &dims[0],
|
||
|
dims.size(), buffer.release(), deleter, &impl));
|
||
|
}
|
||
|
return detail::Access::createObj<TypedArray<T>>(impl);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a SparseArray<T> with the given dimensions.
|
||
|
* Only two dimensions are allowed for sparse arrays.
|
||
|
*
|
||
|
* @param dims - the dimensions for the Array
|
||
|
* @param nnz - number of non-zero elements
|
||
|
* @param data - buffer containing the non-zero elements. Buffer will not be copied. Array takes
|
||
|
* ownership
|
||
|
* @param rows - buffer containing the row value for each element. Buffer will not be copied.
|
||
|
* Array takes ownership
|
||
|
* @param cols - buffer containing the column value for each element. Buffer will not be copied.
|
||
|
* Array takes ownership
|
||
|
*
|
||
|
* @return SparseArray<T> - a sparse array with the appropriate type and dimensions, and data
|
||
|
*
|
||
|
* @throw InvalidArrayTypeException - if array type is not recognized as valid
|
||
|
* @throw InvalidDimensionsInSparseArrayException if more than two dimensions are specified.
|
||
|
* @throw matlab::OutOfMemoryException - if the array could not be allocated
|
||
|
*
|
||
|
*/
|
||
|
template <typename T>
|
||
|
typename std::enable_if<std::is_same<double, T>::value || std::is_same<bool, T>::value ||
|
||
|
std::is_same<std::complex<double>, T>::value,
|
||
|
SparseArray<T>>::type
|
||
|
createSparseArray(ArrayDimensions dims,
|
||
|
size_t nnz,
|
||
|
buffer_ptr_t<T> data,
|
||
|
buffer_ptr_t<size_t> rows,
|
||
|
buffer_ptr_t<size_t> cols) {
|
||
|
|
||
|
// If more than two dimensions are specified, throw an exception
|
||
|
if (dims.size() > 2) {
|
||
|
throw InvalidDimensionsInSparseArrayException(
|
||
|
std::string("Sparse Array can only have 2 dimensions"));
|
||
|
}
|
||
|
|
||
|
buffer_deleter_t data_deleter = data.get_deleter();
|
||
|
buffer_deleter_t rows_deleter = rows.get_deleter();
|
||
|
buffer_deleter_t cols_deleter = cols.get_deleter();
|
||
|
|
||
|
impl::ArrayImpl* impl = nullptr;
|
||
|
typedef int (*CreateSparseArrayFromBufferFcnPtr)(
|
||
|
typename impl::ArrayFactoryImpl * impl, int arrayType, size_t* dims, size_t numDims, size_t nnz,
|
||
|
void* dataBuffer, void (*dataDeleter)(void*), size_t* rowsBuffer,
|
||
|
void (*rowsDeleter)(void*), size_t* colsBuffer, void (*colsDeleter)(void*),
|
||
|
typename impl::ArrayImpl**);
|
||
|
static const CreateSparseArrayFromBufferFcnPtr fcn =
|
||
|
detail::resolveFunction<CreateSparseArrayFromBufferFcnPtr>(
|
||
|
detail::FunctionType::CREATE_SPARSE_ARRAY_FROM_BUFFER);
|
||
|
detail::throwIfError(fcn(pImpl.get(), static_cast<int>(GetSparseArrayType<T>::type),
|
||
|
&dims[0], dims.size(), nnz, data.release(), data_deleter,
|
||
|
rows.release(), rows_deleter, cols.release(), cols_deleter,
|
||
|
&impl));
|
||
|
return detail::Access::createObj<SparseArray<T>>(impl);
|
||
|
}
|
||
|
|
||
|
|
||
|
protected:
|
||
|
std::shared_ptr<impl::ArrayFactoryImpl> pImpl;
|
||
|
|
||
|
private:
|
||
|
ArrayFactory& operator=(ArrayFactory const& rhs) = delete;
|
||
|
ArrayFactory(const ArrayFactory& rhs) = delete;
|
||
|
|
||
|
class NameList {
|
||
|
public:
|
||
|
NameList(detail::NameListImpl* impl)
|
||
|
: pImpl(std::shared_ptr<detail::NameListImpl>(impl, [](detail::NameListImpl* ptr) {
|
||
|
typedef void (*DestroyNamesFcnPtr)(typename detail::NameListImpl * impl);
|
||
|
static const DestroyNamesFcnPtr destroyFcn =
|
||
|
detail::resolveFunction<DestroyNamesFcnPtr>(
|
||
|
detail::FunctionType::DESTROY_NAMES);
|
||
|
destroyFcn(ptr);
|
||
|
})) {
|
||
|
}
|
||
|
|
||
|
detail::NameListImpl* getImpl() const {
|
||
|
return pImpl.get();
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
std::shared_ptr<detail::NameListImpl> pImpl;
|
||
|
};
|
||
|
template <typename T>
|
||
|
typename std::enable_if<!std::is_base_of<Array, T>::value, Array>::type createValue(T value) {
|
||
|
return createScalar(std::move(value));
|
||
|
}
|
||
|
template <typename T>
|
||
|
typename std::enable_if<std::is_base_of<Array, T>::value, Array>::type createValue(T value) {
|
||
|
return matlab::data::Array(std::move(value));
|
||
|
}
|
||
|
template <typename T>
|
||
|
void setCellValues(TypedIterator<Array> it, TypedIterator<Array> end, T value) {
|
||
|
*it = createValue(std::move(value));
|
||
|
}
|
||
|
template <typename T, typename... Targs>
|
||
|
void setCellValues(TypedIterator<Array> it, TypedIterator<Array> end, T value, Targs... args) {
|
||
|
*it = createValue(std::move(value));
|
||
|
if (++it != end) {
|
||
|
setCellValues(std::move(it), std::move(end), args...);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
} // namespace data
|
||
|
} // namespace matlab
|
||
|
|
||
|
#endif
|