src/model.c: making node research efficient and safe
This commit is contained in:
parent
19acd2672c
commit
b2cd2c2fca
102
src/model.c
102
src/model.c
|
@ -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.
|
||||||
|
*/
|
||||||
|
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)
|
tag = strtok(NULL, "/"); // Move to the next tag in the path
|
||||||
{
|
|
||||||
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
|
|
||||||
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
|
|
||||||
return toSplit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline xmlChar* getFirstTag (xmlChar *path)
|
// If there are more tags to find, continue with the found node's children
|
||||||
{
|
if (tag != NULL && foundNode != NULL) {
|
||||||
xmlChar *preop = path;
|
currentNode = foundNode;
|
||||||
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
|
|
||||||
} else {
|
} else {
|
||||||
reste = path;
|
// If this was the last tag, try to get its content
|
||||||
affich = reste;
|
if (foundNode != NULL && tag == NULL) {
|
||||||
last = getLastTag(reste);
|
char *content = (char *)xmlNodeGetContent(foundNode);
|
||||||
node = xmlDocGetRootElement(self->doc);
|
free(pathCopy);
|
||||||
|
return content;
|
||||||
while (xmlStrchr (reste, '/')) {
|
|
||||||
extrait = getFirstTag(reste);
|
|
||||||
reste = splitStrAtSlash((xmlChar *)reste);
|
|
||||||
node = node->xmlChildrenNode;
|
|
||||||
node = getNextChild(node, extrait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node && xmlStrcmp(node->name, last)) {
|
currentNode = NULL; // End loop if tag not found
|
||||||
node = node->xmlChildrenNode;
|
|
||||||
|
|
||||||
while (node && xmlStrcmp(node->name, last)) {
|
|
||||||
node = node->next;
|
|
||||||
}
|
}
|
||||||
xmlHashAddEntry (self->hashtable, path, node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
free(pathCopy);
|
||||||
|
return NULL; // Path not fully matched
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)
|
static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)
|
||||||
|
|
Loading…
Reference in New Issue