src/model.c: making node research use hashtable

This commit is contained in:
Adrien Bourmault 2024-03-25 23:07:01 +02:00
parent b2cd2c2fca
commit 1ea9a356a9
Signed by: neox
GPG Key ID: 95F65F55F682A17A
1 changed files with 37 additions and 34 deletions

View File

@ -40,6 +40,42 @@ struct model_t *knownModels = NULL;
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/**
* Recursively populates a hash table with XML nodes, using the node paths as keys.
*
* @param node The current node being processed.
* @param hashTable The hash table to populate.
* @param currentPath The path to the current node.
*/
void model_populate_hashtable(xmlNode *node,
xmlHashTablePtr hashTable,
char *currentPath) {
if (node == NULL) return;
// Skip text nodes and others that are not element nodes
if (node->type != XML_ELEMENT_NODE) {
model_populate_hashtable(node->next, hashTable, currentPath);
return;
}
// Calculate new path
char newPath[1024]; // large enough
if (currentPath && strlen(currentPath) > 0) {
snprintf(newPath, sizeof(newPath), "%s/%s", currentPath, node->name);
} else {
snprintf(newPath, sizeof(newPath), "%s", node->name); // Root element
}
// Add current node to hash table with its path as the key
xmlHashAddEntry(hashTable, (const xmlChar *)newPath, node);
// Recurse into child nodes with the updated path
model_populate_hashtable(node->children, hashTable, newPath);
// Continue with the next sibling
model_populate_hashtable(node->next, hashTable, currentPath);
}
/* /*
* Finds a node by a path of tags. * Finds a node by a path of tags.
* *
@ -48,40 +84,7 @@ struct model_t *knownModels = NULL;
* @return The content of the tag at the end of the path, or NULL if not found. * @return The content of the tag at the end of the path, or NULL if not found.
*/ */
char* model_find_node_by_path(xmlNode *node, const char *path) { char* model_find_node_by_path(xmlNode *node, const char *path) {
char *pathCopy = strdup(path); // Duplicate path to modify it return (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar *)path);
char *tag = strtok(pathCopy, "/"); // Get the first tag in the path
xmlNode *currentNode = node;
while (tag != NULL && currentNode != NULL) {
xmlNode *foundNode = NULL;
// Search for the tag at the current level
for (xmlNode *child = currentNode->children; child; child = child->next) {
if (child->type == XML_ELEMENT_NODE && strcmp((const char *)child->name, tag) == 0) {
foundNode = child; // Tag found at the current level
break;
}
}
tag = strtok(NULL, "/"); // Move to the next tag in the path
// If there are more tags to find, continue with the found node's children
if (tag != NULL && foundNode != NULL) {
currentNode = foundNode;
} else {
// If this was the last tag, try to get its content
if (foundNode != NULL && tag == NULL) {
char *content = (char *)xmlNodeGetContent(foundNode);
free(pathCopy);
return content;
}
currentNode = NULL; // End loop if tag not found
}
}
free(pathCopy);
return NULL; // Path not fully matched
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */