From 3d7e9e7c0315f14d8180021d8e76e9c05cf13699 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 28 Mar 2021 09:29:04 +0200 Subject: [PATCH] Add _get_at method for B+TREE --- README.md | 11 +++++++++-- m-bptree.h | 23 ++++++++++++++++++++--- tests/test-mbptree.c | 7 +++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2faea7df..98d55c76 100644 --- a/README.md +++ b/README.md @@ -3110,12 +3110,19 @@ or NULL if there is no element in the B+Tree. Return a pointer to the maximum element of the tree or NULL if there is no element in the B+Tree. -##### value\_type * name\_get(const name\_t tree, const key\_type *data) -##### const value\_type * name\_cget(const name\_t tree, const key\_type *data) +##### value\_type * name\_get(const name\_t tree, const key\_type data) +##### const value\_type * name\_cget(const name\_t tree, const key\_type data) Return a pointer to the value of the tree 'tree' that is associated to 'data', or NULL if there is no match. +##### value\_type * name\_get\_at(name\_t tree, const key\_type data) + +Return a pointer to the value of the tree 'tree' that is associated to 'data'. +If the key doesn't exist yet in the tree, a new entry is created with 'key' +and a value initialized with its INIT operator, +then a pointer to the newly created entry is returned. + ##### void name\_swap(name\_t tree1, name\_t tree2) Swap both trees. diff --git a/m-bptree.h b/m-bptree.h index 42914a32..f8c181a4 100644 --- a/m-bptree.h +++ b/m-bptree.h @@ -153,7 +153,7 @@ #define M_BPTR33_KEY_OPLIST_FAILURE(name, oplist) \ ((M_LIB_ERROR(ARGUMENT_OF_BPTREE_OPLIST_IS_NOT_AN_OPLIST, name, oplist))) -/* OPLIST definition of a b+tree */ +/* OPLIST definition of a b+tree (global tree) */ #define M_BPTR33_KEY_OPLIST_P3(name, oplist) \ (INIT(M_C(name, _init)), \ INIT_SET(M_C(name, _init_set)), \ @@ -204,7 +204,7 @@ #define M_BPTR33_OPLIST2_FAILURE(name, key_oplist, value_oplist) \ ((M_LIB_ERROR(ARGUMENT_OF_BPTREE_OPLIST_IS_NOT_AN_OPLIST, name, key_oplist, value_oplist))) -/* Final definition of the oplist */ +/* Final definition of the oplist (associative array) */ #define M_BPTR33_OPLIST2_P4(name, key_oplist, value_oplist) \ (INIT(M_C(name, _init)), \ INIT_SET(M_C(name, _init_set)), \ @@ -235,7 +235,6 @@ ERASE_KEY(M_C(name, _erase)), \ KEY_OPLIST(key_oplist), \ VALUE_OPLIST(value_oplist), \ - M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)(GET_STR(M_C(name, _get_str)),), \ M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)(PARSE_STR(M_C(name, _parse_str)),), \ M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)(OUT_STR(M_C(name, _out_str)),), \ M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)(IN_STR(M_C(name, _in_str)),), \ @@ -757,6 +756,24 @@ } \ } \ \ + static inline value_t *M_C(name, _get_at)(tree_t b, key_t const key) \ + { \ + M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ + /* Not optimized implementation */ \ + value_t *ret = M_C(name, _get)(b, key); \ + if (ret == NULL) { \ + M_IF(isMap)( \ + value_t v; \ + M_CALL_INIT(value_oplist, v); \ + M_C(name, _set_at)(b, key, v); \ + , \ + M_C(name, _push)(b, key); \ + ) \ + ret = M_C(name, _get)(b, key); \ + } \ + return ret; \ + } \ + \ static inline int \ M_C(name, _search_and_remove_in_leaf)(node_t n, key_t const key) \ { \ diff --git a/tests/test-mbptree.c b/tests/test-mbptree.c index 4c92df2b..c4b2ccbc 100644 --- a/tests/test-mbptree.c +++ b/tests/test-mbptree.c @@ -154,6 +154,13 @@ static void test1(void) } assert (btree_size(b) == 0); assert (btree_empty_p(b)); + + int *p = btree_get_at(b, 1000); + assert(p != NULL && *p == 0); + *p = 23; + p = btree_get_at(b, 1000); + assert(p != NULL && *p == 23); + btree_clear(b); }