#ifndef FML_H #define FML_H #include #include #include #include #include #include #include namespace FML { /////////////////////////////////////////////////////////////////////////////// // Utilities bool fml_convert(const std::string& input, bool& b); bool fml_convert(const std::string& input, std::string& output); template bool fml_convert(const V& in, T& out) { std::stringstream ss; ss << in; ss >> out; return !!ss; } /////////////////////////////////////////////////////////////////////////////// // Node class Parser; class Node : boost::noncopyable { public: typedef std::vector NodeList; Node(Parser* parser = 0) : m_parser(parser), m_parent(0), m_line(0) { } ~Node(); bool hasTag() const { return !m_tag.empty(); } bool hasChildren() const { return size() > 0; } bool hasValue() const { return !m_value.empty(); } bool hasNode(const std::string childTag) const { return at(childTag) != 0; } void setTag(std::string tag) { m_tag = tag; } void setLine(int line) { m_line = line; } void setValue(const std::string& value) { m_value = value; } void setParent(Node* parent) { m_parent = parent; } std::string tag() const { return m_tag; } int line() const { return m_line; } int size() const { return m_children.size(); } Node* parent() { return m_parent; } // iterators typedef NodeList::iterator iterator; typedef NodeList::const_iterator const_iterator; iterator begin() { return m_children.begin(); } iterator end() { return m_children.end(); } const_iterator begin() const { return m_children.begin(); } const_iterator end() const { return m_children.end(); } Node* front() const { return at(0); } Node* back() const { return at(size()-1); } // util for generating error message std::string generateErrorMessage(const std::string& message) const; // extracting values operator template friend bool operator >> (const Node& node, T& value); // get nodes Node* at(const std::string& childTag) const; Node* at(int pos) const; // get values std::string value(const std::string& def = std::string()) const; std::string valueAt(const std::string childTag, const std::string& def = std::string()) const; // read values template T read(T def = T()) const { T v = def; *this >> v; return v; } template bool read(T* v) const { return (*this >> *v); } template T readAt(const std::string& childTag, T def = T()) const { T v = def; for(NodeList::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { if((*it)->tag() == childTag) { *(*it) >> v; break; } } return v; } template bool readAt(const std::string& childTag, T* v) const { for(NodeList::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { if((*it)->tag() == childTag) return (*(*it) >> *v); } return false; } void addNode(Node* node); private: Parser* m_parser; Node* m_parent; int m_line; NodeList m_children; std::string m_tag; std::string m_value; }; /////////////////////////////////////////////////////////////////////////////// // Node operators template bool operator >> (const Node& node, T& v) { return fml_convert(node.value(), v); } template bool operator >> (const Node& node, std::vector& v) { bool ret = true; v.clear(); v.resize(node.size()); for(unsigned i=0;i> v[i])) ret = false; } return ret; } template bool operator >> (const Node& node, std::map& m) { bool ret = true; m.clear(); for(Node::const_iterator it = node.begin(); it != node.end(); ++it) { Node* child = (*it); K k; T v; if(fml_convert(child->tag(), k)) { *child >> v; m[k] = v; ret = false; } } return ret; } /////////////////////////////////////////////////////////////////////////////// // Parser class Parser { enum MultilineMode { DONT_MULTILINE = 0, MULTILINE_DONT_FOLD, MULTILINE_FOLD_BLOCK, MULTILINE_FOLD_FLOW }; public: Parser(std::string what = std::string()) : m_rootNode(0), m_what(what) { } Parser(std::istream& in, std::string what = std::string()) : m_rootNode(0), m_what(what) { load(in); } ~Parser(); bool load(std::istream& in); Node* getDocument() const { return m_rootNode; } bool hasError() const { return !m_error.empty(); } std::string getErrorMessage() { return m_error; } std::string getWhat() { return m_what; } protected: void parseLine(std::string& line); Node* parseNode(std::string& line); std::string parseTextScalar(std::string value); void startMultilining(const std::string& param); void stopMultilining(); bool parseMultiline(std::string line); bool isMultilining() { return m_multilineMode != DONT_MULTILINE; } void setErrorMessage(const std::string& message, int line = 0); private: int m_currentDepth; int m_currentLine; Node* m_currentParent; Node* m_previousNode; Node* m_rootNode; MultilineMode m_multilineMode; std::string m_multilineData; std::string m_error; std::string m_what; }; } // namespace FML { #endif // FML_H