Commit a1db41d2 authored by David Thompson's avatar David Thompson
Browse files

Provide a way to stream vtkVariant objects.

Change-Id: I49840f96b2e15ed6a7213b45c9a76c486c93ff04
parent 66d99ee0
......@@ -2,7 +2,7 @@
vtk_module_test_executable(
${vtk-module}CxxTests
coverClientServer.cxx)
add_test(
NAME vtkClientServerCoverage
COMMAND ${vtk-module}CxxTests)
......
#include "vtkClientServerStream.h"
#include "vtkVariantArray.h"
#include "vtkStringArray.h"
#include "vtkDoubleArray.h"
#include "vtkNew.h"
static double dblIni[] = { 904., 906., 917. };
static const char* strIni[] = { "901", "Turbo", "Targa" };
template <class T>
struct Help
......@@ -53,6 +60,51 @@ void do_store(vtkClientServerStream& css)
#endif
Help<float>::Store(css);
Help<double>::Store(css);
vtkVariant varStr("911");
css << varStr;
vtkVariant varNum(356.0);
css << varNum;
// Test a variant that is itself an array of primitives (doubles).
vtkNew<vtkDoubleArray> dblArr;
dblArr->SetArray(dblIni, sizeof(dblIni) / sizeof(dblIni[0]), 1);
vtkVariant varDblArr(dblArr.GetPointer());
css << varDblArr;
// Test a variant that is itself an array of composites (strings).
vtkNew<vtkStringArray> strArr;
strArr->SetNumberOfValues(sizeof(strIni) / sizeof(strIni[0]));
for (vtkIdType i = 0; i < strArr->GetNumberOfValues(); ++i)
{
strArr->SetValue(i, strIni[i]);
}
vtkVariant varStrArr(strArr.GetPointer());
css << varStrArr;
// Test a variant that is itself an array of composites (variants).
vtkNew<vtkVariantArray> varArr;
varArr->SetNumberOfValues(sizeof(strIni) / sizeof(strIni[0]));
for (vtkIdType i = 0; i < varArr->GetNumberOfValues(); ++i)
{
vtkVariant tmp(strIni[i]);
bool numeric;
double x = tmp.ToNumeric(&numeric, &x);;
if (numeric)
{
varArr->SetVariantValue(i, x);
}
else
{
varArr->SetVariantValue(i, strIni[i]);
}
}
vtkVariant varVarArr(varArr.GetPointer());
css << varVarArr;
vtkVariant varInvalid;
css << varInvalid;
css << "123";
{
vtkClientServerStream nested;
......@@ -112,6 +164,63 @@ bool do_check(vtkClientServerStream& css)
if(!Help<double>::Check(css, arg)) { return false; }
}
{
vtkVariant varOut;
if (!css.GetArgument(0, arg, &varOut) || varOut.ToString() != "911")
{
cout << "Variant was \"" << varOut.ToString().c_str() << "\" instead of 911\n";
return false;
}
if (!css.GetArgument(0, arg, &varOut) || varOut.ToDouble() != 356.0 )
{
cout << "Variant was \"" << varOut.ToString().c_str() << "\" instead of 356.0\n";
return false;
}
vtkDoubleArray* dblArr;
if (
!css.GetArgument(0, arg, &varOut) ||
!(dblArr = vtkDoubleArray::SafeDownCast(varOut.ToArray())) ||
dblArr->GetMaxId() != (sizeof(dblIni) / sizeof(dblIni[0]) - 1) ||
dblArr->GetValue(0) != dblIni[0] ||
dblArr->GetValue(1) != dblIni[1] ||
dblArr->GetValue(2) != dblIni[2]
)
{
cout << "Variant was \"" << varOut.ToString().c_str() << "\" instead of (904.0, 906.0, 917.0)\n";
return false;
}
vtkStringArray* strArr;
if (
!css.GetArgument(0, arg, &varOut) ||
!(strArr = vtkStringArray::SafeDownCast(varOut.ToArray())) ||
strArr->GetMaxId() != (sizeof(strIni) / sizeof(strIni[0]) - 1) ||
strArr->GetValue(0) != strIni[0] ||
strArr->GetValue(1) != strIni[1] ||
strArr->GetValue(2) != strIni[2]
)
{
cout << "Variant was \"" << varOut.ToString().c_str() << "\" instead of (\"901\", \"Turbo\", \"Targa\")\n";
return false;
}
vtkVariantArray* varArr;
if (
!css.GetArgument(0, arg, &varOut) ||
!(varArr = vtkVariantArray::SafeDownCast(varOut.ToArray())) ||
varArr->GetMaxId() != (sizeof(strIni) / sizeof(strIni[0]) - 1) ||
varArr->GetValue(0) != vtkVariant(strIni[0]).ToDouble() ||
varArr->GetValue(1) != strIni[1] ||
varArr->GetValue(2) != strIni[2]
)
{
cout << "Variant was \"" << varOut.ToString().c_str() << "\" instead of (901.0, \"Turbo\", \"Targa\")\n";
return false;
}
if (!css.GetArgument(0, arg, &varOut) || varOut.IsValid())
{
cout << "Variant that was supposed to be invalid is valid\n";
return false;
}
}
{
const char* s;
if(!css.GetArgument(0, arg++, &s) || strcmp(s, "123") != 0)
{
......
......@@ -14,9 +14,14 @@
=========================================================================*/
#include "vtkClientServerStream.h"
#include "vtkAbstractArray.h"
#include "vtkArrayIterator.h"
#include "vtkArrayIteratorIncludes.h"
#include "vtkByteSwap.h"
#include "vtkSmartPointer.h"
#include "vtkType.h"
#include "vtkTypeTraits.h"
#include "vtkVariantExtract.h"
#include <string>
#include <vector>
......@@ -252,7 +257,7 @@ void vtkClientServerStream::Reset()
{
// Empty the entire stream.
vtkClientServerStreamInternals::DataType().swap(this->Internal->Data);
this->Internal->ValueOffsets.erase(this->Internal->ValueOffsets.begin(),
this->Internal->ValueOffsets.end());
this->Internal->MessageIndexes.erase(this->Internal->MessageIndexes.begin(),
......@@ -424,6 +429,68 @@ vtkClientServerStream::operator << (vtkObjectBase* obj)
return this->Write(&obj, sizeof(obj));
}
//----------------------------------------------------------------------------
vtkClientServerStream&
vtkClientServerStream::operator << (const vtkStdString& val)
{
(*this) << val.c_str();
return *this;
}
//----------------------------------------------------------------------------
template<typename iterT>
void vtkClientServerPutArrayVariant(vtkClientServerStream& css, iterT* it)
{
vtkIdType numVals = it->GetNumberOfValues();
for (vtkIdType i = 0; i < numVals; ++i)
{
css << it->GetValue(i);
}
}
//----------------------------------------------------------------------------
vtkClientServerStream&
vtkClientServerStream::operator << (const vtkVariant& val)
{
vtkTypeUInt8 variantValid = val.IsValid();
if (variantValid && val.IsVTKObject() && !val.IsArray())
{ // If val is a VTK object that is not an array, fail by encoding an invalid vtkVariant value.
variantValid = 0;
}
(*this) << variantValid;
if (variantValid)
{
vtkTypeUInt8 variantType = static_cast<vtkTypeUInt8>(val.GetType());
(*this) << variantType;
bool validDummy;
switch (variantType)
{
vtkExtendedTemplateMacro(
(*this) << vtkVariantExtract<VTK_TT>(val, validDummy));
case VTK_OBJECT:
{ // The object must be an array; encode it.
vtkAbstractArray* array = val.ToArray();
vtkTypeInt32 arrayType = array->GetDataType();
vtkTypeInt32 numComponents = array->GetNumberOfComponents();
vtkTypeInt64 numTuples = array->GetNumberOfTuples();
(*this) << arrayType << numComponents << numTuples;
vtkArrayIterator* iter = array->NewIterator();
switch(array->GetDataType())
{
vtkExtendedArrayIteratorTemplateMacro(
vtkClientServerPutArrayVariant<VTK_TT>(*this,static_cast<VTK_TT*>(iter)));
}
iter->Delete();
}
break;
}
}
return *this;
}
//----------------------------------------------------------------------------
vtkClientServerStream& vtkClientServerStream::operator << (bool x)
{
......@@ -1055,6 +1122,17 @@ int vtkClientServerStream::GetArgument(int message, int argument,
return 0;
}
int vtkClientServerStream::GetArgument(int message, int argument, vtkStdString* value) const
{
char* tmp;
if (this->GetArgument(message, argument, &tmp))
{
*value = tmp;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
int vtkClientServerStream::GetArgument(int message, int argument,
vtkClientServerStream* value) const
......@@ -1172,6 +1250,93 @@ int vtkClientServerStream::GetArgument(int message, int argument,
return result;
}
template<typename T>
int vtkClientServerGetVariant(const vtkClientServerStream* self, int message, int& argument, vtkVariant& out)
{
T raw;
int result = self->GetArgument(message, argument++, &raw);
if (!result) return result;
out = raw;
return result; // result != 0 by definition
}
// Specialize for vtkVariant as \a argument is handled differently.
template<>
int vtkClientServerGetVariant<vtkVariant>(const vtkClientServerStream* self, int message, int& argument, vtkVariant& out)
{
int result = self->GetArgument(message, argument, &out);
if (!result) return result;
return result; // result != 0 by definition
}
template<typename T>
int vtkClientServerGetArrayVariant(const vtkClientServerStream* self, int message, int& argument, vtkAbstractArray* array)
{
vtkVariant value;
vtkIdType maxId = array->GetMaxId();
int result = 1;
for (vtkIdType i = 0; i <= maxId; ++i)
{
result = vtkClientServerGetVariant<T>(self, message, argument, value);
if (!result) return result;
array->SetVariantValue(i, value);
}
return result;
}
int vtkClientServerStream::GetArgument(int message, int& argument, vtkVariant* value) const
{
int result;
vtkTypeUInt8 variantValid;
result = this->GetArgument(message, argument++, &variantValid);
if (!result) return result;
if (variantValid)
{
vtkTypeUInt8 variantType;
result = this->GetArgument(message, argument++, &variantType);
if (!result) return result;
switch (variantType)
{
vtkExtendedTemplateMacro(
vtkClientServerGetVariant<VTK_TT>(this, message, argument, *value));
case VTK_OBJECT:
{
// Only vtkAbstractArray subclasses are supported, and only their raw values are encoded (no vtkInformation keys)
// Packed values include: the array type, the # components(nc), # tuples(nt), nc*nt raw values.
vtkTypeInt32 arrayType;
vtkTypeInt32 numComponents;
vtkTypeInt64 numTuples;
result = this->GetArgument(message, argument++, &arrayType);
if (!result) return result;
result = this->GetArgument(message, argument++, &numComponents);
if (!result) return result;
result = this->GetArgument(message, argument++, &numTuples);
if (!result) return result;
vtkSmartPointer<vtkAbstractArray> array;
array.TakeReference(vtkAbstractArray::CreateArray(arrayType));
if (!array) return 1;
array->SetNumberOfComponents(numComponents);
array->SetNumberOfTuples(numTuples);
switch (arrayType)
{
vtkExtraExtendedTemplateMacro(
vtkClientServerGetArrayVariant<VTK_TT>(this, message, argument, array));
}
*value = array.GetPointer();
}
break;
}
}
else
{
*value = vtkVariant();
}
return result;
}
//----------------------------------------------------------------------------
int vtkClientServerStream::GetArgumentLength(int message, int argument,
vtkTypeUInt32* length) const
......
......@@ -25,6 +25,7 @@
#define __vtkClientServerStream_h
#include "vtkClientServerID.h"
#include "vtkVariant.h"
class vtkClientServerStreamInternals;
......@@ -154,10 +155,21 @@ public:
#endif
int GetArgument(int message, int argument, const char** value) const;
int GetArgument(int message, int argument, char** value) const;
int GetArgument(int message, int argument, vtkStdString* value) const;
int GetArgument(int message, int argument, vtkClientServerStream* value) const;
int GetArgument(int message, int argument, vtkClientServerID* value) const;
int GetArgument(int message, int argument, vtkObjectBase** value) const;
// Description:
// Get the value of the given argument in the given message.
// Returns whether the argument could be converted to the requested
// type.
//
// Note that this version modifies the \a argument number as a vtkVariant
// is passed in the stream as a composite type with a variable
// number of primitive stream entries required to describe it.
int GetArgument(int message, int& argument, vtkVariant* value) const;
// Description:
// Get the length of an argument of an array type. Returns whether
// the argument is really an array type.
......@@ -216,6 +228,8 @@ public:
vtkClientServerStream& operator << (const vtkClientServerStream&);
vtkClientServerStream& operator << (vtkClientServerID);
vtkClientServerStream& operator << (vtkObjectBase*);
vtkClientServerStream& operator << (const vtkStdString&);
vtkClientServerStream& operator << (const vtkVariant&);
// Description:
// Stream operators for native types.
......
VTK @ faa812f1
Subproject commit 3c04d3955b4df89895a8f448e8fa5385fffcbe6a
Subproject commit faa812f1d50277cf62b63faae7f585cfe0698caa
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