more dot
This commit is contained in:
parent
a3e01e9bd6
commit
66b2dda55c
1 changed files with 672 additions and 694 deletions
84
include/sl.h
84
include/sl.h
|
@ -99,8 +99,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SKIP_COMPARATOR(list, type, fn) \
|
#define SKIP_COMPARATOR(list, type, fn) \
|
||||||
int __skip_cmp_##type(struct list *head, struct type *a, struct type *b, \
|
int __skip_cmp_##type(struct list *head, struct type *a, struct type *b, void *aux) \
|
||||||
void *aux) \
|
|
||||||
{ \
|
{ \
|
||||||
if (a == b) \
|
if (a == b) \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
@ -136,8 +135,7 @@
|
||||||
* 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; \
|
||||||
|
@ -179,8 +177,7 @@
|
||||||
/* -- 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; \
|
||||||
|
@ -242,8 +239,7 @@
|
||||||
* Locates a node that matches another node returning the path to that \
|
* Locates a node that matches another node returning the path to that \
|
||||||
* node and the match in path[0]. \
|
* node and the match in path[0]. \
|
||||||
*/ \
|
*/ \
|
||||||
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; \
|
||||||
|
@ -261,9 +257,7 @@
|
||||||
\
|
\
|
||||||
/* 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, slist->aux) < 0) \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
|
||||||
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); \
|
||||||
|
@ -278,8 +272,7 @@
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- __skip_insert_ */ \
|
/* -- __skip_insert_ */ \
|
||||||
static int __skip_insert_##decl(decl##_t *slist, decl##_node_t *n, \
|
static int __skip_insert_##decl(decl##_t *slist, decl##_node_t *n, int flags) \
|
||||||
int flags) \
|
|
||||||
{ \
|
{ \
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
decl##_node_t *prev, *elm = slist->slh_head; \
|
decl##_node_t *prev, *elm = slist->slh_head; \
|
||||||
|
@ -295,9 +288,7 @@
|
||||||
\
|
\
|
||||||
/* 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, slist->aux) < 0) \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
|
||||||
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); \
|
||||||
|
@ -361,9 +352,7 @@
|
||||||
i = slist->level; \
|
i = slist->level; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
while (elm && \
|
while (elm && __skip_key_compare_##decl(slist, elm->field.sle_next[i], n, slist->aux) < 0) \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
|
||||||
slist->aux) < 0) \
|
|
||||||
elm = elm->field.sle_next[i]; \
|
elm = elm->field.sle_next[i]; \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
elm = elm->field.sle_next[0]; \
|
elm = elm->field.sle_next[0]; \
|
||||||
|
@ -376,8 +365,7 @@
|
||||||
/* -- skip_find_gte \
|
/* -- skip_find_gte \
|
||||||
* Return the matching node or the next greater node after that. \
|
* Return the matching node or the next greater node after that. \
|
||||||
*/ \
|
*/ \
|
||||||
decl##_node_t *prefix##skip_find_gte_##decl(decl##_t *slist, \
|
decl##_node_t *prefix##skip_find_gte_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
decl##_node_t *n) \
|
|
||||||
{ \
|
{ \
|
||||||
int cmp; \
|
int cmp; \
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
|
@ -389,9 +377,7 @@
|
||||||
i = slist->level; \
|
i = slist->level; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
while (elm && \
|
while (elm && __skip_key_compare_##decl(slist, elm->field.sle_next[i], n, slist->aux) < 0) \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
|
||||||
slist->aux) < 0) \
|
|
||||||
elm = elm->field.sle_next[i]; \
|
elm = elm->field.sle_next[i]; \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
do { \
|
do { \
|
||||||
|
@ -404,8 +390,7 @@
|
||||||
/* -- skip_find_lte \
|
/* -- skip_find_lte \
|
||||||
* Return the matching node or the last one before it. \
|
* Return the matching node or the last one before it. \
|
||||||
*/ \
|
*/ \
|
||||||
decl##_node_t *prefix##skip_find_lte_##decl(decl##_t *slist, \
|
decl##_node_t *prefix##skip_find_lte_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
decl##_node_t *n) \
|
|
||||||
{ \
|
{ \
|
||||||
int cmp; \
|
int cmp; \
|
||||||
unsigned int i; \
|
unsigned int i; \
|
||||||
|
@ -417,9 +402,7 @@
|
||||||
i = slist->level; \
|
i = slist->level; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
while (elm && \
|
while (elm && __skip_key_compare_##decl(slist, elm->field.sle_next[i], n, slist->aux) < 0) \
|
||||||
__skip_key_compare_##decl(slist, elm->field.sle_next[i], n, \
|
|
||||||
slist->aux) < 0) \
|
|
||||||
elm = elm->field.sle_next[i]; \
|
elm = elm->field.sle_next[i]; \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
elm = elm->field.sle_next[0]; \
|
elm = elm->field.sle_next[0]; \
|
||||||
|
@ -484,8 +467,7 @@
|
||||||
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--; \
|
||||||
|
@ -494,8 +476,7 @@
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_next_node_ */ \
|
/* -- skip_next_node_ */ \
|
||||||
decl##_node_t *prefix##skip_next_node_##decl(decl##_t *slist, \
|
decl##_node_t *prefix##skip_next_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
decl##_node_t *n) \
|
|
||||||
{ \
|
{ \
|
||||||
if (slist == NULL || n == NULL) \
|
if (slist == NULL || n == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
|
@ -505,8 +486,7 @@
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_prev_node_ */ \
|
/* -- skip_prev_node_ */ \
|
||||||
decl##_node_t *prefix##skip_prev_node_##decl(decl##_t *slist, \
|
decl##_node_t *prefix##skip_prev_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
decl##_node_t *n) \
|
|
||||||
{ \
|
{ \
|
||||||
if (slist == NULL || n == NULL) \
|
if (slist == NULL || n == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
|
@ -613,8 +593,7 @@
|
||||||
/* -- __skip_dot_node_ \
|
/* -- __skip_dot_node_ \
|
||||||
* Writes out a fragment of a DOT file representing a node. \
|
* Writes out a fragment of a DOT file representing a node. \
|
||||||
*/ \
|
*/ \
|
||||||
static void __skip_dot_node_##decl(FILE *os, decl##_t *slist, \
|
static void __skip_dot_node_##decl(FILE *os, decl##_t *slist, decl##_node_t *node, size_t nsg, skip_sprintf_node_##decl##_t fn) \
|
||||||
decl##_node_t *node, size_t nsg, skip_sprintf_node_##decl##_t fn) \
|
|
||||||
{ \
|
{ \
|
||||||
char buf[2048]; \
|
char buf[2048]; \
|
||||||
size_t level, height = ARRAY_LENGTH(node->field.sle_next); \
|
size_t level, height = ARRAY_LENGTH(node->field.sle_next); \
|
||||||
|
@ -624,8 +603,7 @@
|
||||||
fprintf(os, " [label = \""); \
|
fprintf(os, " [label = \""); \
|
||||||
level = height; \
|
level = height; \
|
||||||
while (level--) { \
|
while (level--) { \
|
||||||
fprintf(os, " { <w%zu> | <f%zu> %p } |", level, level, \
|
fprintf(os, " { <w%zu> | <f%zu> %p } |", level, level, (void *)node->field.sle_next[level]); \
|
||||||
(void *)node->field.sle_next[level]); \
|
|
||||||
} \
|
} \
|
||||||
if (fn) { \
|
if (fn) { \
|
||||||
fn(node, buf); \
|
fn(node, buf); \
|
||||||
|
@ -680,11 +658,10 @@
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_dot_start_ */ \
|
/* -- skip_dot_start_ */ \
|
||||||
static int __skip_dot_start_##decl(FILE *os, decl##_t *slist, size_t nsg, \
|
static int __skip_dot_start_##decl(FILE *os, decl##_t *slist, size_t nsg, skip_sprintf_node_##decl##_t fn) \
|
||||||
skip_sprintf_node_##decl##_t fn) \
|
|
||||||
{ \
|
{ \
|
||||||
size_t level; \
|
size_t level; \
|
||||||
decl##_node_t *head; \
|
decl##_node_t *head, *tail; \
|
||||||
if (nsg == 0) { \
|
if (nsg == 0) { \
|
||||||
fprintf(os, "digraph Skiplist {\n"); \
|
fprintf(os, "digraph Skiplist {\n"); \
|
||||||
fprintf(os, "label = \"Skiplist.\"\n"); \
|
fprintf(os, "label = \"Skiplist.\"\n"); \
|
||||||
|
@ -707,9 +684,9 @@
|
||||||
do { \
|
do { \
|
||||||
decl##_node_t *node = head->field.sle_next[level]; \
|
decl##_node_t *node = head->field.sle_next[level]; \
|
||||||
fprintf(os, "{ <f%zu> %p }", level, (void *)node); \
|
fprintf(os, "{ <f%zu> %p }", level, (void *)node); \
|
||||||
if (level) \
|
if (level && head->field.sle_next[level] != slist->slh_tail) \
|
||||||
fprintf(os, " | "); \
|
fprintf(os, " | "); \
|
||||||
} while (level--); \
|
} while (level-- && head->field.sle_next[level] != slist->slh_tail); \
|
||||||
} \
|
} \
|
||||||
fprintf(os, "\"\n"); \
|
fprintf(os, "\"\n"); \
|
||||||
fprintf(os, "shape = \"record\"\n"); \
|
fprintf(os, "shape = \"record\"\n"); \
|
||||||
|
@ -717,8 +694,9 @@
|
||||||
\
|
\
|
||||||
/* Edges for head node */ \
|
/* Edges for head node */ \
|
||||||
decl##_node_t *node = slist->slh_head; \
|
decl##_node_t *node = slist->slh_head; \
|
||||||
for (level = 0; level < ARRAY_LENGTH(slist->slh_head->field.sle_next); \
|
for (level = 0; level < ARRAY_LENGTH(slist->slh_head->field.sle_next); level++) { \
|
||||||
level++) { \
|
if (node->field.sle_next[level] == slist->slh_tail) \
|
||||||
|
break; \
|
||||||
fprintf(os, "\"HeadNode%zu\":f%zu -> ", nsg, level); \
|
fprintf(os, "\"HeadNode%zu\":f%zu -> ", nsg, level); \
|
||||||
fprintf(os, "\"node%zu %p\"", nsg, (void *)node->field.sle_next[level]); \
|
fprintf(os, "\"node%zu %p\"", nsg, (void *)node->field.sle_next[level]); \
|
||||||
fprintf(os, ":w%zu [];\n", level); \
|
fprintf(os, ":w%zu [];\n", level); \
|
||||||
|
@ -732,14 +710,15 @@
|
||||||
fprintf(os, "\n"); \
|
fprintf(os, "\n"); \
|
||||||
\
|
\
|
||||||
/* The tail, sentinal node */ \
|
/* The tail, sentinal node */ \
|
||||||
|
tail = slist->slh_tail; \
|
||||||
if (!SKIP_EMPTY(slist)) { \
|
if (!SKIP_EMPTY(slist)) { \
|
||||||
fprintf(os, "\"node%zu %p\" [label = \"", nsg, (void *)slist->slh_tail); \
|
fprintf(os, "\"node%zu %p\" [label = \"", nsg, (void *)slist->slh_tail); \
|
||||||
level = ARRAY_LENGTH(slist->slh_head->field.sle_next); \
|
level = ARRAY_LENGTH(tail->field.sle_next) - 1; \
|
||||||
while (level--) { \
|
do { \
|
||||||
fprintf(os, "<w%zu> %p", level, (void *)slist->slh_tail); \
|
fprintf(os, "<w%zu> %p", level, (void *)node->field.sle_prev); \
|
||||||
if (level) \
|
if (level && node->field.sle_prev != slist->slh_head) \
|
||||||
fprintf(os, " | "); \
|
fprintf(os, " | "); \
|
||||||
} \
|
} while (level-- && node->field.sle_prev != slist->slh_head); \
|
||||||
fprintf(os, "\" shape = \"record\"];\n"); \
|
fprintf(os, "\" shape = \"record\"];\n"); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -762,8 +741,7 @@
|
||||||
* \
|
* \
|
||||||
* https://en.wikipedia.org/wiki/DOT_(graph_description_language) \
|
* https://en.wikipedia.org/wiki/DOT_(graph_description_language) \
|
||||||
*/ \
|
*/ \
|
||||||
int prefix##skip_dot_##decl(FILE *os, decl##_t *slist, size_t nsg, \
|
int prefix##skip_dot_##decl(FILE *os, decl##_t *slist, size_t nsg, skip_sprintf_node_##decl##_t fn) \
|
||||||
skip_sprintf_node_##decl##_t fn) \
|
|
||||||
{ \
|
{ \
|
||||||
if (__skip_integrity_check_##decl(slist) != 0) { \
|
if (__skip_integrity_check_##decl(slist) != 0) { \
|
||||||
perror("Skiplist failed integrity checks, impossible to diagram."); \
|
perror("Skiplist failed integrity checks, impossible to diagram."); \
|
||||||
|
|
Loading…
Reference in a new issue