// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetUpgradeAndAdd
static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {
    
    // 当前的编码方式
    uint8_t curenc = intrev32ifbe(is->encoding);

    // 新值所需的编码方式
    uint8_t newenc = _intsetValueEncoding(value);

    // 当前集合的元素数量
    int length = intrev32ifbe(is->length);

    // 根据 value 的值，决定是将它添加到底层数组的最前端还是最后端
    // 注意，因为 value 的编码比集合原有的其他元素的编码都要大
    // 所以 value 要么大于集合中的所有元素，要么小于集合中的所有元素
    // 因此，value 只能添加到底层数组的最前端或最后端
    int prepend = value < 0 ? 1 : 0;

    /* First set new encoding and resize */
    // 更新集合的编码方式
    is->encoding = intrev32ifbe(newenc);
    // 根据新编码对集合（的底层数组）进行空间调整
    // T = O(N)
    is = intsetResize(is,intrev32ifbe(is->length)+1);

    /* Upgrade back-to-front so we don't overwrite values.
     * Note that the "prepend" variable is used to make sure we have an empty
     * space at either the beginning or the end of the intset. */
    // 根据集合原来的编码方式，从底层数组中取出集合元素
    // 然后再将元素以新编码的方式添加到集合中
    // 当完成了这个步骤之后，集合中所有原有的元素就完成了从旧编码到新编码的转换
    // 因为新分配的空间都放在数组的后端，所以程序先从后端向前端移动元素
    // 举个例子，假设原来有 curenc 编码的三个元素，它们在数组中排列如下：
    // | x | y | z | 
    // 当程序对数组进行重分配之后，数组就被扩容了（符号 ？ 表示未使用的内存）：
    // | x | y | z | ? |   ?   |   ?   |
    // 这时程序从数组后端开始，重新插入元素：
    // | x | y | z | ? |   z   |   ?   |
    // | x | y |   y   |   z   |   ?   |
    // |   x   |   y   |   z   |   ?   |
    // 最后，程序可以将新元素添加到最后 ？ 号标示的位置中：
    // |   x   |   y   |   z   |  new  |
    // 上面演示的是新元素比原来的所有元素都大的情况，也即是 prepend == 0
    // 当新元素比原来的所有元素都小时（prepend == 1），调整的过程如下：
    // | x | y | z | ? |   ?   |   ?   |
    // | x | y | z | ? |   ?   |   z   |
    // | x | y | z | ? |   y   |   z   |
    // | x | y |   x   |   y   |   z   |
    // 当添加新值时，原本的 | x | y | 的数据将被新值代替
    // |  new  |   x   |   y   |   z   |
    // T = O(N)
    while(length--)
        _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));

    /* Set the value at the beginning or the end. */
    // 设置新值，根据 prepend 的值来决定是添加到数组头还是数组尾
    if (prepend)
        _intsetSet(is,0,value);
    else
        _intsetSet(is,intrev32ifbe(is->length),value);

    // 更新整数集合的元素数量
    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);

    return is;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movb %al, -0x11(%rbp)
movq -0x10(%rbp), %rdi
callq 0x67460
movb %al, -0x12(%rbp)
movq -0x8(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rdx
xorl %eax, %eax
movl $0x1, %ecx
cmpq $0x0, %rdx
cmovll %ecx, %eax
movl %eax, -0x1c(%rbp)
movzbl -0x12(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, (%rax)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x4(%rax), %esi
addl $0x1, %esi
callq 0x67720
movq %rax, -0x8(%rbp)
movl -0x18(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x18(%rbp)
cmpl $0x0, %eax
je 0x67557
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rdi
movl -0x18(%rbp), %esi
movzbl -0x11(%rbp), %edx
callq 0x67af0
movq -0x28(%rbp), %rdi
movl -0x20(%rbp), %esi
movq %rax, %rdx
callq 0x67860
jmp 0x67515
cmpl $0x0, -0x1c(%rbp)
je 0x6756e
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rdx
xorl %esi, %esi
callq 0x67860
jmp 0x67582
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x4(%rax), %esi
movq -0x10(%rbp), %rdx
callq 0x67860
movq -0x8(%rbp), %rax
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x8(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)