(1)
#if (a_Version >= 1)
#define Set0 a_Set0
#define SetElm a_SetElm
#define Set0_ini a_Set0_ini
#define Set0_din a_Set0_din
#define Set0_add a_Set0_add
#define Set0_find a_Set0_find
#define Set0_rmv a_Set0_rmv
#endif
a_class(a_Set) { a_VecChr tbl[1]; };
a_class(a_SetElm) {
const void *k;
intptr_t n;
uint32_t h;
};
a_static uint32_t a_fnv1a32(const void *p, intptr_t n)
{
uint32_t h = 2166136261U;
intptr_t i;
for (i = 0; i < n; i++) {
h ^= ((const unsigned char *) p)[i];
h *= 16777619U;
}
return h;
}
a_static void a_Set_ini(a_Set *w) { a_VecChr_ini(w->tbl); }
a_static void a_Set_din(a_Set *w) { a_VecChr_din(w->tbl); }
a_static int a_Set_cmp(a_SetElm *a, a_SetElm *b)
{
if (a->h > b->h) goto plus; if (a->h < b->h) goto minus;
if (a->n > b->n) goto plus; if (a->n < b->n) goto minus;
return memcmp(a->k, b->k, a->n);
plus: return +1;
minus: return -1;
}
a_static void *a_Set_add(a_Set *w, a_SetElm *elm)
{
elm->h = a_fnv1a32(elm->k, elm->n);
intptr_t i = 0, n = w->tbl->n / sizeof (a_SetElm *), a, b, m;
int c;
a_SetElm **tbl = (a_SetElm **) w->tbl->p, *p;
if (w->tbl->n == 0) goto ins;
p = tbl[0]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
if (c < 0) goto ins;
i = 1; if (n == 1) goto ins;
p = tbl[n - 1]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
i = n; if (c > 0) goto ins;
a = 0; b = n - 1; m = a + ((b - a) >> 1);
i = b; if (m == a) goto ins;
do {
p = tbl[m]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
if (c < 0) { b = m; } else { a = m; }
m = a + ((b - a) >> 1);
} while (m > a);
i = b;
ins:
a_VecChr_resizeDiff(_arg_ w->tbl, sizeof (a_SetElm *));
tbl = (a_SetElm **) w->tbl->p;
if (i < n)
memmove(&tbl[i + 1], &tbl[i], (n - i) * sizeof (a_SetElm *));
tbl[i] = elm;
return NULL;
fin:
return p;
}
a_static void *a_Set_find(a_Set *w, a_SetElm *elm)
{
elm->h = a_fnv1a32(elm->k, elm->n);
intptr_t n = w->tbl->n / sizeof (a_SetElm *), a, b, m;
int c;
a_SetElm **tbl = (a_SetElm **) w->tbl->p, *p;
if (w->tbl->n == 0) goto ins;
p = tbl[0]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
if (c < 0) goto ins;
if (n == 1) goto ins;
p = tbl[n - 1]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
if (c > 0) goto ins;
a = 0; b = n - 1; m = a + ((b - a) >> 1);
if (m == a) goto ins;
do {
p = tbl[m]; c = a_Set_cmp(elm, p); if (c == 0) goto fin;
if (c < 0) { b = m; } else { a = m; }
m = a + ((b - a) >> 1);
} while (m > a);
ins: return NULL;
fin: return p;
}
a_static void *a_Set_rmv(a_Set *w, a_SetElm *elm)
{
elm->h = a_fnv1a32(elm->k, elm->n);
intptr_t i, n = w->tbl->n / sizeof (a_SetElm *), a, b, m;
int c;
a_SetElm **tbl = (a_SetElm **) w->tbl->p, *p;
if (w->tbl->n == 0) goto ins;
i = 0; c = a_Set_cmp(elm, tbl[0]); if (c == 0) goto fin;
if (c < 0) goto ins;
if (n == 1) goto ins;
i = n - 1; c = a_Set_cmp(elm, tbl[n - 1]); if (c == 0) goto fin;
if (c > 0) goto ins;
a = 0; b = n - 1; m = a + ((b - a) >> 1);
if (m == a) goto ins;
do {
i = m; c = a_Set_cmp(elm, tbl[m]); if (c == 0) goto fin;
if (c < 0) { b = m; } else { a = m; }
m = a + ((b - a) >> 1);
} while (m > a);
ins: return NULL;
fin:
p = tbl[i];
if (i + 1 < n)
memmove(&tbl[i], &tbl[i + 1], (n - i - 1) * sizeof (a_SetElm *));
a_VecChr_resizeDiff(_arg_ w->tbl, - (intptr_t) sizeof (a_SetElm *));
return p;
}