impl prev/next api
This commit is contained in:
parent
de415b0d65
commit
f0e4c84fab
686
include/sl.h
686
include/sl.h
|
@ -111,345 +111,353 @@
|
||||||
fn \
|
fn \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_DECL(decl, prefix, field, free_node_blk, update_node_blk) \
|
#define SKIPLIST_DECL(decl, prefix, field, free_node_blk, update_node_blk) \
|
||||||
\
|
\
|
||||||
/* Skiplist node type */ \
|
/* Skiplist node type */ \
|
||||||
typedef struct decl##_node decl##_node_t; \
|
typedef struct decl##_node decl##_node_t; \
|
||||||
\
|
\
|
||||||
/* Skiplist type */ \
|
/* Skiplist type */ \
|
||||||
typedef struct decl { \
|
typedef struct decl { \
|
||||||
size_t level, length, max, fanout; \
|
size_t level, length, max, fanout; \
|
||||||
int (*cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *); \
|
int (*cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *); \
|
||||||
void *aux; \
|
void *aux; \
|
||||||
decl##_node_t *slh_head; \
|
decl##_node_t *slh_head; \
|
||||||
decl##_node_t *slh_tail; \
|
decl##_node_t *slh_tail; \
|
||||||
} decl##_t; \
|
} decl##_t; \
|
||||||
\
|
\
|
||||||
/* -- __skip_key_compare_ \
|
/* -- __skip_key_compare_ \
|
||||||
* \
|
* \
|
||||||
* This function takes four arguments: \
|
* This function takes four arguments: \
|
||||||
* - a reference to the Skiplist \
|
* - a reference to the Skiplist \
|
||||||
* - the two nodes to compare, `a` and `b` \
|
* - the two nodes to compare, `a` and `b` \
|
||||||
* - `aux` an additional auxiliary argument \
|
* - `aux` an additional auxiliary argument \
|
||||||
* and returns: \
|
* and returns: \
|
||||||
* a < b : return -1 \
|
* a < b : return -1 \
|
||||||
* a == b : return 0 \
|
* a == b : return 0 \
|
||||||
* a > b : return 1 \
|
* a > b : return 1 \
|
||||||
*/ \
|
*/ \
|
||||||
static int __skip_key_compare_##decl(decl##_t *slist, decl##_node_t *a, \
|
static int __skip_key_compare_##decl(decl##_t *slist, decl##_node_t *a, \
|
||||||
decl##_node_t *b, void *aux) \
|
decl##_node_t *b, void *aux) \
|
||||||
{ \
|
{ \
|
||||||
if (a == b) \
|
if (a == b) \
|
||||||
return 0; \
|
return 0; \
|
||||||
if (a == slist->slh_head || b == slist->slh_tail) \
|
if (a == slist->slh_head || b == slist->slh_tail) \
|
||||||
return -1; \
|
return -1; \
|
||||||
if (a == slist->slh_tail || b == slist->slh_head) \
|
if (a == slist->slh_tail || b == slist->slh_head) \
|
||||||
return 1; \
|
return 1; \
|
||||||
return slist->cmp(slist, a, b, aux); \
|
return slist->cmp(slist, a, b, aux); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- __skip_toss_ */ \
|
/* -- __skip_toss_ */ \
|
||||||
static int __skip_toss_##decl(size_t max, size_t fanout) \
|
static int __skip_toss_##decl(size_t max, size_t fanout) \
|
||||||
{ \
|
{ \
|
||||||
size_t level = 0; \
|
size_t level = 0; \
|
||||||
while (level + 1 < max) { \
|
while (level + 1 < max) { \
|
||||||
if (rand() % fanout == 0) /* NOLINT(*-msc50-cpp) */ \
|
if (rand() % fanout == 0) /* NOLINT(*-msc50-cpp) */ \
|
||||||
level++; \
|
level++; \
|
||||||
else \
|
else \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
return level; \
|
return level; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_alloc_node_ */ \
|
/* -- skip_alloc_node_ */ \
|
||||||
int prefix##skip_alloc_node_##decl(decl##_t *slist, decl##_node_t **node) \
|
int prefix##skip_alloc_node_##decl(decl##_t *slist, decl##_node_t **node) \
|
||||||
{ \
|
{ \
|
||||||
decl##_node_t *n; \
|
decl##_node_t *n; \
|
||||||
n = (decl##_node_t *)calloc(1, sizeof(decl##_node_t)); \
|
n = (decl##_node_t *)calloc(1, sizeof(decl##_node_t)); \
|
||||||
ARRAY_ALLOC(n->field.sle_next, struct decl##_node, slist->max); \
|
ARRAY_ALLOC(n->field.sle_next, struct decl##_node, slist->max); \
|
||||||
if (n && n->field.sle_next) { \
|
if (n && n->field.sle_next) { \
|
||||||
ARRAY_SET_SIZE(n->field.sle_next, slist->max); \
|
ARRAY_SET_SIZE(n->field.sle_next, slist->max); \
|
||||||
ARRAY_SET_LENGTH(n->field.sle_next, 0); \
|
ARRAY_SET_LENGTH(n->field.sle_next, 0); \
|
||||||
*node = n; \
|
*node = n; \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
return ENOMEM; \
|
return ENOMEM; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_init_ \
|
/* -- skip_init_ \
|
||||||
* max: 12, fanout: 4 are good defaults. \
|
* max: 12, fanout: 4 are good defaults. \
|
||||||
*/ \
|
*/ \
|
||||||
int prefix##skip_init_##decl(decl##_t *slist, size_t max, size_t fanout, \
|
int prefix##skip_init_##decl(decl##_t *slist, size_t max, size_t fanout, \
|
||||||
int (*cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *)) \
|
int (*cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *)) \
|
||||||
{ \
|
{ \
|
||||||
int rc = 0; \
|
int rc = 0; \
|
||||||
slist->level = 0; \
|
slist->level = 0; \
|
||||||
slist->length = 0; \
|
slist->length = 0; \
|
||||||
slist->max = max; \
|
slist->max = max; \
|
||||||
slist->fanout = fanout; \
|
slist->fanout = fanout; \
|
||||||
slist->cmp = cmp; \
|
slist->cmp = cmp; \
|
||||||
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \
|
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \
|
||||||
if (rc) \
|
if (rc) \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_tail); \
|
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_tail); \
|
||||||
if (rc) \
|
if (rc) \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
ARRAY_SET_LENGTH(slist->slh_head->field.sle_next, max); \
|
ARRAY_SET_LENGTH(slist->slh_head->field.sle_next, max); \
|
||||||
for (size_t __i = 0; __i < max; __i++) \
|
for (size_t __i = 0; __i < max; __i++) \
|
||||||
slist->slh_head->field.sle_next[__i] = slist->slh_tail; \
|
slist->slh_head->field.sle_next[__i] = slist->slh_tail; \
|
||||||
slist->slh_head->field.sle_prev = NULL; \
|
slist->slh_head->field.sle_prev = NULL; \
|
||||||
ARRAY_SET_LENGTH(slist->slh_tail->field.sle_next, max); \
|
ARRAY_SET_LENGTH(slist->slh_tail->field.sle_next, max); \
|
||||||
for (size_t __i = 0; __i < max; __i++) \
|
for (size_t __i = 0; __i < max; __i++) \
|
||||||
slist->slh_tail->field.sle_next[__i] = NULL; \
|
slist->slh_tail->field.sle_next[__i] = NULL; \
|
||||||
slist->slh_head->field.sle_prev = slist->slh_tail; \
|
slist->slh_head->field.sle_prev = slist->slh_tail; \
|
||||||
fail:; \
|
fail:; \
|
||||||
return rc; \
|
return rc; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_free_node_ */ \
|
/* -- skip_free_node_ */ \
|
||||||
void prefix##skip_free_node_##decl(decl##_node_t *node) \
|
void prefix##skip_free_node_##decl(decl##_node_t *node) \
|
||||||
{ \
|
{ \
|
||||||
free_node_blk; \
|
free_node_blk; \
|
||||||
free(node->field.sle_next); \
|
free(node->field.sle_next); \
|
||||||
free(node); \
|
free(node); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_size_ */ \
|
/* -- skip_size_ */ \
|
||||||
int prefix##skip_size_##decl(decl##_t *slist) \
|
int prefix##skip_size_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
return slist->length; \
|
return slist->length; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_empty_ */ \
|
/* -- skip_empty_ */ \
|
||||||
int prefix##skip_empty_##decl(decl##_t *slist) \
|
int prefix##skip_empty_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
return slist->length == 0; \
|
return slist->length == 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_head_ */ \
|
/* -- skip_head_ */ \
|
||||||
decl##_node_t *prefix##skip_head_##decl(decl##_t *slist) \
|
decl##_node_t *prefix##skip_head_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
return slist->slh_head; \
|
return slist->slh_head; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_tail_ */ \
|
/* -- skip_tail_ */ \
|
||||||
decl##_node_t *prefix##skip_tail_##decl(decl##_t *slist) \
|
decl##_node_t *prefix##skip_tail_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
return slist->slh_tail; \
|
return slist->slh_tail; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_locate_ */ \
|
/* -- skip_locate_ */ \
|
||||||
decl##_node_t **prefix##skip_locate_##decl(decl##_t *slist, \
|
decl##_node_t **prefix##skip_locate_##decl(decl##_t *slist, \
|
||||||
decl##_node_t *n) \
|
decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
decl##_node_t **path; \
|
decl##_node_t **path; \
|
||||||
decl##_node_t *elm = slist->slh_head; \
|
decl##_node_t *elm = slist->slh_head; \
|
||||||
\
|
\
|
||||||
if (n == NULL) \
|
if (n == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
\
|
\
|
||||||
i = slist->max + 1; \
|
i = slist->max + 1; \
|
||||||
ARRAY_ALLOC(path, decl##_node_t, i); \
|
ARRAY_ALLOC(path, decl##_node_t, i); \
|
||||||
ARRAY_SET_LENGTH(path, 1); \
|
ARRAY_SET_LENGTH(path, 1); \
|
||||||
i = slist->level; \
|
i = slist->level; \
|
||||||
if (path == NULL) \
|
if (path == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
\
|
\
|
||||||
/* Find the node that matches `node` or NULL. */ \
|
/* Find the node that matches `node` or NULL. */ \
|
||||||
do { \
|
do { \
|
||||||
while (elm && \
|
while (elm && \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
||||||
slist->aux) < 0) \
|
slist->aux) < 0) \
|
||||||
elm = elm->field.sle_next[i]; \
|
elm = elm->field.sle_next[i]; \
|
||||||
path[i + 1] = elm; \
|
path[i + 1] = elm; \
|
||||||
ARRAY_SET_LENGTH(path, ARRAY_LENGTH(path) + 1); \
|
ARRAY_SET_LENGTH(path, ARRAY_LENGTH(path) + 1); \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
elm = elm->field.sle_next[0]; \
|
elm = elm->field.sle_next[0]; \
|
||||||
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
||||||
path[0] = elm; \
|
path[0] = elm; \
|
||||||
return path; \
|
return path; \
|
||||||
} \
|
} \
|
||||||
ARRAY_FREE(path); \
|
ARRAY_FREE(path); \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_insert_ */ \
|
/* -- skip_insert_ */ \
|
||||||
int prefix##skip_insert_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_insert_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
decl##_node_t *prev, *elm = slist->slh_head; \
|
decl##_node_t *prev, *elm = slist->slh_head; \
|
||||||
decl##_node_t **path; \
|
decl##_node_t **path; \
|
||||||
\
|
\
|
||||||
if (n == NULL) \
|
if (n == NULL) \
|
||||||
return ENOENT; \
|
return ENOENT; \
|
||||||
\
|
\
|
||||||
i = slist->level; \
|
i = slist->level; \
|
||||||
ARRAY_ALLOC(path, decl##_node_t, slist->max); \
|
ARRAY_ALLOC(path, decl##_node_t, slist->max); \
|
||||||
if (path == NULL) \
|
if (path == NULL) \
|
||||||
return ENOMEM; \
|
return ENOMEM; \
|
||||||
\
|
\
|
||||||
/* Find the position in the list where this element belongs. */ \
|
/* Find the position in the list where this element belongs. */ \
|
||||||
do { \
|
do { \
|
||||||
while (elm && \
|
while (elm && \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
||||||
slist->aux) < 0) \
|
slist->aux) < 0) \
|
||||||
elm = elm->field.sle_next[i]; \
|
elm = elm->field.sle_next[i]; \
|
||||||
path[i] = elm; \
|
path[i] = elm; \
|
||||||
ARRAY_SET_LENGTH(path, ARRAY_LENGTH(path) + 1); \
|
ARRAY_SET_LENGTH(path, ARRAY_LENGTH(path) + 1); \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
i = 0; \
|
i = 0; \
|
||||||
prev = elm; \
|
prev = elm; \
|
||||||
elm = elm->field.sle_next[0]; \
|
elm = elm->field.sle_next[0]; \
|
||||||
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
||||||
/* Don't overwrite, to do that use _REPLACE not _INSERT */ \
|
/* Don't overwrite, to do that use _REPLACE not _INSERT */ \
|
||||||
ARRAY_FREE(path); \
|
ARRAY_FREE(path); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
size_t level = __skip_toss_##decl(slist->max, slist->fanout); \
|
size_t level = __skip_toss_##decl(slist->max, slist->fanout); \
|
||||||
ARRAY_SET_LENGTH(n->field.sle_next, level); \
|
ARRAY_SET_LENGTH(n->field.sle_next, level); \
|
||||||
if (level > slist->level) { \
|
if (level > slist->level) { \
|
||||||
for (i = slist->level + 1; i <= level; i++) { \
|
for (i = slist->level + 1; i <= level; i++) { \
|
||||||
path[i] = slist->slh_tail; \
|
path[i] = slist->slh_tail; \
|
||||||
} \
|
} \
|
||||||
slist->level = level; \
|
slist->level = level; \
|
||||||
} \
|
} \
|
||||||
for (i = 0; i <= level; i++) { \
|
for (i = 0; i <= level; i++) { \
|
||||||
n->field.sle_next[i] = path[i]->field.sle_next[i]; \
|
n->field.sle_next[i] = path[i]->field.sle_next[i]; \
|
||||||
path[i]->field.sle_next[i] = n; \
|
path[i]->field.sle_next[i] = n; \
|
||||||
} \
|
} \
|
||||||
n->field.sle_prev = prev; \
|
n->field.sle_prev = prev; \
|
||||||
if (n->field.sle_next[0] == slist->slh_tail) { \
|
if (n->field.sle_next[0] == slist->slh_tail) { \
|
||||||
slist->slh_tail->field.sle_prev = n; \
|
slist->slh_tail->field.sle_prev = n; \
|
||||||
} \
|
} \
|
||||||
slist->length++; \
|
slist->length++; \
|
||||||
ARRAY_FREE(path); \
|
ARRAY_FREE(path); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_insert_dup_ TODO \
|
/* -- skip_insert_dup_ TODO \
|
||||||
int prefix##skip_insert_dup_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_insert_dup_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); \
|
((void)slist); \
|
||||||
((void)n); \
|
((void)n); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
*/ \
|
*/ \
|
||||||
\
|
\
|
||||||
/* -- skip_update_ \
|
/* -- skip_update_ \
|
||||||
* Locates a node in the list that equals the `new` node and then \
|
* Locates a node in the list that equals the `new` node and then \
|
||||||
* uses the `update_node_blk` to update the contents. \
|
* uses the `update_node_blk` to update the contents. \
|
||||||
* WARNING: Do not update the portion of the node used for ordering \
|
* WARNING: Do not update the portion of the node used for ordering \
|
||||||
* (e.g. `key`) unless you really know what you're doing. \
|
* (e.g. `key`) unless you really know what you're doing. \
|
||||||
*/ \
|
*/ \
|
||||||
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *new) \
|
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *new) \
|
||||||
{ \
|
{ \
|
||||||
decl##_node_t **path, *node; \
|
decl##_node_t **path, *node; \
|
||||||
\
|
\
|
||||||
if (!slist || !new) \
|
if (!slist || !new) \
|
||||||
return -1; \
|
return -1; \
|
||||||
\
|
\
|
||||||
path = prefix##skip_locate_##decl(slist, new); \
|
path = prefix##skip_locate_##decl(slist, new); \
|
||||||
if (ARRAY_SIZE(path) > 0) { \
|
if (ARRAY_SIZE(path) > 0) { \
|
||||||
node = path[0]; \
|
node = path[0]; \
|
||||||
ARRAY_FREE(path); \
|
ARRAY_FREE(path); \
|
||||||
update_node_blk; \
|
update_node_blk; \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_remove_ */ \
|
/* -- skip_remove_ */ \
|
||||||
int prefix##skip_remove_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_remove_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
size_t i, s; \
|
size_t i, s; \
|
||||||
decl##_node_t **path, *node; \
|
decl##_node_t **path, *node; \
|
||||||
\
|
\
|
||||||
if (!slist || !n) \
|
if (!slist || !n) \
|
||||||
return -1; \
|
return -1; \
|
||||||
if (slist->length == 0) \
|
if (slist->length == 0) \
|
||||||
return 0; \
|
return 0; \
|
||||||
\
|
\
|
||||||
path = prefix##skip_locate_##decl(slist, n); \
|
path = prefix##skip_locate_##decl(slist, n); \
|
||||||
s = ARRAY_LENGTH(path); \
|
s = ARRAY_LENGTH(path); \
|
||||||
node = path[0]; \
|
node = path[0]; \
|
||||||
if (s > 0) { \
|
if (s > 0) { \
|
||||||
node->field.sle_next[0]->field.sle_prev = node->field.sle_prev; \
|
node->field.sle_next[0]->field.sle_prev = node->field.sle_prev; \
|
||||||
for (i = 1; i < s; i++) { \
|
for (i = 1; i < s; i++) { \
|
||||||
if (path[i]->field.sle_next[i - 1] != node) \
|
if (path[i]->field.sle_next[i - 1] != node) \
|
||||||
break; \
|
break; \
|
||||||
path[i]->field.sle_next[i - 1] = node->field.sle_next[i - 1]; \
|
path[i]->field.sle_next[i - 1] = node->field.sle_next[i - 1]; \
|
||||||
if (path[i]->field.sle_next[i - 1] == slist->slh_tail) { \
|
if (path[i]->field.sle_next[i - 1] == slist->slh_tail) { \
|
||||||
size_t h = ARRAY_LENGTH(path[i]->field.sle_next); \
|
size_t h = ARRAY_LENGTH(path[i]->field.sle_next); \
|
||||||
ARRAY_SET_LENGTH(path[i]->field.sle_next, h - 1); \
|
ARRAY_SET_LENGTH(path[i]->field.sle_next, h - 1); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
ARRAY_FREE(path); \
|
ARRAY_FREE(path); \
|
||||||
free_node_blk; \
|
free_node_blk; \
|
||||||
/* Find all levels in the first element in the list that point \
|
/* Find all levels in the first element in the list that point \
|
||||||
at the tail and shrink the level*/ \
|
at the tail and shrink the level*/ \
|
||||||
while (slist->level > 0 && \
|
while (slist->level > 0 && \
|
||||||
slist->slh_head->field.sle_next[slist->level] == slist->slh_tail) { \
|
slist->slh_head->field.sle_next[slist->level] == slist->slh_tail) { \
|
||||||
slist->level--; \
|
slist->level--; \
|
||||||
} \
|
} \
|
||||||
slist->length--; \
|
slist->length--; \
|
||||||
} \
|
} \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_find_ */ \
|
/* -- skip_find_ */ \
|
||||||
int prefix##skip_find_##decl(decl##_t *slist, decl##_node_t *n) \
|
decl##_node_t *prefix##skip_find_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
((void)slist); /* TODO */ \
|
||||||
((void)n); \
|
((void)n); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_find_gte */ \
|
/* -- skip_find_gte */ \
|
||||||
int prefix##skip_find_gte_##decl(decl##_t *slist, decl##_node_t *n) \
|
decl##_node_t *prefix##skip_find_gte_##decl(decl##_t *slist, \
|
||||||
{ \
|
decl##_node_t *n) \
|
||||||
((void)slist); /* TODO */ \
|
{ \
|
||||||
((void)n); \
|
((void)slist); /* TODO */ \
|
||||||
return 0; \
|
((void)n); \
|
||||||
} \
|
return 0; \
|
||||||
\
|
} \
|
||||||
/* -- skip_find_lte */ \
|
\
|
||||||
int prefix##skip_find_lte_##decl(decl##_t *slist, decl##_node_t *n) \
|
/* -- skip_find_lte */ \
|
||||||
{ \
|
decl##_node_t *prefix##skip_find_lte_##decl(decl##_t *slist, \
|
||||||
((void)slist); /* TODO */ \
|
decl##_node_t *n) \
|
||||||
((void)n); \
|
{ \
|
||||||
return 0; \
|
((void)slist); /* TODO */ \
|
||||||
} \
|
((void)n); \
|
||||||
\
|
return 0; \
|
||||||
/* -- skip_next_node_ */ \
|
} \
|
||||||
int prefix##skip_next_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
\
|
||||||
{ \
|
/* -- skip_next_node_ */ \
|
||||||
((void)slist); /* TODO */ \
|
decl##_node_t *prefix##skip_next_node_##decl(decl##_t *slist, \
|
||||||
((void)n); \
|
decl##_node_t *n) \
|
||||||
return 0; \
|
{ \
|
||||||
} \
|
if (!slist || !n) \
|
||||||
\
|
return NULL; \
|
||||||
/* -- skip_prev_node_ */ \
|
if (n->field.sle_next[0] == slist->slh_tail) \
|
||||||
int prefix##skip_prev_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
return NULL; \
|
||||||
{ \
|
return n->field.sle_next[0]; \
|
||||||
((void)slist); /* TODO */ \
|
} \
|
||||||
((void)n); \
|
\
|
||||||
return 0; \
|
/* -- skip_prev_node_ */ \
|
||||||
} \
|
decl##_node_t *prefix##skip_prev_node_##decl(decl##_t *slist, \
|
||||||
\
|
decl##_node_t *n) \
|
||||||
/* -- skip_destroy_ */ \
|
{ \
|
||||||
int prefix##skip_destroy_##decl(decl##_t *slist, decl##_node_t *n) \
|
if (!slist || !n) \
|
||||||
{ \
|
return NULL; \
|
||||||
((void)slist); /* TODO */ \
|
if (n->field.sle_prev == slist->slh_head) \
|
||||||
((void)n); \
|
return NULL; \
|
||||||
return 0; \
|
return n->field.sle_prev; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- __skip_integrity_check_ */ \
|
/* -- skip_destroy_ */ \
|
||||||
static int __skip_integrity_check_##decl(decl##_t *slist) \
|
int prefix##skip_destroy_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
((void)slist); /* TODO */ \
|
||||||
return 0; \
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- __skip_integrity_check_ */ \
|
||||||
|
static int __skip_integrity_check_##decl(decl##_t *slist) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_GETTER(decl, prefix, name, ktype, vtype, qblk, rblk) \
|
#define SKIPLIST_GETTER(decl, prefix, name, ktype, vtype, qblk, rblk) \
|
||||||
|
|
Loading…
Reference in a new issue