diff options
Diffstat (limited to 'common/refarray')
-rw-r--r-- | common/refarray/ref_array.c | 122 | ||||
-rw-r--r-- | common/refarray/ref_array.h | 44 | ||||
-rw-r--r-- | common/refarray/ref_array_ut.c | 117 |
3 files changed, 258 insertions, 25 deletions
diff --git a/common/refarray/ref_array.c b/common/refarray/ref_array.c index a571804..464ac30 100644 --- a/common/refarray/ref_array.c +++ b/common/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,10 +466,81 @@ 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, + 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 = ra->cb; + new_ra->cb_data = ra->cb_data; + + for (idx = 0; idx < ra->len; idx++) { + if (copy_cb) { + THIS IS BROKEN!!! + 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) { diff --git a/common/refarray/ref_array.h b/common/refarray/ref_array.h index 4b4b2de..4012116 100644 --- a/common/refarray/ref_array.h +++ b/common/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,27 @@ 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[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, + struct ref_array **copy_ra); + + /** * @} */ diff --git a/common/refarray/ref_array_ut.c b/common/refarray/ref_array_ut.c index 6e6009a..2b6f27c 100644 --- a/common/refarray/ref_array_ut.c +++ b/common/refarray/ref_array_ut.c @@ -560,7 +560,123 @@ 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 = ≠ + + 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; + + 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)); + + 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)); + + 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)); + + 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)); + + 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)); + + 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)); + + 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)); + + RAOUT(printf("\n\nTest 1 - Printing lines.\n\n")); + + error = ref_array_copy(ra, copy_cb, &ra2); + if (error) { + ref_array_destroy(ra); + printf("Failed to get length %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; + } + } + + 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 +685,7 @@ 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, NULL }; test_fn t; int i = 0; |