summaryrefslogtreecommitdiffstats
path: root/refarray
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2010-11-25 17:36:36 -0500
committerStephen Gallagher <sgallagh@redhat.com>2010-12-21 11:16:08 -0500
commit8c201905d5f0720b62d036eb2308f81f4530cfad (patch)
tree3a556b7c4881e04bbd266a92d322005918223b0a /refarray
parent86564695945fa1892fe990ba8b7bbc1af70cc48a (diff)
downloadding-libs-8c201905d5f0720b62d036eb2308f81f4530cfad.tar.gz
ding-libs-8c201905d5f0720b62d036eb2308f81f4530cfad.tar.xz
ding-libs-8c201905d5f0720b62d036eb2308f81f4530cfad.zip
Adding ref_array copy method
* Added a method to copy ref array * Added unit test to check copy functionality * Took advantage of the new trace macros * Reworked the debug function to be able to trace arrays with different types of data.
Diffstat (limited to 'refarray')
-rw-r--r--refarray/ref_array.c135
-rw-r--r--refarray/ref_array.h50
-rw-r--r--refarray/ref_array_ut.c210
3 files changed, 355 insertions, 40 deletions
diff --git a/refarray/ref_array.c b/refarray/ref_array.c
index e9482de..4b23d42 100644
--- a/refarray/ref_array.c
+++ b/refarray/ref_array.c
@@ -48,7 +48,7 @@ static int ref_array_grow(struct ref_array *ra)
int error = EOK;
void *newbuf = NULL;
- TRACE_FLOW_STRING("ref_array_grow", "Entry");
+ TRACE_FLOW_ENTRY();
TRACE_INFO_NUMBER("Current length: ", ra->len);
TRACE_INFO_NUMBER("Current size: ", ra->size);
@@ -83,7 +83,7 @@ int ref_array_create(struct ref_array **ra,
{
struct ref_array *new_ra = NULL;
- TRACE_FLOW_STRING("ref_array_create", "Entry");
+ TRACE_FLOW_ENTRY();
if (!ra) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
@@ -113,14 +113,14 @@ int ref_array_create(struct ref_array **ra,
*ra = new_ra;
- TRACE_FLOW_STRING("ref_array_create", "Exit");
+ TRACE_FLOW_EXIT();
return EOK;
}
/* Get new reference to an array */
struct ref_array *ref_array_getref(struct ref_array *ra)
{
- TRACE_FLOW_STRING("ref_array_getref", "Entry");
+ TRACE_FLOW_ENTRY();
/* Check if array is not NULL */
if (ra) {
@@ -134,7 +134,7 @@ struct ref_array *ref_array_getref(struct ref_array *ra)
TRACE_ERROR_STRING("Uninitialized array.", "Returning NULL");
}
- TRACE_FLOW_STRING("ref_array_getref", "Exit");
+ TRACE_FLOW_EXIT();
return ra;
}
@@ -143,7 +143,7 @@ void ref_array_destroy(struct ref_array *ra)
{
int idx;
- TRACE_FLOW_STRING("ref_array_destroy", "Entry");
+ TRACE_FLOW_ENTRY();
/* Check if array is not NULL */
if (!ra) {
@@ -175,7 +175,7 @@ void ref_array_destroy(struct ref_array *ra)
TRACE_ERROR_STRING("Reference count is 0.", "Coding error???");
}
- TRACE_FLOW_STRING("ref_array_destroy", "Exit");
+ TRACE_FLOW_EXIT();
}
/* Add new element to the array */
@@ -183,7 +183,8 @@ int ref_array_append(struct ref_array *ra, void *element)
{
int error = EOK;
- TRACE_FLOW_STRING("ref_array_append", "Entry");
+ TRACE_FLOW_ENTRY();
+
if ((!ra) || (!element)) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
return EINVAL;
@@ -205,14 +206,14 @@ int ref_array_append(struct ref_array *ra, void *element)
ra->len++;
- TRACE_FLOW_STRING("ref_array_append", "Exit");
+ TRACE_FLOW_EXIT();
return error;
}
/* Get element */
void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr)
{
- TRACE_FLOW_STRING("ref_array_get", "Entry");
+ TRACE_FLOW_ENTRY();
if (!ra) {
TRACE_ERROR_STRING("Uninitialized argument.", "");
@@ -235,7 +236,7 @@ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr)
}
- TRACE_FLOW_STRING("ref_array_get returning internal storage", "Exit");
+ TRACE_FLOW_EXIT();
return (unsigned char *)(ra->storage) + idx * ra->elsize;
}
@@ -243,7 +244,7 @@ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr)
/* Get length */
int ref_array_getlen(struct ref_array *ra, uint32_t *len)
{
- TRACE_FLOW_STRING("ref_array_getlen", "Entry");
+ TRACE_FLOW_ENTRY();
if ((!ra) || (!len)) {
TRACE_ERROR_STRING("Uninitialized argument.", "");
@@ -252,14 +253,14 @@ int ref_array_getlen(struct ref_array *ra, uint32_t *len)
*len = ra->len;
- TRACE_FLOW_STRING("ref_array_getlen", "Exit");
+ TRACE_FLOW_EXIT();
return EOK;
}
/* Alternative function to get length */
uint32_t ref_array_len(struct ref_array *ra)
{
- TRACE_FLOW_STRING("ref_array_len", "Entry");
+ TRACE_FLOW_ENTRY();
if (!ra) {
TRACE_ERROR_STRING("Uninitialized argument.", "");
@@ -267,7 +268,7 @@ uint32_t ref_array_len(struct ref_array *ra)
return 0;
}
- TRACE_FLOW_STRING("ref_array_len", "Exit");
+ TRACE_FLOW_EXIT();
return ra->len;
}
@@ -280,7 +281,7 @@ int ref_array_insert(struct ref_array *ra,
int error = EOK;
uint32_t i;
- TRACE_FLOW_STRING("ref_array_insert", "Entry");
+ TRACE_FLOW_ENTRY();
if ((!ra) || (!element)) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
@@ -315,7 +316,7 @@ int ref_array_insert(struct ref_array *ra,
ra->len++;
- TRACE_FLOW_STRING("ref_array_insert", "Exit");
+ TRACE_FLOW_EXIT();
return error;
}
@@ -328,7 +329,7 @@ int ref_array_replace(struct ref_array *ra,
{
int error = EOK;
- TRACE_FLOW_STRING("ref_array_replace", "Entry");
+ TRACE_FLOW_ENTRY();
if ((!ra) || (!element)) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
@@ -351,7 +352,7 @@ int ref_array_replace(struct ref_array *ra,
ra->elsize);
- TRACE_FLOW_STRING("ref_array_replace", "Exit");
+ TRACE_FLOW_EXIT();
return error;
}
@@ -363,7 +364,7 @@ int ref_array_remove(struct ref_array *ra,
int error = EOK;
uint32_t i;
- TRACE_FLOW_STRING("ref_array_remove", "Entry");
+ TRACE_FLOW_ENTRY();
if (!ra) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
@@ -389,7 +390,7 @@ int ref_array_remove(struct ref_array *ra,
ra->len--;
- TRACE_FLOW_STRING("ref_array_remove", "Exit");
+ TRACE_FLOW_EXIT();
return error;
}
@@ -398,7 +399,7 @@ void ref_array_reset(struct ref_array *ra)
{
int idx;
- TRACE_FLOW_STRING("ref_array_reset", "Entry");
+ TRACE_FLOW_ENTRY();
/* Check if array is not NULL */
if (!ra) {
@@ -418,7 +419,7 @@ void ref_array_reset(struct ref_array *ra)
ra->size = 0;
ra->len = 0;
- TRACE_FLOW_STRING("ref_array_reset", "Exit");
+ TRACE_FLOW_EXIT();
}
/* Swap two elements in the array */
@@ -429,7 +430,7 @@ int ref_array_swap(struct ref_array *ra,
int error = EOK;
void *temp = NULL;
- TRACE_FLOW_STRING("ref_array_swap", "Entry");
+ TRACE_FLOW_ENTRY();
if (!ra) {
TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
@@ -465,12 +466,84 @@ int ref_array_swap(struct ref_array *ra,
free(temp);
- TRACE_FLOW_STRING("ref_array_swap", "Exit");
+ TRACE_FLOW_EXIT();
+ return error;
+}
+
+/* Copy array */
+int ref_array_copy(struct ref_array *ra,
+ ref_array_copy_cb copy_cb,
+ ref_array_fn cb,
+ void *data,
+ struct ref_array **copy_ra)
+{
+ int error = EOK;
+ int idx;
+ struct ref_array *new_ra = NULL;
+ void *src;
+ void *dst;
+
+ TRACE_FLOW_ENTRY();
+
+ /* Check if array is not NULL */
+ if ((!ra) || (!copy_ra)) {
+ TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
+ return EINVAL;
+ }
+
+ new_ra = (struct ref_array *)malloc(sizeof(struct ref_array));
+ if (!new_ra) {
+ TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
+ return ENOMEM;
+ }
+
+ new_ra->storage = calloc(ra->size, ra->elsize);
+ if (!(new_ra->storage)) {
+ TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
+ free(new_ra);
+ return ENOMEM;
+ }
+
+ new_ra->elsize = ra->elsize;
+ new_ra->size = ra->size;
+ new_ra->grow_by = ra->grow_by;
+ new_ra->len = 0;
+ new_ra->refcount = 1;
+ new_ra->cb = cb;
+ new_ra->cb_data = data;
+
+ for (idx = 0; idx < ra->len; idx++) {
+ if (copy_cb) {
+ src = (void *)((unsigned char *)(ra->storage) + idx * ra->elsize);
+ dst = (void *)((unsigned char *)(new_ra->storage) +
+ idx * new_ra->elsize);
+
+ error = copy_cb(src, (void *)(dst));
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to copy data.", error);
+ ref_array_destroy(new_ra);
+ return error;
+ }
+ }
+ else {
+ memcpy((unsigned char *)(new_ra->storage) + idx * new_ra->elsize,
+ (unsigned char *)(ra->storage) + idx * ra->elsize,
+ new_ra->elsize);
+ }
+ (new_ra->len)++;
+ }
+
+
+ *copy_ra = new_ra;
+
+ TRACE_FLOW_EXIT();
return error;
}
+
+
/* Debug function */
-void ref_array_debug(struct ref_array *ra)
+void ref_array_debug(struct ref_array *ra, int num)
{
int i,j;
@@ -485,7 +558,15 @@ void ref_array_debug(struct ref_array *ra)
for (j = 0; j < ra->elsize; j++) {
printf("%x", *((unsigned char *)(ra->storage) + i * ra->elsize + j));
}
- printf("\n%s\n", *((char **)((unsigned char *)(ra->storage) + i * ra->elsize)));
+ if (num == 0) {
+ printf("\n%s\n", *((char **)((unsigned char *)(ra->storage) + i * ra->elsize)));
+ }
+ else if (num > 0) {
+ printf("\n%d\n", *((uint32_t *)((unsigned char *)(ra->storage) + i * ra->elsize)));
+ }
+ else {
+ printf("\nIt is an object.\n");
+ }
}
printf("\nARRAY DUMP END\n\n");
}
diff --git a/refarray/ref_array.h b/refarray/ref_array.h
index 0040fe4..d271d38 100644
--- a/refarray/ref_array.h
+++ b/refarray/ref_array.h
@@ -83,11 +83,34 @@ typedef enum
*
* Callback that can be provided by a caller
* to free data when the storage is actually destroyed.
+ *
+ * @param[in] elem Pointer to the array element.
+ * @param[in] type Type of the operation performed.
+ * @param[in] data Application data that can be used
+ * inside the callback.
+ * No return value.
*/
typedef void (*ref_array_fn)(void *elem,
ref_array_del_enum type,
void *data);
+/**
+ * @brief Copy callback
+ *
+ * Callback that can be provided by a caller
+ * to copy elements of the array.
+ *
+ * @param[in] elem Pointer to the array element.
+ * @param[out] new_elem Pointer to pointer to the new element.
+ *
+ * @return 0 - Success.
+ * @return ENOMEM - No memory.
+ * @return EINVAL - Invalid argument.
+ *
+ * Callback can return other errors and the implementor's discretion.
+ */
+typedef int (*ref_array_copy_cb)(void *elem,
+ void *new_elem);
/**
* @brief Create referenced array
@@ -313,6 +336,33 @@ int ref_array_swap(struct ref_array *ra,
*/
void ref_array_reset(struct ref_array *ra);
+
+/**
+ * @brief Copy array
+ *
+ * Function copies all contents calling a provided
+ * callback for every entry of the array.
+ *
+ *
+ * @param[in] ra Existing array object to copy.
+ * @param[in] copy_cb Copy callback.
+ * @param[in] cb Cleanup callback, will be used
+ * to clean data in the array copy.
+ * @param[in] data Caller supplied data
+ * passed to cleanup callback.
+ * @param[out] copy_ra Newly allocated copy.
+ *
+ * @return 0 - Success.
+ * @return ENOMEM - No memory.
+ * @return EINVAL - Invalid argument.
+ */
+int ref_array_copy(struct ref_array *ra,
+ ref_array_copy_cb copy_cb,
+ ref_array_fn cb,
+ void *data,
+ struct ref_array **copy_ra);
+
+
/**
* @}
*/
diff --git a/refarray/ref_array_ut.c b/refarray/ref_array_ut.c
index 6e6009a..5347634 100644
--- a/refarray/ref_array_ut.c
+++ b/refarray/ref_array_ut.c
@@ -36,7 +36,7 @@ int verbose = 0;
if (verbose) foo; \
} while(0)
-extern void ref_array_debug(struct ref_array *ra);
+extern void ref_array_debug(struct ref_array *ra, int num);
typedef int (*test_fn)(void);
@@ -65,7 +65,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line1);
if (error) {
@@ -74,7 +74,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line2);
if (error) {
@@ -83,7 +83,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line3);
if (error) {
@@ -92,7 +92,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line4);
if (error) {
@@ -101,7 +101,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line5);
if (error) {
@@ -110,7 +110,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line6);
if (error) {
@@ -119,7 +119,7 @@ int ref_array_basic_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
RAOUT(printf("\n\nTest 1 - Printing lines.\n\n"));
@@ -247,7 +247,7 @@ int ref_array_free_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
str = strdup(line1);
@@ -258,7 +258,7 @@ int ref_array_free_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
str = strdup(line2);
@@ -269,7 +269,7 @@ int ref_array_free_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
str = strdup(line3);
@@ -280,7 +280,7 @@ int ref_array_free_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
str = strdup(line4);
@@ -291,7 +291,7 @@ int ref_array_free_test(void)
return error;
}
- RAOUT(ref_array_debug(ra));
+ RAOUT(ref_array_debug(ra, 0));
i = 0;
for (;;) {
@@ -560,7 +560,189 @@ int ref_array_adv_test(void)
return EOK;
}
+int copy_cb(void *elem,
+ void *new_elem)
+{
+ char *ne = NULL;
+
+ ne = strdup(*((char **)elem));
+ *((char **)new_elem) = ne;
+
+ RAOUT(printf("Source: %s\nCopy:%s\n", *((char **)elem), ne));
+
+
+ return EOK;
+}
+
+int ref_array_copy_test(void)
+{
+ const char *line1 = "line1";
+ const char *line2 = "line2";
+ const char *line3 = "line3";
+ const char *line4 = "line4";
+ const char *line5 = "line5";
+ const char *line6 = "line6";
+ uint32_t i;
+ struct ref_array *ra;
+ struct ref_array *ra2;
+ int error = EOK;
+ uint32_t len = 0;
+ char text[] = "Deleting: ";
+
+ error = ref_array_create(&ra, sizeof(char *), 1, NULL, NULL);
+ if (error) {
+ printf("Failed to create array %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line1);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 1 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line2);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 2 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line3);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 3 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line4);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 4 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line5);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 5 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ error = ref_array_append(ra, &line6);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append to array line 6 %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 0));
+
+ RAOUT(printf("\n\nCopy lines.\n\n"));
+
+ error = ref_array_copy(ra, copy_cb, array_cleanup, (char *)text, &ra2);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to copy array %d\n", error);
+ return error;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (strcmp(ref_array_get(ra, i, NULL),
+ ref_array_get(ra2, i, NULL)) != 0) {
+ printf("\nRetrieved strings were expected to be same,\n");
+ printf("but they are not:\n");
+ printf("First:[%s]\nSecond:[%s]\n",
+ (char *)ref_array_get(ra, i, NULL),
+ (char *)ref_array_get(ra2, i, NULL));
+ ref_array_destroy(ra);
+ ref_array_destroy(ra2);
+ return EFAULT;
+ }
+ }
+
+ RAOUT(printf("\n\nSource array.\n\n"));
+ RAOUT(ref_array_debug(ra, 0));
+ ref_array_destroy(ra);
+
+ RAOUT(printf("\n\nAbout to destroy a copy.\n\n"));
+ RAOUT(ref_array_debug(ra2, 0));
+ ref_array_destroy(ra2);
+
+ RAOUT(printf("\n\nDone!!!\n\n"));
+ return EOK;
+
+}
+
+int ref_array_copy_num_test(void)
+{
+ uint32_t i,j,k;
+ struct ref_array *ra;
+ struct ref_array *ra2;
+ int error = EOK;
+ uint32_t len = 0;
+
+ error = ref_array_create(&ra, sizeof(uint32_t), 1, NULL, NULL);
+ if (error) {
+ printf("Failed to create array %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 1));
+
+ for (i=0; i<5; i++) {
+ error = ref_array_append(ra, &i);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to append number to array %d\n", error);
+ return error;
+ }
+
+ RAOUT(ref_array_debug(ra, 1));
+ }
+ RAOUT(printf("\n\nCopy num test.\n\n"));
+
+ error = ref_array_copy(ra, NULL, NULL, NULL, &ra2);
+ if (error) {
+ ref_array_destroy(ra);
+ printf("Failed to copy array %d\n", error);
+ return error;
+ }
+
+ for (i = 0; i < len; i++) {
+ j = *((uint32_t *)(ref_array_get(ra, i, NULL)));
+ k = *((uint32_t *)(ref_array_get(ra2, i, NULL)));
+ if (j != k) {
+ printf("\nRetrieved values were expected to be same,\n");
+ printf("but they are not:\n");
+ printf("First:[%d]\nSecond:[%d]\n", j, k);
+ ref_array_destroy(ra);
+ ref_array_destroy(ra2);
+ return EFAULT;
+ }
+ }
+
+ ref_array_destroy(ra);
+ ref_array_destroy(ra2);
+
+ RAOUT(printf("\n\nDone!!!\n\n"));
+ return EOK;
+
+}
/* Main function of the unit test */
int main(int argc, char *argv[])
@@ -569,6 +751,8 @@ int main(int argc, char *argv[])
test_fn tests[] = { ref_array_basic_test,
ref_array_free_test,
ref_array_adv_test,
+ ref_array_copy_test,
+ ref_array_copy_num_test,
NULL };
test_fn t;
int i = 0;