diff --git a/README.md b/README.md index b6dace7..8714565 100644 --- a/README.md +++ b/README.md @@ -52,24 +52,24 @@ Insert items into a simple btree that only stores ints. #define BGEN_NAME bt // The namespace for the btree structure. #define BGEN_TYPE int // The data type for all items in the btree #define BGEN_LESS return a < b; // A code fragment for comparing items -#include "bgen.h" // Include "bgen.h" to generate the btree +#include "../bgen.h" // Include "bgen.h" to generate the btree int main() { // Create an empty btree instance. struct bt *tree = 0; - // insert some items into the btree + // Insert some items into the btree bt_insert(&tree, 3, 0, 0); bt_insert(&tree, 8, 0, 0); bt_insert(&tree, 2, 0, 0); bt_insert(&tree, 5, 0, 0); // Print items in tree - struct bt_iter iter; + struct bt_iter *iter; bt_iter_init(&tree, &iter, 0); - for (bt_iter_scan(&iter); bt_iter_valid(&iter); bt_iter_next(&iter)) { + for (bt_iter_scan(iter); bt_iter_valid(iter); bt_iter_next(iter)) { int item; - bt_iter_item(&iter, &item); + bt_iter_item(iter, &item); printf("%d ", item); } printf("\n"); @@ -78,13 +78,14 @@ int main() { bt_delete(&tree, 3, 0, 0); // Print again - for (bt_iter_scan(&iter); bt_iter_valid(&iter); bt_iter_next(&iter)) { + for (bt_iter_scan(iter); bt_iter_valid(iter); bt_iter_next(iter)) { int item; - bt_iter_item(&iter, &item); + bt_iter_item(iter, &item); printf("%d ", item); } printf("\n"); + bt_iter_release(iter); bt_clear(&tree, 0); return 0; } @@ -115,13 +116,14 @@ struct pair { void print_map(const char *comment, struct map **map) { printf("%s", comment); - struct map_iter iter; + struct map_iter *iter; map_iter_init(map, &iter, 0); - for (map_iter_scan(&iter); map_iter_valid(&iter); map_iter_next(&iter)) { + for (map_iter_scan(iter); map_iter_valid(iter); map_iter_next(iter)) { struct pair pair; - map_iter_item(&iter, &pair); + map_iter_item(iter, &pair); printf("[%s] = %d; ", pair.key, pair.value); } + map_iter_release(iter); printf("\n"); } @@ -133,14 +135,14 @@ int main() { map_insert(&map, (struct pair){"CPU", 10}, 0, 0); print_map("1) Initial map: ", &map); - // get an existing item + // Get an existing item struct pair item; assert(map_get(&map, (struct pair){"GPU"}, &item, 0) == map_FOUND); printf("2) Get item: [%s] = %d;\n", item.key, item.value); - // update an existing item + // Update an existing item assert(map_insert(&map, (struct pair){"CPU", 25}, 0, 0) == map_REPLACED); - // insert a new item + // Insert a new item assert(map_insert(&map, (struct pair){"SSD", 30}, 0, 0) == map_INSERTED); print_map("3) Updated map: ", &map); assert(map_insert(&map, (struct pair){"UPS"}, 0, 0) == map_INSERTED); @@ -260,6 +262,8 @@ set using the C preprocessor. | BGEN_DIMS `` | Define the number of dimensions for [spatial btree](#spatial-b-tree) | | BGEN_ITEMRECT `` | Define a rect filling operation for [spatial btree](#spatial-b-tree) | | BGEN_RTYPE `` | Define a rect coordinate type [spatial btree](#spatial-b-tree) (default double) | +| BGEN_HEADER | Generate header declaration only. See [Header and source](#header-and-source) | +| BGEN_SOURCE | Generate source declaration only. See [Header and source](#header-and-source) | ## Namespaces @@ -542,15 +546,15 @@ function. It takes a little more work to set up but is sometimes easier t manage the context of operation. ```c -struct users_iter iter; +struct users_iter *iter; users_iter_init(&users, &iter, 0); -users_iter_scan(&iter); -while (users_iter_valid(&iter)) { - users_iter_item(&iter, &user); +users_iter_scan(iter); +while (users_iter_valid(iter)) { + users_iter_item(iter, &user); printf("%s %s (age=%d)\n", user.first, user.last, user.age); - users_iter_next(&iter); + users_iter_next(iter); } -users_iter_release(&iter); +users_iter_release(iter); ``` It's usually not safe to modify the btree while iterating. @@ -558,20 +562,23 @@ If you need to filter data then it's best to reset the iterator after each modification. ```c -struct users_iter iter; +struct users_iter *iter; users_iter_init(&users, &iter, 0); -users_iter_scan(&iter); -while (users_iter_valid(&iter)) { - users_iter_item(&iter, &user); +users_iter_scan(iter); +while (users_iter_valid(iter)) { + users_iter_item(iter, &user); if (user.age >= 30 && user.age < 40) { users_delete(&users, user, 0, 0); - users_iter_seek(&iter, user); + users_iter_seek(iter, user); continue; } - users_iter_next(&iter); + users_iter_next(iter); } +users_iter_release(iter); ``` +Make sure to call `bt_iter_release()` when you are done iterating; + ## Status codes Most btree operations, such as `bt_get()` and `bt_insert()` return status @@ -700,6 +707,48 @@ neighbors operation ([kNN](https://en.wikipedia.org/wiki/K-nearest_neighbors_alg See the [spatial.c](examples/spatial.c) example from the [examples directory](examples). +## Header and source + +By default, bgen generates all the code as a static unit for the current source +file that includes "bgen.h". + +This is great if all you need to access the btree from that one file. +But if you want other c source files to access those same btree functions too +then you'll use the `BGEN_HEADER` and `BGEN_SOURCE` options. + +For example, here we'll create a "users.h" and "users.c" where one generates +only the header declarations and the other generates the code. + +```c +// users.h +#ifndef USERS_H +#define USERS_H + +struct user { + int id; + char *name; +}; + +#define BGEN_NAME users +#define BGEN_TYPE struct user +#define BGEN_HEADER +#include "../deps/bgen.h" + +#endif +``` + +```c +// users.c +#include "users.h" + +#define BGEN_NAME users +#define BGEN_TYPE struct user +#define BGEN_LESS return a.id < b.id; +#define BGEN_SOURCE +#include "../deps/bgen.h" +``` + + ## Performance The following benchmarks compare the performance of bgen to the very fast diff --git a/bgen.h b/bgen.h index 5eab9d0..d21a3bc 100644 --- a/bgen.h +++ b/bgen.h @@ -109,8 +109,12 @@ #endif #ifndef BGEN_EXTERN +#ifdef BGEN_HEADER +#define BGEN_EXTERN extern +#else #define BGEN_EXTERN static #endif +#endif // Enable Spatial B-tree support #ifdef BGEN_SPATIAL @@ -162,7 +166,6 @@ Visit https://github.com/tidwall/bgen for more information. #define BGEN_SNODE struct BGEN_SYM(snode) #define BGEN_RECT struct BGEN_SYM(rect) -// Definitions // The following status codes are private to this file only. // Users should use the prefixed version such as bt_INSERTED as defined in the @@ -179,6 +182,10 @@ Visit https://github.com/tidwall/bgen for more information. #define BGEN_NOMEM 10 // Out of memory #define BGEN_UNSUPPORTED 11 // Operation not supported +#ifndef BGEN_SOURCE + +// Definitions + enum BGEN_API(status) { BGEN_C(BGEN_NAME, _INSERTED) = BGEN_INSERTED, BGEN_C(BGEN_NAME, _REPLACED) = BGEN_REPLACED, @@ -241,7 +248,7 @@ BGEN_EXTERN int BGEN_API(index_of)(BGEN_NODE **root, BGEN_ITEM key, BGEN_EXTERN size_t BGEN_API(count)(BGEN_NODE **root, void *udata); // Cursor Iterators -BGEN_EXTERN void BGEN_API(iter_init)(BGEN_NODE **root, BGEN_ITER *iter, +BGEN_EXTERN void BGEN_API(iter_init)(BGEN_NODE **root, BGEN_ITER **iter, void *udata); BGEN_EXTERN int BGEN_API(iter_status)(BGEN_ITER *iter); BGEN_EXTERN bool BGEN_API(iter_valid)(BGEN_ITER *iter); @@ -314,7 +321,7 @@ BGEN_EXTERN int BGEN_API(front_mut)(BGEN_NODE **root, BGEN_ITEM *item_out, void *udata); BGEN_EXTERN int BGEN_API(back_mut)(BGEN_NODE **root, BGEN_ITEM *item_out, void *udata); -BGEN_EXTERN void BGEN_API(iter_init_mut)(BGEN_NODE **root, BGEN_ITER *iter, +BGEN_EXTERN void BGEN_API(iter_init_mut)(BGEN_NODE **root, BGEN_ITER **iter, void *udata); BGEN_EXTERN int BGEN_API(scan_mut)(BGEN_NODE **root, bool(*iter)(BGEN_ITEM item, void *udata), void *udata); @@ -336,7 +343,9 @@ BGEN_EXTERN int BGEN_API(seek_at_mut)(BGEN_NODE **root, size_t index, BGEN_EXTERN int BGEN_API(seek_at_desc_mut)(BGEN_NODE **root, size_t index, bool(*iter)(BGEN_ITEM item, void *udata), void *udata); -#ifndef BGEN_DEFS +#endif // !BGEN_SOURCE + +#ifndef BGEN_HEADER // IMPLEMENTATION @@ -3601,12 +3610,6 @@ static int BGEN_SYM(ppush0)(BGEN_PQUEUE *queue, BGEN_PITEM item, void *udata) { queue->items = items2; } queue->items[queue->len++] = item; - // static size_t nlen = 0; - // if (queue->len > nlen) { - // printf("%zu\n", nlen); - // nlen = queue->len; - // } - size_t i = queue->len - 1; while (i != 0) { size_t parent = (i - 1) / 2; @@ -3704,59 +3707,62 @@ BGEN_ITER { } u; }; -static void BGEN_SYM(iter_init)(BGEN_NODE **root, BGEN_ITER *iter, void *udata){ - iter->root = root; - iter->udata = udata; - iter->mut = false; - iter->valid = false; - iter->kind = 0; +static void BGEN_SYM(iter_init)(BGEN_NODE **root, BGEN_ITER **iter, void *udata) +{ + *iter = BGEN_SYM(malloc)(sizeof(BGEN_ITER), udata); + if (*iter) { + (*iter)->root = root; + (*iter)->udata = udata; + (*iter)->mut = false; + (*iter)->valid = false; + (*iter)->kind = 0; + } } -static void BGEN_SYM(iter_init_mut)(BGEN_NODE **root, BGEN_ITER *iter, +static void BGEN_SYM(iter_init_mut)(BGEN_NODE **root, BGEN_ITER **iter, void *udata) { BGEN_SYM(iter_init)(root, iter, udata); - iter->mut = 1; + if (*iter) { + (*iter)->mut = 1; + } } static void BGEN_SYM(iter_reset)(BGEN_ITER *iter, int kind) { iter->valid = true; iter->status = 0; #ifdef BGEN_SPATIAL - // printf("A\n"); if (iter->kind == BGEN_NEARBY && kind != BGEN_NEARBY) { - // printf("B\n"); // switching from NEARBY to SCAN BGEN_SYM(pclear)(&iter->u.n.queue, iter->udata); } else if (iter->kind != BGEN_NEARBY && kind == BGEN_NEARBY) { - // printf("C\n"); // switching from SCAN to NEARBY BGEN_SYM(pqueue_init)(&iter->u.n.queue); } - // printf("D\n"); #endif iter->u.s.nstack = 0; iter->kind = kind; } static void BGEN_SYM(iter_release)(BGEN_ITER *iter) { - (void)iter; + if (iter) { #ifdef BGEN_SPATIAL - if (iter->kind == BGEN_NEARBY) { - BGEN_SYM(pclear)(&iter->u.n.queue, iter->udata); - } + if (iter->kind == BGEN_NEARBY) { + BGEN_SYM(pclear)(&iter->u.n.queue, iter->udata); + } #endif + BGEN_SYM(free)(iter, iter->udata); + } } static bool BGEN_SYM(iter_valid)(BGEN_ITER *iter) { - return iter->valid; + return iter && iter->valid; } static int BGEN_SYM(iter_status)(BGEN_ITER *iter) { - return iter->status; + return !iter ? BGEN_NOMEM : iter->status; } - #ifdef BGEN_SPATIAL static bool BGEN_SYM(iter_skip_item)(BGEN_ITER *iter, BGEN_SNODE *snode) { if (iter->kind == BGEN_INTERSECTS) { @@ -3953,6 +3959,9 @@ static void BGEN_SYM(iter_next)(BGEN_ITER *iter) { // Moves iterator to first item and resets the status static void BGEN_SYM(iter_scan)(BGEN_ITER *iter) { + if (!iter) { + return; + } BGEN_SYM(iter_reset)(iter, BGEN_SCAN); if (!*iter->root) { iter->valid = false; @@ -3980,6 +3989,9 @@ static void BGEN_SYM(iter_scan)(BGEN_ITER *iter) { // Moves iterator to last item and resets the status static void BGEN_SYM(iter_scan_desc)(BGEN_ITER *iter) { + if (!iter) { + return; + } BGEN_SYM(iter_reset)(iter, BGEN_SCANDESC); if (!*iter->root) { iter->valid = false; @@ -4045,6 +4057,9 @@ static bool BGEN_SYM(iter_intersects_first)(BGEN_ITER *iter, BGEN_NODE *node) { #endif static void BGEN_SYM(iter_seek)(BGEN_ITER *iter, BGEN_ITEM key) { + if (!iter) { + return; + } #ifdef BGEN_NOORDER (void)iter, (void)key; iter->valid = false; @@ -4085,8 +4100,10 @@ static void BGEN_SYM(iter_seek)(BGEN_ITER *iter, BGEN_ITEM key) { #endif } - static void BGEN_SYM(iter_seek_at)(BGEN_ITER *iter, size_t index) { + if (!iter) { + return; + } BGEN_SYM(iter_reset)(iter, BGEN_SCAN); if (!*iter->root) { iter->valid = false; @@ -4134,6 +4151,9 @@ static void BGEN_SYM(iter_seek_at)(BGEN_ITER *iter, size_t index) { } static void BGEN_SYM(iter_seek_at_desc)(BGEN_ITER *iter, size_t index) { + if (!iter) { + return; + } BGEN_SYM(iter_reset)(iter, BGEN_SCANDESC); if (!*iter->root) { iter->valid = false; @@ -4181,7 +4201,10 @@ static void BGEN_SYM(iter_seek_at_desc)(BGEN_ITER *iter, size_t index) { static void BGEN_SYM(iter_intersects)(BGEN_ITER *iter, BGEN_RTYPE min[], BGEN_RTYPE max[]) { - BGEN_SYM(iter_reset)(iter, BGEN_INTERSECTS); + if (!iter) { + return; + } +BGEN_SYM(iter_reset)(iter, BGEN_INTERSECTS); #ifndef BGEN_SPATIAL (void)iter, (void)min, (void)max; iter->valid = false; @@ -4208,6 +4231,9 @@ static void BGEN_SYM(iter_nearby)(BGEN_ITER *iter, void *target, BGEN_RTYPE(*dist)(BGEN_RTYPE min[BGEN_DIMS], BGEN_RTYPE max[BGEN_DIMS], void *target, void *udata)) { + if (!iter) { + return; + } BGEN_SYM(iter_reset)(iter, BGEN_NEARBY); #ifndef BGEN_SPATIAL (void)iter, (void)target, (void)dist; @@ -4253,6 +4279,9 @@ static void BGEN_SYM(iter_item)(BGEN_ITER *iter, BGEN_ITEM *item) { } static void BGEN_SYM(iter_seek_desc)(BGEN_ITER *iter, BGEN_ITEM key) { + if (!iter) { + return; + } #ifdef BGEN_NOORDER (void)iter, (void)key; iter->valid = false; @@ -4625,7 +4654,7 @@ static inline void BGEN_SYM(all_sym_calls)(void) { (void)BGEN_SYM(intersects_mut); (void)BGEN_SYM(nearby); (void)BGEN_SYM(nearby_mut); - (void)BGEN_API(seek_at_mut); + (void)BGEN_SYM(seek_at_mut); (void)BGEN_SYM(seek_at_desc_mut); (void)BGEN_SYM(rect); (void)BGEN_SYM(scan_rects); @@ -4887,11 +4916,11 @@ bool BGEN_API(less)(BGEN_ITEM a, BGEN_ITEM b, void *udata) { return BGEN_SYM(less)(a, b, udata); } -void BGEN_API(iter_init)(BGEN_NODE **root, BGEN_ITER *iter, void *udata) { +void BGEN_API(iter_init)(BGEN_NODE **root, BGEN_ITER **iter, void *udata) { BGEN_SYM(iter_init)(root, iter, udata); } -void BGEN_API(iter_init_mut)(BGEN_NODE **root, BGEN_ITER *iter, void *udata) { +void BGEN_API(iter_init_mut)(BGEN_NODE **root, BGEN_ITER **iter, void *udata) { BGEN_SYM(iter_init_mut)(root, iter, udata); } @@ -5061,7 +5090,7 @@ void BGEN_API(rect)(BGEN_NODE **root, BGEN_RTYPE min[BGEN_DIMS], BGEN_SYM(rect)(root, min, max, udata); } -#endif // BGEN_DEFS +#endif // BGEN_HEADER // undefine everything // use `gcc -dM -E ` to help find leftover BGEN_* defines @@ -5125,7 +5154,7 @@ void BGEN_API(rect)(BGEN_NODE **root, BGEN_RTYPE min[BGEN_DIMS], #undef BGEN_FANOUTUSED #undef BGEN_POPMAX #undef BGEN_VALUE -#undef BGEN_DEFS +#undef BGEN_HEADER #undef BGEN_NOORDER #undef BGEN_RTYPE #undef BGEN_SNODE @@ -5142,3 +5171,4 @@ void BGEN_API(rect)(BGEN_NODE **root, BGEN_RTYPE min[BGEN_DIMS], #undef BGEN_FOUND #undef BGEN_INSAT #undef BGEN_MAYBELESSEQUAL +#undef BGEN_SOURCE diff --git a/docs/API.md b/docs/API.md index 06cb5cf..4f7b5ef 100644 --- a/docs/API.md +++ b/docs/API.md @@ -263,25 +263,26 @@ int bt_nearby(struct bt **root, void *target, ```c /// Initialize an iterator -void bt_iter_init(struct bt **root, biter *iter, void *udata); +/// Make sure to call bt_iter_release() when done iterating. +void bt_iter_init(struct bt **root, struct bt_iter **iter, void *udata); /// Release the iterator when it's no longer needed -void bt_iter_release(biter *iter); +void bt_iter_release(struct bt_iter *iter); /// Returns an error status code of the iterator, or zero if no error. -int bt_iter_status(biter *iter); +int bt_iter_status(struct bt_iter *iter); /// Returns true if the iterator is valid and an item, using bt_iter_item() is /// available. -bool bt_iter_valid(biter *iter); +bool bt_iter_valid(struct bt_iter *iter); /// Get the current iterator item. /// REQUIRED: iter_valid() and item != NULL -void bt_iter_item(biter *iter, bitem *item); +void bt_iter_item(struct bt_iter *iter, bitem *item); /// Move to the next item /// REQUIRED: iter_valid() -void bt_iter_next(biter *iter); +void bt_iter_next(struct bt_iter *iter); /// Seek to a key in the btree and iterate over each subsequent item. void bt_iter_seek(struct bt_iter *iter, bitem key); diff --git a/examples/deque.c b/examples/deque.c index 612af77..5b5f880 100644 --- a/examples/deque.c +++ b/examples/deque.c @@ -25,15 +25,17 @@ int main() { deque_push_front(&deque, 13, 0); deque_push_back(&deque, 25, 0); + // Iterate and print values of deque - struct deque_iter iter; + struct deque_iter *iter; deque_iter_init(&deque, &iter, 0); - deque_iter_scan(&iter); - for (; deque_iter_valid(&iter); deque_iter_next(&iter)) { + deque_iter_scan(iter); + for (; deque_iter_valid(iter); deque_iter_next(iter)) { int item; - deque_iter_item(&iter, &item); + deque_iter_item(iter, &item); printf("%d ", item); } + deque_iter_release(iter); printf("\n"); return 0; diff --git a/examples/example.c b/examples/example.c index e4ea6ad..49eedb7 100644 --- a/examples/example.c +++ b/examples/example.c @@ -16,11 +16,11 @@ int main() { bt_insert(&tree, 5, 0, 0); // Print items in tree - struct bt_iter iter; + struct bt_iter *iter; bt_iter_init(&tree, &iter, 0); - for (bt_iter_scan(&iter); bt_iter_valid(&iter); bt_iter_next(&iter)) { + for (bt_iter_scan(iter); bt_iter_valid(iter); bt_iter_next(iter)) { int item; - bt_iter_item(&iter, &item); + bt_iter_item(iter, &item); printf("%d ", item); } printf("\n"); @@ -29,13 +29,15 @@ int main() { bt_delete(&tree, 3, 0, 0); // Print again - for (bt_iter_scan(&iter); bt_iter_valid(&iter); bt_iter_next(&iter)) { + for (bt_iter_scan(iter); bt_iter_valid(iter); bt_iter_next(iter)) { int item; - bt_iter_item(&iter, &item); + bt_iter_item(iter, &item); printf("%d ", item); } printf("\n"); + bt_iter_release(iter); + bt_clear(&tree, 0); return 0; } diff --git a/examples/iteration.c b/examples/iteration.c index 0404d55..d087fd0 100644 --- a/examples/iteration.c +++ b/examples/iteration.c @@ -57,15 +57,15 @@ int main() { users_seek(&users, (struct user){ .first="", .last="Murphy" }, user_iter, NULL); printf("\n-- loop iterator (same as previous) --\n"); - struct users_iter iter; + struct users_iter *iter; users_iter_init(&users, &iter, 0); - users_iter_seek(&iter, (struct user){.first="", .last="Murphy"}); - while (users_iter_valid(&iter)) { - users_iter_item(&iter, &user); + users_iter_seek(iter, (struct user){.first="", .last="Murphy"}); + while (users_iter_valid(iter)) { + users_iter_item(iter, &user); printf("%s %s (age=%d)\n", user.first, user.last, user.age); - users_iter_next(&iter); + users_iter_next(iter); } - users_iter_release(&iter); + users_iter_release(iter); return 0; } diff --git a/examples/map.c b/examples/map.c index fcdaa2d..63315c6 100644 --- a/examples/map.c +++ b/examples/map.c @@ -17,13 +17,14 @@ struct pair { void print_map(const char *comment, struct map **map) { printf("%s", comment); - struct map_iter iter; + struct map_iter *iter; map_iter_init(map, &iter, 0); - for (map_iter_scan(&iter); map_iter_valid(&iter); map_iter_next(&iter)) { + for (map_iter_scan(iter); map_iter_valid(iter); map_iter_next(iter)) { struct pair pair; - map_iter_item(&iter, &pair); + map_iter_item(iter, &pair); printf("[%s] = %d; ", pair.key, pair.value); } + map_iter_release(iter); printf("\n"); } diff --git a/examples/set.c b/examples/set.c index 6efc210..eebd46c 100644 --- a/examples/set.c +++ b/examples/set.c @@ -11,14 +11,15 @@ #include "../bgen.h" void print_set(struct set **set) { - struct set_iter iter; + struct set_iter *iter; set_iter_init(set, &iter, 0); printf("{ "); - for (set_iter_scan(&iter); set_iter_valid(&iter); set_iter_next(&iter)) { + for (set_iter_scan(iter); set_iter_valid(iter); set_iter_next(iter)) { int item; - set_iter_item(&iter, &item); + set_iter_item(iter, &item); printf("%d ", item); } + set_iter_release(iter); printf("}"); } diff --git a/examples/spatial.c b/examples/spatial.c index 5c845ea..113d55f 100644 --- a/examples/spatial.c +++ b/examples/spatial.c @@ -68,16 +68,16 @@ int main() { double max[] = { -111, 34 }; printf("Cities inside rectangle ((%.0f %0.f) (%.0f %0.f)):\n", min[0], min[1], max[0], max[1]); - struct cities_iter iter; + struct cities_iter *iter; cities_iter_init(&cities, &iter, 0); - cities_iter_intersects(&iter, min, max); - while (cities_iter_valid(&iter)) { + cities_iter_intersects(iter, min, max); + while (cities_iter_valid(iter)) { struct city city; - cities_iter_item(&iter, &city); + cities_iter_item(iter, &city); printf("- %s\n", city.city); - cities_iter_next(&iter); + cities_iter_next(iter); } - cities_iter_release(&iter); + cities_iter_release(iter); printf("\n"); // Find nearest 10 cities to (-113, 33) @@ -85,16 +85,16 @@ int main() { struct point point = { .lon = -113, .lat = 33 }; printf("Top 10 cities nearby point (%.0f %0.f):\n", point.lon, point.lat); cities_iter_init(&cities, &iter, 0); - cities_iter_nearby(&iter, &point, calcdist); + cities_iter_nearby(iter, &point, calcdist); int n = 0; - while (n < 10 && cities_iter_valid(&iter)) { + while (n < 10 && cities_iter_valid(iter)) { struct city city; - cities_iter_item(&iter, &city); + cities_iter_item(iter, &city); printf("- %s\n", city.city); - cities_iter_next(&iter); + cities_iter_next(iter); n++; } - cities_iter_release(&iter); + cities_iter_release(iter); printf("\n"); return 0; diff --git a/tests/test_base.h b/tests/test_base.h index 84039c0..2baa78b 100644 --- a/tests/test_base.h +++ b/tests/test_base.h @@ -454,9 +454,9 @@ void test_various(void) { // assert(ret == kv_FOUND); // for (int i = 0; i < nkeys; i++) { // val = -1; - // kv_iter_item(&iter, &val); + // kv_iter_item(iter, &val); // assert(val == keys[i]); - // ret = kv_iter_next(&iter); + // ret = kv_iter_next(iter); // if (i == nkeys-1) { // assert(ret == kv_NOTFOUND); // } else { @@ -470,7 +470,7 @@ void test_various(void) { // assert(ret == kv_FOUND); // for (int i = nkeys-1; i >= 0; i--) { // val = -1; - // kv_iter_item(&iter, &val); + // kv_iter_item(iter, &val); // assert(val == keys[i]); // ret = kv_iter_prev(&iter); // if (i == 0) { @@ -1343,15 +1343,17 @@ void test_failures(void) { kv_clear(&tree2, 0); assert(kv_clone(&tree, &tree2, 0) == kv_COPIED); copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_scan(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_scan(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1377,19 +1379,22 @@ void test_failures(void) { j = k; while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_scan_desc(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_scan_desc(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1415,19 +1420,22 @@ void test_failures(void) { j = k; while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_seek(&iter, j); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_seek(iter, j); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1455,22 +1463,26 @@ void test_failures(void) { kv_clear(&tree2, 0); assert(kv_clone(&tree, &tree2, 0) == kv_COPIED); copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_seek_desc(&iter, (l++)%kv_count(&tree, 0)); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_seek_desc(iter, (l++)%kv_count(&tree, 0)); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } - if (kv_iter_status(&iter) == kv_NOMEM) { + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } + kv_iter_release(iter); j++; } } @@ -1496,19 +1508,22 @@ void test_failures(void) { j = k; while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_seek_at(&iter, j); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_seek_at(iter, j); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1534,19 +1549,22 @@ void test_failures(void) { j = k; while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_seek_at_desc(&iter, j); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_seek_at_desc(iter, j); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1583,19 +1601,22 @@ void test_failures(void) { j = k; while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_intersects(&iter, min, max); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_intersects(iter, min, max); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } + kv_iter_release(iter); j++; } } @@ -1635,22 +1656,22 @@ void test_failures(void) { assert(kv_clone(&tree, &tree2, 0) == kv_COPIED); while (j < N) { copysum = freesum = 0; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init_mut(&tree, &iter, 0); - kv_iter_nearby(&iter, 0, dist_noop); - if (kv_iter_status(&iter) == kv_NOMEM) { - kv_iter_release(&iter); + kv_iter_nearby(iter, 0, dist_noop); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - kv_iter_next(&iter); - if (kv_iter_status(&iter) == kv_NOMEM) { - kv_iter_release(&iter); + kv_iter_next(iter); + if (kv_iter_status(iter) == kv_NOMEM) { + kv_iter_release(iter); continue; } - while (kv_iter_valid(&iter)) { - kv_iter_next(&iter); + while (kv_iter_valid(iter)) { + kv_iter_next(iter); } - kv_iter_release(&iter); + kv_iter_release(iter); j++; } } @@ -1774,7 +1795,7 @@ if (doit) { // printf("> %d %d\n", a, b); } - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*intersects)(struct kv **root, double min[], double max[], bool(*iter)(int item, void *udata), void *udata); if (mut) { @@ -1823,19 +1844,20 @@ if (doit) { slow_intersects(min, max, &ctx1); intersects(&tree2, min, max, iiter, &ctx2); - struct kv_iter iter; + struct kv_iter *iter; iter_init(&tree2, &iter, 0); - kv_iter_intersects(&iter, min, max); + kv_iter_intersects(iter, min, max); #ifdef SPATIAL - for (; kv_iter_valid(&iter); kv_iter_next(&iter)) { - kv_iter_item(&iter, &val); + for (; kv_iter_valid(iter); kv_iter_next(iter)) { + kv_iter_item(iter, &val); if (!iiter(val, &ctx3)) { break; } } #else - assert(!kv_iter_valid(&iter)); + assert(!kv_iter_valid(iter)); #endif + kv_iter_release(iter); if (!(ctx3.count == ctx2.count && ctx2.count == ctx1.count && ctx1.count == count)) { @@ -1855,7 +1877,7 @@ if (doit) { void test_intersects_opt(bool mut) { - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); // int(*intersects)(struct kv **root, double min[], double max[], void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -1864,13 +1886,18 @@ void test_intersects_opt(bool mut) { } + + + // test iter_intersects on an empty tree - struct kv_iter iter; - iter_init(&tree, &iter, 0); + struct kv_iter *iter; double min[DIMS] = { 0 }; double max[DIMS] = { 0 }; - kv_iter_intersects(&iter, min, max); - assert(!kv_iter_valid(&iter)); + kv_iter_intersects(0, min, max); // should not fail + iter_init(&tree, &iter, 0); + kv_iter_intersects(iter, min, max); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); @@ -1887,18 +1914,19 @@ void test_intersects_opt(bool mut) { // try intersects to find each item sort(keys, nkeys); - iter_init(&tree2, &iter, 0); for (int i = 0; i < nkeys; i++) { bool found = false; item_rect(keys[i], min, max); - kv_iter_intersects(&iter, min, max); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + iter_init(&tree2, &iter, 0); + kv_iter_intersects(iter, min, max); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (val == keys[i]) { found = true; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); #ifdef SPATIAL assert(found); #else @@ -2031,9 +2059,9 @@ void slow_seek_at_desc(size_t index, bool(*iter)(int item, void *udata), void *u void test_scan_opt(bool mut) { struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*scan)(struct kv **root, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2044,8 +2072,9 @@ void test_scan_opt(bool mut) { } iter_init(&tree, &iter, 0); - kv_iter_scan(&iter); - assert(!kv_iter_valid(&iter)); + kv_iter_scan(iter); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); @@ -2067,15 +2096,15 @@ void test_scan_opt(bool mut) { ctx = (struct siter_ctx){ .limit = 9999999 }; iter_init(&tree2, &iter, 0); - kv_iter_scan(&iter); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_scan(iter); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } - kv_iter_release(&iter); // not really needed for scan + kv_iter_release(iter); // not really needed for scan assert(ctx.sum == asum); for (int i = 0; i < 150; i++) { @@ -2091,14 +2120,15 @@ void test_scan_opt(bool mut) { ctx = (struct siter_ctx){ .limit = i }; iter_init(&tree2, &iter, 0); - kv_iter_scan(&iter); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_scan(iter); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == i); assert(ctx.sum == bsum); } @@ -2119,9 +2149,9 @@ void test_scan(void) { void test_scan_desc_opt(bool mut) { struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*scan_desc)(struct kv **root, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2132,9 +2162,9 @@ void test_scan_desc_opt(bool mut) { } iter_init(&tree, &iter, 0); - kv_iter_scan(&iter); - assert(!kv_iter_valid(&iter)); - + kv_iter_scan(iter); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); ctx = (struct siter_ctx){ 0 }; @@ -2155,14 +2185,15 @@ void test_scan_desc_opt(bool mut) { ctx = (struct siter_ctx){ .limit = 9999999 }; iter_init(&tree2, &iter, 0); - kv_iter_scan_desc(&iter); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_scan_desc(iter); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.sum == asum); for (int i = 0; i < 150; i++) { @@ -2178,14 +2209,15 @@ void test_scan_desc_opt(bool mut) { ctx = (struct siter_ctx){ .limit = i }; iter_init(&tree2, &iter, 0); - kv_iter_scan_desc(&iter); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_scan_desc(iter); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == i); assert(ctx.sum == bsum); } @@ -2203,9 +2235,9 @@ void test_scan_desc(void) { void test_seek_opt(bool mut) { struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*seek)(struct kv **root, int pivot, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2216,8 +2248,9 @@ void test_seek_opt(bool mut) { } iter_init(&tree, &iter, 0); - kv_iter_seek(&iter, 0); - assert(!kv_iter_valid(&iter)); + kv_iter_seek(iter, 0); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); @@ -2255,14 +2288,15 @@ void test_seek_opt(bool mut) { ctx = (struct siter_ctx){ .limit = limit }; iter_init(&tree2, &iter, 0); - kv_iter_seek(&iter, i); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_seek(iter, i); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == count); assert(ctx.sum == bsum); } @@ -2280,7 +2314,7 @@ void test_seek(void) { } void test_seek_desc_opt(bool mut) { - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*seek_desc)(struct kv **root, int pivot, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2291,12 +2325,13 @@ void test_seek_desc_opt(bool mut) { } struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; // test iter with empty trees iter_init(&tree, &iter, 0); - kv_iter_seek_desc(&iter, 99999999); - assert(!kv_iter_valid(&iter)); + kv_iter_seek_desc(iter, 99999999); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); @@ -2336,14 +2371,15 @@ void test_seek_desc_opt(bool mut) { ctx = (struct siter_ctx){ .limit = limit }; iter_init(&tree2, &iter, 0); - kv_iter_seek_desc(&iter, i); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_seek_desc(iter, i); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == count); assert(ctx.sum == bsum); } @@ -2363,9 +2399,9 @@ void test_seek_desc(void) { void test_seek_at_opt(bool mut) { struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*seek_at)(struct kv **root, size_t index, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2376,15 +2412,16 @@ void test_seek_at_opt(bool mut) { } iter_init(&tree, &iter, 0); - kv_iter_seek_at(&iter, 0); - assert(!kv_iter_valid(&iter)); + kv_iter_seek_at(iter, 0); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); iter_init(&tree, &iter, 0); - kv_iter_seek_at(&iter, 999999); - assert(!kv_iter_valid(&iter)); - + kv_iter_seek_at(iter, 999999); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); struct kv *tree2 = tree; assert(kv_clone(&tree, &tree2, 0) == kv_COPIED); @@ -2422,14 +2459,15 @@ void test_seek_at_opt(bool mut) { // printf("iter_seek_at %d:%d\n", i, limit); ctx = (struct siter_ctx){ .limit = limit }; iter_init(&tree2, &iter, 0); - kv_iter_seek_at(&iter, i); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_seek_at(iter, i); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == count); assert(ctx.sum == bsum); } @@ -2448,9 +2486,9 @@ void test_seek_at(void) { void test_seek_at_desc_opt(bool mut) { struct siter_ctx ctx; - struct kv_iter iter; + struct kv_iter *iter; - void(*iter_init)(struct kv **root, struct kv_iter *iter, void *udata); + void(*iter_init)(struct kv **root, struct kv_iter **iter, void *udata); int(*seek_at_desc)(struct kv **root, size_t index, bool(*iter)(int item, void *udata), void *udata); if (mut) { iter_init = kv_iter_init_mut; @@ -2461,14 +2499,16 @@ void test_seek_at_desc_opt(bool mut) { } iter_init(&tree, &iter, 0); - kv_iter_seek_at_desc(&iter, 0); - assert(!kv_iter_valid(&iter)); + kv_iter_seek_at_desc(iter, 0); + assert(!kv_iter_valid(iter)); + kv_iter_release(iter); tree_fill(); iter_init(&tree, &iter, 0); - kv_iter_seek_at_desc(&iter, 999999); - assert(kv_iter_valid(&iter)); + kv_iter_seek_at_desc(iter, 999999); + assert(kv_iter_valid(iter)); + kv_iter_release(iter); ctx = (struct siter_ctx){ .limit = 1 }; int ret = seek_at_desc(&tree, 999999, siter, &ctx); @@ -2512,14 +2552,15 @@ void test_seek_at_desc_opt(bool mut) { // printf("iter_seek_at %d:%d\n", i, limit); ctx = (struct siter_ctx){ .limit = limit }; iter_init(&tree2, &iter, 0); - kv_iter_seek_at_desc(&iter, i); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_seek_at_desc(iter, i); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!siter(val, &ctx)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } + kv_iter_release(iter); assert(ctx.count == count); assert(ctx.sum == bsum); @@ -2594,25 +2635,25 @@ int slow_nearby(struct kv **root, void *target, #else struct nitem *items = malloc(sizeof(struct nitem) * kv_count(root, udata)); assert(items); - struct kv_iter iter2; + struct kv_iter *iter2; if (mut) { kv_iter_init_mut(root, &iter2, udata); } else { kv_iter_init(root, &iter2, udata); } - kv_iter_scan(&iter2); + kv_iter_scan(iter2); int count = 0; - while (kv_iter_valid(&iter2)) { - kv_iter_item(&iter2, &val); + while (kv_iter_valid(iter2)) { + kv_iter_item(iter2, &val); double min[DIMS], max[DIMS]; item_rect(val, min, max); items[count].dist = dist(min, max, target, udata); items[count].item = val; count++; - kv_iter_next(&iter2); + kv_iter_next(iter2); } - assert(kv_iter_status(&iter2) == 0); - kv_iter_release(&iter2); + assert(kv_iter_status(iter2) == 0); + kv_iter_release(iter2); qsort(items, count, sizeof(struct nitem), ncompare); int status = kv_FINISHED; for (int i = 0; i < count; i++) { @@ -2634,10 +2675,12 @@ void test_nearby_opt(bool mut) { assert(kv_nearby(&tree, 0, ndist, niter, 0) == kv_FINISHED); } - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init(&tree, &iter, 0); - kv_iter_nearby(&iter, 0, ndist); - assert(kv_iter_valid(&iter) == false); + kv_iter_nearby(0, 0, ndist); // should not fail + kv_iter_nearby(iter, 0, ndist); + assert(kv_iter_valid(iter) == false); + kv_iter_release(iter); #ifndef SPATIAL @@ -2690,15 +2733,15 @@ void test_nearby_opt(bool mut) { } else { kv_iter_init(&tree3, &iter, &ctx3); } - kv_iter_nearby(&iter, point, ndist); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_nearby(iter, point, ndist); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!niter(val, &ctx3)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } - kv_iter_release(&iter); + kv_iter_release(iter); assert(ctx3.count == count); for (int i = 0; i < count; i++) { @@ -2730,20 +2773,20 @@ void test_nearby_opt(bool mut) { } else { kv_iter_init(&tree3, &iter, &ctx3); } - kv_iter_nearby(&iter, point, ndist); - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + kv_iter_nearby(iter, point, ndist); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (!niter(val, &ctx3)) { break; } - kv_iter_next(&iter); + kv_iter_next(iter); } // printf("============\n"); - kv_iter_scan(&iter); // switch to the different scanner + kv_iter_scan(iter); // switch to the different scanner // printf("============\n"); - kv_iter_release(&iter); + kv_iter_release(iter); assert(ctx3.count == count/2); @@ -2784,12 +2827,12 @@ void check_rect(void) { double max[DIMS] = { 0 }; double imin[DIMS] = { 0 }; double imax[DIMS] = { 0 }; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init(&tree, &iter, 0); - kv_iter_scan(&iter); + kv_iter_scan(iter); int i = 0; - while (kv_iter_valid(&iter)) { - kv_iter_item(&iter, &val); + while (kv_iter_valid(iter)) { + kv_iter_item(iter, &val); if (i == 0) { item_rect(val, min, max); } else { @@ -2803,9 +2846,10 @@ void check_rect(void) { } } } - kv_iter_next(&iter); + kv_iter_next(iter); i++; } + kv_iter_release(iter); kv_rect(&tree, imin, imax, 0); for (int i = 0; i < DIMS; i++) { assert(!(min[i] < imin[i] || min[i] > imin[i])); diff --git a/tests/test_spatial2x.c b/tests/test_spatial2x.c index cf77ecc..b02bc35 100644 --- a/tests/test_spatial2x.c +++ b/tests/test_spatial2x.c @@ -167,14 +167,15 @@ void test_intersects(void) { kv_intersects(&tree, min, max, iiter, &ctx2); // printf("\033[1;34m>>> iter_intersects\033[0m\n"); struct iiter_ctx ctx3 = { .min = min, .max = max, .results = results3 }; - struct kv_iter iter; + struct kv_iter *iter; kv_iter_init(&tree, &iter, 0); - kv_iter_intersects(&iter, min, max); - for (; kv_iter_valid(&iter); kv_iter_next(&iter)) { + kv_iter_intersects(iter, min, max); + for (; kv_iter_valid(iter); kv_iter_next(iter)) { struct point point; - kv_iter_item(&iter, &point); + kv_iter_item(iter, &point); siter(point, &ctx3); } + kv_iter_release(iter); assert(iiter_ctx_equal(ctx1, ctx2)); if (!iiter_ctx_equal(ctx2, ctx3)) { tree_print(&tree);