// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetAdd
intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {

    // 计算编码 value 所需的长度
    uint8_t valenc = _intsetValueEncoding(value);
    uint32_t pos;

    // 默认设置插入为成功
    if (success) *success = 1;

    /* Upgrade encoding if necessary. If we need to upgrade, we know that
     * this value should be either appended (if > 0) or prepended (if < 0),
     * because it lies outside the range of existing values. */
    // 如果 value 的编码比整数集合现在的编码要大
    // 那么表示 value 必然可以添加到整数集合中
    // 并且整数集合需要对自身进行升级，才能满足 value 所需的编码
    if (valenc > intrev32ifbe(is->encoding)) {
        /* This always succeeds, so we don't need to curry *success. */
        // T = O(N)
        return intsetUpgradeAndAdd(is,value);
    } else {
        // 运行到这里，表示整数集合现有的编码方式适用于 value

        /* Abort if the value is already present in the set.
         * This call will populate "pos" with the right position to insert
         * the value when it cannot be found. */
        // 在整数集合中查找 value ，看他是否存在：
        // - 如果存在，那么将 *success 设置为 0 ，并返回未经改动的整数集合
        // - 如果不存在，那么可以插入 value 的位置将被保存到 pos 指针中
        //   等待后续程序使用
        if (intsetSearch(is,value,&pos)) {
            if (success) *success = 0;
            return is;
        }

        // 运行到这里，表示 value 不存在于集合中
        // 程序需要将 value 添加到整数集合中
    
        // 为 value 在集合中分配空间
        is = intsetResize(is,intrev32ifbe(is->length)+1);
        // 如果新元素不是被添加到底层数组的末尾
        // 那么需要对现有元素的数据进行移动，空出 pos 上的位置，用于设置新值
        // 举个例子
        // 如果数组为：
        // | x | y | z | ? |
        //     |<----->|
        // 而新元素 n 的 pos 为 1 ，那么数组将移动 y 和 z 两个元素
        // | x | y | y | z |
        //         |<----->|
        // 这样就可以将新元素设置到 pos 上了：
        // | x | n | y | z |
        // T = O(N)
        if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);
    }

    // 将新值设置到底层数组的指定位置中
    _intsetSet(is,pos,value);

    // 增一集合元素数量的计数器
    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);

    // 返回添加新元素后的整数集合
    return is;

    /* p.s. 上面的代码可以重构成以下更简单的形式：
    
    if (valenc > intrev32ifbe(is->encoding)) {
        return intsetUpgradeAndAdd(is,value);
    }
     
    if (intsetSearch(is,value,&pos)) {
        if (success) *success = 0;
        return is;
    } else {
        is = intsetResize(is,intrev32ifbe(is->length)+1);
        if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);
        _intsetSet(is,pos,value);

        is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
        return is;
    }
    */
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, %r15
movq %rsi, %r13
movq %rdi, %rbx
leaq -0x80000000(%rsi), %rcx
movswq %r13w, %rax
xorl %edx, %edx
cmpq %rsi, %rax
setne %dl
leal 0x2(,%rdx,2), %eax
testq %r15, %r15
je 0x4b2e0
movb $0x1, (%r15)
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rcx
pushq $0x8
popq %rcx
cmovbl %ecx, %eax
movl (%rbx), %r12d
cmpl %eax, %r12d
jae 0x4b35c
movslq 0x4(%rbx), %r14
movq %r13, 0x10(%rsp)
shrq $0x3f, %r13
movl %eax, (%rbx)
leal 0x1(%r14), %esi
movq %rbx, %rdi
callq 0x4b48e
movq %rax, %rbx
leal (%r14,%r13), %ebp
decl %ebp
movzbl %r12b, %r15d
movq %r14, %r13
subq $0x1, %r13
jb 0x4b37b
cmpb $0x4, %r12b
je 0x4b33e
cmpl $0x8, %r15d
jne 0x4b345
movq (%rbx,%r14,8), %rdx
jmp 0x4b34b
movslq 0x8(%rbx,%r13,4), %rdx
jmp 0x4b34b
movswq 0x8(%rbx,%r13,2), %rdx
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4b4e6
decl %ebp
movq %r13, %r14
jmp 0x4b326
leaq 0xc(%rsp), %rdx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x4b3f2
testb %al, %al
je 0x4b38d
testq %r15, %r15
je 0x4b3c3
movb $0x0, (%r15)
jmp 0x4b3c3
movq 0x10(%rsp), %rdx
testq %rdx, %rdx
js 0x4b3d5
movl 0x4(%rbx), %esi
movq %rbx, %rdi
jmp 0x4b3bb
movl 0x4(%rbx), %esi
incl %esi
movq %rbx, %rdi
callq 0x4b48e
movq %rax, %rbx
movl 0xc(%rsp), %esi
cmpl 0x4(%rax), %esi
jae 0x4b3b5
leal 0x1(%rsi), %edx
movq %rbx, %rdi
callq 0x4b49a
movl 0xc(%rsp), %esi
movq %rbx, %rdi
movq %r13, %rdx
callq 0x4b4e6
incl 0x4(%rbx)
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%rbx), %eax
cmpl $0x4, %eax
je 0x4b3e7
cmpl $0x8, %eax
jne 0x4b3ec
movq %rdx, 0x8(%rbx)
jmp 0x4b3c0
movl %edx, 0x8(%rbx)
jmp 0x4b3c0
movw %dx, 0x8(%rbx)
jmp 0x4b3c0