Skip to content

Commit 51afc70

Browse files
pks-tgitster
authored andcommitted
reftable/tree: handle allocation failures
The tree interfaces of the reftable library handle both insertion and searching of tree nodes with a single function, where the behaviour is altered between the two via an `insert` bit. This makes it quit awkward to handle allocation failures because on inserting we'd have to check for `NULL` pointers and return an error, whereas on searching entries we don't have to handle it as an allocation error. Split up concerns of this function into two separate functions, one for inserting entries and one for searching entries. This makes it easy for us to check for allocation errors as `tree_insert()` should never return a `NULL` pointer now. Adapt callers accordingly. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d0501c8 commit 51afc70

File tree

4 files changed

+54
-26
lines changed

4 files changed

+54
-26
lines changed

reftable/tree.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,44 @@ license that can be found in the LICENSE file or at
1111

1212
#include "basics.h"
1313

14-
struct tree_node *tree_search(void *key, struct tree_node **rootp,
15-
int (*compare)(const void *, const void *),
16-
int insert)
14+
struct tree_node *tree_search(struct tree_node *tree,
15+
void *key,
16+
int (*compare)(const void *, const void *))
1717
{
1818
int res;
19+
if (!tree)
20+
return NULL;
21+
res = compare(key, tree->key);
22+
if (res < 0)
23+
return tree_search(tree->left, key, compare);
24+
else if (res > 0)
25+
return tree_search(tree->right, key, compare);
26+
return tree;
27+
}
28+
29+
struct tree_node *tree_insert(struct tree_node **rootp,
30+
void *key,
31+
int (*compare)(const void *, const void *))
32+
{
33+
int res;
34+
1935
if (!*rootp) {
20-
if (!insert) {
36+
struct tree_node *n;
37+
38+
REFTABLE_CALLOC_ARRAY(n, 1);
39+
if (!n)
2140
return NULL;
22-
} else {
23-
struct tree_node *n;
24-
REFTABLE_CALLOC_ARRAY(n, 1);
25-
n->key = key;
26-
*rootp = n;
27-
return *rootp;
28-
}
41+
42+
n->key = key;
43+
*rootp = n;
44+
return *rootp;
2945
}
3046

3147
res = compare(key, (*rootp)->key);
3248
if (res < 0)
33-
return tree_search(key, &(*rootp)->left, compare, insert);
49+
return tree_insert(&(*rootp)->left, key, compare);
3450
else if (res > 0)
35-
return tree_search(key, &(*rootp)->right, compare, insert);
51+
return tree_insert(&(*rootp)->right, key, compare);
3652
return *rootp;
3753
}
3854

reftable/tree.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@ struct tree_node {
1515
struct tree_node *left, *right;
1616
};
1717

18-
/* looks for `key` in `rootp` using `compare` as comparison function. If insert
19-
* is set, insert the key if it's not found. Else, return NULL.
18+
/*
19+
* Search the tree for the node matching the given key using `compare` as
20+
* comparison function. Returns the node whose key matches or `NULL` in case
21+
* the key does not exist in the tree.
22+
*/
23+
struct tree_node *tree_search(struct tree_node *tree,
24+
void *key,
25+
int (*compare)(const void *, const void *));
26+
27+
/*
28+
* Insert a node into the tree. Returns the newly inserted node if the key does
29+
* not yet exist. Otherwise it returns the preexisting node. Returns `NULL`
30+
* when allocating the new node fails.
2031
*/
21-
struct tree_node *tree_search(void *key, struct tree_node **rootp,
22-
int (*compare)(const void *, const void *),
23-
int insert);
32+
struct tree_node *tree_insert(struct tree_node **rootp,
33+
void *key,
34+
int (*compare)(const void *, const void *));
2435

2536
/* performs an infix walk of the tree. */
2637
void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key),

reftable/writer.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,7 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
208208
struct obj_index_tree_node *key;
209209
struct tree_node *node;
210210

211-
node = tree_search(&want, &w->obj_index_tree,
212-
&obj_index_tree_node_compare, 0);
211+
node = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare);
213212
if (!node) {
214213
struct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;
215214

@@ -221,8 +220,8 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
221220

222221
strbuf_reset(&key->hash);
223222
strbuf_addbuf(&key->hash, hash);
224-
tree_search((void *)key, &w->obj_index_tree,
225-
&obj_index_tree_node_compare, 1);
223+
tree_insert(&w->obj_index_tree, key,
224+
&obj_index_tree_node_compare);
226225
} else {
227226
key = node->key;
228227
}

t/unit-tests/t-reftable-tree.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,17 @@ static void t_tree_search(void)
3737
* values[1] and values[10] (inclusive) in the tree.
3838
*/
3939
do {
40-
nodes[i] = tree_search(&values[i], &root, &t_compare, 1);
40+
nodes[i] = tree_insert(&root, &values[i], &t_compare);
41+
check(nodes[i] != NULL);
4142
i = (i * 7) % 11;
4243
} while (i != 1);
4344

4445
for (i = 1; i < ARRAY_SIZE(nodes); i++) {
4546
check_pointer_eq(&values[i], nodes[i]->key);
46-
check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0));
47+
check_pointer_eq(nodes[i], tree_search(root, &values[i], &t_compare));
4748
}
4849

49-
check(!tree_search(values, &root, t_compare, 0));
50+
check(!tree_search(root, values, t_compare));
5051
tree_free(root);
5152
}
5253

@@ -62,7 +63,8 @@ static void t_infix_walk(void)
6263
size_t count = 0;
6364

6465
do {
65-
tree_search(&values[i], &root, t_compare, 1);
66+
struct tree_node *node = tree_insert(&root, &values[i], t_compare);
67+
check(node != NULL);
6668
i = (i * 7) % 11;
6769
count++;
6870
} while (i != 1);

0 commit comments

Comments
 (0)