/* Copyright 2017 The MathWorks, Inc. */ #ifndef MATLAB_EXTDATA_ARRAY_SPARSEARRAY_REF_HPP #define MATLAB_EXTDATA_ARRAY_SPARSEARRAY_REF_HPP #include "Reference.hpp" #include "TypedIterator.hpp" #include "SparseArray.hpp" #include "ArrayReferenceExt.hpp" #include "detail/publish_util.hpp" #include "detail/FunctionType.hpp" #include namespace matlab { namespace data { /** * This specialization of Reference class adds APIs to a reference to a SparseArray. Reference<> is not thread-safe - it should not * be passed between threads. * * @code * auto cellArray = factory.createArray({2,2}); * cellArray[0][0] = factory.createSparseArray(...); * SparseArrayRef ref(cellArray[0][0]); * * auto nnz = ref.getNumberOfNonZeroElements(); * * @endcode */ template class Reference> : public ArrayReferenceExt { public: typedef TypedIterator iterator; typedef TypedIterator::type> const_iterator; /** * Construct a Reference> from a Reference * * @param - rhs Reference value to be copied * @return - newly constructed Reference * @throw TypeMismatchException - if the element of the Array is not a SparseArray */ Reference(const Reference& rhs) : ArrayReferenceExt(rhs) { detail::validateUntypedArrayReference>(pImpl.get()); } /** * Return an iterator to the beginning of the array * * @return iterator * @throw none */ iterator begin() MW_NOEXCEPT { typedef detail::IteratorImpl*(*ArrayReferenceBeginFcnPtr)(detail::ReferenceImpl*, bool); static const ArrayReferenceBeginFcnPtr fcn = detail::resolveFunctionNoExcept (detail::FunctionType::ARRAY_REFERENCE_BEGIN_V2); if (fcn == nullptr) { static const ArrayReferenceBeginFcnPtr fcn2 = detail::resolveFunction (detail::FunctionType::ARRAY_REFERENCE_BEGIN); return detail::Access::createObj(fcn2(pImpl.get(), !std::is_const::value)); } return detail::Access::createObj(fcn(pImpl.get(), !std::is_const::value)); } /** * Return an const_iterator to the beginning of the array * * @return const_iterator * @throw none */ const_iterator begin() const MW_NOEXCEPT { return cbegin(); } /** * Return an const_iterator to the beginning of the array * * @return const_iterator * @throw none */ const_iterator cbegin() const MW_NOEXCEPT { typedef detail::IteratorImpl*(*ArrayReferenceBeginFcnPtr)(detail::ReferenceImpl*, bool); static const ArrayReferenceBeginFcnPtr fcn = detail::resolveFunctionNoExcept (detail::FunctionType::ARRAY_REFERENCE_BEGIN_V2); if (fcn == nullptr) { static const ArrayReferenceBeginFcnPtr fcn2 = detail::resolveFunction (detail::FunctionType::ARRAY_REFERENCE_BEGIN); return detail::Access::createObj(fcn2(pImpl.get(), false)); } return detail::Access::createObj(fcn(pImpl.get(), false)); } /** * Return an iterator to the end of the array * * @return iterator * @throw none */ iterator end() MW_NOEXCEPT { typedef detail::IteratorImpl*(*ArrayReferenceEndFcnPtr)(detail::ReferenceImpl*, bool); static const ArrayReferenceEndFcnPtr fcn = detail::resolveFunctionNoExcept (detail::FunctionType::ARRAY_REFERENCE_END_V2); if (fcn == nullptr) { static const ArrayReferenceEndFcnPtr fcn2 = detail::resolveFunction (detail::FunctionType::ARRAY_REFERENCE_END); return detail::Access::createObj(fcn2(pImpl.get(), !std::is_const::value)); } return detail::Access::createObj(fcn(pImpl.get(), !std::is_const::value)); } /** * Return an const_iterator to the end of the array * * @return const_iterator * @throw none */ const_iterator end() const MW_NOEXCEPT { return cend(); } /** * Return an const_iterator to the end of the array * * @return const_iterator * @throw none */ const_iterator cend() const MW_NOEXCEPT { typedef detail::IteratorImpl*(*ArrayReferenceEndFcnPtr)(detail::ReferenceImpl*, bool); static const ArrayReferenceEndFcnPtr fcn = detail::resolveFunctionNoExcept (detail::FunctionType::ARRAY_REFERENCE_END_V2); if (fcn == nullptr) { static const ArrayReferenceEndFcnPtr fcn2 = detail::resolveFunction (detail::FunctionType::ARRAY_REFERENCE_END); return detail::Access::createObj(fcn2(pImpl.get(), false)); } return detail::Access::createObj(fcn(pImpl.get(), false)); } /** * This API returns the number of non-zero elements in the array. * Since sparse arrays only store non-zero elements, this API effectively * returns the actual array size. It is different from array dimensions * that specify the full array size. * @return Number of non-zero elements in the array * @throw None */ size_t getNumberOfNonZeroElements() const MW_NOEXCEPT { size_t val; typedef void(*SparseArrayRefGetNumNonZeroElementsFcnPtr)(detail::ReferenceImpl*, size_t*); static const SparseArrayRefGetNumNonZeroElementsFcnPtr fcn = detail::resolveFunction (detail::FunctionType::SPARSE_ARRAY_REF_GET_NUM_NONZERO_ELEMENTS); fcn(pImpl.get(), &val); return val; } protected: friend class detail::Access; Reference(std::shared_ptr impl) MW_NOEXCEPT : ArrayReferenceExt(impl) {} Reference() = delete; }; template using SparseArrayRef = Reference>; } } #endif