// File: /workspace/github_c_makefile_star2_O3/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 %rbx
pushq %rax
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %rbx
leaq -0x80000000(%rsi), %rax
movswq %r14w, %rcx
xorl %edx, %edx
cmpq %rsi, %rcx
setne %dl
leal 0x2(,%rdx,2), %ecx
testq %r15, %r15
je 0x4f0af
movb $0x1, (%r15)
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rax
movl $0x8, %esi
cmovbl %esi, %ecx
movl (%rbx), %ebp
cmpl %ecx, %ebp
jae 0x4f175
leaq -0x8000(%r14), %rsi
movslq 0x4(%rbx), %r15
xorl %edi, %edi
cmpq $-0x10000, %rsi         # imm = 0xFFFF0000
adcb $0x1, %dil
leal 0x1(%r15), %esi
cmpq %rdx, %rax
movl %ecx, (%rbx)
movzbl %dil, %eax
movl $0x3, %ecx
cmovael %eax, %ecx
shll %cl, %esi
addq $0x8, %rsi
movq %rbx, %rdi
callq 0x29a61
movq %rax, %rbx
testq %r15, %r15
je 0x4f165
movq %r14, %rax
shrq $0x3f, %rax
addq %r15, %rax
movzbl %bpl, %ecx
cmpb $0x4, %bpl
je 0x4f130
cmpl $0x8, %ecx
jne 0x4f137
movq (%rbx,%r15,8), %rdx
jmp 0x4f13d
movslq 0x4(%rbx,%r15,4), %rdx
jmp 0x4f13d
movswq 0x6(%rbx,%r15,2), %rdx
movl (%rbx), %esi
cmpl $0x4, %esi
je 0x4f14f
cmpl $0x8, %esi
jne 0x4f155
movq %rdx, (%rbx,%rax,8)
jmp 0x4f15a
movl %edx, 0x4(%rbx,%rax,4)
jmp 0x4f15a
movw %dx, 0x6(%rbx,%rax,2)
decq %r15
decq %rax
testq %r15, %r15
jne 0x4f11f
testq %r14, %r14
js 0x4f19b
movslq 0x4(%rbx), %rax
movl (%rbx), %ecx
jmp 0x4f230
leaq 0x4(%rsp), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4f25f
testb %al, %al
je 0x4f1b0
testq %r15, %r15
je 0x4f251
movb $0x0, (%r15)
jmp 0x4f251
movl (%rbx), %eax
cmpl $0x4, %eax
je 0x4f1f8
cmpl $0x8, %eax
jne 0x4f1fe
movq %r14, 0x8(%rbx)
jmp 0x4f24e
movl 0x4(%rbx), %esi
incl %esi
imull %ebp, %esi
addq $0x8, %rsi
movq %rbx, %rdi
callq 0x29a61
movq %rax, %rbx
movl 0x4(%rsp), %eax
movl 0x4(%rbx), %edx
subl %eax, %edx
jbe 0x4f22c
leaq 0x1(%rax), %rcx
movl (%rbx), %esi
movq %rbx, %rdi
addq $0x8, %rdi
cmpl $0x4, %esi
je 0x4f205
cmpl $0x8, %esi
jne 0x4f214
leaq (%rdi,%rax,8), %rsi
leaq (%rdi,%rcx,8), %rdi
movl $0x3, %ecx
jmp 0x4f221
movl %r14d, 0x8(%rbx)
jmp 0x4f24e
movw %r14w, 0x8(%rbx)
jmp 0x4f24e
leaq (%rdi,%rax,4), %rsi
leaq (%rdi,%rcx,4), %rdi
movl $0x2, %ecx
jmp 0x4f221
leaq (%rdi,%rax,2), %rsi
leaq (%rdi,%rcx,2), %rdi
movl $0x1, %ecx
shll %cl, %edx
callq 0x1f780
movl 0x4(%rsp), %eax
movl (%rbx), %ecx
cltq
cmpl $0x4, %ecx
je 0x4f241
cmpl $0x8, %ecx
jne 0x4f248
movq %r14, 0x8(%rbx,%rax,8)
jmp 0x4f24e
movl %r14d, 0x8(%rbx,%rax,4)
jmp 0x4f24e
movw %r14w, 0x8(%rbx,%rax,2)
incl 0x4(%rbx)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq