/*========================================================================= Program: ParaView Module: vtkDelimitedTextWriter.cxx Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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. =========================================================================*/ /*------------------------------------------------------------------------- Copyright 2009 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. -------------------------------------------------------------------------*/ #include "vtkDelimitedTextWriter.h" #include "vtkAlgorithm.h" #include "vtkArrayIteratorIncludes.h" #include "vtkCellData.h" #include "vtkDataArray.h" #include "vtkErrorCode.h" #include "vtkInformation.h" #include "vtkObjectFactory.h" #include "vtkSmartPointer.h" #include "vtkTable.h" #include "vtksys/FStream.hxx" #include #include vtkStandardNewMacro(vtkDelimitedTextWriter); //------------------------------------------------------------------------------ vtkDelimitedTextWriter::vtkDelimitedTextWriter() { this->StringDelimiter = nullptr; this->FieldDelimiter = nullptr; this->UseStringDelimiter = true; this->SetStringDelimiter("\""); this->SetFieldDelimiter(","); this->Stream = nullptr; this->FileName = nullptr; this->WriteToOutputString = false; this->OutputString = nullptr; } //------------------------------------------------------------------------------ vtkDelimitedTextWriter::~vtkDelimitedTextWriter() { this->SetStringDelimiter(nullptr); this->SetFieldDelimiter(nullptr); this->SetFileName(nullptr); delete this->Stream; delete[] this->OutputString; } //------------------------------------------------------------------------------ int vtkDelimitedTextWriter::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable"); return 1; } //------------------------------------------------------------------------------ bool vtkDelimitedTextWriter::OpenStream() { if (this->WriteToOutputString) { this->Stream = new std::ostringstream; } else { if (!this->FileName) { vtkErrorMacro(<< "No FileName specified! Can't write!"); this->SetErrorCode(vtkErrorCode::NoFileNameError); return false; } vtkDebugMacro(<< "Opening file for writing..."); vtksys::ofstream* fptr = new vtksys::ofstream(this->FileName, ios::out); if (fptr->fail()) { vtkErrorMacro(<< "Unable to open file: " << this->FileName); this->SetErrorCode(vtkErrorCode::CannotOpenFileError); delete fptr; return false; } this->Stream = fptr; } return true; } //------------------------------------------------------------------------------ template void vtkDelimitedTextWriterGetDataString( iterT* iter, vtkIdType tupleIndex, ostream* stream, vtkDelimitedTextWriter* writer, bool* first) { int numComps = iter->GetNumberOfComponents(); vtkIdType index = tupleIndex * numComps; for (int cc = 0; cc < numComps; cc++) { if ((index + cc) < iter->GetNumberOfValues()) { if (!*first) { (*stream) << writer->GetFieldDelimiter(); } *first = false; (*stream) << iter->GetValue(index + cc); } else { if (!*first) { (*stream) << writer->GetFieldDelimiter(); } *first = false; } } } //------------------------------------------------------------------------------ template <> void vtkDelimitedTextWriterGetDataString(vtkArrayIteratorTemplate* iter, vtkIdType tupleIndex, ostream* stream, vtkDelimitedTextWriter* writer, bool* first) { int numComps = iter->GetNumberOfComponents(); vtkIdType index = tupleIndex * numComps; for (int cc = 0; cc < numComps; cc++) { if ((index + cc) < iter->GetNumberOfValues()) { if (!*first) { (*stream) << writer->GetFieldDelimiter(); } *first = false; (*stream) << writer->GetString(iter->GetValue(index + cc)); } else { if (!*first) { (*stream) << writer->GetFieldDelimiter(); } *first = false; } } } //------------------------------------------------------------------------------ vtkStdString vtkDelimitedTextWriter::GetString(vtkStdString string) { if (this->UseStringDelimiter && this->StringDelimiter) { vtkStdString temp = this->StringDelimiter; temp += string + this->StringDelimiter; return temp; } return string; } //------------------------------------------------------------------------------ void vtkDelimitedTextWriter::WriteData() { vtkTable* rg = vtkTable::SafeDownCast(this->GetInput()); if (rg) { this->WriteTable(rg); } else { vtkErrorMacro(<< "CSVWriter can only write vtkTable."); } } //------------------------------------------------------------------------------ void vtkDelimitedTextWriter::WriteTable(vtkTable* table) { vtkIdType numRows = table->GetNumberOfRows(); vtkDataSetAttributes* dsa = table->GetRowData(); if (!this->OpenStream()) { return; } std::vector> columnsIters; int cc; int numArrays = dsa->GetNumberOfArrays(); bool first = true; // Write headers: for (cc = 0; cc < numArrays; cc++) { vtkAbstractArray* array = dsa->GetAbstractArray(cc); for (int comp = 0; comp < array->GetNumberOfComponents(); comp++) { if (!first) { (*this->Stream) << this->FieldDelimiter; } first = false; std::ostringstream array_name; array_name << array->GetName(); if (array->GetNumberOfComponents() > 1) { array_name << ":" << comp; } (*this->Stream) << this->GetString(array_name.str()); } vtkArrayIterator* iter = array->NewIterator(); columnsIters.emplace_back(iter); iter->Delete(); } (*this->Stream) << "\n"; for (vtkIdType index = 0; index < numRows; index++) { first = true; std::vector>::iterator iter; for (iter = columnsIters.begin(); iter != columnsIters.end(); ++iter) { switch ((*iter)->GetDataType()) { vtkArrayIteratorTemplateMacro(vtkDelimitedTextWriterGetDataString( static_cast(iter->GetPointer()), index, this->Stream, this, &first)); case VTK_VARIANT: { vtkDelimitedTextWriterGetDataString( static_cast*>(iter->GetPointer()), index, this->Stream, this, &first); break; } } } (*this->Stream) << "\n"; } if (this->WriteToOutputString) { std::ostringstream* ostr = static_cast(this->Stream); delete[] this->OutputString; size_t strLen = ostr->str().size(); this->OutputString = new char[strLen + 1]; memcpy(this->OutputString, ostr->str().c_str(), strLen + 1); } delete this->Stream; this->Stream = nullptr; } //------------------------------------------------------------------------------ char* vtkDelimitedTextWriter::RegisterAndGetOutputString() { char* tmp = this->OutputString; this->OutputString = nullptr; return tmp; } //------------------------------------------------------------------------------ void vtkDelimitedTextWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "FieldDelimiter: " << (this->FieldDelimiter ? this->FieldDelimiter : "(none)") << endl; os << indent << "StringDelimiter: " << (this->StringDelimiter ? this->StringDelimiter : "(none)") << endl; os << indent << "UseStringDelimiter: " << this->UseStringDelimiter << endl; os << indent << "FileName: " << (this->FileName ? this->FileName : "none") << endl; os << indent << "WriteToOutputString: " << this->WriteToOutputString << endl; }