// File: /workspace/github_c_makefile_star2_O3/ttoobne[P]bohttpd/src/core/rbtree.c
// Function: rbtree_delete
int rbtree_delete(volatile rbtree_t* tree, rbtree_node_t* node) {
    rbtree_node_t** root;
    rbtree_node_t* nil;
    rbtree_node_t* replace;
    rbtree_node_t* inharm;
    rbtree_node_t* brother;
    int red;

    if (tree == NULL) {
        log_error("rbtree ptr is NULL.");
        return -1;
    }

    if (node == NULL) {
        log_error("rbtree node is invalid.");
        return -1;
    }

    root = (rbtree_node_t**)&(tree->root);
    nil = tree->nil;

    /*
     * 红黑树的删除操作整体分为两部分
     * 第一部分类似普通二叉搜索树的删除。
     * 如果只有一个孩子（非叶子节点），那么直接让该孩子替代被删除点的位置即可。
     * 如果有两个孩子（非叶子节点），那么找到该节点的前驱或者后继节点，将该点的值赋给被删点，从而替代要删的点被删除。
     * 这里是用的后继节点。
     */

    /*
     * Delete 部分
     * 类似普通二叉搜索树那样删除节点
     */

    if (node->left_son == nil) {
        /*
         * D-case 1: 有一个右孩子的简单情况（这里孩子指非叶子节点）
         * 将右孩子（一定是红色）变黑替代 node 即可。
         */
        /*
         * D-case 2: 没有孩子的情况（这里孩子指非叶子节点）
         * 如果 node 是红色那么不需要变色
         * 如果 node 为黑色则最为复杂，需要执行第二部分 Fix 操作
         */
        replace = node;
        inharm = node->right_son;
    } else if (node->right_son == nil) {
        /*
         * D-case 3: 有一个左孩子的情况
         * 将左孩子（一定是红色）变黑替代 node 即可。
         */
        replace = node;
        inharm = node->left_son;
    } else {
        /*
         * D-case 4: 有两个孩子（这里孩子指非叶子节点）
         * 可以通过用后继节点替换 node 从而转化为 D-case 1~3
         * 因为后继节点一定只有一个孩子
         */
        replace = rbtree_get_successor(node, nil);
        inharm = replace->right_son;
    }

    /* D-case 1~3 中如果 node 是 root */
    if (replace == *root) {
        inharm->parent = NULL;
        *root = inharm;
        rbtree_dye_black(*root);

        /* 清理工作实际上由调用者完成，这里简单清空指针 */
        node->left_son = NULL;
        node->right_son = NULL;
        node->parent = NULL;

        return 0;
    }

    /* 由于 node 的内存由调用者管理，所以用 replace 接替 node 的位置而非直接将 replace 的值赋给 node */
    /* 那么需要保存 replace 的颜色(也就是删掉的点的颜色) */
    red = rbtree_is_red(replace);

    if (replace == node) {
        /* D-case 1~3 */
        /* 直接让 node 的儿子接替 node 即可 */
        inharm->parent = node->parent;
        if (node == node->parent->left_son) {
            node->parent->left_son = inharm;
        } else {
            node->parent->right_son = inharm;
        }
    } else {
        /* D-case 4 转化为 D-case 1~3 */
        /* 由 replace 替代 node 被删除 */
        /* 这里由于 node 的内存由调用者管理，所以并不是直接将 replace 的值放到 node */
        /* 而是用 replace 接替 node 的位置 */
        if (replace->parent != node) {
            /* 如果 replace 与 node 之间隔了若干代 */
            inharm->parent = replace->parent;
        } else {
            inharm->parent = replace;
        }

        /* 不管 replace 的父亲是不是 node 都要替换 replace 父亲的孩子为 inharm */
        if (replace == replace->parent->left_son) {
            replace->parent->left_son = inharm;
        } else {
            replace->parent->right_son = inharm;
        }

        /* 用 replace 替换 node 的位置和颜色 */
        replace->left_son = node->left_son;
        replace->right_son = node->right_son;
        replace->parent = node->parent;
        rbtree_copy_color(replace, node);

        /* 更新父亲的孩子 */
        if (node == *root) {
            *root = replace;
        } else {
            if (node == node->parent->left_son) {
                node->parent->left_son = replace;
            } else {
                node->parent->right_son = replace;
            }
        }

        /* 更新孩子的父亲 */
        if (replace->left_son != nil) {
            replace->left_son->parent = replace;
        }
        if (replace->right_son != nil) {
            replace->right_son->parent = replace;
        }
    }

    /* 清理工作实际上由调用者完成，这里简单清空指针 */
    node->left_son = NULL;
    node->right_son = NULL;
    node->parent = NULL;

    /* 如果被删除的点是红色，那么不需要做任何处理 */
    if (red) {
        return 0;
    }

    /*
     * 红黑树的性质（引自维基百科）
     *  1.节点是红色或黑色。
     *  2.根是黑色。
     *  3.所有叶子都是黑色（叶子是NIL节点）。
     *  4.每个红色节点必须有两个黑色的子节点。（从每个叶子到根的所有路径上不能有两个连续的红色节点。）
     *  5.从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
     */

    /*
     * Fix 部分
     * 删除完点之后如果被删点是黑色，则所在链上不满足性质 5 ，需要调整
     * D-case 2 较为复杂，可能需要向上调整
     * 而 D-case 1,3 直接改变 inharm 颜色即可
     */

    /* D-case 2 由于删除了一个黑色节点导致 inharm 所在的链不满足性质 5 */
    /* 则需要不断向上调整 */
    /* 此时 inharm 一定是 nil 节点，且一定有一个非 nil 的兄弟 */
    while (inharm != *root && rbtree_is_black(inharm)) {
        /* 如果兄弟节点是右孩子 */
        if (inharm == inharm->parent->left_son) {
            brother = inharm->parent->right_son;
            if (brother == nil) {
                log_debug("brother is nil");
                exit(1);
            }
            //ASSERT(brother != nil, "why!!! brother is nil!\n");

            /* F-case 1: */
            /* 如果兄弟为红色，那么 inharm 父亲一定为黑色 */
            /* 将兄弟和父亲变色，然后左旋则兄弟节点就是黑色，则转化为了 F-case 2~4 */
            if (rbtree_is_red(brother)) {
                rbtree_dye_black(brother);
                rbtree_dye_red(inharm->parent);
                rbtree_left_rotate(root, inharm->parent, nil);
                brother = inharm->parent->right_son;
            }

            if (brother == nil) {
                log_debug("brother is nil after f-case 1");
                exit(1);
            }

            /* F-case 2: */
            /* 如果兄弟节点和它的两个孩子都是黑色 */
            /* 那么兄第节点可以变成红色来弥补不平衡的黑色 */
            if (rbtree_is_black(brother->left_son) && rbtree_is_black(brother->right_son)) {
                rbtree_dye_red(brother);
                inharm = brother->parent;
                /* 如果父亲是是红色则退出循环再将 inharm 染黑即可满足所有性质 */
                /* 否则是黑色就需要继续向上调整 */
            } else {
                /* F-case 3: */
                /* 如果兄弟节点的右孩子不是红色，那么左孩子一定是红色 */
                /* 将兄弟节点和其左孩子变色，进行右旋，这时新兄弟节点右孩子是红色，转化为 F-case 4 */
                if (rbtree_is_black(brother->right_son)) {
                    rbtree_dye_red(brother);
                    rbtree_dye_black(brother->left_son);
                    rbtree_right_rotate(root, brother, nil);
                    brother = inharm->parent->right_son;
                }

                if (brother == nil) {
                    log_debug("brother is nil in f-case 4");
                    exit(1);
                }

                /* F-case 4: */
                /* 兄弟节点的右孩子为红色 */
                /* 这时要用右孩子变黑来弥补左边失去的黑色 */
                rbtree_dye_black(brother->right_son);
                rbtree_copy_color(brother, brother->parent);
                rbtree_dye_black(brother->parent);
                rbtree_left_rotate(root, brother->parent, nil);
                inharm = *root;     /* 至此已经满足所有性质 */
            }
        } else {
            /* 如果兄弟节点是左孩子 */
            brother = inharm->parent->left_son;

            /* F-case 5: */
            /* 如果兄弟为红色，那么 inharm 父亲一定为黑色 */
            /* 将兄弟和父亲变色，然后右旋则兄弟节点就是黑色，则转化为了 F-case 6~8 */
            if (rbtree_is_red(brother)) {
                rbtree_dye_black(brother);
                rbtree_dye_red(inharm->parent);
                rbtree_right_rotate(root, inharm->parent, nil);
                brother = inharm->parent->left_son;
            }

            /* F-case 6: */
            /* 如果兄弟节点和它的两个孩子都是黑色 */
            /* 那么兄第节点可以变成红色来弥补不平衡的黑色 */
            if (rbtree_is_black(brother->left_son) && rbtree_is_black(brother->right_son)) {
                rbtree_dye_red(brother);
                inharm = brother->parent;
                /* 如果父亲是是红色则退出循环再将 inharm 染黑即可满足所有性质 */
                /* 否则是黑色就需要继续向上调整 */
            } else {
                /* F-case 7: */
                /* 如果兄弟节点的左孩子不是红色，那么右孩子一定是红色 */
                /* 将兄弟节点和其右孩子变色，进行左旋，这时新兄弟节点左孩子是红色，转化为 F-case 8 */
                if (rbtree_is_black(brother->left_son)) {
                    rbtree_dye_red(brother);
                    rbtree_dye_black(brother->right_son);
                    rbtree_left_rotate(root, brother, nil);
                    brother = inharm->parent->left_son;
                }

                /* F-case 8: */
                /* 兄弟节点的左孩子为红色 */
                /* 这时要用左孩子变黑来弥补右边失去的黑色 */
                rbtree_dye_black(brother->left_son);
                rbtree_copy_color(brother, brother->parent);
                rbtree_dye_black(brother->parent);
                rbtree_right_rotate(root, brother->parent, nil);
                inharm = *root;     /* 至此已经满足所有性质 */
            }
        }
    }
    
    /* 如果是 D-case 1,3 直接将 inharm 染黑即可 */
    /* 如果是 F-case 2,6 也是直接将 inharm 染黑 */
    rbtree_dye_black(inharm);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x5587
testq %rsi, %rsi
je 0x55a8
movq 0x8(%rdi), %rcx
movq 0x10(%rsi), %r10
movq 0x18(%rsi), %r11
movq %rsi, %rax
movq %r11, %rdx
cmpq %rcx, %r10
je 0x5543
movq %rsi, %rax
movq %r10, %rdx
cmpq %rcx, %r11
je 0x5543
movq %r11, %rdx
movq %rdx, %rax
movq 0x10(%rdx), %rdx
cmpq %rcx, %rdx
jne 0x5533
movq 0x18(%rax), %rdx
leaq 0x10(%rsi), %r8
cmpq (%rdi), %rax
je 0x55d8
movb 0x8(%rax), %r9b
cmpq %rsi, %rax
je 0x55f5
movq 0x20(%rax), %rbx
cmpq %rsi, %rbx
cmoveq %rax, %rbx
movq %rbx, 0x20(%rdx)
movq 0x20(%rax), %rbx
cmpq 0x10(%rbx), %rax
je 0x5609
movq %rdx, 0x18(%rbx)
movq 0x18(%rsi), %r11
jmp 0x5610
leaq 0x2836(%rip), %rsi      # 0x7dc4
leaq 0x288a(%rip), %rdx      # 0x7e1f
leaq 0x2846(%rip), %r8       # 0x7de2
movl $0x4, %edi
movl $0x1a4, %ecx            # imm = 0x1A4
jmp 0x55c7
leaq 0x2815(%rip), %rsi      # 0x7dc4
leaq 0x2869(%rip), %rdx      # 0x7e1f
leaq 0x2870(%rip), %r8       # 0x7e2d
movl $0x4, %edi
movl $0x1a9, %ecx            # imm = 0x1A9
xorl %eax, %eax
callq 0x252a
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x5916
xorl %eax, %eax
movq %rax, 0x20(%rdx)
movq %rdx, (%rdi)
movb $0x0, 0x8(%rdx)
movq %rax, 0x10(%r8)
xorps %xmm0, %xmm0
movups %xmm0, (%r8)
jmp 0x5916
movq 0x20(%rsi), %rax
movq %rax, 0x20(%rdx)
cmpq %rsi, 0x10(%rax)
je 0x565f
movq %rdx, 0x18(%rax)
jmp 0x5663
movq %rdx, 0x10(%rbx)
movq (%r8), %r10
movq %r10, 0x10(%rax)
movq %r11, 0x18(%rax)
movq 0x20(%rsi), %r10
movq %r10, 0x20(%rax)
movb 0x8(%rsi), %r11b
movb %r11b, 0x8(%rax)
movq %rdi, %r11
cmpq %rsi, (%rdi)
je 0x5640
leaq 0x10(%r10), %rbx
leaq 0x18(%r10), %r11
cmpq %rsi, 0x10(%r10)
cmoveq %rbx, %r11
movq %rax, (%r11)
movq 0x10(%rax), %rsi
cmpq %rcx, %rsi
je 0x5650
movq %rax, 0x20(%rsi)
movq 0x18(%rax), %rsi
cmpq %rcx, %rsi
je 0x5663
movq %rax, 0x20(%rsi)
jmp 0x5663
movq %rdx, 0x10(%rax)
xorl %eax, %eax
xorps %xmm0, %xmm0
movups %xmm0, (%r8)
movq $0x0, 0x10(%r8)
testb %r9b, %r9b
jne 0x5916
cmpq (%rdi), %rdx
je 0x5912
xorl %esi, %esi
cmpb $0x0, 0x8(%rdx)
jne 0x5912
movq 0x20(%rdx), %r9
movq 0x10(%r9), %r8
cmpq %r8, %rdx
je 0x57bd
cmpb $0x0, 0x8(%r8)
je 0x56f8
movb $0x0, 0x8(%r8)
movb $0x1, 0x8(%r9)
movq 0x20(%r9), %r11
movq %r11, 0x20(%r8)
movq %rdi, %r10
cmpq %r9, (%rdi)
je 0x56d4
leaq 0x10(%r11), %rbx
leaq 0x18(%r11), %r10
cmpq %r9, 0x10(%r11)
cmoveq %rbx, %r10
movq %r8, (%r10)
movq 0x18(%r8), %r10
movq %r10, 0x10(%r9)
cmpq %rcx, %r10
je 0x56e8
movq %r9, 0x20(%r10)
movq %r8, 0x20(%r9)
movq %r9, 0x18(%r8)
movq 0x20(%rdx), %r8
movq 0x10(%r8), %r8
movq 0x10(%r8), %r9
cmpb $0x0, 0x8(%r9)
jne 0x5764
movq 0x18(%r8), %r9
cmpb $0x0, 0x8(%r9)
movb $0x1, 0x8(%r8)
je 0x590c
movb $0x0, 0x8(%r9)
movq 0x20(%r8), %r11
movq %r11, 0x20(%r9)
movq %rdi, %r10
cmpq %r8, (%rdi)
je 0x573c
leaq 0x10(%r11), %rbx
leaq 0x18(%r11), %r10
cmpq %r8, 0x10(%r11)
cmoveq %rbx, %r10
movq %r9, (%r10)
movq 0x10(%r9), %r10
movq %r10, 0x18(%r8)
cmpq %rcx, %r10
je 0x5750
movq %r8, 0x20(%r10)
movq %r9, 0x20(%r8)
movq %r8, 0x10(%r9)
movq 0x20(%rdx), %rdx
movq 0x10(%rdx), %r8
movq 0x10(%r8), %r9
movb %sil, 0x8(%r9)
movq 0x20(%r8), %rdx
movb 0x8(%rdx), %r9b
movb %r9b, 0x8(%r8)
movb %sil, 0x8(%rdx)
movq 0x10(%rdx), %r8
movq 0x20(%rdx), %r10
movq %r10, 0x20(%r8)
movq %rdi, %r9
cmpq %rdx, (%rdi)
je 0x579c
leaq 0x10(%r10), %r11
leaq 0x18(%r10), %r9
cmpq %rdx, 0x10(%r10)
cmoveq %r11, %r9
movq %r8, (%r9)
movq 0x18(%r8), %r9
movq %r9, 0x10(%rdx)
cmpq %rcx, %r9
je 0x57b0
movq %rdx, 0x20(%r9)
movq %r8, 0x20(%rdx)
movq %rdx, 0x18(%r8)
jmp 0x58f6
movq 0x18(%r9), %r8
cmpq %rcx, %r8
je 0x593e
cmpb $0x0, 0x8(%r8)
je 0x581f
movb $0x0, 0x8(%r8)
movb $0x1, 0x8(%r9)
movq 0x20(%r9), %r11
movq %r11, 0x20(%r8)
movq %rdi, %r10
cmpq %r9, (%rdi)
je 0x57fb
leaq 0x10(%r11), %rbx
leaq 0x18(%r11), %r10
cmpq %r9, 0x10(%r11)
cmoveq %rbx, %r10
movq %r8, (%r10)
movq 0x10(%r8), %r10
movq %r10, 0x18(%r9)
cmpq %rcx, %r10
je 0x580f
movq %r9, 0x20(%r10)
movq %r8, 0x20(%r9)
movq %r9, 0x10(%r8)
movq 0x20(%rdx), %r8
movq 0x18(%r8), %r8
cmpq %rcx, %r8
je 0x591d
movq 0x10(%r8), %r9
movq 0x18(%r8), %r10
cmpb $0x0, 0x8(%r9)
movb 0x8(%r10), %r10b
je 0x5890
testb %r10b, %r10b
jne 0x5895
movb $0x1, 0x8(%r8)
movb $0x0, 0x8(%r9)
movq 0x20(%r8), %r11
movq %r11, 0x20(%r9)
movq %rdi, %r10
cmpq %r8, (%rdi)
je 0x586a
leaq 0x10(%r11), %rbx
leaq 0x18(%r11), %r10
cmpq %r8, 0x10(%r11)
cmoveq %rbx, %r10
movq %r9, (%r10)
movq 0x18(%r9), %r10
movq %r10, 0x10(%r8)
cmpq %rcx, %r10
je 0x587e
movq %r8, 0x20(%r10)
movq %r9, 0x20(%r8)
movq %r8, 0x18(%r9)
movq 0x20(%rdx), %rdx
movq 0x18(%rdx), %r8
jmp 0x5895
testb %r10b, %r10b
je 0x5907
cmpq %rcx, %r8
je 0x595f
movq 0x18(%r8), %rdx
movb %sil, 0x8(%rdx)
movq 0x20(%r8), %rdx
movb 0x8(%rdx), %r9b
movb %r9b, 0x8(%r8)
movb %sil, 0x8(%rdx)
movq 0x18(%rdx), %r8
movq 0x20(%rdx), %r10
movq %r10, 0x20(%r8)
movq %rdi, %r9
cmpq %rdx, (%rdi)
je 0x58da
leaq 0x10(%r10), %r11
leaq 0x18(%r10), %r9
cmpq %rdx, 0x10(%r10)
cmoveq %r11, %r9
movq %r8, (%r9)
movq 0x10(%r8), %r9
movq %r9, 0x18(%rdx)
cmpq %rcx, %r9
je 0x58ee
movq %rdx, 0x20(%r9)
movq %r8, 0x20(%rdx)
movq %rdx, 0x10(%r8)
movq %rdi, %r8
movq (%r8), %rdx
cmpq (%rdi), %rdx
jne 0x5688
jmp 0x5912
movb $0x1, 0x8(%r8)
addq $0x20, %r8
jmp 0x58f9
movb $0x0, 0x8(%rdx)
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
leaq 0x24a0(%rip), %rsi      # 0x7dc4
leaq 0x24f4(%rip), %rdx      # 0x7e1f
leaq 0x2522(%rip), %r8       # 0x7e54
movl $0x1, %edi
movl $0x254, %ecx            # imm = 0x254
jmp 0x597e
leaq 0x247f(%rip), %rsi      # 0x7dc4
leaq 0x24d3(%rip), %rdx      # 0x7e1f
leaq 0x24f2(%rip), %r8       # 0x7e45
movl $0x1, %edi
movl $0x244, %ecx            # imm = 0x244
jmp 0x597e
leaq 0x245e(%rip), %rsi      # 0x7dc4
leaq 0x24b2(%rip), %rdx      # 0x7e1f
leaq 0x24fe(%rip), %r8       # 0x7e72
movl $0x1, %edi
movl $0x26c, %ecx            # imm = 0x26C
xorl %eax, %eax
callq 0x252a
movl $0x1, %edi
callq 0x23f0
nop