From 48a09e0c4d59d296e1e3a154a36bca6482ea6661 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Wed, 20 Mar 2024 15:23:27 -0400 Subject: [PATCH] move prev into sle; use sizeof, not offset, add revs to entry --- examples/slm.c | 134 ++++++++++++++++++++++++------------------------- include/sl.h | 48 +++++++++--------- 2 files changed, 92 insertions(+), 90 deletions(-) diff --git a/examples/slm.c b/examples/slm.c index 1ddf0a5..5b125ed 100644 --- a/examples/slm.c +++ b/examples/slm.c @@ -30,18 +30,18 @@ * another, logic you'll provide in SKIP_DECL as a block below. */ struct slex_node { - int key; - int value; - SKIP_ENTRY(slex_node) entries; + int key; + int value; + SKIP_ENTRY(slex_node) entries; }; /* * Generate all the access functions for our type of Skiplist. */ SKIPLIST_DECL( - slex, api_, entries, - /* free node */ { (void)node; }, - /* update node */ { node->value = new->value; }) + slex, api_, entries, + /* free node */ { (void)node; }, + /* update node */ { node->value = new->value; }) /* * Getter @@ -50,7 +50,7 @@ SKIPLIST_DECL( * extract data from within your nodes. */ SKIPLIST_GETTERS( - slex, api_, int, int, { query.key = key; }, { return node->value; }) + slex, api_, int, int, { query.key = key; }, { return node->value; }) /* * Now we need a way to compare the nodes you defined above. @@ -76,13 +76,13 @@ SKIPLIST_GETTERS( int __slm_key_compare(slex_t *list, slex_node_t *a, slex_node_t *b, void *aux) { - (void)list; - (void)aux; - if (a->key < b->key) - return -1; - if (a->key > b->key) - return 1; - return 0; + (void)list; + (void)aux; + if (a->key < b->key) + return -1; + if (a->key > b->key) + return 1; + return 0; } #define DOT @@ -93,71 +93,71 @@ SKIPLIST_DECL_DOT(slex, api_, entries) void sprintf_slex_node(slex_node_t *node, char *buf) { - sprintf(buf, "%d:%d", node->key, node->value); + sprintf(buf, "%d:%d", node->key, node->value); } #endif int main() { - int rc = 0; - /* Allocate and initialize a Skiplist. */ - slex_t *list = (slex_t *)malloc(sizeof(slex_t)); - if (list == NULL) { - rc = ENOMEM; - goto fail; - } - rc = api_skip_init_slex(list, 12, __slm_key_compare); - if (rc) - return rc; - - struct slex_node *n; - - /* Insert 7 key/value pairs into the list. */ - for (int i = -200; i <= 200; i++) { - int v; - slex_node_t new; - rc = api_skip_alloc_node_slex(list, &n); + int rc = 0; + /* Allocate and initialize a Skiplist. */ + slex_t *list = (slex_t *)malloc(sizeof(slex_t)); + if (list == NULL) { + rc = ENOMEM; + goto fail; + } + rc = api_skip_init_slex(list, 12, __slm_key_compare); if (rc) - return rc; - n->key = i; - n->value = i; - 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); - } + return rc; - slex_node_t q; - q.key = 0; - api_skip_remove_slex(list, &q); + struct slex_node *n; -// assert(api_skip_gte_slex(list, -3000000) == -20); - assert(api_skip_gte_slex(list, -2) == -20); - assert(api_skip_gte_slex(list, 0) == 10); -// assert(api_skip_gte_slex(list, 0) == 0); - assert(api_skip_gte_slex(list, 2) == 20); - assert(api_skip_gte_slex(list, 30000000) == 0); + /* Insert 7 key/value pairs into the list. */ + for (int i = -50; i <= 50; i++) { + int v; + slex_node_t new; + rc = api_skip_alloc_node_slex(list, &n); + if (rc) + return rc; + n->key = i; + n->value = i; + 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); + } - assert(api_skip_lte_slex(list, -3000000) == 0); - assert(api_skip_lte_slex(list, -2) == -20); - assert(api_skip_lte_slex(list, 0) == -10); -// assert(api_skip_lte_slex(list, 0) == 0); - assert(api_skip_lte_slex(list, 2) == 20); -// assert(api_skip_lte_slex(list, 30000000) == 20); + slex_node_t q; + q.key = 0; + api_skip_remove_slex(list, &q); - FILE *of = fopen("/tmp/slm.dot", "w"); - if (!of) { - perror("Failed to open file /tmp/slm.dot"); - return EXIT_FAILURE; - } - api_skip_dot_slex(of, list, 0, sprintf_slex_node); - fclose(of); + // assert(api_skip_gte_slex(list, -3000000) == -20); + assert(api_skip_gte_slex(list, -2) == -20); + assert(api_skip_gte_slex(list, 0) == 10); + // assert(api_skip_gte_slex(list, 0) == 0); + assert(api_skip_gte_slex(list, 2) == 20); + assert(api_skip_gte_slex(list, 30000000) == 0); - api_skip_destroy_slex(list); + assert(api_skip_lte_slex(list, -3000000) == 0); + assert(api_skip_lte_slex(list, -2) == -20); + assert(api_skip_lte_slex(list, 0) == -10); + // assert(api_skip_lte_slex(list, 0) == 0); + assert(api_skip_lte_slex(list, 2) == 20); + // assert(api_skip_lte_slex(list, 30000000) == 20); + + FILE *of = fopen("/tmp/slm.dot", "w"); + if (!of) { + perror("Failed to open file /tmp/slm.dot"); + return EXIT_FAILURE; + } + api_skip_dot_slex(of, list, 0, sprintf_slex_node); + fclose(of); + + api_skip_destroy_slex(list); fail:; - return rc; + return rc; } diff --git a/include/sl.h b/include/sl.h index d932a7b..feebf9c 100644 --- a/include/sl.h +++ b/include/sl.h @@ -104,14 +104,16 @@ struct type *slh_tail; \ } -#define SKIP_ENTRY(type) \ - struct { \ - struct __sle { \ - struct type **next; \ - size_t cap; \ - size_t len; \ - } sle; \ - struct type *sle_prev; \ +#define SKIP_ENTRY(type) \ + struct __skiplist_entry { \ + struct __skiplist_idx { \ + struct type *prev, **next; \ + size_t cap, len; \ + } sle; \ + struct __skiplist_revs { \ + struct __skiplist_idx **rev; \ + size_t ref; \ + } **slr; \ } /* @@ -120,7 +122,7 @@ #define SKIP_FIRST(head) ((head)->slh_head) #define SKIP_LAST(head) ((head)->slh_tail) #define SKIP_NEXT(elm, field) ((elm)->field.sle.next[0]) -#define SKIP_PREV(elm, field) ((elm)->field.sle_prev) +#define SKIP_PREV(elm, field) ((elm)->field.sle.prev) #define SKIP_EMPTY(head) ((head)->length == 0) /* @@ -204,8 +206,8 @@ { \ decl##_node_t *n; \ /* Calculate the size of the struct sle within decl##_node_t, multiply \ - by array size. */ \ - size_t sle_arr_sz = (sizeof(size_t) + offsetof(struct __sle, len)) * slist->max; \ + by array size. (16/24 bytes on 32/64 bit systems) */ \ + size_t sle_arr_sz = sizeof(struct __skiplist_idx) * slist->max; \ n = (decl##_node_t *)calloc(1, sizeof(decl##_node_t) + sle_arr_sz); \ if (n == NULL) \ return ENOMEM; \ @@ -239,11 +241,11 @@ slist->slh_head->field.sle.len = slist->max; \ for (i = 0; i < slist->max; i++) \ slist->slh_head->field.sle.next[i] = slist->slh_tail; \ - slist->slh_head->field.sle_prev = NULL; \ + slist->slh_head->field.sle.prev = NULL; \ slist->slh_tail->field.sle.len = slist->max; \ for (i = 0; i < slist->max; i++) \ 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; \ /* NOTE: Here's a testing aid, simply set `max` to a negative number to \ * seed the PRNG in a predictable way and have reproducible random numbers. \ */ \ @@ -283,7 +285,7 @@ /* -- skip_tail_ */ \ decl##_node_t *prefix##skip_tail_##decl(decl##_t *slist) \ { \ - return slist->slh_tail->field.sle_prev; \ + return slist->slh_tail->field.sle.prev; \ } \ \ /* -- __skip_locate_ \ @@ -350,9 +352,9 @@ n->field.sle.next[i] = slist->slh_tail; \ } \ } \ - n->field.sle_prev = path[1]; \ + n->field.sle.prev = path[1]; \ if (n->field.sle.next[0] == slist->slh_tail) { \ - slist->slh_tail->field.sle_prev = n; \ + slist->slh_tail->field.sle.prev = n; \ } \ if (level > slist->level) { \ slist->level = level; \ @@ -453,7 +455,7 @@ return elm; \ } else { \ do { \ - elm = elm->field.sle_prev; \ + elm = elm->field.sle.prev; \ cmp = __skip_key_compare_##decl(slist, elm, n, slist->aux); \ } while (cmp > 0); \ } \ @@ -503,7 +505,7 @@ len = __skip_locate_##decl(slist, n, path); \ node = path[0]; \ if (node) { \ - 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 <= len; i++) { \ if (path[i]->field.sle.next[i - 1] != node) \ break; \ @@ -546,9 +548,9 @@ { \ if (slist == NULL || n == NULL) \ return NULL; \ - if (n->field.sle_prev == slist->slh_head) \ + if (n->field.sle.prev == slist->slh_head) \ return NULL; \ - return n->field.sle_prev; \ + return n->field.sle.prev; \ } \ \ /* -- skip_destroy_ */ \ @@ -769,10 +771,10 @@ fprintf(os, "\"node%zu %p\" [label = \"", nsg, (void *)slist->slh_tail); \ level = tail->field.sle.len - 1; \ do { \ - fprintf(os, " %p", level, (void *)node->field.sle_prev); \ - if (level && node->field.sle_prev != slist->slh_head) \ + fprintf(os, " %p", level, (void *)node->field.sle.prev); \ + if (level && node->field.sle.prev != slist->slh_head) \ fprintf(os, " | "); \ - } while (level-- && node->field.sle_prev != slist->slh_head); \ + } while (level-- && node->field.sle.prev != slist->slh_head); \ fprintf(os, "\" shape = \"record\"];\n"); \ } \ \