1 /*=========================================================================
2 
3   Program:   ParaView
4   Module:    vtkDelimitedTextWriter.cxx
5 
6   Copyright (c) Kitware, Inc.
7   All rights reserved.
8   See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16   Copyright 2009 Sandia Corporation.
17   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18   the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20 
21 #include "vtkDelimitedTextWriter.h"
22 
23 #include "vtkAlgorithm.h"
24 #include "vtkArrayIteratorIncludes.h"
25 #include "vtkCellData.h"
26 #include "vtkDataArray.h"
27 #include "vtkErrorCode.h"
28 #include "vtkInformation.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkTable.h"
31 #include "vtkSmartPointer.h"
32 
33 #include <vector>
34 #include <vtksys/ios/sstream>
35 
36 vtkStandardNewMacro(vtkDelimitedTextWriter);
37 //-----------------------------------------------------------------------------
vtkDelimitedTextWriter()38 vtkDelimitedTextWriter::vtkDelimitedTextWriter()
39 {
40   this->StringDelimiter = 0;
41   this->FieldDelimiter = 0;
42   this->UseStringDelimiter = true;
43   this->SetStringDelimiter("\"");
44   this->SetFieldDelimiter(",");
45   this->Stream = 0;
46   this->FileName = 0;
47   this->WriteToOutputString = false;
48   this->OutputString = 0;
49 }
50 
51 //-----------------------------------------------------------------------------
~vtkDelimitedTextWriter()52 vtkDelimitedTextWriter::~vtkDelimitedTextWriter()
53 {
54   this->SetStringDelimiter(0);
55   this->SetFieldDelimiter(0);
56   this->SetFileName(0);
57   delete this->Stream;
58   delete[] this->OutputString;
59 }
60 
61 //-----------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)62 int vtkDelimitedTextWriter::FillInputPortInformation(
63   int vtkNotUsed(port), vtkInformation* info)
64 {
65   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
66   return 1;
67 }
68 
69 //-----------------------------------------------------------------------------
OpenStream()70 bool vtkDelimitedTextWriter::OpenStream()
71 {
72   if (this->WriteToOutputString)
73     {
74     this->Stream = new vtksys_ios::ostringstream;
75     }
76   else
77     {
78     if ( !this->FileName )
79       {
80       vtkErrorMacro(<< "No FileName specified! Can't write!");
81       this->SetErrorCode(vtkErrorCode::NoFileNameError);
82       return false;
83       }
84 
85     vtkDebugMacro(<<"Opening file for writing...");
86 
87     ofstream *fptr = new ofstream(this->FileName, ios::out);
88 
89     if (fptr->fail())
90       {
91       vtkErrorMacro(<< "Unable to open file: "<< this->FileName);
92       this->SetErrorCode(vtkErrorCode::CannotOpenFileError);
93       delete fptr;
94       return false;
95       }
96 
97     this->Stream = fptr;
98     }
99 
100   return true;
101 }
102 
103 //-----------------------------------------------------------------------------
104 template <class iterT>
vtkDelimitedTextWriterGetDataString(iterT * iter,vtkIdType tupleIndex,ostream * stream,vtkDelimitedTextWriter * writer,bool * first)105 void vtkDelimitedTextWriterGetDataString(
106   iterT* iter, vtkIdType tupleIndex, ostream* stream, vtkDelimitedTextWriter* writer,
107   bool* first)
108 {
109   int numComps = iter->GetNumberOfComponents();
110   vtkIdType index = tupleIndex* numComps;
111   for (int cc=0; cc < numComps; cc++)
112     {
113     if ((index+cc) < iter->GetNumberOfValues())
114       {
115       if (*first == false)
116         {
117         (*stream) << writer->GetFieldDelimiter();
118         }
119       *first = false;
120       (*stream) << iter->GetValue(index+cc);
121       }
122     else
123       {
124       if (*first == false)
125         {
126         (*stream) << writer->GetFieldDelimiter();
127         }
128       *first = false;
129       }
130     }
131 }
132 
133 //-----------------------------------------------------------------------------
134 VTK_TEMPLATE_SPECIALIZE
vtkDelimitedTextWriterGetDataString(vtkArrayIteratorTemplate<vtkStdString> * iter,vtkIdType tupleIndex,ostream * stream,vtkDelimitedTextWriter * writer,bool * first)135 void vtkDelimitedTextWriterGetDataString(
136   vtkArrayIteratorTemplate<vtkStdString>* iter, vtkIdType tupleIndex,
137   ostream* stream, vtkDelimitedTextWriter* writer, bool* first)
138 {
139   int numComps = iter->GetNumberOfComponents();
140   vtkIdType index = tupleIndex* numComps;
141   for (int cc=0; cc < numComps; cc++)
142     {
143     if ((index+cc) < iter->GetNumberOfValues())
144       {
145       if (*first == false)
146         {
147         (*stream) << writer->GetFieldDelimiter();
148         }
149       *first = false;
150       (*stream) << writer->GetString(iter->GetValue(index+cc));
151       }
152     else
153       {
154       if (*first == false)
155         {
156         (*stream) << writer->GetFieldDelimiter();
157         }
158       *first = false;
159       }
160     }
161 }
162 
163 //-----------------------------------------------------------------------------
GetString(vtkStdString string)164 vtkStdString vtkDelimitedTextWriter::GetString(vtkStdString string)
165 {
166   if (this->UseStringDelimiter && this->StringDelimiter)
167     {
168     vtkStdString temp = this->StringDelimiter;
169     temp += string + this->StringDelimiter;
170     return temp;
171     }
172   return string;
173 }
174 
175 //-----------------------------------------------------------------------------
WriteData()176 void vtkDelimitedTextWriter::WriteData()
177 {
178   vtkTable* rg = vtkTable::SafeDownCast(this->GetInput());
179   if (rg)
180     {
181     this->WriteTable(rg);
182     }
183   else
184     {
185     vtkErrorMacro(<< "CSVWriter can only write vtkTable.");
186     }
187 }
188 
189 //-----------------------------------------------------------------------------
WriteTable(vtkTable * table)190 void vtkDelimitedTextWriter::WriteTable(vtkTable* table)
191 {
192   vtkIdType numRows = table->GetNumberOfRows();
193   vtkDataSetAttributes* dsa = table->GetRowData();
194   if (!this->OpenStream())
195     {
196     return;
197     }
198 
199   std::vector<vtkSmartPointer<vtkArrayIterator> > columnsIters;
200 
201   int cc;
202   int numArrays = dsa->GetNumberOfArrays();
203   bool first = true;
204   // Write headers:
205   for (cc=0; cc < numArrays; cc++)
206     {
207     vtkAbstractArray* array = dsa->GetAbstractArray(cc);
208     for (int comp=0; comp < array->GetNumberOfComponents(); comp++)
209       {
210       if (!first)
211         {
212         (*this->Stream) << this->FieldDelimiter;
213         }
214       first = false;
215 
216       vtksys_ios::ostringstream array_name;
217       array_name << array->GetName();
218       if (array->GetNumberOfComponents() > 1)
219         {
220         array_name << ":" << comp;
221         }
222       (*this->Stream) << this->GetString(array_name.str());
223       }
224     vtkArrayIterator* iter = array->NewIterator();
225     columnsIters.push_back(iter);
226     iter->Delete();
227     }
228   (*this->Stream) << "\n";
229 
230   for (vtkIdType index=0; index < numRows; index++)
231     {
232     first = true;
233     std::vector<vtkSmartPointer<vtkArrayIterator> >::iterator iter;
234     for (iter = columnsIters.begin(); iter != columnsIters.end(); ++iter)
235       {
236       switch ((*iter)->GetDataType())
237         {
238         vtkArrayIteratorTemplateMacro(
239           vtkDelimitedTextWriterGetDataString(static_cast<VTK_TT*>(iter->GetPointer()),
240             index, this->Stream, this, &first));
241         case VTK_VARIANT:
242           {
243           vtkDelimitedTextWriterGetDataString(static_cast<vtkArrayIteratorTemplate<vtkVariant>*>(iter->GetPointer()),
244             index, this->Stream, this, &first);
245           break;
246           }
247         }
248       }
249     (*this->Stream) << "\n";
250     }
251 
252   if (this->WriteToOutputString)
253     {
254     vtksys_ios::ostringstream *ostr =
255       static_cast<vtksys_ios::ostringstream*>(this->Stream);
256 
257     delete [] this->OutputString;
258     size_t strLen = ostr->str().size();
259     this->OutputString = new char[strLen+1];
260     memcpy(this->OutputString, ostr->str().c_str(), strLen+1);
261     }
262   delete this->Stream;
263   this->Stream = 0;
264 }
265 
266 //-----------------------------------------------------------------------------
RegisterAndGetOutputString()267 char *vtkDelimitedTextWriter::RegisterAndGetOutputString()
268 {
269   char *tmp = this->OutputString;
270   this->OutputString = NULL;
271 
272   return tmp;
273 }
274 
275 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)276 void vtkDelimitedTextWriter::PrintSelf(ostream& os, vtkIndent indent)
277 {
278   this->Superclass::PrintSelf(os, indent);
279   os << indent << "FieldDelimiter: " << (this->FieldDelimiter ?
280     this->FieldDelimiter : "(none)") << endl;
281   os << indent << "StringDelimiter: " << (this->StringDelimiter ?
282     this->StringDelimiter : "(none)") << endl;
283   os << indent << "UseStringDelimiter: " << this->UseStringDelimiter << endl;
284   os << indent << "FileName: " << (this->FileName? this->FileName : "none")
285     << endl;
286   os << indent << "WriteToOutputString: " << this->WriteToOutputString << endl;
287 }
288