(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;
}

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS