73static void** vt_skiplist_search(
void* obj,
const void* key) {
return skiplist_search(obj, key); }
74static void** vt_skiplist_search_le(
void* obj,
const void* key) {
return skiplist_search_le(obj, key); }
75static void** vt_skiplist_search_lt(
void* obj,
const void* key) {
return skiplist_search_lt(obj, key); }
76static void** vt_skiplist_search_ge(
void* obj,
const void* key) {
return skiplist_search_ge(obj, key); }
77static void** vt_skiplist_search_gt(
void* obj,
const void* key) {
return skiplist_search_gt(obj, key); }
81static size_t vt_skiplist_count(
const void* obj) {
return skiplist_count(obj); }
82static bool vt_skiplist_verify(
const void* obj) {
return skiplist_verify(obj); }
88static bool vt_skiplist_itor_nextn(
void* itor,
size_t count) {
return skiplist_itor_nextn(itor, count); }
89static bool vt_skiplist_itor_prevn(
void* itor,
size_t count) {
return skiplist_itor_prevn(itor, count); }
92static void* vt_skiplist_itor_key(
void* itor) {
return dict_unconst(
skiplist_itor_key(itor)); }
94static bool vt_skiplist_itor_search(
void* itor,
const void* key) {
return skiplist_itor_search(itor, key); }
95static bool vt_skiplist_itor_search_le(
void* itor,
const void* key) {
return skiplist_itor_search_le(itor, key); }
96static bool vt_skiplist_itor_search_lt(
void* itor,
const void* key) {
return skiplist_itor_search_lt(itor, key); }
97static bool vt_skiplist_itor_search_ge(
void* itor,
const void* key) {
return skiplist_itor_search_ge(itor, key); }
98static bool vt_skiplist_itor_search_gt(
void* itor,
const void* key) {
return skiplist_itor_search_gt(itor, key); }
100static int vt_skiplist_itor_compare(
void* itor1,
void* itor2) {
return skiplist_itor_compare(itor1, itor2); }
104 vt_skiplist_dict_itor_new,
108 vt_skiplist_search_le,
109 vt_skiplist_search_lt,
110 vt_skiplist_search_ge,
111 vt_skiplist_search_gt,
114 vt_skiplist_traverse,
121 vt_skiplist_itor_free,
122 vt_skiplist_itor_valid,
123 vt_skiplist_itor_invalidate,
124 vt_skiplist_itor_next,
125 vt_skiplist_itor_prev,
126 vt_skiplist_itor_nextn,
127 vt_skiplist_itor_prevn,
128 vt_skiplist_itor_first,
129 vt_skiplist_itor_last,
130 vt_skiplist_itor_key,
131 vt_skiplist_itor_datum,
132 vt_skiplist_itor_search,
133 vt_skiplist_itor_search_le,
134 vt_skiplist_itor_search_lt,
135 vt_skiplist_itor_search_ge,
136 vt_skiplist_itor_search_gt,
137 vt_skiplist_itor_remove,
138 vt_skiplist_itor_compare,
141static inline skip_node* node_new(
void* key,
unsigned link_count);
148static inline unsigned rand_link_count(
skiplist* list);
166 if (!(list->
head = node_new(NULL, max_link))) {
188 dct->
_vtable = &skiplist_vtable;
206 ASSERT(nlinks < list->max_link);
209 for (
unsigned k = list->
top_link+1; k <= nlinks; k++) {
211 update[k] = list->
head;
216 x->
prev = (update[0] == list->
head) ? NULL : update[0];
217 if (update[0]->link[0])
219 for (
unsigned k = 0; k < nlinks; k++) {
220 ASSERT(update[k]->link_count > k);
222 update[k]->
link[k] = x;
232 for (
unsigned k = list->
top_link+1; k-->0; ) {
240 while (k > 0 && x->
link[k - 1] == y)
250 x = node_new(key, rand_link_count(list));
253 node_insert(list, x, update);
258node_search(
skiplist* list,
const void* key)
261 for (
unsigned k = list->
top_link+1; k-->0;) {
268 while (k > 0 && x->
link[k - 1] == y)
280node_search_le(
skiplist* list,
const void* key)
283 for (
unsigned k = list->
top_link+1; k-->0;) {
290 while (k > 0 && x->
link[k - 1] == y)
298 return x == list->
head ? NULL : x;
302node_search_lt(
skiplist* list,
const void* key)
305 for (
unsigned k = list->
top_link+1; k-->0;) {
312 while (k > 0 && x->
link[k - 1] == y)
320 return x == list->
head ? NULL : x;
324node_search_ge(
skiplist* list,
const void* key)
328 for (
unsigned k = list->
top_link+1; k-->0;) {
336 while (k > 0 && x->
link[k - 1] == y)
348node_search_gt(
skiplist* list,
const void* key)
352 for (
unsigned k = list->
top_link+1; k-->0;) {
360 while (k > 0 && x->
link[k - 1] == y)
375 return x ? &x->
datum : NULL;
381 skip_node* x = node_search_le(list, key);
382 return x ? &x->
datum : NULL;
388 skip_node* x = node_search_lt(list, key);
389 return x ? &x->
datum : NULL;
395 skip_node* x = node_search_ge(list, key);
396 return x ? &x->
datum : NULL;
402 skip_node* x = node_search_gt(list, key);
403 return x ? &x->
datum : NULL;
412 for (
unsigned k = list->
top_link+1; k-->0;) {
422 while (k > 0 && x->
link[k - 1] == y)
434 for (
unsigned k = 0; k <= list->
top_link; k++) {
435 ASSERT(update[k] != NULL);
436 ASSERT(update[k]->link_count > k);
437 if (update[k]->link[k] != x)
break;
458 if (delete_func) delete_func(node->
key, node->
datum);
463 const size_t count = list->
count;
478 if (!visit(node->key, node->datum, user_data))
break;
492 if (list->
count == 0) {
498 for (
unsigned i = 0; i < list->
top_link; ++i) {
501 for (
unsigned i = list->
top_link; i < list->max_link; ++i) {
504 unsigned observed_top_link = 0;
505 size_t observed_count = 0;
510 if (observed_top_link < node->link_count)
516 for (
unsigned k = 0; k < node->
link_count; k++) {
528 node = node->
link[0];
538 for (
size_t i = 0; i < ncounts; ++i)
541 size_t max_num_links = 0;
543 if (max_num_links < node->link_count)
544 max_num_links = node->link_count;
545 if (ncounts > node->link_count)
546 counts[node->link_count]++;
548 return max_num_links;
571 itor->
_vtable = &skiplist_itor_vtable;
585 return itor->
node != NULL;
599 return itor->
node != NULL;
607 return itor->
node != NULL;
616 return itor->
node != NULL;
625 return itor->
node != NULL;
654 return (itor->
node = node_search(itor->
list, key)) != NULL;
660 return (itor->
node = node_search_le(itor->
list, key)) != NULL;
666 return (itor->
node = node_search_lt(itor->
list, key)) != NULL;
672 return (itor->
node = node_search_ge(itor->
list, key)) != NULL;
678 return (itor->
node = node_search_gt(itor->
list, key)) != NULL;
698 return !itor2->
node ? 0 : -1;
717node_new(
void* key,
unsigned link_count)
722 sizeof(node->
link[0]) * link_count);
728 memset(node->
link, 0,
sizeof(node->
link[0]) * link_count);
735static inline unsigned
740 const unsigned r = dict_rand();
742 const unsigned count = tz / 2 + 1;
int(* dict_compare_func)(const void *, const void *)
A pointer to a function that compares two keys.
void(* dict_delete_func)(void *, void *)
A pointer to a function that is called when a key-value pair gets removed from a dictionary.
bool(* dict_visit_func)(const void *, void *, void *)
A pointer to a function used for iterating over dictionary contents.
bool skiplist_itor_search_le(skiplist_itor *itor, const void *key)
Position |itor| on the greatest key less than or equal to |key| and return true, or unposition it and...
size_t skiplist_traverse(skiplist *list, dict_visit_func visit, void *user_data)
Call |visit|(key, datum, |user_data|) for each element in key order, stopping early if |visit| return...
skiplist * skiplist_new(dict_compare_func cmp_func, unsigned max_link)
Create an empty skip list that orders keys with |cmp_func| (must not be NULL).
bool skiplist_itor_search_gt(skiplist_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
bool skiplist_itor_remove(skiplist_itor *itor)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
void ** skiplist_search_le(skiplist *list, const void *key)
Return the address of the datum of the greatest key less than or equal to |key|, or NULL if there is ...
void ** skiplist_search(skiplist *list, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
bool skiplist_itor_search(skiplist_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
bool skiplist_verify(const skiplist *list)
Check the internal invariants of the list and return true if they hold, or print the first failed che...
bool skiplist_itor_first(skiplist_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
bool skiplist_itor_next(skiplist_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
bool skiplist_itor_prevn(skiplist_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
size_t skiplist_free(skiplist *list, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
void skiplist_itor_invalidate(skiplist_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
const void * skiplist_itor_key(const skiplist_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
void ** skiplist_search_gt(skiplist *list, const void *key)
Return the address of the datum of the least key greater than |key|, or NULL if there is none.
bool skiplist_itor_search_lt(skiplist_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
bool skiplist_itor_valid(const skiplist_itor *itor)
Return whether |itor| is positioned on an element.
dict * skiplist_dict_new(dict_compare_func cmp_func, unsigned max_link)
Like skiplist_new(), but wrapped in a generic dict for use with the dict_* macros.
void ** skiplist_search_ge(skiplist *list, const void *key)
Return the address of the datum of the least key greater than or equal to |key|, or NULL if there is ...
bool skiplist_itor_search_ge(skiplist_itor *itor, const void *key)
Position |itor| on the least key greater than or equal to |key| and return true, or unposition it and...
int skiplist_itor_compare(const skiplist_itor *itor1, const skiplist_itor *itor2)
Compare the positions of two iterators over the same list: return a negative value,...
void ** skiplist_itor_datum(skiplist_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
dict_itor * skiplist_dict_itor_new(skiplist *list)
Like skiplist_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
void ** skiplist_search_lt(skiplist *list, const void *key)
Return the address of the datum of the greatest key less than |key|, or NULL if there is none.
void skiplist_itor_free(skiplist_itor *itor)
Free an iterator.
dict_insert_result skiplist_insert(skiplist *list, void *key)
Insert |key| unless an equal key is present.
bool skiplist_itor_nextn(skiplist_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
skiplist_itor * skiplist_itor_new(skiplist *list)
Create an iterator over |list| that is not positioned on any element yet.
size_t skiplist_clear(skiplist *list, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
size_t skiplist_count(const skiplist *list)
Return the number of elements.
dict_remove_result skiplist_remove(skiplist *list, const void *key)
Remove the element with key |key|.
bool skiplist_itor_last(skiplist_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
size_t skiplist_link_count_histogram(const skiplist *list, size_t counts[], size_t ncounts)
Compute the histogram of link counts of the skiplist.
bool skiplist_itor_prev(skiplist_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
const itor_vtable * _vtable
The operations of one container type.
const dict_vtable * _vtable
dict_compare_func cmp_func