// File: /workspace/github_c_makefile_star2_O2/qq-smart[P]qq_sh_server/core/qq_rbtree.c
// Function: qq_rbtree_delete
void
qq_rbtree_delete(qq_rbtree_t *tree, qq_rbtree_node_t *node)
{
    qq_uint_t           red;
    qq_rbtree_node_t  **root, *sentinel, *subst, *temp, *w;

    root = &tree->root;
    sentinel = tree->sentinel;

    if (node->left == sentinel) {
        temp = node->right;
        subst = node;
    } else if (node->right == sentinel) {
        temp = node->left;
        subst = node;
    } else {
        subst = qq_rbtree_min(node->right, sentinel);

        if (subst->left != sentinel) {
            temp = subst->left;
        } else {
            temp = subst->right;
        }
    }

    if (subst == *root) {
        *root = temp;
        qq_rbt_black(temp);

        /* DEBUG stuff */
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
        node->key = 0;

        return;
    }

    red = qq_rbt_is_red(subst);

    if (subst == subst->parent->left) {
        subst->parent->left = temp;
    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {
        temp->parent = subst->parent;
    } else {
        if (subst->parent == node) {
            temp->parent = subst;
        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        qq_rbt_copy_color(subst, node);

        if (node == *root) {
            *root = subst;
        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

        if (subst->right != sentinel) {
            subst->right->parent = subst;
        }
    }

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    if (red) {
        return;
    }

    /* a delete fixup */

    while (temp != *root && qq_rbt_is_black(temp)) {
        if (temp == temp->parent->left) {
            w = temp->parent->right;

            if (qq_rbt_is_red(w)) {
                qq_rbt_black(w);
                qq_rbt_red(temp->parent);
                qq_rbtree_left_rotate(root, sentinel, temp->parent);
                w = temp->parent->right;
            }

            if (qq_rbt_is_black(w->left) && qq_rbt_is_black(w->right)) {
                qq_rbt_red(w);
                temp = temp->parent;
            } else {
                if (qq_rbt_is_black(w->right)) {
                    qq_rbt_black(w->left);
                    qq_rbt_red(w);
                    qq_rbtree_right_rotate(root, sentinel, w);
                    w = temp->parent->right;
                }

                qq_rbt_copy_color(w, temp->parent);
                qq_rbt_black(temp->parent);
                qq_rbt_black(w->right);
                qq_rbtree_left_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        } else {
            w = temp->parent->left;

            if (qq_rbt_is_red(w)) {
                qq_rbt_black(w);
                qq_rbt_red(temp->parent);
                qq_rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (qq_rbt_is_black(w->left) && qq_rbt_is_black(w->right)) {
                qq_rbt_red(w);
                temp = temp->parent;
            } else {
                if (qq_rbt_is_black(w->left)) {
                    qq_rbt_black(w->right);
                    qq_rbt_red(w);
                    qq_rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                qq_rbt_copy_color(w, temp->parent);
                qq_rbt_black(temp->parent);
                qq_rbt_black(w->left);
                qq_rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    qq_rbt_black(temp);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %r14
movq 0x8(%rsi), %rcx
movq 0x10(%rsi), %rdx
movq %rsi, %rax
cmpq %r14, %rcx
je 0x7b11
cmpq %r14, %rdx
je 0x7b14
movq %rdx, %rax
movq 0x8(%rdx), %rdx
cmpq %r14, %rdx
jne 0x7aff
movq 0x10(%rax), %rcx
jmp 0x7b14
movq %rdx, %rcx
cmpq (%rbx), %rax
je 0x7b93
movq 0x18(%rax), %rdi
xorl %r8d, %r8d
cmpq 0x8(%rdi), %rax
movb 0x20(%rax), %dl
setne %r8b
movq %rcx, 0x8(%rdi,%r8,8)
cmpq %rsi, %rax
je 0x7ba9
cmpq %rsi, %rdi
cmoveq %rax, %rdi
movq %rdi, 0x18(%rcx)
movq 0x8(%rsi), %rdi
movq %rdi, 0x8(%rax)
movq 0x10(%rsi), %rdi
movq %rdi, 0x10(%rax)
movq 0x18(%rsi), %rdi
movq %rdi, 0x18(%rax)
movb 0x20(%rsi), %r8b
movb %r8b, 0x20(%rax)
movq %rbx, %r8
cmpq %rsi, (%rbx)
je 0x7b78
leaq 0x8(%rdi), %r9
leaq 0x10(%rdi), %r8
cmpq %rsi, 0x8(%rdi)
cmoveq %r9, %r8
movq %rax, (%r8)
movq 0x8(%rax), %rdi
cmpq %r14, %rdi
je 0x7b88
movq %rax, 0x18(%rdi)
movq 0x10(%rax), %r8
cmpq %r14, %r8
jne 0x7baf
jmp 0x7bb3
movq %rcx, (%rbx)
movb $0x0, 0x20(%rcx)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rsi)
movups %xmm0, (%rsi)
jmp 0x7cfd
movq %rcx, %r8
movq %rdi, %rax
movq %rax, 0x18(%r8)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rsi)
movups %xmm0, (%rsi)
testb %dl, %dl
jne 0x7cfd
xorl %r15d, %r15d
cmpq (%rbx), %rcx
je 0x7cf9
cmpb $0x0, 0x20(%rcx)
jne 0x7cf9
leaq 0x18(%rcx), %r12
movq 0x18(%rcx), %rdx
movq 0x8(%rdx), %rax
cmpq %rax, %rcx
je 0x7c67
cmpb $0x0, 0x20(%rax)
je 0x7c0d
movb $0x0, 0x20(%rax)
movb $0x1, 0x20(%rdx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x7a1d
movq (%r12), %rdx
movq 0x8(%rdx), %rax
movq 0x8(%rax), %rcx
cmpb $0x0, 0x20(%rcx)
jne 0x7c47
movq 0x10(%rax), %rcx
cmpb $0x0, 0x20(%rcx)
je 0x7cf3
movb $0x0, 0x20(%rcx)
movb $0x1, 0x20(%rax)
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x79da
movq (%r12), %rdx
movq 0x8(%rdx), %rax
movq 0x8(%rax), %rcx
movb 0x20(%rdx), %sil
movb %sil, 0x20(%rax)
movb %r15b, 0x20(%rdx)
movb %r15b, 0x20(%rcx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x7a1d
jmp 0x7ce7
movq 0x10(%rdx), %rax
cmpb $0x0, 0x20(%rax)
je 0x7c8c
movb $0x0, 0x20(%rax)
movb $0x1, 0x20(%rdx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x79da
movq (%r12), %rdx
movq 0x10(%rdx), %rax
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rcx
cmpb $0x0, 0x20(%rsi)
movb 0x20(%rcx), %dil
je 0x7cc7
testb %dil, %dil
jne 0x7ccc
movb $0x0, 0x20(%rsi)
movb $0x1, 0x20(%rax)
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x7a1d
movq (%r12), %rdx
movq 0x10(%rdx), %rax
movq 0x10(%rax), %rcx
jmp 0x7ccc
testb %dil, %dil
je 0x7cf3
movb 0x20(%rdx), %sil
movb %sil, 0x20(%rax)
movb %r15b, 0x20(%rdx)
movb %r15b, 0x20(%rcx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x79da
movq %rbx, %r12
movq (%r12), %rcx
jmp 0x7bc8
movb $0x1, 0x20(%rax)
jmp 0x7cea
movb $0x0, 0x20(%rcx)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq