int cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size) { cfulist_entry *entry = new_list_entry(); if (!entry) return 0; if (data_size == (size_t)-1) data_size = strlen((char *)data) + 1; entry->data = data; entry->data_size = data_size; lock_list(list); if (list->entries) { entry->next = list->entries; list->entries->prev = entry; list->entries = entry; } else { list->tail = list->entries = entry; } list->num_entries++; unlock_list(list); return 1; }
void cfulist_destroy(cfulist_t *list) { if (!list) return; if (list->free_fn) { cfulist_destroy_with_free_fn(list, list->free_fn); return; } lock_list(list); if (list->entries) { cfulist_entry *entry = NULL; cfulist_entry *tmp = NULL; entry = list->entries; while (entry) { tmp = entry->next; free(entry); entry = tmp; } } unlock_list(list); #ifdef HAVE_PTHREAD_H pthread_mutex_destroy(&list->mutex); #endif free(list); }
int cfulist_nth_data(cfulist_t *list, void **data, size_t *data_size, size_t n) { int rv = 0; size_t i = 0; cfulist_entry *ptr = NULL; if (!list) { return 0; } lock_list(list); if (list->entries) { for (i = 0, ptr = list->entries; ptr && i < n; i++, ptr = ptr->next); if (ptr && i == n) { rv = 1; *data = ptr->data; if (data_size) *data_size = list->entries->data_size; } } else { rv = 0; *data = NULL; *data_size = 0; } unlock_list(list); return rv; }
int cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size) { if (!list) { *data = NULL; *data_size = 0; return 0; } lock_list(list); if (list->tail) { if (list->tail->prev) { cfulist_entry *new_tail = list->tail->prev; assert(list->num_entries > 1); new_tail->next = NULL; *data = list->tail->data; if (data_size) *data_size = list->tail->data_size; free(list->tail); list->tail = new_tail; } else { /* there is only one entry in the list */ assert(list->num_entries == 1); *data = list->tail->data; if (data_size) *data_size = list->tail->data_size; free(list->tail); list->tail = NULL; list->entries = NULL; } list->num_entries--; unlock_list(list); return 1; } unlock_list(list); if (data_size) *data_size = 0; return 0; }
size_t cfulist_foreach(cfulist_t *list, cfulist_foreach_fn_t fe_fn, void *arg) { cfulist_entry *entry = NULL; size_t num_processed = 0; int rv = 0; if (!list) return 0; lock_list(list); for (entry = list->entries; entry && !rv; entry = entry->next) { rv = fe_fn(entry->data, entry->data_size, arg); num_processed++; } unlock_list(list); return num_processed; }
extern void cfulist_destroy_with_free_fn(cfulist_t *list, cfulist_free_fn_t free_fn) { if (!list) return; lock_list(list); if (list->entries) { cfulist_entry *entry = NULL; cfulist_entry *tmp = NULL; entry = list->entries; while (entry) { tmp = entry->next; if (free_fn) free_fn(entry->data); free(entry); entry = tmp; } } unlock_list(list); pthread_mutex_destroy(&list->mutex); free(list); }
int cfulist_last_data(cfulist_t *list, void **data, size_t *data_size) { int rv = 0; if (!list) { return 0; } lock_list(list); if (list->tail) { rv = 1; *data = list->tail->data; if (data_size) *data_size = list->tail->data_size; } else { rv = 0; *data = NULL; *data_size = 0; } unlock_list(list); return rv; }
extern int cfulist_first_data(cfulist_t *list, void **data, size_t *data_size) { int rv = 0; if (!list) { return 0; } lock_list(list); if (list->entries) { rv = 1; *data = list->entries->data; if (data_size) *data_size = list->entries->data_size; } else { rv = 0; *data = NULL; *data_size = 0; } unlock_list(list); return rv; }
int cfulist_shift_data(cfulist_t *list, void **data, size_t *data_size) { int rv = 0; if (!list) { if (data_size) *data_size = 0; *data = NULL; return rv; } lock_list(list); if (list->entries) { cfulist_entry *entry = list->entries; assert(list->num_entries >= 1); rv = 1; *data = entry->data; if (data_size) *data_size = entry->data_size; if (entry->next) { assert(list->num_entries > 1); list->entries = entry->next; list->entries->prev = NULL; } else { assert(list->num_entries == 1); list->tail = NULL; list->entries = NULL; } free(entry); list->num_entries--; } else { assert(list->num_entries == 0); rv = 0; if (data_size) *data_size = 0; *data = NULL; } unlock_list(list); return rv; }