pull up struct, rename
This commit is contained in:
parent
0f3b3c4f82
commit
a723597bdc
|
@ -29,7 +29,7 @@
|
|||
|
||||
//define SNAPSHOTS
|
||||
//define DOT
|
||||
#define TEST_ARRAY_SIZE 2000
|
||||
#define TEST_ARRAY_SIZE 10
|
||||
|
||||
|
||||
/*
|
||||
|
@ -165,7 +165,7 @@ int_to_roman_numeral(int num)
|
|||
char *sym[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; // Symbols for key values
|
||||
// The maximum length of the Roman numeral representation for the maximum signed 64-bit integer would be approximately 19 * 3 = 57 characters, assuming
|
||||
// every digit is represented by its Roman numeral equivalent up to 3 repetitions. Therefore, 64 should be more than enough.
|
||||
char *res = (char *)calloc(64, sizeof(char));
|
||||
char *res = (char *)calloc(4096, sizeof(char));
|
||||
int i = 0;
|
||||
if (num < 0) {
|
||||
res[0] = '-';
|
||||
|
|
342
include/sl.h
342
include/sl.h
|
@ -164,10 +164,8 @@
|
|||
*/
|
||||
#define SKIPLIST_ENTRY(type) \
|
||||
struct __skiplist_##decl_entry { \
|
||||
struct __skiplist_##decl_idx { \
|
||||
struct type *prev, **next; \
|
||||
size_t height; \
|
||||
} sle; \
|
||||
struct type *sle_prev, **sle_next; \
|
||||
size_t sle_height; \
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -247,13 +245,13 @@
|
|||
for (iter = prefix##skip_size_##decl(list), (elm) = prefix##skip_tailf_##decl(list); (elm) != NULL; \
|
||||
iter--, (elm) = prefix##skip_prev_node_##decl(list, elm))
|
||||
|
||||
#define __SKIP_ENTRIES_T2B(field, elm) for (size_t lvl = elm->field.sle.height; lvl != (size_t)-1; lvl--)
|
||||
#define __SKIP_ENTRIES_T2B(field, elm) for (size_t lvl = elm->field.sle_height; lvl != (size_t)-1; lvl--)
|
||||
#define __SKIP_ENTRIES_T2B_FROM(field, elm, off) for (size_t lvl = off; lvl != (size_t)-1; lvl--)
|
||||
#define __SKIP_IS_LAST_ENTRY_T2B() if (lvl == 0)
|
||||
|
||||
#define __SKIP_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl < elm->field.sle.height + 1; lvl++)
|
||||
#define __SKIP_ENTRIES_B2T_FROM(field, elm, off) for (size_t lvl = off; lvl < elm->field.sle.height + 1; lvl++)
|
||||
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle.height)
|
||||
#define __SKIP_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl < elm->field.sle_height + 1; lvl++)
|
||||
#define __SKIP_ENTRIES_B2T_FROM(field, elm, off) for (size_t lvl = off; lvl < elm->field.sle_height + 1; lvl++)
|
||||
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle_height)
|
||||
|
||||
/*
|
||||
* Skip List declarations and access methods.
|
||||
|
@ -265,9 +263,9 @@
|
|||
\
|
||||
/* Skip List structure and type */ \
|
||||
typedef struct decl { \
|
||||
size_t level, length, max; \
|
||||
int (*cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *); \
|
||||
void *aux; \
|
||||
size_t slh_level, slh_length, slh_max, slh_gen; \
|
||||
int (*slh_cmp)(struct decl *, decl##_node_t *, decl##_node_t *, void *); \
|
||||
void *slh_aux; \
|
||||
decl##_node_t *slh_head; \
|
||||
decl##_node_t *slh_tail; \
|
||||
} decl##_t; \
|
||||
|
@ -302,7 +300,7 @@
|
|||
return -1; \
|
||||
if (a == slist->slh_tail || b == slist->slh_head) \
|
||||
return 1; \
|
||||
return slist->cmp(slist, a, b, aux); \
|
||||
return slist->slh_cmp(slist, a, b, aux); \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -335,12 +333,12 @@
|
|||
decl##_node_t *n; \
|
||||
/* Calculate the size of the struct sle within decl##_node_t, multiply \
|
||||
by array size. (16/24 bytes on 32/64 bit systems) */ \
|
||||
size_t sle_arr_sz = sizeof(struct __skiplist_##decl_idx) * slist->max; \
|
||||
size_t sle_arr_sz = sizeof(struct __skiplist_##decl_entry) * slist->slh_max; \
|
||||
n = (decl##_node_t *)calloc(1, sizeof(decl##_node_t) + sle_arr_sz); \
|
||||
if (n == NULL) \
|
||||
return ENOMEM; \
|
||||
n->field.sle.height = 0; \
|
||||
n->field.sle.next = (decl##_node_t **)((uintptr_t)n + sizeof(decl##_node_t)); \
|
||||
n->field.sle_height = 0; \
|
||||
n->field.sle_next = (decl##_node_t **)((uintptr_t)n + sizeof(decl##_node_t)); \
|
||||
*node = n; \
|
||||
return 0; \
|
||||
} \
|
||||
|
@ -356,12 +354,12 @@
|
|||
int rc = 0; \
|
||||
size_t i; \
|
||||
\
|
||||
slist->length = 0; \
|
||||
slist->max = (size_t)(max < 0 ? -max : max); \
|
||||
slist->max = SKIPLIST_MAX_HEIGHT == 1 ? slist->max : SKIPLIST_MAX_HEIGHT; \
|
||||
if (SKIPLIST_MAX_HEIGHT > 1 && slist->max > SKIPLIST_MAX_HEIGHT) \
|
||||
slist->slh_length = 0; \
|
||||
slist->slh_max = (size_t)(max < 0 ? -max : max); \
|
||||
slist->slh_max = SKIPLIST_MAX_HEIGHT == 1 ? slist->slh_max : SKIPLIST_MAX_HEIGHT; \
|
||||
if (SKIPLIST_MAX_HEIGHT > 1 && slist->slh_max > SKIPLIST_MAX_HEIGHT) \
|
||||
return -1; \
|
||||
slist->cmp = cmp; \
|
||||
slist->slh_cmp = cmp; \
|
||||
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \
|
||||
if (rc) \
|
||||
goto fail; \
|
||||
|
@ -369,15 +367,15 @@
|
|||
if (rc) \
|
||||
goto fail; \
|
||||
\
|
||||
slist->slh_head->field.sle.height = 0; \
|
||||
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_height = 0; \
|
||||
for (i = 0; i < slist->slh_max; i++) \
|
||||
slist->slh_head->field.sle_next[i] = slist->slh_tail; \
|
||||
slist->slh_head->field.sle_prev = NULL; \
|
||||
\
|
||||
slist->slh_tail->field.sle.height = slist->max - 1; \
|
||||
for (i = 0; i < slist->max; i++) \
|
||||
slist->slh_tail->field.sle.next[i] = NULL; \
|
||||
slist->slh_tail->field.sle.prev = slist->slh_head; \
|
||||
slist->slh_tail->field.sle_height = slist->slh_max - 1; \
|
||||
for (i = 0; i < slist->slh_max; i++) \
|
||||
slist->slh_tail->field.sle_next[i] = NULL; \
|
||||
slist->slh_tail->field.sle_prev = slist->slh_head; \
|
||||
\
|
||||
/* 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. \
|
||||
|
@ -411,7 +409,7 @@
|
|||
*/ \
|
||||
int prefix##skip_size_##decl(decl##_t *slist) \
|
||||
{ \
|
||||
return slist->length; \
|
||||
return slist->slh_length; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -421,7 +419,7 @@
|
|||
*/ \
|
||||
int prefix##skip_is_empty_##decl(decl##_t *slist) \
|
||||
{ \
|
||||
return slist->length == 0; \
|
||||
return slist->slh_length == 0; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -432,7 +430,7 @@
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_head_##decl(decl##_t *slist) \
|
||||
{ \
|
||||
return slist->slh_head->field.sle.next[0] == slist->slh_tail ? NULL : slist->slh_head->field.sle.next[0]; \
|
||||
return slist->slh_head->field.sle_next[0] == slist->slh_tail ? NULL : slist->slh_head->field.sle_next[0]; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -443,7 +441,7 @@
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_tail_##decl(decl##_t *slist) \
|
||||
{ \
|
||||
return slist->slh_tail->field.sle.prev == slist->slh_head->field.sle.next[0] ? NULL : slist->slh_tail->field.sle.prev; \
|
||||
return slist->slh_tail->field.sle_prev == slist->slh_head->field.sle_next[0] ? NULL : slist->slh_tail->field.sle_prev; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -456,9 +454,9 @@
|
|||
{ \
|
||||
if (slist == NULL || n == NULL) \
|
||||
return NULL; \
|
||||
if (n->field.sle.next[0] == slist->slh_tail) \
|
||||
if (n->field.sle_next[0] == slist->slh_tail) \
|
||||
return NULL; \
|
||||
return n->field.sle.next[0]; \
|
||||
return n->field.sle_next[0]; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -472,9 +470,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; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -499,8 +497,8 @@
|
|||
} while (node != NULL); \
|
||||
\
|
||||
while (node) { \
|
||||
next = node->field.sle.next[0]; \
|
||||
if (next->field.sle.prev) \
|
||||
next = node->field.sle_next[0]; \
|
||||
if (next->field.sle_prev) \
|
||||
free_node_blk; \
|
||||
free(node); \
|
||||
} \
|
||||
|
@ -537,7 +535,7 @@
|
|||
* Locates a node that matches another node updating `path` and then \
|
||||
* returning the length of that path + 1 to the node and the matching \
|
||||
* node in path[0], or NULL at path[0] where there wasn't a match. \
|
||||
* sizeof(path) should be `slist->max + 1` \
|
||||
* sizeof(path) should be `slist->slh_max + 1` \
|
||||
*/ \
|
||||
static size_t __skip_locate_##decl(decl##_t *slist, decl##_node_t *n, decl##_node_t **path) \
|
||||
{ \
|
||||
|
@ -549,15 +547,15 @@
|
|||
return 0; \
|
||||
\
|
||||
/* Find the node that matches `node` or NULL. */ \
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], n, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], n, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
path[i + 1] = elm; \
|
||||
len++; \
|
||||
} while (i--); \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, n, slist->slh_aux) == 0) { \
|
||||
path[0] = elm; \
|
||||
} \
|
||||
return len; \
|
||||
|
@ -582,11 +580,11 @@
|
|||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->max + 1); \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->max + 1)); \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->slh_max + 1)); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
len = __skip_locate_##decl(slist, new, path); \
|
||||
|
@ -597,9 +595,9 @@
|
|||
return -1; \
|
||||
} \
|
||||
/* Coin toss to determine level of this new node [0, max) */ \
|
||||
cur_height = slist->slh_head->field.sle.height; \
|
||||
new_height = __skip_toss_##decl(slist->max); \
|
||||
new->field.sle.height = new_height; \
|
||||
cur_height = slist->slh_head->field.sle_height; \
|
||||
new_height = __skip_toss_##decl(slist->slh_max); \
|
||||
new->field.sle_height = new_height; \
|
||||
/* Trim the path to at most the new height for the new node. */ \
|
||||
if (new_height > cur_height) { \
|
||||
for (i = cur_height + 1; i <= new_height; i++) { \
|
||||
|
@ -609,7 +607,7 @@
|
|||
/* Ensure all next[] point to tail. */ \
|
||||
__SKIP_ENTRIES_B2T(field, new) \
|
||||
{ \
|
||||
new->field.sle.next[lvl] = slist->slh_tail; \
|
||||
new->field.sle_next[lvl] = slist->slh_tail; \
|
||||
} \
|
||||
/* Adjust all forward pointers for each element in the path. */ \
|
||||
for (i = 0; i <= new_height; i++) { \
|
||||
|
@ -617,34 +615,34 @@
|
|||
next[i] for our new node. Also, don't set the tail's next[i] \
|
||||
because it is always NULL. */ \
|
||||
if (path[i + 1] != slist->slh_tail) { \
|
||||
new->field.sle.next[i] = path[i + 1]->field.sle.next[i]; \
|
||||
path[i + 1]->field.sle.next[i] = new; \
|
||||
new->field.sle_next[i] = path[i + 1]->field.sle_next[i]; \
|
||||
path[i + 1]->field.sle_next[i] = new; \
|
||||
loc = path[i + 1] == slist->slh_head ? i : loc; \
|
||||
} else { \
|
||||
new->field.sle.next[i] = slist->slh_tail; \
|
||||
new->field.sle_next[i] = slist->slh_tail; \
|
||||
} \
|
||||
} \
|
||||
/* Ensure all slh_head->next[] above loc point to tail. */ \
|
||||
if (path[1] == slist->slh_head) { \
|
||||
__SKIP_ENTRIES_B2T_FROM(field, slist->slh_head, loc + 1) \
|
||||
{ \
|
||||
slist->slh_head->field.sle.next[lvl] = slist->slh_tail; \
|
||||
slist->slh_head->field.sle_next[lvl] = slist->slh_tail; \
|
||||
} \
|
||||
} \
|
||||
/* Adujust the previous pointers in the nodes. */ \
|
||||
new->field.sle.prev = path[1]; \
|
||||
new->field.sle.next[0]->field.sle.prev = new; \
|
||||
new->field.sle_prev = path[1]; \
|
||||
new->field.sle_next[0]->field.sle_prev = new; \
|
||||
/* Account for insert at tail. */ \
|
||||
if (new->field.sle.next[0] == slist->slh_tail) { \
|
||||
slist->slh_tail->field.sle.prev = new; \
|
||||
if (new->field.sle_next[0] == slist->slh_tail) { \
|
||||
slist->slh_tail->field.sle_prev = new; \
|
||||
} \
|
||||
/* Adjust the head/tail boundary node heights if necessary. */ \
|
||||
if (new_height > cur_height) { \
|
||||
slist->slh_head->field.sle.height = new_height; \
|
||||
slist->slh_tail->field.sle.height = new_height; \
|
||||
slist->slh_head->field.sle_height = new_height; \
|
||||
slist->slh_tail->field.sle_height = new_height; \
|
||||
} \
|
||||
/* Increase our list length (aka. size, count, etc.) by one. */ \
|
||||
slist->length++; \
|
||||
slist->slh_length++; \
|
||||
\
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
free(path); \
|
||||
|
@ -690,14 +688,14 @@
|
|||
if (slist == NULL || n == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
\
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], n, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], n, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
} while (i--); \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, n, slist->aux) == 0) { \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, n, slist->slh_aux) == 0) { \
|
||||
return elm; \
|
||||
} \
|
||||
return NULL; \
|
||||
|
@ -722,15 +720,15 @@
|
|||
if (slist == NULL || query == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
\
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], query, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], query, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
} while (i--); \
|
||||
do { \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->aux); \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->slh_aux); \
|
||||
} while (cmp < 0); \
|
||||
return elm; \
|
||||
} \
|
||||
|
@ -754,15 +752,15 @@
|
|||
if (slist == NULL || query == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
\
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], query, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], query, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
} while (i--); \
|
||||
do { \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->aux); \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->slh_aux); \
|
||||
} while (cmp <= 0); \
|
||||
return elm; \
|
||||
} \
|
||||
|
@ -786,19 +784,19 @@
|
|||
if (slist == NULL || query == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
\
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], query, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], query, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
} while (i--); \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, query, slist->aux) == 0) { \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
if (__skip_key_compare_##decl(slist, elm, query, slist->slh_aux) == 0) { \
|
||||
return elm; \
|
||||
} else { \
|
||||
do { \
|
||||
elm = elm->field.sle.prev; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->aux); \
|
||||
elm = elm->field.sle_prev; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->slh_aux); \
|
||||
} while (cmp >= 0); \
|
||||
} \
|
||||
return elm; \
|
||||
|
@ -822,16 +820,16 @@
|
|||
if (slist == NULL || query == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
i = slist->slh_head->field.sle.height; \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
\
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle.next[i] && __skip_key_compare_##decl(slist, elm->field.sle.next[i], query, slist->aux) < 0) \
|
||||
elm = elm->field.sle.next[i]; \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_key_compare_##decl(slist, elm->field.sle_next[i], query, slist->slh_aux) < 0) \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
} while (i--); \
|
||||
elm = elm->field.sle.next[0]; \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
do { \
|
||||
elm = elm->field.sle.prev; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->aux); \
|
||||
elm = elm->field.sle_prev; \
|
||||
cmp = __skip_key_compare_##decl(slist, elm, query, slist->slh_aux); \
|
||||
} while (cmp >= 0); \
|
||||
return elm; \
|
||||
} \
|
||||
|
@ -889,11 +887,11 @@
|
|||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->max + 1); \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->max + 1)); \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->slh_max + 1)); \
|
||||
\
|
||||
__skip_locate_##decl(slist, new, path); \
|
||||
node = path[0]; \
|
||||
|
@ -921,16 +919,16 @@
|
|||
\
|
||||
if (slist == NULL || n == NULL) \
|
||||
return -1; \
|
||||
if (slist->length == 0) \
|
||||
if (slist->slh_length == 0) \
|
||||
return 0; \
|
||||
\
|
||||
/* Allocate a buffer */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->max + 1); \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->max + 1)); \
|
||||
memset(path, 0, sizeof(sizeof(decl##_node_t *) * slist->slh_max + 1)); \
|
||||
\
|
||||
/* Attempt to locate the node in the list. */ \
|
||||
len = __skip_locate_##decl(slist, n, path); \
|
||||
|
@ -938,24 +936,24 @@
|
|||
if (node) { \
|
||||
/* We found it, set the next->prev to the node->prev keeping in mind \
|
||||
that the next node might be the tail). */ \
|
||||
node->field.sle.next[0]->field.sle.prev = node->field.sle.prev; \
|
||||
node->field.sle_next[0]->field.sle_prev = node->field.sle_prev; \
|
||||
/* Walk the path, stop when the next node is not the one we're \
|
||||
removing. At each step along our walk... */ \
|
||||
for (i = 0; i < len; i++) { \
|
||||
if (path[i + 1]->field.sle.next[i] != node) \
|
||||
if (path[i + 1]->field.sle_next[i] != node) \
|
||||
break; \
|
||||
/* ... adjust the next pointer at that level. */ \
|
||||
path[i + 1]->field.sle.next[i] = node->field.sle.next[i]; \
|
||||
path[i + 1]->field.sle_next[i] = node->field.sle_next[i]; \
|
||||
/* Adjust the height so we're only pointing at the tail once at \
|
||||
the top so we don't waste steps later when searching. */ \
|
||||
if (path[i + 1]->field.sle.next[i] == slist->slh_tail) { \
|
||||
height = path[i + 1]->field.sle.height; \
|
||||
path[i + 1]->field.sle.height = height - 1; \
|
||||
if (path[i + 1]->field.sle_next[i] == slist->slh_tail) { \
|
||||
height = path[i + 1]->field.sle_height; \
|
||||
path[i + 1]->field.sle_height = height - 1; \
|
||||
} \
|
||||
} \
|
||||
/* Account for delete at tail. */ \
|
||||
if (node->field.sle.next[0] == slist->slh_tail) { \
|
||||
slist->slh_tail->field.sle.prev = n->field.sle.prev; \
|
||||
if (node->field.sle_next[0] == slist->slh_tail) { \
|
||||
slist->slh_tail->field.sle_prev = n->field.sle_prev; \
|
||||
} \
|
||||
\
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
|
@ -965,12 +963,12 @@
|
|||
\
|
||||
/* Reduce the height of the header. */ \
|
||||
i = 0; \
|
||||
while (slist->slh_head->field.sle.next[i] != slist->slh_tail && i < slist->slh_head->field.sle.height) \
|
||||
while (slist->slh_head->field.sle_next[i] != slist->slh_tail && i < slist->slh_head->field.sle_height) \
|
||||
i++; \
|
||||
slist->slh_head->field.sle.height = i; \
|
||||
slist->slh_tail->field.sle.height = i; \
|
||||
slist->slh_head->field.sle_height = i; \
|
||||
slist->slh_tail->field.sle_height = i; \
|
||||
\
|
||||
slist->length--; \
|
||||
slist->slh_length--; \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
|
@ -993,6 +991,22 @@
|
|||
return; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
* -- skip_snapshot_ \
|
||||
* \
|
||||
* A snapshot is a read-only view of a Skip List at a point in time. Once \
|
||||
* taken, a snapshot must be restored or disposed. Any number of snapshots \
|
||||
* can be created. \
|
||||
*/ \
|
||||
size_t prefix##skip_snapshot_##decl(decl##_t *slist) \
|
||||
{ \
|
||||
if (slist == NULL) \
|
||||
return 0; \
|
||||
\
|
||||
slist->slh_gen++; \
|
||||
return slist->slh_gen; \
|
||||
} \
|
||||
\
|
||||
/* Archive of a Skip List */ \
|
||||
typedef struct decl##_archive { \
|
||||
decl##_t list; \
|
||||
|
@ -1016,7 +1030,7 @@
|
|||
if (slist == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
bytes = sizeof(decl##_archive_t) + (slist->length * sizeof(decl##_node_t)); \
|
||||
bytes = sizeof(decl##_archive_t) + (slist->slh_length * sizeof(decl##_node_t)); \
|
||||
node = prefix##skip_head_##decl(slist); \
|
||||
while (node) { \
|
||||
sizeof_entry_blk; \
|
||||
|
@ -1029,8 +1043,8 @@
|
|||
return NULL; \
|
||||
\
|
||||
archive->bytes = bytes; \
|
||||
archive->list.length = slist->length; \
|
||||
archive->list.max = slist->max; \
|
||||
archive->list.slh_length = slist->slh_length; \
|
||||
archive->list.slh_max = slist->slh_max; \
|
||||
archive->nodes = (decl##_node_t *)(archive + sizeof(decl##_archive_t)); \
|
||||
\
|
||||
i = 0; \
|
||||
|
@ -1063,8 +1077,8 @@
|
|||
if (slist == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
slist->cmp = cmp; \
|
||||
slist->max = archive->list.max; \
|
||||
slist->slh_cmp = cmp; \
|
||||
slist->slh_max = archive->list.slh_max; \
|
||||
\
|
||||
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \
|
||||
if (rc) \
|
||||
|
@ -1073,24 +1087,24 @@
|
|||
if (rc) \
|
||||
goto fail; \
|
||||
\
|
||||
slist->slh_head->field.sle.height = 0; \
|
||||
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_height = 0; \
|
||||
for (i = 0; i < slist->slh_max; i++) \
|
||||
slist->slh_head->field.sle_next[i] = slist->slh_tail; \
|
||||
slist->slh_head->field.sle_prev = NULL; \
|
||||
\
|
||||
slist->slh_tail->field.sle.height = slist->max; \
|
||||
for (i = 0; i < slist->max; i++) \
|
||||
slist->slh_tail->field.sle.next[i] = NULL; \
|
||||
slist->slh_tail->field.sle.prev = slist->slh_head; \
|
||||
slist->slh_tail->field.sle_height = slist->slh_max; \
|
||||
for (i = 0; i < slist->slh_max; i++) \
|
||||
slist->slh_tail->field.sle_next[i] = NULL; \
|
||||
slist->slh_tail->field.sle_prev = slist->slh_head; \
|
||||
\
|
||||
i = 0; \
|
||||
while (archive->list.length > 0) { \
|
||||
while (archive->list.slh_length > 0) { \
|
||||
decl##_node_t *n = (decl##_node_t *)archive->nodes + (i++ * sizeof(decl##_node_t)); \
|
||||
node = (decl##_node_t *)&n; \
|
||||
rc = prefix##skip_alloc_node_##decl(slist, &new); \
|
||||
archive_node_blk; \
|
||||
__skip_insert_##decl(slist, new, 1); \
|
||||
archive->list.length--; \
|
||||
archive->list.slh_length--; \
|
||||
} \
|
||||
return slist; \
|
||||
fail:; \
|
||||
|
@ -1118,7 +1132,7 @@
|
|||
{ \
|
||||
unsigned long nth, n_err = 0; \
|
||||
decl##_node_t *node, *prev, *next; \
|
||||
struct __skiplist_##decl_idx *this; \
|
||||
struct __skiplist_##decl_entry *this; \
|
||||
\
|
||||
if (slist == NULL) { \
|
||||
__skip_integrity_failure_##decl("slist was NULL, nothing to check\n"); \
|
||||
|
@ -1140,22 +1154,22 @@
|
|||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (slist->cmp == NULL) { \
|
||||
if (slist->slh_cmp == NULL) { \
|
||||
__skip_integrity_failure_##decl("skiplist comparison function (cmp) is NULL\n"); \
|
||||
n_err++; \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (slist->max < 1) { \
|
||||
if (slist->slh_max < 1) { \
|
||||
__skip_integrity_failure_##decl("skiplist max level must be 1 at minimum\n"); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (slist->level >= slist->max) { \
|
||||
if (slist->slh_level >= slist->slh_max) { \
|
||||
/* level is 0-based, max of 12 means level cannot be > 11 */ \
|
||||
__skip_integrity_failure_##decl("skiplist level %lu in header was >= max %lu\n", slist->level, slist->max); \
|
||||
__skip_integrity_failure_##decl("skiplist level %lu in header was >= max %lu\n", slist->slh_level, slist->slh_max); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
|
@ -1168,8 +1182,9 @@
|
|||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (SKIPLIST_MAX_HEIGHT > 1 && slist->max > SKIPLIST_MAX_HEIGHT) { \
|
||||
__skip_integrity_failure_##decl("slist->max %lu cannot be greater than SKIPLIST_MAX_HEIGHT %lu\n", slist->max, (size_t)SKIPLIST_MAX_HEIGHT); \
|
||||
if (SKIPLIST_MAX_HEIGHT > 1 && slist->slh_max > SKIPLIST_MAX_HEIGHT) { \
|
||||
__skip_integrity_failure_##decl("slist->slh_max %lu cannot be greater than SKIPLIST_MAX_HEIGHT %lu\n", slist->slh_max, \
|
||||
(size_t)SKIPLIST_MAX_HEIGHT); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
|
@ -1179,26 +1194,26 @@
|
|||
node = slist->slh_head; \
|
||||
__SKIP_ENTRIES_B2T(field, node) \
|
||||
{ \
|
||||
if (node->field.sle.next[lvl] == NULL) { \
|
||||
if (node->field.sle_next[lvl] == NULL) { \
|
||||
__skip_integrity_failure_##decl("the head's %lu next node should not be NULL\n", lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
n = lvl; \
|
||||
if (node->field.sle.next[lvl] == slist->slh_tail) \
|
||||
if (node->field.sle_next[lvl] == slist->slh_tail) \
|
||||
break; \
|
||||
} \
|
||||
n++; \
|
||||
__SKIP_ENTRIES_B2T_FROM(field, node, n) \
|
||||
{ \
|
||||
if (node->field.sle.next[lvl] == NULL) { \
|
||||
if (node->field.sle_next[lvl] == NULL) { \
|
||||
__skip_integrity_failure_##decl("the head's %lu next node should not be NULL\n", lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
if (node->field.sle.next[lvl] != slist->slh_tail) { \
|
||||
if (node->field.sle_next[lvl] != slist->slh_tail) { \
|
||||
__skip_integrity_failure_##decl("after internal nodes, the head's %lu next node should always be the tail\n", lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
|
@ -1206,8 +1221,8 @@
|
|||
} \
|
||||
} \
|
||||
\
|
||||
if (slist->length > 0 && slist->slh_tail->field.sle.prev == slist->slh_head) { \
|
||||
__skip_integrity_failure_##decl("slist->length is 0, but tail->prev == head, not an internal node\n"); \
|
||||
if (slist->slh_length > 0 && slist->slh_tail->field.sle_prev == slist->slh_head) { \
|
||||
__skip_integrity_failure_##decl("slist->slh_length is 0, but tail->prev == head, not an internal node\n"); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
|
@ -1220,23 +1235,23 @@
|
|||
/* Validate each node */ \
|
||||
SKIPLIST_FOREACH_H2T(decl, prefix, slist, node, nth) \
|
||||
{ \
|
||||
this = &node->field.sle; \
|
||||
this = &node->field; \
|
||||
\
|
||||
if (this->height >= slist->max) { \
|
||||
__skip_integrity_failure_##decl("the %luth node's [%p] height %lu is >= max %lu\n", nth, (void *)node, this->height, slist->max); \
|
||||
if (this->sle_height >= slist->slh_max) { \
|
||||
__skip_integrity_failure_##decl("the %luth node's [%p] height %lu is >= max %lu\n", nth, (void *)node, this->sle_height, slist->slh_max); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (this->next == NULL) { \
|
||||
if (this->sle_next == NULL) { \
|
||||
__skip_integrity_failure_##decl("the %luth node's [%p] next field should never NULL\n", nth, (void *)node); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (this->prev == NULL) { \
|
||||
if (this->sle_prev == NULL) { \
|
||||
__skip_integrity_failure_##decl("the %luth node [%p] prev field should never NULL\n", nth, (void *)node); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
|
@ -1246,25 +1261,25 @@
|
|||
size_t n = 0; \
|
||||
__SKIP_ENTRIES_B2T(field, node) \
|
||||
{ \
|
||||
if (this->next[lvl] == NULL) { \
|
||||
if (this->sle_next[lvl] == NULL) { \
|
||||
__skip_integrity_failure_##decl("the %luth node's next[%lu] should not be NULL\n", nth, lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
n = lvl; \
|
||||
if (this->next[lvl] == slist->slh_tail) \
|
||||
if (this->sle_next[lvl] == slist->slh_tail) \
|
||||
break; \
|
||||
} \
|
||||
n++; \
|
||||
__SKIP_ENTRIES_B2T_FROM(field, node, n) \
|
||||
{ \
|
||||
if (this->next[lvl] == NULL) { \
|
||||
if (this->sle_next[lvl] == NULL) { \
|
||||
__skip_integrity_failure_##decl("after the %lunth the %luth node's next[%lu] should not be NULL\n", n, nth, lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} else if (this->next[lvl] != slist->slh_tail) { \
|
||||
} else if (this->sle_next[lvl] != slist->slh_tail) { \
|
||||
__skip_integrity_failure_##decl("after the %lunth the %luth node's next[%lu] should point to the tail\n", n, nth, lvl); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
|
@ -1272,7 +1287,7 @@
|
|||
} \
|
||||
} \
|
||||
\
|
||||
decl##_node_t *a = (decl##_node_t *)(uintptr_t)this->next; \
|
||||
decl##_node_t *a = (decl##_node_t *)(uintptr_t)this->sle_next; \
|
||||
decl##_node_t *b = (decl##_node_t *)(intptr_t)((uintptr_t)node + sizeof(decl##_node_t)); \
|
||||
if (a != b) { \
|
||||
__skip_integrity_failure_##decl("the %luth node's [%p] next field isn't at the proper offset relative to the node\n", nth, (void *)node); \
|
||||
|
@ -1281,37 +1296,37 @@
|
|||
return n_err; \
|
||||
} \
|
||||
\
|
||||
next = this->next[0]; \
|
||||
prev = this->prev; \
|
||||
if (__skip_key_compare_##decl(slist, node, node, slist->aux) != 0) { \
|
||||
next = this->sle_next[0]; \
|
||||
prev = this->sle_prev; \
|
||||
if (__skip_key_compare_##decl(slist, node, node, slist->slh_aux) != 0) { \
|
||||
__skip_integrity_failure_##decl("the %luth node [%p] is not equal to itself\n", nth, (void *)node); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (__skip_key_compare_##decl(slist, node, prev, slist->aux) < 0) { \
|
||||
if (__skip_key_compare_##decl(slist, node, prev, slist->slh_aux) < 0) { \
|
||||
__skip_integrity_failure_##decl("the %luth node [%p] is not greater than the prev node [%p]\n", nth, (void *)node, (void *)prev); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (__skip_key_compare_##decl(slist, node, next, slist->aux) > 0) { \
|
||||
if (__skip_key_compare_##decl(slist, node, next, slist->slh_aux) > 0) { \
|
||||
__skip_integrity_failure_##decl("the %luth node [%p] is not less than the next node [%p]\n", nth, (void *)node, (void *)next); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (__skip_key_compare_##decl(slist, prev, node, slist->aux) > 0) { \
|
||||
if (__skip_key_compare_##decl(slist, prev, node, slist->slh_aux) > 0) { \
|
||||
__skip_integrity_failure_##decl("the prev node [%p] is not less than the %luth node [%p]\n", (void *)prev, nth, (void *)node); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
} \
|
||||
\
|
||||
if (__skip_key_compare_##decl(slist, next, node, slist->aux) < 0) { \
|
||||
if (__skip_key_compare_##decl(slist, next, node, slist->slh_aux) < 0) { \
|
||||
__skip_integrity_failure_##decl("the next node [%p] is not greater than the %luth node [%p]\n", (void *)next, nth, (void *)node); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
|
@ -1319,8 +1334,9 @@
|
|||
} \
|
||||
} \
|
||||
\
|
||||
if (slist->length != nth) { \
|
||||
__skip_integrity_failure_slex("slist->length (%lu) doesn't match the count (%lu) of nodes between the head and tail\n", slist->length, nth); \
|
||||
if (slist->slh_length != nth) { \
|
||||
__skip_integrity_failure_slex("slist->slh_length (%lu) doesn't match the count (%lu) of nodes between the head and tail\n", slist->slh_length, \
|
||||
nth); \
|
||||
n_err++; \
|
||||
if (flags) \
|
||||
return n_err; \
|
||||
|
@ -1474,7 +1490,7 @@
|
|||
if (from == NULL || to == NULL) \
|
||||
return 0; \
|
||||
\
|
||||
while (n->field.sle.prev != from) { \
|
||||
while (n->field.sle_prev != from) { \
|
||||
w++; \
|
||||
n = prefix##skip_prev_node_##decl(slist, n); \
|
||||
} \
|
||||
|
@ -1504,7 +1520,7 @@
|
|||
fflush(os); \
|
||||
__SKIP_ENTRIES_T2B(field, node) \
|
||||
{ \
|
||||
next = (node->field.sle.next[lvl] == slist->slh_tail) ? NULL : node->field.sle.next[lvl]; \
|
||||
next = (node->field.sle_next[lvl] == slist->slh_tail) ? NULL : node->field.sle_next[lvl]; \
|
||||
width = __skip_dot_width_##decl(slist, node, next ? next : slist->slh_tail); \
|
||||
fprintf(os, " { <w%lu> %lu | <f%lu> ", lvl, width, lvl); \
|
||||
if (next) \
|
||||
|
@ -1515,9 +1531,9 @@
|
|||
} \
|
||||
if (fn) { \
|
||||
fn(node, buf); \
|
||||
fprintf(os, " <f0> \u219F %lu \u226B %s \"\n", node->field.sle.height + 1, buf); \
|
||||
fprintf(os, " <f0> \u219F %lu \u226B %s \"\n", node->field.sle_height + 1, buf); \
|
||||
} else { \
|
||||
fprintf(os, " <f0> \u219F %lu \"\n", node->field.sle.height); \
|
||||
fprintf(os, " <f0> \u219F %lu \"\n", node->field.sle_height); \
|
||||
} \
|
||||
fprintf(os, "shape = \"record\"\n"); \
|
||||
fprintf(os, "];\n"); \
|
||||
|
@ -1526,7 +1542,7 @@
|
|||
/* Now edges */ \
|
||||
__SKIP_ENTRIES_B2T(field, node) \
|
||||
{ \
|
||||
next = (node->field.sle.next[lvl] == slist->slh_tail) ? NULL : node->field.sle.next[lvl]; \
|
||||
next = (node->field.sle_next[lvl] == slist->slh_tail) ? NULL : node->field.sle_next[lvl]; \
|
||||
__skip_dot_write_node_##decl(os, nsg, node); \
|
||||
fprintf(os, ":f%lu -> ", lvl); \
|
||||
__skip_dot_write_node_##decl(os, nsg, next); \
|
||||
|
@ -1605,7 +1621,7 @@
|
|||
fprintf(os, "\"HeadNode%lu\" [\n", nsg); \
|
||||
fprintf(os, "label = \""); \
|
||||
\
|
||||
if (slist->slh_head->field.sle.height || slist->slh_head->field.sle.next[0] != slist->slh_tail) \
|
||||
if (slist->slh_head->field.sle_height || slist->slh_head->field.sle_next[0] != slist->slh_tail) \
|
||||
letitgo = 1; \
|
||||
\
|
||||
/* Write out the fields */ \
|
||||
|
@ -1613,7 +1629,7 @@
|
|||
if (letitgo) { \
|
||||
__SKIP_ENTRIES_T2B(field, node) \
|
||||
{ \
|
||||
next = (node->field.sle.next[lvl] == slist->slh_tail) ? NULL : node->field.sle.next[lvl]; \
|
||||
next = (node->field.sle_next[lvl] == slist->slh_tail) ? NULL : node->field.sle_next[lvl]; \
|
||||
width = __skip_dot_width_##decl(slist, node, next ? next : slist->slh_tail); \
|
||||
fprintf(os, "{ %lu | <f%lu> ", width, lvl); \
|
||||
if (next) \
|
||||
|
@ -1637,7 +1653,7 @@
|
|||
node = slist->slh_head; \
|
||||
__SKIP_ENTRIES_B2T(field, node) \
|
||||
{ \
|
||||
next = (node->field.sle.next[lvl] == slist->slh_tail) ? NULL : node->field.sle.next[lvl]; \
|
||||
next = (node->field.sle_next[lvl] == slist->slh_tail) ? NULL : node->field.sle_next[lvl]; \
|
||||
fprintf(os, "\"HeadNode%lu\":f%lu -> ", nsg, lvl); \
|
||||
__skip_dot_write_node_##decl(os, nsg, next); \
|
||||
fprintf(os, ":w%lu [];\n", lvl); \
|
||||
|
@ -1664,9 +1680,9 @@
|
|||
__skip_dot_write_node_##decl(os, nsg, NULL); \
|
||||
fprintf(os, " [label = \""); \
|
||||
node = slist->slh_tail; \
|
||||
size_t th = slist->slh_head->field.sle.height; \
|
||||
size_t th = slist->slh_head->field.sle_height; \
|
||||
for (size_t lvl = th; lvl != (size_t)-1; lvl--) { \
|
||||
next = (node->field.sle.next[lvl] == slist->slh_tail) ? NULL : node->field.sle.next[lvl]; \
|
||||
next = (node->field.sle_next[lvl] == slist->slh_tail) ? NULL : node->field.sle_next[lvl]; \
|
||||
fprintf(os, "<w%lu> NULL", lvl); \
|
||||
__SKIP_IS_LAST_ENTRY_T2B() continue; \
|
||||
fprintf(os, " | "); \
|
||||
|
|
Loading…
Reference in a new issue