mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 11:12:29 +00:00
feat(xml): add XML functions
This commit is contained in:
parent
125ffec928
commit
4e43886e37
142 changed files with 68501 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ file(GLOB COMMON_SOURCES
|
|||
"ref/*.cpp"
|
||||
"string/*.cpp"
|
||||
"thread/*.cpp"
|
||||
"xml/*.cpp"
|
||||
)
|
||||
|
||||
add_library(common STATIC
|
||||
|
|
@ -18,5 +19,6 @@ target_include_directories(common
|
|||
|
||||
target_link_libraries(common
|
||||
PUBLIC
|
||||
expat-2.0
|
||||
storm
|
||||
)
|
||||
|
|
|
|||
8
common/XML.hpp
Normal file
8
common/XML.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef COMMON_XML_HPP
|
||||
#define COMMON_XML_HPP
|
||||
|
||||
#include "xml/XMLAttribute.hpp"
|
||||
#include "xml/XMLNode.hpp"
|
||||
#include "xml/XMLTree.hpp"
|
||||
|
||||
#endif
|
||||
8
common/xml/Expat.hpp
Normal file
8
common/xml/Expat.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef COMMON_XML_EXPAT_HPP
|
||||
#define COMMON_XML_EXPAT_HPP
|
||||
|
||||
extern "C" {
|
||||
#include "expat.h"
|
||||
}
|
||||
|
||||
#endif
|
||||
13
common/xml/XMLAttribute.hpp
Normal file
13
common/xml/XMLAttribute.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef COMMON_XML_XML_ATTRIBUTE_HPP
|
||||
#define COMMON_XML_XML_ATTRIBUTE_HPP
|
||||
|
||||
#include "common/String.hpp"
|
||||
|
||||
class XMLAttribute {
|
||||
public:
|
||||
// Member variables
|
||||
RCString m_name;
|
||||
RCString m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
83
common/xml/XMLNode.cpp
Normal file
83
common/xml/XMLNode.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include "common/xml/XMLNode.hpp"
|
||||
#include <storm/String.hpp>
|
||||
|
||||
XMLNode::XMLNode() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
XMLNode::~XMLNode() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const char* XMLNode::GetAttributeByName(const char* name) {
|
||||
for (int32_t i = 0; i < this->m_attributes.Count(); i++) {
|
||||
auto& attribute = this->m_attributes[i];
|
||||
|
||||
if (!SStrCmpI(attribute.m_name.GetString(), name, STORM_MAX_STR)) {
|
||||
return attribute.m_value.GetString();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* XMLNode::GetBody() const {
|
||||
return this->m_body;
|
||||
}
|
||||
|
||||
XMLNode* XMLNode::GetChildByName(const char* name) {
|
||||
auto child = this->m_child;
|
||||
|
||||
if (!child) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (SStrCmpI(child->m_name.GetString(), name, STORM_MAX_STR)) {
|
||||
child = child->m_next;
|
||||
|
||||
if (!child) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
const char* XMLNode::GetName() {
|
||||
return this->m_name.GetString();
|
||||
}
|
||||
|
||||
void XMLNode::Init(XMLNode* parent, const char* name) {
|
||||
RCString(this->m_name);
|
||||
TSGrowableArray<XMLAttribute>(this->m_attributes);
|
||||
this->m_parent = parent;
|
||||
this->m_child = nullptr;
|
||||
this->m_name.Copy(name);
|
||||
this->m_body = nullptr;
|
||||
this->m_bodyLen = 0;
|
||||
|
||||
if (this->m_parent && this->m_parent->m_body) {
|
||||
this->m_next = nullptr;
|
||||
this->m_userData = nullptr;
|
||||
this->m_offset = this->m_parent->m_bodyLen;
|
||||
} else {
|
||||
this->m_offset = 0;
|
||||
this->m_next = nullptr;
|
||||
this->m_userData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void XMLNode::SetAttribute(const char* name, const char* value) {
|
||||
auto attributeCount = this->m_attributes.Count();
|
||||
|
||||
for (int32_t i = 0; i < attributeCount; i++) {
|
||||
if (!SStrCmpI(name, this->m_attributes[i].m_name.GetString(), STORM_MAX_STR)) {
|
||||
this->m_attributes[i].m_value.Copy(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_attributes.SetCount(attributeCount + 1);
|
||||
this->m_attributes[attributeCount].m_name.Copy(name);
|
||||
this->m_attributes[attributeCount].m_value.Copy(value);
|
||||
}
|
||||
33
common/xml/XMLNode.hpp
Normal file
33
common/xml/XMLNode.hpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef COMMON_XML_XML_NODE_HPP
|
||||
#define COMMON_XML_XML_NODE_HPP
|
||||
|
||||
#include "common/String.hpp"
|
||||
#include "common/xml/XMLAttribute.hpp"
|
||||
#include <cstdint>
|
||||
#include <storm/Array.hpp>
|
||||
|
||||
class XMLNode {
|
||||
public:
|
||||
// Member variables
|
||||
void* m_userData;
|
||||
XMLNode* m_parent;
|
||||
XMLNode* m_child;
|
||||
RCString m_name;
|
||||
char* m_body;
|
||||
uint32_t m_bodyLen;
|
||||
TSGrowableArray<XMLAttribute> m_attributes;
|
||||
uint32_t m_offset;
|
||||
XMLNode* m_next;
|
||||
|
||||
// Member functions
|
||||
XMLNode();
|
||||
~XMLNode();
|
||||
const char* GetAttributeByName(const char* name);
|
||||
const char* GetBody() const;
|
||||
XMLNode* GetChildByName(const char* name);
|
||||
const char* GetName();
|
||||
void Init(XMLNode* parent, const char* name);
|
||||
void SetAttribute(const char* name, const char* value);
|
||||
};
|
||||
|
||||
#endif
|
||||
140
common/xml/XMLTree.cpp
Normal file
140
common/xml/XMLTree.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#include "common/xml/XMLTree.hpp"
|
||||
#include "common/xml/Expat.hpp"
|
||||
#include "common/xml/XMLNode.hpp"
|
||||
|
||||
XML_Parser XMLTreeParser;
|
||||
void* XMLNodeFreeList = nullptr;
|
||||
|
||||
void begin_element(void* userData, const XML_Char* name, const XML_Char** atts) {
|
||||
auto tree = static_cast<XMLTree*>(userData);
|
||||
|
||||
XMLNode* node;
|
||||
if (XMLNodeFreeList) {
|
||||
// TODO allocate node off of free list
|
||||
} else {
|
||||
// TODO allocate node off of node heap
|
||||
// XMLNode* node = XMLNode::s_XMLNodeHeap->GetData(0, __FILE__, __LINE__);
|
||||
|
||||
node = new XMLNode;
|
||||
node->Init(tree->leaf, name);
|
||||
}
|
||||
|
||||
auto leaf = tree->leaf;
|
||||
|
||||
if (leaf) {
|
||||
XMLNode* child = leaf->m_child;
|
||||
|
||||
if (child) {
|
||||
for (; child->m_next; child = child->m_next)
|
||||
;
|
||||
child->m_next = node;
|
||||
} else {
|
||||
leaf->m_child = node;
|
||||
}
|
||||
} else {
|
||||
tree->root = node;
|
||||
}
|
||||
|
||||
tree->leaf = node;
|
||||
|
||||
const char** v9 = atts;
|
||||
int32_t attCount = 0;
|
||||
|
||||
// Count attributes
|
||||
if (*atts) {
|
||||
do {
|
||||
v9 += 2;
|
||||
attCount++;
|
||||
} while (*v9);
|
||||
}
|
||||
|
||||
node->m_attributes.SetCount(attCount);
|
||||
|
||||
for (int32_t i = 0; i < attCount; i++) {
|
||||
node->m_attributes[i].m_name.Copy(atts[i * 2]);
|
||||
node->m_attributes[i].m_value.Copy(atts[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void end_element(void* userData, const XML_Char* name) {
|
||||
XMLTree* tree = static_cast<XMLTree*>(userData);
|
||||
|
||||
tree->leaf = tree->leaf->m_parent;
|
||||
}
|
||||
|
||||
void handle_body(void* userData, const XML_Char* s, int32_t len) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
XMLTree* tree = static_cast<XMLTree*>(userData);
|
||||
|
||||
XMLNode* node = tree->leaf;
|
||||
|
||||
if (!node->m_body) {
|
||||
// Only set initial body if string contains non-whitespace
|
||||
char v3;
|
||||
int32_t v6 = 0;
|
||||
|
||||
while (1) {
|
||||
v3 = s[v6];
|
||||
|
||||
if (v3 != ' ' && v3 != '\t' && v3 != '\r' && v3 != '\n') {
|
||||
break;
|
||||
}
|
||||
|
||||
v6++;
|
||||
|
||||
if (v6 >= len) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate / expand if necessary
|
||||
char* v7 = static_cast<char*>(SMemReAlloc(node->m_body, node->m_bodyLen + len + 1, __FILE__, __LINE__, 0x0));
|
||||
node->m_body = v7;
|
||||
|
||||
// Append character data to end of existing body
|
||||
char* v8 = &v7[node->m_bodyLen];
|
||||
memcpy(v8, s, len);
|
||||
node->m_bodyLen += len;
|
||||
|
||||
// Null terminate the body
|
||||
node->m_body[node->m_bodyLen] = '\0';
|
||||
}
|
||||
|
||||
void XMLTree_Free(XMLTree* tree) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
XMLNode* XMLTree_GetRoot(XMLTree* tree) {
|
||||
return tree->root;
|
||||
}
|
||||
|
||||
XMLTree* XMLTree_Load(const char* data, uint32_t length) {
|
||||
XMLTree* tree = static_cast<XMLTree*>(SMemAlloc(sizeof(XMLTree), __FILE__, __LINE__, 0x8));
|
||||
|
||||
if (XMLTreeParser) {
|
||||
XML_ParserReset(XMLTreeParser, nullptr);
|
||||
} else {
|
||||
XMLTreeParser = XML_ParserCreate(nullptr);
|
||||
}
|
||||
|
||||
XML_SetElementHandler(XMLTreeParser, begin_element, end_element);
|
||||
XML_SetCharacterDataHandler(XMLTreeParser, handle_body);
|
||||
XML_SetUserData(XMLTreeParser, tree);
|
||||
|
||||
if (XML_Parse(XMLTreeParser, data, length, 1)) {
|
||||
return tree;
|
||||
} else {
|
||||
if (tree->root) {
|
||||
// TODO
|
||||
// root->Recycle();
|
||||
}
|
||||
|
||||
SMemFree(tree, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
21
common/xml/XMLTree.hpp
Normal file
21
common/xml/XMLTree.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef COMMON_XML_XML_TREE_HPP
|
||||
#define COMMON_XML_XML_TREE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class XMLNode;
|
||||
|
||||
struct XMLTree {
|
||||
XMLNode* root;
|
||||
XMLNode* leaf;
|
||||
};
|
||||
|
||||
void XMLTree_Cleanup();
|
||||
|
||||
void XMLTree_Free(XMLTree* tree);
|
||||
|
||||
XMLNode* XMLTree_GetRoot(XMLTree* tree);
|
||||
|
||||
XMLTree* XMLTree_Load(const char* data, uint32_t length);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue