// File: attractivechaos[P]udb2/tommyds/./tommytrie.c
// Function: trie_bucket_remove_existing
static tommy_trie_node* trie_bucket_remove_existing(tommy_trie* trie, tommy_uint_t shift, tommy_trie_node** let_ptr, tommy_trie_node* remove, tommy_key_t key)
{
	tommy_trie_node* node;
	tommy_trie_tree* tree;
	void* ptr;
	tommy_trie_node** let_back[TOMMY_TRIE_LEVEL_MAX + 1];
	tommy_uint_t level;
	tommy_uint_t i;
	tommy_uint_t count;
	tommy_uint_t last;

	level = 0;
recurse:
	ptr = *let_ptr;

	if (!ptr)
		return 0;

	if (trie_get_type(ptr) == TOMMY_TRIE_TYPE_TREE) {
		tree = trie_get_tree(ptr);

		/* save the path */
		let_back[level++] = let_ptr;

		/* go down one level */
		let_ptr = &tree->map[(key >> shift) & TOMMY_TRIE_TREE_MASK];
		shift -= TOMMY_TRIE_TREE_BIT;

		goto recurse;
	}

	node = tommy_cast(tommy_trie_node*, ptr);

	/* if the node to remove is not specified */
	if (!remove) {
		/* remove the first */
		remove = node;

		/* check if it's really the element to remove */
		if (remove->key != key)
			return 0;
	}

	tommy_list_remove_existing(let_ptr, remove);

	/* if the list is not empty, try to reduce */
	if (*let_ptr || !level)
		return remove;

reduce:
	/* go one level up */
	let_ptr = let_back[--level];

	tree = trie_get_tree(*let_ptr);

	/* check if there is only one child node */
	count = 0;
	last = 0;
	for (i = 0; i < TOMMY_TRIE_TREE_MAX; ++i) {
		if (tree->map[i]) {
			/* if we have a sub tree, we cannot reduce */
			if (trie_get_type(tree->map[i]) != TOMMY_TRIE_TYPE_NODE)
				return remove;
			/* if more than one node, we cannot reduce */
			if (++count > 1)
				return remove;
			last = i;
		}
	}

	/* here count is never 0, as we cannot have a tree with only one sub node */
	assert(count == 1);

	*let_ptr = tree->map[last];

	tommy_allocator_free(trie->alloc, tree);
	--trie->node_count;

	/* repeat until more level */
	if (level)
		goto reduce;

	return remove;
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movl %esi, 0x94(%rsp)
movq %rdx, 0x88(%rsp)
movq %rcx, 0x80(%rsp)
movl %r8d, 0x7c(%rsp)
movl $0x0, 0xc(%rsp)
movq 0x88(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x60(%rsp)
cmpq $0x0, 0x60(%rsp)
jne 0x3d3c
movq $0x0, 0xa0(%rsp)
jmp 0x3f8f
movq 0x60(%rsp), %rax
andq $0x1, %rax
cmpq $0x1, %rax
jne 0x3db4
movq 0x60(%rsp), %rax
subq $0x1, %rax
movq %rax, 0x68(%rsp)
movq 0x88(%rsp), %rcx
movl 0xc(%rsp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0xc(%rsp)
movl %eax, %eax
movq %rcx, 0x10(%rsp,%rax,8)
movq 0x68(%rsp), %rax
movl 0x7c(%rsp), %edx
movl 0x94(%rsp), %ecx
shrl %cl, %edx
movl %edx, %ecx
movl %ecx, %ecx
andq $0x7, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x88(%rsp)
movl 0x94(%rsp), %eax
subl $0x3, %eax
movl %eax, 0x94(%rsp)
jmp 0x3d13
movq 0x60(%rsp), %rax
movq %rax, 0x70(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x3dfa
movq 0x70(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rax
movl 0x18(%rax), %eax
cmpl 0x7c(%rsp), %eax
je 0x3df8
movq $0x0, 0xa0(%rsp)
jmp 0x3f8f
jmp 0x3dfa
movq 0x88(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0x49d0
movq 0x88(%rsp), %rax
cmpq $0x0, (%rax)
jne 0x3e24
cmpl $0x0, 0xc(%rsp)
jne 0x3e39
movq 0x80(%rsp), %rax
movq %rax, 0xa0(%rsp)
jmp 0x3f8f
jmp 0x3e3b
movl 0xc(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xc(%rsp)
movl %eax, %eax
movq 0x10(%rsp,%rax,8), %rax
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rax
movq (%rax), %rax
subq $0x1, %rax
movq %rax, 0x68(%rsp)
movl $0x0, 0x4(%rsp)
movl $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
movl 0x8(%rsp), %eax
cmpq $0x8, %rax
jae 0x3f04
movq 0x68(%rsp), %rax
movl 0x8(%rsp), %ecx
cmpq $0x0, (%rax,%rcx,8)
je 0x3ef2
movq 0x68(%rsp), %rax
movl 0x8(%rsp), %ecx
movq (%rax,%rcx,8), %rax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x3ec6
movq 0x80(%rsp), %rax
movq %rax, 0xa0(%rsp)
jmp 0x3f8f
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
cmpl $0x1, %eax
jbe 0x3eeb
movq 0x80(%rsp), %rax
movq %rax, 0xa0(%rsp)
jmp 0x3f8f
movl 0x8(%rsp), %eax
movl %eax, (%rsp)
jmp 0x3ef4
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0x3e80
cmpl $0x1, 0x4(%rsp)
jne 0x3f0d
jmp 0x3f2c
leaq 0x3370(%rip), %rdi      # 0x7284
leaq 0x3257(%rip), %rsi      # 0x7172
movl $0xee, %edx
leaq 0x3368(%rip), %rcx      # 0x728f
callq 0x1050
movq 0x68(%rsp), %rax
movl (%rsp), %ecx
movq (%rax,%rcx,8), %rcx
movq 0x88(%rsp), %rax
movq %rcx, (%rax)
movq 0x98(%rsp), %rax
movq 0x108(%rax), %rdi
movq 0x68(%rsp), %rsi
callq 0x27f0
movq 0x98(%rsp), %rax
movl 0x104(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x104(%rax)
cmpl $0x0, 0xc(%rsp)
je 0x3f7f
jmp 0x3e3b
movq 0x80(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
addq $0xa8, %rsp
retq
nop