Fix reading of string arrays

This commit is contained in:
Sujin Philip 2021-05-11 11:40:19 -04:00
parent e97d72a528
commit d7b2fec447
5 changed files with 112 additions and 11 deletions

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c20b10be38f4dd931bebbea201fb1d4b3b033c048f2e2c77be369bd58d9d0b0a
size 603

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:efa0d42dc02757126f2186f8c479e370f462c3cd7a16417240d967294725cdab
size 367

@ -322,6 +322,12 @@ void VTKDataSetReaderBase::ReadAttributes()
{ {
association = vtkm::cont::Field::Association::CELL_SET; association = vtkm::cont::Field::Association::CELL_SET;
} }
else if (tag == "FIELD") // can see field in this position also
{
this->ReadGlobalFields(nullptr);
this->DataFile->Stream >> tag;
continue;
}
else else
{ {
internal::parseAssert(false); internal::parseAssert(false);
@ -693,16 +699,11 @@ void VTKDataSetReaderBase::DoSkipArrayVariant(std::string dataType,
std::size_t numElements, std::size_t numElements,
vtkm::IdComponent numComponents) vtkm::IdComponent numComponents)
{ {
// string is unsupported for SkipArrayVariant, so it requires some // string requires some special handling
// special handling if (dataType == "string" || dataType == "utf8_string")
if (dataType == "string")
{ {
const vtkm::Id stringCount = numComponents * static_cast<vtkm::Id>(numElements); const vtkm::Id stringCount = numComponents * static_cast<vtkm::Id>(numElements);
for (vtkm::Id i = 0; i < stringCount; ++i) this->SkipStringArray(stringCount);
{
std::string trash;
this->DataFile->Stream >> trash;
}
} }
else else
{ {
@ -722,9 +723,20 @@ vtkm::cont::UnknownArrayHandle VTKDataSetReaderBase::DoReadArrayVariant(
vtkm::cont::ArrayHandle<vtkm::Float32> empty; vtkm::cont::ArrayHandle<vtkm::Float32> empty;
vtkm::cont::UnknownArrayHandle data(empty); vtkm::cont::UnknownArrayHandle data(empty);
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType); // string requires some special handling
vtkm::io::internal::SelectTypeAndCall( if (dataType == "string" || dataType == "utf8_string")
typeId, numComponents, ReadArrayVariant(this, association, numElements, data)); {
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"Support for data type 'string' and 'utf8_string' is not implemented. Skipping.");
const vtkm::Id stringCount = numComponents * static_cast<vtkm::Id>(numElements);
this->SkipStringArray(stringCount);
}
else
{
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
vtkm::io::internal::SelectTypeAndCall(
typeId, numComponents, ReadArrayVariant(this, association, numElements, data));
}
return data; return data;
} }
@ -758,6 +770,65 @@ void VTKDataSetReaderBase::SkipArray(std::size_t numElements,
this->SkipArrayMetaData(numComponents); this->SkipArrayMetaData(numComponents);
} }
void VTKDataSetReaderBase::SkipStringArray(std::size_t numStrings)
{
if (this->DataFile->IsBinary)
{
for (std::size_t i = 0; i < numStrings; ++i)
{
auto firstByte = this->DataFile->Stream.peek();
auto type = firstByte >> 6;
switch (type)
{
case 3: // length stored in 1 byte
{
auto length = this->DataFile->Stream.get();
length &= 0x3F;
this->DataFile->Stream.seekg(static_cast<std::streamoff>(length), std::ios_base::cur);
break;
}
case 2: // length stored in 2 bytes
{
vtkm::UInt16 length = 0;
auto bytes = reinterpret_cast<char*>(&length);
this->DataFile->Stream.read(bytes, 2);
std::swap(bytes[0], bytes[1]);
length &= 0x3FFF;
this->DataFile->Stream.seekg(static_cast<std::streamoff>(length), std::ios_base::cur);
break;
}
case 1: // length stored in 4 bytes
{
vtkm::UInt32 length = 0;
auto bytes = reinterpret_cast<char*>(&length);
this->DataFile->Stream.read(bytes, 4);
std::reverse(bytes, bytes + 4);
length &= 0x3FFFFFFF;
this->DataFile->Stream.seekg(static_cast<std::streamoff>(length), std::ios_base::cur);
break;
}
default: // length stored in 8 bytes
{
vtkm::UInt64 length = 0;
auto bytes = reinterpret_cast<char*>(&length);
this->DataFile->Stream.read(bytes, 8);
std::reverse(bytes, bytes + 8);
this->DataFile->Stream.seekg(static_cast<std::streamoff>(length), std::ios_base::cur);
break;
}
}
}
}
else
{
for (std::size_t i = 0; i < numStrings; ++i)
{
// ASCII mode stores one string per line
this->DataFile->Stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
void VTKDataSetReaderBase::SkipArrayMetaData(vtkm::IdComponent numComponents) void VTKDataSetReaderBase::SkipArrayMetaData(vtkm::IdComponent numComponents)
{ {
if (!this->DataFile->Stream.good()) if (!this->DataFile->Stream.good())

@ -271,6 +271,8 @@ protected:
vtkm::io::internal::DummyBitType, vtkm::io::internal::DummyBitType,
vtkm::IdComponent numComponents = 1); vtkm::IdComponent numComponents = 1);
VTKM_CONT void SkipStringArray(std::size_t numStrings);
VTKM_CONT void SkipArrayMetaData(vtkm::IdComponent numComponents); VTKM_CONT void SkipArrayMetaData(vtkm::IdComponent numComponents);
}; };
} }

@ -468,6 +468,23 @@ void TestReadingFusion()
VTKM_TEST_ASSERT(test_equal(zVecRange.Max, 0.480726)); VTKM_TEST_ASSERT(test_equal(zVecRange.Max, 0.480726));
} }
void TestSkppingStringFields(Format format)
{
std::string testFileName = (format == FORMAT_ASCII)
? vtkm::cont::testing::Testing::DataPath("uniform/simple_structured_points_strings_ascii.vtk")
: vtkm::cont::testing::Testing::DataPath("uniform/simple_structured_points_strings_bin.vtk");
vtkm::cont::DataSet ds = readVTKDataSet(testFileName);
VTKM_TEST_ASSERT(ds.GetNumberOfFields() == 1, "Incorrect number of fields");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 72, "Incorrect number of points");
VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 72,
"Incorrect number of points (from cell set)");
VTKM_TEST_ASSERT(ds.GetNumberOfCells() == 30, "Incorrect number of cells");
VTKM_TEST_ASSERT(ds.GetCellSet().IsType<vtkm::cont::CellSetStructured<3>>(),
"Incorrect cellset type");
}
void TestReadingVTKDataSet() void TestReadingVTKDataSet()
{ {
std::cout << "Test reading VTK Polydata file in ASCII" << std::endl; std::cout << "Test reading VTK Polydata file in ASCII" << std::endl;
@ -509,6 +526,11 @@ void TestReadingVTKDataSet()
TestReadingASCIIFishTank(); TestReadingASCIIFishTank();
std::cout << "Test reading fusion" << std::endl; std::cout << "Test reading fusion" << std::endl;
TestReadingFusion(); TestReadingFusion();
std::cout << "Test skipping string fields in ASCII files" << std::endl;
TestSkppingStringFields(FORMAT_ASCII);
std::cout << "Test skipping string fields in BINARY files" << std::endl;
TestSkppingStringFields(FORMAT_BINARY);
} }
int UnitTestVTKDataSetReader(int argc, char* argv[]) int UnitTestVTKDataSetReader(int argc, char* argv[])