|
|
@ -6,6 +6,9 @@
|
|
|
|
#include <vector>
|
|
|
|
#include <vector>
|
|
|
|
#include <iterator>
|
|
|
|
#include <iterator>
|
|
|
|
#include <map>
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
#include <typeinfo>
|
|
|
|
|
|
|
|
|
|
|
|
#include <boost/utility.hpp>
|
|
|
|
#include <boost/utility.hpp>
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
@ -26,6 +29,16 @@ bool fml_convert(const V& in, T& out) {
|
|
|
|
return !!ss;
|
|
|
|
return !!ss;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string fml_int2str(int v);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Exception
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Exception : public std::runtime_error {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
explicit Exception(const std::string& what) : std::runtime_error(what) {}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Node
|
|
|
|
// Node
|
|
|
@ -54,6 +67,7 @@ public:
|
|
|
|
int line() const { return m_line; }
|
|
|
|
int line() const { return m_line; }
|
|
|
|
int size() const { return m_children.size(); }
|
|
|
|
int size() const { return m_children.size(); }
|
|
|
|
Node* parent() { return m_parent; }
|
|
|
|
Node* parent() { return m_parent; }
|
|
|
|
|
|
|
|
std::string what() const;
|
|
|
|
|
|
|
|
|
|
|
|
// iterators
|
|
|
|
// iterators
|
|
|
|
typedef NodeList::iterator iterator;
|
|
|
|
typedef NodeList::iterator iterator;
|
|
|
@ -69,6 +83,7 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
// util for generating error message
|
|
|
|
// util for generating error message
|
|
|
|
std::string generateErrorMessage(const std::string& message) const;
|
|
|
|
std::string generateErrorMessage(const std::string& message) const;
|
|
|
|
|
|
|
|
void throwError(const std::string& message) const { throw Exception(generateErrorMessage(message)); }
|
|
|
|
|
|
|
|
|
|
|
|
// extracting values operator
|
|
|
|
// extracting values operator
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
@ -79,45 +94,95 @@ public:
|
|
|
|
Node* at(int pos) const;
|
|
|
|
Node* at(int pos) const;
|
|
|
|
|
|
|
|
|
|
|
|
// get values
|
|
|
|
// get values
|
|
|
|
std::string value(const std::string& def = std::string()) const;
|
|
|
|
std::string value(const std::string& def = std::string()) const {
|
|
|
|
std::string valueAt(const std::string childTag, const std::string& def = std::string()) const;
|
|
|
|
if(!m_value.empty())
|
|
|
|
|
|
|
|
return m_value;
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// read values
|
|
|
|
std::string valueAt(const std::string childTag, const std::string& def = std::string()) const {
|
|
|
|
template <typename T>
|
|
|
|
if(Node* node = at(childTag))
|
|
|
|
T read(T def = T()) const {
|
|
|
|
return node->value();
|
|
|
|
T v = def;
|
|
|
|
return def;
|
|
|
|
*this >> v;
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string valueAt(int pos, const std::string& def = std::string()) const {
|
|
|
|
|
|
|
|
if(Node* node = at(pos))
|
|
|
|
|
|
|
|
return node->value();
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// read values into memory
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
bool read(T* v) const {
|
|
|
|
void read(T* v) const {
|
|
|
|
return (*this >> *v);
|
|
|
|
if(!(*this >> *v))
|
|
|
|
|
|
|
|
throw Exception(generateErrorMessage("failed to cast node value to type " + std::string(typeid(T).name())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
T readAt(const std::string& childTag, T def = T()) const {
|
|
|
|
bool readAt(const std::string& childTag, T* v) const {
|
|
|
|
T v = def;
|
|
|
|
if(Node* node = at(childTag)) {
|
|
|
|
for(NodeList::const_iterator it = m_children.begin(); it != m_children.end(); ++it) {
|
|
|
|
node->read<T>(v);
|
|
|
|
if((*it)->tag() == childTag) {
|
|
|
|
return true;
|
|
|
|
*(*it) >> v;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
bool readAt(const std::string& childTag, T* v) const {
|
|
|
|
bool readAt(int pos, T* v) const {
|
|
|
|
for(NodeList::const_iterator it = m_children.begin(); it != m_children.end(); ++it) {
|
|
|
|
if(Node* node = at(pos)) {
|
|
|
|
if((*it)->tag() == childTag)
|
|
|
|
node->read<T>(v);
|
|
|
|
return (*(*it) >> *v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// read values
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
T read() const {
|
|
|
|
|
|
|
|
T v;
|
|
|
|
|
|
|
|
read<T>(&v);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
T readAt(const std::string& childTag) const {
|
|
|
|
|
|
|
|
if(Node* node = at(childTag))
|
|
|
|
|
|
|
|
return node->read<T>();
|
|
|
|
|
|
|
|
throw Exception(generateErrorMessage("child node " + childTag + " not found"));
|
|
|
|
|
|
|
|
return T();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
T readAt(int pos) const {
|
|
|
|
|
|
|
|
if(Node* node = at(pos))
|
|
|
|
|
|
|
|
return node->read<T>();
|
|
|
|
|
|
|
|
throw Exception(generateErrorMessage("child node at pos " + fml_int2str(pos) + " not found"));
|
|
|
|
|
|
|
|
return T();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// read values with defaults
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
T readAt(const std::string& childTag, const T& def) const {
|
|
|
|
|
|
|
|
if(Node* node = at(childTag))
|
|
|
|
|
|
|
|
return node->read<T>();
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
T readAt(int pos, const T& def) const {
|
|
|
|
|
|
|
|
if(Node* node = at(pos))
|
|
|
|
|
|
|
|
return node->read<T>();
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addNode(Node* node);
|
|
|
|
void addNode(Node* node);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string emitValue();
|
|
|
|
|
|
|
|
std::string emit(int depth = 0);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
Parser* m_parser;
|
|
|
|
Parser* m_parser;
|
|
|
|
Node* m_parent;
|
|
|
|
Node* m_parent;
|
|
|
@ -140,32 +205,29 @@ bool operator >> (const Node& node, T& v)
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
bool operator >> (const Node& node, std::vector<T>& v)
|
|
|
|
bool operator >> (const Node& node, std::vector<T>& v)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
std::vector<T>& tmp;
|
|
|
|
v.clear();
|
|
|
|
tmp.resize(node.size());
|
|
|
|
v.resize(node.size());
|
|
|
|
for(unsigned i=0;i<node.size();++i)
|
|
|
|
for(unsigned i=0;i<node.size();++i) {
|
|
|
|
v[i] = node.readAt<T>(i);
|
|
|
|
if(!(*node.at(i) >> v[i]))
|
|
|
|
v = tmp;
|
|
|
|
ret = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename K, typename T>
|
|
|
|
template <typename K, typename T>
|
|
|
|
bool operator >> (const Node& node, std::map<K, T>& m)
|
|
|
|
bool operator >> (const Node& node, std::map<K, T>& m)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
std::map<K, T> tmp;
|
|
|
|
m.clear();
|
|
|
|
|
|
|
|
for(Node::const_iterator it = node.begin(); it != node.end(); ++it) {
|
|
|
|
for(Node::const_iterator it = node.begin(); it != node.end(); ++it) {
|
|
|
|
Node* child = (*it);
|
|
|
|
|
|
|
|
K k;
|
|
|
|
K k;
|
|
|
|
T v;
|
|
|
|
T v;
|
|
|
|
if(fml_convert<std::string, K>(child->tag(), k)) {
|
|
|
|
if(fml_convert<std::string, K>((*it)->tag(), k)) {
|
|
|
|
*child >> v;
|
|
|
|
(*it)->read(&v);
|
|
|
|
m[k] = v;
|
|
|
|
tmp[k] = v;
|
|
|
|
ret = false;
|
|
|
|
} else
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
m = tmp;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -186,12 +248,10 @@ public:
|
|
|
|
Parser(std::istream& in, std::string what = std::string()) : m_rootNode(0), m_what(what) { load(in); }
|
|
|
|
Parser(std::istream& in, std::string what = std::string()) : m_rootNode(0), m_what(what) { load(in); }
|
|
|
|
~Parser();
|
|
|
|
~Parser();
|
|
|
|
|
|
|
|
|
|
|
|
bool load(std::istream& in);
|
|
|
|
void load(std::istream& in);
|
|
|
|
|
|
|
|
|
|
|
|
Node* getDocument() const { return m_rootNode; }
|
|
|
|
Node* getDocument() const { return m_rootNode; }
|
|
|
|
bool hasError() const { return !m_error.empty(); }
|
|
|
|
std::string what() { return m_what; }
|
|
|
|
std::string getErrorMessage() { return m_error; }
|
|
|
|
|
|
|
|
std::string getWhat() { return m_what; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
protected:
|
|
|
|
void parseLine(std::string& line);
|
|
|
|
void parseLine(std::string& line);
|
|
|
@ -203,7 +263,7 @@ protected:
|
|
|
|
bool parseMultiline(std::string line);
|
|
|
|
bool parseMultiline(std::string line);
|
|
|
|
bool isMultilining() { return m_multilineMode != DONT_MULTILINE; }
|
|
|
|
bool isMultilining() { return m_multilineMode != DONT_MULTILINE; }
|
|
|
|
|
|
|
|
|
|
|
|
void setErrorMessage(const std::string& message, int line = 0);
|
|
|
|
void throwError(const std::string& message, int line = 0);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
int m_currentDepth;
|
|
|
|
int m_currentDepth;
|
|
|
@ -213,7 +273,6 @@ private:
|
|
|
|
Node* m_rootNode;
|
|
|
|
Node* m_rootNode;
|
|
|
|
MultilineMode m_multilineMode;
|
|
|
|
MultilineMode m_multilineMode;
|
|
|
|
std::string m_multilineData;
|
|
|
|
std::string m_multilineData;
|
|
|
|
std::string m_error;
|
|
|
|
|
|
|
|
std::string m_what;
|
|
|
|
std::string m_what;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|