145 lines
4.5 KiB
C++
145 lines
4.5 KiB
C++
#ifndef CODERS_XML_HPP_
|
|
#define CODERS_XML_HPP_
|
|
|
|
#include "commons.hpp"
|
|
|
|
#include <string>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <glm/glm.hpp>
|
|
#include <unordered_map>
|
|
|
|
namespace xml {
|
|
class Node;
|
|
class Attribute;
|
|
class Document;
|
|
|
|
using xmlattribute = Attribute;
|
|
using xmlelement = std::shared_ptr<Node>;
|
|
using xmldocument = std::shared_ptr<Document>;
|
|
using xmlelements_map = std::unordered_map<std::string, xmlattribute>;
|
|
|
|
class Attribute {
|
|
std::string name;
|
|
std::string text;
|
|
public:
|
|
Attribute() {};
|
|
Attribute(std::string name, std::string text);
|
|
|
|
const std::string& getName() const;
|
|
const std::string& getText() const;
|
|
int64_t asInt() const;
|
|
double asFloat() const;
|
|
bool asBool() const;
|
|
glm::vec2 asVec2() const;
|
|
glm::vec3 asVec3() const;
|
|
glm::vec4 asVec4() const;
|
|
glm::vec4 asColor() const;
|
|
};
|
|
|
|
/// @brief XML element class. Text element has tag 'text' and attribute 'text'
|
|
class Node {
|
|
std::string tag;
|
|
std::unordered_map<std::string, xmlattribute> attrs;
|
|
std::vector<xmlelement> elements;
|
|
public:
|
|
Node(std::string tag);
|
|
|
|
/// @brief Add sub-element
|
|
void add(const xmlelement& element);
|
|
|
|
/// @brief Set attribute value. Creates attribute if does not exists
|
|
/// @param name attribute name
|
|
/// @param text attribute value
|
|
void set(const std::string& name, const std::string &text);
|
|
|
|
/// @brief Get element tag
|
|
const std::string& getTag() const;
|
|
|
|
inline bool isText() const {
|
|
return getTag() == "#";
|
|
}
|
|
|
|
inline const std::string& text() const {
|
|
return attr("#").getText();
|
|
}
|
|
|
|
/// @brief Get attribute by name
|
|
/// @param name attribute name
|
|
/// @throws std::runtime_error if element has no attribute
|
|
/// @return xmlattribute - {name, value}
|
|
const xmlattribute& attr(const std::string& name) const;
|
|
|
|
/// @brief Get attribute by name
|
|
/// @param name attribute name
|
|
/// @param def default value will be returned wrapped in xmlattribute
|
|
/// if element has no attribute
|
|
/// @return xmlattribute - {name, value} or {name, def} if not found*/
|
|
xmlattribute attr(const std::string& name, const std::string& def) const;
|
|
|
|
/// @brief Check if element has attribute
|
|
/// @param name attribute name
|
|
bool has(const std::string& name) const;
|
|
|
|
/// @brief Get sub-element by index
|
|
/// @param index sub-element index
|
|
/// @throws std::out_of_range if an invalid index given
|
|
/// @return sub-element
|
|
xmlelement sub(size_t index);
|
|
|
|
/// @brief Get number of sub-elements
|
|
size_t size() const;
|
|
|
|
const std::vector<xmlelement>& getElements() const;
|
|
const xmlelements_map& getAttributes() const;
|
|
};
|
|
|
|
class Document {
|
|
xmlelement root = nullptr;
|
|
std::string version;
|
|
std::string encoding;
|
|
public:
|
|
Document(std::string version, std::string encoding);
|
|
|
|
void setRoot(const xmlelement &element);
|
|
xmlelement getRoot() const;
|
|
|
|
const std::string& getVersion() const;
|
|
const std::string& getEncoding() const;
|
|
};
|
|
|
|
class Parser : BasicParser {
|
|
xmldocument document;
|
|
|
|
xmlelement parseOpenTag();
|
|
xmlelement parseElement();
|
|
void parseDeclaration();
|
|
void parseComment();
|
|
std::string parseText();
|
|
std::string parseXMLName();
|
|
public:
|
|
Parser(std::string_view filename, std::string_view source);
|
|
|
|
xmldocument parse();
|
|
};
|
|
|
|
/// @brief Serialize XML Document to string
|
|
/// @param document serializing document
|
|
/// @param nice use human readable format (with indents and line-separators)
|
|
/// @param indentStr indentation characters sequence (default - 4 spaces)
|
|
/// @return XML string
|
|
extern std::string stringify(
|
|
const xmldocument& document,
|
|
bool nice=true,
|
|
const std::string& indentStr=" "
|
|
);
|
|
|
|
/// @brief Read XML Document from string
|
|
/// @param filename file name will be shown in error messages
|
|
/// @param source xml source code string
|
|
/// @return xml document
|
|
extern xmldocument parse(const std::string& filename, const std::string& source);
|
|
}
|
|
|
|
#endif // CODERS_XML_HPP_
|