static void pl_prepend_append_test(void) { printsln((Any)__func__); List ac, ex; ac = pl_create(); pl_append(ac, "11"); pl_append(ac, "22"); pl_append(ac, "33"); ex = pl_create(); pl_prepend(ex, "33"); pl_prepend(ex, "22"); pl_prepend(ex, "11"); pl_check_expect(ac, ex); l_free(ac); l_free(ex); }
void test_pl_create_delete(void) { int rc; pooled_list *pl = NULL; rc = pl_create(&pl, sizeof(my_message_t), ELEM_COUNT_DEFAULT); /* make sure object creation successful before proceeding */ CU_ASSERT_EQUAL_FATAL(rc, PL_SUCCESS); CU_ASSERT_PTR_NOT_NULL_FATAL(pl); /* Check all default internal values */ CU_ASSERT((int)pl->elem_size == (int)sizeof(my_message_t)); CU_ASSERT(pl->elem_count == ELEM_COUNT_DEFAULT); CU_ASSERT(pl->count_free == ELEM_COUNT_DEFAULT); CU_ASSERT(pl->count_total == ELEM_COUNT_DEFAULT); CU_ASSERT(pl->count_current == 0); /* Check address node list */ CU_ASSERT_PTR_NOT_NULL(pl->addr_list); /* address node exists */ CU_ASSERT_PTR_NULL(pl->addr_list->next); /* no second node */ CU_ASSERT_PTR_NOT_NULL(pl->addr_list->addr); /* memory block allocated */ CU_ASSERT_PTR_EQUAL(pl->active_memblock, pl->addr_list); /*active blk set*/ /* check datablock pointers */ CU_ASSERT_PTR_NULL(pl->head); /* head pointer unset */ CU_ASSERT_PTR_NULL(pl->tail); /* tail pointer unset */ CU_ASSERT_PTR_EQUAL(pl->next_free, pl->addr_list->addr); /* next_free set */ destroy_pl_object(&pl); }
static void pl_iterator_test(void) { printsln((Any)__func__); // various ways of iterating a list: List ac = pl_create(); pl_append(ac, "a"); pl_append(ac, "b"); pl_append(ac, "c"); ListIterator iter = l_iterator(ac); while (l_has_next(iter)) { Any s = pl_next(&iter); printsln(s); } // PointerListNode *first = (PointerListNode*)ac->first; for (PointerListNode *node = ac->first; node != NULL; node = node->next) { Any s = node->value; printsln(s); } #if 0 while (iter = pl_next(iter)) { Any d = pl_current(iter); printiln(d); } for (AnyListIterator iter = pl_iterator(ac); pl_has_current(iter); iter = pl_next(iter)) { Any d = pl_current(iter); printiln(d); } #endif l_free(ac); }
PointList open_spaces(Board b) { PointList pl = pl_create(); for (int r=0; r<BOARDSIZE; r++) { for (int c=0; c<BOARDSIZE; c++) { if (bget(b, r, c) == 0) pl_insert(pl, r, c); } } return pl; }
List pl_map(List list, AnyIntAnyToAny f, Any x) { assert_function_not_null(f); assert_argument_not_null(list); pl_assert_element_size(list); List result = pl_create(); int i = 0; for (PointerListNode *node = list->first; node != NULL; node = node->next, i++) { pl_append(result, f(node->value, i, x)); } return result; }
List pl_repeat(int n, Any value) { if (n < 0) { printf("%s: length cannot be negative (is %d)\n", __func__, n); exit(EXIT_FAILURE); } List list = pl_create(); for (int i = 0; i < n; i++) { pl_append(list, value); } return list; }
static void pl_repeat_test(void) { printsln((Any)__func__); List ac, ex; ac = pl_repeat(3, "abc"); ex = pl_create(); pl_append(ex, "abc"); pl_append(ex, "abc"); pl_append(ex, "abc"); // pl_println(ac); // pl_println(ex); pl_check_expect(ac, ex); l_free(ac); l_free(ex); ac = pl_repeat(0, "abc"); ex = pl_create(); pl_check_expect(ac, ex); l_free(ac); l_free(ex); }
List pl_filter(List list, AnyIntAnyToBool predicate, Any x) { assert_function_not_null(predicate); assert_argument_not_null(list); pl_assert_element_size(list); List result = pl_create(); int i = 0; for (PointerListNode *node = list->first; node != NULL; node = node->next, i++) { if (predicate(node->value, i, x)) { pl_append(result, node->value); } } return result; }
static void pl_print_test(void) { printsln((Any)__func__); List ac = pl_create(); pl_append(ac, "a"); pl_append(ac, "b"); pl_append(ac, "c"); pl_print(ac, print_elem); pl_println(ac, print_elem); l_free(ac); }
void test_pl_multisize(void) { int rc; int elem_count, elem_count2; pooled_list *pl = NULL; pooled_list *pl2 = NULL; /* use different memblock sizes ( >1 ) */ elem_count = ELEM_COUNT_DEFAULT + 50; elem_count2 = (int)(ELEM_COUNT_DEFAULT / 2) + 3; /* create first object */ rc = pl_create(&pl, sizeof(my_message_t), elem_count); CU_ASSERT_FATAL(rc == PL_SUCCESS); CU_ASSERT_PTR_NOT_NULL_FATAL(pl); /* create object of different size */ rc = pl_create(&pl2, sizeof(bigger_message_t), elem_count2); CU_ASSERT_FATAL(rc == PL_SUCCESS); CU_ASSERT_PTR_NOT_NULL_FATAL(pl2); /* make sure both have memory block allocated */ CU_ASSERT_PTR_NOT_NULL(pl->addr_list->addr); CU_ASSERT_PTR_NOT_NULL(pl2->addr_list->addr); /* make sure both have correct values assigned values */ CU_ASSERT((int)pl->count_total == elem_count); CU_ASSERT((int)pl->elem_count == elem_count); CU_ASSERT((int)pl->elem_size == (int)sizeof(my_message_t)); CU_ASSERT((int)pl2->count_total == elem_count2); CU_ASSERT((int)pl2->elem_count == elem_count2); CU_ASSERT((int)pl2->elem_size == (int)sizeof(bigger_message_t)); destroy_pl_object(&pl); destroy_pl_object(&pl2); }
/* test using invalid input */ void test_pl_create_invalid(void) { int rc; pooled_list *pl; /* trying invalid element size * size_t is unsigned. So we don't check for negative size */ rc = pl_create(&pl, (size_t)0, ELEM_COUNT_DEFAULT); CU_ASSERT(rc == PL_ERR_INVALID); CU_ASSERT_PTR_NULL(pl); pl_delete(&pl); /* trying invalid element counts */ rc = pl_create(&pl, sizeof(my_message_t), 0); CU_ASSERT(rc == PL_ERR_INVALID); CU_ASSERT_PTR_NULL(pl); pl_delete(&pl); rc = pl_create(&pl, sizeof(my_message_t), -1); CU_ASSERT(rc == PL_ERR_INVALID); CU_ASSERT_PTR_NULL(pl); pl_delete(&pl); }
static void pl_contains_test(void) { printsln((Any)__func__); String l1 = "10"; String l2 = "20"; String l3 = s_create("20"); List list = pl_create(); pl_append(list, l1); pl_append(list, l2); check_expect_b(pl_contains(list, l1), true); check_expect_b(pl_contains(list, l2), true); check_expect_b(pl_contains(list, l3), false); l_free(list); s_free(l3); }
static void pl_insert_test(void) { printsln((Any)__func__); List ac, ex; ac = sl_of_string("1, 2, 3, 4, 5"); pl_insert(ac, 0, s_create("9")); ex = sl_of_string("9, 1, 2, 3, 4, 5"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1, 2, 3, 4, 5"); pl_insert(ac, 5, s_create("9")); ex = sl_of_string("1, 2, 3, 4, 5, 9"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1, 2, 3, 4, 5"); pl_insert(ac, 3, s_create("9")); ex = sl_of_string("1, 2, 3, 9, 4, 5"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1"); pl_insert(ac, -1, "9"); ex = sl_of_string("1"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1"); pl_insert(ac, 1, s_create("9")); ex = sl_of_string("1, 9"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = pl_create(); pl_insert(ac, 0, s_create("9")); ex = sl_of_string("9"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); }
static void pl_index_test(void) { printsln((Any)__func__); String l1 = "10"; String l2 = "20"; String l3 = s_create("20"); List list = pl_create(); pl_append(list, l1); pl_append(list, l2); int i = pl_index(list, l3); #if 1 if (i < 0) { printsln("value not found"); } else { printf("value found at index %d\n", i); } #endif check_expect_i(i, -1); check_expect_i(pl_index(list, l1), 0); check_expect_i(pl_index(list, l2), 1); l_free(list); s_free(l3); }
/*! * \brief Creates a filtered and sorted Iterator for accessing a selection of * messages in the MessageBoard * \ingroup MB_API * \param[in] mb MessageBoard handle * \param[out] itr_ptr Address of Iterator Handle * \param[in] filterFunc Pointer to user-defined filter function * \param[in] filterFuncParams Pointer to input data that will be passed into \c filterFunc * \param[in] cmpFunc Pointer to user-defined compariosn function * * * The Iterator object is allocated and populated with messages from an array * returned by the \c get_sorted_filtered_ptr_list() (static function defined * in iterator_createfilteredsorted.c). The Iterator is then registered * with the ::MBI_OM_iterator and the reference ID returned by ObjectMap * is then written to \c itr_ptr as the handle. * * \c get_sorted_filtered_ptr_list() populates a message array by traversing * the MessageBoard and selecting messages that are accepted by \c filterFunc. * It then uses \c cmpFunc with \c qsort() (from \c stdlib.h) for sorting before * returning a pointer to the message array. * * The use of \c qsort() got a little * messy as we need to sort the list based on the \em value of the messages whereas * the array stores only \em pointers to those messages. For now, \c qsort() is given * \c ptrSort() -- a static function which dereferences the message pointers before * calling \c cmpFunc. The messy part is that \c cmpFunc cannot be passed to * \c ptrSort() as an argument (for compatibily with \c qsort()) so it has to be * handed over using a global variable (\c funcPtr). This global variable makes * our routine non thread-safe. * * * We expect \c filterFunc() to return a \c 0 if a message is to be rejected, * and a non-zero \c int if it is to be accepted. * * We expect \c cmpFunc() to return an integer * less than, equal to, or greater than zero if the first message is * considered to be respectively less than, equal to, or greater than the * second. In short: * - <tt>0 if (msg1 == msg2)</tt> * - <tt>\< 0 if (msg1 \< msg2)</tt> * - <tt>\> 0 if (msg1 \> msg2)</tt> * * References to messages are stored within a pooled_list and traversed as * a linked list. The memory block size for the Iterator pooled_list is chosen to * be half that of the default MessageBoard block size. * * Message references are stored in the same order they appear in the board. * * \note We only store pointers to message objects within the Iterator, and * not the actual messages. These pointers will be invalid if the * MessageBoard is deleted of modified. Checking the validity of * messages each time it is accessed would be too great an overhead. * * Possible return codes: * - ::MB_SUCCESS * - ::MB_ERR_INVALID (invalid or null board given) * - ::MB_ERR_MEMALLOC (error allocating memory for Iterator object or pooled_list) * - ::MB_ERR_LOCKED (\c mb is locked) * - ::MB_ERR_INTERNAL (possible bug. Recompile and run in debug mode for hints) * - ::MB_ERR_OVERFLOW (MessageBoard overflow. Too many Iterators created.) */ int MB_Iterator_CreateFilteredSorted(MBt_Board mb, MBt_Iterator *itr_ptr, \ int (*filterFunc)(const void *msg, const void *params), \ void *filterFuncParams, \ int (*cmpFunc)(const void *msg1, const void *msg2) ) { int rc, mcount, i, elemOut = 0; OM_key_t rc_om; void **ptr_array = NULL; void *new; MBIt_Board *board; MBIt_Iterator *iter; /* Check for NULL message board */ if (mb == MB_NULL_MBOARD) { P_FUNCFAIL("Cannot create iterator for null board (MB_NULL_MBOARD)"); return MB_ERR_INVALID; } /* get ptr to board */ board = (MBIt_Board*)MBI_getMBoardRef(mb); if (board == NULL) { P_FUNCFAIL("Invalid board handle (%d)", (int)mb); return MB_ERR_INVALID; } mcount = (int)board->data->count_current; /* check if board is locked */ if (board->locked == MB_TRUE) { P_FUNCFAIL("Board (%d) is locked", (int)mb); return MB_ERR_LOCKED; } /* check if board is "unreadable" */ if (board->is_reader == MB_FALSE) { P_FUNCFAIL("Board access mode was set to non-readable"); return MB_ERR_DISABLED; } /* Allocate Iterator object */ iter = (MBIt_Iterator*)malloc(sizeof(MBIt_Iterator)); assert(iter != NULL); if (iter == NULL) { P_FUNCFAIL("Could not allocate required memory"); return MB_ERR_MEMALLOC; } /* assign mb handle to iterator */ iter->mb = mb; iter->msgsize = board->data->elem_size; iter->cursor = NULL; iter->iterating = 0; /* allocate memory for address list */ rc = pl_create(&(iter->data), sizeof(void *), (int)(MBI_CONFIG.mempool_blocksize / 2)); if (rc != PL_SUCCESS) { free(iter); if (rc == PL_ERR_MALLOC) { P_FUNCFAIL("Could not allocate required memory"); return MB_ERR_MEMALLOC; } else { P_FUNCFAIL("pl_create() returned with err code %d", rc); return MB_ERR_INTERNAL; } } /* generate sorted message address array */ if (mcount > 0) { ptr_array = get_sorted_filtered_ptr_list(mb, mcount, cmpFunc, \ filterFunc, filterFuncParams, &elemOut); assert(ptr_array != NULL); } /* populate iterator */ for (i = 0; i < elemOut; i++) { rc = pl_newnode(iter->data, &new); assert(rc == PL_SUCCESS); memcpy(new, &ptr_array[i], sizeof(void*)); } if (ptr_array != NULL) free(ptr_array); /* register iter object */ rc_om = MBI_objmap_push(MBI_OM_iterator, (void*)iter); if (rc_om > OM_MAX_INDEX) { if (rc_om == OM_ERR_MEMALLOC) { P_FUNCFAIL("Could not allocate required memory"); return MB_ERR_MEMALLOC; } else if (rc_om == OM_ERR_OVERFLOW) { P_FUNCFAIL("Too many iterators created. Objmap key overflow"); return MB_ERR_OVERFLOW; } else { P_FUNCFAIL("MBI_objmap_push() returned with err code %d", rc); return MB_ERR_INTERNAL; } } /* assign return pointer */ *itr_ptr = (MBt_Iterator)rc_om; P_INFO("Iterator created (iter:%d, board:%d, mcount:%d) - FILTERED+SORTED", (int)rc_om, (int)mb, (int)iter->data->count_current); return MB_SUCCESS; }
static void pl_remove_test(void) { printsln((Any)__func__); List ac, ex; Any s; ac = sl_of_string("1, 2, 3, 4, 5, 6"); s = pl_get(ac, 0); s_free(s); pl_remove(ac, 0); ex = sl_of_string("2, 3, 4, 5, 6"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1, 2, 3, 4, 5, 6"); s = pl_get(ac, 5); s_free(s); pl_remove(ac, 5); ex = sl_of_string("1, 2, 3, 4, 5"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1, 2, 3, 4, 5, 6"); s = pl_get(ac, 3); s_free(s); pl_remove(ac, 3); ex = sl_of_string("1, 2, 3, 5, 6"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1"); pl_remove(ac, -1); ex = sl_of_string("1"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1"); pl_remove(ac, 1); ex = sl_of_string("1"); sl_check_expect(ac, ex); pl_free(ac); pl_free(ex); ac = sl_of_string("1"); s = pl_get(ac, 0); s_free(s); pl_remove(ac, 0); ex = pl_create(); sl_check_expect(ac, ex); pl_free(ac); l_free(ex); ac = sl_of_string(""); s = pl_get(ac, 0); s_free(s); pl_remove(ac, 0); ex = pl_create(); sl_check_expect(ac, ex); l_free(ac); l_free(ex); }