/*- * Copyright (c) 2016--2019 Taylor R. Campbell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include "container_of.h" #include "critbit_alloc.h" #define arraycount(A) (sizeof(A)/sizeof(A[0])) struct element { const char *p; unsigned n; struct critbit_node node; } S[] = { {"FOO", 3}, {"bar", 3}, {"baz", 3}, {"baz\0", 4}, {"foo", 3}, }; const size_t n = arraycount(S); const size_t insperm[arraycount(S)] = {0,3,4,2,1}; const size_t delperm[arraycount(S)] = {0,1,3,2,4}; char iterstack[42]; static const void * getkey(const struct critbit *C __unused, const struct critbit_node *n, size_t *keylenp) { const struct element *e = const_container_of(n, struct element, node); *keylenp = e->n; return e->p; } static void membar_none(void) { } static struct critbit_branch * branch_alloc(struct critbit *C __unused) { struct critbit_branch *B; B = malloc(sizeof(*B)); printf("alloc %p\n", B); return B; } static void branch_free(struct critbit *C __unused, struct critbit_branch *B) { printf("free %p\n", B); return free(B); } static const struct critbit_ops ops = { .cbo_key = getkey, .cbo_membar_producer = membar_none, .cbo_membar_datadep_consumer = membar_none, .cbo_branch_alloc = branch_alloc, .cbo_branch_free = branch_free, }; int main(int argc, char **argv) { struct critbit C; size_t i; (void)argc; /* ignore */ (void)argv; /* ignore */ critbit_init(&C, &ops); critbit_check(&C); assert(critbit_empty(&C)); for (i = 0; i < n; i++) { critbit_node_init(&S[i].node, S[i].p, S[i].n); critbit_check(&C); } for (i = 0; i < n; i++) { const size_t j = insperm[i]; struct critbit_node *cn = critbit_insert(&C, &S[j].node); (void)printf("inserted %p (%p): %s (%u)\n", cn, &S[j].node, S[j].p, S[j].n); assert(cn == &S[j].node); critbit_check(&C); assert(!critbit_empty(&C)); } for (i = 0; i < n; i++) { const char *k = S[i].p; struct critbit_node *cn = critbit_lookup(&C, k, S[i].n); (void)printf("lookedup %p (%p): %s (%u)\n", cn, &S[i].node, S[i].p, S[i].n); assert(cn == &S[i].node); critbit_check(&C); } (void)printf("first prefix `ba': %p\n", critbit_min_prefix(&C, "ba", 2)); (void)printf("last prefix `ba': %p\n", critbit_max_prefix(&C, "ba", 2)); critbit_print(&C); { struct critbit_iter I; struct critbit_node *cn; critbit_iter_init(&C, &I, iterstack, sizeof iterstack); (void)printf("forward\n"); for (i = 0, cn = critbit_iter_min(&C, &I); i < arraycount(S) && cn != NULL; i++, cn = critbit_iter_next(&C, &I)) { assert(cn == &S[i].node); (void)printf("iter %p: %s (%u)\n", cn, S[i].p, S[i].n); } assert(i == arraycount(S)); (void)printf("backward\n"); for (i = arraycount(S), cn = critbit_iter_max(&C, &I); cn != NULL && i --> 0; cn = critbit_iter_prev(&C, &I)) { assert(cn == &S[i].node); (void)printf("iter %p: %s (%u)\n", cn, S[i].p, S[i].n); } assert(i == 0); assert(cn == NULL); (void)printf("forward starting with `b'\n"); for (i = 1, cn = critbit_iter_min_prefix(&C, &I, "b", 1); i < 4 && cn != NULL; i++, cn = critbit_iter_next(&C, &I)) { assert(cn == &S[i].node); (void)printf("iter %p: %s (%u)\n", cn, S[i].p, S[i].n); } assert(i == 4); assert(cn == NULL); (void)printf("backward starting with `b'\n"); for (i = 4, cn = critbit_iter_max_prefix(&C, &I, "b", 1); cn != NULL && i --> 0; cn = critbit_iter_prev(&C, &I)) { (void)printf("iter %p: %s (%u)\n", cn, S[i].p, S[i].n); } assert(i == 1); assert(cn == NULL); (void)printf("done\n"); critbit_iter_destroy(&C, &I); } for (i = 0; i < arraycount(delperm); i++) { size_t j = delperm[i]; const char *k = S[j].p; struct critbit_node *cn = critbit_delete_key(&C, k, S[j].n); (void)printf("deleted %p (%p): %s (%u)\n", cn, &S[j].node, S[j].p, S[j].n); assert(cn == &S[j].node); critbit_print(&C); fflush(stdout); for (j = 0; j < n; j++) { const char *k = S[j].p; struct critbit_node *cn = critbit_lookup(&C, k, S[j].n); (void)printf("lookedup %p (%p): %s\n", cn, &S[j].node, k ? k : "(null)"); assert(cn == &S[j].node || cn == NULL); } printf("check\n"); critbit_print(&C); fflush(stdout); critbit_check(&C); } for (i = 0; i < n; i++) { critbit_node_destroy(&S[i].node); critbit_check(&C); } assert(critbit_empty(&C)); critbit_destroy(&C); return 0; }