From cbe944835cc0951a946d01f034b4d28ff9874a4e Mon Sep 17 00:00:00 2001 From: Syndamia Date: Thu, 26 May 2022 20:23:42 +0300 Subject: Added a small hard-coded XML parser --- Year 1/Object-oriented Programming/xml.cpp | 128 +++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Year 1/Object-oriented Programming/xml.cpp (limited to 'Year 1/Object-oriented Programming/xml.cpp') 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 +#include +#include + +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(); // ние сме на знак <, затова отиваме на следващия + + // предишния знак е <, тоест, ако сегашния е /, то имаме ), сега просто ще скипнем името му + 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(); +} -- cgit v1.3.1-23-gd82d