/* Copyright 2016-2020 The MathWorks, Inc. */ #ifndef ARRAY_FACTORY_HELPERS_HPP_ #define ARRAY_FACTORY_HELPERS_HPP_ #include "FunctionType.hpp" #include "publish_util.hpp" #include "ExceptionHelpers.hpp" namespace matlab { namespace data { namespace impl { class ArrayFactoryImpl; class ArrayImpl; } namespace detail { class NameListImpl; } } } namespace matlab { namespace data { namespace detail { template <typename ItType> void throwWrongNumberOfElementsException(ItType begin, ItType end, const ArrayDimensions& dims) { auto numel = (end - begin); std::string msg = std::string("Exactly ") + std::to_string(dims[0]*dims[1]) + std::string(" elements required to create ") + std::to_string(dims[0]) + std::string("x") + std::to_string(dims[1]) + std::string(" ObjectArray, but ") + std::to_string(numel) + std::string(" elements provided."); throwIfError(static_cast<int>(matlab::data::ExceptionType::InvalidNumberOfElementsProvided), msg); } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<(matlab::data::is_complex<T>::value || std::is_arithmetic<T>::value) && !std::is_same<T, bool>::value, TypedArray<typename GetReturnType<T>::type>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsAndDataFcnPtr)(matlab::data::impl::ArrayFactoryImpl* impl, int arrayType, size_t* dims, size_t numDims, const void* const dataStart, size_t numEl, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsAndDataFcnPtr fcn = resolveFunction<CreateArrayWithDimsAndDataFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS_AND_DATA); throwIfError(fcn(impl, static_cast<int>(GetArrayType<T>::type), &dims[0], dims.size(), &(*(begin)), (end - begin), &aImpl)); return Access::createObj<TypedArray<typename GetReturnType<T>::type>>(aImpl); } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, bool>::value, TypedArray<bool>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, int, size_t*, size_t, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsFcnPtr fcn = resolveFunction<CreateArrayWithDimsFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS); throwIfError(fcn(impl, static_cast<int>(GetArrayType<T>::type), &dims[0], dims.size(), &aImpl)); auto retVal = Access::createObj<TypedArray<T>>(aImpl); auto it = begin; for (auto& elem : retVal) { elem = *it; if (++it == end) { break; } } return retVal; } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, String>::value || std::is_same<T, const char16_t*>::value, TypedArray<typename GetReturnType<T>::type>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, int, size_t*, size_t, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsFcnPtr fcn = resolveFunction<CreateArrayWithDimsFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS); throwIfError(fcn(impl, static_cast<int>(GetArrayType<typename GetReturnType<T>::type>::type), &dims[0], dims.size(), &aImpl)); auto retVal = Access::createObj<TypedArray<typename GetReturnType<T>::type>>(aImpl); auto it = begin; for (auto elem : retVal) { elem = *it; if (++it == end) { break; } } return retVal; } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, Object>::value, TypedArray<T>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateObjectArrayWithObjsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, size_t*, size_t, matlab::data::impl::ObjectImpl*, matlab::data::impl::ArrayImpl**); static const CreateObjectArrayWithObjsFcnPtr fcn = resolveFunction<CreateObjectArrayWithObjsFcnPtr> (FunctionType::CREATE_OBJECT_ARRAY_WITH_OBJ); throwIfError(fcn(impl, &dims[0], dims.size(), Access::getImpl<matlab::data::impl::ObjectImpl>(*begin), &aImpl)); ObjectArray retVal = Access::createObj<ObjectArray>(aImpl); auto temp = retVal.getDimensions(); auto it = begin; for (auto elem : retVal) { if (it == end) { throwWrongNumberOfElementsException(begin, end, dims); } elem = T(*it); ++it; } if (it != end) { throwWrongNumberOfElementsException(begin, end, dims); } return retVal; } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, Array>::value, TypedArray<T>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, int, size_t*, size_t, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsFcnPtr fcn = resolveFunction<CreateArrayWithDimsFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS); throwIfError(fcn(impl, static_cast<int>(GetArrayType<T>::type), &dims[0], dims.size(), &aImpl)); auto retVal = Access::createObj<TypedArray<T>>(aImpl); auto it = begin; for (auto elem : retVal) { elem = T(*it); if (++it == end) { break; } } return retVal; } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, const char *>::value || std::is_same<T, std::string>::value, TypedArray<MATLABString>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { if (std::find_if(begin, end, [](std::string str) {return (isAscii7(str) == false); }) != end) { throw NonAsciiCharInInputDataException(std::string("Input data can only contain ASCII characters")); } matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, int, size_t*, size_t, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsFcnPtr fcn = resolveFunction<CreateArrayWithDimsFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS); throwIfError(fcn(impl, static_cast<int>(ArrayType::MATLAB_STRING), &dims[0], dims.size(), &aImpl)); auto retVal = Access::createObj<TypedArray<MATLABString>>(aImpl); auto it = begin; for (auto elem : retVal) { elem = *it; if (++it == end) { break; } } return retVal; } template <typename ItType, typename T = typename std::remove_cv<typename std::iterator_traits<ItType>::value_type>::type> typename std::enable_if<std::is_same<T, MATLABString>::value, TypedArray<MATLABString>>::type createArrayWithIterator(matlab::data::impl::ArrayFactoryImpl* impl, ArrayDimensions dims, ItType begin, ItType end) { matlab::data::impl::ArrayImpl* aImpl = nullptr; typedef int(*CreateArrayWithDimsFcnPtr)(matlab::data::impl::ArrayFactoryImpl*, int, size_t*, size_t, matlab::data::impl::ArrayImpl**); static const CreateArrayWithDimsFcnPtr fcn = resolveFunction<CreateArrayWithDimsFcnPtr> (FunctionType::CREATE_ARRAY_WITH_DIMS); throwIfError(fcn(impl, static_cast<int>(ArrayType::MATLAB_STRING), &dims[0], dims.size(), &aImpl)); auto retVal = Access::createObj<TypedArray<MATLABString>>(aImpl); auto it = begin; for (auto elem : retVal) { MATLABString x = *it; if (x) { elem = x; } if (++it == end) { break; } } return retVal; } } } } #endif