00001
00025 #include "mkavl.h"
00026 #include "libavl/avl.h"
00027 #include <stdio.h>
00028
00033 #ifndef CT_ASSERT
00034 #define CT_ASSERT(e) extern char (*CT_ASSERT(void)) [sizeof(char[1 - 2*!(e)])]
00035 #endif
00036
00040 #ifndef NELEMS
00041 #define NELEMS(x) (sizeof(x) / sizeof(x[0]))
00042 #endif
00043
00047 #define MKAVL_RUNAWAY_SANITY 100000
00048
00052 #define MKAVL_CTX_MAGIC 0xCAFEBABE
00053
00057 #define MKAVL_CTX_STALE 0xDEADBEEF
00058
00062 typedef struct mkavl_avl_ctx_st_ {
00064 uint32_t magic;
00066 mkavl_tree_handle tree_h;
00068 size_t key_idx;
00069 } mkavl_avl_ctx_st;
00070
00074 typedef struct mkavl_avl_tree_st_ {
00076 struct avl_table *tree;
00078 mkavl_compare_fn compare_fn;
00080 mkavl_avl_ctx_st *avl_ctx;
00081 } mkavl_avl_tree_st;
00082
00086 typedef struct mkavl_allocator_wrapper_st_ {
00090 struct libavl_allocator avl_allocator;
00092 uint32_t magic;
00094 mkavl_allocator_st mkavl_allocator;
00096 mkavl_tree_handle tree_h;
00097 } mkavl_allocator_wrapper_st;
00098
00102 typedef struct mkavl_tree_st_ {
00104 void *context;
00106 mkavl_allocator_wrapper_st allocator;
00108 size_t avl_tree_count;
00110 mkavl_avl_tree_st *avl_tree_array;
00116 uint32_t item_count;
00121 mkavl_copy_fn copy_fn;
00122 } mkavl_tree_st;
00123
00127 typedef struct mkavl_iterator_st_ {
00129 struct avl_traverser avl_t;
00131 mkavl_tree_handle tree_h;
00133 size_t key_idx;
00134 } mkavl_iterator_st;
00135
00143 static inline void
00144 mkavl_assert_abort (bool condition)
00145 {
00146 if (!condition) {
00147 abort();
00148 }
00149 }
00150
00156 static const char * const mkavl_rc_e_string[] = {
00157 "Invalid RC",
00158 "Success",
00159 "Invalid input",
00160 "No memory",
00161 "Out of sync",
00162 "Max RC"
00163 };
00164
00166
00167 CT_ASSERT(NELEMS(mkavl_rc_e_string) == (MKAVL_RC_E_MAX + 1));
00176 bool
00177 mkavl_rc_e_is_notok (mkavl_rc_e rc)
00178 {
00179 return (MKAVL_RC_E_SUCCESS != rc);
00180 }
00181
00188 bool
00189 mkavl_rc_e_is_ok (mkavl_rc_e rc)
00190 {
00191 return (MKAVL_RC_E_SUCCESS == rc);
00192 }
00193
00200 bool
00201 mkavl_rc_e_is_valid (mkavl_rc_e rc)
00202 {
00203 return ((rc >= MKAVL_RC_E_INVALID) && (rc <= MKAVL_RC_E_MAX));
00204 }
00205
00213 const char *
00214 mkavl_rc_e_get_string (mkavl_rc_e rc)
00215 {
00216 const char* retval = "__Invalid__";
00217
00218 if (mkavl_rc_e_is_valid(rc)) {
00219 retval = mkavl_rc_e_string[rc];
00220 }
00221
00222 return (retval);
00223 }
00224
00230 static const char * const mkavl_find_type_e_string[] = {
00231 "Invalid",
00232 "Equal",
00233 "Greater than",
00234 "Less than",
00235 "Greater than or equal",
00236 "Less than or equal",
00237 "Max type"
00238 };
00239
00241
00242 CT_ASSERT(NELEMS(mkavl_find_type_e_string) == (MKAVL_FIND_TYPE_E_MAX + 1));
00251 bool
00252 mkavl_find_type_e_is_valid (mkavl_find_type_e type)
00253 {
00254 return ((type >= MKAVL_FIND_TYPE_E_INVALID) &&
00255 (type <= MKAVL_FIND_TYPE_E_MAX));
00256 }
00257
00265 const char *
00266 mkavl_find_type_e_get_string (mkavl_find_type_e type)
00267 {
00268 const char* retval = "__Invalid__";
00269
00270 if (mkavl_find_type_e_is_valid(type)) {
00271 retval = mkavl_find_type_e_string[type];
00272 }
00273
00274 return (retval);
00275 }
00276
00283 static bool
00284 mkavl_avl_ctx_is_valid (mkavl_avl_ctx_st *avl_ctx)
00285 {
00286 bool is_valid = true;
00287
00288 if (is_valid && (NULL == avl_ctx)) {
00289 is_valid = false;
00290 }
00291
00292 if (is_valid && (MKAVL_CTX_MAGIC != avl_ctx->magic)) {
00293 is_valid = false;
00294 }
00295
00296 if (is_valid && (NULL == avl_ctx->tree_h)) {
00297 is_valid = false;
00298 }
00299
00300 if (is_valid && (avl_ctx->key_idx >= avl_ctx->tree_h->avl_tree_count)) {
00301 is_valid = false;
00302 }
00303
00304 return (is_valid);
00305 }
00306
00313 static bool
00314 mkavl_allocator_wrapper_is_valid (mkavl_allocator_wrapper_st *allocator)
00315 {
00316 bool is_valid = true;
00317
00318 if (is_valid && (NULL == allocator)) {
00319 is_valid = false;
00320 }
00321
00322 if (is_valid && (MKAVL_CTX_MAGIC != allocator->magic)) {
00323 is_valid = false;
00324 }
00325
00326 if (is_valid && (NULL == allocator->mkavl_allocator.malloc_fn)) {
00327 is_valid = false;
00328 }
00329
00330 if (is_valid && (NULL == allocator->mkavl_allocator.free_fn)) {
00331 is_valid = false;
00332 }
00333
00334 if (is_valid && (NULL == allocator->tree_h)) {
00335 is_valid = false;
00336 }
00337
00338 return (is_valid);
00339 }
00340
00348 static void *
00349 mkavl_malloc_wrapper (struct libavl_allocator *allocator, size_t size)
00350 {
00351 mkavl_allocator_wrapper_st *mkavl_allocator =
00352 (mkavl_allocator_wrapper_st *) allocator;
00353
00354 mkavl_assert_abort(mkavl_allocator_wrapper_is_valid(mkavl_allocator));
00355
00356 return (mkavl_allocator->mkavl_allocator.malloc_fn(size,
00357 mkavl_allocator->tree_h->context));
00358 }
00359
00366 static void
00367 mkavl_free_wrapper (struct libavl_allocator *allocator, void *libavl_block)
00368 {
00369 mkavl_allocator_wrapper_st *mkavl_allocator =
00370 (mkavl_allocator_wrapper_st *) allocator;
00371
00372 mkavl_assert_abort(mkavl_allocator_wrapper_is_valid(mkavl_allocator));
00373
00374 return (mkavl_allocator->mkavl_allocator.free_fn(libavl_block,
00375 mkavl_allocator->tree_h->context));
00376 }
00377
00385 static void *
00386 mkavl_default_malloc_fn (size_t size, void *context)
00387 {
00388 return (malloc(size));
00389 }
00390
00397 static void
00398 mkavl_default_free_fn (void *ptr, void *context)
00399 {
00400 return (free(ptr));
00401 }
00402
00406 static mkavl_allocator_st mkavl_allocator_default = {
00407 mkavl_default_malloc_fn,
00408 mkavl_default_free_fn
00409 };
00410
00414 static struct libavl_allocator mkavl_allocator_wrapper = {
00415 mkavl_malloc_wrapper,
00416 mkavl_free_wrapper
00417 };
00418
00427 static int
00428 mkavl_compare_wrapper (const void *avl_a, const void *avl_b, void *avl_param)
00429 {
00430 mkavl_avl_ctx_st *avl_ctx;
00431 mkavl_compare_fn cmp_fn;
00432
00433 avl_ctx = (mkavl_avl_ctx_st *) avl_param;
00434 mkavl_assert_abort(mkavl_avl_ctx_is_valid(avl_ctx));
00435
00436 cmp_fn = avl_ctx->tree_h->avl_tree_array[avl_ctx->key_idx].compare_fn;
00437 mkavl_assert_abort(NULL != cmp_fn);
00438
00439 return (cmp_fn(avl_a, avl_b, avl_ctx->tree_h->context));
00440 }
00441
00449 static void *
00450 mkavl_copy_wrapper (void *avl_item, void *avl_param)
00451 {
00452 mkavl_avl_ctx_st *avl_ctx;
00453 mkavl_copy_fn copy_fn;
00454
00455 avl_ctx = (mkavl_avl_ctx_st *) avl_param;
00456 mkavl_assert_abort(mkavl_avl_ctx_is_valid(avl_ctx));
00457
00458 copy_fn = avl_ctx->tree_h->copy_fn;
00459 mkavl_assert_abort(NULL != copy_fn);
00460
00461 return (copy_fn(avl_item, avl_ctx->tree_h->context));
00462 }
00463
00471 static mkavl_rc_e
00472 mkavl_delete_tree (mkavl_tree_handle *tree_h)
00473 {
00474 mkavl_allocator_st local_allocator;
00475 mkavl_tree_handle local_tree_h;
00476 void *context;
00477 uint32_t i;
00478
00479 if (NULL == tree_h) {
00480 return (MKAVL_RC_E_EINVAL);
00481 }
00482 local_tree_h = *tree_h;
00483
00484 memcpy(&local_allocator, &(local_tree_h->allocator.mkavl_allocator),
00485 sizeof(local_allocator));
00486 context = local_tree_h->context;
00487
00488 if (NULL == local_tree_h) {
00489 return (MKAVL_RC_E_SUCCESS);
00490 }
00491
00492 if (NULL != local_tree_h->avl_tree_array) {
00493 for (i = 0; i < local_tree_h->avl_tree_count; ++i) {
00494 if (NULL != local_tree_h->avl_tree_array[i].tree) {
00495 if (NULL != local_tree_h->avl_tree_array[i].avl_ctx) {
00496 local_allocator.free_fn(
00497 local_tree_h->avl_tree_array[i].avl_ctx, context);
00498 local_tree_h->avl_tree_array[i].avl_ctx = NULL;
00499 }
00500 avl_destroy(local_tree_h->avl_tree_array[i].tree, NULL);
00501 local_tree_h->avl_tree_array[i].tree = NULL;
00502 }
00503 }
00504 local_allocator.free_fn(local_tree_h->avl_tree_array, context);
00505 }
00506 local_tree_h->allocator.tree_h = NULL;
00507 local_tree_h->allocator.magic = MKAVL_CTX_STALE;
00508
00509 local_allocator.free_fn(local_tree_h, context);
00510
00511 *tree_h = NULL;
00512
00513 return (MKAVL_RC_E_SUCCESS);
00514 }
00515
00522 static bool
00523 mkavl_tree_is_valid (mkavl_tree_handle tree_h)
00524 {
00525 bool is_valid = true;
00526 uint32_t i;
00527
00528 if (is_valid && (NULL == tree_h)) {
00529 is_valid = false;
00530 }
00531
00532 if (is_valid && (0 == tree_h->avl_tree_count)) {
00533 is_valid = false;
00534 }
00535
00536 if (is_valid &&
00537 !mkavl_allocator_wrapper_is_valid(&(tree_h->allocator))) {
00538 is_valid = false;
00539 }
00540
00541 if (is_valid) {
00542 for (i = 0; i < tree_h->avl_tree_count; ++i) {
00543 if (NULL == tree_h->avl_tree_array[i].tree) {
00544 is_valid = false;
00545 break;
00546 }
00547
00548 if (NULL == tree_h->avl_tree_array[i].compare_fn) {
00549 is_valid = false;
00550 break;
00551 }
00552
00553 if (!mkavl_avl_ctx_is_valid(tree_h->avl_tree_array[i].avl_ctx)) {
00554 is_valid = false;
00555 break;
00556 }
00557 }
00558 }
00559
00560 return (is_valid);
00561 }
00562
00569 static bool
00570 mkavl_iterator_is_valid (mkavl_iterator_handle iterator_h)
00571 {
00572 bool is_valid = true;
00573
00574 if (is_valid && (NULL == iterator_h)) {
00575 is_valid = false;
00576 }
00577
00578 if (is_valid && !mkavl_tree_is_valid(iterator_h->tree_h)) {
00579 is_valid = false;
00580 }
00581
00582 if (is_valid &&
00583 (iterator_h->key_idx >= iterator_h->tree_h->avl_tree_count)) {
00584 is_valid = false;
00585 }
00586
00587 return (is_valid);
00588 }
00589
00607 mkavl_rc_e
00608 mkavl_new (mkavl_tree_handle *tree_h,
00609 mkavl_compare_fn *compare_fn_array,
00610 size_t compare_fn_array_count,
00611 void *context, mkavl_allocator_st *allocator)
00612 {
00613 mkavl_allocator_st *local_allocator;
00614 mkavl_tree_handle local_tree_h;
00615 mkavl_avl_ctx_st *avl_ctx;
00616 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS, err_rc;
00617 uint32_t i;
00618
00619 if ((NULL == tree_h) || (NULL == compare_fn_array) ||
00620 (0 == compare_fn_array_count)) {
00621 return (MKAVL_RC_E_EINVAL);
00622 }
00623 *tree_h = NULL;
00624
00625 local_allocator =
00626 (NULL == allocator) ? &mkavl_allocator_default : allocator;
00627
00628 local_tree_h = local_allocator->malloc_fn(sizeof(*local_tree_h), context);
00629 if (NULL == local_tree_h) {
00630 rc = MKAVL_RC_E_ENOMEM;
00631 goto err_exit;
00632 }
00633
00634 local_tree_h->context = context;
00635 memcpy(&(local_tree_h->allocator.avl_allocator), &mkavl_allocator_wrapper,
00636 sizeof(local_tree_h->allocator.avl_allocator));
00637 memcpy(&(local_tree_h->allocator.mkavl_allocator), local_allocator,
00638 sizeof(local_tree_h->allocator));
00639 local_tree_h->allocator.tree_h = local_tree_h;
00640 local_tree_h->allocator.magic = MKAVL_CTX_MAGIC;
00641 local_tree_h->avl_tree_count = compare_fn_array_count;
00642 local_tree_h->avl_tree_array = NULL;
00643 local_tree_h->item_count = 0;
00644 local_tree_h->copy_fn = NULL;
00645
00646 local_tree_h->avl_tree_array =
00647 local_allocator->malloc_fn(local_tree_h->avl_tree_count *
00648 sizeof(*(local_tree_h->avl_tree_array)),
00649 context);
00650 if (NULL == local_tree_h->avl_tree_array) {
00651 rc = MKAVL_RC_E_ENOMEM;
00652 goto err_exit;
00653 }
00654
00655 for (i = 0; i < local_tree_h->avl_tree_count; ++i) {
00656 local_tree_h->avl_tree_array[i].tree = NULL;
00657 local_tree_h->avl_tree_array[i].compare_fn = compare_fn_array[i];
00658 if (NULL == local_tree_h->avl_tree_array[i].compare_fn) {
00659 rc = MKAVL_RC_E_ENOMEM;
00660 goto err_exit;
00661 }
00662 local_tree_h->avl_tree_array[i].avl_ctx = NULL;
00663 }
00664
00665 for (i = 0; i < local_tree_h->avl_tree_count; ++i) {
00666 avl_ctx = local_allocator->malloc_fn(sizeof(*avl_ctx), context);
00667 if (NULL == avl_ctx) {
00668 rc = MKAVL_RC_E_ENOMEM;
00669 goto err_exit;
00670 }
00671 avl_ctx->magic = MKAVL_CTX_STALE;
00672
00673 local_tree_h->avl_tree_array[i].tree =
00674 avl_create(mkavl_compare_wrapper, avl_ctx,
00675 &(local_tree_h->allocator.avl_allocator));
00676 if (NULL == local_tree_h->avl_tree_array[i].tree) {
00677 rc = MKAVL_RC_E_ENOMEM;
00678 goto err_exit;
00679 }
00680
00681 avl_ctx->tree_h = local_tree_h;
00682 avl_ctx->key_idx = i;
00683 avl_ctx->magic = MKAVL_CTX_MAGIC;
00684 local_tree_h->avl_tree_array[i].avl_ctx = avl_ctx;
00685 avl_ctx = NULL;
00686 }
00687
00688 if (!mkavl_tree_is_valid(local_tree_h)) {
00689 rc = MKAVL_RC_E_EINVAL;
00690 goto err_exit;
00691 }
00692
00693 *tree_h = local_tree_h;
00694
00695 return (rc);
00696
00697 err_exit:
00698
00699 if (NULL != local_tree_h) {
00700 err_rc = mkavl_delete_tree(&local_tree_h);
00701 mkavl_assert_abort(mkavl_rc_e_is_ok(err_rc));
00702 }
00703
00704 if (NULL != avl_ctx) {
00705
00706 local_allocator->free_fn(avl_ctx, context);
00707 }
00708
00709 return (rc);
00710 }
00711
00720 void *
00721 mkavl_get_tree_context (mkavl_tree_handle tree_h)
00722 {
00723 mkavl_assert_abort(mkavl_tree_is_valid(tree_h));
00724
00725 return (tree_h->context);
00726 }
00727
00749 mkavl_rc_e
00750 mkavl_delete (mkavl_tree_handle *tree_h, mkavl_item_fn item_fn,
00751 mkavl_delete_context_fn delete_context_fn)
00752 {
00753 mkavl_tree_handle local_tree_h;
00754 void *item, *item_to_delete;
00755 uint32_t i, first_tree_idx;
00756 uint32_t runaway_counter = 0;
00757 struct avl_traverser avl_t = {0};
00758 void *context;
00759 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS;
00760 mkavl_rc_e retval = MKAVL_RC_E_SUCCESS;
00761
00762 if (NULL == tree_h) {
00763 return (MKAVL_RC_E_EINVAL);
00764 }
00765 local_tree_h = *tree_h;
00766
00767 if (!mkavl_tree_is_valid(local_tree_h)) {
00768 return (MKAVL_RC_E_EINVAL);
00769 }
00770
00771
00772
00773
00774
00775 first_tree_idx = local_tree_h->avl_tree_count;
00776 for (i = 0; i < local_tree_h->avl_tree_count; ++i) {
00777 if (NULL != local_tree_h->avl_tree_array[i].tree) {
00778 first_tree_idx = i;
00779 avl_t_init(&avl_t,
00780 local_tree_h->avl_tree_array[first_tree_idx].tree);
00781 break;
00782 }
00783 }
00784
00785 if (first_tree_idx < local_tree_h->avl_tree_count) {
00786
00787
00788
00789
00790 item_to_delete =
00791 avl_t_first(&avl_t,
00792 local_tree_h->avl_tree_array[first_tree_idx].tree);
00793 while (NULL != item_to_delete) {
00794 mkavl_assert_abort(runaway_counter <= MKAVL_RUNAWAY_SANITY);
00795 for (i = first_tree_idx; i < local_tree_h->avl_tree_count; ++i) {
00796 if (NULL != local_tree_h->avl_tree_array[i].tree) {
00797 item = avl_delete(local_tree_h->avl_tree_array[i].tree,
00798 item_to_delete);
00799 mkavl_assert_abort(NULL != item);
00800 }
00801 }
00802
00803 if (NULL != item_fn) {
00804 rc = item_fn(item_to_delete, local_tree_h->context);
00805 if (mkavl_rc_e_is_notok(rc)) {
00806 retval = rc;
00807 }
00808 }
00809
00810 --(local_tree_h->item_count);
00811
00812
00813 item_to_delete =
00814 avl_t_first(&avl_t,
00815 local_tree_h->avl_tree_array[first_tree_idx].tree);
00816 ++runaway_counter;
00817 }
00818 }
00819
00820 context = local_tree_h->context;
00821
00822 rc = mkavl_delete_tree(tree_h);
00823 mkavl_assert_abort(mkavl_rc_e_is_ok(rc));
00824
00825 if (NULL != delete_context_fn) {
00826 rc = delete_context_fn(context);
00827 if (mkavl_rc_e_is_notok(rc)) {
00828 retval = rc;
00829 }
00830 }
00831
00832 return (retval);
00833 }
00834
00861 mkavl_rc_e
00862 mkavl_copy (mkavl_tree_handle source_tree_h,
00863 mkavl_tree_handle *new_tree_h,
00864 mkavl_copy_fn copy_fn, mkavl_item_fn item_fn,
00865 bool use_source_context, void *new_context,
00866 mkavl_delete_context_fn delete_context_fn,
00867 mkavl_allocator_st *allocator)
00868 {
00869 mkavl_tree_handle local_tree_h = NULL;
00870 mkavl_allocator_st *local_allocator = allocator;
00871 bool allocated_mkavl_tree = false;
00872 struct avl_traverser avl_t = {0};
00873 mkavl_copy_fn old_copy_fn, copy_fn_to_use;
00874 void *item, *existing_item;
00875 void *context_to_use;
00876 mkavl_delete_context_fn delete_context_fn_to_use;
00877 uint32_t i;
00878 bool is_first_item;
00879 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS;
00880
00881 if (NULL == new_tree_h) {
00882 return (MKAVL_RC_E_EINVAL);
00883 }
00884 *new_tree_h = NULL;
00885
00886 if (!mkavl_tree_is_valid(source_tree_h)) {
00887 return (MKAVL_RC_E_EINVAL);
00888 }
00889
00890 if (NULL == local_allocator) {
00891 local_allocator = &(source_tree_h->allocator.mkavl_allocator);
00892 }
00893
00894 {
00895 mkavl_compare_fn cmp_fn_array[source_tree_h->avl_tree_count];
00896
00897 for (i = 0; i < NELEMS(cmp_fn_array); ++i) {
00898 cmp_fn_array[i] = source_tree_h->avl_tree_array[i].compare_fn;
00899 }
00900
00901 context_to_use = new_context;
00902 if (use_source_context) {
00903 context_to_use = source_tree_h->context;
00904 }
00905
00906 rc = mkavl_new(&local_tree_h,
00907 cmp_fn_array, NELEMS(cmp_fn_array),
00908 context_to_use, local_allocator);
00909 if (mkavl_rc_e_is_notok(rc)) {
00910 goto err_exit;
00911 }
00912 allocated_mkavl_tree = true;
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 old_copy_fn = source_tree_h->copy_fn;
00923 source_tree_h->copy_fn = copy_fn;
00924 copy_fn_to_use = NULL;
00925 if (NULL != copy_fn) {
00926 copy_fn_to_use = mkavl_copy_wrapper;
00927 }
00928
00929
00930
00931
00932 local_tree_h->allocator.mkavl_allocator.free_fn(
00933 local_tree_h->avl_tree_array[0].tree, local_tree_h->context);
00934 local_tree_h->avl_tree_array[0].tree =
00935 avl_copy(source_tree_h->avl_tree_array[0].tree, copy_fn_to_use,
00936 NULL, &(local_tree_h->allocator.avl_allocator));
00937 source_tree_h->copy_fn = old_copy_fn;
00938 if (NULL == local_tree_h->avl_tree_array[0].tree) {
00939 goto err_exit;
00940 }
00941
00942 local_tree_h->item_count =
00943 avl_count(local_tree_h->avl_tree_array[0].tree);
00944
00945
00946
00947
00948 local_tree_h->avl_tree_array[0].tree->avl_param =
00949 local_tree_h->avl_tree_array[0].avl_ctx;
00950
00951 if (local_tree_h->avl_tree_count > 1) {
00952 item = avl_t_first(&avl_t, local_tree_h->avl_tree_array[0].tree);
00953 is_first_item = true;
00954 while (NULL != item) {
00955 for (i = 1; i < local_tree_h->avl_tree_count; ++i) {
00956 if (is_first_item) {
00957
00958
00959
00960
00961 local_tree_h->avl_tree_array[i].tree->avl_param =
00962 local_tree_h->avl_tree_array[i].avl_ctx;
00963 }
00964 rc = mkavl_add_key_idx(local_tree_h, i,
00965 item, &existing_item);
00966 if (mkavl_rc_e_is_notok(rc)) {
00967 goto err_exit;
00968 }
00969 }
00970 item = avl_t_next(&avl_t);
00971 is_first_item = false;
00972 }
00973 }
00974 }
00975
00976 *new_tree_h = local_tree_h;
00977
00978 return (MKAVL_RC_E_SUCCESS);
00979
00980 err_exit:
00981
00982 if (allocated_mkavl_tree) {
00983 delete_context_fn_to_use = NULL;
00984 if (!use_source_context) {
00985 delete_context_fn_to_use = delete_context_fn;
00986 }
00987
00988 mkavl_delete(&local_tree_h, item_fn, delete_context_fn_to_use);
00989 }
00990
00991 return (rc);
00992 }
00993
01003 mkavl_rc_e
01004 mkavl_add (mkavl_tree_handle tree_h, void *item_to_add,
01005 void **existing_item)
01006 {
01007 uint32_t i, err_idx = 0;
01008 void *item, *first_item = NULL;
01009 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS;
01010
01011 if ((NULL == item_to_add) || (NULL == existing_item)) {
01012 return (MKAVL_RC_E_EINVAL);
01013 }
01014 *existing_item = NULL;
01015
01016 if (!mkavl_tree_is_valid(tree_h)) {
01017 return (MKAVL_RC_E_EINVAL);
01018 }
01019
01020 for (i = 0; i < tree_h->avl_tree_count; ++i) {
01021 item = avl_insert(tree_h->avl_tree_array[i].tree, item_to_add);
01022 if (0 == i) {
01023 first_item = item;
01024 } else if (first_item != item) {
01025 err_idx = i + 1;
01026 rc = MKAVL_RC_E_EOOSYNC;
01027 goto err_exit;
01028 }
01029 }
01030
01031 if (NULL == first_item) {
01032 ++(tree_h->item_count);
01033 }
01034
01035 *existing_item = first_item;
01036
01037 return (rc);
01038
01039 err_exit:
01040
01041 for (i = 0; i < err_idx; ++i) {
01042 if (NULL == first_item) {
01043
01044 item = avl_delete(tree_h->avl_tree_array[i].tree, item_to_add);
01045 mkavl_assert_abort(NULL != item);
01046 }
01047 }
01048
01049 return (rc);
01050 }
01051
01062 static inline mkavl_rc_e
01063 mkavl_avl_end_item (const struct avl_node *node, void **found_item,
01064 uint8_t side)
01065 {
01066 const struct avl_node *cur_node;
01067
01068 if (NULL == found_item) {
01069 return (MKAVL_RC_E_EINVAL);
01070 }
01071 *found_item = NULL;
01072
01073 if (side >= 2) {
01074 return (MKAVL_RC_E_EINVAL);
01075 }
01076
01077 if (NULL == node) {
01078 return (MKAVL_RC_E_SUCCESS);
01079 }
01080 cur_node = node;
01081
01082 while (NULL != cur_node->avl_link[side]) {
01083 cur_node = cur_node->avl_link[side];
01084 }
01085 *found_item = cur_node->avl_data;
01086
01087 return (MKAVL_RC_E_SUCCESS);
01088 }
01089
01097 static mkavl_rc_e
01098 mkavl_avl_first (const struct avl_node *node, void **found_item)
01099 {
01100 return (mkavl_avl_end_item(node, found_item, 0));
01101 }
01102
01110 static mkavl_rc_e
01111 mkavl_avl_last (const struct avl_node *node, void **found_item)
01112 {
01113 return (mkavl_avl_end_item(node, found_item, 1));
01114 }
01115
01129 static mkavl_rc_e
01130 mkavl_find_avl_lt (const struct avl_table *avl_tree,
01131 const struct avl_node *node,
01132 bool find_equal_to, const void *lookup_item,
01133 void **found_item)
01134 {
01135 int32_t cmp_rc;
01136 mkavl_rc_e rc;
01137
01138 if ((NULL == found_item) || (NULL == lookup_item) ||
01139 (NULL == avl_tree)) {
01140 return (MKAVL_RC_E_EINVAL);
01141 }
01142 *found_item = NULL;
01143
01144 if (NULL == node) {
01145 return (MKAVL_RC_E_SUCCESS);
01146 }
01147
01148 cmp_rc = avl_tree->avl_compare(node->avl_data, lookup_item,
01149 avl_tree->avl_param);
01150
01151 if (cmp_rc < 0) {
01152
01153 rc = mkavl_find_avl_lt(avl_tree, node->avl_link[1], find_equal_to,
01154 lookup_item, found_item);
01155 if (mkavl_rc_e_is_notok(rc)) {
01156 return (rc);
01157 }
01158
01159 if (NULL == *found_item) {
01160
01161
01162
01163
01164
01165 *found_item = node->avl_data;
01166 }
01167
01168 return (MKAVL_RC_E_SUCCESS);
01169 } else if (cmp_rc > 0) {
01170
01171 return (mkavl_find_avl_lt(avl_tree, node->avl_link[0], find_equal_to,
01172 lookup_item, found_item));
01173 }
01174
01175
01176
01177 if (find_equal_to) {
01178
01179 *found_item = node->avl_data;
01180 return (MKAVL_RC_E_SUCCESS);
01181 }
01182
01183
01184
01185
01186
01187 return (mkavl_avl_last(node->avl_link[0], found_item));
01188 }
01189
01203 static mkavl_rc_e
01204 mkavl_find_avl_gt (const struct avl_table *avl_tree,
01205 const struct avl_node *node,
01206 bool find_equal_to, const void *lookup_item,
01207 void **found_item)
01208 {
01209 int32_t cmp_rc;
01210 mkavl_rc_e rc;
01211
01212 if ((NULL == found_item) || (NULL == lookup_item) ||
01213 (NULL == avl_tree)) {
01214 return (MKAVL_RC_E_EINVAL);
01215 }
01216 *found_item = NULL;
01217
01218 if (NULL == node) {
01219 return (MKAVL_RC_E_SUCCESS);
01220 }
01221
01222 cmp_rc = avl_tree->avl_compare(node->avl_data, lookup_item,
01223 avl_tree->avl_param);
01224
01225 if (cmp_rc < 0) {
01226
01227 return (mkavl_find_avl_gt(avl_tree, node->avl_link[1], find_equal_to,
01228 lookup_item, found_item));
01229 } else if (cmp_rc > 0) {
01230
01231 rc = mkavl_find_avl_gt(avl_tree, node->avl_link[0], find_equal_to,
01232 lookup_item, found_item);
01233 if (mkavl_rc_e_is_notok(rc)) {
01234 return (rc);
01235 }
01236
01237 if (NULL == *found_item) {
01238
01239
01240
01241
01242
01243 *found_item = node->avl_data;
01244 }
01245
01246 return (MKAVL_RC_E_SUCCESS);
01247 }
01248
01249
01250
01251 if (find_equal_to) {
01252
01253 *found_item = node->avl_data;
01254 return (MKAVL_RC_E_SUCCESS);
01255 }
01256
01257
01258
01259
01260
01261 return (mkavl_avl_first(node->avl_link[1], found_item));
01262 }
01263
01274 mkavl_rc_e
01275 mkavl_find (mkavl_tree_handle tree_h, mkavl_find_type_e type,
01276 size_t key_idx, const void *lookup_item, void **found_item)
01277 {
01278 void *item = NULL;
01279 mkavl_rc_e rc;
01280
01281 if ((NULL == lookup_item) || (NULL == found_item)) {
01282 return (MKAVL_RC_E_EINVAL);
01283 }
01284 *found_item = NULL;
01285
01286 if (!mkavl_find_type_e_is_valid(type)) {
01287 return (MKAVL_RC_E_EINVAL);
01288 }
01289
01290 if (!mkavl_tree_is_valid(tree_h)) {
01291 return (MKAVL_RC_E_EINVAL);
01292 }
01293
01294 if (key_idx >= tree_h->avl_tree_count) {
01295 return (MKAVL_RC_E_EINVAL);
01296 }
01297
01298 switch (type) {
01299 case MKAVL_FIND_TYPE_E_EQUAL:
01300 item = avl_find(tree_h->avl_tree_array[key_idx].tree, lookup_item);
01301 break;
01302 case MKAVL_FIND_TYPE_E_GT:
01303 rc = mkavl_find_avl_gt(tree_h->avl_tree_array[key_idx].tree,
01304 tree_h->avl_tree_array[key_idx].tree->avl_root,
01305 false, lookup_item, &item);
01306 if (mkavl_rc_e_is_notok(rc)) {
01307 return (rc);
01308 }
01309 break;
01310 case MKAVL_FIND_TYPE_E_GE:
01311 rc = mkavl_find_avl_gt(tree_h->avl_tree_array[key_idx].tree,
01312 tree_h->avl_tree_array[key_idx].tree->avl_root,
01313 true, lookup_item, &item);
01314 if (mkavl_rc_e_is_notok(rc)) {
01315 return (rc);
01316 }
01317 break;
01318 case MKAVL_FIND_TYPE_E_LT:
01319 rc = mkavl_find_avl_lt(tree_h->avl_tree_array[key_idx].tree,
01320 tree_h->avl_tree_array[key_idx].tree->avl_root,
01321 false, lookup_item, &item);
01322 if (mkavl_rc_e_is_notok(rc)) {
01323 return (rc);
01324 }
01325 break;
01326 case MKAVL_FIND_TYPE_E_LE:
01327 rc = mkavl_find_avl_lt(tree_h->avl_tree_array[key_idx].tree,
01328 tree_h->avl_tree_array[key_idx].tree->avl_root,
01329 true, lookup_item, &item);
01330 if (mkavl_rc_e_is_notok(rc)) {
01331 return (rc);
01332 }
01333 break;
01334 default:
01335 return (MKAVL_RC_E_EINVAL);
01336 }
01337
01338 *found_item = item;
01339
01340 return (MKAVL_RC_E_SUCCESS);
01341 }
01342
01351 mkavl_rc_e
01352 mkavl_remove (mkavl_tree_handle tree_h, const void *item_to_remove,
01353 void **found_item)
01354 {
01355 uint32_t i, err_idx = 0;
01356 void *item, *first_item = NULL;
01357 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS;
01358
01359 if ((NULL == item_to_remove) || (NULL == found_item)) {
01360 return (MKAVL_RC_E_EINVAL);
01361 }
01362 *found_item = NULL;
01363
01364 if (!mkavl_tree_is_valid(tree_h)) {
01365 return (MKAVL_RC_E_EINVAL);
01366 }
01367
01368 for (i = 0; i < tree_h->avl_tree_count; ++i) {
01369 item = avl_delete(tree_h->avl_tree_array[i].tree, item_to_remove);
01370 if (0 == i) {
01371 first_item = item;
01372 } else if (first_item != item) {
01373 err_idx = i + 1;
01374 rc = MKAVL_RC_E_EOOSYNC;
01375 goto err_exit;
01376 }
01377 }
01378
01379 if (NULL != first_item) {
01380 if (0 == tree_h->item_count) {
01381 rc = MKAVL_RC_E_EOOSYNC;
01382 goto err_exit;
01383 }
01384 --(tree_h->item_count);
01385 }
01386
01387 *found_item = first_item;
01388
01389 return (rc);
01390
01391 err_exit:
01392
01393 for (i = 0; i < err_idx; ++i) {
01394 if (NULL != first_item) {
01395
01396 item = avl_insert(tree_h->avl_tree_array[i].tree, first_item);
01397 mkavl_assert_abort(NULL == item);
01398 }
01399 }
01400
01401 return (rc);
01402 }
01403
01421 mkavl_rc_e
01422 mkavl_add_key_idx (mkavl_tree_handle tree_h, size_t key_idx,
01423 void *item_to_add, void **existing_item)
01424 {
01425 void *item;
01426
01427 if ((NULL == item_to_add) || (NULL == existing_item)) {
01428 return (MKAVL_RC_E_EINVAL);
01429 }
01430 *existing_item = NULL;
01431
01432 if (!mkavl_tree_is_valid(tree_h)) {
01433 return (MKAVL_RC_E_EINVAL);
01434 }
01435
01436 if (key_idx >= tree_h->avl_tree_count) {
01437 return (MKAVL_RC_E_EINVAL);
01438 }
01439
01440 item = avl_insert(tree_h->avl_tree_array[key_idx].tree, item_to_add);
01441 *existing_item = item;
01442
01443 return (MKAVL_RC_E_SUCCESS);
01444 }
01445
01463 mkavl_rc_e
01464 mkavl_remove_key_idx (mkavl_tree_handle tree_h, size_t key_idx,
01465 const void *item_to_remove, void **found_item)
01466 {
01467 void *item;
01468
01469 if ((NULL == item_to_remove) || (NULL == found_item)) {
01470 return (MKAVL_RC_E_EINVAL);
01471 }
01472 *found_item = NULL;
01473
01474 if (!mkavl_tree_is_valid(tree_h)) {
01475 return (MKAVL_RC_E_EINVAL);
01476 }
01477
01478 if (key_idx >= tree_h->avl_tree_count) {
01479 return (MKAVL_RC_E_EINVAL);
01480 }
01481
01482 item = avl_delete(tree_h->avl_tree_array[key_idx].tree, item_to_remove);
01483 *found_item = item;
01484
01485 return (MKAVL_RC_E_SUCCESS);
01486 }
01487
01501 uint32_t
01502 mkavl_count (mkavl_tree_handle tree_h)
01503 {
01504 if (!mkavl_tree_is_valid(tree_h)) {
01505 return (0);
01506 }
01507
01508 return (tree_h->item_count);
01509 }
01510
01520 mkavl_rc_e
01521 mkavl_walk (mkavl_tree_handle tree_h, mkavl_walk_cb_fn cb_fn,
01522 void *walk_context)
01523 {
01524 void *item;
01525 bool stop_walk = false;
01526 struct avl_traverser avl_t = {0};
01527 mkavl_rc_e rc = MKAVL_RC_E_SUCCESS;
01528
01529 if (NULL == cb_fn) {
01530 return (MKAVL_RC_E_EINVAL);
01531 }
01532
01533 if (!mkavl_tree_is_valid(tree_h)) {
01534 return (MKAVL_RC_E_EINVAL);
01535 }
01536
01537
01538
01539
01540
01541 avl_t_init(&avl_t, tree_h->avl_tree_array[0].tree);
01542
01543 item = avl_t_first(&avl_t, tree_h->avl_tree_array[0].tree);
01544 while ((NULL != item) && !stop_walk) {
01545 rc = cb_fn(item, tree_h->context, walk_context, &stop_walk);
01546 if (mkavl_rc_e_is_notok(rc)) {
01547 break;
01548 }
01549 item = avl_t_next(&avl_t);
01550 }
01551
01552 return (rc);
01553 }
01554
01564 mkavl_rc_e
01565 mkavl_iter_new (mkavl_iterator_handle *iterator_h, mkavl_tree_handle tree_h,
01566 size_t key_idx)
01567 {
01568 mkavl_iterator_handle local_iter_h;
01569 mkavl_rc_e rc;
01570
01571 if ((NULL == iterator_h) || !mkavl_tree_is_valid(tree_h)) {
01572 return (MKAVL_RC_E_EINVAL);
01573 }
01574
01575 if (key_idx >= tree_h->avl_tree_count) {
01576 return (MKAVL_RC_E_EINVAL);
01577 }
01578 *iterator_h = NULL;
01579
01580 local_iter_h =
01581 tree_h->allocator.mkavl_allocator.malloc_fn(sizeof(*local_iter_h),
01582 tree_h->context);
01583 if (NULL == local_iter_h) {
01584 rc = MKAVL_RC_E_ENOMEM;
01585 goto err_exit;
01586 }
01587 local_iter_h->tree_h = tree_h;
01588 local_iter_h->key_idx = key_idx;
01589 memset(&(local_iter_h->avl_t), 0, sizeof(local_iter_h->avl_t));
01590
01591 avl_t_init(&(local_iter_h->avl_t), tree_h->avl_tree_array[key_idx].tree);
01592
01593 *iterator_h = local_iter_h;
01594
01595 return (MKAVL_RC_E_SUCCESS);
01596
01597 err_exit:
01598
01599 if (NULL != local_iter_h) {
01600 tree_h->allocator.mkavl_allocator.free_fn(local_iter_h,
01601 tree_h->context);
01602 local_iter_h = NULL;
01603 }
01604
01605 return (rc);
01606 }
01607
01616 mkavl_rc_e
01617 mkavl_iter_delete (mkavl_iterator_handle *iterator_h)
01618 {
01619 mkavl_iterator_handle local_iter_h;
01620 mkavl_free_fn free_fn;
01621
01622 if (NULL == iterator_h) {
01623 return (MKAVL_RC_E_EINVAL);
01624 }
01625 local_iter_h = *iterator_h;
01626
01627 if (!mkavl_iterator_is_valid(local_iter_h)) {
01628 return (MKAVL_RC_E_EINVAL);
01629 }
01630
01631 free_fn = local_iter_h->tree_h->allocator.mkavl_allocator.free_fn;
01632 free_fn(local_iter_h, local_iter_h->tree_h->context);
01633
01634 *iterator_h = NULL;
01635
01636 return (MKAVL_RC_E_SUCCESS);
01637 }
01638
01647 mkavl_rc_e
01648 mkavl_iter_first (mkavl_iterator_handle iterator_h, void **item)
01649 {
01650 if (NULL == item) {
01651 return (MKAVL_RC_E_EINVAL);
01652 }
01653 *item = NULL;
01654
01655 if (!mkavl_iterator_is_valid(iterator_h)) {
01656 return (MKAVL_RC_E_EINVAL);
01657 }
01658
01659 *item = avl_t_first(&(iterator_h->avl_t),
01660 iterator_h->tree_h->avl_tree_array[iterator_h->key_idx].tree);
01661
01662 return (MKAVL_RC_E_SUCCESS);
01663 }
01664
01673 mkavl_rc_e
01674 mkavl_iter_last (mkavl_iterator_handle iterator_h, void **item)
01675 {
01676 if (NULL == item) {
01677 return (MKAVL_RC_E_EINVAL);
01678 }
01679 *item = NULL;
01680
01681 if (!mkavl_iterator_is_valid(iterator_h)) {
01682 return (MKAVL_RC_E_EINVAL);
01683 }
01684
01685 *item = avl_t_last(&(iterator_h->avl_t),
01686 iterator_h->tree_h->avl_tree_array[iterator_h->key_idx].tree);
01687
01688 return (MKAVL_RC_E_SUCCESS);
01689 }
01690
01700 mkavl_rc_e
01701 mkavl_iter_find (mkavl_iterator_handle iterator_h, void *lookup_item,
01702 void **found_item)
01703 {
01704 if ((NULL == lookup_item) || (NULL == found_item)) {
01705 return (MKAVL_RC_E_EINVAL);
01706 }
01707 *found_item = NULL;
01708
01709 if (!mkavl_iterator_is_valid(iterator_h)) {
01710 return (MKAVL_RC_E_EINVAL);
01711 }
01712
01713 *found_item =
01714 avl_t_find(&(iterator_h->avl_t),
01715 iterator_h->tree_h->avl_tree_array[iterator_h->key_idx].tree,
01716 lookup_item);
01717
01718 return (MKAVL_RC_E_SUCCESS);
01719 }
01720
01729 mkavl_rc_e
01730 mkavl_iter_next (mkavl_iterator_handle iterator_h, void **item)
01731 {
01732 if (NULL == item) {
01733 return (MKAVL_RC_E_EINVAL);
01734 }
01735 *item = NULL;
01736
01737 if (!mkavl_iterator_is_valid(iterator_h)) {
01738 return (MKAVL_RC_E_EINVAL);
01739 }
01740
01741 *item = avl_t_next(&(iterator_h->avl_t));
01742
01743 return (MKAVL_RC_E_SUCCESS);
01744 }
01745
01754 mkavl_rc_e
01755 mkavl_iter_prev (mkavl_iterator_handle iterator_h, void **item)
01756 {
01757 if (NULL == item) {
01758 return (MKAVL_RC_E_EINVAL);
01759 }
01760 *item = NULL;
01761
01762 if (!mkavl_iterator_is_valid(iterator_h)) {
01763 return (MKAVL_RC_E_EINVAL);
01764 }
01765
01766 *item = avl_t_prev(&(iterator_h->avl_t));
01767
01768 return (MKAVL_RC_E_SUCCESS);
01769 }
01770
01779 mkavl_rc_e
01780 mkavl_iter_cur (mkavl_iterator_handle iterator_h, void **item)
01781 {
01782 if (NULL == item) {
01783 return (MKAVL_RC_E_EINVAL);
01784 }
01785 *item = NULL;
01786
01787 if (!mkavl_iterator_is_valid(iterator_h)) {
01788 return (MKAVL_RC_E_EINVAL);
01789 }
01790
01791 *item = avl_t_cur(&(iterator_h->avl_t));
01792
01793 return (MKAVL_RC_E_SUCCESS);
01794 }