// File: /workspace/github_c_makefile_star2_O3/ttoobne[P]bohttpd/src/core/rbtree.c
// Function: rbtree_insert
int rbtree_insert(volatile rbtree_t* tree, rbtree_node_t* node) {
    rbtree_node_t** root;
    rbtree_node_t* nil;
    rbtree_node_t* uncle;

    if (tree == NULL) {
        log_error("rbtree ptr is NULL.");
        return -1;
    }

    root = (rbtree_node_t**)&(tree->root);
    nil = tree->nil;
    
    /* 如果红黑树为空 */
    if (*root == nil) {
        *root = node;
        node->left_son = nil;
        node->right_son = nil;
        node->parent = NULL;
        rbtree_dye_black(node);

        return 0;
    }
    
    tree->insert(*root, node, nil);

    /*
     * 红黑树的性质（引自维基百科）
     *  1.节点是红色或黑色。
     *  2.根是黑色。
     *  3.所有叶子都是黑色（叶子是NIL节点）。
     *  4.每个红色节点必须有两个黑色的子节点。（从每个叶子到根的所有路径上不能有两个连续的红色节点。）
     *  5.从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
     */
    /* 以下的任何操作都不会破坏性质 5 ，但可能导致性质 4 被破坏 */

    /* 如果父亲节点是红色的则性质 4 依然没有满足 */
    while (node != *root && rbtree_is_red(node->parent)) {
        /* 此处父亲节点一定不是根 */
        /* 如果叔叔节点是祖父节点的右孩子 */
        if (node->parent == node->parent->parent->left_son) {
            uncle = node->parent->parent->right_son;

            /* 如果叔叔节点是红色的 */
            if (rbtree_is_red(uncle)) {
                /* 此处可能导致性质 4 被破坏，如果破坏需要继续向上维护 */
                /* case 1: 叔叔和父亲都是红色 */
                /* 将叔叔和父亲染黑，祖父染红，那么祖父可能使得性质破坏 */
                rbtree_dye_black(node->parent);
                rbtree_dye_black(uncle);
                rbtree_dye_red(node->parent->parent);
                node = node->parent->parent;
            } else {
                /* 此处完成后已经满足所有性质 */
                /* case 2: node 是父亲节点的右孩子 */
                /* 通过左旋转化为 case 3 */
                if (node == node->parent->right_son) {
                    node = node->parent;
                    rbtree_left_rotate(root, node, nil);
                }

                /* case 3: 父亲是红色，叔叔是黑色 */
                /* 将父亲染黑，祖父染红，在祖父处进行右旋 */
                rbtree_dye_black(node->parent);
                rbtree_dye_red(node->parent->parent);
                rbtree_right_rotate(root, node->parent->parent, nil);
                /* 至此已经满足所有性质 */
            }
        } else {
            /* 如果叔叔节点是祖父节点的左孩子 */
            uncle = node->parent->parent->left_son;
            /* 如果叔叔节点是红色的 */
            if (rbtree_is_red(uncle)) {
                /* 此处可能导致性质 4 被破坏，如果破坏需要继续向上维护 */
                /* case 4: 叔叔和父亲都是红色 */
                /* 将叔叔和父亲染黑，祖父染红，那么祖父可能使得性质破坏 */
                rbtree_dye_black(uncle);
                rbtree_dye_black(node->parent);
                rbtree_dye_red(node->parent->parent);
                node = node->parent->parent;
            } else {
                /* 此处完成后已经满足所有性质 */
                /* case 5: node 是父亲节点的左孩子 */
                /* 通过右旋转化为 case 6 */
                if (node == node->parent->left_son) {
                    node = node->parent;
                    rbtree_right_rotate(root, node, nil);
                }

                /* case 6: 父亲是红色，叔叔是黑色 */
                /* 将父亲染黑，祖父染红，在祖父处进行左旋 */
                rbtree_dye_black(node->parent);
                rbtree_dye_red(node->parent->parent);
                rbtree_left_rotate(root, node->parent->parent, nil);
            }
        }
    }

    /* 如果最后 node 到了根节点的位置 */
    rbtree_dye_black(*root);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x54a4
movq %rsi, %r15
movq %rdi, %rbx
movq (%rdi), %rdi
movq 0x8(%rbx), %r14
cmpq %r14, %rdi
je 0x54d1
movq 0x10(%rbx), %rax
movq %r15, %rsi
movq %r14, %rdx
callq *%rax
movq (%rbx), %rdx
cmpq %r15, %rdx
je 0x549e
movq 0x20(%r15), %rcx
cmpb $0x0, 0x8(%rcx)
je 0x549e
leaq 0x8(%rcx), %rdi
xorl %eax, %eax
movq 0x20(%rcx), %rdx
movq 0x10(%rdx), %rsi
cmpq %rsi, %rcx
je 0x534b
cmpb $0x0, 0x8(%rsi)
je 0x5368
movb %al, 0x8(%rsi)
movb %al, (%rdi)
jmp 0x535c
movq 0x18(%rdx), %r8
cmpb $0x0, 0x8(%r8)
je 0x5379
movb %al, (%rdi)
movb %al, 0x8(%r8)
movb $0x1, 0x8(%rdx)
movq %rdx, %r15
jmp 0x5484
movq 0x10(%rcx), %rsi
cmpq %rsi, %r15
je 0x5391
movq %rcx, %rsi
movq %r15, %rcx
jmp 0x53c0
movq 0x18(%rcx), %rdi
cmpq %rdi, %r15
je 0x540a
movq %rcx, %rdi
movq %r15, %rcx
jmp 0x543d
movq %rdx, 0x20(%rsi)
addq $0x18, %rdx
cmpq %rcx, (%rbx)
cmoveq %rbx, %rdx
movq %rsi, (%rdx)
movq 0x18(%rsi), %rdx
movq %rdx, 0x10(%rcx)
cmpq %r14, %rdx
je 0x53b4
movq %rcx, 0x20(%rdx)
movq %rsi, 0x20(%rcx)
movq %rcx, 0x18(%rsi)
movq 0x20(%rsi), %rdx
movb $0x0, 0x8(%rsi)
movb $0x1, 0x8(%rdx)
movq 0x18(%rdx), %rsi
movq 0x20(%rdx), %r8
movq %r8, 0x20(%rsi)
movq %rbx, %rdi
cmpq %rdx, (%rbx)
je 0x53ec
leaq 0x10(%r8), %r9
leaq 0x18(%r8), %rdi
cmpq %rdx, 0x10(%r8)
cmoveq %r9, %rdi
movq %rsi, (%rdi)
movq 0x10(%rsi), %rdi
movq %rdi, 0x18(%rdx)
cmpq %r14, %rdi
je 0x5400
movq %rdx, 0x20(%rdi)
movq %rsi, 0x20(%rdx)
movq %rdx, 0x10(%rsi)
jmp 0x5481
movq %rdx, 0x20(%rdi)
addq $0x10, %rdx
cmpq %rcx, (%rbx)
cmoveq %rbx, %rdx
movq %rdi, (%rdx)
movq 0x10(%rdi), %rdx
movq %rdx, 0x18(%rcx)
cmpq %r14, %rdx
je 0x542d
movq %rcx, 0x20(%rdx)
movq %rdi, 0x20(%rcx)
movq %rcx, 0x10(%rdi)
movq 0x20(%rdi), %rdx
movq 0x10(%rdx), %rsi
movb $0x0, 0x8(%rdi)
movb $0x1, 0x8(%rdx)
movq 0x20(%rdx), %r8
movq %r8, 0x20(%rsi)
movq %rbx, %rdi
cmpq %rdx, (%rbx)
je 0x5465
leaq 0x10(%r8), %r9
leaq 0x18(%r8), %rdi
cmpq %rdx, 0x10(%r8)
cmoveq %r9, %rdi
movq %rsi, (%rdi)
movq 0x18(%rsi), %rdi
movq %rdi, 0x10(%rdx)
cmpq %r14, %rdi
je 0x5479
movq %rdx, 0x20(%rdi)
movq %rsi, 0x20(%rdx)
movq %rdx, 0x18(%rsi)
movq %rcx, %r15
movq (%rbx), %rdx
cmpq %rdx, %r15
je 0x549e
movq 0x20(%r15), %rcx
leaq 0x8(%rcx), %rdi
cmpb $0x0, 0x8(%rcx)
jne 0x5331
movb $0x0, 0x8(%rdx)
jmp 0x54e9
leaq 0x2919(%rip), %rsi      # 0x7dc4
leaq 0x295f(%rip), %rdx      # 0x7e11
leaq 0x2929(%rip), %r8       # 0x7de2
movl $0x4, %edi
movl $0x136, %ecx            # imm = 0x136
xorl %eax, %eax
callq 0x252a
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x54eb
movq %r15, (%rbx)
movq %r14, 0x10(%r15)
movq %r14, 0x18(%r15)
movq $0x0, 0x20(%r15)
movb $0x0, 0x8(%r15)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq