From 52d6255031aef9f8144eb56d322554a7652e6fae Mon Sep 17 00:00:00 2001 From: Zack Galbreath <zack.galbreath@kitware.com> Date: Fri, 21 Feb 2014 10:48:08 -0500 Subject: [PATCH] add option to write XML to string instead of file This commit enables vtkXMLWriter and its subclasses to write their output to a string instead of a file. Change-Id: Idff93039f9536379e3ef9abad6ea4ce18b4f2a60 --- .../Testing/Cxx/TestPhyloXMLTreeWriter.cxx | 22 ++- IO/XML/vtkXMLWriter.cxx | 133 ++++++++++++++---- IO/XML/vtkXMLWriter.h | 20 +++ 3 files changed, 146 insertions(+), 29 deletions(-) diff --git a/IO/Infovis/Testing/Cxx/TestPhyloXMLTreeWriter.cxx b/IO/Infovis/Testing/Cxx/TestPhyloXMLTreeWriter.cxx index cdbd9bbda2c..0f69af177db 100644 --- a/IO/Infovis/Testing/Cxx/TestPhyloXMLTreeWriter.cxx +++ b/IO/Infovis/Testing/Cxx/TestPhyloXMLTreeWriter.cxx @@ -54,7 +54,7 @@ int TestPhyloXMLTreeWriter(int argc, char* argv[]) char* baselineFile = vtkTestUtilities::GetArgOrEnvOrDefault("-V", argc, argv, "", ""); - // compare the baseline to the test file & return accordingly. + // compare the baseline file to the test file int result = EXIT_SUCCESS; if(vtksys::SystemTools::FilesDiffer(baselineFile, testFile.c_str())) { @@ -62,6 +62,26 @@ int TestPhyloXMLTreeWriter(int argc, char* argv[]) result = EXIT_FAILURE; } + // also test the "write to string" capabilities of this class + std::ifstream inFileStream; + inFileStream.open(baselineFile); + std::string baselineStr; + inFileStream.seekg(0, std::ios::end); + baselineStr.reserve(inFileStream.tellg()); + inFileStream.seekg(0, std::ios::beg); + baselineStr.assign((std::istreambuf_iterator<char>(inFileStream)), + std::istreambuf_iterator<char>()); + + writer->SetWriteToOutputString(1); + writer->Update(); + std::string testStr = writer->GetOutputString(); + + if (baselineStr.compare(testStr) != 0) + { + cout << "PhyloXML write to string did not yield expected results." << endl; + result = EXIT_FAILURE; + } + delete [] baselineFile; return result; } diff --git a/IO/XML/vtkXMLWriter.cxx b/IO/XML/vtkXMLWriter.cxx index 163520b82f1..0ec69ffad28 100644 --- a/IO/XML/vtkXMLWriter.cxx +++ b/IO/XML/vtkXMLWriter.cxx @@ -44,7 +44,6 @@ #include "vtkInformationStringKey.h" #include <vtksys/auto_ptr.hxx> -#include <vtksys/ios/sstream> #include <cassert> #include <string> @@ -293,6 +292,7 @@ vtkXMLWriter::vtkXMLWriter() { this->FileName = 0; this->Stream = 0; + this->WriteToOutputString = 0; // Default binary data mode is base-64 encoding. this->DataStream = vtkBase64OutputStream::New(); @@ -329,6 +329,7 @@ vtkXMLWriter::vtkXMLWriter() this->SetNumberOfInputPorts(1); this->OutFile = 0; + this->OutStringStream = 0; // Time support this->TimeStep = 0; // By default the file does not have timestep @@ -347,7 +348,16 @@ vtkXMLWriter::~vtkXMLWriter() this->SetFileName(0); this->DataStream->Delete(); this->SetCompressor(0); - delete this->OutFile; + if (this->OutFile) + { + delete this->OutFile; + this->OutFile = 0; + } + if (this->OutStringStream) + { + delete this->OutStringStream; + this->OutStringStream = 0; + } delete this->FieldDataOM; delete[] this->NumberOfTimeValues; @@ -670,10 +680,10 @@ int vtkXMLWriter::Write() return 1; } + //---------------------------------------------------------------------------- -int vtkXMLWriter::OpenFile() +int vtkXMLWriter::OpenStream() { - this->OutFile = 0; if(this->Stream) { // Rewind stream to the beginning. @@ -681,32 +691,20 @@ int vtkXMLWriter::OpenFile() } else { - // Strip trailing whitespace from the filename. - int len = static_cast<int>(strlen(this->FileName)); - for (int i = len-1; i >= 0; i--) + if (this->WriteToOutputString) { - if (isalnum(this->FileName[i])) + if (!this->OpenString()) { - break; + return 0; } - this->FileName[i] = 0; } - - // Try to open the output file for writing. -#ifdef _WIN32 - this->OutFile = new ofstream(this->FileName, ios::out | ios::binary); -#else - this->OutFile = new ofstream(this->FileName, ios::out); -#endif - if(!this->OutFile || !*this->OutFile) + else { - vtkErrorMacro("Error opening output file \"" << this->FileName << "\""); - this->SetErrorCode(vtkErrorCode::GetLastSystemError()); - vtkErrorMacro("Error code \"" - << vtkErrorCode::GetStringFromErrorCode(this->GetErrorCode()) << "\""); - return 0; + if (!this->OpenFile()) + { + return 0; + } } - this->Stream = this->OutFile; } // Make sure sufficient precision is used in the ascii @@ -720,24 +718,103 @@ int vtkXMLWriter::OpenFile() } //---------------------------------------------------------------------------- -void vtkXMLWriter::CloseFile() +int vtkXMLWriter::OpenFile() +{ + if (this->OutFile) + { + delete this->OutFile; + this->OutFile = 0; + } + + // Strip trailing whitespace from the filename. + int len = static_cast<int>(strlen(this->FileName)); + for (int i = len-1; i >= 0; i--) + { + if (isalnum(this->FileName[i])) + { + break; + } + this->FileName[i] = 0; + } + + // Try to open the output file for writing. +#ifdef _WIN32 + this->OutFile = new ofstream(this->FileName, ios::out | ios::binary); +#else + this->OutFile = new ofstream(this->FileName, ios::out); +#endif + if(!this->OutFile || !*this->OutFile) + { + vtkErrorMacro("Error opening output file \"" << this->FileName << "\""); + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + vtkErrorMacro("Error code \"" + << vtkErrorCode::GetStringFromErrorCode(this->GetErrorCode()) << "\""); + return 0; + } + this->Stream = this->OutFile; + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::OpenString() +{ + if (this->OutStringStream) + { + delete this->OutStringStream; + this->OutStringStream = 0; + } + + this->OutStringStream = new vtksys_ios::ostringstream(); + this->Stream = this->OutStringStream; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::CloseStream() { // Cleanup the output streams. this->DataStream->SetStream(0); + if (this->WriteToOutputString) + { + this->CloseString(); + } + else + { + this->CloseFile(); + } + + this->Stream = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::CloseFile() +{ if(this->OutFile) { // We opened a file. Close it. delete this->OutFile; this->OutFile = 0; - this->Stream = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::CloseString() +{ + if(this->OutStringStream) + { + this->OutputString = this->OutStringStream->str(); + delete this->OutStringStream; + this->OutStringStream = 0; } } //---------------------------------------------------------------------------- int vtkXMLWriter::WriteInternal() { - if (!this->OpenFile()) + if (!this->OpenStream()) { return 0; } @@ -750,7 +827,7 @@ int vtkXMLWriter::WriteInternal() // if user manipulate execution don't try closing file if( this->UserContinueExecuting != 1 ) { - this->CloseFile(); + this->CloseStream(); } return result; diff --git a/IO/XML/vtkXMLWriter.h b/IO/XML/vtkXMLWriter.h index 00c8fa9ef2f..f7b82f2ae90 100644 --- a/IO/XML/vtkXMLWriter.h +++ b/IO/XML/vtkXMLWriter.h @@ -24,6 +24,7 @@ #include "vtkIOXMLModule.h" // For export macro #include "vtkAlgorithm.h" +#include <vtksys/ios/sstream> // For ostringstream ivar class vtkAbstractArray; class vtkArrayIterator; @@ -111,6 +112,13 @@ public: vtkSetStringMacro(FileName); vtkGetStringMacro(FileName); + // Description: + // Enable writing to an OutputString instead of the default, a file. + vtkSetMacro(WriteToOutputString,int); + vtkGetMacro(WriteToOutputString,int); + vtkBooleanMacro(WriteToOutputString,int); + std::string GetOutputString() { return this->OutputString; } + // Description: // Get/Set the compressor used to compress binary and appended data // before writing to the file. Default is a vtkZLibDataCompressor. @@ -226,6 +234,13 @@ protected: // 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. + int WriteToOutputString; + + // The output string. + std::string OutputString; + // The output byte order. int ByteOrder; @@ -428,9 +443,14 @@ protected: float ProgressRange[2]; ofstream* OutFile; + vtksys_ios::ostringstream* OutStringStream; + int OpenStream(); int OpenFile(); + int OpenString(); + void CloseStream(); void CloseFile(); + void CloseString(); // The timestep currently being written int TimeStep; -- GitLab