hash_t hash_create (int size, hash_key_f key_f, hash_cmp_f cmp_f, hash_del_f del_f) { hash_t h; if (!cmp_f || !key_f) { errno = EINVAL; return (NULL); } if (size <= 0) { size = HASH_DEF_SIZE; } if (!(h = malloc (sizeof (*h)))) { return (lsd_nomem_error (__FILE__, __LINE__, "hash_create")); } if (!(h->table = calloc (size, sizeof (struct hash_node *)))) { free (h); return (lsd_nomem_error (__FILE__, __LINE__, "hash_create")); } h->count = 0; h->size = size; h->cmp_f = cmp_f; h->del_f = del_f; h->key_f = key_f; lsd_mutex_init (&h->mutex); assert (h->magic = HASH_MAGIC); /* set magic via assert abuse */ return (h); }
cbuf_t cbuf_create (int minsize, int maxsize) { cbuf_t cb; if (minsize <= 0) { errno = EINVAL; return(NULL); } if (!(cb = malloc(sizeof(struct cbuf)))) { errno = ENOMEM; return(lsd_nomem_error(__FILE__, __LINE__, "cbuf struct")); } /* Circular buffer is empty when (i_in == i_out), * so reserve 1 byte for this sentinel. */ cb->alloc = minsize + 1; #ifndef NDEBUG /* Reserve space for the magic cookies used to protect the * cbuf data[] array from underflow and overflow. */ cb->alloc += 2 * CBUF_MAGIC_LEN; #endif /* !NDEBUG */ if (!(cb->data = malloc(cb->alloc))) { free(cb); errno = ENOMEM; return(lsd_nomem_error(__FILE__, __LINE__, "cbuf data")); } cbuf_mutex_init(cb); cb->minsize = minsize; cb->maxsize = (maxsize > minsize) ? maxsize : minsize; cb->size = minsize; cb->used = 0; cb->overwrite = CBUF_WRAP_MANY; cb->got_wrap = 0; cb->i_in = cb->i_out = cb->i_rep = 0; #ifndef NDEBUG /* C is for cookie, that's good enough for me, yeah! * The magic cookies are only defined during DEBUG code. * The first "magic" cookie is at the top of the structure. * Magic cookies are also placed at the top & bottom of the * cbuf data[] array to catch buffer underflow & overflow errors. */ cb->data += CBUF_MAGIC_LEN; /* jump forward past underflow magic */ cb->magic = CBUF_MAGIC; /* * Must use memcpy since overflow cookie may not be word-aligned. */ memcpy(cb->data - CBUF_MAGIC_LEN, (void *) &cb->magic, CBUF_MAGIC_LEN); memcpy(cb->data + cb->size + 1, (void *) &cb->magic, CBUF_MAGIC_LEN); cbuf_mutex_lock(cb); assert(cbuf_is_valid(cb)); cbuf_mutex_unlock(cb); #endif /* !NDEBUG */ return(cb); }
static void * list_node_create (List l, ListNode *pp, void *x) { /* Inserts data pointed to by [x] into list [l] after [pp], * the address of the previous node's "next" ptr. * Returns a ptr to data [x], or NULL if insertion fails. * This routine assumes the list is already locked upon entry. */ ListNode p; ListIterator i; assert(l != NULL); assert(l->magic == LIST_MAGIC); assert(list_mutex_is_locked(&l->mutex)); assert(pp != NULL); assert(x != NULL); if (!(p = list_node_alloc())) return(lsd_nomem_error(__FILE__, __LINE__, "list node create")); p->data = x; if (!(p->next = *pp)) l->tail = &p->next; *pp = p; l->count++; for (i=l->iNext; i; i=i->iNext) { assert(i->magic == LIST_MAGIC); if (i->prev == pp) i->prev = &p->next; else if (i->pos == p->next) i->pos = p; assert((i->pos == *i->prev) || (i->pos == (*i->prev)->next)); } return(x); }
void * hash_insert (hash_t h, const void *key, void *data) { struct hash_node *p; unsigned int slot; if (!h || !key || !data) { errno = EINVAL; return (NULL); } lsd_mutex_lock (&h->mutex); assert (h->magic == HASH_MAGIC); slot = h->key_f (key) % h->size; for (p = h->table[slot]; p != NULL; p = p->next) { if (!h->cmp_f (p->hkey, key)) { errno = EEXIST; data = NULL; goto end; } } if (!(p = hash_node_alloc ())) { data = lsd_nomem_error (__FILE__, __LINE__, "hash_insert"); goto end; } p->hkey = key; p->data = data; p->next = h->table[slot]; h->table[slot] = p; h->count++; end: lsd_mutex_unlock (&h->mutex); return (data); }
List list_create (ListDelF f) { List l; if (!(l = list_alloc())) return(lsd_nomem_error(__FILE__, __LINE__, "list create")); l->head = NULL; l->tail = &l->head; l->iNext = NULL; l->fDel = f; l->count = 0; list_mutex_init(&l->mutex); assert(l->magic = LIST_MAGIC); /* set magic via assert abuse */ return(l); }
ListIterator list_iterator_create (List l) { ListIterator i; assert(l != NULL); if (!(i = list_iterator_alloc())) return(lsd_nomem_error(__FILE__, __LINE__, "list iterator create")); i->list = l; list_mutex_lock(&l->mutex); assert(l->magic == LIST_MAGIC); i->pos = l->head; i->prev = &l->head; i->iNext = l->iNext; l->iNext = i; assert(i->magic = LIST_MAGIC); /* set magic via assert abuse */ list_mutex_unlock(&l->mutex); return(i); }