Expose node extended info. Add unit test for it.
This commit is contained in:
parent
648941cb15
commit
166f1d83bd
@ -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.
|
||||||
|
137
libisofs/node.c
137
libisofs/node.c
@ -69,19 +69,144 @@ void iso_node_unref(IsoNode *node)
|
|||||||
/* other kind of nodes does not need to delete anything here */
|
/* other kind of nodes does not need to delete anything here */
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
180
test/test_node.c
180
test/test_node.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user