Skip to content

Commit

Permalink
Add TSVSerialiser class. Refs #9970
Browse files Browse the repository at this point in the history
This time it ought not break the build.
  • Loading branch information
Harry Jeffery committed Jul 25, 2014
1 parent 4176734 commit 8d7cbe5
Show file tree
Hide file tree
Showing 3 changed files with 304 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/MantidPlot/CMakeLists.txt
Expand Up @@ -129,6 +129,7 @@ set ( QTIPLOT_SRCS src/ApplicationWindow.cpp
src/TiledWindow.cpp
src/TitlePicker.cpp
src/TranslateCurveTool.cpp
src/TSVSerialiser.cpp
src/UserFunction.cpp
src/VectorCurve.cpp
src/origin/OPJFile.cpp
Expand Down Expand Up @@ -372,6 +373,7 @@ set ( QTIPLOT_HDRS src/ApplicationWindow.h
src/TiledWindow.h
src/TitlePicker.h
src/TranslateCurveTool.h
src/TSVSerialiser.h
src/UserFunction.h
src/VectorCurve.h
src/analysis/fft2D.h
Expand Down
234 changes: 234 additions & 0 deletions Code/Mantid/MantidPlot/src/TSVSerialiser.cpp
@@ -0,0 +1,234 @@
#include "TSVSerialiser.h"

#include "MantidKernel/Logger.h"

#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <sstream>

namespace
{
Mantid::Kernel::Logger g_log("TSVSerialiser");
}

TSVSerialiser::TSVSerialiser() : m_curIndex(0)
{
}

TSVSerialiser::TSVSerialiser(std::string lines)
{
parseLines(lines);
}

void TSVSerialiser::parseLines(std::string lines)
{
std::vector<std::string> lineVec;
boost::split(lineVec, lines, boost::is_any_of("\n"));

//Clear out any old data.
m_lines.clear();
m_sections.clear();

boost::regex valueLineRegex("([a-zA-Z0-9]+)\\b.*");
boost::regex closedSectionRegex("<([a-zA-Z0-9]+)>(.*)</\\1>");
boost::regex openSectionRegex("<([a-zA-Z0-9]+)>(.*)");

for(auto lineIt = lineVec.begin(); lineIt != lineVec.end(); ++lineIt)
{
std::string line = *lineIt;

if(line.length() == 0)
continue;

//Stores matched sections of a regex
boost::smatch matches;

//Check if this is a value line
if(boost::regex_match(line, matches, valueLineRegex))
{
std::string name = matches[1].str();

m_lines[name].push_back(line);

g_log.information() << "found value line with name '" << name << "'" << std::endl;
continue;
}

//Look for lines which open and close a section in one line: <section>data</section>
if(boost::regex_match(line, matches, closedSectionRegex))
{
std::string name = matches[1].str();
std::string contents = matches[2].str();

m_sections[name].push_back(contents);

g_log.information() << "found closed section '" << name << "' with contents='" << contents << "'" << std::endl;
continue;
}

//Check if this is the start of a multiline section, if so, consume the whole section.
if(boost::regex_match(line, matches, openSectionRegex))
{
std::stringstream sectionSS;

std::string name = matches[1].str();
std::string firstLine = matches[2].str();

//firstLine exists because of a legacy edgecase: the <folder> section keeps values on the same line as
//the opening tag, so we have to be able to read that.
if(firstLine.length() > 0)
sectionSS << firstLine << "\n";

std::stringstream openSS;
openSS << "<" << name << ">.*";
boost::regex openRegex(openSS.str());

std::stringstream closeSS;
closeSS << "</" << name << ">";
boost::regex closeRegex(closeSS.str());

//Next line, to begin parsing
lineIt++;

//Search for opening and closing tags, counting depth and building the section string.
for(int depth = 1; depth > 0 && lineIt != lineVec.end(); ++lineIt)
{
line = *lineIt;
//Are we going down?
if(boost::regex_match(line, openRegex))
{
depth++;
} else if(boost::regex_match(line, closeRegex))
{
depth--;
}

if(depth > 0)
sectionSS << line << "\n";
}

//Back to start of next line;
lineIt--;

std::string sectionStr = sectionSS.str();

//We drop the last character because it's a spare newline
if(sectionStr.size() > 0)
sectionStr.resize(sectionStr.size() - 1);

m_sections[name].push_back(sectionStr);

g_log.information() << "read <" << name << ">:\n---------------------------\n" << sectionSS.str() << "----------------------------" << std::endl;
continue;
}

//If we've made it here then we don't know what kind of line this is.
g_log.error() << "Unable to identify line in TSVSerialiser::parseLines(): '" << line << "'" << std::endl;
}
}

bool TSVSerialiser::hasLine(std::string name) const
{
return ( m_lines.find(name) != m_lines.end() );
}

bool TSVSerialiser::hasSection(std::string name) const
{
return ( m_sections.find(name) != m_sections.end() );
}

std::vector<std::string> TSVSerialiser::values(std::string name, size_t i) const
{
//Select correct line with lineAsString, parse it, then return values
std::vector<std::string> ret;

std::string line = lineAsString(name, i);
boost::split(ret, line, boost::is_any_of("\t"));

return ret;
}

std::vector<std::string> TSVSerialiser::sections(std::string name) const
{
if(!hasSection(name))
return std::vector<std::string>();

return m_sections.at(name);
}

std::string TSVSerialiser::lineAsString(const std::string name, const size_t i) const
{
if(!hasLine(name))
return "";

auto lines = m_lines.at(name);

return lines[i];
}

bool TSVSerialiser::selectLine(std::string name, const size_t i)
{
if(!hasLine(name))
return false;

if(i >= m_lines[name].size())
return false;

m_curValues = values(name, i);
m_curIndex = 1; //1 because we want to start on the values, not the name
return true;
}

int TSVSerialiser::asInt(const size_t i) const
{
if(i >= m_curValues.size())
return 0;

std::string valStr = m_curValues.at(i);

std::stringstream valSS(valStr);
int ret;
valSS >> ret;

return ret;
}

double TSVSerialiser::asDouble(const size_t i) const
{
if(i >= m_curValues.size())
return 0.00;

std::string valStr = m_curValues.at(i);

std::stringstream valSS(valStr);
double ret;
valSS >> ret;

return ret;
}

std::string TSVSerialiser::asString(const size_t i) const
{
if(i >= m_curValues.size())
return "";

return m_curValues.at(i);
}

TSVSerialiser& TSVSerialiser::operator>>(int& val)
{
val = asInt(m_curIndex++);
return *this;
}

TSVSerialiser& TSVSerialiser::operator>>(double& val)
{
val = asDouble(m_curIndex++);
return *this;
}

TSVSerialiser& TSVSerialiser::operator>>(std::string& val)
{
val = asString(m_curIndex++);
return *this;
}
68 changes: 68 additions & 0 deletions Code/Mantid/MantidPlot/src/TSVSerialiser.h
@@ -0,0 +1,68 @@
#ifndef MANTID_TSVSERIALISER_H_
#define MANTID_TSVSERIALISER_H_

#include <map>
#include <string>
#include <vector>

/** Parses the formatting used in MantidPlot project files
@author Harry Jeffery, ISIS, RAL
@date 23/07/2014
Copyright &copy; 2007-2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
*/
class TSVSerialiser
{
public:

TSVSerialiser();

TSVSerialiser(std::string lines);

void parseLines(std::string lines);

bool hasLine(const std::string name) const;
bool hasSection(const std::string name) const;

std::vector<std::string> values(const std::string name, const size_t i = 0) const;
std::vector<std::string> sections(const std::string name) const;

std::string lineAsString(const std::string name, const size_t i = 0) const;

bool selectLine(const std::string name, const size_t i = 0);

int asInt(const size_t i) const;
double asDouble(const size_t i) const;
std::string asString(const size_t i) const;

TSVSerialiser& operator>>(int& val);
TSVSerialiser& operator>>(double& val);
TSVSerialiser& operator>>(std::string& val);

private:
std::map<std::string,std::vector<std::string> > m_sections;
std::map<std::string,std::vector<std::string> > m_lines;

std::vector<std::string> m_curValues;
int m_curIndex;
};

#endif

0 comments on commit 8d7cbe5

Please sign in to comment.