struct rb_node * rb_node_create (void *value) { return rb_node_init(rb_node_alloc(), value); }
/** Insert value. Returns 1 if value was inserted, 0 if the value is already stored, and -1 in case of error (e.g., memory allocation failure). */ int bst_insert(rb_tree_t *tree, void *key, size_t key_len, void *val, size_t val_len, rb_node_t **new_node) { rb_node_t *parent = NULL, *curr = tree->root; rb_key_t insert_key = { .data = (void *)key, .len = key_len }; if (!curr) { /* Insert root */ tree->root = rb_node_alloc(key, key_len, val, val_len, parent); if (!tree->root) return -1; if (new_node) *new_node = tree->root; LOG_DBG("Added new root\n"); return 1; } while (1) { int comp; parent = curr; comp = tree->ops->key_compare(&insert_key, &curr->key); /* if (comp == 0) { //LOG_DBG("element exists\n"); return 0; } else */ if (comp < 0) { curr = curr->left; //LOG_DBG("\tgoing left\n"); if (!curr) { /* Insert new node at found location */ curr = rb_node_alloc(key, key_len, val, val_len, parent); parent->left = curr; break; } } else { curr = curr->right; //LOG_DBG("\tgoing right\n"); if (!curr) { /* Insert new node at found location */ curr = rb_node_alloc(key, key_len, val, val_len, parent); parent->right = curr; break; } } } LOG_DBG("\tnew node: %s\n", tree->ops->value_print(&curr->val)); LOG_DBG("\tparent: %s\n", tree->ops->value_print(&parent->val)); if (new_node) *new_node = curr; return curr ? 1 : -1; } static inline rb_node_t *grandparent(rb_node_t *node) { if (node && node->parent) return node->parent->parent; return NULL; } static inline rb_node_t *uncle(rb_node_t *node) { rb_node_t *gp = grandparent(node); if (gp == NULL) return NULL; if (node->parent == gp->left) return gp->right; return gp->left; }