static struct hamt_node *__hamt_new_node2(struct hamt_root *root, void *item1, int slice1, void *item2, int slice2) { struct hamt_node *node = \ __hamt_new_node(root, set_add(set_add(0ULL, slice1), slice2), 2); node->slots[set_slot_number(node->mask, slice1)] = item_to_slot(item1); node->slots[set_slot_number(node->mask, slice2)] = item_to_slot(item2); return node; }
void *hamt_insert(struct hamt_root *root, void *item) { uint128_t *item_hash = root->hash(root->hash_ud, item); assert(((unsigned long)item & ITEM_MASK) == 0); assert(item); if (unlikely(ston(root->slot) == NULL)) { root->slot = item_to_slot(item); return item; } struct hamt_state s; s.level = 0; s.ptr[0] = &root->slot; void *found_item = __hamt_search(root, item_hash, &s); if (unlikely(found_item != NULL)) { return found_item; } if (!is_leaf(s.ptr[s.level])) { __hamt_add_slot(root, s.ptr[s.level], item, item_hash, s.level); } else { void *leaf = to_leaf(s.ptr[s.level]); uint128_t *leaf_hash = root->hash(root->hash_ud, leaf); __hamt_insert_leaf(root, &s, item_hash, item, leaf_hash, leaf); } return item; }
static struct hamt_node *__hamt_add_slot(struct hamt_root *root, struct hamt_slot *slot_ptr, void *item, uint128_t *item_hash, int level) { uint64_t slice = slice_get(*item_hash, level); struct hamt_node *old_node = ston(*slot_ptr); int old_size = set_count(old_node->mask); int new_size = old_size + 1; struct hamt_node *node = __hamt_new_node(root, set_add(old_node->mask, slice), new_size); *slot_ptr = ntos(node); int slot = set_slot_number(node->mask, slice); memcpy(&node->slots[0], &old_node->slots[0], sizeof(struct hamt_slot)*slot); memcpy(&node->slots[slot+1], &old_node->slots[slot], sizeof(struct hamt_slot)*(old_size-slot)); node->slots[slot] = item_to_slot(item); __hamt_free_node(root, old_node); return node; }
static inline void __hamt_insert_leaf(struct hamt_root *root, struct hamt_state *s, uint128_t *item_hash, void *item, uint128_t *leaf_hash, void *leaf) { int leaf_slice = slice_get(*leaf_hash, s->level); int item_slice = slice_get(*item_hash, s->level); if (leaf_slice != item_slice) { *s->ptr[s->level] = ntos(__hamt_new_node2(root, item, item_slice, leaf, leaf_slice)); } else { struct hamt_node *node = __hamt_new_node1(root, item_slice, item_to_slot(NULL)); *s->ptr[s->level] = ntos(node); s->ptr[s->level + 1] = &node->slots[0]; s->level += 1; __hamt_insert_leaf(root, s, item_hash, item, leaf_hash, leaf); } }
static void __ohamt_insert_leaf(struct ohamt_root *root, struct ohamt_state *s, uint128_t item_hash, uint64_t item, uint128_t leaf_hash, uint64_t leaf) { int leaf_slice = slice_get(leaf_hash, s->level); int item_slice = slice_get(item_hash, s->level); if (leaf_slice != item_slice) { *s->ptr[s->level] = ntos(__ohamt_new_node2(root, item, item_slice, leaf, leaf_slice)); } else { struct ohamt_node *node = __ohamt_new_node1(root, item_slice, item_to_slot(OHAMT_NOT_FOUND)); *s->ptr[s->level] = ntos(node); s->ptr[s->level + 1] = &node->slots[0]; s->level += 1; __ohamt_insert_leaf(root, s, item_hash, item, leaf_hash, leaf); } }