Continous integration / Tests (push) Canceled after 0s
Testing clients / Build beanstalkd (push) Canceled after 0s
Continous integration / Docker build (push) Canceled after 0s
Testing clients / Test Pheanstalk PHP (push) Canceled after 0s
Testing clients / Test Greenstalk Python (3.9) (push) Canceled after 0s
Testing clients / Test Pystalk Python (3.10) (push) Canceled after 0s
111 lines
1.9 KiB
C
111 lines
1.9 KiB
C
#include "dat.h"
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
void
|
|
ms_init(Ms *a, ms_event_fn oninsert, ms_event_fn onremove)
|
|
{
|
|
a->len = a->cap = a->last = 0;
|
|
a->items = NULL;
|
|
a->oninsert = oninsert;
|
|
a->onremove = onremove;
|
|
}
|
|
|
|
static int
|
|
grow(Ms *a)
|
|
{
|
|
void **nitems;
|
|
size_t ncap = a->cap << 1;
|
|
if (!ncap)
|
|
ncap = 1;
|
|
|
|
nitems = malloc(ncap * sizeof(void *));
|
|
if (!nitems)
|
|
return 0;
|
|
|
|
memcpy(nitems, a->items, a->len * sizeof(void *));
|
|
free(a->items);
|
|
a->items = nitems;
|
|
a->cap = ncap;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
ms_append(Ms *a, void *item)
|
|
{
|
|
if (a->len >= a->cap && !grow(a))
|
|
return 0;
|
|
|
|
a->items[a->len++] = item;
|
|
if (a->oninsert)
|
|
a->oninsert(a, item, a->len - 1);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
ms_delete(Ms *a, size_t i)
|
|
{
|
|
void *item;
|
|
|
|
if (i >= a->len)
|
|
return 0;
|
|
item = a->items[i];
|
|
a->items[i] = a->items[--a->len];
|
|
|
|
/* it has already been removed now */
|
|
if (a->onremove)
|
|
a->onremove(a, item, i);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
ms_clear(Ms *a)
|
|
{
|
|
while (ms_delete(a, 0));
|
|
free(a->items);
|
|
ms_init(a, a->oninsert, a->onremove);
|
|
}
|
|
|
|
int
|
|
ms_remove(Ms *a, void *item)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < a->len; i++) {
|
|
if (a->items[i] == item)
|
|
return ms_delete(a, i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ms_contains(Ms *a, void *item)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < a->len; i++) {
|
|
if (a->items[i] == item)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void *
|
|
ms_take(Ms *a)
|
|
{
|
|
void *item;
|
|
|
|
if (!a->len)
|
|
return NULL;
|
|
|
|
// The result of last behaviour is that ms_take returns the oldest elements
|
|
// first, exception is a row of multiple take calls without inserts on ms
|
|
// of even number of elements. See the test.
|
|
a->last = a->last % a->len;
|
|
item = a->items[a->last];
|
|
ms_delete(a, a->last);
|
|
++a->last;
|
|
return item;
|
|
}
|