WIP: devel : travail du mois de mars/avril #28
79
src/model.c
79
src/model.c
|
@ -38,27 +38,25 @@
|
||||||
|
|
||||||
struct model_t *knownModels = NULL;
|
struct model_t *knownModels = NULL;
|
||||||
|
|
||||||
static xmlHashTablePtr hashTable == NULL;
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively populates a hash table with XML nodes, using the node paths as keys.
|
* Recursively populates a hash table with XML nodes, using the node paths as keys.
|
||||||
*
|
*
|
||||||
|
* @param self The self structure containing hash table containing
|
||||||
|
* nodes indexed by their paths to populate
|
||||||
* @param node The current node being processed.
|
* @param node The current node being processed.
|
||||||
* @param hashTable The hash table to populate.
|
|
||||||
* @param currentPath The path to the current node.
|
* @param currentPath The path to the current node.
|
||||||
*/
|
*/
|
||||||
void model_populate_hashtable (xmlNode *node,
|
void model_populate_hashTable (struct model_t *self, xmlNode *node, char *currentPath)
|
||||||
char *currentPath)
|
|
||||||
{
|
{
|
||||||
if (node == NULL) return;
|
if (node == NULL) return;
|
||||||
|
|
||||||
assert(hashTable == NULL);
|
assert(self->hashTable == NULL);
|
||||||
|
|
||||||
// Skip text nodes and others that are not element nodes
|
// Skip text nodes and others that are not element nodes
|
||||||
if (node->type != XML_ELEMENT_NODE) {
|
if (node->type != XML_ELEMENT_NODE) {
|
||||||
model_populate_hashtable (node->next, hashTable, currentPath);
|
model_populate_hashTable (node->next, self->hashTable, currentPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,43 +69,46 @@ void model_populate_hashtable (xmlNode *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add current node to hash table with its path as the key
|
// Add current node to hash table with its path as the key
|
||||||
xmlHashAddEntry (hashTable, (const xmlChar *)newPath, node);
|
xmlHashAddEntry (self->hashTable, (const xmlChar *)newPath, node);
|
||||||
|
|
||||||
// Recurse into child nodes with the updated path
|
// Recurse into child nodes with the updated path
|
||||||
model_populate_hashtable (node->children, hashTable, newPath);
|
model_populate_hashTable (self, node->children, newPath);
|
||||||
|
|
||||||
// Continue with the next sibling
|
// Continue with the next sibling
|
||||||
model_populate_hashtable (node->next, hashTable, currentPath);
|
model_populate_hashTable (self, node->next, currentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds a node by a path of tags.
|
* Finds a node by a path of tags.
|
||||||
*
|
*
|
||||||
* @param node The starting node for the search.
|
* @param self The self structure containing hash table containing
|
||||||
|
* nodes indexed by their paths.
|
||||||
* @param path The path to the tag, with '/' as the delimiter.
|
* @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 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)
|
xmlNodePtr model_get_node (struct model_t *self, const char *path)
|
||||||
{
|
{
|
||||||
assert(hashTable != NULL);
|
assert(self->hashTable != NULL);
|
||||||
|
|
||||||
return (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar *)path);
|
return (xmlNodePtr)xmlHashLookup (self->hashTable, (const xmlChar *)path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifies the content of an XML node identified by its path in the hash table.
|
* Modifies the content of an XML node identified by its path in the hash table.
|
||||||
*
|
*
|
||||||
* @param hashTable The hash table containing the XML nodes.
|
* @param self The self structure containing hash table containing
|
||||||
|
* nodes indexed by their paths.
|
||||||
* @param path The path to the node to modify.
|
* @param path The path to the node to modify.
|
||||||
* @param newContent The new content to set for the node.
|
* @param newContent The new content to set for the node.
|
||||||
* @return 1 if the node was found and modified, 0 otherwise.
|
* @return 1 if the node was found and modified, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int model_modify_node (const char *path,
|
int model_modify_node (struct model_t *self,
|
||||||
|
const char *path,
|
||||||
const char *newContent)
|
const char *newContent)
|
||||||
{
|
{
|
||||||
assert(hashTable != NULL);
|
assert(self->hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = model_find_node_by_path(hashTable, path);
|
xmlNodePtr node = model_get_node (self, path);
|
||||||
if (node) {
|
if (node) {
|
||||||
// Free the current content of the node, if any
|
// Free the current content of the node, if any
|
||||||
xmlNodeSetContent (node, (const xmlChar *)""); // Clear existing content
|
xmlNodeSetContent (node, (const xmlChar *)""); // Clear existing content
|
||||||
|
@ -121,17 +122,19 @@ int model_modify_node (const char *path,
|
||||||
/**
|
/**
|
||||||
* Retrieves the value of an attribute for a node identified by its path.
|
* Retrieves the value of an attribute for a node identified by its path.
|
||||||
*
|
*
|
||||||
* @param hashTable The hash table containing nodes indexed by their paths.
|
* @param self The self structure containing hash table containing
|
||||||
|
* nodes indexed by their paths.
|
||||||
* @param nodePath The path to the node.
|
* @param nodePath The path to the node.
|
||||||
* @param attributeName The name of the attribute.
|
* @param attributeName The name of the attribute.
|
||||||
* @return The value of the attribute, or NULL if not found.
|
* @return The value of the attribute, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
char* model_get_attribute (const char* nodePath,
|
char *model_get_attribute (struct model_t *self,
|
||||||
|
const char* nodePath,
|
||||||
const char* attributeName)
|
const char* attributeName)
|
||||||
{
|
{
|
||||||
assert(hashTable != NULL);
|
assert(self->hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = (xmlNodePtr)xmlHashLookup (hashTable, (const xmlChar*)nodePath);
|
xmlNodePtr node = (xmlNodePtr)xmlHashLookup (self->hashTable, (const xmlChar*)nodePath);
|
||||||
if (node) {
|
if (node) {
|
||||||
return getAttributeValue (node, attributeName);
|
return getAttributeValue (node, attributeName);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,19 +145,21 @@ char* model_get_attribute (const char* nodePath,
|
||||||
/**
|
/**
|
||||||
* Sets or updates the value of an attribute for a node identified by its path.
|
* Sets or updates the value of an attribute for a node identified by its path.
|
||||||
*
|
*
|
||||||
* @param hashTable The hash table containing nodes indexed by their paths.
|
* @param self The self structure containing hash table containing
|
||||||
|
* nodes indexed by their paths.
|
||||||
* @param nodePath The path to the node.
|
* @param nodePath The path to the node.
|
||||||
* @param attributeName The name of the attribute to set.
|
* @param attributeName The name of the attribute to set.
|
||||||
* @param attributeValue The value to set for the attribute.
|
* @param attributeValue The value to set for the attribute.
|
||||||
* @return 1 on success, 0 on failure.
|
* @return 1 on success, 0 on failure.
|
||||||
*/
|
*/
|
||||||
int model_set_attribute (const char* nodePath,
|
int model_set_attribute (struct model_t *self,
|
||||||
|
const char* nodePath,
|
||||||
const char* attributeName,
|
const char* attributeName,
|
||||||
const char* attributeValue)
|
const char* attributeValue)
|
||||||
{
|
{
|
||||||
assert(hashTable != NULL);
|
assert(self->hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = (xmlNodePtr)xmlHashLookup (hashTable, (const xmlChar*)nodePath);
|
xmlNodePtr node = (xmlNodePtr)xmlHashLookup (self->hashTable, (const xmlChar*)nodePath);
|
||||||
if (node) {
|
if (node) {
|
||||||
return setAttributeValue (node, attributeName, attributeValue);
|
return setAttributeValue (node, attributeName, attributeValue);
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,12 +168,11 @@ int model_set_attribute (const char* nodePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies a node recursively to a new sibling node with a modified attribute and updates the hashtable.
|
* Copies a node recursively to a new sibling node with a modified attribute and updates the self->hashTable.
|
||||||
*
|
*
|
||||||
* @param doc The document to which the nodes belong.
|
|
||||||
* @param node The node to copy.
|
* @param node The node to copy.
|
||||||
* @param hashTable The hashtable for tracking nodes by path.
|
* @param self The self structure for tracking nodes by path.
|
||||||
* @param originalNodePath The path of the original node in the hashtable.
|
* @param originalNodePath The path of the original node in the self->hashTable.
|
||||||
* @param attributeName The name of the attribute to modify in the copied node.
|
* @param attributeName The name of the attribute to modify in the copied node.
|
||||||
* @param newAttributeValue The new value for the specified attribute in the copied node.
|
* @param newAttributeValue The new value for the specified attribute in the copied node.
|
||||||
* @return The copied node with the modified attribute, or NULL on failure.
|
* @return The copied node with the modified attribute, or NULL on failure.
|
||||||
|
@ -179,7 +183,7 @@ xmlNodePtr model_copy_node(struct model_t *self,
|
||||||
const char* attributeName,
|
const char* attributeName,
|
||||||
const char* newAttributeValue)
|
const char* newAttributeValue)
|
||||||
{
|
{
|
||||||
assert(hashTable != NULL);
|
assert(self->hashTable != NULL);
|
||||||
|
|
||||||
// Deep copy the node
|
// Deep copy the node
|
||||||
xmlNodePtr copiedNode = xmlDocCopyNode(node, self->doc, 1);
|
xmlNodePtr copiedNode = xmlDocCopyNode(node, self->doc, 1);
|
||||||
|
@ -197,8 +201,8 @@ xmlNodePtr model_copy_node(struct model_t *self,
|
||||||
char newPath[1024];
|
char newPath[1024];
|
||||||
snprintf (newPath, sizeof(newPath), "%s_copy", originalNodePath);
|
snprintf (newPath, sizeof(newPath), "%s_copy", originalNodePath);
|
||||||
|
|
||||||
// Update the hashtable with the new node's path
|
// Update the self->hashTable with the new node's path
|
||||||
xmlHashAddEntry (hashTable, (const xmlChar*)newPath, copiedNode);
|
xmlHashAddEntry (self->hashTable, (const xmlChar*)newPath, copiedNode);
|
||||||
|
|
||||||
return copiedNode;
|
return copiedNode;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +228,8 @@ xmlNodePtr model_copy_node(struct model_t *self,
|
||||||
* additional information to the callback function. It is passed
|
* additional information to the callback function. It is passed
|
||||||
* directly through to the callback function as its second argument.
|
* directly through to the callback function as its second argument.
|
||||||
*/
|
*/
|
||||||
void model_iterate_node(xmlNodePtr node,
|
void model_iterate_node(struct model_t *self,
|
||||||
|
xmlNodePtr node,
|
||||||
void (*processNode)(xmlNodePtr node, void* userData), void* userData)
|
void (*processNode)(xmlNodePtr node, void* userData), void* userData)
|
||||||
{
|
{
|
||||||
for (xmlNodePtr curNode = node->children; curNode; curNode = curNode->next) {
|
for (xmlNodePtr curNode = node->children; curNode; curNode = curNode->next) {
|
||||||
|
@ -308,9 +313,9 @@ static bool model_init(struct model_t *self)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->hashtable = xmlHashCreate(0);
|
model_populate_hashTable(self, node, "/");
|
||||||
|
|
||||||
if (self->hashtable == NULL) {
|
if (self->hashTable == NULL) {
|
||||||
printerr("Can't create model hash table !\n");
|
printerr("Can't create model hash table !\n");
|
||||||
xmlFreeDoc(self->doc);
|
xmlFreeDoc(self->doc);
|
||||||
return false;
|
return false;
|
||||||
|
@ -322,7 +327,7 @@ static bool model_init(struct model_t *self)
|
||||||
static bool model_shutdown(struct model_t *self)
|
static bool model_shutdown(struct model_t *self)
|
||||||
{
|
{
|
||||||
xmlFreeDoc(self->doc);
|
xmlFreeDoc(self->doc);
|
||||||
xmlHashFree(self->hashtable, NULL);
|
xmlHashFree(self->hashTable, NULL);
|
||||||
// This is to debug memory for regression tests
|
// This is to debug memory for regression tests
|
||||||
//xmlMemoryDump();
|
//xmlMemoryDump();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue