# HG changeset patch # User Mike Becker # Date 1374493549 -7200 # Node ID 7fb0f74517c5b3e36bdc6cb69071e06a518ba50e # Parent 540d99722f1f1aac6ab3f4e5f8daecc17f3dcc6e changed signature of sstrncat + some documentation for UcxList + new features for UcxList diff -r 540d99722f1f -r 7fb0f74517c5 test/list_tests.c --- a/test/list_tests.c Mon Jul 22 11:53:39 2013 +0200 +++ b/test/list_tests.c Mon Jul 22 13:45:49 2013 +0200 @@ -99,12 +99,13 @@ UCX_TEST_IMPLEMENT(test_ucx_list_size) { UcxList *list = ucx_list_append(NULL, (void*)"This "); - UCX_TEST_BEGIN list = ucx_list_append(list, (void*)"list "); list = ucx_list_append(list, (void*)"has "); list = ucx_list_append(list, (void*)"size "); list = ucx_list_append(list, (void*)"5!"); + UCX_TEST_BEGIN + UCX_TEST_ASSERT(ucx_list_size(list) == 5, "failed"); UCX_TEST_END @@ -113,10 +114,11 @@ UCX_TEST_IMPLEMENT(test_ucx_list_first) { UcxList *list = ucx_list_append(NULL, (void*)"Find "); - UCX_TEST_BEGIN list = ucx_list_append(list, (void*)"the "); list = ucx_list_append(list, (void*)"first!"); + UCX_TEST_BEGIN + const char* first = (const char*) (ucx_list_first(list)->data); UCX_TEST_ASSERT(strncmp(first, "Find ", 5) == 0, "failed"); @@ -127,10 +129,11 @@ UCX_TEST_IMPLEMENT(test_ucx_list_last) { UcxList *list = ucx_list_append(NULL, (void*)"Find "); - UCX_TEST_BEGIN list = ucx_list_append(list, (void*)"the "); list = ucx_list_append(list, (void*)"last!"); + UCX_TEST_BEGIN + const char* last = (const char*) (ucx_list_last(list)->data); UCX_TEST_ASSERT(strncmp(last, "last!", 5) == 0, "failed"); @@ -141,10 +144,11 @@ UCX_TEST_IMPLEMENT(test_ucx_list_get) { UcxList *list = ucx_list_append(NULL, (void*)"Find "); - UCX_TEST_BEGIN list = ucx_list_append(list, (void*)"the "); list = ucx_list_append(list, (void*)"mid!"); + UCX_TEST_BEGIN + const char* mid = (const char*) (ucx_list_get(list, 1)->data); UCX_TEST_ASSERT(strncmp(mid, "the ", 4) == 0, "failed"); @@ -153,14 +157,53 @@ ucx_list_free(list); } +UCX_TEST_IMPLEMENT(test_ucx_list_indexof) { + UcxList *list = ucx_list_append(NULL, (void*)"Find "); + list = ucx_list_append(list, (void*)"the "); + list = ucx_list_append(list, (void*)"mid!"); + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(ucx_list_indexof(list, list) == 0, "failed"); + UCX_TEST_ASSERT(ucx_list_indexof(list, list->next) == 1, "failed"); + UCX_TEST_ASSERT(ucx_list_indexof(list, ucx_list_get(list, 2)) == 2, + "failed"); + + UcxList *otherlist = ucx_list_append(NULL, (void*) "foobar"); + UCX_TEST_ASSERT(ucx_list_indexof(list, otherlist) == -1, "failed"); + ucx_list_free(otherlist); + + UCX_TEST_END + ucx_list_free(list); +} + +UCX_TEST_IMPLEMENT(test_ucx_list_find) { + UcxList *l = ucx_list_append(NULL, (void*)"find "); + l = ucx_list_append(l, (void*)"some "); + l = ucx_list_append(l, (void*)"string!"); + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(ucx_list_find(l,(void*)"some ",ucx_strcmp,NULL) == 1, + "doesn't find string"); + UCX_TEST_ASSERT(ucx_list_find(l,(void*)"a",ucx_strcmp,NULL) == -1, + "finds non-existing string"); + + UCX_TEST_END + ucx_list_free(l); +} + UCX_TEST_IMPLEMENT(test_ucx_list_contains) { UcxList *l = ucx_list_append(NULL, (void*)"Contains "); - UCX_TEST_BEGIN l = ucx_list_append(l, (void*)"a "); l = ucx_list_append(l, (void*)"string!"); - UCX_TEST_ASSERT(ucx_list_contains(l,(void*)"a ",ucx_strcmp,NULL),"failed"); - UCX_TEST_ASSERT(!ucx_list_contains(l,(void*)"a",ucx_strcmp,NULL),"failed"); + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(ucx_list_contains(l,(void*)"a ",ucx_strcmp,NULL), + "false negative"); + UCX_TEST_ASSERT(!ucx_list_contains(l,(void*)"a",ucx_strcmp,NULL), + "false positive"); UCX_TEST_END ucx_list_free(l); @@ -168,10 +211,11 @@ UCX_TEST_IMPLEMENT(test_ucx_list_remove) { UcxList *list = ucx_list_append(NULL, (void*)"Hello"); - UCX_TEST_BEGIN list = ucx_list_append(list, (void*)" fucking"); list = ucx_list_append(list, (void*)" World!"); + UCX_TEST_BEGIN + list = ucx_list_remove(list, ucx_list_get(list, 1)); UCX_TEST_ASSERT(strncmp((const char*)list->data, "Hello", 5) == 0, diff -r 540d99722f1f -r 7fb0f74517c5 test/list_tests.h --- a/test/list_tests.h Mon Jul 22 11:53:39 2013 +0200 +++ b/test/list_tests.h Mon Jul 22 13:45:49 2013 +0200 @@ -51,6 +51,8 @@ UCX_TEST_DECLARE(test_ucx_list_first); UCX_TEST_DECLARE(test_ucx_list_last); UCX_TEST_DECLARE(test_ucx_list_get); +UCX_TEST_DECLARE(test_ucx_list_indexof); +UCX_TEST_DECLARE(test_ucx_list_find); UCX_TEST_DECLARE(test_ucx_list_contains); UCX_TEST_DECLARE(test_ucx_list_remove); UCX_TEST_DECLARE(test_ucx_list_clone); diff -r 540d99722f1f -r 7fb0f74517c5 test/main.c --- a/test/main.c Mon Jul 22 11:53:39 2013 +0200 +++ b/test/main.c Mon Jul 22 13:45:49 2013 +0200 @@ -120,7 +120,7 @@ /* UcxLogger Tests */ ucx_test_register(suite, test_ucx_logger_log); - /* UcxDlist Tests */ + /* UcxList Tests */ ucx_test_register(suite, test_ucx_list_append); ucx_test_register(suite, test_ucx_list_prepend); ucx_test_register(suite, test_ucx_list_equals); @@ -129,6 +129,8 @@ ucx_test_register(suite, test_ucx_list_first); ucx_test_register(suite, test_ucx_list_last); ucx_test_register(suite, test_ucx_list_get); + ucx_test_register(suite, test_ucx_list_indexof); + ucx_test_register(suite, test_ucx_list_find); ucx_test_register(suite, test_ucx_list_contains); ucx_test_register(suite, test_ucx_list_remove); ucx_test_register(suite, test_ucx_list_clone); diff -r 540d99722f1f -r 7fb0f74517c5 test/string_tests.c --- a/test/string_tests.c Mon Jul 22 11:53:39 2013 +0200 +++ b/test/string_tests.c Mon Jul 22 13:45:49 2013 +0200 @@ -49,7 +49,7 @@ sstr_t cat; cat.ptr = (char*) malloc(16); cat.length = 16; - cat = sstrncat(3, cat, s1, s2, s3); + cat = sstrncat(cat, 3, s1, s2, s3); UCX_TEST_BEGIN diff -r 540d99722f1f -r 7fb0f74517c5 ucx/list.c --- a/ucx/list.c Mon Jul 22 11:53:39 2013 +0200 +++ b/ucx/list.c Mon Jul 22 13:45:49 2013 +0200 @@ -116,6 +116,18 @@ return (UcxList*)e; } +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) { + ssize_t index = 0; + while (list) { + if (list == elem) { + return index; + } + list = list->next; + index++; + } + return -1; +} + UcxList *ucx_list_get(const UcxList *l, int index) { if (l == NULL) return NULL; @@ -128,13 +140,19 @@ return (UcxList*)(index == 0 ? e : NULL); } -int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { +ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { + ssize_t index = 0; UCX_FOREACH(e, l) { - if (!fnc(elem, e->data, cmpdata)) { - return 1; + if (fnc(elem, e->data, cmpdata) == 0) { + return index; } + index++; } - return 0; + return -1; +} + +int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { + return ucx_list_find(l, elem, fnc, cmpdata) > -1; } size_t ucx_list_size(const UcxList *l) { diff -r 540d99722f1f -r 7fb0f74517c5 ucx/list.h --- a/ucx/list.h Mon Jul 22 11:53:39 2013 +0200 +++ b/ucx/list.h Mon Jul 22 13:45:49 2013 +0200 @@ -25,6 +25,13 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/** + * Double linked list implementation. + * + * @file list.h + * @author Mike Becker + * @author Olaf Wintermann + */ #ifndef UCX_LIST_H #define UCX_LIST_H @@ -52,30 +59,77 @@ #define UCX_FOREACH(elem,list) \ for (UcxList* elem = list ; elem != NULL ; elem = elem->next) +/** + * UCX list type + * @see UcxList + */ typedef struct UcxList UcxList; struct UcxList { + /** + * List element payload. + */ void *data; + /** + * Pointer to the next list element or NULL, if this is the + * last element. + */ UcxList *next; + /** + * Pointer to the previous list element or NULL, if this is + * the first element. + */ UcxList *prev; }; UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void* data); -int ucx_list_equals(const UcxList *l1, const UcxList *l2, - cmp_func fnc, void* data); + +/** + * Compares two UCX lists element-wise by using a compare function. + * + * Each element of the two specified lists are compared by using the specified + * compare function and the additional data. The type and content of this + * additional data depends on the cmp_func() used. + * + * If the list pointers denote elements within a list, the lists are compared + * starting with the denoted elements. Thus any previous elements are not taken + * into account. This might be useful to check, if certain list tails match + * each other. + * + * @param list1 the first list + * @param list2 the second list + * @param cmpfnc the compare function + * @param data additional data for the compare function + * @return 1, if and only if the two lists equal element-wise, 0 otherwise + */ +int ucx_list_equals(const UcxList *list1, const UcxList *list2, + cmp_func cmpfnc, void* data); -void ucx_list_free(UcxList *l); -UcxList *ucx_list_append(UcxList *l, void *data); -UcxList *ucx_list_prepend(UcxList *l, void *data); -UcxList *ucx_list_concat(UcxList *l1, UcxList *l2); -UcxList *ucx_list_last(const UcxList *l); -UcxList *ucx_list_get(const UcxList *l, int index); -size_t ucx_list_size(const UcxList *l); -int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata); +/** + * Destroys the entire list. + * + * The members of the list are not automatically freed, so ensure they are + * otherwise referenced or a memory leak will occur. + * + * Caution: the argument MUST denote an entire list (i.e. a call + * to ucx_list_first() on the argument must return the argument itself) + * + * @param list The list to free. + */ +void ucx_list_free(UcxList *list); +UcxList *ucx_list_append(UcxList *list, void *data); +UcxList *ucx_list_prepend(UcxList *list, void *data); +UcxList *ucx_list_concat(UcxList *list1, UcxList *list2); +UcxList *ucx_list_last(const UcxList *list); +UcxList *ucx_list_get(const UcxList *list, int index); +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem); +size_t ucx_list_size(const UcxList *list); +ssize_t ucx_list_find(UcxList *list, void *elem, cmp_func fnc, void *cmpdata); +int ucx_list_contains(UcxList *list, void *elem, cmp_func fnc, void *cmpdata); -UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data); +UcxList *ucx_list_sort(UcxList *list, cmp_func cmpfnc, void *data); -UcxList *ucx_list_first(const UcxList *l); -UcxList *ucx_list_remove(UcxList *l, UcxList *e); +UcxList *ucx_list_first(const UcxList *list); +UcxList *ucx_list_remove(UcxList *list, UcxList *element); #ifdef __cplusplus } diff -r 540d99722f1f -r 7fb0f74517c5 ucx/string.c --- a/ucx/string.c Mon Jul 22 11:53:39 2013 +0200 +++ b/ucx/string.c Mon Jul 22 13:45:49 2013 +0200 @@ -61,7 +61,7 @@ return size; } -sstr_t sstrncat(size_t n, sstr_t s, sstr_t c1, ...) { +sstr_t sstrncat(sstr_t s, size_t n, sstr_t c1, ...) { va_list ap; va_start(ap, c1); s.ptr[0] = 0; diff -r 540d99722f1f -r 7fb0f74517c5 ucx/string.h --- a/ucx/string.h Mon Jul 22 11:53:39 2013 +0200 +++ b/ucx/string.h Mon Jul 22 13:45:49 2013 +0200 @@ -142,14 +142,14 @@ * mystring.ptr[mystring.length]='\0' after calling this * function * - * + * + * @param dest new sstr_t with capacity information and allocated memory * @param count the total number of strings to concatenate - * @param dest new sstr_t with capacity information and allocated memory * @param src the first string * @param ... all other strings * @return the argument for dest is returned */ -sstr_t sstrncat(size_t count, sstr_t dest, sstr_t src, ...); +sstr_t sstrncat(sstr_t dest, size_t count, sstr_t src, ...); /**