src/model.c: making node research efficient and safe
This commit is contained in:
parent
19acd2672c
commit
b2cd2c2fca
104
src/model.c
104
src/model.c
|
@ -2,7 +2,7 @@
|
|||
// Model management module //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
|
@ -40,85 +40,49 @@ struct model_t *knownModels = NULL;
|
|||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline xmlNodePtr getNextChild (xmlNodePtr node, xmlChar *last)
|
||||
{
|
||||
while (node != NULL && xmlStrcmp(node->name, last)) {
|
||||
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name);
|
||||
node = node->next;
|
||||
/*
|
||||
* Finds a node by a path of tags.
|
||||
*
|
||||
* @param node The starting node for the search.
|
||||
* @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.
|
||||
*/
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline xmlChar* splitStrAtSlash (xmlChar *toSplit)
|
||||
{
|
||||
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
|
||||
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
|
||||
return toSplit;
|
||||
}
|
||||
tag = strtok(NULL, "/"); // Move to the next tag in the path
|
||||
|
||||
static inline xmlChar* getFirstTag (xmlChar *path)
|
||||
{
|
||||
xmlChar *preop = path;
|
||||
path = (xmlChar *)xmlStrchr(path, '/');
|
||||
path = xmlStrsub (path, 1, xmlStrlen(path));
|
||||
|
||||
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
|
||||
// If there are more tags to find, continue with the found node's children
|
||||
if (tag != NULL && foundNode != NULL) {
|
||||
currentNode = foundNode;
|
||||
} 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 this was the last tag, try to get its content
|
||||
if (foundNode != NULL && tag == NULL) {
|
||||
char *content = (char *)xmlNodeGetContent(foundNode);
|
||||
free(pathCopy);
|
||||
return content;
|
||||
}
|
||||
|
||||
if(node && xmlStrcmp(node->name, last)) {
|
||||
node = node->xmlChildrenNode;
|
||||
|
||||
while (node && xmlStrcmp(node->name, last)) {
|
||||
node = node->next;
|
||||
currentNode = NULL; // End loop if tag not found
|
||||
}
|
||||
xmlHashAddEntry (self->hashtable, path, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
free(pathCopy);
|
||||
return NULL; // Path not fully matched
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)
|
||||
|
|
Loading…
Reference in New Issue