impl remove api
This commit is contained in:
parent
81d2f817f2
commit
de415b0d65
2 changed files with 366 additions and 276 deletions
|
@ -29,7 +29,10 @@ struct slex_node {
|
||||||
/*
|
/*
|
||||||
* Generate all the access functions for our type of Skiplist.
|
* Generate all the access functions for our type of Skiplist.
|
||||||
*/
|
*/
|
||||||
SKIPLIST_DECL(slex, api_, entries, { (void)node; })
|
SKIPLIST_DECL(
|
||||||
|
slex, api_, entries,
|
||||||
|
/* free node */ { (void)node; },
|
||||||
|
/* update node */ { node->value = new->value; })
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Getter
|
* Getter
|
||||||
|
@ -103,14 +106,25 @@ main()
|
||||||
|
|
||||||
/* Insert 7 key/value pairs into the list. */
|
/* Insert 7 key/value pairs into the list. */
|
||||||
for (int i = -2; i <= 2; i++) {
|
for (int i = -2; i <= 2; i++) {
|
||||||
|
int v;
|
||||||
|
slex_node_t new;
|
||||||
rc = api_skip_alloc_node_slex(list, &n);
|
rc = api_skip_alloc_node_slex(list, &n);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
n->key = i;
|
n->key = i;
|
||||||
n->value = i;
|
n->value = i;
|
||||||
api_skip_insert_slex(list, n);
|
api_skip_insert_slex(list, n);
|
||||||
|
v = api_skip_get_slex(list, i);
|
||||||
|
((void)v);
|
||||||
|
new.key = n->key;
|
||||||
|
new.value = n->value * 10;
|
||||||
|
api_skip_update_slex(list, &new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slex_node_t q;
|
||||||
|
q.key = 0;
|
||||||
|
api_skip_remove_slex(list, &q);
|
||||||
|
|
||||||
FILE *of = fopen("/tmp/slm.dot", "w");
|
FILE *of = fopen("/tmp/slm.dot", "w");
|
||||||
if (!of) {
|
if (!of) {
|
||||||
perror("Failed to open file /tmp/slm.dot");
|
perror("Failed to open file /tmp/slm.dot");
|
||||||
|
|
164
include/sl.h
164
include/sl.h
|
@ -57,11 +57,11 @@
|
||||||
(size) = (size == 0 ? 254 : size); \
|
(size) = (size == 0 ? 254 : size); \
|
||||||
(var) = (type **)calloc(sizeof(type *), size + 2); \
|
(var) = (type **)calloc(sizeof(type *), size + 2); \
|
||||||
if ((var) != NULL) { \
|
if ((var) != NULL) { \
|
||||||
*(var)++ = (type *)size; \
|
*(var)++ = (void *)(uintptr_t)size; \
|
||||||
*(var)++ = 0; \
|
*(var)++ = (void *)(uintptr_t)0; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define ARRAY_FREE(var) free((var)-2)
|
#define ARRAY_FREE(list) free((list)-2)
|
||||||
#define ARRAY_SIZE(list) (unsigned int)(uintptr_t)(list)[-2]
|
#define ARRAY_SIZE(list) (unsigned int)(uintptr_t)(list)[-2]
|
||||||
#define ARRAY_SET_SIZE(list, size) (list)[-2] = (void *)(uintptr_t)(size)
|
#define ARRAY_SET_SIZE(list, size) (list)[-2] = (void *)(uintptr_t)(size)
|
||||||
#define ARRAY_LENGTH(list) (unsigned int)(uintptr_t)(list)[-1]
|
#define ARRAY_LENGTH(list) (unsigned int)(uintptr_t)(list)[-1]
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
fn \
|
fn \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_DECL(decl, prefix, field, free_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; \
|
||||||
|
@ -214,65 +214,81 @@
|
||||||
free(node); \
|
free(node); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_destroy_ */ \
|
|
||||||
int prefix##skip_destroy_##decl(decl##_t *slist, decl##_node_t *n) \
|
|
||||||
{ \
|
|
||||||
((void)slist); /* TODO */ \
|
|
||||||
((void)n); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* -- skip_size_ */ \
|
/* -- skip_size_ */ \
|
||||||
int prefix##skip_size_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_size_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
return slist->length; \
|
||||||
((void)n); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_empty_ */ \
|
/* -- skip_empty_ */ \
|
||||||
int prefix##skip_empty_##decl(decl##_t *slist) \
|
int prefix##skip_empty_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
return slist->length == 0; \
|
||||||
return 0; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_head_ */ \
|
/* -- skip_head_ */ \
|
||||||
int prefix##skip_head_##decl(decl##_t *slist, decl##_node_t *n) \
|
decl##_node_t *prefix##skip_head_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
return slist->slh_head; \
|
||||||
((void)n); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_tail_ */ \
|
/* -- skip_tail_ */ \
|
||||||
int prefix##skip_tail_##decl(decl##_t *slist, decl##_node_t *n) \
|
decl##_node_t *prefix##skip_tail_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
return slist->slh_tail; \
|
||||||
((void)n); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_locate_ */ \
|
/* -- skip_locate_ */ \
|
||||||
decl##_node_t *prefix##skip_locate_##decl(decl##_t *slist, decl##_node_t *n) \
|
decl##_node_t **prefix##skip_locate_##decl(decl##_t *slist, \
|
||||||
|
decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
unsigned int i; \
|
||||||
((void)n); \
|
decl##_node_t **path; \
|
||||||
|
decl##_node_t *elm = slist->slh_head; \
|
||||||
|
\
|
||||||
|
if (n == NULL) \
|
||||||
|
return NULL; \
|
||||||
|
\
|
||||||
|
i = slist->max + 1; \
|
||||||
|
ARRAY_ALLOC(path, decl##_node_t, i); \
|
||||||
|
ARRAY_SET_LENGTH(path, 1); \
|
||||||
|
i = slist->level; \
|
||||||
|
if (path == NULL) \
|
||||||
|
return NULL; \
|
||||||
|
\
|
||||||
|
/* Find the node that matches `node` or NULL. */ \
|
||||||
|
do { \
|
||||||
|
while (elm && \
|
||||||
|
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
||||||
|
slist->aux) < 0) \
|
||||||
|
elm = elm->field.sle_next[i]; \
|
||||||
|
path[i + 1] = elm; \
|
||||||
|
ARRAY_SET_LENGTH(path, ARRAY_LENGTH(path) + 1); \
|
||||||
|
} while (i--); \
|
||||||
|
elm = elm->field.sle_next[0]; \
|
||||||
|
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
||||||
|
path[0] = elm; \
|
||||||
|
return 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) \
|
||||||
{ \
|
{ \
|
||||||
if (n == NULL) \
|
|
||||||
return ENOMEM; \
|
|
||||||
decl##_node_t *prev, *elm = slist->slh_head; \
|
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
|
decl##_node_t *prev, *elm = slist->slh_head; \
|
||||||
decl##_node_t **path; \
|
decl##_node_t **path; \
|
||||||
|
\
|
||||||
|
if (n == NULL) \
|
||||||
|
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 && \
|
||||||
|
@ -311,27 +327,73 @@
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_insert_dup_ */ \
|
/* -- 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); /* TODO */ \
|
((void)slist); \
|
||||||
((void)n); \
|
((void)n); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
|
*/ \
|
||||||
\
|
\
|
||||||
/* -- skip_update_ */ \
|
/* -- skip_update_ \
|
||||||
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *n) \
|
* Locates a node in the list that equals the `new` node and then \
|
||||||
|
* uses the `update_node_blk` to update the contents. \
|
||||||
|
* WARNING: Do not update the portion of the node used for ordering \
|
||||||
|
* (e.g. `key`) unless you really know what you're doing. \
|
||||||
|
*/ \
|
||||||
|
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *new) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
decl##_node_t **path, *node; \
|
||||||
((void)n); \
|
\
|
||||||
|
if (!slist || !new) \
|
||||||
|
return -1; \
|
||||||
|
\
|
||||||
|
path = prefix##skip_locate_##decl(slist, new); \
|
||||||
|
if (ARRAY_SIZE(path) > 0) { \
|
||||||
|
node = path[0]; \
|
||||||
|
ARRAY_FREE(path); \
|
||||||
|
update_node_blk; \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
} \
|
||||||
|
return -1; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_delete_ */ \
|
/* -- skip_remove_ */ \
|
||||||
int prefix##skip_delete_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_remove_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
size_t i, s; \
|
||||||
((void)n); \
|
decl##_node_t **path, *node; \
|
||||||
|
\
|
||||||
|
if (!slist || !n) \
|
||||||
|
return -1; \
|
||||||
|
if (slist->length == 0) \
|
||||||
|
return 0; \
|
||||||
|
\
|
||||||
|
path = prefix##skip_locate_##decl(slist, n); \
|
||||||
|
s = ARRAY_LENGTH(path); \
|
||||||
|
node = path[0]; \
|
||||||
|
if (s > 0) { \
|
||||||
|
node->field.sle_next[0]->field.sle_prev = node->field.sle_prev; \
|
||||||
|
for (i = 1; i < s; i++) { \
|
||||||
|
if (path[i]->field.sle_next[i - 1] != node) \
|
||||||
|
break; \
|
||||||
|
path[i]->field.sle_next[i - 1] = node->field.sle_next[i - 1]; \
|
||||||
|
if (path[i]->field.sle_next[i - 1] == slist->slh_tail) { \
|
||||||
|
size_t h = ARRAY_LENGTH(path[i]->field.sle_next); \
|
||||||
|
ARRAY_SET_LENGTH(path[i]->field.sle_next, h - 1); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
ARRAY_FREE(path); \
|
||||||
|
free_node_blk; \
|
||||||
|
/* Find all levels in the first element in the list that point \
|
||||||
|
at the tail and shrink the level*/ \
|
||||||
|
while (slist->level > 0 && \
|
||||||
|
slist->slh_head->field.sle_next[slist->level] == slist->slh_tail) { \
|
||||||
|
slist->level--; \
|
||||||
|
} \
|
||||||
|
slist->length--; \
|
||||||
|
} \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -369,6 +431,14 @@
|
||||||
\
|
\
|
||||||
/* -- skip_prev_node_ */ \
|
/* -- skip_prev_node_ */ \
|
||||||
int prefix##skip_prev_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_prev_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_destroy_ */ \
|
||||||
|
int prefix##skip_destroy_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
((void)slist); /* TODO */ \
|
((void)slist); /* TODO */ \
|
||||||
((void)n); \
|
((void)n); \
|
||||||
|
@ -385,10 +455,16 @@
|
||||||
#define SKIPLIST_GETTER(decl, prefix, name, ktype, vtype, qblk, rblk) \
|
#define SKIPLIST_GETTER(decl, prefix, name, ktype, vtype, qblk, rblk) \
|
||||||
vtype prefix##skip_##name##_##decl(decl##_t *slist, ktype key) \
|
vtype prefix##skip_##name##_##decl(decl##_t *slist, ktype key) \
|
||||||
{ \
|
{ \
|
||||||
decl##_node_t *node, query; \
|
decl##_node_t **path, *node, query; \
|
||||||
|
\
|
||||||
qblk; \
|
qblk; \
|
||||||
node = prefix##skip_locate_##decl(slist, &query); \
|
path = prefix##skip_locate_##decl(slist, &query); \
|
||||||
|
if (ARRAY_SIZE(path) > 0) { \
|
||||||
|
node = path[0]; \
|
||||||
|
ARRAY_FREE(path); \
|
||||||
rblk; \
|
rblk; \
|
||||||
|
} \
|
||||||
|
return (vtype)0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_DECL_DOT(decl, prefix, field) \
|
#define SKIPLIST_DECL_DOT(decl, prefix, field) \
|
||||||
|
|
Loading…
Reference in a new issue