src/model.c: making node research efficient and safe

This commit is contained in:
Adrien Bourmault 2024-03-24 22:04:07 +02:00
parent 19acd2672c
commit b2cd2c2fca
Signed by: neox
GPG Key ID: 95F65F55F682A17A
1 changed files with 35 additions and 71 deletions

View File

@ -2,7 +2,7 @@
// Model management module // // Model management module //
// // // //
// Copyright © 2021 Libre en Communs (contact@a-lec.org) // // Copyright © 2021 Libre en Communs (contact@a-lec.org) //
// Copyright © 2021 Adrien Bourmault (neox@a-lec.org) // // Copyright © 2021-2024 Adrien Bourmault (neox@a-lec.org) //
// // // //
// This file is part of gem-graph. // // This file is part of gem-graph. //
// // // //
@ -40,85 +40,49 @@ struct model_t *knownModels = NULL;
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
static inline xmlNodePtr getNextChild (xmlNodePtr node, xmlChar *last) /*
{ * Finds a node by a path of tags.
while (node != NULL && xmlStrcmp(node->name, last)) { *
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name); * @param node The starting node for the search.
node = node->next; * @param path The path to the tag, with '/' as the delimiter.
} * @return The content of the tag at the end of the path, or NULL if not found.
return node; */
} char* model_find_node_by_path(xmlNode *node, const char *path) {
char *pathCopy = strdup(path); // Duplicate path to modify it
char *tag = strtok(pathCopy, "/"); // Get the first tag in the path
xmlNode *currentNode = node;
static inline xmlChar* splitStrAtSlash (xmlChar *toSplit) while (tag != NULL && currentNode != NULL) {
{ xmlNode *foundNode = NULL;
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
return toSplit;
}
static inline xmlChar* getFirstTag (xmlChar *path) // Search for the tag at the current level
{ for (xmlNode *child = currentNode->children; child; child = child->next) {
xmlChar *preop = path; if (child->type == XML_ELEMENT_NODE && strcmp((const char *)child->name, tag) == 0) {
path = (xmlChar *)xmlStrchr(path, '/'); foundNode = child; // Tag found at the current level
path = xmlStrsub (path, 1, xmlStrlen(path)); break;
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
}
static inline xmlChar* getLastTag (xmlChar *path)
{
while ((ulong)xmlStrchr (path, '/'))
path = splitStrAtSlash ((xmlChar *)path);
// //printf("last tag in the path = <%s>\n", path);
return path; // which is no more the given path but only its last tag !
}
/* -------------------------------------------------------------------------- */
static xmlNodePtr model_get_node (struct model_t *self, xmlChar *path)
{
xmlNodePtr node;
xmlChar *extrait;
xmlChar *reste, *last, *affich;
// Lookup for node from path in hash table
node = xmlHashLookup(self->hashtable, path);
// Found a node in hash table
if (node) {
return node;
// no node found in hash table
} else {
reste = path;
affich = reste;
last = getLastTag(reste);
node = xmlDocGetRootElement(self->doc);
while (xmlStrchr (reste, '/')) {
extrait = getFirstTag(reste);
reste = splitStrAtSlash((xmlChar *)reste);
node = node->xmlChildrenNode;
node = getNextChild(node, extrait);
}
if(node && xmlStrcmp(node->name, last)) {
node = node->xmlChildrenNode;
while (node && xmlStrcmp(node->name, last)) {
node = node->next;
} }
xmlHashAddEntry (self->hashtable, path, node);
} }
return node; 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
}
} }
return NULL; free(pathCopy);
return NULL; // Path not fully matched
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
static inline long model_get_node_long_attrib (xmlNodePtr node, char *id) static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)