Expose node extended info. Add unit test for it.

This commit is contained in:
Vreixo Formoso 2008-03-15 17:34:58 +01:00
parent 648941cb15
commit 166f1d83bd
4 changed files with 384 additions and 14 deletions

View File

@ -1820,6 +1820,78 @@ void iso_node_unref(IsoNode *node);
*/ */
enum IsoNodeType iso_node_get_type(IsoNode *node); enum IsoNodeType iso_node_get_type(IsoNode *node);
/**
* Function to handle particular extended information. The function
* pointer acts as an identifier for the type of the information. Structs
* with same information type must use the same function.
*
* @param data
* Attached data
* @param flag
* What to do with the data. At this time the following values are
* defined:
* -> 1 the data must be freed
* @return
* 1 in any case.
*
* @since 0.6.4
*/
typedef int (*iso_node_xinfo_func)(void *data, int flag);
/**
* Add extended information to the given node. Extended info allows
* applications (and libisofs itself) to add more information to an IsoNode.
* You can use this facilities to associate new information with a given
* node.
*
* Each node keeps a list of added extended info, meaning you can add several
* extended info data to each node. Each extended info you add is identified
* by the proc parameter, a pointer to a function that knows how to manage
* the external info data. Thus, in order to add several types of extended
* info, you need to define a "proc" function for each type.
*
* @param node
* The node where to add the extended info
* @param proc
* A function pointer used to identify the type of the data, and that
* knows how to manage it
* @param data
* Extended info to add.
* @return
* 1 if success, 0 if the given node already has extended info of the
* type defined by the "proc" function, < 0 on error
*
* @since 0.6.4
*/
int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data);
/**
* Remove the given extended info (defined by the proc function) from the
* given node.
*
* @return
* 1 on success, 0 if node does not have extended info of the requested
* type, < 0 on error
*
* @since 0.6.4
*/
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc);
/**
* Get the given extended info (defined by the proc function) from the
* given node.
*
* @param data
* Will be filled with the extended info corresponding to the given proc
* function
* @return
* 1 on success, 0 if node does not have extended info of the requested
* type, < 0 on error
*
* @since 0.6.4
*/
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data);
/** /**
* Set the name of a node. Note that if the node is already added to a dir * Set the name of a node. Note that if the node is already added to a dir
* this can fail if dir already contains a node with the new name. * this can fail if dir already contains a node with the new name.

View File

@ -70,18 +70,143 @@ void iso_node_unref(IsoNode *node)
break; break;
} }
#ifdef LIBISO_EXTENDED_INFORMATION
if (node->xinfo) { if (node->xinfo) {
/* free extended info */ IsoExtendedInfo *info = node->xinfo;
node->xinfo->process(node->xinfo->data, 1); while (info != NULL) {
free(node->xinfo); IsoExtendedInfo *tmp = info->next;
/* free extended info */
info->process(info->data, 1);
free(info);
info = tmp;
}
} }
#endif
free(node->name); free(node->name);
free(node); free(node);
} }
} }
/**
* Add extended information to the given node. Extended info allows
* applications (and libisofs itself) to add more information to an IsoNode.
* You can use this facilities to associate new information with a given
* node.
*
* Each node keeps a list of added extended info, meaning you can add several
* extended info data to each node. Each extended info you add is identified
* by the proc parameter, a pointer to a function that knows how to manage
* the external info data. Thus, in order to add several types of extended
* info, you need to define a "proc" function for each type.
*
* @param node
* The node where to add the extended info
* @param proc
* A function pointer used to identify the type of the data, and that
* knows how to manage it
* @param data
* Extended info to add.
* @return
* 1 if success, 0 if the given node already has extended info of the
* type defined by the "proc" function, < 0 on error
*/
int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data)
{
IsoExtendedInfo *info;
IsoExtendedInfo *pos;
if (node == NULL || proc == NULL) {
return ISO_NULL_POINTER;
}
pos = node->xinfo;
while (pos != NULL) {
if (pos->process == proc) {
return 0; /* extended info already added */
}
pos = pos->next;
}
info = malloc(sizeof(IsoExtendedInfo));
if (info == NULL) {
return ISO_OUT_OF_MEM;
}
info->next = node->xinfo;
info->data = data;
info->process = proc;
node->xinfo = info;
return ISO_SUCCESS;
}
/**
* Remove the given extended info (defined by the proc function) from the
* given node.
*
* @return
* 1 on success, 0 if node does not have extended info of the requested
* type, < 0 on error
*/
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc)
{
IsoExtendedInfo *pos, *prev;
if (node == NULL || proc == NULL) {
return ISO_NULL_POINTER;
}
prev = NULL;
pos = node->xinfo;
while (pos != NULL) {
if (pos->process == proc) {
/* this is the extended info we want to remove */
pos->process(pos->data, 1);
if (prev != NULL) {
prev->next = pos->next;
} else {
node->xinfo = pos->next;
}
free(pos);
return ISO_SUCCESS;
}
prev = pos;
pos = pos->next;
}
/* requested xinfo not found */
return 0;
}
/**
* Get the given extended info (defined by the proc function) from the
* given node.
*
* @param data
* Will be filled with the extended info corresponding to the given proc
* function
* @return
* 1 on success, 0 if node does not have extended info of the requested
* type, < 0 on error
*/
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
{
IsoExtendedInfo *pos;
if (node == NULL || proc == NULL || data == NULL) {
return ISO_NULL_POINTER;
}
pos = node->xinfo;
while (pos != NULL) {
if (pos->process == proc) {
/* this is the extended info we want */
*data = pos->data;
return ISO_SUCCESS;
}
pos = pos->next;
}
/* requested xinfo not found */
return 0;
}
/** /**
* Get the type of an IsoNode. * Get the type of an IsoNode.
*/ */

View File

@ -20,9 +20,6 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
/* #define LIBISO_EXTENDED_INFORMATION */
#ifdef LIBISO_EXTENDED_INFORMATION
/** /**
* The extended information is a way to attach additional information to each * The extended information is a way to attach additional information to each
* IsoNode. External applications may want to use this extension system to * IsoNode. External applications may want to use this extension system to
@ -55,7 +52,7 @@ struct iso_extended_info {
* @return * @return
* 1 * 1
*/ */
int (*process)(void *data, int flag); iso_node_xinfo_func process;
/** /**
* Pointer to information specific data. * Pointer to information specific data.
@ -63,8 +60,6 @@ struct iso_extended_info {
void *data; void *data;
}; };
#endif
/** /**
* *
*/ */
@ -102,12 +97,10 @@ struct Iso_Node
*/ */
IsoNode *next; IsoNode *next;
#ifdef LIBISO_EXTENDED_INFORMATION
/** /**
* Extended information for the node. * Extended information for the node.
*/ */
IsoExtendedInfo *xinfo; IsoExtendedInfo *xinfo;
#endif
}; };
struct Iso_Dir struct Iso_Dir

View File

@ -1106,6 +1106,183 @@ void test_iso_node_set_name()
free(dir); free(dir);
} }
static
int xinfo_a(void *data, int flag) {
return 1;
}
static
int xinfo_b(void *data, int flag) {
return 1;
}
static
void test_iso_node_add_xinfo()
{
int result;
IsoNode *node;
/* cretae a node */
node = calloc(1, sizeof(IsoNode));
/* add xinfo data */
result = iso_node_add_xinfo(node, xinfo_a, NULL);
CU_ASSERT_EQUAL(result, 1);
/* we can't add again the same xinfo type */
result = iso_node_add_xinfo(node, xinfo_a, &result);
CU_ASSERT_EQUAL(result, 0);
result = iso_node_add_xinfo(node, xinfo_b, NULL);
CU_ASSERT_EQUAL(result, 1);
free(node->xinfo->next);
free(node->xinfo);
free(node);
}
static
void test_iso_node_get_xinfo()
{
int result;
IsoNode *node;
char *one_data = "my data";
char *another_data = "my data 2";
void *data;
/* cretae a node */
node = calloc(1, sizeof(IsoNode));
/* at the beginning we have no data */
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 0);
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 0);
/* add xinfo data */
result = iso_node_add_xinfo(node, xinfo_a, one_data);
CU_ASSERT_EQUAL(result, 1);
/* we get the correct data */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
/* we can't add again the same xinfo type */
result = iso_node_add_xinfo(node, xinfo_a, &result);
CU_ASSERT_EQUAL(result, 0);
/* we get the correct data again */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
/* xinfo_b has no data */
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 0);
/* add another xinfo */
result = iso_node_add_xinfo(node, xinfo_b, another_data);
CU_ASSERT_EQUAL(result, 1);
/* test both data is returned propertly */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, another_data);
free(node->xinfo->next);
free(node->xinfo);
free(node);
}
static
void test_iso_node_remove_xinfo()
{
int result;
IsoNode *node;
char *one_data = "my data";
char *another_data = "my data 2";
void *data;
/* cretae a node */
node = calloc(1, sizeof(IsoNode));
/* try to remove inexistent data */
result = iso_node_remove_xinfo(node, xinfo_b);
CU_ASSERT_EQUAL(result, 0);
result = iso_node_remove_xinfo(node, xinfo_a);
CU_ASSERT_EQUAL(result, 0);
/* add xinfo data */
result = iso_node_add_xinfo(node, xinfo_a, one_data);
CU_ASSERT_EQUAL(result, 1);
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
/* remove it */
result = iso_node_remove_xinfo(node, xinfo_b);
CU_ASSERT_EQUAL(result, 0);
result = iso_node_remove_xinfo(node, xinfo_a);
CU_ASSERT_EQUAL(result, 1);
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 0);
/* add again the same xinfo type */
result = iso_node_add_xinfo(node, xinfo_a, one_data);
CU_ASSERT_EQUAL(result, 1);
/* we get the correct data again */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
/* add another xinfo */
result = iso_node_add_xinfo(node, xinfo_b, another_data);
CU_ASSERT_EQUAL(result, 1);
/* test both data is returned propertly */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, another_data);
/* remove b */
result = iso_node_remove_xinfo(node, xinfo_b);
CU_ASSERT_EQUAL(result, 1);
/* only a can be get */
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 1);
CU_ASSERT_PTR_EQUAL(data, one_data);
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 0);
/* try to remove b again */
result = iso_node_remove_xinfo(node, xinfo_b);
CU_ASSERT_EQUAL(result, 0);
/* remove a */
result = iso_node_remove_xinfo(node, xinfo_a);
CU_ASSERT_EQUAL(result, 1);
result = iso_node_get_xinfo(node, xinfo_a, &data);
CU_ASSERT_EQUAL(result, 0);
result = iso_node_get_xinfo(node, xinfo_b, &data);
CU_ASSERT_EQUAL(result, 0);
free(node);
}
void add_node_suite() void add_node_suite()
{ {
CU_pSuite pSuite = CU_add_suite("Node Test Suite", NULL, NULL); CU_pSuite pSuite = CU_add_suite("Node Test Suite", NULL, NULL);
@ -1128,4 +1305,7 @@ void add_node_suite()
CU_add_test(pSuite, "iso_node_take()", test_iso_node_take); CU_add_test(pSuite, "iso_node_take()", test_iso_node_take);
CU_add_test(pSuite, "iso_node_take() during iteration", test_iso_dir_iter_when_external_take); CU_add_test(pSuite, "iso_node_take() during iteration", test_iso_dir_iter_when_external_take);
CU_add_test(pSuite, "iso_node_set_name()", test_iso_node_set_name); CU_add_test(pSuite, "iso_node_set_name()", test_iso_node_set_name);
CU_add_test(pSuite, "iso_node_add_xinfo()", test_iso_node_add_xinfo);
CU_add_test(pSuite, "iso_node_get_xinfo()", test_iso_node_get_xinfo);
CU_add_test(pSuite, "iso_node_remove_xinfo()", test_iso_node_remove_xinfo);
} }