Commit f53db33d authored by Kirill Terekhov's avatar Kirill Terekhov
Browse files

Added XML parsing as a service

parent 1ea676ef
......@@ -247,6 +247,7 @@ set(INMOST_INSTALL_HEADERS Source/Headers/inmost.h
Source/Headers/inmost_partitioner.h
Source/Headers/inmost_solver.h
Source/Headers/inmost_sparse.h
Source/Headers/inmost_xml.h
Source/Headers/inmost_variable.h
Source/Headers/container.hpp)
......@@ -277,6 +278,7 @@ set_property(TARGET inmost PROPERTY PUBLIC_HEADER
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_solver.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_sparse.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_variable.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_xml.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/container.hpp")
install(FILES
......
......@@ -18,6 +18,7 @@ set(HEADER
${CMAKE_CURRENT_SOURCE_DIR}/inmost_variable.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_sparse.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_nonlinear.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_xml.h
${CMAKE_CURRENT_SOURCE_DIR}/container.hpp
PARENT_SCOPE
)
\ No newline at end of file
......@@ -9,5 +9,6 @@
#include "inmost_partitioner.h"
#include "inmost_variable.h"
#include "inmost_nonlinear.h"
#include "inmost_xml.h"
#endif // INMOST_H_INCLUDED
#ifndef INMOST_XML_INCLUDED
#define INMOST_XML_INCLUDED
#include "inmost.h"
namespace INMOST
{
std::string CharToHex(char c);
#if defined(USE_MESH)
std::string ReferenceToString(INMOST::HandleType h, int pos);
#endif
#if defined(USE_AUTODIFF)
std::string VariableToString(INMOST::Storage::var v);
#endif
char * sstrip(char * str);
std::string sstrip(const std::string & input);
int ConvertHex(char in);
char atoc(const char * str);
class XMLReader
{
class Interpreter
{
bool error_state;
std::vector<std::string> Expand(const std::string & input) const;
std::vector<std::string> MakePolish(const std::vector<std::string> & input);
void Print(const std::vector<std::string> & polish) const;
double Run(const std::vector<std::string> & polish);
public:
Interpreter();
Interpreter(const Interpreter & b);
Interpreter & operator = (Interpreter const & b);
double Evaluate(const std::string & str);
bool isError();
void ClearError();
};
Interpreter intrp;
struct Stream
{
std::string src;
std::istream * s;
int linebreak, linechar;
int hadlinebreak, hadlinechar;
};
std::vector<Stream> inp;
int verbose;
enum State
{
Intro, //read tag or read tag contents
WaitTag, //wait tag name or comment
ReadTag, //reading in tag name
ReadCommentExclamation, //skipping comments
ReadCommentQuestion, //skipping comments
WaitAttribute, //reading attribute name
ReadAttribute,
WaitAttributeValue, //read attribute value
ReadAttributeValue,
ReadAttributeValueQuote,
EndTag, //tag ended read closing
WaitCloseTag,
ReadCloseTagSlash,
ReadCloseTagName,
WaitContentsOpen,
WaitContents,
ReadContents, //parse a word
ReadContentsVector, // {0,1,2,3}
ReadContentsQuotes, // "hello world"
ReadContentsMultiplier, // 123*5
ReadContentsMultiplierSkopes, // 123*(SetSize/2)
EndContents,
ReadVector,
EndOfFile, // end of file reached
Failure //unexpected error
} _state;
Stream & get_Stream();
const Stream & get_Stream() const;
std::istream & get_iStream();
const std::istream & get_iStream() const;
//should not share the reference to the stream with another reader
XMLReader(const XMLReader & other);
XMLReader & operator =(XMLReader & other);
char GetChar();
//return one character back to the stream
void RetChar();
void SkipComments(State RetState);
std::string StateName(State s) const;
public:
void Report(const char * fmt, ...) const;
XMLReader(std::string sourcename, std::istream & input);
void PushStream(std::string file);
void PopStream();
//read in <TagName returns TagName
std::string ReadOpenTag();
//read > or /> skipping for attributes
int ReadCloseTag();
bool isTagFinish() const;
//read </TagName> or fail
bool ReadFinishTag(std::string TagName);
//read next attribute name, check isTagEnded
std::string AttributeName();
//read value of the attribute after reading it's name
std::string AttributeValue();
// > or /> was reached, should close ReadCloseTag
// to finalize
bool isTagEnded() const;
//read in <![CDATA[
//Quick and dirty, rewrite with states!
bool ReadOpenContents();
//get next full word inside contents
std::string GetContentsWord();
//read ]]>
bool ReadCloseContents();
//]]> was reached, should call ReadCloseContents
//to finalize
bool isContentsEnded() const;
bool isFailure() const;
bool isEof() const;
#if defined(USE_MESH)
INMOST::ElementType atoes(const char * _str);
INMOST::ElementType atoe(const char * _str);
std::pair<INMOST::ElementType,int> atoh(const char * _str);
std::pair<std::string,std::pair<INMOST::ElementType,int> > atorh(const char * _str);
#endif
#if defined(USE_AUTODIFF)
INMOST::Storage::var atov(const char * _str);
#endif
int EvaluateExpression(std::string expression);
int ConvertMultiplier(std::string expression, int SetSize);
void SplitValueMultiplier(std::string expression, std::string & value, std::string & multiplier);
bool ParseBool(std::string word);
void ParseCommaSeparated(std::string word, std::vector<std::string> & parsed, char symbol = ',');
void ParseReal(std::string word, std::vector<INMOST::Storage::real> & Vector, int & Repeat, int SetSize);
#if defined(USE_AUTODIFF)
void ParseVariable(std::string word, std::vector<INMOST::Storage::var> & Vector, int & Repeat, int SetSize);
#endif
void ParseInteger(std::string word, std::vector<INMOST::Storage::integer> & Vector, int & Repeat, int SetSize);
void ParseBulk(std::string word, std::string & Vector, int & Repeat, int SetSize);
void ParseReference(std::string word, std::vector<std::pair<INMOST::ElementType,int> > & Vector, int & Repeat, int SetSize);
void ParseRemoteReference(std::string word, std::vector< std::pair<std::string,std::pair<INMOST::ElementType,int> > > & Vector, int & Repeat, int SetSize);
struct XMLAttrib
{
std::string name;
std::string value;
};
struct XMLTag
{
std::string name; //<Name of the XML tag
std::vector<XMLAttrib> attributes; //<List of attributes
int finish; //<Whether to close the tag
///Was not able to read the tag
bool Failure() const;
///Tag was red, can process the contents
bool Process() const;
///Tag was not red, finish of enclosing tag was encountered
bool Finalize() const;
const XMLAttrib & GetAttib(int n) const;
XMLAttrib & GetAttib(int n);
int NumAttrib() const;
};
XMLTag OpenTag();
bool CloseTag(XMLTag & tag);
};
}
#endif //INMOST_XML_INCLUDED
#ifdef _MSC_VER //kill some warnings
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "inmost.h"
#include <stdarg.h> //for va_list
#if defined(USE_MESH)
std::string CharToHex(char c)
{
char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B','C','D','E','F'};
std::string str = "";
str.append(&hex[(c & 0xF0) >> 4], 1);
str.append(&hex[c & 0xF], 1);
return str;
}
std::string ReferenceToString(INMOST::HandleType h, int pos)
{
std::stringstream ret;
switch(INMOST::GetHandleElementType(h))
{
case INMOST::NODE: ret << "Node:"; break;
case INMOST::EDGE: ret << "Edge:"; break;
case INMOST::FACE: ret << "Face:"; break;
case INMOST::CELL: ret << "Cell:"; break;
case INMOST::ESET: ret << "Set:"; break;
case INMOST::MESH: ret << "Mesh:"; break;
}
ret << pos;//INMOST::GetHandleID(h);
return ret.str();
}
#if defined(USE_AUTODIFF)
std::string VariableToString(INMOST::Storage::var v)
{
std::stringstream ret;
const INMOST::Sparse::Row & r = v.GetRow();
ret << "(";
ret << v.GetValue() << ";";
ret << r.Size();
if( !r.Empty() )
{
ret << ";";
for(int q = 0; q < (int)r.Size()-1; ++q)
{
ret << r.GetValue(q) << ";";
ret << r.GetIndex(q) << ";";
}
ret << r.GetValue(r.Size()-1) << ";";
ret << r.GetIndex(r.Size()-1);
}
ret << ")";
return ret.str();
}
#endif
class XMLReader
{
class Interpreter
{
bool error_state;
std::vector<std::string> Expand(std::string & input)
{
std::vector<std::string> ret;
std::string put;
for(int k = 0; k < (int)input.length(); ++k)
{
if( get_priority(input[k]) != -1 )
{
if( !put.empty() )
{
ret.push_back(put);
put.clear();
}
ret.push_back(std::string(1,input[k]));
}
else put.push_back(input[k]);
}
if( !put.empty() ) ret.push_back(put);
return ret;
}
int get_priority(char c)
{
switch(c)
{
case '(': return 0;
case ')': return 1;
case '+':
case '-': return 8;
case '*':
case '/': return 9;
case '~': return 10;
default: return -1;
}
}
std::vector<std::string> MakePolish(std::vector<std::string> & input)
{
std::vector<std::string> stack, ret;
int priority;
for(int k = 0; k < (int)input.size(); ++k)
{
if( input[k].size() == 1 && (priority = get_priority(input[k][0])) != -1 )
{
char op = input[k][0];
if( op != '(' )
{
while(!stack.empty() && priority <= get_priority(stack.back()[0]) )
{
ret.push_back(stack.back());
stack.pop_back();
}
}
if( op == ')' )
{
if( stack.empty() )
{
std::cout << "Warning: parentheses unbalanced" << std::endl;
error_state = true;
break;
}
else if( stack.back()[0] == '(' )
stack.pop_back();
else
{
std::cout << "Warning: expected left bracket" << std::endl;
error_state = true;
break;
}
}
else if( op == '-' && (k == 0 || (input[k-1].size() == 1 && get_priority(input[k-1][0]) != -1)) ) //unary minus
stack.push_back("~");
else
stack.push_back(input[k]);
}
else ret.push_back(input[k]);
}
while(!stack.empty())
{
ret.push_back(stack.back());
stack.pop_back();
}
return ret;
}
void Print(std::vector<std::string> & polish)
{
for(int k = 0; k < (int)polish.size(); ++k)
std::cout << polish[k] << " ";
std::cout << std::endl;
}
double Run(std::vector<std::string> & polish)
{
std::vector<double> stack;
for(int k = 0; k < (int)polish.size(); ++k)
{
if( polish[k].size() == 1 && get_priority(polish[k][0]) != -1 )
{
double larg, rarg;
char op = polish[k][0];
switch(op)
{
case '+':
if( stack.size() < 2 )
{
std::cout << "Less then two arguments in stack for + operand" << std::endl;
error_state = true;
return 1.0e+20;
}
rarg = stack.back();
stack.pop_back();
larg = stack.back();
stack.pop_back();
stack.push_back(larg+rarg);
break;
case '-':
if( stack.size() < 2 )
{
std::cout << "Less then two arguments in stack for - operand" << std::endl;
error_state = true;
return 1.0e+20;
}
rarg = stack.back();
stack.pop_back();
larg = stack.back();
stack.pop_back();
stack.push_back(larg-rarg);
break;
case '*':
if( stack.size() < 2 )
{
std::cout << "Less then two arguments in stack for * operand" << std::endl;
error_state = true;
return 1.0e+20;
}
rarg = stack.back();
stack.pop_back();
larg = stack.back();
stack.pop_back();
stack.push_back(larg*rarg);
break;
case '/':
if( stack.size() < 2 )
{
std::cout << "Less then two arguments in stack for / operand" << std::endl;
error_state = true;
return 1.0e+20;
}
rarg = stack.back();
stack.pop_back();
larg = stack.back();
stack.pop_back();
stack.push_back(larg/rarg);
break;
case '~':
if( stack.size() < 1 )
{
std::cout << "No arguments in stack for unary minus operand" << std::endl;
error_state = true;
return 1.0e+20;
}
larg = stack.back();
stack.pop_back();
stack.push_back(-larg);
break;
}
}
else stack.push_back(atof(polish[k].c_str()));
}
if( stack.size() != 1 )
{
std::cout << "There are more operands on stack, but no operators" << std::endl;
error_state = true;
return 1.0e+20;
}
return stack.back();
}
public:
Interpreter() :error_state(false) {}
Interpreter(const Interpreter & b)
: error_state(b.error_state)
{}
Interpreter & operator = (Interpreter const & b)
{
error_state = b.error_state;
return * this;
}
double Evaluate(std::string & str)
{
//const char * debug_str = str.c_str();
std::vector<std::string> decompose = Expand(str);
std::vector<std::string> polish = MakePolish(decompose);
//Print(polish);
return Run(polish);
}
bool isError() {return error_state;}
void ClearError() {error_state = false;}
};
Interpreter intrp;
struct Stream
{
std::string src;
std::istream * s;
int linebreak, linechar;
int hadlinebreak, hadlinechar;
};
std::vector<Stream> inp;
int verbose;
enum State
{
Intro, //read tag or read tag contents
WaitTag, //wait tag name or comment
ReadTag, //reading in tag name
ReadCommentExclamation, //skipping comments
ReadCommentQuestion, //skipping comments
WaitAttribute, //reading attribute name
ReadAttribute,
WaitAttributeValue, //read attribute value
ReadAttributeValue,
ReadAttributeValueQuote,
EndTag, //tag ended read closing
WaitCloseTag,
ReadCloseTagSlash,
ReadCloseTagName,
WaitContentsOpen,
WaitContents,
ReadContents, //parse a word
ReadContentsVector, // {0,1,2,3}
ReadContentsQuotes, // "hello world"
ReadContentsMultiplier, // 123*5
ReadContentsMultiplierSkopes, // 123*(SetSize/2)
EndContents,
ReadVector,
EndOfFile, // end of file reached
Failure //unexpected error
} _state;
Stream & get_Stream() {return inp.back();}
std::istream & get_iStream() {return *inp.back().s;}
//should not share the reference to the stream with another reader
XMLReader(const XMLReader & other) {}
XMLReader & operator =(XMLReader & other) {return *this;}
char GetChar()
{
char c = '\0';
get_iStream().get(c);
get_Stream().hadlinebreak = get_Stream().linebreak;
get_Stream().hadlinechar = get_Stream().linechar;
if( c == '\n' )
{
++get_Stream().linebreak;
get_Stream().linechar = 0;
}
else ++get_Stream().linechar;
if( get_iStream().eof() )
{
if( inp.size() > 1 )
{
PopStream();
c = GetChar();
}
else
_state = EndOfFile;
}
if( get_iStream().fail() )
{
Report("Stream failed while getting the char");
_state = Failure;
}
return c;
}
//return one character back to the stream
void RetChar()
{
get_Stream().linebreak = get_Stream().hadlinebreak;
get_Stream().linechar = get_Stream().hadlinechar;
get_iStream().unget();
if( get_iStream().fail() )
{
Report("Stream failed while ungetting the char");
_state = Failure;
}
}
void SkipComments(State RetState)
{
int ntmp = 0;
char tmp[3] = {'\0','\0','\0'};
char c;
bool done = false;
if( _state == ReadCommentExclamation )
{
while(!done)
{
c = GetChar();
tmp[ntmp] = c;
if( tmp[ntmp] == '>' && tmp[(ntmp-1+3)%3] == '-' && tmp[(ntmp-2+3)%3] == '-' )
{
_state = RetState;
done = true;
}
ntmp = (ntmp+1)%3;
}
}
else if( _state == ReadCommentQuestion )
{
while(!done)
{
c = GetChar();
tmp[ntmp] = c;
if( tmp[ntmp] == '>' && tmp[(ntmp-1+2)%2] == '?' )
{
_state = RetState;
done = true;
}
ntmp = (ntmp+1)%2;
}
}
else
{
Report("Unexpected state %s while reading comments",StateName(_state).c_str());
_state = Failure; //What are we doing here?
}
}
std::string StateName(State s)
{
switch(s)
{
case Intro: return "Intro";
case WaitTag: return "WaitTag";
case ReadTag: return "ReadTag";
case ReadCommentExclamation: return "ReadCommentExclamation";
case ReadCommentQuestion: return "ReadCommentQuestion";
case WaitAttribute: return "WaitAttribute";
case ReadAttribute: return "ReadAttribute";
case WaitAttributeValue: return "WaitAttributeValue";
case ReadAttributeValue: return "ReadAttributeValue";
case ReadAttributeValueQuote: return "ReadAttributeValueQuote";