Commit a7a8248c authored by Kenneth Moreland's avatar Kenneth Moreland

Add data size introspection to DynamicArrayHandle.

Sometimes it is useful to know how big an array held in a
DynamicArrayHandle is. This adds two methods to DynamicArrayHandle:
GetNumberOfValues and GetNumberOfComponents. They allow you to query the
size of the array without having to statically cast to the array itself.
parent 79960e83
......@@ -21,13 +21,13 @@
#define vtk_m_cont_DynamicArrayHandle_h
#include <vtkm/TypeListTag.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/StorageListTag.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/cont/internal/SimplePolymorphicContainer.h>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/utility/enable_if.hpp>
......@@ -35,6 +35,65 @@
namespace vtkm {
namespace cont {
namespace detail {
/// \brief Base class for PolymorphicArrayHandleContainer
///
struct PolymorphicArrayHandleContainerBase
{
// This must exist so that subclasses are destroyed correctly.
virtual ~PolymorphicArrayHandleContainerBase() { }
virtual vtkm::IdComponent GetNumberOfComponents() const = 0;
virtual vtkm::Id GetNumberOfValues() const = 0;
virtual boost::shared_ptr<PolymorphicArrayHandleContainerBase>
NewInstance() const = 0;
};
/// \brief ArrayHandle container that can use C++ run-time type information.
///
/// The \c PolymorphicArrayHandleContainer is similar to the
/// \c SimplePolymorphicContainer in that it can contain an object of an
/// unkown type. However, this class specifically holds ArrayHandle objects
/// (with different template parameters) so that it can polymorphically answer
/// simple questions about the object.
///
template<typename T, typename Storage>
struct PolymorphicArrayHandleContainer
: public PolymorphicArrayHandleContainerBase
{
typedef vtkm::cont::ArrayHandle<T, Storage> ArrayHandleType;
ArrayHandleType Array;
VTKM_CONT_EXPORT
PolymorphicArrayHandleContainer() : Array() { }
VTKM_CONT_EXPORT
PolymorphicArrayHandleContainer(const ArrayHandleType &array)
: Array(array) { }
virtual vtkm::IdComponent GetNumberOfComponents() const
{
return vtkm::VecTraits<T>::NUM_COMPONENTS;
}
virtual vtkm::Id GetNumberOfValues() const
{
return this->Array.GetNumberOfValues();
}
virtual boost::shared_ptr<PolymorphicArrayHandleContainerBase>
NewInstance() const
{
return boost::shared_ptr<PolymorphicArrayHandleContainerBase>(
new PolymorphicArrayHandleContainer<T,Storage>());
}
};
} // namespace detail
namespace internal {
/// Behaves like (and is interchangable with) a DynamicArrayHandle. The
......@@ -82,8 +141,8 @@ public:
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
DynamicArrayHandle(const vtkm::cont::ArrayHandle<Type,Storage> &array)
: ArrayStorage(new vtkm::cont::internal::SimplePolymorphicContainer<
vtkm::cont::ArrayHandle<Type,Storage> >(array))
: ArrayStorage(new vtkm::cont::detail::PolymorphicArrayHandleContainer<
Type,Storage>(array))
{ }
template<typename TypeList, typename StorageList>
......@@ -109,14 +168,13 @@ public:
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<Type, Storage>
CastToArrayHandle(Type = Type(), Storage = Storage()) const {
vtkm::cont::internal::SimplePolymorphicContainer<
vtkm::cont::ArrayHandle<Type,Storage> > *container =
this->TryCastStorage<Type,Storage>();
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *container
= this->TryCastStorage<Type,Storage>();
if (container == NULL)
{
throw vtkm::cont::ErrorControlBadValue("Bad cast of dynamic array.");
}
return container->Item;
return container->Array;
}
/// Changes the types to try casting to when resolving this dynamic array,
......@@ -187,20 +245,38 @@ public:
return newArray;
}
/// \brief Get the number of components in each array value.
///
/// This method will query the array type for the number of components in
/// each value of the array. The number of components is determined by
/// the \c VecTraits::NUM_COMPONENTS trait class.
///
VTKM_CONT_EXPORT
vtkm::IdComponent GetNumberOfComponents() const
{
return this->ArrayStorage->GetNumberOfComponents();
}
/// \brief Get the number of values in the array.
///
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const
{
return this->ArrayStorage->GetNumberOfValues();
}
private:
boost::shared_ptr<vtkm::cont::internal::SimplePolymorphicContainerBase>
boost::shared_ptr<vtkm::cont::detail::PolymorphicArrayHandleContainerBase>
ArrayStorage;
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
vtkm::cont::internal::SimplePolymorphicContainer<
vtkm::cont::ArrayHandle<Type,Storage> > *
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *
TryCastStorage() const {
return
dynamic_cast<
vtkm::cont::internal::SimplePolymorphicContainer<
vtkm::cont::ArrayHandle<Type,Storage> > *>(
this->ArrayStorage.get());
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *>(
this->ArrayStorage.get());
}
};
......
......@@ -31,6 +31,7 @@ namespace internal {
/// \brief Base class for SimplePolymorphicContainer
///
struct SimplePolymorphicContainerBase {
// This must exist so that subclasses are destroyed correctly.
virtual ~SimplePolymorphicContainerBase() { }
virtual boost::shared_ptr<SimplePolymorphicContainerBase>
......
......@@ -28,6 +28,21 @@
#include "vtkm/cont/testing/Testing.h"
namespace vtkm {
// DynamicArrayHandle requires its value type to have a defined VecTraits
// class. One of the tests is to use an "unusual" array of std::string
// (which is pretty pointless but might tease out some assumptions).
// Make an implementation here. Because I am lazy, this is only a partial
// implementation.
template<>
struct VecTraits<std::string>
{
static const vtkm::IdComponent NUM_COMPONENTS = 1;
};
} // namespace vtkm
namespace {
static int g_FunctionCalls;
......
......@@ -33,6 +33,21 @@
#include <string>
#include <typeinfo>
namespace vtkm {
// DynamicArrayHandle requires its value type to have a defined VecTraits
// class. One of the tests is to use an "unusual" array of std::string
// (which is pretty pointless but might tease out some assumptions).
// Make an implementation here. Because I am lazy, this is only a partial
// implementation.
template<>
struct VecTraits<std::string>
{
static const vtkm::IdComponent NUM_COMPONENTS = 1;
};
} // namespace vtkm
namespace {
const vtkm::Id ARRAY_SIZE = 10;
......@@ -89,8 +104,20 @@ struct CheckFunctor
}
};
void CheckDynamicArray(vtkm::cont::DynamicArrayHandle array)
void BasicDynamicArrayChecks(const vtkm::cont::DynamicArrayHandle &array,
vtkm::IdComponent numComponents)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE,
"Dynamic array reports unexpected size.");
VTKM_TEST_ASSERT(array.GetNumberOfComponents() == numComponents,
"Dynamic array reports unexpected number of components.");
}
void CheckDynamicArray(vtkm::cont::DynamicArrayHandle array,
vtkm::IdComponent numComponents)
{
BasicDynamicArrayChecks(array, numComponents);
array.CastAndCall(CheckFunctor());
VTKM_TEST_ASSERT(CheckCalled,
......@@ -99,8 +126,11 @@ void CheckDynamicArray(vtkm::cont::DynamicArrayHandle array)
template<typename TypeList, typename StorageList>
void CheckDynamicArray(
vtkm::cont::internal::DynamicArrayHandleCast<TypeList, StorageList> array)
vtkm::cont::internal::DynamicArrayHandleCast<TypeList, StorageList> array,
vtkm::IdComponent numComponents)
{
BasicDynamicArrayChecks(array, numComponents);
array.CastAndCall(CheckFunctor());
VTKM_TEST_ASSERT(CheckCalled,
......@@ -125,7 +155,7 @@ template<typename T, typename DynamicArrayType>
void TryNewInstance(T, DynamicArrayType originalArray)
{
// This check should already have been performed by caller, but just in case.
CheckDynamicArray(originalArray);
CheckDynamicArray(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS);
std::cout << "Create new instance of array." << std::endl;
DynamicArrayType newArray = originalArray.NewInstance();
......@@ -142,7 +172,7 @@ void TryNewInstance(T, DynamicArrayType originalArray)
{
staticArray.GetPortalControl().Set(index, TestValue(index+100, T()));
}
CheckDynamicArray(originalArray);
CheckDynamicArray(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS);
std::cout << "Set the new static array to expected values and make sure the new" << std::endl
<< "dynamic array points to the same new values." << std::endl;
......@@ -150,7 +180,7 @@ void TryNewInstance(T, DynamicArrayType originalArray)
{
staticArray.GetPortalControl().Set(index, TestValue(index, T()));
}
CheckDynamicArray(newArray);
CheckDynamicArray(newArray, vtkm::VecTraits<T>::NUM_COMPONENTS);
}
template<typename T>
......@@ -160,7 +190,7 @@ void TryDefaultType(T)
vtkm::cont::DynamicArrayHandle array = CreateDynamicArray(T());
CheckDynamicArray(array);
CheckDynamicArray(array, vtkm::VecTraits<T>::NUM_COMPONENTS);
TryNewInstance(T(), array);
}
......@@ -173,7 +203,8 @@ struct TryBasicVTKmType
vtkm::cont::DynamicArrayHandle array = CreateDynamicArray(T());
CheckDynamicArray(array.ResetTypeList(vtkm::TypeListTagAll()));
CheckDynamicArray(array.ResetTypeList(vtkm::TypeListTagAll()),
vtkm::VecTraits<T>::NUM_COMPONENTS);
TryNewInstance(T(), array.ResetTypeList(vtkm::TypeListTagAll()));
}
......@@ -186,7 +217,7 @@ void TryUnusualType()
try
{
CheckDynamicArray(array);
CheckDynamicArray(array, 1);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type.");
}
catch (vtkm::cont::ErrorControlBadValue)
......@@ -195,7 +226,7 @@ void TryUnusualType()
}
CheckCalled = false;
CheckDynamicArray(array.ResetTypeList(TypeListTagString()));
CheckDynamicArray(array.ResetTypeList(TypeListTagString()), 1);
VTKM_TEST_ASSERT(CheckCalled,
"The functor was never called (and apparently a bad value exception not thrown).");
std::cout << " Found type when type list was reset." << std:: endl;
......@@ -208,7 +239,7 @@ void TryUnusualStorage()
try
{
CheckDynamicArray(array);
CheckDynamicArray(array, 1);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized storage.");
}
catch (vtkm::cont::ErrorControlBadValue)
......@@ -217,7 +248,7 @@ void TryUnusualStorage()
}
CheckCalled = false;
CheckDynamicArray(array.ResetStorageList(StorageListTagUnusual()));
CheckDynamicArray(array.ResetStorageList(StorageListTagUnusual()), 1);
std::cout << " Found instance when storage list was reset." << std:: endl;
}
......@@ -228,7 +259,7 @@ void TryUnusualTypeAndStorage()
try
{
CheckDynamicArray(array);
CheckDynamicArray(array, 1);
VTKM_TEST_FAIL(
"CastAndCall failed to error for unrecognized type/storage.");
}
......@@ -240,7 +271,7 @@ void TryUnusualTypeAndStorage()
try
{
CheckDynamicArray(array.ResetTypeList(TypeListTagString()));
CheckDynamicArray(array.ResetTypeList(TypeListTagString()), 1);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized storage.");
}
catch (vtkm::cont::ErrorControlBadValue)
......@@ -250,7 +281,7 @@ void TryUnusualTypeAndStorage()
try
{
CheckDynamicArray(array.ResetStorageList(StorageListTagUnusual()));
CheckDynamicArray(array.ResetStorageList(StorageListTagUnusual()), 1);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type.");
}
catch (vtkm::cont::ErrorControlBadValue)
......@@ -261,13 +292,15 @@ void TryUnusualTypeAndStorage()
CheckCalled = false;
CheckDynamicArray(array
.ResetTypeList(TypeListTagString())
.ResetStorageList(StorageListTagUnusual()));
.ResetStorageList(StorageListTagUnusual()),
1);
std::cout << " Found instance when type and storage lists were reset." << std:: endl;
CheckCalled = false;
CheckDynamicArray(array
.ResetStorageList(StorageListTagUnusual())
.ResetTypeList(TypeListTagString()));
.ResetTypeList(TypeListTagString()),
1);
std::cout << " Found instance when storage and type lists were reset." << std:: endl;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment