Salome HOME
Merge branch V7_3_1_BR
[modules/paravis.git] / src / Plugins / TableReader / Reader / TableParser.cxx
1 // Copyright (C) 2010-2014  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, or (at your option) any later version.
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 }