aboutsummaryrefslogtreecommitdiff
path: root/src/xml/XmlParser.cpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-01-01 01:28:21 +0800
committercrupest <crupest@outlook.com>2022-01-01 01:28:21 +0800
commit96a93e17baaff2c2050eba2afada639e93001232 (patch)
tree4e1625c0004b711c0bcf5c774ad37b54e3975de1 /src/xml/XmlParser.cpp
parent4e92e8709b30c385e1a88d7d4f76c50ee4a3d736 (diff)
downloadcru-96a93e17baaff2c2050eba2afada639e93001232.tar.gz
cru-96a93e17baaff2c2050eba2afada639e93001232.tar.bz2
cru-96a93e17baaff2c2050eba2afada639e93001232.zip
...
Diffstat (limited to 'src/xml/XmlParser.cpp')
-rw-r--r--src/xml/XmlParser.cpp114
1 files changed, 102 insertions, 12 deletions
diff --git a/src/xml/XmlParser.cpp b/src/xml/XmlParser.cpp
index 23407d11..f24a7f68 100644
--- a/src/xml/XmlParser.cpp
+++ b/src/xml/XmlParser.cpp
@@ -1,27 +1,117 @@
#include "cru/xml/XmlParser.hpp"
+#include "cru/xml/XmlNode.hpp"
namespace cru::xml {
-XmlNode XmlParser::Parse() {
- if (!root_node_) {
- root_node_ = DoParse();
+XmlElementNode* XmlParser::Parse() {
+ if (!cache_) {
+ cache_ = DoParse();
}
- return *root_node_;
+ return static_cast<XmlElementNode*>(cache_->Clone());
}
-XmlNode XmlParser::DoParse() {
- XmlNode root(XmlNode::Type::Element);
- XmlNode* current = &root;
- int current_position = 0;
+char16_t XmlParser::Read1() {
+ if (current_position_ >= xml_.size()) {
+ throw XmlParsingException(u"Unexpected end of xml");
+ }
+ return xml_[current_position_++];
+}
+
+void XmlParser::ReadSpacesAndDiscard() {
+ while (current_position_ < xml_.size() &&
+ (xml_[current_position_] == ' ' || xml_[current_position_] == '\t' ||
+ xml_[current_position_] == '\n' || xml_[current_position_] == '\r')) {
+ ++current_position_;
+ }
+}
+
+String XmlParser::ReadSpaces() {
+ String spaces;
+ while (current_position_ < xml_.size() &&
+ (xml_[current_position_] == ' ' || xml_[current_position_] == '\t' ||
+ xml_[current_position_] == '\n' || xml_[current_position_] == '\r')) {
+ spaces += xml_[current_position_];
+ ++current_position_;
+ }
+ return spaces;
+}
+
+String XmlParser::ReadIdenitifier() {
+ String identifier;
+ while (current_position_ < xml_.size() &&
+ (xml_[current_position_] >= 'a' && xml_[current_position_] <= 'z' ||
+ xml_[current_position_] >= 'A' && xml_[current_position_] <= 'Z' ||
+ xml_[current_position_] >= '0' && xml_[current_position_] <= '9' ||
+ xml_[current_position_] == '_')) {
+ identifier += xml_[current_position_];
+ ++current_position_;
+ }
+ return identifier;
+}
+
+String XmlParser::ReadAttributeString() {
+ if (Read1() != '"') {
+ throw XmlParsingException(u"Expected \".");
+ }
+
+ String string;
+
+ while (true) {
+ char16_t c = Read1();
+
+ if (c == '"') {
+ break;
+ }
+
+ string += c;
+ }
+
+ return string;
+}
- // TODO: Implement this.
- while (current_position < xml_.size()) {
- switch (xml_[current_position]) {
+XmlElementNode* XmlParser::DoParse() {
+ while (current_position_ < xml_.size()) {
+ switch (xml_[current_position_]) {
case '<': {
+ ++current_position_;
+
+ if (Read1() == '/') {
+ } else {
+ ReadSpacesAndDiscard();
+
+ String tag = ReadIdenitifier();
+
+ XmlElementNode* node = new XmlElementNode(tag);
+
+ while (true) {
+ ReadSpacesAndDiscard();
+ if (Read1() == '>') {
+ break;
+ } else {
+ String attribute_name = ReadIdenitifier();
+
+ ReadSpacesAndDiscard();
+
+ if (Read1() != '=') {
+ throw XmlParsingException(u"Expected '='");
+ }
+
+ ReadSpacesAndDiscard();
+
+ String attribute_value = ReadAttributeString();
+
+ node->AddAttribute(attribute_name, attribute_value);
+ }
+ }
+
+ current_->AddChild(node);
+ current_ = node;
+ }
+
break;
}
}
}
- return root;
+ return pseudo_root_node_;
}
} // namespace cru::xml