/*========================================================================= Program: Visualization Toolkit Module: vtkXMLWriter.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 vtkXMLWriter * @brief Superclass for VTK's XML file writers. * * vtkXMLWriter provides methods implementing most of the * functionality needed to write VTK XML file formats. Concrete * subclasses provide actual writer implementations calling upon this * functionality. * * @par Thanks * CompressionLevel getters/setters exposed by Quincy Wofford * (qwofford@lanl.gov) and John Patchett (patchett@lanl.gov), * Los Alamos National Laboratory (2017) */ #ifndef vtkXMLWriter_h #define vtkXMLWriter_h #include "vtkAlgorithm.h" #include "vtkIOXMLModule.h" // For export macro #include // For ostringstream ivar class vtkAbstractArray; class vtkArrayIterator; template class vtkArrayIteratorTemplate; class vtkCellData; class vtkDataArray; class vtkDataCompressor; class vtkDataSet; class vtkDataSetAttributes; class vtkFieldData; class vtkOutputStream; class vtkPointData; class vtkPoints; class vtkFieldData; class vtkXMLDataHeader; class vtkStdString; class OffsetsManager; // one per piece/per time class OffsetsManagerGroup; // array of OffsetsManager class OffsetsManagerArray; // array of OffsetsManagerGroup class VTKIOXML_EXPORT vtkXMLWriter : public vtkAlgorithm { public: vtkTypeMacro(vtkXMLWriter, vtkAlgorithm); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Enumerate big and little endian byte order settings. */ enum { BigEndian, LittleEndian }; /** * Enumerate the supported data modes. * Ascii = Inline ascii data. * Binary = Inline binary data (base64 encoded, possibly compressed). * Appended = Appended binary data (possibly compressed and/or base64). */ enum { Ascii, Binary, Appended }; /** * Enumerate the supported vtkIdType bit lengths. * Int32 = File stores 32-bit values for vtkIdType. * Int64 = File stores 64-bit values for vtkIdType. */ enum { Int32 = 32, Int64 = 64 }; /** * Enumerate the supported binary data header bit lengths. * UInt32 = File stores 32-bit binary data header elements. * UInt64 = File stores 64-bit binary data header elements. */ enum { UInt32 = 32, UInt64 = 64 }; //@{ /** * Get/Set the byte order of data written to the file. The default * is the machine's hardware byte order. */ vtkSetMacro(ByteOrder, int); vtkGetMacro(ByteOrder, int); void SetByteOrderToBigEndian(); void SetByteOrderToLittleEndian(); //@} //@{ /** * Get/Set the binary data header word type. The default is UInt32. * Set to UInt64 when storing arrays requiring 64-bit indexing. */ virtual void SetHeaderType(int); vtkGetMacro(HeaderType, int); void SetHeaderTypeToUInt32(); void SetHeaderTypeToUInt64(); //@} //@{ /** * Get/Set the size of the vtkIdType values stored in the file. The * default is the real size of vtkIdType. */ virtual void SetIdType(int); vtkGetMacro(IdType, int); void SetIdTypeToInt32(); void SetIdTypeToInt64(); //@} //@{ /** * Get/Set the name of the output file. */ vtkSetStringMacro(FileName); vtkGetStringMacro(FileName); //@} //@{ /** * Enable writing to an OutputString instead of the default, a file. */ vtkSetMacro(WriteToOutputString, vtkTypeBool); vtkGetMacro(WriteToOutputString, vtkTypeBool); vtkBooleanMacro(WriteToOutputString, vtkTypeBool); std::string GetOutputString() { return this->OutputString; } //@} //@{ /** * Get/Set the compressor used to compress binary and appended data * before writing to the file. Default is a vtkZLibDataCompressor. */ virtual void SetCompressor(vtkDataCompressor*); vtkGetObjectMacro(Compressor, vtkDataCompressor); //@} enum CompressorType { NONE, ZLIB, LZ4, LZMA }; //@{ /** * Convenience functions to set the compressor to certain known types. */ void SetCompressorType(int compressorType); void SetCompressorTypeToNone() { this->SetCompressorType(NONE); } void SetCompressorTypeToLZ4() { this->SetCompressorType(LZ4); } void SetCompressorTypeToZLib() { this->SetCompressorType(ZLIB); } void SetCompressorTypeToLZMA() { this->SetCompressorType(LZMA); } void SetCompressionLevel(int compressorLevel); vtkGetMacro(CompressionLevel, int); //@} //@{ /** * Get/Set the block size used in compression. When reading, this * controls the granularity of how much extra information must be * read when only part of the data are requested. The value should * be a multiple of the largest scalar data type. */ virtual void SetBlockSize(size_t blockSize); vtkGetMacro(BlockSize, size_t); //@} //@{ /** * Get/Set the data mode used for the file's data. The options are * vtkXMLWriter::Ascii, vtkXMLWriter::Binary, and * vtkXMLWriter::Appended. */ vtkSetMacro(DataMode, int); vtkGetMacro(DataMode, int); void SetDataModeToAscii(); void SetDataModeToBinary(); void SetDataModeToAppended(); //@} //@{ /** * Get/Set whether the appended data section is base64 encoded. If * encoded, reading and writing will be slower, but the file will be * fully valid XML and text-only. If not encoded, the XML * specification will be violated, but reading and writing will be * fast. The default is to do the encoding. */ vtkSetMacro(EncodeAppendedData, vtkTypeBool); vtkGetMacro(EncodeAppendedData, vtkTypeBool); vtkBooleanMacro(EncodeAppendedData, vtkTypeBool); //@} //@{ /** * Assign a data object as input. Note that this method does not * establish a pipeline connection. Use SetInputConnection() to * setup a pipeline connection. */ void SetInputData(vtkDataObject*); void SetInputData(int, vtkDataObject*); vtkDataObject* GetInput(int port); vtkDataObject* GetInput() { return this->GetInput(0); } //@} /** * Get the default file extension for files written by this writer. */ virtual const char* GetDefaultFileExtension() = 0; /** * Invoke the writer. Returns 1 for success, 0 for failure. */ int Write(); // See the vtkAlgorithm for a description of what these do vtkTypeBool ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) override; //@{ /** * Set the number of time steps */ vtkGetMacro(NumberOfTimeSteps, int); vtkSetMacro(NumberOfTimeSteps, int); //@} //@{ /** * API to interface an outside the VTK pipeline control */ void Start(); void Stop(); void WriteNextTime(double time); //@} protected: vtkXMLWriter(); ~vtkXMLWriter() override; virtual int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector); virtual int RequestData(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector); // The name of the output file. char* FileName; // The output stream to which the XML is written. ostream* Stream; // Whether this object is writing to a string or a file. // Default is 0: write to file. vtkTypeBool WriteToOutputString; // The output string. std::string OutputString; // The output byte order. int ByteOrder; // The output binary header word type. int HeaderType; // The output vtkIdType. int IdType; // The form of binary data to write. Used by subclasses to choose // how to write data. int DataMode; // Whether to base64-encode the appended data section. vtkTypeBool EncodeAppendedData; // The stream position at which appended data starts. vtkTypeInt64 AppendedDataPosition; // appended data offsets for field data OffsetsManagerGroup* FieldDataOM; // one per array // We need a 32 bit signed integer type to which vtkIdType will be // converted if Int32 is specified for the IdType parameter to this // writer. #if VTK_SIZEOF_SHORT == 4 typedef short Int32IdType; #elif VTK_SIZEOF_INT == 4 typedef int Int32IdType; #elif VTK_SIZEOF_LONG == 4 typedef long Int32IdType; #else #error "No native data type can represent a signed 32-bit integer." #endif // Buffer for vtkIdType conversion. Int32IdType* Int32IdTypeBuffer; // The byte swapping buffer. unsigned char* ByteSwapBuffer; // Compression information. vtkDataCompressor* Compressor; size_t BlockSize; size_t CompressionBlockNumber; vtkXMLDataHeader* CompressionHeader; vtkTypeInt64 CompressionHeaderPosition; // Compression Level for vtkDataCompressor objects // 1 (worst compression, fastest) ... 9 (best compression, slowest) int CompressionLevel = 5; // The output stream used to write binary and appended data. May // transparently encode the data. vtkOutputStream* DataStream; // Allow subclasses to set the data stream. virtual void SetDataStream(vtkOutputStream*); vtkGetObjectMacro(DataStream, vtkOutputStream); // Method to drive most of actual writing. virtual int WriteInternal(); // Method defined by subclasses to write data. Return 1 for // success, 0 for failure. virtual int WriteData() { return 1; } // Method defined by subclasses to specify the data set's type name. virtual const char* GetDataSetName() = 0; // Methods to define the file's major and minor version numbers. virtual int GetDataSetMajorVersion(); virtual int GetDataSetMinorVersion(); // Utility methods for subclasses. vtkDataSet* GetInputAsDataSet(); virtual int StartFile(); virtual void WriteFileAttributes(); virtual int EndFile(); void DeleteAFile(); void DeleteAFile(const char* name); virtual int WritePrimaryElement(ostream& os, vtkIndent indent); virtual void WritePrimaryElementAttributes(ostream& os, vtkIndent indent); void StartAppendedData(); void EndAppendedData(); // Write enough space to go back and write the given attribute with // at most "length" characters in the value. Returns the stream // position at which attribute should be later written. The default // length of 20 is enough for a 64-bit integer written in decimal or // a double-precision floating point value written to 13 digits of // precision (the other 7 come from a minus sign, decimal place, and // a big exponent like "e+300"). vtkTypeInt64 ReserveAttributeSpace(const char* attr, size_t length = 20); vtkTypeInt64 GetAppendedDataOffset(); void WriteAppendedDataOffset( vtkTypeInt64 streamPos, vtkTypeInt64& lastoffset, const char* attr = nullptr); void ForwardAppendedDataOffset( vtkTypeInt64 streamPos, vtkTypeInt64 offset, const char* attr = nullptr); void ForwardAppendedDataDouble(vtkTypeInt64 streamPos, double value, const char* attr); int WriteScalarAttribute(const char* name, int data); int WriteScalarAttribute(const char* name, float data); int WriteScalarAttribute(const char* name, double data); #ifdef VTK_USE_64BIT_IDS int WriteScalarAttribute(const char* name, vtkIdType data); #endif int WriteVectorAttribute(const char* name, int length, int* data); int WriteVectorAttribute(const char* name, int length, float* data); int WriteVectorAttribute(const char* name, int length, double* data); #ifdef VTK_USE_64BIT_IDS int WriteVectorAttribute(const char* name, int length, vtkIdType* data); #endif int WriteDataModeAttribute(const char* name); int WriteWordTypeAttribute(const char* name, int dataType); int WriteStringAttribute(const char* name, const char* value); // Returns true if any keys were written. bool WriteInformation(vtkInformation* info, vtkIndent indent); void WriteArrayHeader(vtkAbstractArray* a, vtkIndent indent, const char* alternateName, int writeNumTuples, int timestep); virtual void WriteArrayFooter( ostream& os, vtkIndent indent, vtkAbstractArray* a, int shortFormat); virtual void WriteArrayInline(vtkAbstractArray* a, vtkIndent indent, const char* alternateName = nullptr, int writeNumTuples = 0); virtual void WriteInlineData(vtkAbstractArray* a, vtkIndent indent); void WriteArrayAppended(vtkAbstractArray* a, vtkIndent indent, OffsetsManager& offs, const char* alternateName = nullptr, int writeNumTuples = 0, int timestep = 0); int WriteAsciiData(vtkAbstractArray* a, vtkIndent indent); int WriteBinaryData(vtkAbstractArray* a); int WriteBinaryDataInternal(vtkAbstractArray* a); void WriteArrayAppendedData(vtkAbstractArray* a, vtkTypeInt64 pos, vtkTypeInt64& lastoffset); // Methods for writing points, point data, and cell data. void WriteFieldData(vtkIndent indent); void WriteFieldDataInline(vtkFieldData* fd, vtkIndent indent); void WritePointDataInline(vtkPointData* pd, vtkIndent indent); void WriteCellDataInline(vtkCellData* cd, vtkIndent indent); void WriteFieldDataAppended(vtkFieldData* fd, vtkIndent indent, OffsetsManagerGroup* fdManager); void WriteFieldDataAppendedData(vtkFieldData* fd, int timestep, OffsetsManagerGroup* fdManager); void WritePointDataAppended(vtkPointData* pd, vtkIndent indent, OffsetsManagerGroup* pdManager); void WritePointDataAppendedData(vtkPointData* pd, int timestep, OffsetsManagerGroup* pdManager); void WriteCellDataAppended(vtkCellData* cd, vtkIndent indent, OffsetsManagerGroup* cdManager); void WriteCellDataAppendedData(vtkCellData* cd, int timestep, OffsetsManagerGroup* cdManager); void WriteAttributeIndices(vtkDataSetAttributes* dsa, char** names); void WritePointsAppended(vtkPoints* points, vtkIndent indent, OffsetsManager* manager); void WritePointsAppendedData(vtkPoints* points, int timestep, OffsetsManager* pdManager); void WritePointsInline(vtkPoints* points, vtkIndent indent); void WriteCoordinatesInline( vtkDataArray* xc, vtkDataArray* yc, vtkDataArray* zc, vtkIndent indent); void WriteCoordinatesAppended(vtkDataArray* xc, vtkDataArray* yc, vtkDataArray* zc, vtkIndent indent, OffsetsManagerGroup* coordManager); void WriteCoordinatesAppendedData(vtkDataArray* xc, vtkDataArray* yc, vtkDataArray* zc, int timestep, OffsetsManagerGroup* coordManager); void WritePPointData(vtkPointData* pd, vtkIndent indent); void WritePCellData(vtkCellData* cd, vtkIndent indent); void WritePPoints(vtkPoints* points, vtkIndent indent); void WritePArray(vtkAbstractArray* a, vtkIndent indent, const char* alternateName = nullptr); void WritePCoordinates(vtkDataArray* xc, vtkDataArray* yc, vtkDataArray* zc, vtkIndent indent); // Internal utility methods. int WriteBinaryDataBlock(unsigned char* in_data, size_t numWords, int wordType); void PerformByteSwap(void* data, size_t numWords, size_t wordSize); int CreateCompressionHeader(size_t size); int WriteCompressionBlock(unsigned char* data, size_t size); int WriteCompressionHeader(); size_t GetWordTypeSize(int dataType); const char* GetWordTypeName(int dataType); size_t GetOutputWordTypeSize(int dataType); char** CreateStringArray(int numStrings); void DestroyStringArray(int numStrings, char** strings); // The current range over which progress is moving. This allows for // incrementally fine-tuned progress updates. virtual void GetProgressRange(float range[2]); 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 SetProgressPartial(float fraction); virtual void UpdateProgressDiscrete(float progress); float ProgressRange[2]; // This shallows copy input field data to the passed field data and // then adds any additional field arrays. For example, TimeValue. void UpdateFieldData(vtkFieldData*); ostream* OutFile; std::ostringstream* OutStringStream; int OpenStream(); int OpenFile(); int OpenString(); void CloseStream(); void CloseFile(); void CloseString(); // The timestep currently being written int CurrentTimeIndex; int NumberOfTimeSteps; // Dummy boolean var to start/stop the continue executing: // when using the Start/Stop/WriteNextTime API int UserContinueExecuting; // can only be -1 = invalid, 0 = stop, 1 = start // This variable is used to ease transition to new versions of VTK XML files. // If data that needs to be written satisfies certain conditions, // the writer can use the previous file version version. // For version change 0.1 -> 2.0 (UInt32 header) and 1.0 -> 2.0 // (UInt64 header), if data does not have a vtkGhostType array, // the file is written with version: 0.1/1.0. bool UsePreviousVersion; vtkTypeInt64* NumberOfTimeValues; // one per piece / per timestep friend class vtkXMLWriterHelper; private: vtkXMLWriter(const vtkXMLWriter&) = delete; void operator=(const vtkXMLWriter&) = delete; }; #endif