Salome HOME
Merge from BR_PORTING_VTK6 01/03/2013
[modules/paravis.git] / src / Plugins / TableReader / Reader / TableParser.cxx
1 // Copyright (C) 2010-2012  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "TableParser.h"
21
22 #include <QString>
23 #include <QStringList>
24
25 // STL includes
26 #include <fstream>
27 #include <sstream>
28 #include <stdexcept>
29
30 using namespace std;
31
32 int getLine(std::ifstream& streamIn, QString& str)
33 {
34   char tmp;
35   std::ostringstream streamOut;
36   
37   while (streamIn.get(tmp)) {
38     streamOut<<tmp;
39     if (tmp == '\n') 
40       break;
41   }
42   
43   streamOut<<std::ends;
44   str = streamOut.str().c_str();
45   
46   return !streamIn.eof();
47 }
48
49
50 bool Table2D::Check()
51 {
52   if (myRows.empty()) 
53     return false;
54
55   int iEnd = myRows[0].myValues.size();
56   if (iEnd == 0)
57     {
58       return false;
59     }
60
61   if (myColumnTitles.size() != iEnd) 
62     {
63       myColumnTitles.resize(iEnd);
64     }
65
66   if (myColumnUnits.size() != iEnd)
67     {
68       myColumnUnits.resize(iEnd);
69     }
70
71   int jEnd = myRows.size();
72   for (int j = 0; j < jEnd; j++)
73     {
74       if (myRows[j].myValues.size() != iEnd)
75         {
76           return false;
77         }
78     }
79   
80   return true;
81 }
82
83 std::vector<std::string> GetTableNames(const char* fname, const char* separator,
84                                        const bool firstStringAsTitles)
85 {
86   Table2D table;
87   std::vector<std::string> tableTitles;
88
89   int nb = 0;
90   table = GetTable(fname, separator, nb, firstStringAsTitles);
91   while (table.Check()) {
92     tableTitles.push_back(table.myTitle);
93     table = GetTable(fname, separator, ++nb, firstStringAsTitles);
94   }
95   
96   return tableTitles;
97 }
98
99 Table2D GetTable(const char* fname, const char* separator, const int tableNb,
100                  const bool firstStringAsTitles)
101 {
102   std::ifstream streamIn(fname);
103   
104   if(!streamIn.good())
105     {
106       throw std::runtime_error("Unable to open input Post-Pro table file.");
107     }
108   
109   QString tmp;
110   int count = 0;
111   do {
112     // Find beginning of table (tables are separated by empty lines)
113     while (getLine(streamIn, tmp) && tmp.trimmed() == "");
114
115     Table2D table2D;
116
117     bool isFirst = true;
118     while (!streamIn.eof() && tmp.trimmed() != "") 
119       {
120         QString data = tmp.trimmed();
121         QString cmt = "";
122         QString keyword = "";
123
124         // Split string to data and comment (comment starts from '#' symbol)
125         int index = tmp.indexOf("#");
126         if (index >= 0) 
127           {
128             data = tmp.left(index).trimmed();
129             cmt = tmp.mid(index+1).trimmed();
130           }
131
132         // If comment is not empty, try to get keyword from it (separated by ':' symbol)
133         if (!cmt.isEmpty()) 
134           {
135             int index1 = cmt.indexOf(":");
136
137             if (index1 >= 0) 
138               {
139                 QString tmpstr = cmt.left(index1).trimmed();
140                 if (tmpstr == QString("TITLE") ||
141                     tmpstr == QString("COLUMN_TITLES") ||
142                     tmpstr == QString("COLUMN_UNITS") ||
143                     tmpstr == QString("COMMENT")) 
144                   {
145                     keyword = tmpstr;
146                     cmt = cmt.mid(index1+1).trimmed();
147                   }
148               }
149           }
150         
151         // If data is empty, process only comment
152         if (data.isEmpty()) 
153           {
154             // If keyword is found, try to process it
155             // elsewise it is a simple comment, just ignore it
156             if (!keyword.isEmpty()) 
157               {
158                 if (keyword == QString( "TITLE" )) 
159                   {
160                     QString title = cmt;
161                     if (table2D.myTitle != "") {
162                       title = QString(table2D.myTitle.c_str()) + QString(" ") + title;
163                     }
164                     table2D.myTitle = title.toLatin1().constData();
165                   }
166                 else if (keyword == QString("COLUMN_TITLES")) 
167                   {
168                     // Comment may contain column headers
169                     QStringList strList = cmt.split("|", QString::SkipEmptyParts);
170
171                     for ( int i = 0; i < strList.count(); i++ ) 
172                       {
173                         QString tmpstr = strList[i].trimmed();
174                         table2D.myColumnTitles.push_back(tmpstr.toLatin1().constData());
175                       }
176                   }
177                 else if (keyword == QString("COLUMN_UNITS")) 
178                   {
179                     // Comment may contain column units
180                     QStringList strList = cmt.split( " ", QString::SkipEmptyParts );
181             
182                     for (int i = 0; i < strList.count(); i++) 
183                       {
184                         QString tmpstr = strList[i].trimmed();
185                         table2D.myColumnUnits.push_back(tmpstr.toLatin1().constData());
186                       }
187                   }
188                 else if (keyword == QString("COMMENT")) 
189                   {
190                     // Keyword 'COMMENT' processing can be here,
191                     // currently it is ignored
192                   }
193               }
194             else {
195               // Simple comment processing can be here,
196               // currently it is ignored
197             }
198           }
199         // If data is not empty, try to process it
200         else {
201           Table2D::Row row;
202         
203           QString datar1 = data.replace(QRegExp("\t"), " ");
204           QStringList valList = datar1.split(separator, QString::SkipEmptyParts);
205           if(table2D.myColumnTitles.size() == 0 && isFirst && firstStringAsTitles) 
206             {
207               for ( int i = 0; i < valList.count(); i++ ) 
208                 {
209                   QString tmpstr = valList[i].trimmed();
210                   table2D.myColumnTitles.push_back(tmpstr.toLatin1().constData());
211                 }
212             }
213           else 
214             {
215               if (!cmt.isEmpty()) 
216                 {
217                   row.myTitle = cmt.toLatin1().constData();
218                 }
219           
220               for (int i = 0; i < valList.count(); i++) 
221                 {
222                   if (valList[i].trimmed() != "") 
223                     {
224                       Table2D::Value val = valList[i].trimmed().toLatin1().constData();
225                       row.myValues.push_back(val);
226                     }
227                 }
228           
229               if(row.myValues.size() > 0)
230                 {
231                   table2D.myRows.push_back(row);
232                 }
233             }
234
235           isFirst = false;
236         }
237         getLine(streamIn, tmp);
238       }
239     
240     
241     if(table2D.Check()) 
242       {
243         if (count == tableNb) 
244           {
245             if (QString::fromStdString(table2D.myTitle).isEmpty()) 
246               {
247                 table2D.myTitle = QString("Table:%1").arg(tableNb).toStdString();
248               }
249             return table2D;
250           }
251         count++;
252       }
253     
254   } while (!streamIn.eof());
255   
256   streamIn.close();
257   
258   // Return empty table
259   Table2D emptyTable;
260   return emptyTable;
261 }