/*=========================================================================
Program: Visualization Toolkit
Module: vtkXMLReader.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkXMLReader
* @brief Superclass for VTK's XML format readers.
*
* vtkXMLReader uses vtkXMLDataParser to parse a
* VTK XML input file.
* Concrete subclasses then traverse the parsed file structure and extract data.
*/
#ifndef vtkXMLReader_h
#define vtkXMLReader_h
#include "vtkAlgorithm.h"
#include "vtkIOXMLModule.h" // For export macro
#include // for std::string
class vtkAbstractArray;
class vtkCallbackCommand;
class vtkDataArraySelection;
class vtkDataSet;
class vtkDataSetAttributes;
class vtkXMLDataElement;
class vtkXMLDataParser;
class vtkInformationVector;
class vtkInformation;
class vtkCommand;
class VTKIOXML_EXPORT vtkXMLReader : public vtkAlgorithm
{
public:
vtkTypeMacro(vtkXMLReader, vtkAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
enum FieldType
{
POINT_DATA,
CELL_DATA,
OTHER
};
//@{
/**
* Get/Set the name of the input file.
*/
vtkSetStringMacro(FileName);
vtkGetStringMacro(FileName);
//@}
//@{
/**
* Enable reading from an InputString instead of the default, a file.
*/
vtkSetMacro(ReadFromInputString, vtkTypeBool);
vtkGetMacro(ReadFromInputString, vtkTypeBool);
vtkBooleanMacro(ReadFromInputString, vtkTypeBool);
void SetInputString(const std::string& s) { this->InputString = s; }
//@}
/**
* Test whether the file (type) with the given name can be read by this
* reader. If the file has a newer version than the reader, we still say
* we can read the file type and we fail later, when we try to read the file.
* This enables clients (ParaView) to distinguish between failures when we
* need to look for another reader and failures when we don't.
*/
virtual int CanReadFile(const char* name);
//@{
/**
* Get the output as a vtkDataSet pointer.
*/
vtkDataSet* GetOutputAsDataSet();
vtkDataSet* GetOutputAsDataSet(int index);
//@}
//@{
/**
* Get the data array selection tables used to configure which data
* arrays are loaded by the reader.
*/
vtkGetObjectMacro(PointDataArraySelection, vtkDataArraySelection);
vtkGetObjectMacro(CellDataArraySelection, vtkDataArraySelection);
vtkGetObjectMacro(ColumnArraySelection, vtkDataArraySelection);
//@}
//@{
/**
* Get the number of point, cell or column arrays available in the input.
*/
int GetNumberOfPointArrays();
int GetNumberOfCellArrays();
int GetNumberOfColumnArrays();
//@}
//@{
/**
* Get the name of the point, cell or column array with the given index in
* the input.
*/
const char* GetPointArrayName(int index);
const char* GetCellArrayName(int index);
const char* GetColumnArrayName(int index);
//@}
//@{
/**
* Get/Set whether the point, cell or column array with the given name is to
* be read.
*/
int GetPointArrayStatus(const char* name);
int GetCellArrayStatus(const char* name);
void SetPointArrayStatus(const char* name, int status);
void SetCellArrayStatus(const char* name, int status);
int GetColumnArrayStatus(const char* name);
void SetColumnArrayStatus(const char* name, int status);
//@}
// For the specified port, copy the information this reader sets up in
// SetupOutputInformation to outInfo
virtual void CopyOutputInformation(vtkInformation* vtkNotUsed(outInfo), int vtkNotUsed(port)) {}
//@{
/**
* Which TimeStep to read.
*/
vtkSetMacro(TimeStep, int);
vtkGetMacro(TimeStep, int);
//@}
vtkGetMacro(NumberOfTimeSteps, int);
//@{
/**
* Which TimeStepRange to read
*/
vtkGetVector2Macro(TimeStepRange, int);
vtkSetVector2Macro(TimeStepRange, int);
//@}
/**
* Returns the internal XML parser. This can be used to access
* the XML DOM after RequestInformation() was called.
*/
vtkXMLDataParser* GetXMLParser() { return this->XMLParser; }
vtkTypeBool ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
//@{
/**
* Set/get the ErrorObserver for the internal reader
* This is useful for applications that want to catch error messages.
*/
void SetReaderErrorObserver(vtkCommand*);
vtkGetObjectMacro(ReaderErrorObserver, vtkCommand);
//@}
//@{
/**
* Set/get the ErrorObserver for the internal xml parser
* This is useful for applications that want to catch error messages.
*/
void SetParserErrorObserver(vtkCommand*);
vtkGetObjectMacro(ParserErrorObserver, vtkCommand);
//@}
protected:
vtkXMLReader();
~vtkXMLReader() override;
// Pipeline execution methods to be defined by subclass. Called by
// corresponding RequestData methods after appropriate setup has been
// done.
virtual int ReadXMLInformation();
virtual void ReadXMLData();
// Get the name of the data set being read.
virtual const char* GetDataSetName() = 0;
// Test if the reader can read a file with the given version number.
virtual int CanReadFileVersion(int major, int minor);
// Setup the output with no data available. Used in error cases.
virtual void SetupEmptyOutput() = 0;
// Setup the output's information.
virtual void SetupOutputInformation(vtkInformation* vtkNotUsed(outInfo)) {}
// Setup the output's data with allocation.
virtual void SetupOutputData();
// Read the primary element from the file. This is the element
// whose name is the value returned by GetDataSetName().
virtual int ReadPrimaryElement(vtkXMLDataElement* ePrimary);
// Read the top-level element from the file. This is always the
// VTKFile element.
virtual int ReadVTKFile(vtkXMLDataElement* eVTKFile);
/**
* If the IdType argument is present in the provided XMLDataElement
* and the provided dataType has the same size with VTK_ID_TYPE on this build of VTK,
* returns VTK_ID_TYPE. Returns dataType in any other cases.
*/
int GetLocalDataType(vtkXMLDataElement* da, int datatype);
// Create a vtkAbstractArray from its cooresponding XML representation.
// Does not allocate.
vtkAbstractArray* CreateArray(vtkXMLDataElement* da);
// Create a vtkInformationKey from its corresponding XML representation.
// Stores it in the instance of vtkInformationProvided. Does not allocate.
int CreateInformationKey(vtkXMLDataElement* eInfoKey, vtkInformation* info);
// Populates the info object with the InformationKey children in infoRoot.
// Returns false if errors occur.
bool ReadInformation(vtkXMLDataElement* infoRoot, vtkInformation* info);
// Internal utility methods.
virtual int OpenStream();
virtual void CloseStream();
virtual int OpenVTKFile();
virtual void CloseVTKFile();
virtual int OpenVTKString();
virtual void CloseVTKString();
virtual void CreateXMLParser();
virtual void DestroyXMLParser();
void SetupCompressor(const char* type);
int CanReadFileVersionString(const char* version);
/**
* This method is used by CanReadFile() to check if the reader can read an XML
* with the primary element with the given name. Default implementation
* compares the name with the text returned by this->GetDataSetName().
*/
virtual int CanReadFileWithDataType(const char* dsname);
// Returns the major version for the file being read. -1 when invalid.
vtkGetMacro(FileMajorVersion, int);
// Returns the minor version for the file being read. -1 when invalid.
vtkGetMacro(FileMinorVersion, int);
// Utility methods for subclasses.
int IntersectExtents(int* extent1, int* extent2, int* result);
int Min(int a, int b);
int Max(int a, int b);
void ComputePointDimensions(int* extent, int* dimensions);
void ComputePointIncrements(int* extent, vtkIdType* increments);
void ComputeCellDimensions(int* extent, int* dimensions);
void ComputeCellIncrements(int* extent, vtkIdType* increments);
vtkIdType GetStartTuple(int* extent, vtkIdType* increments, int i, int j, int k);
void ReadAttributeIndices(vtkXMLDataElement* eDSA, vtkDataSetAttributes* dsa);
char** CreateStringArray(int numStrings);
void DestroyStringArray(int numStrings, char** strings);
// Read an Array values starting at the given index and up to numValues.
// This method assumes that the array is of correct size to
// accommodate all numValues values. arrayIndex is the value index at which the read
// values will be put in the array.
virtual int ReadArrayValues(vtkXMLDataElement* da, vtkIdType arrayIndex, vtkAbstractArray* array,
vtkIdType startIndex, vtkIdType numValues, FieldType type = OTHER);
// Setup the data array selections for the input's set of arrays.
void SetDataArraySelections(vtkXMLDataElement* eDSA, vtkDataArraySelection* sel);
int SetFieldDataInfo(vtkXMLDataElement* eDSA, int association, vtkIdType numTuples,
vtkInformationVector*(&infoVector));
// Check whether the given array element is an enabled array.
int PointDataArrayIsEnabled(vtkXMLDataElement* ePDA);
int CellDataArrayIsEnabled(vtkXMLDataElement* eCDA);
// Callback registered with the SelectionObserver.
static void SelectionModifiedCallback(
vtkObject* caller, unsigned long eid, void* clientdata, void* calldata);
// Give concrete classes an option to squeeze any output arrays
// at the end of RequestData.
virtual void SqueezeOutputArrays(vtkDataObject*) {}
// The vtkXMLDataParser instance used to hide XML reading details.
vtkXMLDataParser* XMLParser;
// The FieldData element representation.
vtkXMLDataElement* FieldDataElement;
// The input file's name.
char* FileName;
// The stream used to read the input.
istream* Stream;
// Whether this object is reading from a string or a file.
// Default is 0: read from file.
vtkTypeBool ReadFromInputString;
// The input string.
std::string InputString;
// The array selections.
vtkDataArraySelection* PointDataArraySelection;
vtkDataArraySelection* CellDataArraySelection;
vtkDataArraySelection* ColumnArraySelection;
// The observer to modify this object when the array selections are
// modified.
vtkCallbackCommand* SelectionObserver;
// Whether there was an error reading the file in RequestInformation.
int InformationError;
// Whether there was an error reading the file in RequestData.
int DataError;
// incrementally fine-tuned progress updates.
virtual void GetProgressRange(float* range);
virtual void SetProgressRange(const float range[2], int curStep, int numSteps);
virtual void SetProgressRange(const float range[2], int curStep, const float* fractions);
virtual void UpdateProgressDiscrete(float progress);
float ProgressRange[2];
virtual int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
virtual int RequestDataObject(vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector))
{
return 1;
}
virtual int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
vtkTimeStamp ReadMTime;
// Whether there was an error reading the XML.
int ReadError;
// For structured data keep track of dimensions empty of cells. For
// unstructured data these are always zero. This is used to support
// 1-D and 2-D cell data.
int AxesEmpty[3];
// The timestep currently being read.
int TimeStep;
int CurrentTimeStep;
int NumberOfTimeSteps;
void SetNumberOfTimeSteps(int num);
// buffer for reading timestep from the XML file the length is of
// NumberOfTimeSteps and therefore is always long enough
int* TimeSteps;
// Store the range of time steps
int TimeStepRange[2];
// Now we need to save what was the last time read for each kind of
// data to avoid rereading it that is to say we need a var for
// e.g. PointData/CellData/Points/Cells...
// See SubClass for details with member vars like PointsTimeStep/PointsOffset
// Helper function useful to know if a timestep is found in an array of timestep
static int IsTimeStepInArray(int timestep, int* timesteps, int length);
vtkDataObject* GetCurrentOutput();
vtkInformation* GetCurrentOutputInformation();
// Flag for whether DataProgressCallback should actually update
// progress.
int InReadData;
virtual void ConvertGhostLevelsToGhostType(FieldType, vtkAbstractArray*, vtkIdType, vtkIdType) {}
void ReadFieldData();
private:
// The stream used to read the input if it is in a file.
istream* FileStream;
// The stream used to read the input if it is in a string.
std::istringstream* StringStream;
int TimeStepWasReadOnce;
int FileMajorVersion;
int FileMinorVersion;
vtkDataObject* CurrentOutput;
vtkInformation* CurrentOutputInformation;
private:
vtkXMLReader(const vtkXMLReader&) = delete;
void operator=(const vtkXMLReader&) = delete;
vtkCommand* ReaderErrorObserver;
vtkCommand* ParserErrorObserver;
};
#endif