Summary Files Commits Branches @commit @diff @stats
path: root / Year 1 / Object-oriented Programming
diff options
context:
space:
mode:
Commitcbe944835cc0951a946d01f034b4d28ff9874a4e (patch)
Author
 Syndamia <kamen.d.mladenov@protonmail.com>
2022-05-26 20:23:42 +0300
Committer
 Syndamia <kamen.d.mladenov@protonmail.com>
2022-05-26 20:23:42 +0300
Files08322248813ab2b1e072a978f1ea3ffe32b74630 /Year 1/Object-oriented Programming
uni-projects-cbe944835cc0951a946d01f034b4d28ff9874a4e.tar
uni-projects-cbe944835cc0951a946d01f034b4d28ff9874a4e.tar.gz
uni-projects-cbe944835cc0951a946d01f034b4d28ff9874a4e.zip
Parente4f64cec4b7c85b1e39c221a57bcab4cb1980d7d (diff)
Added a small hard-coded XML parser
1 files changed, 128 insertions, 0 deletions
-rw-r--r--Year 1/Object-oriented Programming/xml.cpp128
diff --git a/Year 1/Object-oriented Programming/xml.cpp b/Year 1/Object-oriented Programming/xml.cpp
new file mode 100644
index 0000000..720e838
--- /dev/null
+++ b/Year 1/Object-oriented Programming/xml.cpp
@@ -0,0 +1,128 @@
+/*
+ * This is a very simple, hard-coded and limited XML parser, which parses XML from file into local variable.
+ * Made for illustrative purposes.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <cstring>
+
+class Tag {
+public: // щото да не се занимавам с гетъри и сетъри
+ char name[64];
+ // char id[64];
+ char value[64];
+
+ Tag* children;
+ unsigned length;
+ unsigned count;
+
+private:
+ void copyFrom(const Tag& other) {
+ strncpy(name, other.name, 64);
+ strncpy(value, other.value, 64);
+ children = new Tag[other.length];
+ for (unsigned i = 0; i < other.count; i++)
+ children[i] = other.children[i];
+ length = other.length;
+ count = other.count;
+ }
+
+ void free() {
+ delete[] children;
+ }
+
+ void resize() {
+ if (length == 0) length = 4;
+
+ Tag* tmp = new Tag[length <<= 1];
+ for (unsigned i = 0; i < count; i++)
+ tmp[i] = children[i];
+ delete[] children;
+ children = tmp;
+ }
+public:
+ void addChild(const Tag& child) {
+ if (length == count)
+ resize();
+ children[count++] = child;
+ }
+
+ Tag() {
+ children = nullptr;
+ length = count = 0;
+ }
+
+ Tag(const Tag& other) {
+ copyFrom(other);
+ }
+
+ Tag& operator=(const Tag& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+ }
+
+ ~Tag() {
+ free();
+ }
+};
+
+void parseTag(Tag& root, std::ifstream& file) {
+ Tag newTag;
+
+ // Вземаме името на тага (все едно всичко между < и >)
+ // важно: предполагаме, че вече сме минали < и от сега до > е само името на тага
+ char buffer = '<';
+ for (unsigned i = 0; i < 63 && file.peek() != '>'; i++) {
+ buffer = file.get();
+ newTag.name[i] = buffer;
+ newTag.name[i + 1] = '\0';
+ }
+ file.get(); // ние сме на знак >, затова отиваме на следващия
+
+ // ако следващия не е <, то имаме някаква стойност, която ще запазим
+ for (unsigned i = 0; i < 63 && file.peek() != '<'; i++) {
+ buffer = file.get();
+ newTag.value[i] = buffer;
+ newTag.value[i + 1] = '\0';
+ }
+ file.get(); // ние сме на знак <, затова отиваме на следващия
+
+ // предишния знак е <, тоест, ако сегашния е /, то имаме </ и значи край на обекта
+ // иначе, означава, че четем името на някое дете
+ while (file.peek() != '/') {
+ parseTag(newTag, file);
+ }
+ // значи, намираме се в затварящ таг (</ ... >), сега просто ще скипнем името му
+ for (unsigned i = 0; file.peek() != '>'; i++)
+ file.get();
+
+ file.get(); // знаем, че сме на >, затова отиваме на следващия
+ file.get(); // ако има съседни тагове, то в момента ще сме на <, затова и него го скипваме
+
+ root.addChild(newTag);
+}
+
+void printTag(Tag& tag, unsigned level = 0) {
+ for (unsigned i = 0; i < level; i++)
+ std::cout << " ";
+
+ std::cout << "<" << tag.name << ">" << " " << tag.value << std::endl;
+ level++;
+ for (unsigned i = 0; i < tag.count; i++)
+ printTag(tag.children[i], level);
+}
+
+int main() {
+ std::ifstream inFile("test.xml");
+ inFile.get();
+
+ Tag root;
+ parseTag(root, inFile);
+ printTag(root);
+
+ inFile.close();
+}