Mantid
Loading...
Searching...
No Matches
TSVSerialiser.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
10
11#include <boost/algorithm/string.hpp>
12#include <boost/regex.hpp>
13#include <sstream>
14
15namespace {
16Mantid::Kernel::Logger g_log("TSVSerialiser");
17}
18
19using namespace MantidQt::API;
20
21TSVSerialiser::TSVSerialiser() : m_curIndex(0), m_midLine(false) {}
22
23TSVSerialiser::TSVSerialiser(const std::string &lines) : m_curIndex(0), m_midLine(false) { parseLines(lines); }
24
25void TSVSerialiser::parseLines(const std::string &lines) {
26 std::vector<std::string> lineVec;
27 boost::split(lineVec, lines, boost::is_any_of("\n"));
28
29 // Clear out any old data.
30 m_lines.clear();
31 m_sections.clear();
32
33 boost::regex valueLineRegex("\\s*([a-zA-Z0-9]+)\\b.*");
34 boost::regex closedSectionRegex("\\s*<([a-zA-Z0-9]+)>(.*)</\\1>");
35 boost::regex openSectionRegex("\\s*<([a-zA-Z0-9]+)( [0-9]+)?>(.*)");
36
37 for (auto lineIt = lineVec.begin(); lineIt != lineVec.end(); ++lineIt) {
38 const std::string line = *lineIt;
39
40 if (line.length() == 0)
41 continue;
42
43 // Stores matched sections of a regex
44 boost::smatch matches;
45
46 // Check if this is a value line
47 if (boost::regex_match(line, matches, valueLineRegex)) {
48 std::string name = matches[1].str();
49 m_lines[name].emplace_back(line);
50 }
51 // Look for lines which open and close a section in one line:
52 // <section>data</section>
53 else if (boost::regex_match(line, matches, closedSectionRegex)) {
54 std::string name = matches[1].str();
55 std::string contents = matches[2].str();
56
57 m_sections[name].emplace_back(contents);
58 }
59 // Check if this is the start of a multiline section, if so, consume the
60 // whole section.
61 else if (boost::regex_match(line, matches, openSectionRegex)) {
62 std::stringstream sectionSS;
63
64 std::string name = matches[1].str();
65 std::string firstLine = matches[2].str();
66 std::string num;
67 if (matches.size() == 4) {
68 num = matches[2].str();
69 firstLine = matches[3].str();
70 }
71
72 // firstLine exists because of a legacy edgecase: the <folder> section
73 // keeps values on the same line as
74 // the opening tag, so we have to be able to read that.
75 if (firstLine.length() > 0)
76 sectionSS << firstLine << "\n";
77
78 boost::regex openRegex("\\s*<" + name + num + ">.*");
79 boost::regex closeRegex("\\s*</" + name + ">");
80
81 // Lets iterate over the contents of the section
82 auto secIt = lineIt + 1;
83
84 // Search for opening and closing tags, counting depth and building the
85 // section string.
86 for (int depth = 1; depth > 0 && secIt != lineVec.end(); ++secIt) {
87 std::string secLine = *secIt;
88 // Are we going down?
89 if (boost::regex_match(secLine, openRegex))
90 depth++;
91 else if (boost::regex_match(secLine, closeRegex))
92 depth--;
93
94 if (depth > 0)
95 sectionSS << secLine << "\n";
96 }
97
98 // We've now advanced beyond the end of the section so go back one
99 secIt--;
100
101 std::string sectionStr = sectionSS.str();
102
103 // We drop the last character because it's a spare newline
104 if (sectionStr.size() > 0)
105 sectionStr.resize(sectionStr.size() - 1);
106
107 m_sections[name + num].emplace_back(sectionStr);
108
109 // Skip parsing to the end of the section
110 lineIt = secIt;
111 } else {
112 // If we've made it here then we don't know what kind of line this is.
113 g_log.warning() << "Unable to identify line in TSVSerialiser::parseLines(): '" << line << "'\n";
114 }
115 }
116}
117
118bool TSVSerialiser::hasLine(const std::string &name) const { return (m_lines.find(name) != m_lines.end()); }
119
120bool TSVSerialiser::hasSection(const std::string &name) const { return (m_sections.find(name) != m_sections.end()); }
121
122std::vector<std::string> TSVSerialiser::values(const std::string &name, size_t i) const {
123 // Select correct line with lineAsString, parse it, then return values
124 std::vector<std::string> ret;
125
126 std::string line = lineAsString(name, i);
127 boost::split(ret, line, boost::is_any_of("\t"));
128
129 return ret;
130}
131
132std::vector<std::string> TSVSerialiser::sections(const std::string &name) const {
133 if (!hasSection(name))
134 return std::vector<std::string>();
135
136 return m_sections.at(name);
137}
138
139std::string TSVSerialiser::lineAsString(const std::string &name, const size_t i) const {
140 if (!hasLine(name))
141 return "";
142
143 auto lines = m_lines.at(name);
144
145 return lines[i];
146}
147
148QString TSVSerialiser::lineAsQString(const std::string &name, const size_t i) const {
149 return QString::fromStdString(lineAsString(name, i));
150}
151
152bool TSVSerialiser::selectLine(const std::string &name, const size_t i) {
153 if (!hasLine(name))
154 return false;
155
156 if (i >= m_lines[name].size())
157 return false;
158
159 m_curValues = values(name, i);
160 m_curIndex = 1; // 1 because we want to start on the values, not the name
161 return true;
162}
163
164bool TSVSerialiser::selectSection(const std::string &name, const size_t i) {
165 if (!hasSection(name))
166 return false;
167
168 if (i >= m_sections[name].size())
169 return false;
170
171 m_curValues.clear();
172 m_curValues.emplace_back(name);
173 m_curValues.emplace_back(m_sections[name][i]);
174 m_curIndex = 1; // 1 because we want to start on the values, not the name
175 return true;
176}
177
178int TSVSerialiser::asInt(const size_t i) const {
179 if (i >= m_curValues.size())
180 return 0;
181
182 std::string valStr = m_curValues.at(i);
183
184 std::stringstream valSS(valStr);
185 int ret;
186 valSS >> ret;
187
188 return ret;
189}
190
191size_t TSVSerialiser::asSize_t(const size_t i) const {
192 if (i >= m_curValues.size())
193 return 0;
194
195 std::string valStr = m_curValues.at(i);
196
197 std::stringstream valSS(valStr);
198 size_t ret;
199 valSS >> ret;
200
201 return ret;
202}
203
204double TSVSerialiser::asDouble(const size_t i) const {
205 if (i >= m_curValues.size())
206 return 0.00;
207
208 std::string valStr = m_curValues.at(i);
209
210 std::stringstream valSS(valStr);
211 double ret;
212 valSS >> ret;
213
214 return ret;
215}
216
217float TSVSerialiser::asFloat(const size_t i) const {
218 if (i >= m_curValues.size())
219 return 0.00;
220
221 std::string valStr = m_curValues.at(i);
222
223 std::stringstream valSS(valStr);
224 float ret;
225 valSS >> ret;
226
227 return ret;
228}
229
230bool TSVSerialiser::asBool(const size_t i) const {
231 if (i >= m_curValues.size())
232 return false;
233
234 std::string valStr = m_curValues.at(i);
235
236 std::stringstream valSS(valStr);
237 bool ret;
238 valSS >> ret;
239
240 return ret;
241}
242
243QRect TSVSerialiser::asQRect(const size_t i) {
244 if (i + 3 >= m_curValues.size())
245 return QRect();
246
247 int x0 = asInt(m_curIndex);
248 int y0 = asInt(++m_curIndex);
249 int x1 = asInt(++m_curIndex);
250 int y1 = asInt(++m_curIndex);
251 ++m_curIndex;
252
253 QPoint point0(x0, y0);
254 QPoint point1(x1, y1);
255 QRect rect(point0, point1);
256
257 return rect;
258}
259
260QColor TSVSerialiser::asQColor(const size_t i) {
261 if (i + 3 >= m_curValues.size())
262 return QColor();
263
264 int r = asInt(m_curIndex);
265 int g = asInt(++m_curIndex);
266 int b = asInt(++m_curIndex);
267 int a = asInt(++m_curIndex);
268 ++m_curIndex;
269
270 QColor color(r, g, b, a);
271 return color;
272}
273
274QPoint TSVSerialiser::asQPoint(const size_t i) {
275 if (i + 1 >= m_curValues.size())
276 return QPoint();
277
278 int x = asInt(m_curIndex);
279 int y = asInt(++m_curIndex);
280 ++m_curIndex;
281
282 QPoint point(x, y);
283 return point;
284}
285
286QPointF TSVSerialiser::asQPointF(const size_t i) {
287 if (i + 1 >= m_curValues.size())
288 return QPointF();
289
290 double x = asDouble(m_curIndex);
291 double y = asDouble(++m_curIndex);
292 ++m_curIndex;
293
294 QPointF point(x, y);
295 return point;
296}
297
298std::string TSVSerialiser::asString(const size_t i) const {
299 if (i >= m_curValues.size())
300 return "";
301
302 return m_curValues.at(i);
303}
304
305QString TSVSerialiser::asQString(const size_t i) const {
306 if (i >= m_curValues.size())
307 return "";
308
309 return QString::fromStdString(m_curValues.at(i));
310}
311
312void TSVSerialiser::storeDouble(const double val) { m_output << "\t" << val; }
313
314void TSVSerialiser::storeInt(const int val) { m_output << "\t" << val; }
315void TSVSerialiser::storeString(const std::string &val) { m_output << "\t" << val; }
316
317void TSVSerialiser::storeBool(const bool val) { m_output << "\t" << val; }
318
320
322
324
326
328 val = asInt(m_curIndex++);
329 return *this;
330}
331
333 val = asSize_t(m_curIndex++);
334 return *this;
335}
336
338 val = asDouble(m_curIndex++);
339 return *this;
340}
341
343 val = asFloat(m_curIndex++);
344 return *this;
345}
346
348 val = asString(m_curIndex++);
349 return *this;
350}
351
353 val = QString::fromUtf8(asString(m_curIndex++).c_str());
354 return *this;
355}
356
358 val = asBool(m_curIndex++);
359 return *this;
360}
361
363 val = asQRect(m_curIndex);
364 return *this;
365}
366
368 val = asQColor(m_curIndex);
369 return *this;
370}
371
373 val = asQPoint(m_curIndex);
374 return *this;
375}
376
378 val = asQPointF(m_curIndex);
379 return *this;
380}
381
382TSVSerialiser &TSVSerialiser::writeLine(const std::string &name) {
383 // If we're not on a new line, make one
384 if (m_midLine) {
385 m_output << "\n";
386 }
387
388 m_output << name;
389
390 m_midLine = true;
391 return *this;
392}
393
394TSVSerialiser &TSVSerialiser::operator<<(const std::string &val) {
395 storeString(val);
396 return *this;
397}
398
400 m_output << "\t" << std::string(val);
401 return *this;
402}
403
405 const std::string str = val.toUtf8().constData();
406 m_output << "\t" << str;
407 return *this;
408}
409
411 storeDouble(val);
412 return *this;
413}
414
416 storeInt(val);
417 return *this;
418}
419
421 m_output << "\t" << val;
422 return *this;
423}
424
426 storeBool(val);
427 return *this;
428}
429
431 auto point0 = val.topLeft();
432 auto point1 = val.bottomRight();
433 m_output << "\t" << point0.x() << "\t" << point0.y() << "\t" << point1.x() << "\t" << point1.y();
434 return *this;
435}
436
438
439 m_output << "\t" << val.red() << "\t" << val.green() << "\t" << val.blue() << "\t" << val.alpha();
440 return *this;
441}
442
444
445 m_output << "\t" << val.x() << "\t" << val.y();
446 return *this;
447}
448
450
451 m_output << "\t" << val.x() << "\t" << val.y();
452 return *this;
453}
454
455void TSVSerialiser::writeRaw(const std::string &raw) {
456 if (m_midLine) {
457 m_output << "\n";
458 m_midLine = false;
459 }
460
461 m_output << raw;
462
463 // If raw didn't end in a newline, make a note of it.
464 m_midLine = (raw.length() > 0 && raw[raw.length() - 1] != '\n');
465}
466
467void TSVSerialiser::writeSection(const std::string &name, const std::string &body) {
468 // If we're not on a new line, make one
469 if (m_midLine) {
470 m_output << "\n";
471 m_midLine = false;
472 }
473
474 m_output << "<" << name << ">"
475 << "\n";
476 m_output << body;
477
478 // If body isn't blank and didn't end with a new line, add one.
479 if (body.length() > 0 && body[body.length() - 1] != '\n')
480 m_output << "\n";
481
482 m_output << "</" << name << ">"
483 << "\n";
484}
485
486void TSVSerialiser::writeInlineSection(const std::string &name, const std::string &body) {
487 // If we're not on a new line, make one
488 if (m_midLine) {
489 m_output << "\n";
490 m_midLine = false;
491 }
492
493 m_output << "<" << name << ">";
494 m_output << body;
495 m_output << "</" << name << ">"
496 << "\n";
497}
498
499std::string TSVSerialiser::outputLines() const {
500 std::string output = m_output.str();
501 if (m_midLine)
502 output += "\n";
503
504 return output;
505}
506
508 m_sections.clear();
509 m_lines.clear();
510 m_curValues.clear();
511 m_curIndex = 0;
512 m_output.clear();
513 m_midLine = false;
514}
std::string outputLines() const
void writeInlineSection(const std::string &name, const std::string &body)
TSVSerialiser & operator<<(const std::string &val)
std::vector< std::string > sections(const std::string &name) const
void writeSection(const std::string &name, const std::string &body)
bool hasSection(const std::string &name) const
bool asBool(const size_t i) const
Mantid::Kernel::CaseInsensitiveMap< std::vector< std::string > > m_sections
QString lineAsQString(const std::string &name, const size_t i=0) const
bool selectLine(const std::string &name, const size_t i=0)
QColor asQColor(const size_t i)
std::vector< std::string > values(const std::string &name, const size_t i=0) const
bool selectSection(const std::string &name, const size_t i=0)
double asDouble(const size_t i) const
size_t asSize_t(const size_t i) const
bool hasLine(const std::string &name) const
QPointF asQPointF(const size_t i)
std::vector< std::string > m_curValues
void storeDouble(const double val)
void storeInt(const int val)
TSVSerialiser & operator>>(std::vector< T > &val)
Definition: TSVSerialiser.h:46
Mantid::Kernel::CaseInsensitiveMap< std::vector< std::string > > m_lines
void writeRaw(const std::string &raw)
void storeBool(const bool val)
TSVSerialiser & writeLine(const std::string &name)
QString asQString(const size_t i) const
void storeString(const std::string &val)
std::string lineAsString(const std::string &name, const size_t i=0) const
QRect asQRect(const size_t i)
int asInt(const size_t i) const
float asFloat(const size_t i) const
std::stringstream m_output
QPoint asQPoint(const size_t i)
std::string asString(const size_t i) const
void parseLines(const std::string &lines)
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
Kernel::Logger g_log("ExperimentInfo")
static logger object